src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java

Tue, 24 Jan 2012 15:51:44 -0800

author
jjh
date
Tue, 24 Jan 2012 15:51:44 -0800
changeset 1187
ac36176b7de0
parent 1077
ec27e5befa53
child 1210
62e611704863
permissions
-rw-r--r--

7126832: com.sun.tools.javac.api.ClientCodeWrapper$WrappedJavaFileManager cannot be cast
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    27 package com.sun.tools.javac.api;
    29 import java.io.IOException;
    30 import java.io.InputStream;
    31 import java.io.OutputStream;
    32 import java.io.Reader;
    33 import java.io.Writer;
    34 import java.net.URI;
    35 import java.util.ArrayList;
    36 import java.util.Collections;
    37 import java.util.HashMap;
    38 import java.util.Iterator;
    39 import java.util.List;
    40 import java.util.Locale;
    41 import java.util.Map;
    42 import java.util.Set;
    44 import javax.lang.model.element.NestingKind;
    45 import javax.tools.Diagnostic;
    46 import javax.tools.FileObject;
    47 import javax.tools.JavaFileManager;
    48 import javax.tools.JavaFileManager.Location;
    49 import javax.tools.JavaFileObject;
    51 import com.sun.source.util.TaskEvent;
    52 import com.sun.source.util.TaskListener;
    53 import com.sun.tools.javac.util.ClientCodeException;
    54 import com.sun.tools.javac.util.Context;
    55 import com.sun.tools.javac.util.JCDiagnostic;
    56 import java.lang.annotation.ElementType;
    57 import java.lang.annotation.Retention;
    58 import java.lang.annotation.RetentionPolicy;
    59 import java.lang.annotation.Target;
    60 import javax.lang.model.element.Modifier;
    61 import javax.tools.DiagnosticListener;
    62 import javax.tools.JavaFileObject.Kind;
    64 /**
    65  *  Wrap objects to enable unchecked exceptions to be caught and handled.
    66  *
    67  *  For each method, exceptions are handled as follows:
    68  *  <ul>
    69  *  <li>Checked exceptions are left alone and propogate upwards in the
    70  *      obvious way, since they are an expected aspect of the method's
    71  *      specification.
    72  *  <li>Unchecked exceptions which have already been caught and wrapped in
    73  *      ClientCodeException are left alone to continue propogating upwards.
    74  *  <li>All other unchecked exceptions (i.e. subtypes of RuntimeException
    75  *      and Error) and caught, and rethrown as a ClientCodeException with
    76  *      its cause set to the original exception.
    77  *  </ul>
    78  *
    79  *  The intent is that ClientCodeException can be caught at an appropriate point
    80  *  in the program and can be distinguished from any unanticipated unchecked
    81  *  exceptions arising in the main body of the code (i.e. bugs.) When the
    82  *  ClientCodeException has been caught, either a suitable message can be
    83  *  generated, or if appropriate, the original cause can be rethrown.
    84  *
    85  *  <p><b>This is NOT part of any supported API.
    86  *  If you write code that depends on this, you do so at your own risk.
    87  *  This code and its internal interfaces are subject to change or
    88  *  deletion without notice.</b>
    89  */
    90 public class ClientCodeWrapper {
    91     @Retention(RetentionPolicy.RUNTIME)
    92     @Target(ElementType.TYPE)
    93     public @interface Trusted { }
    95     public static ClientCodeWrapper instance(Context context) {
    96         ClientCodeWrapper instance = context.get(ClientCodeWrapper.class);
    97         if (instance == null)
    98             instance = new ClientCodeWrapper(context);
    99         return instance;
   100     }
   102     /**
   103      * A map to cache the results of whether or not a specific classes can
   104      * be "trusted", and thus does not need to be wrapped.
   105      */
   106     Map<Class<?>, Boolean> trustedClasses;
   108     protected ClientCodeWrapper(Context context) {
   109         trustedClasses = new HashMap<Class<?>, Boolean>();
   110     }
   112     public JavaFileManager wrap(JavaFileManager fm) {
   113         if (isTrusted(fm))
   114             return fm;
   115         return new WrappedJavaFileManager(fm);
   116     }
   118     public FileObject wrap(FileObject fo) {
   119         if (isTrusted(fo))
   120             return fo;
   121         return new WrappedFileObject(fo);
   122     }
   124     FileObject unwrap(FileObject fo) {
   125         if (fo instanceof WrappedFileObject)
   126             return ((WrappedFileObject) fo).clientFileObject;
   127         else
   128             return fo;
   129     }
   131     public JavaFileObject wrap(JavaFileObject fo) {
   132         if (isTrusted(fo))
   133             return fo;
   134         return new WrappedJavaFileObject(fo);
   135     }
   137     public Iterable<JavaFileObject> wrapJavaFileObjects(Iterable<? extends JavaFileObject> list) {
   138         List<JavaFileObject> wrapped = new ArrayList<JavaFileObject>();
   139         for (JavaFileObject fo : list)
   140             wrapped.add(wrap(fo));
   141         return Collections.unmodifiableList(wrapped);
   142     }
   144     JavaFileObject unwrap(JavaFileObject fo) {
   145         if (fo instanceof WrappedJavaFileObject)
   146             return ((JavaFileObject) ((WrappedJavaFileObject) fo).clientFileObject);
   147         else
   148             return fo;
   149     }
   151     <T /*super JavaFileOject*/> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) {
   152         if (isTrusted(dl))
   153             return dl;
   154         return new WrappedDiagnosticListener<T>(dl);
   155     }
   157     TaskListener wrap(TaskListener tl) {
   158         if (isTrusted(tl))
   159             return tl;
   160         return new WrappedTaskListener(tl);
   161     }
   163     @SuppressWarnings("unchecked")
   164     private <T> Diagnostic<T> unwrap(final Diagnostic<T> diagnostic) {
   165         if (diagnostic instanceof JCDiagnostic) {
   166             JCDiagnostic d = (JCDiagnostic) diagnostic;
   167             return (Diagnostic<T>) new DiagnosticSourceUnwrapper(d);
   168         } else {
   169             return diagnostic;
   170         }
   171     }
   173     protected boolean isTrusted(Object o) {
   174         Class<?> c = o.getClass();
   175         Boolean trusted = trustedClasses.get(c);
   176         if (trusted == null) {
   177             trusted = c.getName().startsWith("com.sun.tools.javac.")
   178                     || c.isAnnotationPresent(Trusted.class);
   179             trustedClasses.put(c, trusted);
   180         }
   181         return trusted;
   182     }
   184     // <editor-fold defaultstate="collapsed" desc="Wrapper classes">
   186     // FIXME: all these classes should be converted to use multi-catch when
   187     // that is available in the bootstrap compiler.
   189     protected class WrappedJavaFileManager implements JavaFileManager {
   190         protected JavaFileManager clientJavaFileManager;
   191         WrappedJavaFileManager(JavaFileManager clientJavaFileManager) {
   192             clientJavaFileManager.getClass(); // null check
   193             this.clientJavaFileManager = clientJavaFileManager;
   194         }
   196         @Override
   197         public ClassLoader getClassLoader(Location location) {
   198             try {
   199                 return clientJavaFileManager.getClassLoader(location);
   200             } catch (ClientCodeException e) {
   201                 throw e;
   202             } catch (RuntimeException e) {
   203                 throw new ClientCodeException(e);
   204             } catch (Error e) {
   205                 throw new ClientCodeException(e);
   206             }
   207         }
   209         @Override
   210         public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
   211             try {
   212                 return wrapJavaFileObjects(clientJavaFileManager.list(location, packageName, kinds, recurse));
   213             } catch (ClientCodeException e) {
   214                 throw e;
   215             } catch (RuntimeException e) {
   216                 throw new ClientCodeException(e);
   217             } catch (Error e) {
   218                 throw new ClientCodeException(e);
   219             }
   220         }
   222         @Override
   223         public String inferBinaryName(Location location, JavaFileObject file) {
   224             try {
   225                 return clientJavaFileManager.inferBinaryName(location, unwrap(file));
   226             } catch (ClientCodeException e) {
   227                 throw e;
   228             } catch (RuntimeException e) {
   229                 throw new ClientCodeException(e);
   230             } catch (Error e) {
   231                 throw new ClientCodeException(e);
   232             }
   233         }
   235         @Override
   236         public boolean isSameFile(FileObject a, FileObject b) {
   237             try {
   238                 return clientJavaFileManager.isSameFile(unwrap(a), unwrap(b));
   239             } catch (ClientCodeException e) {
   240                 throw e;
   241             } catch (RuntimeException e) {
   242                 throw new ClientCodeException(e);
   243             } catch (Error e) {
   244                 throw new ClientCodeException(e);
   245             }
   246         }
   248         @Override
   249         public boolean handleOption(String current, Iterator<String> remaining) {
   250             try {
   251                 return clientJavaFileManager.handleOption(current, remaining);
   252             } catch (ClientCodeException e) {
   253                 throw e;
   254             } catch (RuntimeException e) {
   255                 throw new ClientCodeException(e);
   256             } catch (Error e) {
   257                 throw new ClientCodeException(e);
   258             }
   259         }
   261         @Override
   262         public boolean hasLocation(Location location) {
   263             try {
   264                 return clientJavaFileManager.hasLocation(location);
   265             } catch (ClientCodeException e) {
   266                 throw e;
   267             } catch (RuntimeException e) {
   268                 throw new ClientCodeException(e);
   269             } catch (Error e) {
   270                 throw new ClientCodeException(e);
   271             }
   272         }
   274         @Override
   275         public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
   276             try {
   277                 return wrap(clientJavaFileManager.getJavaFileForInput(location, className, kind));
   278             } catch (ClientCodeException e) {
   279                 throw e;
   280             } catch (RuntimeException e) {
   281                 throw new ClientCodeException(e);
   282             } catch (Error e) {
   283                 throw new ClientCodeException(e);
   284             }
   285         }
   287         @Override
   288         public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   289             try {
   290                 return wrap(clientJavaFileManager.getJavaFileForOutput(location, className, kind, unwrap(sibling)));
   291             } catch (ClientCodeException e) {
   292                 throw e;
   293             } catch (RuntimeException e) {
   294                 throw new ClientCodeException(e);
   295             } catch (Error e) {
   296                 throw new ClientCodeException(e);
   297             }
   298         }
   300         @Override
   301         public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   302             try {
   303                 return wrap(clientJavaFileManager.getFileForInput(location, packageName, relativeName));
   304             } catch (ClientCodeException e) {
   305                 throw e;
   306             } catch (RuntimeException e) {
   307                 throw new ClientCodeException(e);
   308             } catch (Error e) {
   309                 throw new ClientCodeException(e);
   310             }
   311         }
   313         @Override
   314         public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
   315             try {
   316                 return wrap(clientJavaFileManager.getFileForOutput(location, packageName, relativeName, unwrap(sibling)));
   317             } catch (ClientCodeException e) {
   318                 throw e;
   319             } catch (RuntimeException e) {
   320                 throw new ClientCodeException(e);
   321             } catch (Error e) {
   322                 throw new ClientCodeException(e);
   323             }
   324         }
   326         @Override
   327         public void flush() throws IOException {
   328             try {
   329                 clientJavaFileManager.flush();
   330             } catch (ClientCodeException e) {
   331                 throw e;
   332             } catch (RuntimeException e) {
   333                 throw new ClientCodeException(e);
   334             } catch (Error e) {
   335                 throw new ClientCodeException(e);
   336             }
   337         }
   339         @Override
   340         public void close() throws IOException {
   341             try {
   342                 clientJavaFileManager.close();
   343             } catch (ClientCodeException e) {
   344                 throw e;
   345             } catch (RuntimeException e) {
   346                 throw new ClientCodeException(e);
   347             } catch (Error e) {
   348                 throw new ClientCodeException(e);
   349             }
   350         }
   352         @Override
   353         public int isSupportedOption(String option) {
   354             try {
   355                 return clientJavaFileManager.isSupportedOption(option);
   356             } catch (ClientCodeException e) {
   357                 throw e;
   358             } catch (RuntimeException e) {
   359                 throw new ClientCodeException(e);
   360             } catch (Error e) {
   361                 throw new ClientCodeException(e);
   362             }
   363         }
   364     }
   366     protected class WrappedFileObject implements FileObject {
   367         protected FileObject clientFileObject;
   368         WrappedFileObject(FileObject clientFileObject) {
   369             clientFileObject.getClass(); // null check
   370             this.clientFileObject = clientFileObject;
   371         }
   373         @Override
   374         public URI toUri() {
   375             try {
   376                 return clientFileObject.toUri();
   377             } catch (ClientCodeException e) {
   378                 throw e;
   379             } catch (RuntimeException e) {
   380                 throw new ClientCodeException(e);
   381             } catch (Error e) {
   382                 throw new ClientCodeException(e);
   383             }
   384         }
   386         @Override
   387         public String getName() {
   388             try {
   389                 return clientFileObject.getName();
   390             } catch (ClientCodeException e) {
   391                 throw e;
   392             } catch (RuntimeException e) {
   393                 throw new ClientCodeException(e);
   394             } catch (Error e) {
   395                 throw new ClientCodeException(e);
   396             }
   397         }
   399         @Override
   400         public InputStream openInputStream() throws IOException {
   401             try {
   402                 return clientFileObject.openInputStream();
   403             } catch (ClientCodeException e) {
   404                 throw e;
   405             } catch (RuntimeException e) {
   406                 throw new ClientCodeException(e);
   407             } catch (Error e) {
   408                 throw new ClientCodeException(e);
   409             }
   410         }
   412         @Override
   413         public OutputStream openOutputStream() throws IOException {
   414             try {
   415                 return clientFileObject.openOutputStream();
   416             } catch (ClientCodeException e) {
   417                 throw e;
   418             } catch (RuntimeException e) {
   419                 throw new ClientCodeException(e);
   420             } catch (Error e) {
   421                 throw new ClientCodeException(e);
   422             }
   423         }
   425         @Override
   426         public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   427             try {
   428                 return clientFileObject.openReader(ignoreEncodingErrors);
   429             } catch (ClientCodeException e) {
   430                 throw e;
   431             } catch (RuntimeException e) {
   432                 throw new ClientCodeException(e);
   433             } catch (Error e) {
   434                 throw new ClientCodeException(e);
   435             }
   436         }
   438         @Override
   439         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   440             try {
   441                 return clientFileObject.getCharContent(ignoreEncodingErrors);
   442             } catch (ClientCodeException e) {
   443                 throw e;
   444             } catch (RuntimeException e) {
   445                 throw new ClientCodeException(e);
   446             } catch (Error e) {
   447                 throw new ClientCodeException(e);
   448             }
   449         }
   451         @Override
   452         public Writer openWriter() throws IOException {
   453             try {
   454                 return clientFileObject.openWriter();
   455             } catch (ClientCodeException e) {
   456                 throw e;
   457             } catch (RuntimeException e) {
   458                 throw new ClientCodeException(e);
   459             } catch (Error e) {
   460                 throw new ClientCodeException(e);
   461             }
   462         }
   464         @Override
   465         public long getLastModified() {
   466             try {
   467                 return clientFileObject.getLastModified();
   468             } catch (ClientCodeException e) {
   469                 throw e;
   470             } catch (RuntimeException e) {
   471                 throw new ClientCodeException(e);
   472             } catch (Error e) {
   473                 throw new ClientCodeException(e);
   474             }
   475         }
   477         @Override
   478         public boolean delete() {
   479             try {
   480                 return clientFileObject.delete();
   481             } catch (ClientCodeException e) {
   482                 throw e;
   483             } catch (RuntimeException e) {
   484                 throw new ClientCodeException(e);
   485             } catch (Error e) {
   486                 throw new ClientCodeException(e);
   487             }
   488         }
   489     }
   491     protected class WrappedJavaFileObject extends WrappedFileObject implements JavaFileObject {
   492         WrappedJavaFileObject(JavaFileObject clientJavaFileObject) {
   493             super(clientJavaFileObject);
   494         }
   496         @Override
   497         public Kind getKind() {
   498             try {
   499                 return ((JavaFileObject)clientFileObject).getKind();
   500             } catch (ClientCodeException e) {
   501                 throw e;
   502             } catch (RuntimeException e) {
   503                 throw new ClientCodeException(e);
   504             } catch (Error e) {
   505                 throw new ClientCodeException(e);
   506             }
   507         }
   509         @Override
   510         public boolean isNameCompatible(String simpleName, Kind kind) {
   511             try {
   512                 return ((JavaFileObject)clientFileObject).isNameCompatible(simpleName, kind);
   513             } catch (ClientCodeException e) {
   514                 throw e;
   515             } catch (RuntimeException e) {
   516                 throw new ClientCodeException(e);
   517             } catch (Error e) {
   518                 throw new ClientCodeException(e);
   519             }
   520         }
   522         @Override
   523         public NestingKind getNestingKind() {
   524             try {
   525                 return ((JavaFileObject)clientFileObject).getNestingKind();
   526             } catch (ClientCodeException e) {
   527                 throw e;
   528             } catch (RuntimeException e) {
   529                 throw new ClientCodeException(e);
   530             } catch (Error e) {
   531                 throw new ClientCodeException(e);
   532             }
   533         }
   535         @Override
   536         public Modifier getAccessLevel() {
   537             try {
   538                 return ((JavaFileObject)clientFileObject).getAccessLevel();
   539             } catch (ClientCodeException e) {
   540                 throw e;
   541             } catch (RuntimeException e) {
   542                 throw new ClientCodeException(e);
   543             } catch (Error e) {
   544                 throw new ClientCodeException(e);
   545             }
   546         }
   547     }
   549     protected class WrappedDiagnosticListener<T /*super JavaFileObject*/> implements DiagnosticListener<T> {
   550         protected DiagnosticListener<T> clientDiagnosticListener;
   551         WrappedDiagnosticListener(DiagnosticListener<T> clientDiagnosticListener) {
   552             clientDiagnosticListener.getClass(); // null check
   553             this.clientDiagnosticListener = clientDiagnosticListener;
   554         }
   556         @Override
   557         public void report(Diagnostic<? extends T> diagnostic) {
   558             try {
   559                 clientDiagnosticListener.report(unwrap(diagnostic));
   560             } catch (ClientCodeException e) {
   561                 throw e;
   562             } catch (RuntimeException e) {
   563                 throw new ClientCodeException(e);
   564             } catch (Error e) {
   565                 throw new ClientCodeException(e);
   566             }
   567         }
   568     }
   570     public class DiagnosticSourceUnwrapper implements Diagnostic<JavaFileObject> {
   571         public final JCDiagnostic d;
   573         DiagnosticSourceUnwrapper(JCDiagnostic d) {
   574             this.d = d;
   575         }
   577         public Diagnostic.Kind getKind() {
   578             return d.getKind();
   579         }
   581         public JavaFileObject getSource() {
   582             return unwrap(d.getSource());
   583         }
   585         public long getPosition() {
   586             return d.getPosition();
   587         }
   589         public long getStartPosition() {
   590             return d.getStartPosition();
   591         }
   593         public long getEndPosition() {
   594             return d.getEndPosition();
   595         }
   597         public long getLineNumber() {
   598             return d.getLineNumber();
   599         }
   601         public long getColumnNumber() {
   602             return d.getColumnNumber();
   603         }
   605         public String getCode() {
   606             return d.getCode();
   607         }
   609         public String getMessage(Locale locale) {
   610             return d.getMessage(locale);
   611         }
   613         public String toString() {
   614             return d.toString();
   615         }
   616     }
   618     protected class WrappedTaskListener implements TaskListener {
   619         protected TaskListener clientTaskListener;
   620         WrappedTaskListener(TaskListener clientTaskListener) {
   621             clientTaskListener.getClass(); // null check
   622             this.clientTaskListener = clientTaskListener;
   623         }
   625         @Override
   626         public void started(TaskEvent ev) {
   627             try {
   628                 clientTaskListener.started(ev);
   629             } catch (ClientCodeException e) {
   630                 throw e;
   631             } catch (RuntimeException e) {
   632                 throw new ClientCodeException(e);
   633             } catch (Error e) {
   634                 throw new ClientCodeException(e);
   635             }
   636         }
   638         @Override
   639         public void finished(TaskEvent ev) {
   640             try {
   641                 clientTaskListener.finished(ev);
   642             } catch (ClientCodeException e) {
   643                 throw e;
   644             } catch (RuntimeException e) {
   645                 throw new ClientCodeException(e);
   646             } catch (Error e) {
   647                 throw new ClientCodeException(e);
   648             }
   649         }
   650     }
   652     // </editor-fold>
   653 }

mercurial