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