langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java
changeset 9071 88cd61b4e5aa
child 10454 9d5584396849
equal deleted inserted replaced
9070:f847fe5cad3d 9071:88cd61b4e5aa
       
     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  */
       
    25 
       
    26 
       
    27 package com.sun.tools.javac.api;
       
    28 
       
    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.Map;
       
    41 import java.util.Set;
       
    42 
       
    43 import javax.lang.model.element.NestingKind;
       
    44 import javax.tools.Diagnostic;
       
    45 import javax.tools.FileObject;
       
    46 import javax.tools.JavaFileManager;
       
    47 import javax.tools.JavaFileManager.Location;
       
    48 import javax.tools.JavaFileObject;
       
    49 
       
    50 import com.sun.source.util.TaskEvent;
       
    51 import com.sun.source.util.TaskListener;
       
    52 import com.sun.tools.javac.util.ClientCodeException;
       
    53 import com.sun.tools.javac.util.Context;
       
    54 import java.lang.annotation.ElementType;
       
    55 import java.lang.annotation.Retention;
       
    56 import java.lang.annotation.RetentionPolicy;
       
    57 import java.lang.annotation.Target;
       
    58 import javax.lang.model.element.Modifier;
       
    59 import javax.tools.DiagnosticListener;
       
    60 import javax.tools.JavaFileObject.Kind;
       
    61 
       
    62 /**
       
    63  *  Wrap objects to enable unchecked exceptions to be caught and handled.
       
    64  *
       
    65  *  For each method, exceptions are handled as follows:
       
    66  *  <ul>
       
    67  *  <li>Checked exceptions are left alone and propogate upwards in the
       
    68  *      obvious way, since they are an expected aspect of the method's
       
    69  *      specification.
       
    70  *  <li>Unchecked exceptions which have already been caught and wrapped in
       
    71  *      ClientCodeException are left alone to continue propogating upwards.
       
    72  *  <li>All other unchecked exceptions (i.e. subtypes of RuntimeException
       
    73  *      and Error) and caught, and rethrown as a ClientCodeException with
       
    74  *      its cause set to the original exception.
       
    75  *  </ul>
       
    76  *
       
    77  *  The intent is that ClientCodeException can be caught at an appropriate point
       
    78  *  in the program and can be distinguished from any unanticipated unchecked
       
    79  *  exceptions arising in the main body of the code (i.e. bugs.) When the
       
    80  *  ClientCodeException has been caught, either a suitable message can be
       
    81  *  generated, or if appropriate, the original cause can be rethrown.
       
    82  *
       
    83  *  <p><b>This is NOT part of any supported API.
       
    84  *  If you write code that depends on this, you do so at your own risk.
       
    85  *  This code and its internal interfaces are subject to change or
       
    86  *  deletion without notice.</b>
       
    87  */
       
    88 public class ClientCodeWrapper {
       
    89     @Retention(RetentionPolicy.RUNTIME)
       
    90     @Target(ElementType.TYPE)
       
    91     public @interface Trusted { }
       
    92 
       
    93     public static ClientCodeWrapper instance(Context context) {
       
    94         ClientCodeWrapper instance = context.get(ClientCodeWrapper.class);
       
    95         if (instance == null)
       
    96             instance = new ClientCodeWrapper(context);
       
    97         return instance;
       
    98     }
       
    99 
       
   100     /**
       
   101      * A map to cache the results of whether or not a specific classes can
       
   102      * be "trusted", and thus does not need to be wrapped.
       
   103      */
       
   104     Map<Class<?>, Boolean> trustedClasses;
       
   105 
       
   106     protected ClientCodeWrapper(Context context) {
       
   107         trustedClasses = new HashMap<Class<?>, Boolean>();
       
   108     }
       
   109 
       
   110     public JavaFileManager wrap(JavaFileManager fm) {
       
   111         if (isTrusted(fm))
       
   112             return fm;
       
   113         return new WrappedJavaFileManager(fm);
       
   114     }
       
   115 
       
   116     public FileObject wrap(FileObject fo) {
       
   117         if (isTrusted(fo))
       
   118             return fo;
       
   119         return new WrappedFileObject(fo);
       
   120     }
       
   121 
       
   122     FileObject unwrap(FileObject fo) {
       
   123         if (fo instanceof WrappedFileObject)
       
   124             return ((WrappedFileObject) fo).clientFileObject;
       
   125         else
       
   126             return fo;
       
   127     }
       
   128 
       
   129     public JavaFileObject wrap(JavaFileObject fo) {
       
   130         if (isTrusted(fo))
       
   131             return fo;
       
   132         return new WrappedJavaFileObject(fo);
       
   133     }
       
   134 
       
   135     public Iterable<JavaFileObject> wrapJavaFileObjects(Iterable<? extends JavaFileObject> list) {
       
   136         List<JavaFileObject> wrapped = new ArrayList<JavaFileObject>();
       
   137         for (JavaFileObject fo : list)
       
   138             wrapped.add(wrap(fo));
       
   139         return Collections.unmodifiableList(wrapped);
       
   140     }
       
   141 
       
   142     JavaFileObject unwrap(JavaFileObject fo) {
       
   143         if (fo instanceof WrappedJavaFileObject)
       
   144             return ((JavaFileObject) ((WrappedJavaFileObject) fo).clientFileObject);
       
   145         else
       
   146             return fo;
       
   147     }
       
   148 
       
   149     <T> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) {
       
   150         if (isTrusted(dl))
       
   151             return dl;
       
   152         return new WrappedDiagnosticListener<T>(dl);
       
   153     }
       
   154 
       
   155     TaskListener wrap(TaskListener tl) {
       
   156         if (isTrusted(tl))
       
   157             return tl;
       
   158         return new WrappedTaskListener(tl);
       
   159     }
       
   160 
       
   161     protected boolean isTrusted(Object o) {
       
   162         Class<?> c = o.getClass();
       
   163         Boolean trusted = trustedClasses.get(c);
       
   164         if (trusted == null) {
       
   165             trusted = c.getName().startsWith("com.sun.tools.javac.")
       
   166                     || c.isAnnotationPresent(Trusted.class);
       
   167             trustedClasses.put(c, trusted);
       
   168         }
       
   169         return trusted;
       
   170     }
       
   171 
       
   172     // <editor-fold defaultstate="collapsed" desc="Wrapper classes">
       
   173 
       
   174     // FIXME: all these classes should be converted to use multi-catch when
       
   175     // that is available in the bootstrap compiler.
       
   176 
       
   177     protected class WrappedJavaFileManager implements JavaFileManager {
       
   178         protected JavaFileManager clientJavaFileManager;
       
   179         WrappedJavaFileManager(JavaFileManager clientJavaFileManager) {
       
   180             clientJavaFileManager.getClass(); // null check
       
   181             this.clientJavaFileManager = clientJavaFileManager;
       
   182         }
       
   183 
       
   184         @Override
       
   185         public ClassLoader getClassLoader(Location location) {
       
   186             try {
       
   187                 return clientJavaFileManager.getClassLoader(location);
       
   188             } catch (ClientCodeException e) {
       
   189                 throw e;
       
   190             } catch (RuntimeException e) {
       
   191                 throw new ClientCodeException(e);
       
   192             } catch (Error e) {
       
   193                 throw new ClientCodeException(e);
       
   194             }
       
   195         }
       
   196 
       
   197         @Override
       
   198         public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
       
   199             try {
       
   200                 return wrapJavaFileObjects(clientJavaFileManager.list(location, packageName, kinds, recurse));
       
   201             } catch (ClientCodeException e) {
       
   202                 throw e;
       
   203             } catch (RuntimeException e) {
       
   204                 throw new ClientCodeException(e);
       
   205             } catch (Error e) {
       
   206                 throw new ClientCodeException(e);
       
   207             }
       
   208         }
       
   209 
       
   210         @Override
       
   211         public String inferBinaryName(Location location, JavaFileObject file) {
       
   212             try {
       
   213                 return clientJavaFileManager.inferBinaryName(location, unwrap(file));
       
   214             } catch (ClientCodeException e) {
       
   215                 throw e;
       
   216             } catch (RuntimeException e) {
       
   217                 throw new ClientCodeException(e);
       
   218             } catch (Error e) {
       
   219                 throw new ClientCodeException(e);
       
   220             }
       
   221         }
       
   222 
       
   223         @Override
       
   224         public boolean isSameFile(FileObject a, FileObject b) {
       
   225             try {
       
   226                 return clientJavaFileManager.isSameFile(unwrap(a), unwrap(b));
       
   227             } catch (ClientCodeException e) {
       
   228                 throw e;
       
   229             } catch (RuntimeException e) {
       
   230                 throw new ClientCodeException(e);
       
   231             } catch (Error e) {
       
   232                 throw new ClientCodeException(e);
       
   233             }
       
   234         }
       
   235 
       
   236         @Override
       
   237         public boolean handleOption(String current, Iterator<String> remaining) {
       
   238             try {
       
   239                 return clientJavaFileManager.handleOption(current, remaining);
       
   240             } catch (ClientCodeException e) {
       
   241                 throw e;
       
   242             } catch (RuntimeException e) {
       
   243                 throw new ClientCodeException(e);
       
   244             } catch (Error e) {
       
   245                 throw new ClientCodeException(e);
       
   246             }
       
   247         }
       
   248 
       
   249         @Override
       
   250         public boolean hasLocation(Location location) {
       
   251             try {
       
   252                 return clientJavaFileManager.hasLocation(location);
       
   253             } catch (ClientCodeException e) {
       
   254                 throw e;
       
   255             } catch (RuntimeException e) {
       
   256                 throw new ClientCodeException(e);
       
   257             } catch (Error e) {
       
   258                 throw new ClientCodeException(e);
       
   259             }
       
   260         }
       
   261 
       
   262         @Override
       
   263         public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
       
   264             try {
       
   265                 return wrap(clientJavaFileManager.getJavaFileForInput(location, className, kind));
       
   266             } catch (ClientCodeException e) {
       
   267                 throw e;
       
   268             } catch (RuntimeException e) {
       
   269                 throw new ClientCodeException(e);
       
   270             } catch (Error e) {
       
   271                 throw new ClientCodeException(e);
       
   272             }
       
   273         }
       
   274 
       
   275         @Override
       
   276         public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
       
   277             try {
       
   278                 return wrap(clientJavaFileManager.getJavaFileForOutput(location, className, kind, unwrap(sibling)));
       
   279             } catch (ClientCodeException e) {
       
   280                 throw e;
       
   281             } catch (RuntimeException e) {
       
   282                 throw new ClientCodeException(e);
       
   283             } catch (Error e) {
       
   284                 throw new ClientCodeException(e);
       
   285             }
       
   286         }
       
   287 
       
   288         @Override
       
   289         public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
       
   290             try {
       
   291                 return wrap(clientJavaFileManager.getFileForInput(location, packageName, relativeName));
       
   292             } catch (ClientCodeException e) {
       
   293                 throw e;
       
   294             } catch (RuntimeException e) {
       
   295                 throw new ClientCodeException(e);
       
   296             } catch (Error e) {
       
   297                 throw new ClientCodeException(e);
       
   298             }
       
   299         }
       
   300 
       
   301         @Override
       
   302         public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
       
   303             try {
       
   304                 return wrap(clientJavaFileManager.getFileForOutput(location, packageName, relativeName, unwrap(sibling)));
       
   305             } catch (ClientCodeException e) {
       
   306                 throw e;
       
   307             } catch (RuntimeException e) {
       
   308                 throw new ClientCodeException(e);
       
   309             } catch (Error e) {
       
   310                 throw new ClientCodeException(e);
       
   311             }
       
   312         }
       
   313 
       
   314         @Override
       
   315         public void flush() throws IOException {
       
   316             try {
       
   317                 clientJavaFileManager.flush();
       
   318             } catch (ClientCodeException e) {
       
   319                 throw e;
       
   320             } catch (RuntimeException e) {
       
   321                 throw new ClientCodeException(e);
       
   322             } catch (Error e) {
       
   323                 throw new ClientCodeException(e);
       
   324             }
       
   325         }
       
   326 
       
   327         @Override
       
   328         public void close() throws IOException {
       
   329             try {
       
   330                 clientJavaFileManager.close();
       
   331             } catch (ClientCodeException e) {
       
   332                 throw e;
       
   333             } catch (RuntimeException e) {
       
   334                 throw new ClientCodeException(e);
       
   335             } catch (Error e) {
       
   336                 throw new ClientCodeException(e);
       
   337             }
       
   338         }
       
   339 
       
   340         @Override
       
   341         public int isSupportedOption(String option) {
       
   342             try {
       
   343                 return clientJavaFileManager.isSupportedOption(option);
       
   344             } catch (ClientCodeException e) {
       
   345                 throw e;
       
   346             } catch (RuntimeException e) {
       
   347                 throw new ClientCodeException(e);
       
   348             } catch (Error e) {
       
   349                 throw new ClientCodeException(e);
       
   350             }
       
   351         }
       
   352     }
       
   353 
       
   354     protected class WrappedFileObject implements FileObject {
       
   355         protected FileObject clientFileObject;
       
   356         WrappedFileObject(FileObject clientFileObject) {
       
   357             clientFileObject.getClass(); // null check
       
   358             this.clientFileObject = clientFileObject;
       
   359         }
       
   360 
       
   361         @Override
       
   362         public URI toUri() {
       
   363             try {
       
   364                 return clientFileObject.toUri();
       
   365             } catch (ClientCodeException e) {
       
   366                 throw e;
       
   367             } catch (RuntimeException e) {
       
   368                 throw new ClientCodeException(e);
       
   369             } catch (Error e) {
       
   370                 throw new ClientCodeException(e);
       
   371             }
       
   372         }
       
   373 
       
   374         @Override
       
   375         public String getName() {
       
   376             try {
       
   377                 return clientFileObject.getName();
       
   378             } catch (ClientCodeException e) {
       
   379                 throw e;
       
   380             } catch (RuntimeException e) {
       
   381                 throw new ClientCodeException(e);
       
   382             } catch (Error e) {
       
   383                 throw new ClientCodeException(e);
       
   384             }
       
   385         }
       
   386 
       
   387         @Override
       
   388         public InputStream openInputStream() throws IOException {
       
   389             try {
       
   390                 return clientFileObject.openInputStream();
       
   391             } catch (ClientCodeException e) {
       
   392                 throw e;
       
   393             } catch (RuntimeException e) {
       
   394                 throw new ClientCodeException(e);
       
   395             } catch (Error e) {
       
   396                 throw new ClientCodeException(e);
       
   397             }
       
   398         }
       
   399 
       
   400         @Override
       
   401         public OutputStream openOutputStream() throws IOException {
       
   402             try {
       
   403                 return clientFileObject.openOutputStream();
       
   404             } catch (ClientCodeException e) {
       
   405                 throw e;
       
   406             } catch (RuntimeException e) {
       
   407                 throw new ClientCodeException(e);
       
   408             } catch (Error e) {
       
   409                 throw new ClientCodeException(e);
       
   410             }
       
   411         }
       
   412 
       
   413         @Override
       
   414         public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
       
   415             try {
       
   416                 return clientFileObject.openReader(ignoreEncodingErrors);
       
   417             } catch (ClientCodeException e) {
       
   418                 throw e;
       
   419             } catch (RuntimeException e) {
       
   420                 throw new ClientCodeException(e);
       
   421             } catch (Error e) {
       
   422                 throw new ClientCodeException(e);
       
   423             }
       
   424         }
       
   425 
       
   426         @Override
       
   427         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
       
   428             try {
       
   429                 return clientFileObject.getCharContent(ignoreEncodingErrors);
       
   430             } catch (ClientCodeException e) {
       
   431                 throw e;
       
   432             } catch (RuntimeException e) {
       
   433                 throw new ClientCodeException(e);
       
   434             } catch (Error e) {
       
   435                 throw new ClientCodeException(e);
       
   436             }
       
   437         }
       
   438 
       
   439         @Override
       
   440         public Writer openWriter() throws IOException {
       
   441             try {
       
   442                 return clientFileObject.openWriter();
       
   443             } catch (ClientCodeException e) {
       
   444                 throw e;
       
   445             } catch (RuntimeException e) {
       
   446                 throw new ClientCodeException(e);
       
   447             } catch (Error e) {
       
   448                 throw new ClientCodeException(e);
       
   449             }
       
   450         }
       
   451 
       
   452         @Override
       
   453         public long getLastModified() {
       
   454             try {
       
   455                 return clientFileObject.getLastModified();
       
   456             } catch (ClientCodeException e) {
       
   457                 throw e;
       
   458             } catch (RuntimeException e) {
       
   459                 throw new ClientCodeException(e);
       
   460             } catch (Error e) {
       
   461                 throw new ClientCodeException(e);
       
   462             }
       
   463         }
       
   464 
       
   465         @Override
       
   466         public boolean delete() {
       
   467             try {
       
   468                 return clientFileObject.delete();
       
   469             } catch (ClientCodeException e) {
       
   470                 throw e;
       
   471             } catch (RuntimeException e) {
       
   472                 throw new ClientCodeException(e);
       
   473             } catch (Error e) {
       
   474                 throw new ClientCodeException(e);
       
   475             }
       
   476         }
       
   477     }
       
   478 
       
   479     protected class WrappedJavaFileObject extends WrappedFileObject implements JavaFileObject {
       
   480         WrappedJavaFileObject(JavaFileObject clientJavaFileObject) {
       
   481             super(clientJavaFileObject);
       
   482         }
       
   483 
       
   484         @Override
       
   485         public Kind getKind() {
       
   486             try {
       
   487                 return ((JavaFileObject)clientFileObject).getKind();
       
   488             } catch (ClientCodeException e) {
       
   489                 throw e;
       
   490             } catch (RuntimeException e) {
       
   491                 throw new ClientCodeException(e);
       
   492             } catch (Error e) {
       
   493                 throw new ClientCodeException(e);
       
   494             }
       
   495         }
       
   496 
       
   497         @Override
       
   498         public boolean isNameCompatible(String simpleName, Kind kind) {
       
   499             try {
       
   500                 return ((JavaFileObject)clientFileObject).isNameCompatible(simpleName, kind);
       
   501             } catch (ClientCodeException e) {
       
   502                 throw e;
       
   503             } catch (RuntimeException e) {
       
   504                 throw new ClientCodeException(e);
       
   505             } catch (Error e) {
       
   506                 throw new ClientCodeException(e);
       
   507             }
       
   508         }
       
   509 
       
   510         @Override
       
   511         public NestingKind getNestingKind() {
       
   512             try {
       
   513                 return ((JavaFileObject)clientFileObject).getNestingKind();
       
   514             } catch (ClientCodeException e) {
       
   515                 throw e;
       
   516             } catch (RuntimeException e) {
       
   517                 throw new ClientCodeException(e);
       
   518             } catch (Error e) {
       
   519                 throw new ClientCodeException(e);
       
   520             }
       
   521         }
       
   522 
       
   523         @Override
       
   524         public Modifier getAccessLevel() {
       
   525             try {
       
   526                 return ((JavaFileObject)clientFileObject).getAccessLevel();
       
   527             } catch (ClientCodeException e) {
       
   528                 throw e;
       
   529             } catch (RuntimeException e) {
       
   530                 throw new ClientCodeException(e);
       
   531             } catch (Error e) {
       
   532                 throw new ClientCodeException(e);
       
   533             }
       
   534         }
       
   535     }
       
   536 
       
   537     protected class WrappedDiagnosticListener<T> implements DiagnosticListener<T> {
       
   538         protected DiagnosticListener<T> clientDiagnosticListener;
       
   539         WrappedDiagnosticListener(DiagnosticListener<T> clientDiagnosticListener) {
       
   540             clientDiagnosticListener.getClass(); // null check
       
   541             this.clientDiagnosticListener = clientDiagnosticListener;
       
   542         }
       
   543 
       
   544         @Override
       
   545         public void report(Diagnostic<? extends T> diagnostic) {
       
   546             try {
       
   547                 clientDiagnosticListener.report(diagnostic);
       
   548             } catch (ClientCodeException e) {
       
   549                 throw e;
       
   550             } catch (RuntimeException e) {
       
   551                 throw new ClientCodeException(e);
       
   552             } catch (Error e) {
       
   553                 throw new ClientCodeException(e);
       
   554             }
       
   555         }
       
   556     }
       
   557 
       
   558     protected class WrappedTaskListener implements TaskListener {
       
   559         protected TaskListener clientTaskListener;
       
   560         WrappedTaskListener(TaskListener clientTaskListener) {
       
   561             clientTaskListener.getClass(); // null check
       
   562             this.clientTaskListener = clientTaskListener;
       
   563         }
       
   564 
       
   565         @Override
       
   566         public void started(TaskEvent ev) {
       
   567             try {
       
   568                 clientTaskListener.started(ev);
       
   569             } catch (ClientCodeException e) {
       
   570                 throw e;
       
   571             } catch (RuntimeException e) {
       
   572                 throw new ClientCodeException(e);
       
   573             } catch (Error e) {
       
   574                 throw new ClientCodeException(e);
       
   575             }
       
   576         }
       
   577 
       
   578         @Override
       
   579         public void finished(TaskEvent ev) {
       
   580             try {
       
   581                 clientTaskListener.finished(ev);
       
   582             } catch (ClientCodeException e) {
       
   583                 throw e;
       
   584             } catch (RuntimeException e) {
       
   585                 throw new ClientCodeException(e);
       
   586             } catch (Error e) {
       
   587                 throw new ClientCodeException(e);
       
   588             }
       
   589         }
       
   590     }
       
   591 
       
   592     // </editor-fold>
       
   593 }