ClientCodeWrapper.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 2011, 2015, 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 getModuleLocation(Location location, String moduleName) throws IOException {
352            try {
353                return clientJavaFileManager.getModuleLocation(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 getModuleLocation(Location location, JavaFileObject fo, String pkgName) throws IOException {
363            try {
364                return clientJavaFileManager.getModuleLocation(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>> listModuleLocations(Location location) throws IOException {
385            try {
386                return clientJavaFileManager.listModuleLocations(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, Iterable<? 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
539    protected class WrappedFileObject implements FileObject {
540        protected FileObject clientFileObject;
541        WrappedFileObject(FileObject clientFileObject) {
542            this.clientFileObject = Objects.requireNonNull(clientFileObject);
543        }
544
545        @Override @DefinedBy(Api.COMPILER)
546        public URI toUri() {
547            try {
548                return clientFileObject.toUri();
549            } catch (ClientCodeException e) {
550                throw e;
551            } catch (RuntimeException | Error e) {
552                throw new ClientCodeException(e);
553            }
554        }
555
556        @Override @DefinedBy(Api.COMPILER)
557        public String getName() {
558            try {
559                return clientFileObject.getName();
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 InputStream openInputStream() throws IOException {
569            try {
570                return clientFileObject.openInputStream();
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 OutputStream openOutputStream() throws IOException {
580            try {
581                return clientFileObject.openOutputStream();
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 Reader openReader(boolean ignoreEncodingErrors) throws IOException {
591            try {
592                return clientFileObject.openReader(ignoreEncodingErrors);
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 CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
602            try {
603                return clientFileObject.getCharContent(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 Writer openWriter() throws IOException {
613            try {
614                return clientFileObject.openWriter();
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 long getLastModified() {
624            try {
625                return clientFileObject.getLastModified();
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 boolean delete() {
635            try {
636                return clientFileObject.delete();
637            } catch (ClientCodeException e) {
638                throw e;
639            } catch (RuntimeException | Error e) {
640                throw new ClientCodeException(e);
641            }
642        }
643
644        @Override
645        public String toString() {
646            return wrappedToString(getClass(), clientFileObject);
647        }
648    }
649
650    protected class WrappedJavaFileObject extends WrappedFileObject implements JavaFileObject {
651        WrappedJavaFileObject(JavaFileObject clientJavaFileObject) {
652            super(clientJavaFileObject);
653        }
654
655        @Override @DefinedBy(Api.COMPILER)
656        public Kind getKind() {
657            try {
658                return ((JavaFileObject)clientFileObject).getKind();
659            } catch (ClientCodeException e) {
660                throw e;
661            } catch (RuntimeException | Error e) {
662                throw new ClientCodeException(e);
663            }
664        }
665
666        @Override @DefinedBy(Api.COMPILER)
667        public boolean isNameCompatible(String simpleName, Kind kind) {
668            try {
669                return ((JavaFileObject)clientFileObject).isNameCompatible(simpleName, kind);
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 NestingKind getNestingKind() {
679            try {
680                return ((JavaFileObject)clientFileObject).getNestingKind();
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 Modifier getAccessLevel() {
690            try {
691                return ((JavaFileObject)clientFileObject).getAccessLevel();
692            } catch (ClientCodeException e) {
693                throw e;
694            } catch (RuntimeException | Error e) {
695                throw new ClientCodeException(e);
696            }
697        }
698
699        @Override
700        public String toString() {
701            return wrappedToString(getClass(), clientFileObject);
702        }
703    }
704
705    protected class WrappedDiagnosticListener<T /*super JavaFileObject*/> implements DiagnosticListener<T> {
706        protected DiagnosticListener<T> clientDiagnosticListener;
707        WrappedDiagnosticListener(DiagnosticListener<T> clientDiagnosticListener) {
708            this.clientDiagnosticListener = Objects.requireNonNull(clientDiagnosticListener);
709        }
710
711        @Override @DefinedBy(Api.COMPILER)
712        public void report(Diagnostic<? extends T> diagnostic) {
713            try {
714                clientDiagnosticListener.report(unwrap(diagnostic));
715            } catch (ClientCodeException e) {
716                throw e;
717            } catch (RuntimeException | Error e) {
718                throw new ClientCodeException(e);
719            }
720        }
721
722        @Override
723        public String toString() {
724            return wrappedToString(getClass(), clientDiagnosticListener);
725        }
726    }
727
728    public class DiagnosticSourceUnwrapper implements Diagnostic<JavaFileObject> {
729        public final JCDiagnostic d;
730
731        DiagnosticSourceUnwrapper(JCDiagnostic d) {
732            this.d = d;
733        }
734
735        @Override @DefinedBy(Api.COMPILER)
736        public Diagnostic.Kind getKind() {
737            return d.getKind();
738        }
739
740        @Override @DefinedBy(Api.COMPILER)
741        public JavaFileObject getSource() {
742            return unwrap(d.getSource());
743        }
744
745        @Override @DefinedBy(Api.COMPILER)
746        public long getPosition() {
747            return d.getPosition();
748        }
749
750        @Override @DefinedBy(Api.COMPILER)
751        public long getStartPosition() {
752            return d.getStartPosition();
753        }
754
755        @Override @DefinedBy(Api.COMPILER)
756        public long getEndPosition() {
757            return d.getEndPosition();
758        }
759
760        @Override @DefinedBy(Api.COMPILER)
761        public long getLineNumber() {
762            return d.getLineNumber();
763        }
764
765        @Override @DefinedBy(Api.COMPILER)
766        public long getColumnNumber() {
767            return d.getColumnNumber();
768        }
769
770        @Override @DefinedBy(Api.COMPILER)
771        public String getCode() {
772            return d.getCode();
773        }
774
775        @Override @DefinedBy(Api.COMPILER)
776        public String getMessage(Locale locale) {
777            return d.getMessage(locale);
778        }
779
780        @Override
781        public String toString() {
782            return d.toString();
783        }
784    }
785
786    protected class WrappedTaskListener implements TaskListener {
787        protected TaskListener clientTaskListener;
788        WrappedTaskListener(TaskListener clientTaskListener) {
789            this.clientTaskListener = Objects.requireNonNull(clientTaskListener);
790        }
791
792        @Override @DefinedBy(Api.COMPILER_TREE)
793        public void started(TaskEvent ev) {
794            try {
795                clientTaskListener.started(ev);
796            } catch (ClientCodeException e) {
797                throw e;
798            } catch (RuntimeException | Error e) {
799                throw new ClientCodeException(e);
800            }
801        }
802
803        @Override @DefinedBy(Api.COMPILER_TREE)
804        public void finished(TaskEvent ev) {
805            try {
806                clientTaskListener.finished(ev);
807            } catch (ClientCodeException e) {
808                throw e;
809            } catch (RuntimeException | Error e) {
810                throw new ClientCodeException(e);
811            }
812        }
813
814        @Override
815        public String toString() {
816            return wrappedToString(getClass(), clientTaskListener);
817        }
818    }
819
820    // </editor-fold>
821}
822