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    }