1 /* 2 * Copyright (c) 2005, 2020, 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 java.util.Objects; 32 import javax.lang.model.element.Modifier; 33 import javax.lang.model.element.NestingKind; 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 Objects.requireNonNull(uri); 65 Objects.requireNonNull(kind); 66 if (uri.getPath() == null) 67 throw new IllegalArgumentException("URI must have a path: " + uri); 68 this.uri = uri; 69 this.kind = kind; 70 } 71 toUri()72 public URI toUri() { 73 return uri; 74 } 75 getName()76 public String getName() { 77 return toUri().getPath(); 78 } 79 80 /** 81 * This implementation always throws {@linkplain 82 * UnsupportedOperationException}. Subclasses can change this 83 * behavior as long as the contract of {@link FileObject} is 84 * obeyed. 85 */ openInputStream()86 public InputStream openInputStream() throws IOException { 87 throw new UnsupportedOperationException(); 88 } 89 90 /** 91 * This implementation always throws {@linkplain 92 * UnsupportedOperationException}. Subclasses can change this 93 * behavior as long as the contract of {@link FileObject} is 94 * obeyed. 95 */ openOutputStream()96 public OutputStream openOutputStream() throws IOException { 97 throw new UnsupportedOperationException(); 98 } 99 100 /** 101 * Wraps the result of {@linkplain #getCharContent} in a Reader. 102 * Subclasses can change this behavior as long as the contract of 103 * {@link FileObject} is obeyed. 104 * 105 * @param ignoreEncodingErrors {@inheritDoc} 106 * @return a Reader wrapping the result of getCharContent 107 * @throws IllegalStateException {@inheritDoc} 108 * @throws UnsupportedOperationException {@inheritDoc} 109 * @throws IOException {@inheritDoc} 110 */ openReader(boolean ignoreEncodingErrors)111 public Reader openReader(boolean ignoreEncodingErrors) throws IOException { 112 CharSequence charContent = getCharContent(ignoreEncodingErrors); 113 if (charContent == null) 114 throw new UnsupportedOperationException(); 115 if (charContent instanceof CharBuffer) { 116 CharBuffer buffer = (CharBuffer)charContent; 117 if (buffer.hasArray()) 118 return new CharArrayReader(buffer.array()); 119 } 120 return new StringReader(charContent.toString()); 121 } 122 123 /** 124 * This implementation always throws {@linkplain 125 * UnsupportedOperationException}. Subclasses can change this 126 * behavior as long as the contract of {@link FileObject} is 127 * obeyed. 128 */ getCharContent(boolean ignoreEncodingErrors)129 public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { 130 throw new UnsupportedOperationException(); 131 } 132 133 /** 134 * Wraps the result of openOutputStream in a Writer. Subclasses 135 * can change this behavior as long as the contract of {@link 136 * FileObject} is obeyed. 137 * 138 * @return a Writer wrapping the result of openOutputStream 139 * @throws IllegalStateException {@inheritDoc} 140 * @throws UnsupportedOperationException {@inheritDoc} 141 * @throws IOException {@inheritDoc} 142 */ openWriter()143 public Writer openWriter() throws IOException { 144 return new OutputStreamWriter(openOutputStream()); 145 } 146 147 /** 148 * This implementation returns {@code 0L}. Subclasses can change 149 * this behavior as long as the contract of {@link FileObject} is 150 * obeyed. 151 * 152 * @return {@code 0L} 153 */ getLastModified()154 public long getLastModified() { 155 return 0L; 156 } 157 158 /** 159 * This implementation does nothing. Subclasses can change this 160 * behavior as long as the contract of {@link FileObject} is 161 * obeyed. 162 * 163 * @return {@code false} 164 */ delete()165 public boolean delete() { 166 return false; 167 } 168 169 /** 170 * @return {@code this.kind} 171 */ getKind()172 public Kind getKind() { 173 return kind; 174 } 175 176 /** 177 * This implementation compares the path of its URI to the given 178 * simple name. This method returns true if the given kind is 179 * equal to the kind of this object, and if the path is equal to 180 * {@code simpleName + kind.extension} or if it ends with {@code 181 * "/" + simpleName + kind.extension}. 182 * 183 * <p>This method calls {@link #getKind} and {@link #toUri} and 184 * does not access the fields {@link #uri} and {@link #kind} 185 * directly. 186 * 187 * <p>Subclasses can change this behavior as long as the contract 188 * of {@link JavaFileObject} is obeyed. 189 */ isNameCompatible(String simpleName, Kind kind)190 public boolean isNameCompatible(String simpleName, Kind kind) { 191 String baseName = simpleName + kind.extension; 192 return kind.equals(getKind()) 193 && (baseName.equals(toUri().getPath()) 194 || toUri().getPath().endsWith("/" + baseName)); 195 } 196 197 /** 198 * This implementation returns {@code null}. Subclasses can 199 * change this behavior as long as the contract of 200 * {@link JavaFileObject} is obeyed. 201 */ getNestingKind()202 public NestingKind getNestingKind() { return null; } 203 204 /** 205 * This implementation returns {@code null}. Subclasses can 206 * change this behavior as long as the contract of 207 * {@link JavaFileObject} is obeyed. 208 */ getAccessLevel()209 public Modifier getAccessLevel() { return null; } 210 211 @Override toString()212 public String toString() { 213 return getClass().getName() + "[" + toUri() + "]"; 214 } 215 } 216