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()));