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

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

mercurial