integrate tag "merge_01092006" from HEAD (3.1.1) to APT_32 branch
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java
index 6c4cd81..4fff1fb 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/AptPlugin.java
@@ -125,6 +125,18 @@
}
/**
+ * Convenience wrapper around log(IStatus), to log an exception
+ * with severity of WARNING.
+ */
+ public static void logWarning(Throwable e, String message) {
+ // TODO: before ship, remove this printing. Instead just log
+ // Note: we don't include the stack here, but it goes in the log
+ System.err.println(message);
+
+ log(createWarningStatus(e, message));
+ }
+
+ /**
* Convenience wrapper for rethrowing exceptions as CoreExceptions,
* with severity of ERROR.
*/
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/env/EclipseAnnotationProcessorEnvironment.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/env/EclipseAnnotationProcessorEnvironment.java
index 74aa167..b01d28d 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/env/EclipseAnnotationProcessorEnvironment.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/env/EclipseAnnotationProcessorEnvironment.java
@@ -11,6 +11,7 @@
package org.eclipse.jdt.apt.core.env;
import org.eclipse.jdt.apt.core.util.EclipseMessager;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.dom.CompilationUnit;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
@@ -42,6 +43,11 @@
Phase getPhase();
/**
+ * @return the java project associated with the current processing phase
+ */
+ IJavaProject getJavaProject();
+
+ /**
* Add a type dependency on the type named <code>fullyQualifiedTypeName</code>
* @param fullyQualifiedTypeName the fully qualified (dot-separated) name of a type.
* @throws IllegalArgumentException if <code>fullyQualifiedTypeName</code> cannot be resolved to a type.
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptCompilationParticipant.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptCompilationParticipant.java
index cde5e9a..c0daec2 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptCompilationParticipant.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptCompilationParticipant.java
@@ -155,8 +155,8 @@
public void cleanStarting(IJavaProject javaProject){
IProject p = javaProject.getProject();
- GeneratedFileManager gfm = AptPlugin.getAptProject(javaProject).getGeneratedFileManager();
- gfm.projectClean( true );
+
+ AptPlugin.getAptProject(javaProject).projectClean( true );
try{
// clear out all markers during a clean.
IMarker[] markers = p.findMarkers(AptPlugin.APT_BATCH_PROCESSOR_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
@@ -181,9 +181,8 @@
public int aboutToBuild(IJavaProject project) {
if (AptConfig.isEnabled(project)) {
- // setup the classpath and make sure the generated source folder is on disk.
- GeneratedFileManager manager = AptPlugin.getAptProject(project).getGeneratedFileManager();
- manager.compilationStarted();
+ // setup the classpath and make sure the generated source folder is on disk.
+ AptPlugin.getAptProject(project).compilationStarted();
}
_buildRound = 0; // reset
// TODO: (wharley) if the factory path is different we need a full build
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java
index 56b9dde..249090f 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/AptProject.java
@@ -1,6 +1,12 @@
package org.eclipse.jdt.apt.core.internal;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.apt.core.AptPlugin;
import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedFileManager;
+import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedSourceFolderManager;
+import org.eclipse.jdt.apt.core.util.AptPreferenceConstants;
import org.eclipse.jdt.core.IJavaProject;
/**
@@ -14,9 +20,12 @@
private final GeneratedFileManager _gfm;
+ private final GeneratedSourceFolderManager _gsfm;
+
public AptProject(final IJavaProject javaProject) {
_javaProject = javaProject;
- _gfm = new GeneratedFileManager(this);
+ _gsfm = new GeneratedSourceFolderManager(this);
+ _gfm = new GeneratedFileManager(this, _gsfm);
}
public IJavaProject getJavaProject() {
@@ -26,4 +35,105 @@
public GeneratedFileManager getGeneratedFileManager() {
return _gfm;
}
+
+ public GeneratedSourceFolderManager getGeneratedSourceFolderManager() {
+ return _gsfm;
+ }
+
+ /**
+ * This method should be called whenever project preferences are
+ * changed by the user. It is safe to call it on every change;
+ * irrelevant changes will be efficiently ignored. This may cause
+ * the classpath and generated source folder to change, so this
+ * should <em>not</em> be called from a resource change listener,
+ * preference change listener, or other context where resources
+ * may be locked.
+ * @param key a preference key such as @see AptPreferenceConstants#APT_ENABLED
+ * @param oldValue the old value, or null if unknown
+ * @param newValue the new value, which will be ignored if it is null
+ */
+ public void handlePreferenceChange(String key, String oldValue, String newValue) {
+ if (newValue == null) {
+ // Null is used to indicate this preference has
+ // been removed, as the project has been deleted.
+ // We do nothing.
+ return;
+ }
+ if (newValue.equals(oldValue)) {
+ // Nothing has changed
+ return;
+ }
+
+ if (AptPreferenceConstants.APT_GENSRCDIR.equals(key)) {
+ _gsfm.changeFolderName(oldValue, newValue);
+ }
+ else if(AptPreferenceConstants.APT_ENABLED.equals(key) ){
+ _gsfm.setEnabled(Boolean.parseBoolean(newValue));
+ }
+ }
+
+ /**
+ * This method should be called whenever compilation begins, to perform
+ * initialization and verify configuration.
+ */
+ public void compilationStarted() {
+ _gfm.compilationStarted();
+ }
+
+ /**
+ * Invoked whenever a project is cleaned. This will remove any state kept about
+ * generated files for the given project. If the deleteFiles flag is specified,
+ * then the contents of the generated source folder will be deleted.
+ *
+ * @param deleteFiles true if the contents of the generated source folder are to be
+ * deleted, false otherwise.
+ */
+
+ public void projectClean( boolean deleteFiles )
+ {
+ _gfm.clearAllMaps();
+
+ // delete the contents of the generated source folder, but don't delete
+ // the generated source folder because that will cause a classpath change,
+ // which will force the next build to be a full build.
+ if ( deleteFiles )
+ {
+ IFolder f = _gsfm.getFolder();
+ if ( f != null && f.exists() )
+ {
+ try
+ {
+ IResource[] members = f.members();
+ for ( int i = 0; i<members.length; i++ ){
+ _gfm.deleteDerivedResources(members[i]);
+ }
+ }
+ catch ( CoreException ce )
+ {
+ AptPlugin.log(ce, "Could not delete generated files"); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ /**
+ * invoked when a project is closed. This will discard any open working-copies
+ * of generated files.
+ */
+ public void projectClosed()
+ {
+ _gfm.clearWorkingCopyMaps();
+ }
+
+ /**
+ * Invoked when a project has been deleted. This will remove this generated file manager
+ * from the static map of projects->generated file managers, and this will flush any known
+ * in-memory state tracking generated files. This will not delete any of the project's generated files
+ * from disk.
+ */
+ public void projectDeleted()
+ {
+ _gfm.clearAllMaps();
+ }
+
}
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java
index 4620565..3377f38 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/BinaryFileOutputStream.java
@@ -29,35 +29,67 @@
*/
public class BinaryFileOutputStream extends ByteArrayOutputStream {
- private final IFile _file;
+ protected final IFile _file;
+ private final ProcessorEnvImpl _env;
- public BinaryFileOutputStream(IFile file) {
+ public BinaryFileOutputStream(IFile file, ProcessorEnvImpl env) {
_file = file;
+ _env = env;
}
@Override
public void close() throws IOException {
super.close();
+
InputStream contents = new ByteArrayInputStream(toByteArray());
- if (!_file.exists()) {
- saveToDisk(contents, true);
- return;
- }
- boolean needToWriteData = true;
try {
- // Only write the contents if the data is different
- InputStream in = new ByteArrayInputStream(toByteArray());
- InputStream oldData = new BufferedInputStream(_file.getContents());
- if (FileSystemUtil.compareStreams(in, oldData)) {
- needToWriteData = false;
+
+ boolean contentsChanged = true;
+ if (!_file.exists()) {
+ saveToDisk(contents, true);
+ }
+ else {
+ InputStream in = null;
+ InputStream oldData = null;
+ try {
+ // Only write the contents if the data is different
+ in = new ByteArrayInputStream(toByteArray());
+ oldData = new BufferedInputStream(_file.getContents());
+ if (FileSystemUtil.compareStreams(in, oldData)) {
+ contentsChanged = false;
+ }
+ }
+ catch (CoreException ce) {
+ // Ignore -- couldn't read the old data, so assume it's different
+ contentsChanged = true;
+ }
+ finally {
+ closeInputStream(in);
+ closeInputStream(oldData);
+ }
+ if (contentsChanged) {
+ contents.reset();
+ saveToDisk(contents, false);
+ }
}
}
- catch (CoreException ce) {
- // Ignore -- couldn't read the old data, so assume it's different
+ finally {
+ closeInputStream(contents);
}
- if (needToWriteData) {
- contents.reset();
- saveToDisk(contents, false);
+
+ IFile parentFile = _env.getFile();
+ if (parentFile != null) {
+ _env.getAptProject().getGeneratedFileManager().addEntryToFileMaps(parentFile, _file);
+ _env.addGeneratedNonSourceFile(_file);
+ }
+ }
+
+ private void closeInputStream(InputStream stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ }
+ catch (IOException ioe) {}
}
}
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/FileRefreshJob.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/FileRefreshJob.java
deleted file mode 100644
index c4949d9..0000000
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/FileRefreshJob.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * jgarms@bea.com - initial API and implementation
- *
- *******************************************************************************/
-package org.eclipse.jdt.apt.core.internal.env;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-
-public class FileRefreshJob extends Job {
-
- private final IFile _file;
-
- FileRefreshJob(final IFile file) {
- super(file.toString());
- _file = file;
- }
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- _file.getParent().refreshLocal(IResource.DEPTH_INFINITE, monitor);
- }
- catch (CoreException ce) {
- return ce.getStatus();
- }
- return Status.OK_STATUS;
- }
-
-}
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/FilerImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/FilerImpl.java
index e34d15f..bb5c629 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/FilerImpl.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/FilerImpl.java
@@ -22,7 +22,7 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.apt.core.AptPlugin;
import org.eclipse.jdt.apt.core.env.Phase;
-import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedFileManager;
+import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedSourceFolderManager;
import org.eclipse.jdt.apt.core.internal.util.FileSystemUtil;
import org.eclipse.jdt.core.JavaModelException;
@@ -75,11 +75,11 @@
return new NoOpOutputStream();
}
- GeneratedFileManager gfm = _env.getAptProject().getGeneratedFileManager();
+ GeneratedSourceFolderManager gsfm = _env.getAptProject().getGeneratedSourceFolderManager();
IPath path;
try
{
- path = gfm.getGeneratedSourceFolderOutputLocation();
+ path = gsfm.getBinaryOutputLocation();
}
catch ( Exception e )
{
@@ -91,7 +91,7 @@
path = path.append(name.replace('.', File.separatorChar) + ".class"); //$NON-NLS-1$
IFile file = _env.getProject().getFile(path);
- return new BinaryFileOutputStream(file);
+ return new BinaryFileOutputStream(file, _env);
}
public boolean hasGeneratedClassFile(){ return _generatedClassFiles; }
@@ -125,7 +125,7 @@
IPath path = getOutputFileForLocation( loc, pkg, relPath );
IFile file = _env.getProject().getFile(path);
- OutputStream binaryOut = new BinaryFileOutputStream(file);
+ OutputStream binaryOut = new EncodedFileOutputStream(file, _env, charsetName);
if (charsetName == null) {
return new PrintWriter(binaryOut);
@@ -161,7 +161,7 @@
IPath path = getOutputFileForLocation( loc, pkg, relPath );
IFile file = _env.getProject().getFile(path);
- return new BinaryFileOutputStream(file);
+ return new BinaryFileOutputStream(file, _env);
}
/**
@@ -170,13 +170,13 @@
private IPath getOutputFileForLocation( Filer.Location loc, String pkg, File relPath )
throws IOException
{
- GeneratedFileManager gfm = _env.getAptProject().getGeneratedFileManager();
+ GeneratedSourceFolderManager gsfm = _env.getAptProject().getGeneratedSourceFolderManager();
IPath path = null;
if ( loc == Filer.Location.CLASS_TREE )
{
try
{
- path = gfm.getGeneratedSourceFolderOutputLocation();
+ path = gsfm.getBinaryOutputLocation();
}
catch ( JavaModelException e )
{
@@ -185,7 +185,7 @@
}
}
else if ( loc == Filer.Location.SOURCE_TREE ) {
- path = gfm.getGeneratedSourceFolder().getProjectRelativePath();
+ path = gsfm.getFolder().getProjectRelativePath();
}
if( pkg != null )
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/JavaSourceFilePrintWriter.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/JavaSourceFilePrintWriter.java
index 30cdb7f..4b78447 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/JavaSourceFilePrintWriter.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/JavaSourceFilePrintWriter.java
@@ -22,6 +22,10 @@
// note: only works in BUILD phase.
public class JavaSourceFilePrintWriter extends PrintWriter {
+ private final StringWriter _sw;
+ private final String _typeName;
+ private final ProcessorEnvImpl _env;
+
public JavaSourceFilePrintWriter( String typeName, StringWriter sw, ProcessorEnvImpl env )
{
super( sw );
@@ -39,16 +43,11 @@
FileGenerationResult result = gfm.generateFileDuringBuild(
_env.getFile(), _typeName, contents, _env, null /* progress monitor */ );;
if (result != null) {
- _env.addGeneratedFile(result.getFile(), result.isModified());
+ _env.addGeneratedSourceFile(result.getFile(), result.isModified());
}
}
catch (CoreException ce) {
AptPlugin.log(ce, "Unable to generate type when JavaSourceFilePrintWriter was closed"); //$NON-NLS-1$
}
}
-
-
- private StringWriter _sw;
- private String _typeName;
- private ProcessorEnvImpl _env;
}
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java
index 37394d4..0a40847 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/env/ProcessorEnvImpl.java
@@ -63,8 +63,8 @@
private static final boolean ENABLE_GENERATED_FILE_LISTENER = false;
private boolean _hasRaisedErrors = false;
- private Set<IFile> _allGeneratedFiles = new HashSet<IFile>();
- private Set<IFile> _modifiedGeneratedFiles = new HashSet<IFile>();
+ private Set<IFile> _allGeneratedSourceFiles = new HashSet<IFile>();
+ private Set<IFile> _modifiedGeneratedSourceFiles = new HashSet<IFile>();
private final FilerImpl _filer;
/**
@@ -189,21 +189,29 @@
return null;
}
- public void addGeneratedFile( IFile f, boolean contentsChanged ) {
- _allGeneratedFiles.add(f);
+ public void addGeneratedSourceFile( IFile f, boolean contentsChanged ) {
+ if (!f.toString().endsWith(".java")) { //$NON-NLS-1$
+ throw new IllegalArgumentException("Source files must be java source files, and end with .java"); //$NON-NLS-1$
+ }
+
+ _allGeneratedSourceFiles.add(f);
if (contentsChanged)
- _modifiedGeneratedFiles.add(f);
+ _modifiedGeneratedSourceFiles.add(f);
}
- public Set<IFile> getAllGeneratedFiles(){ return _allGeneratedFiles; }
+ public void addGeneratedNonSourceFile(final IFile file) {
+ _allGeneratedSourceFiles.add(file);
+ }
+
+ public Set<IFile> getAllGeneratedFiles(){ return _allGeneratedSourceFiles; }
- public Set<IFile> getModifiedGeneratedFiles() { return _modifiedGeneratedFiles; }
+ public Set<IFile> getModifiedGeneratedFiles() { return _modifiedGeneratedSourceFiles; }
/**
* @return true iff source files has been generated.
* Always return false when this environment is closed.
*/
- public boolean hasGeneratedSourceFiles(){ return !_allGeneratedFiles.isEmpty(); }
+ public boolean hasGeneratedSourceFiles(){ return !_allGeneratedSourceFiles.isEmpty(); }
/**
* @return true iff class files has been generated.
@@ -244,8 +252,8 @@
_filesWithAnnotation = null;
_problems = null;
_modelCompUnit2astCompUnit.clear();
- _allGeneratedFiles = null;
- _modifiedGeneratedFiles = null;
+ _allGeneratedSourceFiles = null;
+ _modifiedGeneratedSourceFiles = null;
_hasRaisedErrors = false;
super.close();
}
@@ -501,7 +509,7 @@
private void completedProcessing(){
_problems.clear();
- _modifiedGeneratedFiles.clear();
+ _modifiedGeneratedSourceFiles.clear();
_typeDependencies.clear();
}
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java
index be7796c..f28eb4a 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedFileManager.java
@@ -29,24 +29,17 @@
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
-import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.apt.core.AptPlugin;
import org.eclipse.jdt.apt.core.internal.AptProject;
import org.eclipse.jdt.apt.core.internal.Messages;
import org.eclipse.jdt.apt.core.internal.env.ProcessorEnvImpl;
import org.eclipse.jdt.apt.core.internal.util.FileSystemUtil;
-import org.eclipse.jdt.apt.core.util.AptConfig;
-import org.eclipse.jdt.apt.core.util.AptPreferenceConstants;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
@@ -86,7 +79,7 @@
*
*/
public class GeneratedFileManager {
-
+
// disable type generation during reconcile. This can cause deadlock.
// See radar bug #238684
public static final boolean GENERATE_TYPE_DURING_RECONCILE = false;
@@ -115,16 +108,9 @@
*/
private Map<IFile, ICompilationUnit> _generatedFile2WorkingCopy = new HashMap();
- /**
- * The folder where generated source files are placed. This will be null until
- * the folder is actually created and the project's source path is updated to
- * include the folder.
- */
- private IFolder _generatedSourceFolder;
+ private final IJavaProject _jProject;
- private String _generatedSourceFolderName;
-
- private final AptProject _aptProject;
+ private final GeneratedSourceFolderManager _gsfm;
// This is set when the build starts, and accessed during type generation.
private IPackageFragmentRoot _generatedPackageFragmentRoot;
@@ -138,29 +124,11 @@
private String _snapshotFolderName = null;
/**
- * Construction can only take place from within
- * the factory method, getGeneratedFileManager().
+ * Clients should not instantiate this class; it is created only by @see AptProject .
*/
- public GeneratedFileManager(final AptProject aptProject) {
- _aptProject = aptProject;
- final IJavaProject javaProject = aptProject.getJavaProject();
-
- // get generated source dir from config
- // default value is set in org.eclipse.jdt.apt.core.internal.util.AptCorePreferenceInitializer
- _generatedSourceFolderName = AptConfig.getString( javaProject, AptPreferenceConstants.APT_GENSRCDIR);
- // properly initialize the GeneratedFileManager if project path is up-to-date and the generated
- // source folder is there.
- final IFolder folder = javaProject.getProject().getFolder(_generatedSourceFolderName);
- if(folder.exists()){
- boolean uptodate = false;
- try{
- uptodate = isProjectClassPathUpToDate(javaProject, null, folder.getFullPath(), null);
- }catch(JavaModelException e){
- e.printStackTrace();
- }
- if( uptodate )
- _generatedSourceFolder = folder;
- }
+ public GeneratedFileManager(final AptProject aptProject, final GeneratedSourceFolderManager gsfm) {
+ _jProject = aptProject.getJavaProject();
+ _gsfm = gsfm;
}
static
@@ -197,11 +165,13 @@
throws CoreException
{
if( _skipTypeGeneration ) return null;
+ // If the generated package fragment root wasn't set,
+ // then our classpath is incorrect. Add a marker and return
else if( _generatedPackageFragmentRoot == null ){
String message = Messages.bind(
Messages.GeneratedFileManager_missing_classpath_entry,
new String[] {_snapshotFolderName});
- IMarker marker = _aptProject.getJavaProject().getProject().createMarker(AptPlugin.APT_CONFIG_PROBLEM_MARKER);
+ IMarker marker = _jProject.getProject().createMarker(AptPlugin.APT_CONFIG_PROBLEM_MARKER);
marker.setAttributes(
new String[] {
IMarker.MESSAGE,
@@ -265,7 +235,6 @@
// Do nothing. Assume the new content is different
}
finally {
- is.reset();
if (oldData != null) {
try {
oldData.close();
@@ -273,6 +242,13 @@
catch (IOException ioe)
{}
}
+ if (is != null) {
+ try {
+ is.close();
+ }
+ catch (IOException ioe)
+ {}
+ }
}
}
@@ -311,8 +287,9 @@
// as refactorings then fail in the future, which is worse
// than allowing a user to modify a generated file.
- // during a batch build
- if( parentFile != null ){
+ // during a batch build, parentFile will be null.
+ // Only keep track of ownership in iterative builds
+ if( parentFile != null ) {
addEntryToFileMaps( parentFile, file );
}
return new FileGenerationResult(file, contentsDiffer);
@@ -324,7 +301,7 @@
return null; // something failed. The catch block have already logged the error.
}
-
+
/**
* This function generates a type "in-memory" by creating or updating a working copy with the
* specified contents. The generated-source folder must be configured correctly for this to
@@ -413,75 +390,6 @@
/**
- * Update the classpath and generated source folder in response to a change
- * in a preference.
- * <p>
- * This used to be called within a preference change listener. However, we
- * sometimes get preference change events within jobs that hold locks that
- * are incompatible with changing the classpath. Instead, we now call this
- * method directly from AptConfig and from the APT config UI code whenever
- * the preference has changed. Programmatic preference changes, such as those
- * that take place when syncing to a changed settings file, do not directly
- * cause the classpath or GSF to be updated. This is fine, because changes
- * like that should simultaneously update both the preferences and the classpath
- * (except in the case of syncing to a broken project, which we don't want to
- * fix anyhow). The GSF will still get created on disk during the prebuild
- * notification.
- * @param key the preference that is changing, e.g., AptPreferenceConstants.APT_GENSRCDIR
- * @param oldValue the previous value, or null if unknown
- * @param newValue the new value, which must not be null
- */
- public void handlePreferenceChange(String key, String oldValue, String newValue)
- {
- if (newValue == null) {
- // Null is used to indicate this preference has
- // been removed, as the project has been deleted.
- // We do nothing
- return;
- }
- if (newValue.equals(oldValue)) {
- // No-op -- same config
- return;
- }
-
- if (AptPreferenceConstants.APT_GENSRCDIR.equals(key)) {
- final boolean aptEnabled = AptConfig.isEnabled(_aptProject.getJavaProject());
- if( AptPlugin.DEBUG )
- AptPlugin.trace("configure generated source directory new value = " + //$NON-NLS-1$
- newValue +
- " old value = " + oldValue + //$NON-NLS-1$
- " APT is enabled = " + aptEnabled); //$NON-NLS-1$
- // If APT is enabled,
- // clean up the old cp entry, delete the old folder,
- // create the new one and update the classpath.
- if( aptEnabled )
- configureGeneratedSourceFolder( newValue, oldValue );
- else
- setGeneratedSourceFolderName(newValue);
- }
- else if(AptPreferenceConstants.APT_ENABLED.equals(key) ){
- if( AptPlugin.DEBUG ){
- AptPlugin.trace("Got preference change event for " + AptPreferenceConstants.APT_ENABLED ); //$NON-NLS-1$
- }
-
- final boolean isEnabling = Boolean.parseBoolean(newValue);
- if( AptPlugin.DEBUG ){
- if( isEnabling )
- AptPlugin.trace("enabling APT for " + _aptProject.getJavaProject().getElementName()); //$NON-NLS-1$
- else
- AptPlugin.trace("diabling APT " + _aptProject.getJavaProject().getElementName()); //$NON-NLS-1$
- }
- if( isEnabling )
- configureGeneratedSourceFolder();
- else{
- final IFolder srcFolder = getGeneratedSourceFolder();
- projectClean(true);
- resetGeneratedSrcFolder(srcFolder, false);
- }
- }
- }
-
- /**
* returns true if the specified file is a generated file (i.e., it has one or more parent files)
*
* @param f the file in question
@@ -516,27 +424,6 @@
/**
- * returns true if the specified folder is the source folder used where
- * generated files are placed.
- *
- * @param folder - the folder to determine if it is the generated source folder
- * @return true if it is the generated source folder, false otherwise.
- *
- * @see #getGeneratedSourceFolder()
- */
- public boolean isGeneratedSourceFolder( IFolder folder )
- {
- // use getGeneratedSourceFolder() here. Bad things can happen if we try to
- // create the generated source folder when this is invoked from a resource
- // change listener
- if ( folder != null && folder.equals( getGeneratedSourceFolder() ) )
- return true;
- else
- return false;
- }
-
-
- /**
* @param parent - the parent file that you want to get generated files for
* @return Set of IFile instances that are the files known to be generated
* by this parent
@@ -569,7 +456,7 @@
* @param parentFile - the parent file for the generated file
* @throws JavaModelException
*/
- public void discardGeneratedWorkingCopy( IFile generatedFile, IFile parentFile )
+ private void discardGeneratedWorkingCopy( IFile generatedFile, IFile parentFile )
throws JavaModelException
{
removeFromWorkingCopyMaps( generatedFile, parentFile );
@@ -647,10 +534,16 @@
}
if ( delete ){
- final IFolder genFolder = getGeneratedSourceFolder();
+ final IFolder genFolder = _gsfm.getFolder();
assert genFolder != null : "Generated folder == null"; //$NON-NLS-1$
IContainer parent = generatedFile.getParent();
- generatedFile.delete(true, true, progressMonitor);
+ try {
+ generatedFile.delete(true, true, progressMonitor);
+ }
+ catch (CoreException ce) {
+ // File was locked or read-only
+ AptPlugin.logWarning(ce, "Failed to delete file: " + generatedFile); //$NON-NLS-1$
+ }
// not deleting the generated source folder and only
// delete generated folders containing the generated file.
while( !genFolder.equals(parent) && parent != null && parent.isDerived() ){
@@ -771,8 +664,7 @@
{
IPath p = f.getFullPath();
- IProject project = f.getProject();
- IFolder folder = project.getFolder( getGeneratedSourceFolderName() );
+ IFolder folder = _gsfm.getFolder();
IPath generatedSourcePath = folder.getFullPath();
int count = p.matchingFirstSegments( generatedSourcePath );
@@ -793,7 +685,7 @@
// split the type name into its parts
String[] parts = typeName.split( "\\."); //$NON-NLS-1$
- IFolder folder = getGeneratedSourceFolder();
+ IFolder folder = _gsfm.getFolder();
for ( int i = 0; i < parts.length - 1; i++ )
folder = folder.getFolder( parts[i] );
@@ -876,7 +768,7 @@
try{
// clear out any generated source folder config markers
- IMarker[] markers = _aptProject.getJavaProject().getProject().findMarkers(AptPlugin.APT_CONFIG_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
+ IMarker[] markers = _jProject.getProject().findMarkers(AptPlugin.APT_CONFIG_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
if( markers != null ){
for( IMarker marker : markers )
marker.delete();
@@ -886,15 +778,15 @@
AptPlugin.log(e, "Unable to delete configuration marker."); //$NON-NLS-1$
}
_skipTypeGeneration = false;
- createGeneratedSourceFolder();
+ _gsfm.createGeneratedSourceFolder();
final IFolder genFolder;
synchronized(this){
- genFolder = getGeneratedSourceFolder();
- _snapshotFolderName = _generatedSourceFolderName;
+ genFolder = _gsfm.getFolder();
+ _snapshotFolderName = _gsfm.getFolderName();
}
try {
_generatedPackageFragmentRoot = null;
- IPackageFragmentRoot[] roots = _aptProject.getJavaProject().getAllPackageFragmentRoots();
+ IPackageFragmentRoot[] roots = _jProject.getAllPackageFragmentRoots();
for (IPackageFragmentRoot root : roots) {
final IResource resource = root.getResource();
if( resource != null && resource.equals(genFolder)){
@@ -909,179 +801,6 @@
}
- /**
- * Creates the generated source folder if it doesn't exist.
- * No changes to the classpath will be made.
- */
- public void createGeneratedSourceFolder(){
- IFolder srcFolder = getGeneratedSourceFolder();
- // This most likely means the preference change event hasn't occured yet
- // and we don't know about the name of the generated source directory.
- if( srcFolder == null )
- return;
- try{
- srcFolder.refreshLocal( IResource.DEPTH_INFINITE, null );
- if (!srcFolder.exists()) {
- if( AptPlugin.DEBUG )
- AptPlugin.trace("creating " + srcFolder.getProjectRelativePath()); //$NON-NLS-1$
-
- FileSystemUtil.makeDerivedParentFolders(srcFolder);
- }
- }
- catch(CoreException ce){
- AptPlugin.log(ce, "Failure during refreshLocal on " + srcFolder.getProjectRelativePath()); //$NON-NLS-1$
- }
- synchronized (this) {
- _generatedSourceFolder = srcFolder;
- }
- }
-
- /**
- * Creates the generated source folder if it doesn't exist, and adds it as a source path
- * to the project. To access the generated source folder, but not have it be created
- * or added as a source path, use getGeneratedSourceFolder(). Note that this method
- * will take a resource lock if the generated source folder needs to be created on disk,
- * and it will take a java model lock if the project's source paths need to be updated.
- * Care should be taken when calling this method to ensure that locking behavior is correct.
- *
- * <em>
- * The only time that it is save to call this method is either we are explicitly fixing the
- * classpath during a <code>ICompilationParitcipant.BROKEN_CLASSPATH_BUILD_FAILURE_EVENT</code>
- * or during a resource change event. Since resource change event only occur before or after a build
- * but never during one, the classpath will be updated at the correct time.
- * </em>
- *
- *
- * @param progressMonitor the progress monitor. This can be null.
- * @return <code>true</code> iff the any resource or classpath has been modified.
- * return <code>false</code> otherwise.
- *
- * @see #getGeneratedSourceFolder()
- * @see #isGeneratedSourceFolderConfigured()
- */
- private boolean ensureGeneratedSourceFolder(){
-
- boolean reset = false;
- IFolder curSrcFolder = null;
-
- synchronized( this )
- {
- if( _generatedSourceFolder != null ){
- final IPath srcFolderPath = _generatedSourceFolder.getProjectRelativePath();
-
- if( !_generatedSourceFolderName.equals( srcFolderPath.toString()) ){
- reset = true;
- curSrcFolder = _generatedSourceFolder;
- _generatedSourceFolder = null;
- }
- else {
- try{
- _generatedSourceFolder.refreshLocal( IResource.DEPTH_INFINITE, null );
- }
- catch(CoreException ce){
- AptPlugin.log(ce, "Failure during refreshLocal on " + srcFolderPath); //$NON-NLS-1$
-
- }
-
- // if the folder doesn't exists, there is no point examining the classpath
- boolean isConsistent = false;
- if (_generatedSourceFolder.exists()) {
- try {
- IJavaProject jp = _aptProject.getJavaProject();
- IClasspathEntry[] cp = jp.getRawClasspath();
- IPath path = _generatedSourceFolder.getFullPath();
- isConsistent = isProjectClassPathUpToDate(jp, cp, path, null);
- }
- catch (JavaModelException jme) {
- AptPlugin.log(jme, "Failure examining the classpath"); //$NON-NLS-1$
- }
- }
-
- if(isConsistent)
- return false;
- }
- }
-
- }
- IFolder srcFolder = null;
- try{
- if( reset ){
- // the generated source folder and the generated source folder name is not
- // lining up.
- removeFromProjectClasspath(_aptProject.getJavaProject(), curSrcFolder, null );
- if ( curSrcFolder.exists() ){
- if( AptPlugin.DEBUG )
- AptPlugin.trace("deleting gen src dir " + curSrcFolder.getName() ); //$NON-NLS-1$
- curSrcFolder.delete( true, false, null );
- }
- }
-
- // don't take any locks while creating the folder, since we are doing file-system operations
- srcFolder = getGeneratedSourceFolder();
- srcFolder.refreshLocal( IResource.DEPTH_INFINITE, null );
- if (!srcFolder.exists()) {
- FileSystemUtil.makeDerivedParentFolders(srcFolder);
- }
-
- //
- // make sure __generated_src dir is on the cp if not already
- //
- updateProjectClasspath( _aptProject.getJavaProject(), srcFolder, null );
-
- if(AptPlugin.DEBUG)
- AptPlugin.trace("Added directory " + srcFolder.getName() + " and updated classpath" ); //$NON-NLS-1$ //$NON-NLS-2$
- }
- catch(CoreException e){
- e.printStackTrace();
- AptPlugin.log(e, "Failed to create generated source directory"); //$NON-NLS-1$
- return false;
- }
-
- synchronized ( this )
- {
- _generatedSourceFolder = srcFolder;
- return true;
- }
- }
-
-
- /**
- * This method will return the binary output location for the generated source folder.
- * If the generated-source folder is not configured (i.e., not created or not added to
- * the project's source path, then this method will return the default binary output
- * location for the project.
- *
- * @return the IPath corresponding to the binary output location for the
- * generated source folder. This is relative to the project.
- *
- * @throws JavaModelException
- *
- * @see #getGeneratedSourceFolder()
- * @see #isGeneratedSourceFolderConfigured()
- */
- public IPath getGeneratedSourceFolderOutputLocation()
- throws JavaModelException
- {
- IPath outputRootPath = null;
- IFolder generatedSourceFolder = getGeneratedSourceFolder();
- if ( generatedSourceFolder != null && generatedSourceFolder.exists() )
- {
- IClasspathEntry cpe = findProjectSourcePath( _aptProject.getJavaProject(), generatedSourceFolder );
- if ( cpe != null )
- outputRootPath = cpe.getOutputLocation();
- }
-
- // no output root, so get project's default output location
- if ( outputRootPath == null )
- outputRootPath = _aptProject.getJavaProject().getOutputLocation();
-
- // output location is relative to the workspace, we want to make it relative to project
- int segments = outputRootPath.matchingFirstSegments( _aptProject.getJavaProject().getPath() );
- outputRootPath = outputRootPath.removeFirstSegments( segments );
-
- return outputRootPath;
- }
-
//
// check cache to see if we already have a working copy
//
@@ -1106,7 +825,7 @@
IProblemRequestor problemRequestor, IProgressMonitor progressMonitor)
throws JavaModelException
{
- IFolder folder = getGeneratedSourceFolder();
+ IFolder folder = _gsfm.getFolder();
//
// figure out package part of type & file name
@@ -1129,7 +848,7 @@
//
// create compilation unit
//
- IPackageFragmentRoot root = _aptProject.getJavaProject().getPackageFragmentRoot(folder);
+ IPackageFragmentRoot root = _jProject.getPackageFragmentRoot(folder);
IPackageFragment pkgFragment = root.getPackageFragment(pkgName );
ICompilationUnit cu = pkgFragment.getCompilationUnit( fname );
@@ -1215,7 +934,7 @@
}
}
- private void addEntryToFileMaps( IFile parentFile, IFile generatedFile )
+ public void addEntryToFileMaps( IFile parentFile, IFile generatedFile )
{
synchronized ( this )
{
@@ -1309,7 +1028,7 @@
workingCopy.discardWorkingCopy();
}
- private void clearWorkingCopyMaps()
+ public void clearWorkingCopyMaps()
{
// first discard all working copies
@@ -1339,7 +1058,7 @@
}
}
- private void clearAllMaps()
+ public void clearAllMaps()
{
clearWorkingCopyMaps();
@@ -1352,224 +1071,6 @@
}
/**
- * Given a java project, this function will determine if the specified
- * folder is a source folder of the java project.
- *
- * @param jp - the java project
- * @param folder - the folder that you want to see if it is a classpath entry for the java project
- * @return
- * @throws JavaModelException
- */
- public static IClasspathEntry findProjectSourcePath( IJavaProject jp, IFolder folder )
- throws JavaModelException
- {
- IClasspathEntry[] cp = jp.getRawClasspath();
- IClasspathEntry searchingFor =
- JavaCore.newSourceEntry(folder.getFullPath());
- IPath searchingForPath = searchingFor.getPath();
- for (int i = 0; i < cp.length; i++)
- {
- if (cp[i].getPath().equals( searchingForPath ))
- return cp[i];
- }
- return null;
- }
-
- private static boolean isProjectClassPathUpToDate(
- IJavaProject jp,
- IClasspathEntry[] cp,
- IPath path,
- IProgressMonitor progressMonitor)
- throws JavaModelException
- {
- if( cp == null )
- cp = jp.getRawClasspath();
- for (int i = 0; i < cp.length; i++)
- {
- if (cp[i].getPath().equals( path ))
- {
- return true;
- }
- }
- return false;
- }
-
- /**
- * returns true if we updated the classpath, false otherwise
- */
- private static boolean updateProjectClasspath( IJavaProject jp, IFolder folder, IProgressMonitor progressMonitor )
- throws JavaModelException
- {
- IClasspathEntry[] cp = jp.getRawClasspath();
- IPath path = folder.getFullPath();
- boolean found = isProjectClassPathUpToDate(jp, cp, path, progressMonitor);
-
- if (!found)
- {
- // update exclusion patterns
- ArrayList<IPath> exclusions = new ArrayList<IPath>();
- for ( int i = 0; i< cp.length; i++ )
- {
- if ( cp[i].getPath().isPrefixOf( path ) )
- {
- // exclusion patterns must be project-relative paths, and must end with a "/"
- IPath projectRelativePath = folder.getProjectRelativePath().addTrailingSeparator();
-
- // path is contained in an existing source path, so update existing paths's exclusion patterns
- IPath[] oldExclusions = cp[i].getExclusionPatterns();
-
- // don't add if exclusion pattern already contains src dir
- boolean add = true;
- for ( int j = 0; j < oldExclusions.length; j++ )
- if ( oldExclusions[j].equals( projectRelativePath ) )
- add = false;
-
- if ( add )
- {
- IPath[] newExclusions;
- if ( cp[i].getExclusionPatterns() == null )
- newExclusions = new IPath[1];
- else
- {
- newExclusions = new IPath[ oldExclusions.length + 1 ];
- System.arraycopy( oldExclusions, 0, newExclusions, 0, oldExclusions.length );
- }
- newExclusions[ newExclusions.length - 1 ] = projectRelativePath;
- cp[i] = JavaCore.newSourceEntry(cp[i].getPath(), cp[i].getInclusionPatterns(), newExclusions, cp[i].getOutputLocation(), cp[i].getExtraAttributes());
- }
-
- }
- else if ( path.isPrefixOf( cp[i].getPath() ))
- {
- // new source path contains an existing source path, so add an exclusion pattern for it
- exclusions.add( cp[i].getPath().addTrailingSeparator() );
- }
- }
-
- IPath[] exclusionPatterns = exclusions.toArray( new IPath[exclusions.size()] );
- IClasspathEntry generatedSourceClasspathEntry =
- JavaCore.newSourceEntry(folder.getFullPath(), exclusionPatterns );
-
- IClasspathEntry[] newCp = new IClasspathEntry[cp.length + 1];
- System.arraycopy(cp, 0, newCp, 0, cp.length);
- newCp[newCp.length - 1] = generatedSourceClasspathEntry;
-
- jp.setRawClasspath(newCp, progressMonitor );
- }
-
- // return true if we updated the project's classpath entries
- return !found;
- }
-
- /**
- * removes a classpath entry from the project
- */
- public static void removeFromProjectClasspath( IJavaProject jp, IFolder folder, IProgressMonitor progressMonitor )
- throws JavaModelException
- {
- IClasspathEntry[] cp = jp.getRawClasspath();
- IPath workspaceRelativePath = folder.getFullPath();
- boolean found = isProjectClassPathUpToDate(jp, cp, workspaceRelativePath, progressMonitor);
-
- if( found ){
- IPath projectRelativePath = folder.getProjectRelativePath().addTrailingSeparator();
-
- // remove entries that are for the specified folder, account for
- // multiple entries, and clean up any exclusion entries to the
- // folder being removed.
- int j = 0;
- for ( int i=0; i<cp.length; i++ )
- {
- if (! cp[i].getPath().equals( workspaceRelativePath ) )
- {
-
- // see if we added the generated source dir as an exclusion pattern to some other entry
- IPath[] oldExclusions = cp[i].getExclusionPatterns();
- int m = 0;
- for ( int k = 0; k < oldExclusions.length; k++ )
- {
- if ( !oldExclusions[k].equals( projectRelativePath ) )
- {
- oldExclusions[m] = oldExclusions[k];
- m++;
- }
- }
-
- if ( oldExclusions.length == m )
- {
- // no exclusions changed, so we do't need to create a new entry
- cp[j] = cp[i];
- }
- else
- {
- // we've removed some exclusion, so create a new entry
- IPath[] newExclusions = new IPath[ m ];
- System.arraycopy( oldExclusions, 0, newExclusions, 0, m );
- cp[j] = JavaCore.newSourceEntry( cp[i].getPath(), cp[i].getInclusionPatterns(), newExclusions, cp[i].getOutputLocation(), cp[i].getExtraAttributes() );
- }
-
- j++;
- }
- }
-
- // now copy updated classpath entries into new array
- IClasspathEntry[] newCp = new IClasspathEntry[ j ];
- System.arraycopy( cp, 0, newCp, 0, j);
- jp.setRawClasspath( newCp, progressMonitor );
-
- if( AptPlugin.DEBUG ){
- AptPlugin.trace("removed " + workspaceRelativePath + " from classpath"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- }
-
- /**
- * invoked when a project is closed. This will discard any open working-copies
- * of generated files.
- */
- public void projectClosed()
- {
- clearWorkingCopyMaps();
- }
-
- /**
- * invoked whenever a project is cleaned. This will remove any state kept about
- * generated files for the given project. If the deleteFiles flag is specified,
- * then the contents of the generated source folder will be deleted.
- *
- * @param deleteFiles true if the contents of the generated source folder are to be
- * deleted, false otherwise.
- */
-
- public void projectClean( boolean deleteFiles )
- {
- clearAllMaps();
-
- // delete the generated source dir
- if ( deleteFiles )
- {
- IFolder f = getGeneratedSourceFolder();
- if ( f != null && f.exists() )
- {
- // delete the contents of the generated source folder, but don't delete
- // the generated source folder because that will cause a classpath change,
- // which will force the next build to be a full build.
- try
- {
- IResource[] members = f.members();
- for ( int i = 0; i<members.length; i++ ){
- deleteDerivedResources(members[i]);
- }
- }
- catch ( CoreException ce )
- {
- AptPlugin.log(ce, "Could not delete generated files"); //$NON-NLS-1$
- }
- }
- }
- }
-
- /**
* If the given resource is a folder, then recursively deleted all derived
* files and folders contained within it. Delete the folder if it becomes empty
* and if itself is also a derived resource.
@@ -1579,7 +1080,7 @@
* @return <code>true</code> iff the resource has been deleted.
* @throws CoreException
*/
- private boolean deleteDerivedResources(final IResource resource)
+ public boolean deleteDerivedResources(final IResource resource)
throws CoreException
{
if( resource.getType() == IResource.FOLDER ){
@@ -1607,37 +1108,6 @@
}
/**
- * Inovked when a project has been deleted. This will remove this generated file manager
- * from the static map of projects->generated file managers, and this will flush any known
- * in-memory state tracking generated files. This will not delete any of the project's generated files
- * from disk.
- */
- public void projectDeleted()
- {
- projectClean( false );
- }
-
- /**
- * Invoked when the generated source folder has been deleted. This will
- * flush any in-memory state tracking generated files and clean up the project classpath.
- *
- * Note: this should only be called within a resource change event to ensure that the classpath
- * is correct during any build. Resource change event never occurs during a build.
- */
- public void generatedSourceFolderDeleted()
- {
- projectClean( false );
-
- IFolder srcFolder;
- synchronized(this){
- srcFolder = getGeneratedSourceFolder();
- _generatedSourceFolder = null;
- }
- if(AptPlugin.DEBUG)
- AptPlugin.trace("nulled out gen src dir " + srcFolder.getName() ); //$NON-NLS-1$
- }
-
- /**
* This method should only be used for testing purposes to ensure
* that maps contain entries when we expect them to.
*/
@@ -1670,150 +1140,4 @@
return false;
}
- /**
- * @return get the generated source folder. May return null if
- * creation has failed, the folder has been deleted or has not been created.
- */
- public IFolder getGeneratedSourceFolder(){
-
- final String folderName;
- synchronized (this) {
- if( _generatedSourceFolder != null )
- return _generatedSourceFolder;
- folderName = getGeneratedSourceFolderName();
- }
- if(folderName == null)
- return null;
-
- return _aptProject.getJavaProject().getProject().getFolder( folderName );
- }
-
- /**
- * returns the name of the folder for generated source files. The name is relative
- * to the project root.
- *
- * @see #getGeneratedSourceFolder()
- * @see #isGeneratedSourceFolderConfigured()
- */
- public synchronized String getGeneratedSourceFolderName()
- {
- return _generatedSourceFolderName;
- }
-
- public boolean isGeneratedSourceFolderConfigured(){
- return _generatedSourceFolder != null;
- }
-
- public void configureGeneratedSourceFolder(){
- final String folderName = _generatedSourceFolderName;
- if( AptPlugin.DEBUG ){
- AptPlugin.trace("configure genenerated source folder to be " + folderName ); //$NON-NLS-1$
- }
- configureGeneratedSourceFolder(folderName, null);
- }
-
- /**
- * Simply set the name of the generated source folder.
- * <em>This should only be called when APT is disabled.</em>
- * @param newName
- */
- private void setGeneratedSourceFolderName(String newName){
- assert !AptConfig.isEnabled(_aptProject.getJavaProject()) :
- "APT is enabled for " + _aptProject.getJavaProject().getElementName(); //$NON-NLS-1$
- if( newName == null || newName.length() == 0 )
- throw new IllegalStateException("[" + newName + "] not a valid name for generated source folder "); //$NON-NLS-1$//$NON-NLS-2$
- synchronized (this) {
- _generatedSourceFolderName = newName;
- }
- }
-
- /**
- * Sets the name of the generated soruce folder. The source folder will not be created
- * and will not be added to the project's source paths (i.e., after a call to
- * setGeneratedSourceFolderName, isGeneratedSourceFolderConfigured() will return false.)
- * To properly have the new generated source folder configured, call #ensureGeneratedSourceFolder().
- *
- * @param newValue The string name of the new generated source folder. This should be relative
- * to the project root. Absolute paths are not supported. The specified string should be
- * a valid folder name for the file system, and should not be an existing source folder for the
- * project.
- *
- * @see #getGeneratedSourceFolder()
- * @see #getGeneratedSourceFolderName()
- * @see #isGeneratedSourceFolderConfigured()
- */
- private void configureGeneratedSourceFolder( String newValue, String oldValue )
- {
-
- // bail if they specify null, empty-string or don't change the name of the source folder
- if ( newValue == null ||
- newValue.length() == 0 ||
- newValue.equals(oldValue) )
- return;
-
- projectClean( true );
-
- IFolder srcFolder = null;
- synchronized ( this )
- {
- // We are not going to delete any directories or change the classpath
- // since this could happen during a build.
- // see ensureGeneratedSourceFolder()
- _generatedSourceFolderName = newValue;
- srcFolder = _generatedSourceFolder;
- }
-
- // if the preference change occur before we actually
- // initialized the _generatedSourceFolder.
- // This may happen when the pre-processor resource change event occurs after
- // the preference change event.
- if( oldValue != null && srcFolder == null ){
- srcFolder = _aptProject.getJavaProject().getProject().getFolder( oldValue );
- }
-
- resetGeneratedSrcFolder(srcFolder, true);
- }
-
- /**
- * Cleanup the classpath and schedule a job to delete the generated source folder.
- * @param recreate if <code>true</code> configure the generated source directory.
- */
- private void resetGeneratedSrcFolder(final IFolder srcFolder, boolean recreate){
- // clean up the classpath first so that when we actually delete the
- // generated source folder and won't cause a classpath error.
- if( srcFolder != null ){
- try{
- removeFromProjectClasspath( _aptProject.getJavaProject(), srcFolder, null );
- }catch(JavaModelException e){
- AptPlugin.log( e, "Error occurred deleting old generated src folder " + srcFolder.getName() ); //$NON-NLS-1$
- }
- }
-
- if( recreate )
- ensureGeneratedSourceFolder();
-
- if( srcFolder != null ){
- // schedule the deletion job.
- final IWorkspaceRunnable runnable = new IWorkspaceRunnable(){
- public void run(IProgressMonitor monitor)
- {
- if( srcFolder != null ){
- try{
- srcFolder.delete(true, false, null);
- }catch(CoreException e){
- AptPlugin.log(e, "failed to delete old generated source folder " + srcFolder.getName() ); //$NON-NLS-1$
- }catch(OperationCanceledException cancel){
- AptPlugin.log(cancel, "deletion of generated source folder got cancelled"); //$NON-NLS-1$
- }
- }
- };
- };
- IWorkspace ws = _aptProject.getJavaProject().getProject().getWorkspace();
- try{
- ws.run(runnable, ws.getRoot(), IWorkspace.AVOID_UPDATE, null);
- }catch(CoreException e){
- AptPlugin.log(e, "Runnable for deleting old generated source folder " + srcFolder.getName() + " failed."); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- }
}
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java
index 94dd54e..9f3be3b 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/generatedfile/GeneratedResourceChangeListener.java
@@ -25,6 +25,7 @@
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.apt.core.AptPlugin;
+import org.eclipse.jdt.apt.core.internal.AptProject;
import org.eclipse.jdt.apt.core.util.AptConfig;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
@@ -58,8 +59,7 @@
{
IProject p = (IProject)event.getResource();
IJavaProject jp = JavaCore.create(p);
- GeneratedFileManager gfm = AptPlugin.getAptProject(jp).getGeneratedFileManager();
- gfm.projectClosed();
+ AptPlugin.getAptProject(jp).projectClosed();
}
else if ( event.getType() == IResourceChangeEvent.PRE_DELETE )
{
@@ -67,8 +67,7 @@
// in an async thread. The resource tree is locked here.
IProject p = (IProject)event.getResource();
IJavaProject jp = JavaCore.create(p);
- GeneratedFileManager gfm = AptPlugin.getAptProject(jp).getGeneratedFileManager();
- gfm.projectDeleted();
+ AptPlugin.getAptProject(jp).projectDeleted();
AptPlugin.deleteAptProject(jp);
}
}
@@ -78,8 +77,8 @@
for(IProject proj : projs ){
final IJavaProject javaProj = JavaCore.create(proj);
if(AptConfig.isEnabled(javaProj)){
- final GeneratedFileManager gfm = AptPlugin.getAptProject(javaProj).getGeneratedFileManager();
- gfm.createGeneratedSourceFolder();
+ final GeneratedSourceFolderManager gsfm = AptPlugin.getAptProject(javaProj).getGeneratedSourceFolderManager();
+ gsfm.createGeneratedSourceFolder();
}
}
@@ -101,8 +100,9 @@
if( delta.getKind() == IResourceDelta.REMOVED ){
final IJavaProject javaProj = JavaCore.create(project);
- final GeneratedFileManager gfm = AptPlugin.getAptProject(javaProj).getGeneratedFileManager();
+ final AptProject aptProj = AptPlugin.getAptProject(javaProj);
if( r instanceof IFile ){
+ final GeneratedFileManager gfm = aptProj.getGeneratedFileManager();
IFile f = (IFile)r;
if ( gfm.isParentFile( f ) )
{
@@ -114,9 +114,10 @@
}
}
else if( r instanceof IFolder ){
+ final GeneratedSourceFolderManager gsfm = aptProj.getGeneratedSourceFolderManager();
IFolder f = (IFolder) r;
- if ( gfm.isGeneratedSourceFolder( f ) ){
- gfm.generatedSourceFolderDeleted();
+ if ( gsfm.isGeneratedSourceFolder( f ) ){
+ gsfm.generatedSourceFolderDeleted();
// all deletion occurs before any add (adding the generated source directory)
if( !_removedProjects.contains(project) ){
_addGenFolderTo.add(project);
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java
index 43d8c66..2cb0c0e 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FileSystemUtil.java
@@ -52,11 +52,23 @@
}
public static void makeDerivedParentFolders (IContainer container) throws CoreException {
- if ((container instanceof IFolder) && !container.exists()) {
- makeDerivedParentFolders(container.getParent());
- ((IFolder) container).create(true, true, null);
- container.setDerived(true);
- }
+ // synchronize the "does it exist - if not, create it" sequence.
+ synchronized(container.getProject()) {
+ if ((container instanceof IFolder) && !container.exists()) {
+ makeDerivedParentFolders(container.getParent());
+ try {
+ ((IFolder)container).create(true, true, null);
+ }
+ catch (CoreException e) {
+ // Ignore race condition where another thread created the folder at the
+ // same time, causing checkDoesNotExist() to throw within create().
+ if (!container.exists()) {
+ throw e;
+ }
+ }
+ container.setDerived(true);
+ }
+ }
}
/**
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java
index bfa47f4..5018385 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java
@@ -30,7 +30,6 @@
import org.eclipse.jdt.apt.core.AptPlugin;
import org.eclipse.jdt.apt.core.internal.AnnotationProcessorFactoryLoader;
import org.eclipse.jdt.apt.core.internal.AptProject;
-import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedFileManager;
import org.eclipse.jdt.apt.core.internal.util.FactoryPath;
import org.eclipse.jdt.apt.core.internal.util.FactoryPathUtil;
import org.eclipse.jdt.core.IClasspathEntry;
@@ -640,11 +639,12 @@
IScopeContext context = (null != jproject) ?
new ProjectScope(jproject.getProject()) : new InstanceScope();
IEclipsePreferences node = context.getNode(AptPlugin.PLUGIN_ID);
+ // get old val as a String, so it can be null if setting doesn't exist yet
+ String oldValue = node.get(optionName, null);
node.putBoolean(optionName, value);
if (jproject != null) {
AptProject aproj = AptPlugin.getAptProject(jproject);
- GeneratedFileManager gfm = aproj.getGeneratedFileManager();
- gfm.handlePreferenceChange(optionName, null, Boolean.toString(value));
+ aproj.handlePreferenceChange(optionName, oldValue, Boolean.toString(value));
}
flushPreference(optionName, node);
}
@@ -657,8 +657,7 @@
node.put(optionName, value);
if (jproject != null) {
AptProject aproj = AptPlugin.getAptProject(jproject);
- GeneratedFileManager gfm = aproj.getGeneratedFileManager();
- gfm.handlePreferenceChange(optionName, oldValue, value);
+ aproj.handlePreferenceChange(optionName, oldValue, value);
}
flushPreference(optionName, node);
}
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/APTTestBase.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/APTTestBase.java
index c014c71..735e06a 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/APTTestBase.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/APTTestBase.java
@@ -47,6 +47,7 @@
*/
public void setUp() throws Exception
{
+ runFinalizers();
ProcessorTestStatus.reset();
super.setUp();
@@ -89,9 +90,18 @@
throws Exception
{
AptPlugin.trace("Tearing down " + getProjectName() );
+ runFinalizers();
super.tearDown();
}
+ private static void runFinalizers() {
+ // GC in an attempt to release file lock on Classes.jar
+ System.gc();
+ System.runFinalization();
+ System.gc();
+ System.runFinalization();
+ }
+
public String getProjectName()
{
return this.getClass().getName() + "Project"; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java
index 543dcdc..4f177de 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/AptBuilderTests.java
@@ -20,7 +20,7 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.apt.core.AptPlugin;
-import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedFileManager;
+import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedSourceFolderManager;
import org.eclipse.jdt.apt.core.util.AptConfig;
import org.eclipse.jdt.apt.core.util.AptPreferenceConstants;
import org.eclipse.jdt.core.IClasspathEntry;
@@ -592,8 +592,8 @@
expectingNoProblems();
expectingNoMarkers();
- GeneratedFileManager mgr = AptPlugin.getAptProject(javaProj).getGeneratedFileManager();
- IFolder srcFolder = mgr.getGeneratedSourceFolder();
+ GeneratedSourceFolderManager mgr = AptPlugin.getAptProject(javaProj).getGeneratedSourceFolderManager();
+ IFolder srcFolder = mgr.getFolder();
assertEquals(true, srcFolder.exists());
// delete the gen source folder
srcFolder.delete(true, false, null);
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/PreferencesTests.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/PreferencesTests.java
index 5a480fc..d8627ce 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/PreferencesTests.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/PreferencesTests.java
@@ -23,7 +23,7 @@
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.apt.core.AptPlugin;
-import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedFileManager;
+import org.eclipse.jdt.apt.core.internal.generatedfile.GeneratedSourceFolderManager;
import org.eclipse.jdt.apt.core.internal.util.FactoryContainer;
import org.eclipse.jdt.apt.core.internal.util.FactoryPath;
import org.eclipse.jdt.apt.core.internal.util.FactoryPathUtil;
@@ -242,8 +242,8 @@
boolean aptEnabled = AptConfig.isEnabled(javaProj);
// test 1: make sure apt is disabled by default
assertEquals(false, aptEnabled);
- final GeneratedFileManager gfm = AptPlugin.getAptProject(javaProj).getGeneratedFileManager();
- IFolder srcFolder = gfm.getGeneratedSourceFolder();
+ final GeneratedSourceFolderManager gsfm = AptPlugin.getAptProject(javaProj).getGeneratedSourceFolderManager();
+ IFolder srcFolder = gsfm.getFolder();
String folderName = srcFolder.getProjectRelativePath().toOSString();
// test 2: apt is disabled, then folder should not exists
assertEquals(srcFolder.exists(), false);
@@ -254,7 +254,7 @@
// set folder name while apt is disabled
String newName = ".gensrcdir";
AptConfig.setGenSrcDir(javaProj, newName);
- srcFolder = gfm.getGeneratedSourceFolder();
+ srcFolder = gsfm.getFolder();
folderName = srcFolder.getProjectRelativePath().toOSString();
// test 4: apt still disabled but folder name changed, make sure the folder is not on disk.
assertEquals(false, srcFolder.exists());
@@ -268,7 +268,7 @@
aptEnabled = AptConfig.isEnabled(javaProj);
// test 7: make sure it's enabled after we called the API to enable it.
assertEquals(true, aptEnabled);
- srcFolder = gfm.getGeneratedSourceFolder();
+ srcFolder = gsfm.getFolder();
folderName = srcFolder.getProjectRelativePath().toOSString();
// test 8: apt enabled, the source folder should be on disk
assertEquals(true, srcFolder.exists());
@@ -282,7 +282,7 @@
aptEnabled = AptConfig.isEnabled(javaProj);
// test 11: make sure it's disabled.
assertEquals(false, aptEnabled);
- srcFolder = gfm.getGeneratedSourceFolder();
+ srcFolder = gsfm.getFolder();
folderName = srcFolder.getProjectRelativePath().toOSString();
// test 12: make sure we deleted the source folder when we disable apt
assertEquals(false, srcFolder.exists());
diff --git a/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java b/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java
index c88cc6b..3e0206c 100644
--- a/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java
+++ b/org.eclipse.jdt.apt.ui/src/org/eclipse/jdt/apt/ui/internal/preferences/AptConfigurationBlock.java
@@ -326,9 +326,9 @@
elements = getListElements();
}
saveProcessorOptions(elements);
- fAptProject.getGeneratedFileManager().handlePreferenceChange(
+ fAptProject.handlePreferenceChange(
AptPreferenceConstants.APT_GENSRCDIR, fOriginalGenSrcDir, fGenSrcDirField.getText());
- fAptProject.getGeneratedFileManager().handlePreferenceChange(
+ fAptProject.handlePreferenceChange(
AptPreferenceConstants.APT_ENABLED,
Boolean.toString(fOriginalAptEnabled),
Boolean.toString(fAptEnabledField.isSelected()));