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

Sun, 17 Feb 2013 16:44:55 -0500

author
dholmes
date
Sun, 17 Feb 2013 16:44:55 -0500
changeset 1571
af8417e590f4
parent 1413
bdcef2ef52d2
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright (c) 2011, 2012, 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.lang.annotation.ElementType;
    35 import java.lang.annotation.Retention;
    36 import java.lang.annotation.RetentionPolicy;
    37 import java.lang.annotation.Target;
    38 import java.net.URI;
    39 import java.util.ArrayList;
    40 import java.util.Collection;
    41 import java.util.Collections;
    42 import java.util.HashMap;
    43 import java.util.Iterator;
    44 import java.util.List;
    45 import java.util.Locale;
    46 import java.util.Map;
    47 import java.util.Set;
    49 import javax.lang.model.element.Modifier;
    50 import javax.lang.model.element.NestingKind;
    51 import javax.tools.Diagnostic;
    52 import javax.tools.DiagnosticListener;
    53 import javax.tools.FileObject;
    54 import javax.tools.JavaFileManager;
    55 import javax.tools.JavaFileManager.Location;
    56 import javax.tools.JavaFileObject;
    57 import javax.tools.JavaFileObject.Kind;
    59 import com.sun.source.util.TaskEvent;
    60 import com.sun.source.util.TaskListener;
    61 import com.sun.tools.javac.util.ClientCodeException;
    62 import com.sun.tools.javac.util.Context;
    63 import com.sun.tools.javac.util.JCDiagnostic;
    65 /**
    66  *  Wrap objects to enable unchecked exceptions to be caught and handled.
    67  *
    68  *  For each method, exceptions are handled as follows:
    69  *  <ul>
    70  *  <li>Checked exceptions are left alone and propogate upwards in the
    71  *      obvious way, since they are an expected aspect of the method's
    72  *      specification.
    73  *  <li>Unchecked exceptions which have already been caught and wrapped in
    74  *      ClientCodeException are left alone to continue propogating upwards.
    75  *  <li>All other unchecked exceptions (i.e. subtypes of RuntimeException
    76  *      and Error) and caught, and rethrown as a ClientCodeException with
    77  *      its cause set to the original exception.
    78  *  </ul>
    79  *
    80  *  The intent is that ClientCodeException can be caught at an appropriate point
    81  *  in the program and can be distinguished from any unanticipated unchecked
    82  *  exceptions arising in the main body of the code (i.e. bugs.) When the
    83  *  ClientCodeException has been caught, either a suitable message can be
    84  *  generated, or if appropriate, the original cause can be rethrown.
    85  *
    86  *  <p><b>This is NOT part of any supported API.
    87  *  If you write code that depends on this, you do so at your own risk.
    88  *  This code and its internal interfaces are subject to change or
    89  *  deletion without notice.</b>
    90  */
    91 public class ClientCodeWrapper {
    92     @Retention(RetentionPolicy.RUNTIME)
    93     @Target(ElementType.TYPE)
    94     public @interface Trusted { }
    96     public static ClientCodeWrapper instance(Context context) {
    97         ClientCodeWrapper instance = context.get(ClientCodeWrapper.class);
    98         if (instance == null)
    99             instance = new ClientCodeWrapper(context);
   100         return instance;
   101     }
   103     /**
   104      * A map to cache the results of whether or not a specific classes can
   105      * be "trusted", and thus does not need to be wrapped.
   106      */
   107     Map<Class<?>, Boolean> trustedClasses;
   109     protected ClientCodeWrapper(Context context) {
   110         trustedClasses = new HashMap<Class<?>, Boolean>();
   111     }
   113     public JavaFileManager wrap(JavaFileManager fm) {
   114         if (isTrusted(fm))
   115             return fm;
   116         return new WrappedJavaFileManager(fm);
   117     }
   119     public FileObject wrap(FileObject fo) {
   120         if (isTrusted(fo))
   121             return fo;
   122         return new WrappedFileObject(fo);
   123     }
   125     FileObject unwrap(FileObject fo) {
   126         if (fo instanceof WrappedFileObject)
   127             return ((WrappedFileObject) fo).clientFileObject;
   128         else
   129             return fo;
   130     }
   132     public JavaFileObject wrap(JavaFileObject fo) {
   133         if (isTrusted(fo))
   134             return fo;
   135         return new WrappedJavaFileObject(fo);
   136     }
   138     public Iterable<JavaFileObject> wrapJavaFileObjects(Iterable<? extends JavaFileObject> list) {
   139         List<JavaFileObject> wrapped = new ArrayList<JavaFileObject>();
   140         for (JavaFileObject fo : list)
   141             wrapped.add(wrap(fo));
   142         return Collections.unmodifiableList(wrapped);
   143     }
   145     JavaFileObject unwrap(JavaFileObject fo) {
   146         if (fo instanceof WrappedJavaFileObject)
   147             return ((JavaFileObject) ((WrappedJavaFileObject) fo).clientFileObject);
   148         else
   149             return fo;
   150     }
   152     public <T /*super JavaFileOject*/> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) {
   153         if (isTrusted(dl))
   154             return dl;
   155         return new WrappedDiagnosticListener<T>(dl);
   156     }
   158     TaskListener wrap(TaskListener tl) {
   159         if (isTrusted(tl))
   160             return tl;
   161         return new WrappedTaskListener(tl);
   162     }
   164     TaskListener unwrap(TaskListener l) {
   165         if (l instanceof WrappedTaskListener)
   166             return ((WrappedTaskListener) l).clientTaskListener;
   167         else
   168             return l;
   169     }
   171     Collection<TaskListener> unwrap(Collection<? extends TaskListener> listeners) {
   172         Collection<TaskListener> c = new ArrayList<TaskListener>(listeners.size());
   173         for (TaskListener l: listeners)
   174             c.add(unwrap(l));
   175         return c;
   176     }
   178     @SuppressWarnings("unchecked")
   179     private <T> Diagnostic<T> unwrap(final Diagnostic<T> diagnostic) {
   180         if (diagnostic instanceof JCDiagnostic) {
   181             JCDiagnostic d = (JCDiagnostic) diagnostic;
   182             return (Diagnostic<T>) new DiagnosticSourceUnwrapper(d);
   183         } else {
   184             return diagnostic;
   185         }
   186     }
   188     protected boolean isTrusted(Object o) {
   189         Class<?> c = o.getClass();
   190         Boolean trusted = trustedClasses.get(c);
   191         if (trusted == null) {
   192             trusted = c.getName().startsWith("com.sun.tools.javac.")
   193                     || c.isAnnotationPresent(Trusted.class);
   194             trustedClasses.put(c, trusted);
   195         }
   196         return trusted;
   197     }
   199     private String wrappedToString(Class<?> wrapperClass, Object wrapped) {
   200         return wrapperClass.getSimpleName() + "[" + wrapped + "]";
   201     }
   203     // <editor-fold defaultstate="collapsed" desc="Wrapper classes">
   205     // FIXME: all these classes should be converted to use multi-catch when
   206     // that is available in the bootstrap compiler.
   208     protected class WrappedJavaFileManager implements JavaFileManager {
   209         protected JavaFileManager clientJavaFileManager;
   210         WrappedJavaFileManager(JavaFileManager clientJavaFileManager) {
   211             clientJavaFileManager.getClass(); // null check
   212             this.clientJavaFileManager = clientJavaFileManager;
   213         }
   215         @Override
   216         public ClassLoader getClassLoader(Location location) {
   217             try {
   218                 return clientJavaFileManager.getClassLoader(location);
   219             } catch (ClientCodeException e) {
   220                 throw e;
   221             } catch (RuntimeException e) {
   222                 throw new ClientCodeException(e);
   223             } catch (Error e) {
   224                 throw new ClientCodeException(e);
   225             }
   226         }
   228         @Override
   229         public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
   230             try {
   231                 return wrapJavaFileObjects(clientJavaFileManager.list(location, packageName, kinds, recurse));
   232             } catch (ClientCodeException e) {
   233                 throw e;
   234             } catch (RuntimeException e) {
   235                 throw new ClientCodeException(e);
   236             } catch (Error e) {
   237                 throw new ClientCodeException(e);
   238             }
   239         }
   241         @Override
   242         public String inferBinaryName(Location location, JavaFileObject file) {
   243             try {
   244                 return clientJavaFileManager.inferBinaryName(location, unwrap(file));
   245             } catch (ClientCodeException e) {
   246                 throw e;
   247             } catch (RuntimeException e) {
   248                 throw new ClientCodeException(e);
   249             } catch (Error e) {
   250                 throw new ClientCodeException(e);
   251             }
   252         }
   254         @Override
   255         public boolean isSameFile(FileObject a, FileObject b) {
   256             try {
   257                 return clientJavaFileManager.isSameFile(unwrap(a), unwrap(b));
   258             } catch (ClientCodeException e) {
   259                 throw e;
   260             } catch (RuntimeException e) {
   261                 throw new ClientCodeException(e);
   262             } catch (Error e) {
   263                 throw new ClientCodeException(e);
   264             }
   265         }
   267         @Override
   268         public boolean handleOption(String current, Iterator<String> remaining) {
   269             try {
   270                 return clientJavaFileManager.handleOption(current, remaining);
   271             } catch (ClientCodeException e) {
   272                 throw e;
   273             } catch (RuntimeException e) {
   274                 throw new ClientCodeException(e);
   275             } catch (Error e) {
   276                 throw new ClientCodeException(e);
   277             }
   278         }
   280         @Override
   281         public boolean hasLocation(Location location) {
   282             try {
   283                 return clientJavaFileManager.hasLocation(location);
   284             } catch (ClientCodeException e) {
   285                 throw e;
   286             } catch (RuntimeException e) {
   287                 throw new ClientCodeException(e);
   288             } catch (Error e) {
   289                 throw new ClientCodeException(e);
   290             }
   291         }
   293         @Override
   294         public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
   295             try {
   296                 return wrap(clientJavaFileManager.getJavaFileForInput(location, className, kind));
   297             } catch (ClientCodeException e) {
   298                 throw e;
   299             } catch (RuntimeException e) {
   300                 throw new ClientCodeException(e);
   301             } catch (Error e) {
   302                 throw new ClientCodeException(e);
   303             }
   304         }
   306         @Override
   307         public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   308             try {
   309                 return wrap(clientJavaFileManager.getJavaFileForOutput(location, className, kind, unwrap(sibling)));
   310             } catch (ClientCodeException e) {
   311                 throw e;
   312             } catch (RuntimeException e) {
   313                 throw new ClientCodeException(e);
   314             } catch (Error e) {
   315                 throw new ClientCodeException(e);
   316             }
   317         }
   319         @Override
   320         public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   321             try {
   322                 return wrap(clientJavaFileManager.getFileForInput(location, packageName, relativeName));
   323             } catch (ClientCodeException e) {
   324                 throw e;
   325             } catch (RuntimeException e) {
   326                 throw new ClientCodeException(e);
   327             } catch (Error e) {
   328                 throw new ClientCodeException(e);
   329             }
   330         }
   332         @Override
   333         public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
   334             try {
   335                 return wrap(clientJavaFileManager.getFileForOutput(location, packageName, relativeName, unwrap(sibling)));
   336             } catch (ClientCodeException e) {
   337                 throw e;
   338             } catch (RuntimeException e) {
   339                 throw new ClientCodeException(e);
   340             } catch (Error e) {
   341                 throw new ClientCodeException(e);
   342             }
   343         }
   345         @Override
   346         public void flush() throws IOException {
   347             try {
   348                 clientJavaFileManager.flush();
   349             } catch (ClientCodeException e) {
   350                 throw e;
   351             } catch (RuntimeException e) {
   352                 throw new ClientCodeException(e);
   353             } catch (Error e) {
   354                 throw new ClientCodeException(e);
   355             }
   356         }
   358         @Override
   359         public void close() throws IOException {
   360             try {
   361                 clientJavaFileManager.close();
   362             } catch (ClientCodeException e) {
   363                 throw e;
   364             } catch (RuntimeException e) {
   365                 throw new ClientCodeException(e);
   366             } catch (Error e) {
   367                 throw new ClientCodeException(e);
   368             }
   369         }
   371         @Override
   372         public int isSupportedOption(String option) {
   373             try {
   374                 return clientJavaFileManager.isSupportedOption(option);
   375             } catch (ClientCodeException e) {
   376                 throw e;
   377             } catch (RuntimeException e) {
   378                 throw new ClientCodeException(e);
   379             } catch (Error e) {
   380                 throw new ClientCodeException(e);
   381             }
   382         }
   384         @Override
   385         public String toString() {
   386             return wrappedToString(getClass(), clientJavaFileManager);
   387         }
   388     }
   390     protected class WrappedFileObject implements FileObject {
   391         protected FileObject clientFileObject;
   392         WrappedFileObject(FileObject clientFileObject) {
   393             clientFileObject.getClass(); // null check
   394             this.clientFileObject = clientFileObject;
   395         }
   397         @Override
   398         public URI toUri() {
   399             try {
   400                 return clientFileObject.toUri();
   401             } catch (ClientCodeException e) {
   402                 throw e;
   403             } catch (RuntimeException e) {
   404                 throw new ClientCodeException(e);
   405             } catch (Error e) {
   406                 throw new ClientCodeException(e);
   407             }
   408         }
   410         @Override
   411         public String getName() {
   412             try {
   413                 return clientFileObject.getName();
   414             } catch (ClientCodeException e) {
   415                 throw e;
   416             } catch (RuntimeException e) {
   417                 throw new ClientCodeException(e);
   418             } catch (Error e) {
   419                 throw new ClientCodeException(e);
   420             }
   421         }
   423         @Override
   424         public InputStream openInputStream() throws IOException {
   425             try {
   426                 return clientFileObject.openInputStream();
   427             } catch (ClientCodeException e) {
   428                 throw e;
   429             } catch (RuntimeException e) {
   430                 throw new ClientCodeException(e);
   431             } catch (Error e) {
   432                 throw new ClientCodeException(e);
   433             }
   434         }
   436         @Override
   437         public OutputStream openOutputStream() throws IOException {
   438             try {
   439                 return clientFileObject.openOutputStream();
   440             } catch (ClientCodeException e) {
   441                 throw e;
   442             } catch (RuntimeException e) {
   443                 throw new ClientCodeException(e);
   444             } catch (Error e) {
   445                 throw new ClientCodeException(e);
   446             }
   447         }
   449         @Override
   450         public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
   451             try {
   452                 return clientFileObject.openReader(ignoreEncodingErrors);
   453             } catch (ClientCodeException e) {
   454                 throw e;
   455             } catch (RuntimeException e) {
   456                 throw new ClientCodeException(e);
   457             } catch (Error e) {
   458                 throw new ClientCodeException(e);
   459             }
   460         }
   462         @Override
   463         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   464             try {
   465                 return clientFileObject.getCharContent(ignoreEncodingErrors);
   466             } catch (ClientCodeException e) {
   467                 throw e;
   468             } catch (RuntimeException e) {
   469                 throw new ClientCodeException(e);
   470             } catch (Error e) {
   471                 throw new ClientCodeException(e);
   472             }
   473         }
   475         @Override
   476         public Writer openWriter() throws IOException {
   477             try {
   478                 return clientFileObject.openWriter();
   479             } catch (ClientCodeException e) {
   480                 throw e;
   481             } catch (RuntimeException e) {
   482                 throw new ClientCodeException(e);
   483             } catch (Error e) {
   484                 throw new ClientCodeException(e);
   485             }
   486         }
   488         @Override
   489         public long getLastModified() {
   490             try {
   491                 return clientFileObject.getLastModified();
   492             } catch (ClientCodeException e) {
   493                 throw e;
   494             } catch (RuntimeException e) {
   495                 throw new ClientCodeException(e);
   496             } catch (Error e) {
   497                 throw new ClientCodeException(e);
   498             }
   499         }
   501         @Override
   502         public boolean delete() {
   503             try {
   504                 return clientFileObject.delete();
   505             } catch (ClientCodeException e) {
   506                 throw e;
   507             } catch (RuntimeException e) {
   508                 throw new ClientCodeException(e);
   509             } catch (Error e) {
   510                 throw new ClientCodeException(e);
   511             }
   512         }
   514         @Override
   515         public String toString() {
   516             return wrappedToString(getClass(), clientFileObject);
   517         }
   518     }
   520     protected class WrappedJavaFileObject extends WrappedFileObject implements JavaFileObject {
   521         WrappedJavaFileObject(JavaFileObject clientJavaFileObject) {
   522             super(clientJavaFileObject);
   523         }
   525         @Override
   526         public Kind getKind() {
   527             try {
   528                 return ((JavaFileObject)clientFileObject).getKind();
   529             } catch (ClientCodeException e) {
   530                 throw e;
   531             } catch (RuntimeException e) {
   532                 throw new ClientCodeException(e);
   533             } catch (Error e) {
   534                 throw new ClientCodeException(e);
   535             }
   536         }
   538         @Override
   539         public boolean isNameCompatible(String simpleName, Kind kind) {
   540             try {
   541                 return ((JavaFileObject)clientFileObject).isNameCompatible(simpleName, kind);
   542             } catch (ClientCodeException e) {
   543                 throw e;
   544             } catch (RuntimeException e) {
   545                 throw new ClientCodeException(e);
   546             } catch (Error e) {
   547                 throw new ClientCodeException(e);
   548             }
   549         }
   551         @Override
   552         public NestingKind getNestingKind() {
   553             try {
   554                 return ((JavaFileObject)clientFileObject).getNestingKind();
   555             } catch (ClientCodeException e) {
   556                 throw e;
   557             } catch (RuntimeException e) {
   558                 throw new ClientCodeException(e);
   559             } catch (Error e) {
   560                 throw new ClientCodeException(e);
   561             }
   562         }
   564         @Override
   565         public Modifier getAccessLevel() {
   566             try {
   567                 return ((JavaFileObject)clientFileObject).getAccessLevel();
   568             } catch (ClientCodeException e) {
   569                 throw e;
   570             } catch (RuntimeException e) {
   571                 throw new ClientCodeException(e);
   572             } catch (Error e) {
   573                 throw new ClientCodeException(e);
   574             }
   575         }
   577         @Override
   578         public String toString() {
   579             return wrappedToString(getClass(), clientFileObject);
   580         }
   581     }
   583     protected class WrappedDiagnosticListener<T /*super JavaFileObject*/> implements DiagnosticListener<T> {
   584         protected DiagnosticListener<T> clientDiagnosticListener;
   585         WrappedDiagnosticListener(DiagnosticListener<T> clientDiagnosticListener) {
   586             clientDiagnosticListener.getClass(); // null check
   587             this.clientDiagnosticListener = clientDiagnosticListener;
   588         }
   590         @Override
   591         public void report(Diagnostic<? extends T> diagnostic) {
   592             try {
   593                 clientDiagnosticListener.report(unwrap(diagnostic));
   594             } catch (ClientCodeException e) {
   595                 throw e;
   596             } catch (RuntimeException e) {
   597                 throw new ClientCodeException(e);
   598             } catch (Error e) {
   599                 throw new ClientCodeException(e);
   600             }
   601         }
   603         @Override
   604         public String toString() {
   605             return wrappedToString(getClass(), clientDiagnosticListener);
   606         }
   607     }
   609     public class DiagnosticSourceUnwrapper implements Diagnostic<JavaFileObject> {
   610         public final JCDiagnostic d;
   612         DiagnosticSourceUnwrapper(JCDiagnostic d) {
   613             this.d = d;
   614         }
   616         public Diagnostic.Kind getKind() {
   617             return d.getKind();
   618         }
   620         public JavaFileObject getSource() {
   621             return unwrap(d.getSource());
   622         }
   624         public long getPosition() {
   625             return d.getPosition();
   626         }
   628         public long getStartPosition() {
   629             return d.getStartPosition();
   630         }
   632         public long getEndPosition() {
   633             return d.getEndPosition();
   634         }
   636         public long getLineNumber() {
   637             return d.getLineNumber();
   638         }
   640         public long getColumnNumber() {
   641             return d.getColumnNumber();
   642         }
   644         public String getCode() {
   645             return d.getCode();
   646         }
   648         public String getMessage(Locale locale) {
   649             return d.getMessage(locale);
   650         }
   652         @Override
   653         public String toString() {
   654             return d.toString();
   655         }
   656     }
   658     protected class WrappedTaskListener implements TaskListener {
   659         protected TaskListener clientTaskListener;
   660         WrappedTaskListener(TaskListener clientTaskListener) {
   661             clientTaskListener.getClass(); // null check
   662             this.clientTaskListener = clientTaskListener;
   663         }
   665         @Override
   666         public void started(TaskEvent ev) {
   667             try {
   668                 clientTaskListener.started(ev);
   669             } catch (ClientCodeException e) {
   670                 throw e;
   671             } catch (RuntimeException e) {
   672                 throw new ClientCodeException(e);
   673             } catch (Error e) {
   674                 throw new ClientCodeException(e);
   675             }
   676         }
   678         @Override
   679         public void finished(TaskEvent ev) {
   680             try {
   681                 clientTaskListener.finished(ev);
   682             } catch (ClientCodeException e) {
   683                 throw e;
   684             } catch (RuntimeException e) {
   685                 throw new ClientCodeException(e);
   686             } catch (Error e) {
   687                 throw new ClientCodeException(e);
   688             }
   689         }
   691         @Override
   692         public String toString() {
   693             return wrappedToString(getClass(), clientTaskListener);
   694         }
   695     }
   697     // </editor-fold>
   698 }

mercurial