duke@1: /*
jjg@1092: * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@1: *
duke@1: * This code is free software; you can redistribute it and/or modify it
duke@1: * under the terms of the GNU General Public License version 2 only, as
ohair@554: * published by the Free Software Foundation. Oracle designates this
duke@1: * particular file as subject to the "Classpath" exception as provided
ohair@554: * by Oracle in the LICENSE file that accompanied this code.
duke@1: *
duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT
duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@1: * version 2 for more details (a copy is included in the LICENSE file that
duke@1: * accompanied this code).
duke@1: *
duke@1: * You should have received a copy of the GNU General Public License version
duke@1: * 2 along with this work; if not, write to the Free Software Foundation,
duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@1: *
ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554: * or visit www.oracle.com if you need additional information or have any
ohair@554: * questions.
duke@1: */
duke@1:
duke@1: package com.sun.tools.javac.processing;
duke@1:
duke@1: import java.io.Closeable;
jjg@655: import java.io.FileNotFoundException;
duke@1: import java.io.InputStream;
duke@1: import java.io.OutputStream;
duke@1: import java.io.FilterOutputStream;
duke@1: import java.io.Reader;
duke@1: import java.io.Writer;
duke@1: import java.io.FilterWriter;
duke@1: import java.io.PrintWriter;
duke@1: import java.io.IOException;
jjg@700: import java.util.*;
duke@1:
duke@1: import static java.util.Collections.*;
duke@1:
jjg@700: import javax.annotation.processing.*;
jjg@700: import javax.lang.model.SourceVersion;
jjg@700: import javax.lang.model.element.NestingKind;
jjg@700: import javax.lang.model.element.Modifier;
jjg@700: import javax.lang.model.element.Element;
jjg@700: import javax.tools.*;
duke@1: import javax.tools.JavaFileManager.Location;
jjg@700:
duke@1: import static javax.tools.StandardLocation.SOURCE_OUTPUT;
duke@1: import static javax.tools.StandardLocation.CLASS_OUTPUT;
duke@1:
jjg@700: import com.sun.tools.javac.code.Lint;
jjg@700: import com.sun.tools.javac.util.*;
jjg@700:
jjg@700: import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
jjg@700:
duke@1: /**
duke@1: * The FilerImplementation class must maintain a number of
duke@1: * constraints. First, multiple attempts to open the same path within
duke@1: * the same invocation of the tool results in an IOException being
duke@1: * thrown. For example, trying to open the same source file twice:
duke@1: *
duke@1: *
duke@1: * createSourceFile("foo.Bar")
duke@1: * ...
duke@1: * createSourceFile("foo.Bar")
duke@1: *
duke@1: *
duke@1: * is disallowed as is opening a text file that happens to have
duke@1: * the same name as a source file:
duke@1: *
duke@1: *
duke@1: * createSourceFile("foo.Bar")
duke@1: * ...
duke@1: * createTextFile(SOURCE_TREE, "foo", new File("Bar"), null)
duke@1: *
duke@1: *
duke@1: * Additionally, creating a source file that corresponds to an
duke@1: * already created class file (or vice versa) also results in an
duke@1: * IOException since each type can only be created once. However, if
duke@1: * the Filer is used to create a text file named *.java that happens
duke@1: * to correspond to an existing class file, a warning is *not*
duke@1: * generated. Similarly, a warning is not generated for a binary file
duke@1: * named *.class and an existing source file.
duke@1: *
duke@1: *
The reason for this difference is that source files and class
duke@1: * files are registered with the tool and can get passed on as
duke@1: * declarations to the next round of processing. Files that are just
duke@1: * named *.java and *.class are not processed in that manner; although
duke@1: * having extra source files and class files on the source path and
duke@1: * class path can alter the behavior of the tool and any final
duke@1: * compile.
duke@1: *
jjg@581: *
This is NOT part of any supported API.
duke@1: * If you write code that depends on this, you do so at your own risk.
duke@1: * This code and its internal interfaces are subject to change or
duke@1: * deletion without notice.
duke@1: */
duke@1: public class JavacFiler implements Filer, Closeable {
duke@1: // TODO: Implement different transaction model for updating the
duke@1: // Filer's record keeping on file close.
duke@1:
duke@1: private static final String ALREADY_OPENED =
duke@1: "Output stream or writer has already been opened.";
duke@1: private static final String NOT_FOR_READING =
duke@1: "FileObject was not opened for reading.";
duke@1: private static final String NOT_FOR_WRITING =
duke@1: "FileObject was not opened for writing.";
duke@1:
duke@1: /**
duke@1: * Wrap a JavaFileObject to manage writing by the Filer.
duke@1: */
duke@1: private class FilerOutputFileObject extends ForwardingFileObject {
duke@1: private boolean opened = false;
duke@1: private String name;
duke@1:
duke@1: FilerOutputFileObject(String name, FileObject fileObject) {
duke@1: super(fileObject);
duke@1: this.name = name;
duke@1: }
duke@1:
duke@1: @Override
duke@1: public synchronized OutputStream openOutputStream() throws IOException {
duke@1: if (opened)
duke@1: throw new IOException(ALREADY_OPENED);
duke@1: opened = true;
duke@1: return new FilerOutputStream(name, fileObject);
duke@1: }
duke@1:
duke@1: @Override
duke@1: public synchronized Writer openWriter() throws IOException {
duke@1: if (opened)
duke@1: throw new IOException(ALREADY_OPENED);
duke@1: opened = true;
duke@1: return new FilerWriter(name, fileObject);
duke@1: }
duke@1:
duke@1: // Three anti-literacy methods
duke@1: @Override
duke@1: public InputStream openInputStream() throws IOException {
duke@1: throw new IllegalStateException(NOT_FOR_READING);
duke@1: }
duke@1:
duke@1: @Override
duke@1: public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
duke@1: throw new IllegalStateException(NOT_FOR_READING);
duke@1: }
duke@1:
duke@1: @Override
duke@1: public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
duke@1: throw new IllegalStateException(NOT_FOR_READING);
duke@1: }
duke@1:
duke@1: @Override
duke@1: public boolean delete() {
duke@1: return false;
duke@1: }
duke@1: }
duke@1:
duke@1: private class FilerOutputJavaFileObject extends FilerOutputFileObject implements JavaFileObject {
duke@1: private final JavaFileObject javaFileObject;
duke@1: FilerOutputJavaFileObject(String name, JavaFileObject javaFileObject) {
duke@1: super(name, javaFileObject);
duke@1: this.javaFileObject = javaFileObject;
duke@1: }
duke@1:
duke@1: public JavaFileObject.Kind getKind() {
duke@1: return javaFileObject.getKind();
duke@1: }
duke@1:
duke@1: public boolean isNameCompatible(String simpleName,
duke@1: JavaFileObject.Kind kind) {
duke@1: return javaFileObject.isNameCompatible(simpleName, kind);
duke@1: }
duke@1:
duke@1: public NestingKind getNestingKind() {
duke@1: return javaFileObject.getNestingKind();
duke@1: }
duke@1:
duke@1: public Modifier getAccessLevel() {
duke@1: return javaFileObject.getAccessLevel();
duke@1: }
duke@1: }
duke@1:
duke@1: /**
duke@1: * Wrap a JavaFileObject to manage reading by the Filer.
duke@1: */
duke@1: private class FilerInputFileObject extends ForwardingFileObject {
duke@1: FilerInputFileObject(FileObject fileObject) {
duke@1: super(fileObject);
duke@1: }
duke@1:
duke@1: @Override
duke@1: public OutputStream openOutputStream() throws IOException {
duke@1: throw new IllegalStateException(NOT_FOR_WRITING);
duke@1: }
duke@1:
duke@1: @Override
duke@1: public Writer openWriter() throws IOException {
duke@1: throw new IllegalStateException(NOT_FOR_WRITING);
duke@1: }
duke@1:
duke@1: @Override
duke@1: public boolean delete() {
duke@1: return false;
duke@1: }
duke@1: }
duke@1:
duke@1: private class FilerInputJavaFileObject extends FilerInputFileObject implements JavaFileObject {
duke@1: private final JavaFileObject javaFileObject;
duke@1: FilerInputJavaFileObject(JavaFileObject javaFileObject) {
duke@1: super(javaFileObject);
duke@1: this.javaFileObject = javaFileObject;
duke@1: }
duke@1:
duke@1: public JavaFileObject.Kind getKind() {
duke@1: return javaFileObject.getKind();
duke@1: }
duke@1:
duke@1: public boolean isNameCompatible(String simpleName,
duke@1: JavaFileObject.Kind kind) {
duke@1: return javaFileObject.isNameCompatible(simpleName, kind);
duke@1: }
duke@1:
duke@1: public NestingKind getNestingKind() {
duke@1: return javaFileObject.getNestingKind();
duke@1: }
duke@1:
duke@1: public Modifier getAccessLevel() {
duke@1: return javaFileObject.getAccessLevel();
duke@1: }
duke@1: }
duke@1:
duke@1:
duke@1: /**
duke@1: * Wrap a {@code OutputStream} returned from the {@code
duke@1: * JavaFileManager} to properly register source or class files
duke@1: * when they are closed.
duke@1: */
duke@1: private class FilerOutputStream extends FilterOutputStream {
duke@1: String typeName;
duke@1: FileObject fileObject;
duke@1: boolean closed = false;
duke@1:
duke@1: /**
duke@1: * @param typeName name of class or {@code null} if just a
duke@1: * binary file
duke@1: */
duke@1: FilerOutputStream(String typeName, FileObject fileObject) throws IOException {
duke@1: super(fileObject.openOutputStream());
duke@1: this.typeName = typeName;
duke@1: this.fileObject = fileObject;
duke@1: }
duke@1:
duke@1: public synchronized void close() throws IOException {
duke@1: if (!closed) {
duke@1: closed = true;
duke@1: /*
duke@1: * If an IOException occurs when closing the underlying
duke@1: * stream, still try to process the file.
duke@1: */
duke@1:
duke@1: closeFileObject(typeName, fileObject);
duke@1: out.close();
duke@1: }
duke@1: }
duke@1: }
duke@1:
duke@1: /**
duke@1: * Wrap a {@code Writer} returned from the {@code JavaFileManager}
duke@1: * to properly register source or class files when they are
duke@1: * closed.
duke@1: */
duke@1: private class FilerWriter extends FilterWriter {
duke@1: String typeName;
duke@1: FileObject fileObject;
duke@1: boolean closed = false;
duke@1:
duke@1: /**
duke@1: * @param fileObject the fileObject to be written to
duke@1: * @param typeName name of source file or {@code null} if just a
duke@1: * text file
duke@1: */
duke@1: FilerWriter(String typeName, FileObject fileObject) throws IOException {
duke@1: super(fileObject.openWriter());
duke@1: this.typeName = typeName;
duke@1: this.fileObject = fileObject;
duke@1: }
duke@1:
duke@1: public synchronized void close() throws IOException {
duke@1: if (!closed) {
duke@1: closed = true;
duke@1: /*
duke@1: * If an IOException occurs when closing the underlying
duke@1: * Writer, still try to process the file.
duke@1: */
duke@1:
duke@1: closeFileObject(typeName, fileObject);
duke@1: out.close();
duke@1: }
duke@1: }
duke@1: }
duke@1:
duke@1: JavaFileManager fileManager;
duke@1: Log log;
duke@1: Context context;
duke@1: boolean lastRound;
duke@1:
duke@1: private final boolean lint;
duke@1:
duke@1: /**
duke@1: * Logical names of all created files. This set must be
duke@1: * synchronized.
duke@1: */
duke@1: private final Set fileObjectHistory;
duke@1:
duke@1: /**
duke@1: * Names of types that have had files created but not closed.
duke@1: */
duke@1: private final Set openTypeNames;
duke@1:
duke@1: /**
duke@1: * Names of source files closed in this round. This set must be
duke@1: * synchronized. Its iterators should preserve insertion order.
duke@1: */
duke@1: private Set generatedSourceNames;
duke@1:
duke@1: /**
duke@1: * Names and class files of the class files closed in this round.
duke@1: * This set must be synchronized. Its iterators should preserve
duke@1: * insertion order.
duke@1: */
duke@1: private final Map generatedClasses;
duke@1:
duke@1: /**
duke@1: * JavaFileObjects for source files closed in this round. This
duke@1: * set must be synchronized. Its iterators should preserve
duke@1: * insertion order.
duke@1: */
duke@1: private Set generatedSourceFileObjects;
duke@1:
duke@1: /**
duke@1: * Names of all created source files. Its iterators should
duke@1: * preserve insertion order.
duke@1: */
duke@1: private final Set aggregateGeneratedSourceNames;
duke@1:
duke@1: /**
duke@1: * Names of all created class files. Its iterators should
duke@1: * preserve insertion order.
duke@1: */
duke@1: private final Set aggregateGeneratedClassNames;
duke@1:
duke@1:
duke@1: JavacFiler(Context context) {
duke@1: this.context = context;
duke@1: fileManager = context.get(JavaFileManager.class);
duke@1:
duke@1: log = Log.instance(context);
duke@1:
duke@1: fileObjectHistory = synchronizedSet(new LinkedHashSet());
duke@1: generatedSourceNames = synchronizedSet(new LinkedHashSet());
duke@1: generatedSourceFileObjects = synchronizedSet(new LinkedHashSet());
duke@1:
duke@1: generatedClasses = synchronizedMap(new LinkedHashMap());
duke@1:
duke@1: openTypeNames = synchronizedSet(new LinkedHashSet());
duke@1:
duke@1: aggregateGeneratedSourceNames = new LinkedHashSet();
duke@1: aggregateGeneratedClassNames = new LinkedHashSet();
duke@1:
jjg@700: lint = (Lint.instance(context)).isEnabled(PROCESSING);
duke@1: }
duke@1:
duke@1: public JavaFileObject createSourceFile(CharSequence name,
duke@1: Element... originatingElements) throws IOException {
duke@1: return createSourceOrClassFile(true, name.toString());
duke@1: }
duke@1:
duke@1: public JavaFileObject createClassFile(CharSequence name,
duke@1: Element... originatingElements) throws IOException {
duke@1: return createSourceOrClassFile(false, name.toString());
duke@1: }
duke@1:
duke@1: private JavaFileObject createSourceOrClassFile(boolean isSourceFile, String name) throws IOException {
jjg@618: if (lint) {
jjg@618: int periodIndex = name.lastIndexOf(".");
jjg@618: if (periodIndex != -1) {
jjg@618: String base = name.substring(periodIndex);
jjg@618: String extn = (isSourceFile ? ".java" : ".class");
jjg@618: if (base.equals(extn))
jjg@618: log.warning("proc.suspicious.class.name", name, extn);
jjg@618: }
jjg@618: }
duke@1: checkNameAndExistence(name, isSourceFile);
duke@1: Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT);
duke@1: JavaFileObject.Kind kind = (isSourceFile ?
duke@1: JavaFileObject.Kind.SOURCE :
duke@1: JavaFileObject.Kind.CLASS);
duke@1:
duke@1: JavaFileObject fileObject =
duke@1: fileManager.getJavaFileForOutput(loc, name, kind, null);
duke@1: checkFileReopening(fileObject, true);
duke@1:
duke@1: if (lastRound)
duke@1: log.warning("proc.file.create.last.round", name);
duke@1:
duke@1: if (isSourceFile)
duke@1: aggregateGeneratedSourceNames.add(name);
duke@1: else
duke@1: aggregateGeneratedClassNames.add(name);
duke@1: openTypeNames.add(name);
duke@1:
duke@1: return new FilerOutputJavaFileObject(name, fileObject);
duke@1: }
duke@1:
duke@1: public FileObject createResource(JavaFileManager.Location location,
duke@1: CharSequence pkg,
duke@1: CharSequence relativeName,
duke@1: Element... originatingElements) throws IOException {
duke@1: locationCheck(location);
duke@1:
duke@1: String strPkg = pkg.toString();
duke@1: if (strPkg.length() > 0)
duke@1: checkName(strPkg);
duke@1:
duke@1: FileObject fileObject =
duke@1: fileManager.getFileForOutput(location, strPkg,
duke@1: relativeName.toString(), null);
duke@1: checkFileReopening(fileObject, true);
duke@1:
duke@1: if (fileObject instanceof JavaFileObject)
duke@1: return new FilerOutputJavaFileObject(null, (JavaFileObject)fileObject);
duke@1: else
duke@1: return new FilerOutputFileObject(null, fileObject);
duke@1: }
duke@1:
duke@1: private void locationCheck(JavaFileManager.Location location) {
duke@1: if (location instanceof StandardLocation) {
duke@1: StandardLocation stdLoc = (StandardLocation) location;
duke@1: if (!stdLoc.isOutputLocation())
duke@1: throw new IllegalArgumentException("Resource creation not supported in location " +
duke@1: stdLoc);
duke@1: }
duke@1: }
duke@1:
duke@1: public FileObject getResource(JavaFileManager.Location location,
duke@1: CharSequence pkg,
duke@1: CharSequence relativeName) throws IOException {
duke@1: String strPkg = pkg.toString();
duke@1: if (strPkg.length() > 0)
duke@1: checkName(strPkg);
duke@1:
duke@1: // TODO: Only support reading resources in selected output
duke@1: // locations? Only allow reading of non-source, non-class
duke@1: // files from the supported input locations?
jjg@1092:
jjg@1092: // In the following, getFileForInput is the "obvious" method
jjg@1092: // to use, but it does not have the "obvious" semantics for
jjg@1092: // SOURCE_OUTPUT and CLASS_OUTPUT. Conversely, getFileForOutput
jjg@1092: // does not have the correct semantics for any "path" location
jjg@1092: // with more than one component. So, for now, we use a hybrid
jjg@1092: // invocation.
jjg@1092: FileObject fileObject;
jjg@1092: if (location.isOutputLocation()) {
jjg@1092: fileObject = fileManager.getFileForOutput(location,
jjg@1092: pkg.toString(),
jjg@1092: relativeName.toString(),
jjg@1092: null);
jjg@1092: } else {
jjg@1092: fileObject = fileManager.getFileForInput(location,
jjg@655: pkg.toString(),
jjg@655: relativeName.toString());
jjg@1092: }
jjg@655: if (fileObject == null) {
jjg@655: String name = (pkg.length() == 0)
jjg@655: ? relativeName.toString() : (pkg + "/" + relativeName);
jjg@655: throw new FileNotFoundException(name);
jjg@655: }
jjg@655:
duke@1: // If the path was already opened for writing, throw an exception.
duke@1: checkFileReopening(fileObject, false);
duke@1: return new FilerInputFileObject(fileObject);
duke@1: }
duke@1:
duke@1: private void checkName(String name) throws FilerException {
duke@1: checkName(name, false);
duke@1: }
duke@1:
duke@1: private void checkName(String name, boolean allowUnnamedPackageInfo) throws FilerException {
duke@1: if (!SourceVersion.isName(name) && !isPackageInfo(name, allowUnnamedPackageInfo)) {
duke@1: if (lint)
duke@1: log.warning("proc.illegal.file.name", name);
duke@1: throw new FilerException("Illegal name " + name);
duke@1: }
duke@1: }
duke@1:
duke@1: private boolean isPackageInfo(String name, boolean allowUnnamedPackageInfo) {
duke@1: // Is the name of the form "package-info" or
duke@1: // "foo.bar.package-info"?
duke@1: final String PKG_INFO = "package-info";
duke@1: int periodIndex = name.lastIndexOf(".");
duke@1: if (periodIndex == -1) {
duke@1: return allowUnnamedPackageInfo ? name.equals(PKG_INFO) : false;
duke@1: } else {
duke@1: // "foo.bar.package-info." illegal
duke@1: String prefix = name.substring(0, periodIndex);
duke@1: String simple = name.substring(periodIndex+1);
duke@1: return SourceVersion.isName(prefix) && simple.equals(PKG_INFO);
duke@1: }
duke@1: }
duke@1:
duke@1: private void checkNameAndExistence(String typename, boolean allowUnnamedPackageInfo) throws FilerException {
duke@1: // TODO: Check if type already exists on source or class path?
duke@1: // If so, use warning message key proc.type.already.exists
duke@1: checkName(typename, allowUnnamedPackageInfo);
duke@1: if (aggregateGeneratedSourceNames.contains(typename) ||
duke@1: aggregateGeneratedClassNames.contains(typename)) {
duke@1: if (lint)
duke@1: log.warning("proc.type.recreate", typename);
duke@1: throw new FilerException("Attempt to recreate a file for type " + typename);
duke@1: }
duke@1: }
duke@1:
duke@1: /**
duke@1: * Check to see if the file has already been opened; if so, throw
duke@1: * an exception, otherwise add it to the set of files.
duke@1: */
duke@1: private void checkFileReopening(FileObject fileObject, boolean addToHistory) throws FilerException {
duke@1: for(FileObject veteran : fileObjectHistory) {
duke@1: if (fileManager.isSameFile(veteran, fileObject)) {
duke@1: if (lint)
duke@1: log.warning("proc.file.reopening", fileObject.getName());
duke@1: throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
duke@1: }
duke@1: }
duke@1: if (addToHistory)
duke@1: fileObjectHistory.add(fileObject);
duke@1: }
duke@1:
duke@1: public boolean newFiles() {
duke@1: return (!generatedSourceNames.isEmpty())
duke@1: || (!generatedClasses.isEmpty());
duke@1: }
duke@1:
duke@1: public Set getGeneratedSourceNames() {
duke@1: return generatedSourceNames;
duke@1: }
duke@1:
duke@1: public Set getGeneratedSourceFileObjects() {
duke@1: return generatedSourceFileObjects;
duke@1: }
duke@1:
duke@1: public Map getGeneratedClasses() {
duke@1: return generatedClasses;
duke@1: }
duke@1:
duke@1: public void warnIfUnclosedFiles() {
duke@1: if (!openTypeNames.isEmpty())
duke@1: log.warning("proc.unclosed.type.files", openTypeNames.toString());
duke@1: }
duke@1:
duke@1: /**
duke@1: * Update internal state for a new round.
duke@1: */
jjg@620: public void newRound(Context context) {
duke@1: this.context = context;
duke@1: this.log = Log.instance(context);
jjg@620: clearRoundState();
jjg@620: }
jjg@620:
jjg@620: void setLastRound(boolean lastRound) {
duke@1: this.lastRound = lastRound;
duke@1: }
duke@1:
duke@1: public void close() {
duke@1: clearRoundState();
duke@1: // Cross-round state
duke@1: fileObjectHistory.clear();
duke@1: openTypeNames.clear();
duke@1: aggregateGeneratedSourceNames.clear();
duke@1: aggregateGeneratedClassNames.clear();
duke@1: }
duke@1:
duke@1: private void clearRoundState() {
duke@1: generatedSourceNames.clear();
duke@1: generatedSourceFileObjects.clear();
duke@1: generatedClasses.clear();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Debugging function to display internal state.
duke@1: */
duke@1: public void displayState() {
duke@1: PrintWriter xout = context.get(Log.outKey);
duke@1: xout.println("File Object History : " + fileObjectHistory);
duke@1: xout.println("Open Type Names : " + openTypeNames);
duke@1: xout.println("Gen. Src Names : " + generatedSourceNames);
duke@1: xout.println("Gen. Cls Names : " + generatedClasses.keySet());
duke@1: xout.println("Agg. Gen. Src Names : " + aggregateGeneratedSourceNames);
duke@1: xout.println("Agg. Gen. Cls Names : " + aggregateGeneratedClassNames);
duke@1: }
duke@1:
duke@1: public String toString() {
duke@1: return "javac Filer";
duke@1: }
duke@1:
duke@1: /**
duke@1: * Upon close, register files opened by create{Source, Class}File
duke@1: * for annotation processing.
duke@1: */
duke@1: private void closeFileObject(String typeName, FileObject fileObject) {
duke@1: /*
duke@1: * If typeName is non-null, the file object was opened as a
duke@1: * source or class file by the user. If a file was opened as
duke@1: * a resource, typeName will be null and the file is *not*
duke@1: * subject to annotation processing.
duke@1: */
duke@1: if ((typeName != null)) {
duke@1: if (!(fileObject instanceof JavaFileObject))
duke@1: throw new AssertionError("JavaFileOject not found for " + fileObject);
duke@1: JavaFileObject javaFileObject = (JavaFileObject)fileObject;
duke@1: switch(javaFileObject.getKind()) {
duke@1: case SOURCE:
duke@1: generatedSourceNames.add(typeName);
duke@1: generatedSourceFileObjects.add(javaFileObject);
duke@1: openTypeNames.remove(typeName);
duke@1: break;
duke@1:
duke@1: case CLASS:
duke@1: generatedClasses.put(typeName, javaFileObject);
duke@1: openTypeNames.remove(typeName);
duke@1: break;
duke@1:
duke@1: default:
duke@1: break;
duke@1: }
duke@1: }
duke@1: }
duke@1:
duke@1: }