ClientCodeWrapper.java revision 3981:8be741555fa6
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
26package com.sun.tools.javac.api;
27
28import java.io.File;
29import java.io.IOException;
30import java.io.InputStream;
31import java.io.OutputStream;
32import java.io.Reader;
33import java.io.Writer;
34import java.lang.annotation.ElementType;
35import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
37import java.lang.annotation.Target;
38import java.net.URI;
39import java.nio.file.Path;
40import java.util.ArrayList;
41import java.util.Collection;
42import java.util.Collections;
43import java.util.HashMap;
44import java.util.Iterator;
45import java.util.List;
46import java.util.Locale;
47import java.util.Map;
48import java.util.Objects;
49import java.util.Set;
50
51import javax.lang.model.element.Modifier;
52import javax.lang.model.element.NestingKind;
53import javax.tools.Diagnostic;
54import javax.tools.DiagnosticListener;
55import javax.tools.FileObject;
56import javax.tools.JavaFileManager;
57import javax.tools.JavaFileManager.Location;
58import javax.tools.JavaFileObject;
59import javax.tools.JavaFileObject.Kind;
60import javax.tools.StandardJavaFileManager;
61
62import com.sun.source.util.TaskEvent;
63import com.sun.source.util.TaskListener;
64import com.sun.tools.javac.util.ClientCodeException;
65import com.sun.tools.javac.util.Context;
66import com.sun.tools.javac.util.DefinedBy;
67import com.sun.tools.javac.util.DefinedBy.Api;
68import 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 */
96public 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, unwrap(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}
833