1 /*
2  * Copyright (c) 2005, 2006, 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 javax.tools;
27 
28 import java.io.*;
29 import java.net.URI;
30 import java.nio.CharBuffer;
31 import javax.lang.model.element.Modifier;
32 import javax.lang.model.element.NestingKind;
33 import javax.tools.JavaFileObject.Kind;
34 
35 /**
36  * Provides simple implementations for most methods in JavaFileObject.
37  * This class is designed to be subclassed and used as a basis for
38  * JavaFileObject implementations.  Subclasses can override the
39  * implementation and specification of any method of this class as
40  * long as the general contract of JavaFileObject is obeyed.
41  *
42  * @author Peter von der Ahé
43  * @since 1.6
44  */
45 public class SimpleJavaFileObject implements JavaFileObject {
46     /**
47      * A URI for this file object.
48      */
49     protected final URI uri;
50 
51     /**
52      * The kind of this file object.
53      */
54     protected final Kind kind;
55 
56     /**
57      * Construct a SimpleJavaFileObject of the given kind and with the
58      * given URI.
59      *
60      * @param uri  the URI for this file object
61      * @param kind the kind of this file object
62      */
SimpleJavaFileObject(URI uri, Kind kind)63     protected SimpleJavaFileObject(URI uri, Kind kind) {
64         // null checks
65         uri.getClass();
66         kind.getClass();
67         if (uri.getPath() == null)
68             throw new IllegalArgumentException("URI must have a path: " + uri);
69         this.uri = uri;
70         this.kind = kind;
71     }
72 
toUri()73     public URI toUri() {
74         return uri;
75     }
76 
getName()77     public String getName() {
78         return toUri().getPath();
79     }
80 
81     /**
82      * This implementation always throws {@linkplain
83      * UnsupportedOperationException}.  Subclasses can change this
84      * behavior as long as the contract of {@link FileObject} is
85      * obeyed.
86      */
openInputStream()87     public InputStream openInputStream() throws IOException {
88         throw new UnsupportedOperationException();
89     }
90 
91     /**
92      * This implementation always throws {@linkplain
93      * UnsupportedOperationException}.  Subclasses can change this
94      * behavior as long as the contract of {@link FileObject} is
95      * obeyed.
96      */
openOutputStream()97     public OutputStream openOutputStream() throws IOException {
98         throw new UnsupportedOperationException();
99     }
100 
101     /**
102      * Wraps the result of {@linkplain #getCharContent} in a Reader.
103      * Subclasses can change this behavior as long as the contract of
104      * {@link FileObject} is obeyed.
105      *
106      * @param  ignoreEncodingErrors {@inheritDoc}
107      * @return a Reader wrapping the result of getCharContent
108      * @throws IllegalStateException {@inheritDoc}
109      * @throws UnsupportedOperationException {@inheritDoc}
110      * @throws IOException {@inheritDoc}
111      */
openReader(boolean ignoreEncodingErrors)112     public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
113         CharSequence charContent = getCharContent(ignoreEncodingErrors);
114         if (charContent == null)
115             throw new UnsupportedOperationException();
116         if (charContent instanceof CharBuffer) {
117             CharBuffer buffer = (CharBuffer)charContent;
118             if (buffer.hasArray())
119                 return new CharArrayReader(buffer.array());
120         }
121         return new StringReader(charContent.toString());
122     }
123 
124     /**
125      * This implementation always throws {@linkplain
126      * UnsupportedOperationException}.  Subclasses can change this
127      * behavior as long as the contract of {@link FileObject} is
128      * obeyed.
129      */
getCharContent(boolean ignoreEncodingErrors)130     public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
131         throw new UnsupportedOperationException();
132     }
133 
134     /**
135      * Wraps the result of openOutputStream in a Writer.  Subclasses
136      * can change this behavior as long as the contract of {@link
137      * FileObject} is obeyed.
138      *
139      * @return a Writer wrapping the result of openOutputStream
140      * @throws IllegalStateException {@inheritDoc}
141      * @throws UnsupportedOperationException {@inheritDoc}
142      * @throws IOException {@inheritDoc}
143      */
openWriter()144     public Writer openWriter() throws IOException {
145         return new OutputStreamWriter(openOutputStream());
146     }
147 
148     /**
149      * This implementation returns {@code 0L}.  Subclasses can change
150      * this behavior as long as the contract of {@link FileObject} is
151      * obeyed.
152      *
153      * @return {@code 0L}
154      */
getLastModified()155     public long getLastModified() {
156         return 0L;
157     }
158 
159     /**
160      * This implementation does nothing.  Subclasses can change this
161      * behavior as long as the contract of {@link FileObject} is
162      * obeyed.
163      *
164      * @return {@code false}
165      */
delete()166     public boolean delete() {
167         return false;
168     }
169 
170     /**
171      * @return {@code this.kind}
172      */
getKind()173     public Kind getKind() {
174         return kind;
175     }
176 
177     /**
178      * This implementation compares the path of its URI to the given
179      * simple name.  This method returns true if the given kind is
180      * equal to the kind of this object, and if the path is equal to
181      * {@code simpleName + kind.extension} or if it ends with {@code
182      * "/" + simpleName + kind.extension}.
183      *
184      * <p>This method calls {@link #getKind} and {@link #toUri} and
185      * does not access the fields {@link #uri} and {@link #kind}
186      * directly.
187      *
188      * <p>Subclasses can change this behavior as long as the contract
189      * of {@link JavaFileObject} is obeyed.
190      */
isNameCompatible(String simpleName, Kind kind)191     public boolean isNameCompatible(String simpleName, Kind kind) {
192         String baseName = simpleName + kind.extension;
193         return kind.equals(getKind())
194             && (baseName.equals(toUri().getPath())
195                 || toUri().getPath().endsWith("/" + baseName));
196     }
197 
198     /**
199      * This implementation returns {@code null}.  Subclasses can
200      * change this behavior as long as the contract of
201      * {@link JavaFileObject} is obeyed.
202      */
getNestingKind()203     public NestingKind getNestingKind() { return null; }
204 
205     /**
206      * This implementation returns {@code null}.  Subclasses can
207      * change this behavior as long as the contract of
208      * {@link JavaFileObject} is obeyed.
209      */
getAccessLevel()210     public Modifier getAccessLevel()  { return null; }
211 
212     @Override
toString()213     public String toString() {
214         return getClass().getName() + "[" + toUri() + "]";
215     }
216 }
217