001 /*
002 * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.tools;
027
028 import java.io.*;
029 import java.net.URI;
030 import java.net.URISyntaxException;
031 import java.nio.CharBuffer;
032 import javax.lang.model.element.Modifier;
033 import javax.lang.model.element.NestingKind;
034 import javax.tools.JavaFileObject.Kind;
035
036 /**
037 * Provides simple implementations for most methods in JavaFileObject.
038 * This class is designed to be subclassed and used as a basis for
039 * JavaFileObject implementations. Subclasses can override the
040 * implementation and specification of any method of this class as
041 * long as the general contract of JavaFileObject is obeyed.
042 *
043 * @author Peter von der Ahé
044 * @since 1.6
045 */
046 public class SimpleJavaFileObject implements JavaFileObject {
047 /**
048 * A URI for this file object.
049 */
050 protected final URI uri;
051
052 /**
053 * The kind of this file object.
054 */
055 protected final Kind kind;
056
057 /**
058 * Construct a SimpleJavaFileObject of the given kind and with the
059 * given URI.
060 *
061 * @param uri the URI for this file object
062 * @param kind the kind of this file object
063 */
064 protected SimpleJavaFileObject(URI uri, Kind kind) {
065 // null checks
066 uri.getClass();
067 kind.getClass();
068 if (uri.getPath() == null)
069 throw new IllegalArgumentException("URI must have a path: " + uri);
070 this.uri = uri;
071 this.kind = kind;
072 }
073
074 public URI toUri() {
075 return uri;
076 }
077
078 public String getName() {
079 return toUri().getPath();
080 }
081
082 /**
083 * This implementation always throws {@linkplain
084 * UnsupportedOperationException}. Subclasses can change this
085 * behavior as long as the contract of {@link FileObject} is
086 * obeyed.
087 */
088 public InputStream openInputStream() throws IOException {
089 throw new UnsupportedOperationException();
090 }
091
092 /**
093 * This implementation always throws {@linkplain
094 * UnsupportedOperationException}. Subclasses can change this
095 * behavior as long as the contract of {@link FileObject} is
096 * obeyed.
097 */
098 public OutputStream openOutputStream() throws IOException {
099 throw new UnsupportedOperationException();
100 }
101
102 /**
103 * Wraps the result of {@linkplain #getCharContent} in a Reader.
104 * Subclasses can change this behavior as long as the contract of
105 * {@link FileObject} is obeyed.
106 *
107 * @param ignoreEncodingErrors {@inheritDoc}
108 * @return a Reader wrapping the result of getCharContent
109 * @throws IllegalStateException {@inheritDoc}
110 * @throws UnsupportedOperationException {@inheritDoc}
111 * @throws IOException {@inheritDoc}
112 */
113 public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
114 CharSequence charContent = getCharContent(ignoreEncodingErrors);
115 if (charContent == null)
116 throw new UnsupportedOperationException();
117 if (charContent instanceof CharBuffer) {
118 CharBuffer buffer = (CharBuffer)charContent;
119 if (buffer.hasArray())
120 return new CharArrayReader(buffer.array());
121 }
122 return new StringReader(charContent.toString());
123 }
124
125 /**
126 * This implementation always throws {@linkplain
127 * UnsupportedOperationException}. Subclasses can change this
128 * behavior as long as the contract of {@link FileObject} is
129 * obeyed.
130 */
131 public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
132 throw new UnsupportedOperationException();
133 }
134
135 /**
136 * Wraps the result of openOutputStream in a Writer. Subclasses
137 * can change this behavior as long as the contract of {@link
138 * FileObject} is obeyed.
139 *
140 * @return a Writer wrapping the result of openOutputStream
141 * @throws IllegalStateException {@inheritDoc}
142 * @throws UnsupportedOperationException {@inheritDoc}
143 * @throws IOException {@inheritDoc}
144 */
145 public Writer openWriter() throws IOException {
146 return new OutputStreamWriter(openOutputStream());
147 }
148
149 /**
150 * This implementation returns {@code 0L}. Subclasses can change
151 * this behavior as long as the contract of {@link FileObject} is
152 * obeyed.
153 *
154 * @return {@code 0L}
155 */
156 public long getLastModified() {
157 return 0L;
158 }
159
160 /**
161 * This implementation does nothing. Subclasses can change this
162 * behavior as long as the contract of {@link FileObject} is
163 * obeyed.
164 *
165 * @return {@code false}
166 */
167 public boolean delete() {
168 return false;
169 }
170
171 /**
172 * @return {@code this.kind}
173 */
174 public Kind getKind() {
175 return kind;
176 }
177
178 /**
179 * This implementation compares the path of its URI to the given
180 * simple name. This method returns true if the given kind is
181 * equal to the kind of this object, and if the path is equal to
182 * {@code simpleName + kind.extension} or if it ends with {@code
183 * "/" + simpleName + kind.extension}.
184 *
185 * <p>This method calls {@link #getKind} and {@link #toUri} and
186 * does not access the fields {@link #uri} and {@link #kind}
187 * directly.
188 *
189 * <p>Subclasses can change this behavior as long as the contract
190 * of {@link JavaFileObject} is obeyed.
191 */
192 public boolean isNameCompatible(String simpleName, Kind kind) {
193 String baseName = simpleName + kind.extension;
194 return kind.equals(getKind())
195 && (baseName.equals(toUri().getPath())
196 || toUri().getPath().endsWith("/" + baseName));
197 }
198
199 /**
200 * This implementation returns {@code null}. Subclasses can
201 * change this behavior as long as the contract of
202 * {@link JavaFileObject} is obeyed.
203 */
204 public NestingKind getNestingKind() { return null; }
205
206 /**
207 * This implementation returns {@code null}. Subclasses can
208 * change this behavior as long as the contract of
209 * {@link JavaFileObject} is obeyed.
210 */
211 public Modifier getAccessLevel() { return null; }
212
213 @Override
214 public String toString() {
215 return getClass().getName() + "[" + toUri() + "]";
216 }
217 }