1 /*
   2  * Copyright (c) 2011, 2016, 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 package com.sun.tools.javac.api;
  27 
  28 import java.io.File;
  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.nio.file.Path;
  40 import java.util.ArrayList;
  41 import java.util.Collection;
  42 import java.util.Collections;
  43 import java.util.HashMap;
  44 import java.util.Iterator;
  45 import java.util.List;
  46 import java.util.Locale;
  47 import java.util.Map;
  48 import java.util.Objects;
  49 import java.util.Set;
  50 
  51 import javax.lang.model.element.Modifier;
  52 import javax.lang.model.element.NestingKind;
  53 import javax.tools.Diagnostic;
  54 import javax.tools.DiagnosticListener;
  55 import javax.tools.FileObject;
  56 import javax.tools.JavaFileManager;
  57 import javax.tools.JavaFileManager.Location;
  58 import javax.tools.JavaFileObject;
  59 import javax.tools.JavaFileObject.Kind;
  60 import javax.tools.StandardJavaFileManager;
  61 
  62 import com.sun.source.util.TaskEvent;
  63 import com.sun.source.util.TaskListener;
  64 import com.sun.tools.javac.util.ClientCodeException;
  65 import com.sun.tools.javac.util.Context;
  66 import com.sun.tools.javac.util.DefinedBy;
  67 import com.sun.tools.javac.util.DefinedBy.Api;
  68 import com.sun.tools.javac.util.JCDiagnostic;
  69 
  70 /**
  71  *  Wrap objects to enable unchecked exceptions to be caught and handled.
  72  *
  73  *  For each method, exceptions are handled as follows:
  74  *  <ul>
  75  *  <li>Checked exceptions are left alone and propogate upwards in the
  76  *      obvious way, since they are an expected aspect of the method's
  77  *      specification.
  78  *  <li>Unchecked exceptions which have already been caught and wrapped in
  79  *      ClientCodeException are left alone to continue propogating upwards.
  80  *  <li>All other unchecked exceptions (i.e. subtypes of RuntimeException
  81  *      and Error) and caught, and rethrown as a ClientCodeException with
  82  *      its cause set to the original exception.
  83  *  </ul>
  84  *
  85  *  The intent is that ClientCodeException can be caught at an appropriate point
  86  *  in the program and can be distinguished from any unanticipated unchecked
  87  *  exceptions arising in the main body of the code (i.e. bugs.) When the
  88  *  ClientCodeException has been caught, either a suitable message can be
  89  *  generated, or if appropriate, the original cause can be rethrown.
  90  *
  91  *  <p><b>This is NOT part of any supported API.
  92  *  If you write code that depends on this, you do so at your own risk.
  93  *  This code and its internal interfaces are subject to change or
  94  *  deletion without notice.</b>
  95  */
  96 public class ClientCodeWrapper {
  97     @Retention(RetentionPolicy.RUNTIME)
  98     @Target(ElementType.TYPE)
  99     public @interface Trusted { }
 100 
 101     public static ClientCodeWrapper instance(Context context) {
 102         ClientCodeWrapper instance = context.get(ClientCodeWrapper.class);
 103         if (instance == null)
 104             instance = new ClientCodeWrapper(context);
 105         return instance;
 106     }
 107 
 108     /**
 109      * A map to cache the results of whether or not a specific classes can
 110      * be "trusted", and thus does not need to be wrapped.
 111      */
 112     Map<Class<?>, Boolean> trustedClasses;
 113 
 114     protected ClientCodeWrapper(Context context) {
 115         trustedClasses = new HashMap<>();
 116     }
 117 
 118     public JavaFileManager wrap(JavaFileManager fm) {
 119         if (isTrusted(fm))
 120             return fm;
 121         if (fm instanceof StandardJavaFileManager)
 122             return new WrappedStandardJavaFileManager((StandardJavaFileManager) fm);
 123         return new WrappedJavaFileManager(fm);
 124     }
 125 
 126     public FileObject wrap(FileObject fo) {
 127         if (fo == null || isTrusted(fo))
 128             return fo;
 129         return new WrappedFileObject(fo);
 130     }
 131 
 132     FileObject unwrap(FileObject fo) {
 133         if (fo instanceof WrappedFileObject)
 134             return ((WrappedFileObject) fo).clientFileObject;
 135         else
 136             return fo;
 137     }
 138 
 139     public JavaFileObject wrap(JavaFileObject fo) {
 140         if (fo == null || isTrusted(fo))
 141             return fo;
 142         return new WrappedJavaFileObject(fo);
 143     }
 144 
 145     public Iterable<JavaFileObject> wrapJavaFileObjects(Iterable<? extends JavaFileObject> list) {
 146         List<JavaFileObject> wrapped = new ArrayList<>();
 147         for (JavaFileObject fo : list)
 148             wrapped.add(wrap(fo));
 149         return Collections.unmodifiableList(wrapped);
 150     }
 151 
 152     JavaFileObject unwrap(JavaFileObject fo) {
 153         if (fo instanceof WrappedJavaFileObject)
 154             return ((JavaFileObject) ((WrappedJavaFileObject) fo).clientFileObject);
 155         else
 156             return fo;
 157     }
 158 
 159     public <T /*super JavaFileOject*/> DiagnosticListener<T> wrap(DiagnosticListener<T> dl) {
 160         if (isTrusted(dl))
 161             return dl;
 162         return new WrappedDiagnosticListener<>(dl);
 163     }
 164 
 165     TaskListener wrap(TaskListener tl) {
 166         if (isTrusted(tl))
 167             return tl;
 168         return new WrappedTaskListener(tl);
 169     }
 170 
 171     TaskListener unwrap(TaskListener l) {
 172         if (l instanceof WrappedTaskListener)
 173             return ((WrappedTaskListener) l).clientTaskListener;
 174         else
 175             return l;
 176     }
 177 
 178     Collection<TaskListener> unwrap(Collection<? extends TaskListener> listeners) {
 179         Collection<TaskListener> c = new ArrayList<>(listeners.size());
 180         for (TaskListener l: listeners)
 181             c.add(unwrap(l));
 182         return c;
 183     }
 184 
 185     @SuppressWarnings("unchecked")
 186     private <T> Diagnostic<T> unwrap(final Diagnostic<T> diagnostic) {
 187         if (diagnostic instanceof JCDiagnostic) {
 188             JCDiagnostic d = (JCDiagnostic) diagnostic;
 189             return (Diagnostic<T>) new DiagnosticSourceUnwrapper(d);
 190         } else {
 191             return diagnostic;
 192         }
 193     }
 194 
 195     protected boolean isTrusted(Object o) {
 196         Class<?> c = o.getClass();
 197         Boolean trusted = trustedClasses.get(c);
 198         if (trusted == null) {
 199             trusted = c.getName().startsWith("com.sun.tools.javac.")
 200                     || c.isAnnotationPresent(Trusted.class);
 201             trustedClasses.put(c, trusted);
 202         }
 203         return trusted;
 204     }
 205 
 206     private String wrappedToString(Class<?> wrapperClass, Object wrapped) {
 207         return wrapperClass.getSimpleName() + "[" + wrapped + "]";
 208     }
 209 
 210     // <editor-fold defaultstate="collapsed" desc="Wrapper classes">
 211 
 212     protected class WrappedJavaFileManager implements JavaFileManager {
 213         protected JavaFileManager clientJavaFileManager;
 214         WrappedJavaFileManager(JavaFileManager clientJavaFileManager) {
 215             this.clientJavaFileManager = Objects.requireNonNull(clientJavaFileManager);
 216         }
 217 
 218         @Override @DefinedBy(Api.COMPILER)
 219         public ClassLoader getClassLoader(Location location) {
 220             try {
 221                 return clientJavaFileManager.getClassLoader(location);
 222             } catch (ClientCodeException e) {
 223                 throw e;
 224             } catch (RuntimeException | Error e) {
 225                 throw new ClientCodeException(e);
 226             }
 227         }
 228 
 229         @Override @DefinedBy(Api.COMPILER)
 230         public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
 231             try {
 232                 return wrapJavaFileObjects(clientJavaFileManager.list(location, packageName, kinds, recurse));
 233             } catch (ClientCodeException e) {
 234                 throw e;
 235             } catch (RuntimeException | Error e) {
 236                 throw new ClientCodeException(e);
 237             }
 238         }
 239 
 240         @Override @DefinedBy(Api.COMPILER)
 241         public String inferBinaryName(Location location, JavaFileObject file) {
 242             try {
 243                 return clientJavaFileManager.inferBinaryName(location, unwrap(file));
 244             } catch (ClientCodeException e) {
 245                 throw e;
 246             } catch (RuntimeException | Error e) {
 247                 throw new ClientCodeException(e);
 248             }
 249         }
 250 
 251         @Override @DefinedBy(Api.COMPILER)
 252         public boolean isSameFile(FileObject a, FileObject b) {
 253             try {
 254                 return clientJavaFileManager.isSameFile(unwrap(a), unwrap(b));
 255             } catch (ClientCodeException e) {
 256                 throw e;
 257             } catch (RuntimeException | Error e) {
 258                 throw new ClientCodeException(e);
 259             }
 260         }
 261 
 262         @Override @DefinedBy(Api.COMPILER)
 263         public boolean handleOption(String current, Iterator<String> remaining) {
 264             try {
 265                 return clientJavaFileManager.handleOption(current, remaining);
 266             } catch (ClientCodeException e) {
 267                 throw e;
 268             } catch (RuntimeException | Error e) {
 269                 throw new ClientCodeException(e);
 270             }
 271         }
 272 
 273         @Override @DefinedBy(Api.COMPILER)
 274         public boolean hasLocation(Location location) {
 275             try {
 276                 return clientJavaFileManager.hasLocation(location);
 277             } catch (ClientCodeException e) {
 278                 throw e;
 279             } catch (RuntimeException | Error e) {
 280                 throw new ClientCodeException(e);
 281             }
 282         }
 283 
 284         @Override @DefinedBy(Api.COMPILER)
 285         public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
 286             try {
 287                 return wrap(clientJavaFileManager.getJavaFileForInput(location, className, kind));
 288             } catch (ClientCodeException e) {
 289                 throw e;
 290             } catch (RuntimeException | Error e) {
 291                 throw new ClientCodeException(e);
 292             }
 293         }
 294 
 295         @Override @DefinedBy(Api.COMPILER)
 296         public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
 297             try {
 298                 return wrap(clientJavaFileManager.getJavaFileForOutput(location, className, kind, unwrap(sibling)));
 299             } catch (ClientCodeException e) {
 300                 throw e;
 301             } catch (RuntimeException | Error e) {
 302                 throw new ClientCodeException(e);
 303             }
 304         }
 305 
 306         @Override @DefinedBy(Api.COMPILER)
 307         public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
 308             try {
 309                 return wrap(clientJavaFileManager.getFileForInput(location, packageName, relativeName));
 310             } catch (ClientCodeException e) {
 311                 throw e;
 312             } catch (RuntimeException | Error e) {
 313                 throw new ClientCodeException(e);
 314             }
 315         }
 316 
 317         @Override @DefinedBy(Api.COMPILER)
 318         public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
 319             try {
 320                 return wrap(clientJavaFileManager.getFileForOutput(location, packageName, relativeName, unwrap(sibling)));
 321             } catch (ClientCodeException e) {
 322                 throw e;
 323             } catch (RuntimeException | Error e) {
 324                 throw new ClientCodeException(e);
 325             }
 326         }
 327 
 328         @Override @DefinedBy(Api.COMPILER)
 329         public void flush() throws IOException {
 330             try {
 331                 clientJavaFileManager.flush();
 332             } catch (ClientCodeException e) {
 333                 throw e;
 334             } catch (RuntimeException | Error e) {
 335                 throw new ClientCodeException(e);
 336             }
 337         }
 338 
 339         @Override @DefinedBy(Api.COMPILER)
 340         public void close() throws IOException {
 341             try {
 342                 clientJavaFileManager.close();
 343             } catch (ClientCodeException e) {
 344                 throw e;
 345             } catch (RuntimeException | Error e) {
 346                 throw new ClientCodeException(e);
 347             }
 348         }
 349 
 350         @Override @DefinedBy(Api.COMPILER)
 351         public Location getLocationForModule(Location location, String moduleName) throws IOException {
 352             try {
 353                 return clientJavaFileManager.getLocationForModule(location, moduleName);
 354             } catch (ClientCodeException e) {
 355                 throw e;
 356             } catch (RuntimeException | Error e) {
 357                 throw new ClientCodeException(e);
 358             }
 359         }
 360 
 361         @Override @DefinedBy(Api.COMPILER)
 362         public Location getLocationForModule(Location location, JavaFileObject fo, String pkgName) throws IOException {
 363             try {
 364                 return clientJavaFileManager.getLocationForModule(location, fo, pkgName);
 365             } catch (ClientCodeException e) {
 366                 throw e;
 367             } catch (RuntimeException | Error e) {
 368                 throw new ClientCodeException(e);
 369             }
 370         }
 371 
 372         @Override @DefinedBy(Api.COMPILER)
 373         public String inferModuleName(Location location) throws IOException {
 374             try {
 375                 return clientJavaFileManager.inferModuleName(location);
 376             } catch (ClientCodeException e) {
 377                 throw e;
 378             } catch (RuntimeException | Error e) {
 379                 throw new ClientCodeException(e);
 380             }
 381         }
 382 
 383         @Override @DefinedBy(Api.COMPILER)
 384         public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
 385             try {
 386                 return clientJavaFileManager.listLocationsForModules(location);
 387             } catch (ClientCodeException e) {
 388                 throw e;
 389             } catch (RuntimeException | Error e) {
 390                 throw new ClientCodeException(e);
 391             }
 392         }
 393 
 394         @Override @DefinedBy(Api.COMPILER)
 395         public int isSupportedOption(String option) {
 396             try {
 397                 return clientJavaFileManager.isSupportedOption(option);
 398             } catch (ClientCodeException e) {
 399                 throw e;
 400             } catch (RuntimeException | Error e) {
 401                 throw new ClientCodeException(e);
 402             }
 403         }
 404 
 405         @Override
 406         public String toString() {
 407             return wrappedToString(getClass(), clientJavaFileManager);
 408         }
 409     }
 410 
 411     protected class WrappedStandardJavaFileManager extends WrappedJavaFileManager
 412             implements StandardJavaFileManager {
 413         WrappedStandardJavaFileManager(StandardJavaFileManager clientJavaFileManager) {
 414             super(clientJavaFileManager);
 415         }
 416 
 417         @Override @DefinedBy(Api.COMPILER)
 418         public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
 419             try {
 420                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromFiles(files);
 421             } catch (ClientCodeException e) {
 422                 throw e;
 423             } catch (RuntimeException | Error e) {
 424                 throw new ClientCodeException(e);
 425             }
 426         }
 427 
 428         @Override @DefinedBy(Api.COMPILER)
 429         public Iterable<? extends JavaFileObject> getJavaFileObjectsFromPaths(Iterable<? extends Path> paths) {
 430             try {
 431                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromPaths(paths);
 432             } catch (ClientCodeException e) {
 433                 throw e;
 434             } catch (RuntimeException | Error e) {
 435                 throw new ClientCodeException(e);
 436             }
 437         }
 438 
 439         @Override @DefinedBy(Api.COMPILER)
 440         public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
 441             try {
 442                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjects(files);
 443             } catch (ClientCodeException e) {
 444                 throw e;
 445             } catch (RuntimeException | Error e) {
 446                 throw new ClientCodeException(e);
 447             }
 448         }
 449 
 450         @Override @DefinedBy(Api.COMPILER)
 451         public Iterable<? extends JavaFileObject> getJavaFileObjects(Path... paths) {
 452             try {
 453                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjects(paths);
 454             } catch (ClientCodeException e) {
 455                 throw e;
 456             } catch (RuntimeException | Error e) {
 457                 throw new ClientCodeException(e);
 458             }
 459         }
 460 
 461         @Override @DefinedBy(Api.COMPILER)
 462         public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
 463             try {
 464                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjectsFromStrings(names);
 465             } catch (ClientCodeException e) {
 466                 throw e;
 467             } catch (RuntimeException | Error e) {
 468                 throw new ClientCodeException(e);
 469             }
 470         }
 471 
 472         @Override @DefinedBy(Api.COMPILER)
 473         public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
 474             try {
 475                 return ((StandardJavaFileManager)clientJavaFileManager).getJavaFileObjects(names);
 476             } catch (ClientCodeException e) {
 477                 throw e;
 478             } catch (RuntimeException | Error e) {
 479                 throw new ClientCodeException(e);
 480             }
 481         }
 482 
 483         @Override @DefinedBy(Api.COMPILER)
 484         public void setLocation(Location location, Iterable<? extends File> files) throws IOException {
 485             try {
 486                 ((StandardJavaFileManager)clientJavaFileManager).setLocation(location, files);
 487             } catch (ClientCodeException e) {
 488                 throw e;
 489             } catch (RuntimeException | Error e) {
 490                 throw new ClientCodeException(e);
 491             }
 492         }
 493 
 494         @Override @DefinedBy(Api.COMPILER)
 495         public void setLocationFromPaths(Location location, Collection<? extends Path> paths) throws IOException {
 496             try {
 497                 ((StandardJavaFileManager)clientJavaFileManager).setLocationFromPaths(location, paths);
 498             } catch (ClientCodeException e) {
 499                 throw e;
 500             } catch (RuntimeException | Error e) {
 501                 throw new ClientCodeException(e);
 502             }
 503         }
 504 
 505         @Override @DefinedBy(Api.COMPILER)
 506         public Iterable<? extends File> getLocation(Location location) {
 507             try {
 508                 return ((StandardJavaFileManager)clientJavaFileManager).getLocation(location);
 509             } catch (ClientCodeException e) {
 510                 throw e;
 511             } catch (RuntimeException | Error e) {
 512                 throw new ClientCodeException(e);
 513             }
 514         }
 515 
 516         @Override @DefinedBy(Api.COMPILER)
 517         public Iterable<? extends Path> getLocationAsPaths(Location location) {
 518             try {
 519                 return ((StandardJavaFileManager)clientJavaFileManager).getLocationAsPaths(location);
 520             } catch (ClientCodeException e) {
 521                 throw e;
 522             } catch (RuntimeException | Error e) {
 523                 throw new ClientCodeException(e);
 524             }
 525         }
 526 
 527         @Override @DefinedBy(Api.COMPILER)
 528         public Path asPath(FileObject file) {
 529             try {
 530                 return ((StandardJavaFileManager)clientJavaFileManager).asPath(file);
 531             } catch (ClientCodeException e) {
 532                 throw e;
 533             } catch (RuntimeException | Error e) {
 534                 throw new ClientCodeException(e);
 535             }
 536         }
 537 
 538         @Override @DefinedBy(Api.COMPILER)
 539         public void setPathFactory(PathFactory f) {
 540             try {
 541                 ((StandardJavaFileManager)clientJavaFileManager).setPathFactory(f);
 542             } catch (ClientCodeException e) {
 543                 throw e;
 544             } catch (RuntimeException | Error e) {
 545                 throw new ClientCodeException(e);
 546             }
 547         }
 548     }
 549 
 550     protected class WrappedFileObject implements FileObject {
 551         protected FileObject clientFileObject;
 552         WrappedFileObject(FileObject clientFileObject) {
 553             this.clientFileObject = Objects.requireNonNull(clientFileObject);
 554         }
 555 
 556         @Override @DefinedBy(Api.COMPILER)
 557         public URI toUri() {
 558             try {
 559                 return clientFileObject.toUri();
 560             } catch (ClientCodeException e) {
 561                 throw e;
 562             } catch (RuntimeException | Error e) {
 563                 throw new ClientCodeException(e);
 564             }
 565         }
 566 
 567         @Override @DefinedBy(Api.COMPILER)
 568         public String getName() {
 569             try {
 570                 return clientFileObject.getName();
 571             } catch (ClientCodeException e) {
 572                 throw e;
 573             } catch (RuntimeException | Error e) {
 574                 throw new ClientCodeException(e);
 575             }
 576         }
 577 
 578         @Override @DefinedBy(Api.COMPILER)
 579         public InputStream openInputStream() throws IOException {
 580             try {
 581                 return clientFileObject.openInputStream();
 582             } catch (ClientCodeException e) {
 583                 throw e;
 584             } catch (RuntimeException | Error e) {
 585                 throw new ClientCodeException(e);
 586             }
 587         }
 588 
 589         @Override @DefinedBy(Api.COMPILER)
 590         public OutputStream openOutputStream() throws IOException {
 591             try {
 592                 return clientFileObject.openOutputStream();
 593             } catch (ClientCodeException e) {
 594                 throw e;
 595             } catch (RuntimeException | Error e) {
 596                 throw new ClientCodeException(e);
 597             }
 598         }
 599 
 600         @Override @DefinedBy(Api.COMPILER)
 601         public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
 602             try {
 603                 return clientFileObject.openReader(ignoreEncodingErrors);
 604             } catch (ClientCodeException e) {
 605                 throw e;
 606             } catch (RuntimeException | Error e) {
 607                 throw new ClientCodeException(e);
 608             }
 609         }
 610 
 611         @Override @DefinedBy(Api.COMPILER)
 612         public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
 613             try {
 614                 return clientFileObject.getCharContent(ignoreEncodingErrors);
 615             } catch (ClientCodeException e) {
 616                 throw e;
 617             } catch (RuntimeException | Error e) {
 618                 throw new ClientCodeException(e);
 619             }
 620         }
 621 
 622         @Override @DefinedBy(Api.COMPILER)
 623         public Writer openWriter() throws IOException {
 624             try {
 625                 return clientFileObject.openWriter();
 626             } catch (ClientCodeException e) {
 627                 throw e;
 628             } catch (RuntimeException | Error e) {
 629                 throw new ClientCodeException(e);
 630             }
 631         }
 632 
 633         @Override @DefinedBy(Api.COMPILER)
 634         public long getLastModified() {
 635             try {
 636                 return clientFileObject.getLastModified();
 637             } catch (ClientCodeException e) {
 638                 throw e;
 639             } catch (RuntimeException | Error e) {
 640                 throw new ClientCodeException(e);
 641             }
 642         }
 643 
 644         @Override @DefinedBy(Api.COMPILER)
 645         public boolean delete() {
 646             try {
 647                 return clientFileObject.delete();
 648             } catch (ClientCodeException e) {
 649                 throw e;
 650             } catch (RuntimeException | Error e) {
 651                 throw new ClientCodeException(e);
 652             }
 653         }
 654 
 655         @Override
 656         public String toString() {
 657             return wrappedToString(getClass(), clientFileObject);
 658         }
 659     }
 660 
 661     protected class WrappedJavaFileObject extends WrappedFileObject implements JavaFileObject {
 662         WrappedJavaFileObject(JavaFileObject clientJavaFileObject) {
 663             super(clientJavaFileObject);
 664         }
 665 
 666         @Override @DefinedBy(Api.COMPILER)
 667         public Kind getKind() {
 668             try {
 669                 return ((JavaFileObject)clientFileObject).getKind();
 670             } catch (ClientCodeException e) {
 671                 throw e;
 672             } catch (RuntimeException | Error e) {
 673                 throw new ClientCodeException(e);
 674             }
 675         }
 676 
 677         @Override @DefinedBy(Api.COMPILER)
 678         public boolean isNameCompatible(String simpleName, Kind kind) {
 679             try {
 680                 return ((JavaFileObject)clientFileObject).isNameCompatible(simpleName, kind);
 681             } catch (ClientCodeException e) {
 682                 throw e;
 683             } catch (RuntimeException | Error e) {
 684                 throw new ClientCodeException(e);
 685             }
 686         }
 687 
 688         @Override @DefinedBy(Api.COMPILER)
 689         public NestingKind getNestingKind() {
 690             try {
 691                 return ((JavaFileObject)clientFileObject).getNestingKind();
 692             } catch (ClientCodeException e) {
 693                 throw e;
 694             } catch (RuntimeException | Error e) {
 695                 throw new ClientCodeException(e);
 696             }
 697         }
 698 
 699         @Override @DefinedBy(Api.COMPILER)
 700         public Modifier getAccessLevel() {
 701             try {
 702                 return ((JavaFileObject)clientFileObject).getAccessLevel();
 703             } catch (ClientCodeException e) {
 704                 throw e;
 705             } catch (RuntimeException | Error e) {
 706                 throw new ClientCodeException(e);
 707             }
 708         }
 709 
 710         @Override
 711         public String toString() {
 712             return wrappedToString(getClass(), clientFileObject);
 713         }
 714     }
 715 
 716     protected class WrappedDiagnosticListener<T /*super JavaFileObject*/> implements DiagnosticListener<T> {
 717         protected DiagnosticListener<T> clientDiagnosticListener;
 718         WrappedDiagnosticListener(DiagnosticListener<T> clientDiagnosticListener) {
 719             this.clientDiagnosticListener = Objects.requireNonNull(clientDiagnosticListener);
 720         }
 721 
 722         @Override @DefinedBy(Api.COMPILER)
 723         public void report(Diagnostic<? extends T> diagnostic) {
 724             try {
 725                 clientDiagnosticListener.report(unwrap(diagnostic));
 726             } catch (ClientCodeException e) {
 727                 throw e;
 728             } catch (RuntimeException | Error e) {
 729                 throw new ClientCodeException(e);
 730             }
 731         }
 732 
 733         @Override
 734         public String toString() {
 735             return wrappedToString(getClass(), clientDiagnosticListener);
 736         }
 737     }
 738 
 739     public class DiagnosticSourceUnwrapper implements Diagnostic<JavaFileObject> {
 740         public final JCDiagnostic d;
 741 
 742         DiagnosticSourceUnwrapper(JCDiagnostic d) {
 743             this.d = d;
 744         }
 745 
 746         @Override @DefinedBy(Api.COMPILER)
 747         public Diagnostic.Kind getKind() {
 748             return d.getKind();
 749         }
 750 
 751         @Override @DefinedBy(Api.COMPILER)
 752         public JavaFileObject getSource() {
 753             return unwrap(d.getSource());
 754         }
 755 
 756         @Override @DefinedBy(Api.COMPILER)
 757         public long getPosition() {
 758             return d.getPosition();
 759         }
 760 
 761         @Override @DefinedBy(Api.COMPILER)
 762         public long getStartPosition() {
 763             return d.getStartPosition();
 764         }
 765 
 766         @Override @DefinedBy(Api.COMPILER)
 767         public long getEndPosition() {
 768             return d.getEndPosition();
 769         }
 770 
 771         @Override @DefinedBy(Api.COMPILER)
 772         public long getLineNumber() {
 773             return d.getLineNumber();
 774         }
 775 
 776         @Override @DefinedBy(Api.COMPILER)
 777         public long getColumnNumber() {
 778             return d.getColumnNumber();
 779         }
 780 
 781         @Override @DefinedBy(Api.COMPILER)
 782         public String getCode() {
 783             return d.getCode();
 784         }
 785 
 786         @Override @DefinedBy(Api.COMPILER)
 787         public String getMessage(Locale locale) {
 788             return d.getMessage(locale);
 789         }
 790 
 791         @Override
 792         public String toString() {
 793             return d.toString();
 794         }
 795     }
 796 
 797     protected class WrappedTaskListener implements TaskListener {
 798         protected TaskListener clientTaskListener;
 799         WrappedTaskListener(TaskListener clientTaskListener) {
 800             this.clientTaskListener = Objects.requireNonNull(clientTaskListener);
 801         }
 802 
 803         @Override @DefinedBy(Api.COMPILER_TREE)
 804         public void started(TaskEvent ev) {
 805             try {
 806                 clientTaskListener.started(ev);
 807             } catch (ClientCodeException e) {
 808                 throw e;
 809             } catch (RuntimeException | Error e) {
 810                 throw new ClientCodeException(e);
 811             }
 812         }
 813 
 814         @Override @DefinedBy(Api.COMPILER_TREE)
 815         public void finished(TaskEvent ev) {
 816             try {
 817                 clientTaskListener.finished(ev);
 818             } catch (ClientCodeException e) {
 819                 throw e;
 820             } catch (RuntimeException | Error e) {
 821                 throw new ClientCodeException(e);
 822             }
 823         }
 824 
 825         @Override
 826         public String toString() {
 827             return wrappedToString(getClass(), clientTaskListener);
 828         }
 829     }
 830 
 831     // </editor-fold>
 832 }