new buildconfig plugin
diff --git a/org.eclipse.ajdt.ui.buildconfig/.classpath b/org.eclipse.ajdt.ui.buildconfig/.classpath
new file mode 100644
index 0000000..9bc605c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="var" path="ASPECTJRT_LIB"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.ajdt.ui.buildconfig/.cvsignore b/org.eclipse.ajdt.ui.buildconfig/.cvsignore
new file mode 100755
index 0000000..67b544a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/.cvsignore
@@ -0,0 +1,3 @@
+bin
+build
+dist
diff --git a/org.eclipse.ajdt.ui.buildconfig/.project b/org.eclipse.ajdt.ui.buildconfig/.project
new file mode 100644
index 0000000..4556b18
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.ajdt.ui.buildconfig</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.ajdt.core.ajbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.ajdt.ui.ajnature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.ajdt.ui.buildconfig/META-INF/MANIFEST.MF b/org.eclipse.ajdt.ui.buildconfig/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..81444b3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/META-INF/MANIFEST.MF
@@ -0,0 +1,39 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.ajdt.ui.buildconfig; singleton:=true
+Bundle-Version: 1.3.0.DEVELOPMENT
+Bundle-Localization: plugin
+Bundle-Vendor: %providerName
+Bundle-Activator: org.eclipse.ajdt.ui.buildconfig.BuildConfigPlugin
+Export-Package: org.eclipse.ajdt.internal.buildconfig;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.actions;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.editor;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.editor.model;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.menu;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.propertypage;x-internal:=true,
+ org.eclipse.ajdt.internal.buildconfig.wizards;x-internal:=true,
+ org.eclipse.ajdt.pde.internal.ui.editor;x-internal:=true,
+ org.eclipse.ajdt.pde.internal.ui.editor.context;x-internal:=true,
+ org.eclipse.ajdt.ui.buildconfig
+Require-Bundle: org.aspectj.ajde,
+ org.eclipse.ajdt.core,
+ org.eclipse.core.resources,
+ org.eclipse.core.runtime,
+ org.eclipse.ajdt.ui,
+ org.eclipse.jface,
+ org.eclipse.ui,
+ org.eclipse.jdt.core,
+ org.eclipse.jdt.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.contribution.xref.ui,
+ org.eclipse.pde.core,
+ org.eclipse.ui.forms,
+ org.eclipse.jface.text,
+ org.eclipse.pde.ui,
+ org.eclipse.ui.workbench.texteditor,
+ org.eclipse.ui.editors,
+ org.eclipse.search,
+ org.eclipse.ui.views
+Eclipse-AutoStart: true
+Eclipse-RegisterBuddy: org.eclipse.ajdt.ui
diff --git a/org.eclipse.ajdt.ui.buildconfig/about.html b/org.eclipse.ajdt.ui.buildconfig/about.html
new file mode 100755
index 0000000..1b5fac9
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/about.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>1st March, 2003</p>	
+<h3>License</h3>
+<p>Eclipse.org makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Common Public License Version 1.0 (&quot;CPL&quot;).  A copy of the CPL is available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>.
+For purposes of the CPL, &quot;Program&quot; will mean the Content.</p>
+
+<h3>Contributions</h3>
+
+<p>If this Content is licensed to you under the terms and conditions of the CPL, any Contributions, as defined in the CPL, uploaded, submitted, or otherwise
+made available to Eclipse.org, members of Eclipse.org and/or the host of Eclipse.org web site, by you that relate to such
+Content are provided under the terms and conditions of the CPL and can be made available to others under the terms of the CPL.</p>
+
+<p>If this Content is licensed to you under license terms and conditions other than the CPL (&quot;Other License&quot;), any modifications, enhancements and/or
+other code and/or documentation (&quot;Modifications&quot;) uploaded, submitted, or otherwise made available to Eclipse.org, members of Eclipse.org and/or the
+host of Eclipse.org, by you that relate to such Content are provided under terms and conditions of the Other License and can be made available
+to others under the terms of the Other License.  In addition, with regard to Modifications for which you are the copyright holder, you are also
+providing the Modifications under the terms and conditions of the CPL and such Modifications can be made available to others under the terms of
+the CPL.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/build.ajproperties b/org.eclipse.ajdt.ui.buildconfig/build.ajproperties
new file mode 100644
index 0000000..7db383d
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/build.ajproperties
@@ -0,0 +1,2 @@
+src.includes = src/
+src.excludes = src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java
diff --git a/org.eclipse.ajdt.ui.buildconfig/build.properties b/org.eclipse.ajdt.ui.buildconfig/build.properties
new file mode 100644
index 0000000..9bb04e1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+bin.includes = META-INF/,\
+               .
+src.includes = src/
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/buildconfig_file.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/buildconfig_file.gif
new file mode 100755
index 0000000..1de898e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/buildconfig_file.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/exclusion_filter_attrib.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/exclusion_filter_attrib.gif
new file mode 100644
index 0000000..92bce14
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/exclusion_filter_attrib.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/inclusion_filter_attrib.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/inclusion_filter_attrib.gif
new file mode 100644
index 0000000..ca17a44
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/inclusion_filter_attrib.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/new_build_config_wizard.gif b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/new_build_config_wizard.gif
new file mode 100755
index 0000000..aeb0236
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/icons/buildconfig/new_build_config_wizard.gif
Binary files differ
diff --git a/org.eclipse.ajdt.ui.buildconfig/plugin.properties b/org.eclipse.ajdt.ui.buildconfig/plugin.properties
new file mode 100644
index 0000000..7133595
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/plugin.properties
@@ -0,0 +1,28 @@
+######################################################################
+#Copyright (c) 2005 IBM Corporation and others.
+#All rights reserved. This program and the accompanying materials
+#are made available under the terms of the Common Public License v1.0
+#which accompanies this distribution, and is available at
+#http://www.eclipse.org/legal/cpl-v10.html
+#Contributors:
+#Matt Chapman - initial version to separate out build configuration
+#               support from the UI plugin
+#...
+######################################################################
+pluginName=AspectJ Development Tools Build Config support
+providerName=Eclipse.org
+
+# Build configuration
+# -------------------
+activateConfig=&Activate Build Configuration
+saveAsAJProperties=&Save as .ajproperties File
+saveAsLst=&Save as .lst File
+BuildConfigDecorator.label=AspectJ Build Configuration and Advice Indicator
+BuildConfigDecorator.description=Decorates packages and source files to indicate whether or not they are included in the active build configuration, and decorates the active configuration file.
+excludeFromBuildConfig=&Exclude from active build configuration
+includeInActiveBuildConfig=&Include in active build configuration
+
+buildConfigFile=Build Configuration
+buildConfigDescription=Create a new AspectJ build configuration
+
+org.eclipse.ajdt.ui.tools=Aspect&J Tools
diff --git a/org.eclipse.ajdt.ui.buildconfig/plugin.xml b/org.eclipse.ajdt.ui.buildconfig/plugin.xml
new file mode 100644
index 0000000..df46922
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/plugin.xml
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+
+<plugin>
+
+    <extension
+         point="org.eclipse.ui.popupMenus">
+      <objectContribution
+            objectClass="org.eclipse.jdt.core.IJavaElement"
+            id="Build Configurator Plugin.objectContribution2">
+         <menu
+               label="%org.eclipse.ajdt.ui.tools"
+               id="org.eclipse.ajdt.ui.feature.tools">
+            <separator
+                  name="group0">
+            </separator>
+            <separator
+                  name="group1">
+            </separator>
+            <separator
+                  name="group2">
+            </separator>
+         </menu>
+         <action
+               label="%excludeFromBuildConfig"
+               class="org.eclipse.ajdt.internal.buildconfig.actions.ExcludeAction"
+               menubarPath="org.eclipse.ajdt.ui.feature.tools/group0"
+               icon="icons/buildconfig/exclusion_filter_attrib.gif"
+               id="exclude">
+         </action>
+        <visibility>
+           <and>
+             <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+             <or>
+               <objectClass name="org.eclipse.jdt.core.ICompilationUnit"/>
+               <objectClass name="org.eclipse.jdt.core.IPackageFragment"/>
+             </or>
+           </and>
+         </visibility>
+      </objectContribution>
+      <objectContribution
+            objectClass="org.eclipse.jdt.core.IJavaElement"
+            id="Build Configurator Plugin.objectContribution1">
+         <menu
+               label="%org.eclipse.ajdt.ui.tools"
+               id="org.eclipse.ajdt.ui.feature.tools">
+            <separator
+                  name="group0">
+            </separator>
+            <separator
+                  name="group1">
+            </separator>
+            <separator
+                  name="group2">
+            </separator>
+         </menu>
+         <action
+               label="%includeInActiveBuildConfig"
+               class="org.eclipse.ajdt.internal.buildconfig.actions.IncludeAction"
+               menubarPath="org.eclipse.ajdt.ui.feature.tools/group0"
+               icon="icons/buildconfig/inclusion_filter_attrib.gif"
+               id="include">
+         </action>
+        <visibility>
+           <and>
+             <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+             <or>
+               <objectClass name="org.eclipse.jdt.core.ICompilationUnit"/>
+               <objectClass name="org.eclipse.jdt.core.IPackageFragment"/>
+             </or>
+           </and>
+         </visibility>
+      </objectContribution>
+            <objectContribution
+            objectClass="org.eclipse.core.resources.IFile"
+            nameFilter="*.lst"
+            id="buildfilecontributions">
+         <visibility>
+            <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+         </visibility>
+         <menu
+               label="%org.eclipse.ajdt.ui.tools"
+               id="org.eclipse.ajdt.ui.feature.tools">
+            <separator
+                  name="group0">
+            </separator>
+            <separator
+                  name="group1">
+            </separator>
+            <separator
+                  name="group2">
+            </separator>
+         </menu>
+         <action
+               label="%saveAsAJProperties"
+               class="org.eclipse.ajdt.internal.buildconfig.actions.ImportAction"
+               menubarPath="org.eclipse.ajdt.ui.feature.tools/group1"
+               id="buildselectorpopup">
+         </action>
+      </objectContribution>
+
+      <objectContribution
+            objectClass="org.eclipse.core.resources.IFile"
+            nameFilter="*.ajproperties"
+            id="ajproperties">
+         <visibility>
+            <objectState name="projectNature" value="org.eclipse.ajdt.ui.ajnature"/>
+         </visibility>
+         <menu
+               label="%org.eclipse.ajdt.ui.tools"
+               id="org.eclipse.ajdt.ui.feature.tools">
+            <separator
+                  name="group0">
+            </separator>
+            <separator
+                  name="group1">
+            </separator>
+            <separator
+                  name="group2">
+            </separator>
+         </menu>
+         <action
+               label="%activateConfig"
+               class="org.eclipse.ajdt.internal.buildconfig.actions.ActivateAction"
+               menubarPath="org.eclipse.ajdt.ui.feature.tools/group0"
+               id="ajpropertiespopup">
+         </action>
+         <action
+               label="%saveAsLst"
+               class="org.eclipse.ajdt.internal.buildconfig.actions.ExportAction"
+               menubarPath="org.eclipse.ajdt.ui.feature.tools/group1"
+               id="org.eclipse.ajdt.buildconfigurator.exportAction"/>
+      </objectContribution>
+   </extension>
+
+   <extension
+         point="org.eclipse.ui.decorators">
+      <decorator
+            lightweight="false"
+            label="%BuildConfigDecorator.label"
+            class="org.eclipse.ajdt.internal.buildconfig.ImageDecorator"
+            state="true"
+            id="org.eclipse.ajdt.buildconfig.decorator">
+         <description>
+			%BuildConfigDecorator.description
+		 </description>
+         <enablement>
+            <objectClass
+                  name="java.lang.Object">
+            </objectClass>
+         </enablement>
+         <description>
+         </description>
+      </decorator>
+   </extension>
+   
+   <extension
+         id="editors"
+         point="org.eclipse.ui.editors">
+      <editor
+            name="%ajPropertiesEditor"
+            icon="icons/buildconfig/buildconfig_file.gif"
+            extensions="ajproperties"
+            contributorClass="org.eclipse.ajdt.internal.buildconfig.editor.BuildEditorContributor"
+            class="org.eclipse.ajdt.internal.buildconfig.editor.BuildEditor"
+            id="AJPropertiesEditor">
+      </editor>
+   </extension>
+   
+   <!--
+   <extension
+         point="org.eclipse.ui.propertyPages">
+      <page
+            objectClass="org.eclipse.core.resources.IProject"
+            adaptable="true"
+            name="%javaBuildPath"
+            class="org.eclipse.ajdt.internal.buildconfig.propertypage.BCPropertyPage"
+            id="org.eclipse.ajdt.ui.ConfiguratorPage">
+         <filter
+               name="projectNature"
+               value="org.eclipse.ajdt.ui.ajnature">
+         </filter>
+      </page>
+    </extension>
+    -->
+    
+    <extension point="org.eclipse.ui.newWizards">
+      <!-- Define wizard for creating new build configurations -->
+      <wizard
+            name="%buildConfigFile"
+            icon="icons/buildconfig/new_build_config_wizard.gif"
+            category="org.eclipse.ajdt.wizards"
+            class="org.eclipse.ajdt.internal.buildconfig.wizards.BuildConfigurationFileWizard"
+            finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
+            id="ajbuildconfigwizard">
+         <description>
+            %buildConfigDescription
+         </description>
+      </wizard>       
+    </extension>
+    
+ 	<extension point="org.eclipse.ui.startup">
+	</extension>
+
+</plugin>
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceChangeListener.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceChangeListener.java
new file mode 100644
index 0000000..870fcb8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceChangeListener.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.io.File;
+
+import org.aspectj.ajdt.internal.core.builder.IncrementalStateManager;
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.core.model.AJModel;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * @author Luzius Meisser
+ * 
+ * Listens to resource changes and:
+ * 
+ * -informs BuildConfigurator if a project gets closed or deleted -lets
+ * BCResourceDeltaVisitor visit the delta otherwise
+ * 
+ */
+public class BCResourceChangeListener implements IResourceChangeListener {
+	private BCResourceDeltaVisitor myDeltaVisitor;
+
+	private IBuildConfigurator myBCor;
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+	 */
+	public BCResourceChangeListener() {
+		myDeltaVisitor = new BCResourceDeltaVisitor();
+		myBCor = DefaultBuildConfigurator.getBuildConfigurator();
+	}
+
+	public void resourceChanged(IResourceChangeEvent event) {
+		if ((event.getType() == IResourceChangeEvent.PRE_CLOSE)
+				|| (event.getType() == IResourceChangeEvent.PRE_DELETE)) {
+			IResource res = event.getResource();
+			if (res.getType() == IResource.PROJECT) {
+				IProject project = (IProject) res;
+				((BuildConfigurator)myBCor).closeProject(project);
+				boolean delete = (event.getType() == IResourceChangeEvent.PRE_DELETE);
+				String lstFileName = AspectJPlugin.getBuildConfigurationFile(project);
+				File lstFile = new File(lstFileName);
+				if (delete && lstFile.exists()) {
+					lstFile.delete();
+				}
+				AJModel.getInstance().clearMap(project, delete);
+				IncrementalStateManager
+						.removeIncrementalStateInformationFor(AspectJPlugin
+								.getBuildConfigurationFile(project));
+			}
+		} else if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
+			// avoid processing deltas for non-AspectJ projects,
+			IResourceDelta delta = event.getDelta();
+			if (delta != null) {
+				IResourceDelta[] cd = delta.getAffectedChildren();
+				if (cd == null) {
+					try {
+						delta.accept(myDeltaVisitor);
+					} catch (CoreException e) {
+					}
+				} else {
+					for (int i = 0; i < cd.length; i++) {
+						try {
+							IResource res = cd[i].getResource();
+							if (res == null) {
+								cd[i].accept(myDeltaVisitor);
+							} else {
+								IProject proj = res.getProject();
+								// if we don't know the project, or it is
+								// no longer accessible, we'd better process
+								// the delta. Otherwise we only process it
+								// if it is an AspectJ project.
+								if ((proj == null) || !proj.isAccessible()
+										|| AspectJPlugin.isAJProject(proj)) {
+									cd[i].accept(myDeltaVisitor);
+								}
+							}
+						} catch (CoreException e) {
+						}
+					}
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceDeltaVisitor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceDeltaVisitor.java
new file mode 100644
index 0000000..b4e48df
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCResourceDeltaVisitor.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.bc.BuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+
+/**
+ * @author Luzius Meisser
+ * 
+ * This ResourceDeltaVisitor initiates the appropriate measures if it finds
+ * removed folders or changes in project descriptions.
+ * 
+ * If a folder gets deleted, BuildConfigurations that used this folder as source
+ * need to be changed. If a project description changes, we have to let the
+ * BuildConfigurator check if its aj nature was removed.
+ *  
+ */
+public class BCResourceDeltaVisitor implements IResourceDeltaVisitor {
+	private IBuildConfigurator myBCor;
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+	 */
+	public BCResourceDeltaVisitor() {
+		myBCor = DefaultBuildConfigurator.getBuildConfigurator();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+	 */
+	public boolean visit(IResourceDelta delta) {
+		IResource myRes = delta.getResource();
+		if (myRes.getType() == IResource.FILE) {
+			switch (delta.getKind()) {
+			case IResourceDelta.CHANGED:
+				if (BuildConfiguration.EXTENSION.equals(myRes
+						.getFileExtension())) {
+					new UpdateJob(myBCor, UpdateJob.BUILD_CONFIG_CHANGED, myRes)
+							.schedule();
+				} else if (".classpath".equals(myRes.getName())) { //$NON-NLS-1$
+					new UpdateJob(myBCor, UpdateJob.CLASSPATH_CHANGED, myRes)
+							.schedule();
+				}
+				break;
+			case IResourceDelta.REMOVED:
+				//Build Configuration has been deleted
+				if (BuildConfiguration.EXTENSION.equals(myRes
+						.getFileExtension())) {
+					new UpdateJob(myBCor, UpdateJob.BUILD_CONFIG_REMOVED, myRes)
+							.schedule();
+				}
+				break;
+			case IResourceDelta.ADDED:
+				if ((delta.getFlags() & IResourceDelta.MOVED_FROM) == 0){
+					if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(myRes
+							.getName())) {
+						new UpdateJob(myBCor, UpdateJob.SOURCE_ADDED, myRes)
+								.schedule();
+					}
+				} else {
+					IFile oldLocation = myRes.getWorkspace().getRoot().getFile(delta.getMovedFromPath());
+					if (oldLocation != null){
+						new UpdateJob(myBCor, UpdateJob.FILE_MOVED, myRes, oldLocation).schedule();
+					}
+				}
+				break;
+			}
+		}
+		return true;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCWorkbenchWindowInitializer.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCWorkbenchWindowInitializer.java
new file mode 100644
index 0000000..c7ed71a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BCWorkbenchWindowInitializer.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import org.eclipse.ajdt.internal.buildconfig.menu.DynamicBuildConfigurationMenu;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.ui.IStartup;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.internal.WorkbenchWindow;
+
+/**
+ * @author Luzius Meisser
+ *
+ * Adds the menu and our selection listener to all workbench windows.
+ */
+public class BCWorkbenchWindowInitializer implements IWindowListener, IStartup {
+	
+	private IBuildConfigurator buildConfigurator;
+	private IWorkbench workbench;
+
+	private static final String BUILD_MENU_ID = "org.eclipse.ajdt.BuildMenu"; //$NON-NLS-1$
+	
+	/**
+	 */
+	public BCWorkbenchWindowInitializer() {
+		this.workbench = AspectJUIPlugin.getDefault().getWorkbench();
+		buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+		
+		workbench.addWindowListener(this);
+		IWorkbenchWindow[] wins = workbench.getWorkbenchWindows();
+		for (int i=0; i<wins.length; i++){
+			this.windowOpened(wins[i]);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowActivated(IWorkbenchWindow window) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowDeactivated(IWorkbenchWindow window) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowClosed(IWorkbenchWindow window) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
+	 */
+	public void windowOpened(IWorkbenchWindow window) {
+		window.getSelectionService().addSelectionListener((BuildConfigurator)buildConfigurator);
+		IMenuManager imm = ((WorkbenchWindow)window).getMenuManager();
+		imm = imm.findMenuUsingPath("project"); //$NON-NLS-1$
+		// only add the menu if it's not already there
+		IContributionItem buildMenu = imm.find(BUILD_MENU_ID);
+		if (buildMenu == null) {
+			imm.insertAfter("buildProject", new DynamicBuildConfigurationMenu(BUILD_MENU_ID)); //$NON-NLS-1$
+		}
+	}
+
+	public void earlyStartup() {
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfiguration.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfiguration.java
new file mode 100644
index 0000000..300a04e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfiguration.java
@@ -0,0 +1,693 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ * 	   Sian January - updated for new build configuration wizard
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.editor.BuildProperties;
+import org.eclipse.ajdt.internal.ui.ajde.ErrorHandler;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.ide.IDE;
+
+/**
+ * This class represents a Build Configuration. It stores all the Classpath data
+ * and offers functionality to include/exclude files, commit changes and to
+ * create new Build Configurations using sophisticated constructors.
+ */
+public class BuildConfiguration implements IBuildConfiguration, Cloneable,
+		org.eclipse.jdt.internal.core.util.Util.Comparable {
+
+	//because we are using jdts classpath file reader/writer, we cannot
+	//define new entry kinds and have to recycle one we are not using
+	public static final int LST_FILE_LINK = IClasspathEntry.CPE_CONTAINER;
+
+	private String name;
+
+	private BuildProperties propertiesFile;
+
+	private HashSet fileList;
+
+	private IProjectBuildConfigurator pbc;
+
+	private boolean listenToFileChanges = true;
+
+	//creates BuildConfiguration from data and writes according file
+	public BuildConfiguration(String name, IJavaProject jp,
+			IProjectBuildConfigurator pbc) {
+		this.pbc = pbc;
+		this.name = name;
+
+		//check if buildconfigurator has a filelist we should use
+		//(when converting to an aj project, this file list gets
+		//populated using jdts exclusion/inclusion patterns)
+		BuildConfigurator bcg = (BuildConfigurator)DefaultBuildConfigurator.getBuildConfigurator();
+		fileList = bcg.getInitialFileList();
+		if (fileList != null) {
+			propertiesFile = new BuildProperties(getFileFromName(name),
+					minimizeIncludes(fileList));
+		} else {
+			try {
+				IClasspathEntry[] cpes2 = jp.getRawClasspath();
+				if (bcg.haveExclusionPatterns(cpes2)) {
+					fileList = bcg.getFileSetFromCPE(cpes2, jp);
+					propertiesFile = new BuildProperties(getFileFromName(name),
+							minimizeIncludes(fileList));
+				} else {
+					fileList = bcg.getInitialFileList();
+					if (fileList != null) {
+						//maybe filelist is written now
+						//(this check could be prevented using synchronization
+						//but we risk creating deadlock opportunities when
+						// doing so)
+						propertiesFile = new BuildProperties(
+								getFileFromName(name),
+								minimizeIncludes(fileList));
+					} else {
+						List pathes = new ArrayList();
+						for (int i = 0; i < cpes2.length; i++) {
+							if (cpes2[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+								IPath p = cpes2[i].getPath();
+								IResource res = jp.getProject().getParent()
+										.findMember(p);
+								if ((res != null) && res.exists())
+									pathes.add(res.getProjectRelativePath());
+							}
+						}
+						propertiesFile = new BuildProperties(
+								getFileFromName(name), pathes);
+					}
+				}
+			} catch (JavaModelException e) {
+			}
+		}
+	}
+
+	public IFile getFile() {
+		return getFileFromName(name);
+	}
+
+	//creates BuildConfiguration from file
+	public BuildConfiguration(IFile existingFile, IProjectBuildConfigurator pbc) {
+		this.pbc = pbc;
+		loadDataFromFile(existingFile);
+	}
+
+	private HashSet getFileList() {
+		if (fileList == null) {
+			HashSet newList = new HashSet(20);
+			newList.addAll(propertiesFile.getFiles(false));
+			fileList = newList;
+			return newList;
+		}
+		return fileList;
+	}
+
+	/**
+	 * Creates BuildConfiguration from lst file
+	 * 
+	 * @param lstFile2
+	 * @param shell
+	 * @param pbc
+	 *  
+	 */
+	public BuildConfiguration(IFile lstFile2, Shell shell,
+			IProjectBuildConfigurator pbc) {
+		this.pbc = pbc;
+		name = lstFile2.getName();
+		name = name.substring(0, name.length() - 4);
+
+
+		String title = UIMessages.BCDialog_SaveLstAsAJProp_title;
+		String msg = UIMessages.BCDialog_SaveLstAsAJProp_message.replaceAll("%src", name); //$NON-NLS-1$
+		InputDialogWithCheck md = new InputDialogWithCheck(shell, title, msg, name + "." //$NON-NLS-1$
+				+ BuildConfiguration.EXTENSION, null);
+		md.setBlockOnOpen(true);
+		if ((md.open() == Window.OK) && (md.getValue() != null)) {
+			String fileName = md.getValue();
+			if (!fileName.endsWith("." + BuildConfiguration.EXTENSION)) { //$NON-NLS-1$
+				fileName = fileName + "." + BuildConfiguration.EXTENSION; //$NON-NLS-1$
+			}
+			IFile file = pbc.getJavaProject().getProject().getFile(fileName);
+			name = BuildConfiguration.getNameFromFile(file);
+
+			if (file.exists()) {
+				if (!askUserOverwrite(fileName)) {
+					return;
+				}
+			}
+
+			fileList = new HashSet();
+			addLStFileContentsToFileList(lstFile2);
+			IFile newFile = getFileFromName(name);
+			this.propertiesFile = new BuildProperties(newFile, minimizeIncludes(fileList));
+			pbc.addBuildConfiguration(this);
+			if (md.isActivateChecked()){
+				pbc.setActiveBuildConfiguration(this);
+			}
+			if (md.isOpenInEditorChecked()) {
+				IWorkbenchWindow dwindow = AspectJUIPlugin.getDefault().getActiveWorkbenchWindow();
+				IWorkbenchPage page = dwindow.getActivePage();
+				if (page != null) 
+					try {
+						IDE.openEditor(page, newFile, true);
+					}
+					catch (PartInitException pie) {}
+			}
+		}
+	}
+
+	private List minimizeIncludes(HashSet fileList) {
+		//if all files of a folder are included, include folder instead of
+		// files seperately
+		HashSet temp1 = (HashSet) fileList.clone();
+		HashSet temp2 = new HashSet();
+		HashSet temp3;
+		boolean hasChanged = true;
+		Iterator iter = temp1.iterator();
+
+		while (hasChanged) {
+
+			hasChanged = false;
+			iter = temp1.iterator();
+			while (iter.hasNext()) {
+				IResource f = (IResource) iter.next();
+				IContainer cont = f.getParent();
+				if (cont.getType() != IResource.PROJECT) {
+					try {
+						IResource[] mems = cont.members();
+						boolean containsAll = true;
+						for (int i = 0; i < mems.length; i++) {
+							if (!temp1.contains(mems[i])
+									&& CoreUtils.ASPECTJ_SOURCE_FILTER
+											.accept(mems[i].getName())) {
+								containsAll = false;
+								break;
+							} else if (!temp1.contains(mems[i])
+									&& (mems[i].getType() == IResource.FOLDER)) {
+								containsAll = false;
+								break;
+							}
+						}
+						if (!containsAll) {
+							for (int i = 0; i < mems.length; i++) {
+								if (temp1.remove(mems[i]))
+									temp2.add(mems[i]);
+							}
+						} else {
+							for (int i = 0; i < mems.length; i++) {
+								temp1.remove(mems[i]);
+							}
+							hasChanged = true;
+							temp2.add(cont);
+						}
+					} catch (CoreException e1) {
+					}
+				} else {
+					temp1.remove(f);
+					temp2.add(f);
+				}
+				iter = temp1.iterator();
+			}
+
+			temp3 = temp2;
+			temp2 = temp1;
+			temp1 = temp3;
+		}
+
+		return new ArrayList(temp1);
+	}
+
+	private void addLStFileContentsToFileList(IFile lstFile) {
+		ArrayList files = new ArrayList();
+		ArrayList options = new ArrayList();
+		ArrayList links = new ArrayList();
+
+		try {
+			org.eclipse.ajdt.internal.buildconfig.Util.getLstFileContents(lstFile
+					.getLocation(), files, options, links);
+		} catch (FileNotFoundException e) {
+			return;
+		}
+
+		IProject pro = pbc.getJavaProject().getProject();
+		IPath lstFileFolder = lstFile.getFullPath().removeLastSegments(1);
+		int segs = lstFileFolder.matchingFirstSegments(pro.getFullPath());
+		IPath relPath = lstFileFolder.removeFirstSegments(segs);
+
+		Iterator iter;
+		iter = files.iterator();
+		while (iter.hasNext()) {
+			String filename = (String) iter.next();
+			IFile f = pro.getFile(relPath.append(filename));
+			if (f.exists()) {
+				getFileList().add(f);
+			}
+		}
+
+		//read linked lst files
+		iter = links.iterator();
+		while (iter.hasNext()) {
+			String filename = ((String) iter.next()).substring(1);
+			IFile f = pro.getFile(relPath.append(filename));
+			if (f.exists()) {
+				addLStFileContentsToFileList(f);
+			}
+		}
+	}
+
+	//creates new BuildConfiguration and askes user for name
+	public BuildConfiguration(final IProjectBuildConfigurator pbc, Shell parentShell)
+			throws BuildConfigurationCreationException {
+		this.pbc = pbc;
+
+		String title = UIMessages.BCDialog_SaveBuildConfigurationAs_title;
+		String msg = UIMessages.BCDialog_SaveBuildConfigurationAs_message; 
+		String fileName = BuildConfigurator.getFreeFileName(pbc.getJavaProject().getProject());
+
+		IBuildConfiguration origBC = pbc.getActiveBuildConfiguration();
+
+		IInputValidator validator = new IInputValidator() {
+			public String isValid(String input) {
+				IFile[] files = pbc.getConfigurationFiles();
+				for (int i = 0; i < files.length; i++) {
+					IFile file = files[i];
+					if (file.getName().equals(input)
+							|| file.getName()  //$NON-NLS-1$
+									.equals(input + "." + BuildConfiguration.EXTENSION)) { //$NON-NLS-1$
+						return UIMessages.BCDialog_NameValidator_ExistsError;
+					}
+				}
+				return null;				
+			}
+		};
+
+		InputDialogWithCheck md = new InputDialogWithCheck(parentShell, title, msg, fileName,
+				validator);
+		md.setBlockOnOpen(true);
+		if (md.open() == Window.OK) {
+			if (md.getValue() != null) {
+			
+				String newName = md.getValue();
+				this.name = newName;
+	
+				IFile origFile = origBC.getFile();
+				IFile newFile = this.getFile();
+				if (newFile.exists()) {
+					if (!askUserOverwrite(newFile.getName())) {
+						throw new BuildConfigurationCreationException();
+					} 
+					try {
+						newFile.delete(true, null);
+					} catch (CoreException e1) {
+					}
+					
+				}
+				try {
+					origFile.copy(newFile.getFullPath(), true, null);
+					this.propertiesFile = new BuildProperties(newFile);
+				} catch (CoreException e) {
+					//could not copy file, try another way to create it
+					this.propertiesFile = new BuildProperties(
+							getFileFromName(name), new ArrayList(getFileList()));
+				}
+				fileList = new HashSet(propertiesFile.getFiles(false));
+				pbc.addBuildConfiguration(this);
+				if (md.isActivateChecked()) {
+					pbc.setActiveBuildConfiguration(this);
+				}
+				if (md.isOpenInEditorChecked()) {
+					IWorkbenchWindow dwindow = AspectJUIPlugin.getDefault().getActiveWorkbenchWindow();
+					IWorkbenchPage page = dwindow.getActivePage();
+					if (page != null) 
+						try {
+							IDE.openEditor(page,newFile,true);
+						}
+						catch (PartInitException pie) {}
+				}
+			} else {
+				throw new BuildConfigurationCreationException();
+			}
+		}
+	}
+	
+	/**
+	 * Creates a build configuration with the given name
+	 * @param name
+	 * @param pbc
+	 */
+	public BuildConfiguration (IFile fileToUse, IProjectBuildConfigurator pbc, boolean makeActive) {
+		this.pbc = pbc;
+		name = getNameFromFile(fileToUse);
+		IProject project = fileToUse.getProject();
+		BuildConfigurator bcg = (BuildConfigurator)DefaultBuildConfigurator.getBuildConfigurator();
+		fileList = bcg.getInitialFileList();
+		if(fileList != null) {
+			propertiesFile = new BuildProperties(
+				fileToUse, new ArrayList(getFileList()));
+		} else {
+			try {
+				IJavaProject jp = JavaCore.create(project);		
+				IClasspathEntry[] cpes2 = jp.getRawClasspath();
+				if (bcg.haveExclusionPatterns(cpes2)) {
+					fileList = bcg.getFileSetFromCPE(cpes2, jp);
+					propertiesFile = new BuildProperties(fileToUse,
+							minimizeIncludes(fileList));
+				} else {
+					List pathes = new ArrayList();
+					for (int i = 0; i < cpes2.length; i++) {
+						if (cpes2[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+							IPath p = cpes2[i].getPath();
+							IResource res = jp.getProject().getParent()
+									.findMember(p);
+							if ((res != null) && res.exists())
+								pathes.add(res.getProjectRelativePath());
+						}
+					}
+					propertiesFile = new BuildProperties(
+							fileToUse, pathes);
+				}
+			} catch (JavaModelException jme) {}
+		}
+		
+		pbc.addBuildConfiguration(this);
+		if (makeActive)
+			pbc.setActiveBuildConfiguration(this);		
+
+	}
+	
+	IFile getFileFromName(String name) {
+		return pbc.getJavaProject().getProject().getFile(
+				name + "." + BuildConfiguration.EXTENSION); //$NON-NLS-1$
+	}
+
+	static String getNameFromFile(IFile file) {
+		String n = file.getName();
+		return n.substring(0, n.indexOf("." + EXTENSION)); //$NON-NLS-1$
+	}
+
+	public void loadDataFromFile(IFile existingFile) {
+		if (existingFile.exists()) {
+			name = getNameFromFile(existingFile);
+			propertiesFile = new BuildProperties(existingFile);
+		}
+	}
+
+	private String getLstContentFromData() {
+		String files = ""; //$NON-NLS-1$
+		Iterator iter = getFileList().iterator();
+		while (iter.hasNext()) {
+			files = files.concat(((IFile) iter.next()).getProjectRelativePath()
+					.toOSString().concat(System.getProperty("line.separator", "\n"))); //$NON-NLS-1$ //$NON-NLS-2$
+			;
+		}
+		return files;
+	}
+
+	/**
+	 * @return Returns the name.
+	 */
+	public String getName() {
+		return name;
+	}
+
+	//adds an exclusion filter for a given file to a given classpathentry[]
+	private boolean excludeFile(IResource file) throws CoreException {
+		listenToFileChanges = false;
+		propertiesFile.exclude(file);
+		listenToFileChanges = true;
+		if (file.getType() == IResource.FILE) {
+			getFileList().remove(file);
+			return true;
+		}
+		return false;
+	}
+
+	public void excludeFiles(List exFiles) throws CoreException {
+		Iterator iter = exFiles.iterator();
+		boolean needsupdate = false;
+		IResource res = null;
+		while (iter.hasNext()) {
+			res = (IResource) iter.next();
+			if (!excludeFile(res))
+				needsupdate = true;
+		}
+		if (needsupdate) {
+			update(false);
+		}
+		
+		propertiesFile.writeFile();
+	}
+
+	//adds an exclusion filter for a given file to a given classpathentry[]
+	private boolean includeFile(IResource file) {
+		listenToFileChanges = false;
+		propertiesFile.include(file);
+		listenToFileChanges = true;
+		if (file.getType() == IResource.FILE) {
+			getFileList().add(file);
+			return true;
+		}
+		return false;
+	}
+
+	public void includeFiles(List exFiles) {
+		Iterator iter = exFiles.iterator();
+		boolean needsupdate = false;
+		IResource res = null;
+		while (iter.hasNext()) {
+			res = (IResource) iter.next();
+			if (!includeFile(res))
+				needsupdate = true;
+		}
+		if (needsupdate) {
+			update(false);
+		}
+		
+		propertiesFile.writeFile();
+	}
+
+	public boolean isIncluded(IResource file) {
+		//System.out.println("include check");
+		boolean isIncl = getFileList().contains(file);
+		return isIncl;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.lang.Comparable#compareTo(java.lang.Object)
+	 */
+	public int compareTo(org.eclipse.jdt.internal.core.util.Util.Comparable o) {
+		if (o instanceof BuildConfiguration) {
+			return getName().compareToIgnoreCase(
+					((BuildConfiguration) o).getName());
+		}
+		return 0;
+	}
+
+	/**
+	 *  
+	 */
+	public void update(boolean forceReadingFile) {
+		// mark file list as dirty as it is (probably) about to change
+		AspectJUIPlugin.getDefault().getAjdtProjectProperties()
+				.setProjectSourceFileListKnown(
+						pbc.getJavaProject().getProject(), false);
+
+		if (listenToFileChanges == true) {
+			if (fileList == null) {
+				fileList = new HashSet();
+			} else {
+				fileList.clear();
+			}
+			List l = propertiesFile.getFiles(forceReadingFile);
+			fileList.addAll(l);
+		}
+	}
+
+	//	returns a list of java.io.Files containing the selected files
+	public List getIncludedJavaFiles(CoreUtils.FilenameFilter filter) {
+		Iterator iter = getFileList().iterator();
+		ArrayList list = new ArrayList(getFileList().size());
+		while (iter.hasNext()) {
+			IResource res = (IResource) iter.next();
+			if (res.exists() && filter.accept(res.getName()))
+				list.add(new File(res.getLocation().toOSString()));
+		}
+		return list;
+	}
+
+	//returns a list of strings containing the file names
+	public List getIncludedJavaFileNames(CoreUtils.FilenameFilter filter) {
+		Iterator iter = getFileList().iterator();
+		ArrayList list = new ArrayList(getFileList().size());
+		while (iter.hasNext()) {
+			IResource res = (IResource) iter.next();
+			if (res.exists() && filter.accept(res.getName()))
+				list.add(res.getLocation().toOSString());
+		}
+		return list;
+	}
+
+	/**
+	 *  
+	 */
+	public void writeLstFile() {
+		update(false);
+		String lstFileContent = this.getLstContentFromData();
+
+		String title = UIMessages.BCDialog_SaveAJPropAsLst_title;
+		String msg = UIMessages.BCDialog_SaveAJPropAsLst_message.replaceAll("%name", name); //$NON-NLS-1$
+
+		InputDialog md = new InputDialog(null, title, msg, name + ".lst", null); //$NON-NLS-1$
+		md.setBlockOnOpen(true);
+		if ((md.open() == Window.OK) && (md.getValue() != null)) {
+			String fileName = md.getValue();
+			if (!fileName.endsWith(".lst")) { //$NON-NLS-1$
+				fileName = fileName + ".lst"; //$NON-NLS-1$
+			}
+			try {
+				IFile file = pbc.getJavaProject().getProject()
+						.getFile(fileName);
+				if (file.exists()) {
+					if (askUserOverwrite(fileName)) {
+						InputStream inputStream = new ByteArrayInputStream(
+								lstFileContent.getBytes());
+						if (file.isReadOnly()) {
+							ResourcesPlugin.getWorkspace().validateEdit(
+									new IFile[] { file }, null);
+						}
+						file.setContents(inputStream, IResource.FORCE, null);
+					}
+				} else {
+					InputStream inputStream = new ByteArrayInputStream(
+							lstFileContent.getBytes());
+					file.create(inputStream, IResource.FORCE, null);
+				}
+			} catch (CoreException e) {
+				ErrorHandler.handleAJDTError(
+						NLS.bind(UIMessages.buildConfig_exceptionWriting,fileName), e); //$NON-NLS-1$
+			}
+
+		}
+
+	}
+
+	private boolean askUserOverwrite(String fileName) {
+		String[] options = {
+				UIMessages.BCDialog_Overwrite_yes,
+				UIMessages.BCDialog_Overwrite_no };
+		String title = UIMessages.BCDialog_Overwrite_title;
+		String msg = UIMessages.BCDialog_Overwrite_message.replaceAll("%fileName", fileName); //$NON-NLS-1$
+
+		MessageDialog mdiag = new MessageDialog(null, title, null, msg,
+				MessageDialog.QUESTION, options, 1);
+		return (mdiag.open() == 0);
+	}
+
+	/**
+	 * @return
+	 */
+	public boolean areFilesActive() {
+		return (getFileList().size() != 0);
+	}
+
+	/**
+	 *  
+	 */
+	public void updateSourceFolders(List sourcePathes) {
+		propertiesFile.updateSourceFolders(sourcePathes);
+		fileList = null;
+	}
+	
+	private class InputDialogWithCheck extends InputDialog {
+		private Button activateCheckbox;
+		private Button openInEditorCheckbox;
+		private boolean activateSelected;
+		private boolean openInEditorSelected;
+		
+		/**
+		 * @param parentShell
+		 * @param dialogTitle
+		 * @param dialogMessage
+		 * @param initialValue
+		 * @param validator
+		 */
+		public InputDialogWithCheck(Shell parentShell, String dialogTitle, String dialogMessage, String initialValue, IInputValidator validator) {
+			super(parentShell, dialogTitle, dialogMessage, initialValue, validator);
+		}
+		
+		protected Control createDialogArea(Composite parent) {
+			Composite composite = (Composite) super.createDialogArea(parent);
+			openInEditorCheckbox = new Button(composite, SWT.CHECK);
+			openInEditorCheckbox.setSelection(true);
+			openInEditorCheckbox.setText(UIMessages.BuildConfig_openForEdit);
+			activateCheckbox = new Button(composite, SWT.CHECK);
+			activateCheckbox.setSelection(true);
+			activateCheckbox.setText(UIMessages.BuildConfig_activate);
+			return composite;
+		}
+		
+		protected void okPressed() {
+			activateSelected = activateCheckbox.getSelection();
+			openInEditorSelected = openInEditorCheckbox.getSelection();
+			super.okPressed();
+		}
+		/**
+		 * Is the checkbox selected?
+		 * @return
+		 */
+		public boolean isActivateChecked() {
+			return activateSelected;
+		}
+		
+		public boolean isOpenInEditorChecked() {
+			return openInEditorSelected;
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurationCreationException.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurationCreationException.java
new file mode 100644
index 0000000..f340db3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurationCreationException.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+/**
+ * @author Luzius Meisser
+ *
+ */
+public class BuildConfigurationCreationException extends Exception {
+
+	private static final long serialVersionUID = 6334629352889509802L;
+
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurator.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurator.java
new file mode 100644
index 0000000..d3f4368
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/BuildConfigurator.java
@@ -0,0 +1,402 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Vector;
+
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.ui.ajde.ErrorHandler;
+import org.eclipse.ajdt.internal.ui.preferences.AspectJPreferences;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.contribution.xref.ui.views.XReferenceView;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+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;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.ui.packageview.ClassPathContainer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.progress.UIJob;
+
+/**
+ * @author Luzius Meisser
+ * 
+ * This class manages the ProjectBuildConfiguratiors.
+ * It offers functionality to
+ * - get the ProjectBuildConfigurator for a specific Project
+ * - register IBuildConfigurationChangedListeners
+ * - notify these change listeners
+ * 
+ * It creates exaclty one ProjectBuildConfigurator per Project
+ * that fulfills the criteria specified in 
+ * public boolen canManage(IProject p);
+ * 
+ */
+public class BuildConfigurator implements IBuildConfigurator, ISelectionListener {
+	private HashMap projectConfigurators;
+	private Vector changeListeners;
+	private IProject currentProj;
+	private int notificationType;
+	private static DefaultBuildConfigurator buildConfigurator;
+	
+	private HashSet fileList;
+	private boolean triedToOpenXRefView;
+	private boolean isOpen;
+	
+	public BuildConfigurator() {
+		projectConfigurators = new HashMap();
+		changeListeners = new Vector();
+		notificationType = -1;
+	}
+	
+	//guarantuees to return a non-null value
+//	public static synchronized DefaultBuildConfigurator getBuildConfigurator(){
+//		if (buildConfigurator == null)
+//			buildConfigurator = new DefaultBuildConfigurator();
+//		return buildConfigurator;
+//	}
+
+	public synchronized void selectionChanged(IWorkbenchPart action, ISelection selection) {
+		IResource res;
+		IProject selectedProj;
+		IPreferenceStore store = AspectJUIPlugin.getDefault().getPreferenceStore();
+		if (!triedToOpenXRefView) { // only try this once
+			String workspaceLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString();
+			if (!store.getBoolean(AspectJPreferences.DONE_AUTO_OPEN_XREF_VIEW + workspaceLocation)
+			        && !store.getBoolean(workspaceLocation)) {
+		        // open xref view in perspective if we haven't opened the xref view before.
+				Job job = new UIJob(UIMessages.BuildConfigurator_workbench_openXRefView) {
+					public IStatus runInUIThread(IProgressMonitor monitor) {
+						try {
+			                AspectJUIPlugin.getDefault().getActiveWorkbenchWindow()
+								.getActivePage().showView(XReferenceView.ID);
+			                return Status.OK_STATUS;
+				        } catch (PartInitException e) {
+				        	ErrorHandler.handleAJDTError(UIMessages.BuildConfigurator_ErrorOpeningXRefView, e);
+				            return Status.OK_STATUS;
+				        }
+					}
+				};
+			    job.schedule();
+		        store.setValue(AspectJPreferences.DONE_AUTO_OPEN_XREF_VIEW + workspaceLocation, true);
+		    }
+			triedToOpenXRefView = true;
+			
+		}
+		if (action instanceof IEditorPart) {
+			res = (IResource) ((IEditorPart) action).getEditorInput()
+					.getAdapter(IResource.class);
+			if (res != null) {
+				selectedProj = res.getProject();
+			} else {
+				selectedProj = null;
+			}
+		} else {
+			selectedProj = getProjectFromSelection(selection);
+		}
+		if ((selectedProj != currentProj) && (selectedProj != null)) {
+			fileList = null;
+			currentProj = selectedProj;
+//			if (canManage(currentProj)){
+//				
+//				PropertyPageManager.unregisterJDTPropertyPage();
+//			} else {
+//				if (currentProj.isOpen())
+//					PropertyPageManager.registerJDTPropertyPage();
+//			}
+			notifyChangeListeners();
+		} else if (selectedProj != null) {
+			// Fix for 79376 - re-activate the build button if a closed project is re-openened
+			boolean justOpened = currentProj.isOpen() && !isOpen;
+			if(justOpened) {
+				notifyChangeListeners();
+			}			
+		}
+		// adding null check since saw NPE when fixing bug 90094
+		if (currentProj != null) {
+			isOpen = currentProj.isOpen();
+		}		
+	}
+	
+	public void notifyChangeListeners() {
+		// this notificationType check is done to break infinite notifyChangeListeners loops
+		// TODO: implement a more elegant notification model
+		if (notificationType == -1) {
+			try {
+				notificationType = 0;
+				ProjectBuildConfigurator pbc = getActiveProjectBuildConfigurator();
+				Iterator iter = changeListeners.iterator();
+				while (iter.hasNext()) {
+					((IBuildConfigurationChangedListener) iter.next())
+							.buildConfigurationChanged(pbc);
+				}
+			} finally {
+//				whatever happens here, we must reset notificationType to -1
+				notificationType = -1;
+			}		
+		}
+	}
+
+	private IProject getProjectFromSelection(ISelection selection) {
+		if (selection instanceof IStructuredSelection) {
+			//get the Project & set text
+			Object first = ((IStructuredSelection) selection).getFirstElement();
+			if (first instanceof IJavaElement)
+				return ((IJavaElement) first).getJavaProject().getProject();
+			if (first instanceof IResource){
+				IResource myRes = (IResource) first;
+				return myRes.getProject();
+			}
+			if (first instanceof ClassPathContainer)
+				return ((ClassPathContainer) first).getJavaProject().getProject();
+		}
+		return null;
+	}
+	
+	/**
+	 * @return Returns the activeBuildConfigurator or null if none are active
+	 */
+	public ProjectBuildConfigurator getActiveProjectBuildConfigurator() {
+		return getProjectBuildConfigurator(currentProj);
+	}
+	
+	public Set getProjectBuildConfigurators() {
+		return projectConfigurators.entrySet();
+	}
+	
+/**
+ * @return The ProjectBuildConfigurator for the given Project if it is an open aj project or null otherwise
+ */
+	public ProjectBuildConfigurator getProjectBuildConfigurator(IJavaProject proj) {
+		if ((proj != null) && (this.canManage(proj.getProject()))) {
+			ProjectBuildConfigurator pbc = (ProjectBuildConfigurator) projectConfigurators
+					.get(proj.getProject().getName());
+			if (pbc != null)
+				return pbc;
+			return createPBC(proj);
+		}
+		return null;
+	}
+	
+	private synchronized ProjectBuildConfigurator createPBC(IJavaProject proj){
+		//check if already there
+		ProjectBuildConfigurator pbc = (ProjectBuildConfigurator) projectConfigurators
+		.get(proj.getProject().getName());
+		if (pbc != null)
+			return pbc;
+		//if not, create:
+		pbc = new ProjectBuildConfigurator(proj);
+		projectConfigurators.put(proj.getProject().getName(), pbc);
+		return pbc;
+	}
+	
+	/**
+	 * @return The ProjectBuildConfigurator for the given Project if it is an open aj project or null otherwise
+	 */
+	public ProjectBuildConfigurator getProjectBuildConfigurator(IProject proj) {
+		return getProjectBuildConfigurator(JavaCore.create(proj));
+	}
+	
+	public boolean canManage(IProject proj) {
+		if ((proj == null) || (!proj.isOpen())) {
+			return false;
+		}
+		if (AspectJPlugin.isAJProject(proj)) {
+			return true;
+		}
+		return false;
+	}
+	
+	public void addProjectBuildConfigurator(ProjectBuildConfigurator pbc) {
+		projectConfigurators.put(pbc.getJavaProject().getProject().getName(),
+				pbc);
+	}
+	/**
+	 * @param bccl
+	 */
+	public void addBuildConfigurationChangedListener(
+			IBuildConfigurationChangedListener bccl) {
+		changeListeners.add(bccl);
+	}
+	
+	/**
+	 * @param bccl
+	 */
+	public void removeBuildConfigurationChangedListener(IBuildConfigurationChangedListener bccl) {
+		changeListeners.remove(bccl);
+		
+	}	
+	
+	/**
+	 * @param jp
+	 */
+	public void closeProject(IProject proj) {
+		fileList = null;
+		ProjectBuildConfigurator pbc = (ProjectBuildConfigurator)projectConfigurators.get(proj.getName());
+		if (pbc != null) {
+			if (proj == currentProj)
+				currentProj = null;
+			projectConfigurators.remove(proj.getName());
+			notifyChangeListeners();
+		}
+	}
+	/**
+	 * @param project
+	 */
+	public void checkNature(IProject project) {
+		if (projectConfigurators.containsKey(project.getName())){
+			//if aj nature was removed, remove pbc
+			if (!this.canManage(project)){
+				ProjectBuildConfigurator pbc = (ProjectBuildConfigurator)projectConfigurators.get(project.getName());
+				if (pbc != null){
+					closeProject(project);
+				}
+			}
+		} else {
+			//aj nature has been added
+			if (this.canManage(project)){
+				currentProj = project;
+				this.notifyChangeListeners();
+			}
+		}
+		
+	}
+
+	/**
+	 * @param project
+	 */
+	public void restoreJDTState(IProject project) {
+		//PropertyPageManager.registerJDTPropertyPage();
+		this.checkNature(project);
+	}
+	/**
+	 * @param project
+	 */
+	public void setup(IProject project) {
+		fileList = null;
+		//PropertyPageManager.unregisterJDTPropertyPage();
+		try {
+			IJavaProject jp = JavaCore.create(project);
+			IClasspathEntry[] cpes = jp.getRawClasspath();
+			
+			if (haveExclusionPatterns(cpes)){
+				fileList = getFileSetFromCPE(cpes, jp);
+				for (int i=0; i<cpes.length; i++){
+					if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE){
+						cpes[i] = JavaCore.newSourceEntry(cpes[i].getPath());
+					}
+				}		
+				jp.setRawClasspath(cpes, null);
+			}
+		} catch (JavaModelException e) {
+			fileList = null;
+		}
+		
+		if ((currentProj == null) || (currentProj == project)){
+			currentProj = project;
+			this.notifyChangeListeners();
+		}
+	}
+	
+	HashSet getFileSetFromCPE(IClasspathEntry[] cpes, IJavaProject jp){
+		HashSet fileSet = new HashSet(30);
+		for (int i=0; i<cpes.length; i++){
+			if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE){
+				IResource res = jp.getProject().getParent().findMember(cpes[i].getPath());
+				if (res!=null && (res.getType()==IResource.FOLDER || res.getType()==IResource.PROJECT))
+					addAllIncludedMembers(fileSet, (IContainer)res, jp);
+			}
+		}
+		return fileSet;
+	}
+	
+	boolean haveExclusionPatterns(IClasspathEntry[] cpes){
+		for (int i=0; i<cpes.length; i++){
+			if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE){
+				if ((cpes[i].getExclusionPatterns().length > 0)
+					|| (cpes[i].getInclusionPatterns().length > 0))
+					return true;
+			}
+		}
+		return false;
+	}
+
+	
+	HashSet getInitialFileList(){
+		return fileList;
+	}
+	
+	
+	private void addAllIncludedMembers(HashSet l, IContainer con, IJavaProject jp){
+		try {
+			IResource[] reses = con.members();
+			for(int i=0; i<reses.length; i++){
+				if (reses[i] instanceof IContainer){
+					addAllIncludedMembers(l, (IContainer)reses[i], jp);
+				} else {
+					if (jp.isOnClasspath(reses[i]) && CoreUtils.ASPECTJ_SOURCE_FILTER
+							.accept(reses[i].getName())){
+						l.add(reses[i]);
+					}
+				}
+			}
+		} catch (CoreException e) {
+		}
+	}
+
+	/**
+	 * Get a new filename for the given project.  Returns the name without the file extension.
+	 * @param project
+	 * @return a string that is NOT the name of a current build configuration in the project
+	 */
+	public static String getFreeFileName(IProject project) {
+		String defaultFileName = UIMessages.BCDialog_SaveBuildConfigurationAs_default;
+	
+		int counter = 0;
+		if(project != null) {
+			boolean foundFreeName = false;
+			while (!foundFreeName) {
+				String name = counter==0 ? defaultFileName : defaultFileName+counter;
+				IPath path = project.getFullPath().append(name + "." + BuildConfiguration.EXTENSION); //$NON-NLS-1$
+				if(!AspectJPlugin.getWorkspace().getRoot().getFile(path).exists()) {
+					foundFreeName = true;
+				} else {
+					counter++;
+				}
+			}
+		}
+		return counter==0 ? defaultFileName : defaultFileName+counter;
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/IBuildConfigurationChangedListener.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/IBuildConfigurationChangedListener.java
new file mode 100644
index 0000000..606a48d
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/IBuildConfigurationChangedListener.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+
+/**
+ * To notify listeners when ACTIVE build configuration changed somehow
+ * 
+ * @author Luzius Meisser
+ */
+public interface IBuildConfigurationChangedListener {
+	public void buildConfigurationChanged(IProjectBuildConfigurator pbc);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ImageDecorator.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ImageDecorator.java
new file mode 100644
index 0000000..aff4ae3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ImageDecorator.java
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.util.ArrayList;
+
+import org.aspectj.asm.IProgramElement;
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.core.javaelements.AJCompilationUnit;
+import org.eclipse.ajdt.core.javaelements.IAspectJElement;
+import org.eclipse.ajdt.internal.ui.resources.AspectJImages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
+import org.eclipse.jdt.internal.ui.viewsupport.ImageDescriptorRegistry;
+import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
+import org.eclipse.jdt.internal.ui.viewsupport.TreeHierarchyLayoutProblemsDecorator;
+import org.eclipse.jdt.ui.JavaElementImageDescriptor;
+import org.eclipse.jface.resource.CompositeImageDescriptor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ILabelDecorator;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.ui.internal.WorkbenchPlugin;
+import org.eclipse.ui.internal.decorators.DecoratorManager;
+
+/**
+ * @see ILabelDecorator
+ */
+public class ImageDecorator implements ILabelDecorator {
+	
+	private ArrayList listeners;
+	private ImageDescriptorRegistry fRegistry;
+	private boolean preventRecursion = false;
+	private TreeHierarchyLayoutProblemsDecorator problemsDecorator;
+	private DecoratorManager decman;
+	private ImageDescriptor halfFilledPackageID;
+	private ImageDescriptor activeConfigFileImage;
+	private IBuildConfigurator buildConfor;
+	
+	private AspectJImages iconRegistry = AspectJImages.instance();
+	
+	/**
+	 *
+	 */
+	public ImageDecorator() {
+		listeners = new ArrayList(2);
+		problemsDecorator = new TreeHierarchyLayoutProblemsDecorator();
+		decman = WorkbenchPlugin.getDefault().getDecoratorManager();
+		halfFilledPackageID = AspectJImages.BC_HALF_FILLED_PACKAGE.getImageDescriptor();
+		activeConfigFileImage = AspectJImages.BC_SELECTED_FILE.getImageDescriptor();
+		buildConfor = DefaultBuildConfigurator.getBuildConfigurator();
+	}
+
+	public void addListener(ILabelProviderListener listener)  {
+		listeners.add(listener);
+	}
+
+	public void dispose()  {
+	}
+
+	public boolean isLabelProperty(Object element, String property)  {
+		return false;
+	}
+
+	public void removeListener(ILabelProviderListener listener)  {
+		listeners.remove(listener);
+	}
+
+	/**
+	 * @see ILabelDecorator#decorateImage
+	 */
+	public Image decorateImage(Image image, Object element)  {
+		if (preventRecursion)
+			return null;
+		
+		if (element instanceof ICompilationUnit){
+			ICompilationUnit comp = (ICompilationUnit)element;
+			try {
+				element = comp.getCorrespondingResource();
+			} catch (JavaModelException e) {
+				element = null;
+			}
+		}
+		
+		Image img = null;
+		if (element instanceof IFile){ 
+			IFile file= (IFile) element;
+			if (file.exists() && CoreUtils.ASPECTJ_SOURCE_ONLY_FILTER.accept(file.getName())) {
+				// Fix for 108961 - use different icons for .aj files
+				IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(file.getProject());
+				
+				if (pbc == null)
+					return null;
+				
+				if (pbc.getActiveBuildConfiguration().isIncluded(file)){
+					Rectangle rect = image.getBounds();
+					img = getImageLabel(getJavaImageDescriptor(AspectJImages.ASPECTJ_FILE.getImageDescriptor(), rect, 0));
+				} else {
+					Rectangle rect = image.getBounds();
+					img = getImageLabel(getJavaImageDescriptor(AspectJImages.EXCLUDED_ASPECTJ_FILE.getImageDescriptor(), rect, 0));
+				}
+			} else if (file.exists() && CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file.getName())){
+				IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(file.getProject());
+				
+				if (pbc == null)
+					return null;
+				
+				if (pbc.getActiveBuildConfiguration().isIncluded(file)){
+					Rectangle rect = image.getBounds();
+					img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_CUNIT, rect, 0));
+				} else {
+					Rectangle rect = image.getBounds();
+					img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_CUNIT_RESOURCE, rect, 0));
+				}
+			} else  {
+				if (BuildConfiguration.EXTENSION.equals(file.getFileExtension())){
+					IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(file.getProject());
+					if (pbc != null){
+						if (file.equals(pbc.getActiveBuildConfiguration().getFile())){
+							img = getImageLabel(getJavaImageDescriptor(activeConfigFileImage, image.getBounds(), 0));
+						}
+					}
+				
+				}
+			}
+		} else if (element instanceof IPackageFragment){
+			IPackageFragment pack = (IPackageFragment)element;
+			IProjectBuildConfigurator pbc = buildConfor.getProjectBuildConfigurator(pack.getJavaProject());
+			
+			if (pbc == null)
+				return null;
+			
+			IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+			
+			try {
+				if (containsIncludedFiles(bc, pack)){
+					if (containsExcludedFiles(bc, pack)){
+						//half filled package
+						img = getImageLabel(getJavaImageDescriptor(halfFilledPackageID, image.getBounds(), 0));
+						
+					} else {
+						//if all included files are aj files, override icon
+						//(full package icon needed)
+						if (!pack.containsJavaResources()){
+							img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_PACKAGE, image.getBounds(), 0));
+						}
+					}
+				} else {
+					if (containsExcludedFiles(bc, pack))
+						img = getImageLabel(getJavaImageDescriptor(JavaPluginImages.DESC_OBJS_EMPTY_PACKAGE, image.getBounds(), 0));
+				}
+			} catch (JavaModelException e) {
+				// problems with package, better don't do anything
+				// can be ignored
+			}
+		}
+
+		if (img != null){			
+			preventRecursion = true;
+			
+			//the Java ProblemsDecorator is not registered in the official
+			//decorator list of eclipse, so we need it to call ourself.
+			//problem: if jdt includes more decorators, we won't know it.
+			img = problemsDecorator.decorateImage(img, element);
+			
+			//apply standard decorators (eg cvs)
+			img = decman.decorateImage(img, element);
+			preventRecursion = false;
+			return img;
+		}
+		return null;
+	}
+	
+	class MyCompositeImageDesc extends CompositeImageDescriptor {
+		private Image fBaseImage;
+
+		private Point fSize;
+
+		public MyCompositeImageDesc(Image baseImage) {
+			this.fBaseImage = baseImage;
+
+			fSize = new Point(baseImage.getBounds().width,
+					baseImage.getBounds().height);
+			//System.out.println("size=" + size);
+		}
+
+		protected void drawCompositeImage(int width, int height) {
+			// To draw a composite image, the base image should be
+			// drawn first (first layer) and then the overlay image
+			// (second layer)
+
+			// Draw the base image using the base image's image data
+			drawImage(fBaseImage.getImageData(), 0, 0);
+
+			// Method to create the overlay image data
+			// Get the image data from the Image store or by other means
+			ImageData overlayImageData = AspectJImages.ADVICE_OVERLAY.getImageDescriptor().getImageData();
+				//adviceDescriptor.getImageData();
+
+			// Overlaying the icon in the top left corner i.e. x and y
+			// coordinates are both zero
+			int xValue = 0;
+			int yValue = 0;
+			drawImage(overlayImageData, xValue, yValue);
+		}
+		
+		/* (non-Javadoc)
+		 * Method declared on Object.
+		 */
+		public boolean equals(Object object) {
+			if (object == null || !MyCompositeImageDesc.class.equals(object.getClass()))
+				return false;
+				
+			MyCompositeImageDesc other= (MyCompositeImageDesc)object;
+			return (fBaseImage.equals(other.fBaseImage) && fSize.equals(other.fSize));
+		}
+		
+		/* (non-Javadoc)
+		 * Method declared on Object.
+		 */
+		public int hashCode() {
+			return fBaseImage.hashCode() | fSize.hashCode();
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see org.eclipse.jface.resource.CompositeImageDescriptor#getSize()
+		 */
+		protected Point getSize() {
+			return fSize;
+		}
+	}
+	
+	public static boolean containsIncludedFiles(IBuildConfiguration bc, IPackageFragment pack){
+		try {
+			// Bug 88477 - JDT may have refreshed the model
+			IResource res = pack.getResource();
+			if(res instanceof IFolder) {
+				IResource[] children = ((IFolder)res).members();
+				for (int i = 0; i < children.length; i++) {
+					IResource resource = children[i];
+					if (resource instanceof IFile) {
+						IFile file = (IFile)resource;
+						if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file.getName())) {
+							if(bc.isIncluded(file)) {
+								return true;
+							}
+						}
+					}
+				}
+			}				
+		} catch (JavaModelException e) {
+			//assume empty
+			// can be ignored
+		} catch (CoreException e) {
+		}	
+		return false;
+	}
+	
+	public static boolean containsExcludedFiles(IBuildConfiguration bc, IPackageFragment pack){
+		try {			
+			// Bug 88477 - JDT may have refreshed the model
+			IResource res = pack.getResource();
+			if(res instanceof IFolder) {
+				IResource[] children = ((IFolder)res).members();
+				for (int i = 0; i < children.length; i++) {
+					IResource resource = children[i];
+					if (resource instanceof IFile) {
+						IFile file = (IFile)resource;
+						if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file.getName())) {
+							if(!bc.isIncluded(file)) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		} catch (JavaModelException e) {
+			//assume empty
+			// can be ignored
+		} catch (CoreException e) {
+		}
+		return false;
+	}
+	
+	private Image getImageLabel(ImageDescriptor descriptor){
+		if (descriptor == null) 
+			return null;	
+		return getRegistry().get(descriptor);
+	}
+	
+	private ImageDescriptorRegistry getRegistry() {
+		if (fRegistry == null) {
+			fRegistry= JavaPlugin.getImageDescriptorRegistry();
+		}
+		return fRegistry;
+	}
+	
+	public static ImageDescriptor getJavaImageDescriptor(ImageDescriptor descriptor, Rectangle rect, int adorflags) {
+		int flags = (rect.width == 16)?JavaElementImageProvider.SMALL_ICONS:0;
+		Point size= useSmallSize(flags) ? JavaElementImageProvider.SMALL_SIZE : JavaElementImageProvider.BIG_SIZE;
+		return new JavaElementImageDescriptor(descriptor, adorflags, size);
+	}
+	
+	private static boolean useSmallSize(int flags) {
+		return (flags & JavaElementImageProvider.SMALL_ICONS) != 0;
+	}
+
+	/**
+	 * @see ILabelDecorator#decorateText
+	 */
+	public String decorateText(String text, Object element)  {
+		if (element instanceof AJCompilationUnit){
+			return text.replaceFirst(".java", ".aj");  //$NON-NLS-1$  //$NON-NLS-2$
+		} else {
+			if (element instanceof IAspectJElement){
+				try {
+					if(((IAspectJElement)element).getJavaProject().getProject().exists()) {
+						IProgramElement.Kind kind = ((IAspectJElement)element).getAJKind();
+						if (!((kind == IProgramElement.Kind.ASPECT) || (kind == IProgramElement.Kind.ADVICE) || (kind == IProgramElement.Kind.POINTCUT) || (kind == IProgramElement.Kind.INTER_TYPE_METHOD) || (kind == IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR))){
+							return text.substring(0, text.length() - 2);
+						}
+					}
+				} catch (JavaModelException e) {
+				}
+			}
+		}
+		return null;
+	}
+	
+	private int computeJavaAdornmentFlags(IJavaElement element) {
+		int flags= 0;
+		if (true && element instanceof IMember) {
+			try {
+				IMember member= (IMember) element;
+				
+				if (element.getElementType() == IJavaElement.METHOD && ((IMethod)element).isConstructor())
+					flags |= JavaElementImageDescriptor.CONSTRUCTOR;
+					
+				int modifiers= member.getFlags();
+				if (Flags.isAbstract(modifiers) && confirmAbstract(member))
+					flags |= JavaElementImageDescriptor.ABSTRACT;
+				if (Flags.isFinal(modifiers) || isInterfaceField(member))
+					flags |= JavaElementImageDescriptor.FINAL;
+				if (Flags.isSynchronized(modifiers) && confirmSynchronized(member))
+					flags |= JavaElementImageDescriptor.SYNCHRONIZED;
+				if (Flags.isStatic(modifiers) || isInterfaceField(member))
+					flags |= JavaElementImageDescriptor.STATIC;
+				
+				if (Flags.isDeprecated(modifiers))
+					flags |= JavaElementImageDescriptor.DEPRECATED;
+				
+				if (member.getElementType() == IJavaElement.TYPE) {
+					if (JavaModelUtil.hasMainMethod((IType) member)) {
+						flags |= JavaElementImageDescriptor.RUNNABLE;
+					}
+				}
+			} catch (JavaModelException e) {
+				// do nothing. Can't compute runnable adornment or get flags
+				// can be ignored
+			}
+		}
+		return flags;
+	}
+	
+	private static boolean confirmAbstract(IMember element) throws JavaModelException {
+		// never show the abstract symbol on interfaces or members in interfaces
+		if (element.getElementType() == IJavaElement.TYPE) {
+			return ((IType) element).isClass();
+		}
+		return element.getDeclaringType().isClass();
+	}
+	
+	private static boolean isInterfaceField(IMember element) throws JavaModelException {
+		// always show the final && static symbol on interface fields
+		if (element.getElementType() == IJavaElement.FIELD) {
+			return element.getDeclaringType().isInterface();
+		}
+		return false;
+	}	
+	
+	private static boolean confirmSynchronized(IJavaElement member) {
+		// Synchronized types are allowed but meaningless.
+		return member.getElementType() != IJavaElement.TYPE;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ProjectBuildConfigurator.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ProjectBuildConfigurator.java
new file mode 100644
index 0000000..dbda779
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/ProjectBuildConfigurator.java
@@ -0,0 +1,261 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.ajdt.internal.ui.preferences.AspectJPreferences;
+import org.eclipse.ajdt.internal.utils.AJDTUtils;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaProject;
+
+/**
+ * @author Luzius Meisser
+ * 
+ * This class manages the Build Configurations of a project. 
+ * 
+ */
+public class ProjectBuildConfigurator implements IProjectBuildConfigurator {
+	private HashMap buildconfigs;
+	private IJavaProject javaProject;
+
+	IFile activeBuildConfiguration;
+	private IBuildConfigurator buildConfigurator;
+	private boolean initialized;
+	
+	public ProjectBuildConfigurator(IJavaProject project) {
+		this.javaProject = project;
+		buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+		buildconfigs = new HashMap();
+	}
+	
+	public void reInit(){
+		initialized = false;
+	}
+	
+	private void init(){
+		if (!initialized){
+			readBuildConfigurationsFromFileSystem();
+			activeBuildConfiguration = getStoredBuildConfiguration();
+			initialized = true;
+		}
+	}
+	
+	private IFile getStoredBuildConfiguration(){
+		IProject project = javaProject.getProject();
+		String configFile = AspectJPreferences.getActiveBuildConfigurationName(project);
+		if ((configFile==null) || configFile.length()==0) {
+			return null;
+		}
+		return project.getFile(configFile);
+	}
+	
+	private void storeActiveBuildConfigurationName(String configName){
+		IProject project = javaProject.getProject();
+		AspectJPreferences.setActiveBuildConfigurationName(project,configName);
+	}
+
+	private void readBuildConfigurationsFromFileSystem() {
+		try {
+			IResource[] files = javaProject.getProject().members(IResource.FILE);
+			for (int i = 0; i < files.length; i++) {
+				if ((files[i].getType() != IResource.FOLDER)
+						&& BuildConfiguration.EXTENSION.equals(files[i]
+								.getFileExtension())
+						&& files[i].exists()) {
+					BuildConfiguration bc;
+					bc = new BuildConfiguration((IFile) files[i], this);
+					buildconfigs.put(files[i], bc);
+				}
+			}
+		} catch (CoreException e) {
+			//Could not read project members, no BuildConfigurations read
+		}
+	}
+
+	public IBuildConfiguration getActiveBuildConfiguration() {
+		makeSureThereIsAtLeastOneActiveConfiguration();
+		return (BuildConfiguration) buildconfigs.get(activeBuildConfiguration);
+	}
+	public void setActiveBuildConfiguration(IBuildConfiguration bc) {
+		if (buildconfigs.containsKey(bc.getFile())) {
+			if(!bc.getFile().exists()) {
+				buildconfigs.remove(bc.getFile());
+				makeSureThereIsAtLeastOneActiveConfiguration();
+			} else {
+				IFile oldActive = activeBuildConfiguration;
+				activeBuildConfiguration = bc.getFile();
+				storeActiveBuildConfigurationName(bc.getFile().getName());
+				bc.update(false);
+				if (!activeBuildConfiguration.equals(oldActive)){
+					try {
+						requestFullBuild(true);
+						activeBuildConfiguration.touch(null);
+					} catch (CoreException e) {
+					}
+				}
+			}
+		}
+	}
+	public IBuildConfiguration getBuildConfiguration(IFile bcFile) {
+		return (BuildConfiguration) buildconfigs.get(bcFile);
+	}
+	
+	private boolean fullbuildrequested;
+	
+	public void requestFullBuild(boolean temp){
+		fullbuildrequested = temp;
+	}
+	
+	public boolean fullBuildRequested(){
+		return fullbuildrequested;
+	}
+	
+	//if active buildconfiguration has changed, updated jdt project entries
+	//should only be called by resource delta visitor, so if you want to update
+	//the build configuration, its better to touch its file than to call this method
+	public void configurationChanged(IBuildConfiguration bc) {
+		if (initialized){
+			if (!buildconfigs.containsKey(bc.getFile())) {
+				buildconfigs.put(bc.getFile(), bc);
+			}
+			if (bc.getFile().equals(activeBuildConfiguration)) {
+				
+				//why do we need to do full builds after build configuration changes?
+				//when doing a normal build, .class files of classes that have been excluded
+				//do not get removed from the bin dir so we don't get errors if excluded classes
+				//are needed by others.
+				requestFullBuild(true);					
+				
+				//update package explorer view
+				AJDTUtils.refreshPackageExplorer();
+			}
+			((BuildConfigurator)buildConfigurator).notifyChangeListeners();
+		}
+	}
+	
+	/**
+	 * @return Returns the project.
+	 */
+	public IJavaProject getJavaProject() {
+		return javaProject;
+	}
+	/**
+	 * @param project
+	 *            The project to set.
+	 */
+	public void setProject(IJavaProject project) {
+		this.javaProject = project;
+	}
+	public IFile[] getConfigurationFiles() {
+		makeSureThereIsAtLeastOneActiveConfiguration();
+		IFile[] z = new IFile[0];
+		return (IFile[]) buildconfigs.keySet().toArray(z);
+	}
+	/**
+	 * @return
+	 */
+	public Collection getBuildConfigurations() {
+		makeSureThereIsAtLeastOneActiveConfiguration();
+		return buildconfigs.values();
+	}
+	public void addBuildConfiguration(IBuildConfiguration bc) {
+		buildconfigs.put(bc.getFile(), bc);
+		((BuildConfigurator)buildConfigurator).notifyChangeListeners();
+	}
+
+	/**
+	 *  
+	 */
+	private void makeSureThereIsAtLeastOneActiveConfiguration() {
+		if (!initialized){
+			init();
+		}
+		if (buildconfigs.size() == 0) {
+			BuildConfiguration nbc = new BuildConfiguration(BuildConfiguration.STANDARD_BUILD_CONFIGURATION_NAME, javaProject, this);
+			buildconfigs.put(nbc.getFile(), nbc);
+		}
+		if ((activeBuildConfiguration == null) || !buildconfigs.containsKey(activeBuildConfiguration)) {
+			// choose the active configuration
+			setActiveBuildConfiguration(getDefaultBuildConfiguration());
+		}
+	}
+	
+	/**
+	 * If there is no preference setting defining which build config should be
+	 * active, we need to pick on from the ones available. Choosing one at
+	 * random wouldn't be helpful, so for consistency we define the rule to be:
+	 * choose build.ajproperties if there is one with that name, otherwise
+	 * choose the first one alphabetically (bug 84310)
+	 * 
+	 * @return the chosen build configuration
+	 */
+	private IBuildConfiguration getDefaultBuildConfiguration() {
+		if (buildconfigs.size()==1) {
+			// hobsons choice
+			return (BuildConfiguration)buildconfigs.values().iterator().next();
+		}
+		IFile first = null;
+		for (Iterator iter = buildconfigs.keySet().iterator(); iter.hasNext();) {
+			IFile file = (IFile) iter.next();
+			if (file.getName().equals(BuildConfiguration.STANDARD_BUILD_CONFIGURATION_FILE)) {
+				return (BuildConfiguration)buildconfigs.get(file);
+			}
+			if (first==null || (file.getName().compareTo(first.getName()) < 0)) {
+				first = file;
+			}
+		}
+		return (BuildConfiguration)buildconfigs.get(first);
+	}
+	
+	/**
+	 * Deletes the specified build configuration.
+	 * If it was the only one, it creates a standard build configuration.
+	 * If it was the active one, the next one gets activated.
+	 * @param bc Build Configuration to delete
+	 */
+	public void removeBuildConfiguration(IBuildConfiguration bc){
+		if (bc.getFile().equals(activeBuildConfiguration))
+			activeBuildConfiguration = null;
+		buildconfigs.remove(bc.getFile());
+		makeSureThereIsAtLeastOneActiveConfiguration();
+		((BuildConfigurator)buildConfigurator).notifyChangeListeners();
+	}
+
+	/**
+	 * @param buildFile
+	 */
+	public void setActiveBuildConfiguration(IFile buildFile) {
+		IBuildConfiguration bc = getBuildConfiguration(buildFile);
+		if (bc == null){
+			bc = new BuildConfiguration(buildFile, this);
+			this.addBuildConfiguration(bc);	
+		}		
+		setActiveBuildConfiguration(bc);
+	}
+
+	/**
+	 * @param file
+	 */
+	public void removeBuildConfiguration(IFile file) {
+		IBuildConfiguration bc = getBuildConfiguration(file);
+		if (bc != null)
+			this.removeBuildConfiguration(bc);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java
new file mode 100644
index 0000000..4fd7db4
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/PropertyPageManager.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *     George Harley  - fix for bugzilla 73317
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ui.internal.dialogs.PropertyPageContributorManager;
+import org.eclipse.ui.internal.dialogs.RegistryPageContributor;
+
+/**
+ * @author Luzius Meisser
+ *
+ * This class can be used to register and unregister jdts project property page.
+ */
+public class PropertyPageManager {
+	private static RegistryPageContributor jdtProjectPropertyPage = null;
+	private static RegistryPageContributor jdtJavaProjectPropertyPage = null;
+	private static boolean jdtPropertyPageActive = true;
+	final static String projectID = "org.eclipse.core.resources.IProject";  //$NON-NLS-1$
+	final static String javaProjectID = "org.eclipse.jdt.core.IJavaProject";  //$NON-NLS-1$
+	final static String buildPathsPageID = "org.eclipse.jdt.ui.propertyPages.BuildPathsPropertyPage";  //$NON-NLS-1$
+	
+	
+	private PropertyPageManager(){}
+	
+	public static void unregisterJDTPropertyPage(){
+		if (jdtProjectPropertyPage == null){
+			extractJDTRegistryPageContributors();
+		}
+		if (isJDTPropertyPageActive()){
+			PropertyPageContributorManager ppcm = PropertyPageContributorManager.getManager();
+			
+			// Get number of contributors prior to attempting the unregistering.
+			int beforeCount = getBuildPathContributorsCount(ppcm);
+			
+			ppcm.unregisterContributor(jdtProjectPropertyPage, projectID);
+			ppcm.unregisterContributor(jdtJavaProjectPropertyPage, javaProjectID);
+			
+			// Get number of contributors after attempting the unregistering.
+			int afterCount = getBuildPathContributorsCount(ppcm);
+			
+			// If the unregistering was successful then the before and after 
+			// counts will differ by 2. If they don't then we got our "IJavaProject"
+			// and "IProject" contributors mixed up. This can happen because when
+			// we set the jdtProjectPropertyPage and jdtJavaProjectPropertyPage
+			// values we (AFAIK) have no way of telling their real objectClass
+			// property value. Re-try the unregistering using the alternative
+			// contributor references.
+			if (afterCount != (beforeCount - 2)) {
+				ppcm.unregisterContributor(jdtProjectPropertyPage, javaProjectID);
+				ppcm.unregisterContributor(jdtJavaProjectPropertyPage, projectID);
+				afterCount = getBuildPathContributorsCount(ppcm);
+			}
+			
+			if (afterCount != (beforeCount - 2)) {
+				AJLog.log("Failed to unregister Java Build Path property pages"); //$NON-NLS-1$
+			}
+			else {
+				AJLog.log("Successfully unregistered Java Build Path property pages"); //$NON-NLS-1$
+			}
+			
+			jdtPropertyPageActive = false;
+		}
+	}
+	
+	/**
+	 * @param ppcm 
+	 * @return
+	 */
+	private static int getBuildPathContributorsCount(
+			PropertyPageContributorManager ppcm) {
+		int count = 0;
+		Iterator iter = ppcm.getContributors().iterator();
+		while (iter.hasNext()) {
+			List v = (List) iter.next();
+			Iterator iter2 = v.iterator();
+			while (iter2.hasNext()) {
+				RegistryPageContributor rpc = (RegistryPageContributor) iter2
+						.next();
+				if (rpc.getPageId().equals(buildPathsPageID)) {
+					count++;
+				}
+			}
+		}
+		return count;
+	}
+
+	public static void registerJDTPropertyPage(){
+		if (jdtProjectPropertyPage == null){
+			extractJDTRegistryPageContributors();
+		}
+		if (!isJDTPropertyPageActive()){
+			PropertyPageContributorManager ppcm = PropertyPageContributorManager.getManager();
+			ppcm.registerContributor(jdtProjectPropertyPage, projectID);
+			ppcm.registerContributor(jdtJavaProjectPropertyPage, javaProjectID);
+			jdtPropertyPageActive = true;
+		}
+	}
+	
+	private static void extractJDTRegistryPageContributors(){
+		List list = new ArrayList(3);
+		PropertyPageContributorManager ppcm = PropertyPageContributorManager.getManager();
+		Iterator iter = ppcm.getContributors().iterator();
+		while (iter.hasNext()){
+			List v = (List)iter.next();
+			Iterator iter2 = v.iterator();
+			while(iter2.hasNext()){
+				RegistryPageContributor rpc = (RegistryPageContributor)iter2.next();
+				if (rpc.getPageId().equals(buildPathsPageID)){
+					list.add(rpc);
+				}
+			}
+		}
+		
+		// There does not seem to be a way of determining the objectClass
+		// attribute of the contributor. That is, we cannot tell which of 
+		// the contributors is for the "org.eclipse.jdt.core.IJavaProject"
+		// objectClass and which is for "org.eclipse.core.resources.IProject".
+		// Being able to distinguish them is essential when it comes to 
+		// attempting to unregister the contributions.
+		jdtProjectPropertyPage = (RegistryPageContributor)list.get(0);
+		jdtJavaProjectPropertyPage = (RegistryPageContributor)list.get(1);
+		jdtPropertyPageActive = true;
+	}
+	
+	public static boolean isJDTPropertyPageActive(){
+		return jdtPropertyPageActive;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/UpdateJob.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/UpdateJob.java
new file mode 100644
index 0000000..fe64a02
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/UpdateJob.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Common Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+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;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+public class UpdateJob extends Job {
+	public static final int BUILD_CONFIG_CHANGED = 1;
+
+	public static final int BUILD_CONFIG_REMOVED = 2;
+
+	public static final int CLASSPATH_CHANGED = 3;
+
+	public static final int SOURCE_ADDED = 4;
+
+	public static final int FILE_MOVED = 5;
+
+	private int type;
+
+	private IResource myRes;
+
+	private IResource myRes2;
+
+	private final IBuildConfigurator myBCor;
+
+	/**
+	 *  
+	 */
+	public UpdateJob(IBuildConfigurator myBCor, int type, IResource myRes) {
+		super(UIMessages.UpdateJob_name);
+		setRule(myRes.getProject());
+		setSystem(true);
+		setPriority(Job.SHORT);
+		this.myBCor = myBCor;
+		this.type = type;
+		this.myRes = myRes;
+	}
+
+	public UpdateJob(IBuildConfigurator myBCor, int type, IResource myRes,
+			IResource myRes2) {
+		super(UIMessages.UpdateJob_name);
+		setRule(myRes.getProject());
+		setSystem(true);
+		setPriority(Job.SHORT);
+		this.myBCor = myBCor;
+		this.type = type;
+		this.myRes = myRes;
+		this.myRes2 = myRes2;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	protected IStatus run(IProgressMonitor monitor) {
+		switch (type) {
+		case BUILD_CONFIG_CHANGED:
+			buildConfigChanged();
+			break;
+		case BUILD_CONFIG_REMOVED:
+			buildConfigRemoved();
+			break;
+		case CLASSPATH_CHANGED:
+			classpathChanged();
+			break;
+		case SOURCE_ADDED:
+			sourceAdded();
+			break;
+		case FILE_MOVED:
+			fileMoved();
+			break;
+		}
+		return Status.OK_STATUS;
+	}
+
+	/**
+	 *  
+	 */
+	private void sourceAdded() {
+		IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+				.getProject());
+		if (pbc != null) {
+			IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+			if (bc != null) {
+				if (!bc.isIncluded(myRes))
+					bc.update(false);
+			}
+		}
+	}
+
+	/**
+	 *  
+	 */
+	private void classpathChanged() {
+		IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+				.getProject());
+		if (pbc != null) {
+			try {
+				IJavaProject jp = JavaCore.create(myRes.getProject());
+				IClasspathEntry[] cpes = jp.getRawClasspath();
+				ArrayList sourcePathes = new ArrayList();
+				for (int i = 0; i < cpes.length; i++) {
+					if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+						//make path project relative by
+						// removing first segment
+						sourcePathes.add(cpes[i].getPath().removeFirstSegments(
+								1));
+					}
+				}
+				Iterator iter = pbc.getBuildConfigurations().iterator();
+				while (iter.hasNext()) {
+					((BuildConfiguration) iter.next())
+							.updateSourceFolders(sourcePathes);
+				}
+			} catch (JavaModelException e) {
+			}
+		}
+	}
+
+	/**
+	 *  
+	 */
+	private void buildConfigRemoved() {
+		IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+				.getProject());
+		if (pbc != null) {
+			((ProjectBuildConfigurator)pbc).removeBuildConfiguration((IFile) myRes);
+		}
+	}
+
+	/**
+	 *  
+	 */
+	private void buildConfigChanged() {
+		IProjectBuildConfigurator pbc = myBCor.getProjectBuildConfigurator(myRes
+				.getProject());
+		if (pbc != null) {
+			IBuildConfiguration bc = pbc.getBuildConfiguration((IFile) myRes);
+			if (bc != null) {
+				bc.update(true);
+				((ProjectBuildConfigurator)pbc).configurationChanged(bc);
+			}
+		}
+	}
+
+	private void fileMoved() {
+		if ((myRes2 == null) || (myRes == null))
+			return;
+		if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(myRes2.getName())
+				&& CoreUtils.ASPECTJ_SOURCE_FILTER.accept(myRes
+						.getName())) {
+			IProjectBuildConfigurator pbc = myBCor
+					.getProjectBuildConfigurator(myRes.getProject());
+			if (pbc != null) {
+				IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+				// reread build config file to update the include/exclude status
+				bc.update(true);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/Util.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/Util.java
new file mode 100644
index 0000000..e04f732
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/Util.java
@@ -0,0 +1,361 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * @author Luzius Meisser
+ *
+ */
+public class Util {
+    
+    private static String OS_INDEPENDENT_LINE_SEPARATOR = System
+			.getProperty("line.separator"); //$NON-NLS-1$
+    
+	
+    // LstSupport
+	/**
+     * Get the path of the file <code>file</code> relative to 
+     * the location <code>fromDir</code>. 
+	 * @param file 
+	 * @param fromDir
+	 * @return relative path in a <code>java.lang.String</code>
+	 */
+	public static String getRelativePathString(IPath file, IPath fromDir) {
+		String result = null;
+
+		if (file != null && fromDir != null) {
+            // Check for identical inputs 
+            if (file.equals(fromDir)) {
+                result = "."; //$NON-NLS-1$
+            }// end if identical
+            else {
+                List fromList;
+                List fileList;
+                fromList = getPathList(fromDir.toFile());
+                fileList = getPathList(file.toFile());
+                result = matchPathLists(fromList, fileList);
+            }// end else different
+		}// end if inputs are usable
+		return result;
+	}
+
+    /**
+     * Get the path of the file <code>file</code> relative to 
+     * the location <code>fromDir</code>. 
+     * @param file 
+     * @param fromDir
+     * @return relative path in a <code>java.lang.String</code>
+     */
+    public static String getRelativePathString(String file, String fromDir) {
+		String result = null;
+
+		if (file != null && fromDir != null) {
+			return getRelativePathString(new Path(file), new Path(fromDir));
+		}// end if inputs are usable
+		return result;
+	}
+    
+    /**
+	 *  
+	 */
+	private static List getPathList(File f) {
+		List l = new ArrayList();
+		File r;
+		try {
+			r = f.getCanonicalFile();
+			while (r != null) {
+				l.add(r.getName());
+				r = r.getParentFile();
+			}
+		} catch (IOException e) {
+			l = null;
+		}
+		return l;
+	}
+
+	/**
+     * 
+	 */
+	private static String matchPathLists(List fromList, List toList) {
+		int i;
+		int j;
+		String result = ""; //$NON-NLS-1$
+        
+		i = fromList.size() - 1;
+		j = toList.size() - 1;
+
+		// First, get rid of the common root
+		while ((i >= 0) && (j >= 0) &&
+                (fromList.get(i).equals(toList.get(j)))) {
+			i--;
+			j--;
+		}// end while still finding common components 
+
+		// For each remaining level in the home path add
+        // a double dot (..)
+		for (; i >= 0; i--) {
+			result += ".." + AspectJPlugin.NON_OS_SPECIFIC_SEPARATOR; //$NON-NLS-1$
+		}// end for each remaining level 
+
+		// for each level in the file path, add the path
+		for (; j >= 1; j--) {
+			result += toList.get(j) +
+                AspectJPlugin.NON_OS_SPECIFIC_SEPARATOR;
+		}
+
+		// Return the file name
+		result += toList.get(j);
+		return result;
+	}
+    
+    /**
+     * If input file contains no links to other lst files then just returns
+     * the IPath to the original file. Otherwise, creates a new file in the 
+     * same directory as the original file with the extension ".inlined.lst"
+     * and returns an IPath for the new file. The original .lst file is 
+     * left remaining on disk with its original name.
+     * @param lstFile
+     * @return
+     * @throws FileNotFoundException
+     */
+    public static IPath getInlinedLstFile(IPath lstFile)
+			throws FileNotFoundException {
+		IPath result = lstFile;
+
+		if (lstFile != null) {
+            // Quick check that we have a bona fide file to work with
+			if (!lstFile.toFile().exists()) {
+				throw new FileNotFoundException(lstFile.toOSString()
+						+ " " + UIMessages.buildConfig_notFound); //$NON-NLS-1$
+			}
+            
+			// Quick check to see if file has a line starting with the
+			// link symbol "@". If not, just return the input IPath to
+			// the caller.
+			if (lstFileContainsLinks(lstFile)) {
+				File resultFile = new File(getInlinedFileName(lstFile
+						.toOSString()));
+				try {
+					BufferedWriter bw = new BufferedWriter(new FileWriter(
+							resultFile));
+					writeInlinedLstFileToBuffer(lstFile.toFile(), bw);
+					bw.close();
+					result = new Path(resultFile.getAbsolutePath());
+				} catch (IOException e) {
+				}
+			}// end if a link found
+		}// end if input is usable
+
+		return result;
+	}
+    
+    public static String getInlinedFileName(String originalName) {
+		String result = originalName;
+		if (originalName != null) {
+			String tmp1 = originalName.substring(0, originalName
+					.lastIndexOf('.'));
+			String tmp2 = originalName.substring(originalName.lastIndexOf('.'));
+			result = tmp1 + ".inlined" + tmp2;  //$NON-NLS-1$
+		}// end if input is usable
+		return result;
+	}
+    
+    /**
+	 * @param file
+	 * @param bos
+	 * @throws FileNotFoundException
+	 */
+	private static void writeInlinedLstFileToBuffer(File file,
+			BufferedWriter bw) throws FileNotFoundException {
+        // Open up the input file
+        BufferedReader in = new BufferedReader(new FileReader(file));   
+        String line = null;
+        try {
+            while ((line = in.readLine()) != null) {
+                line = line.trim();
+                if (!line.startsWith("@")) { //$NON-NLS-1$
+                    bw.write(line);
+                    bw.newLine();
+                }// end if no lst link reference found on line
+                else {
+                    // Get the location of the linked file. If it 
+                    // exists then recursively call it from here 
+                    // (passing in the original BufferedWriter).
+                    String linkedFilePath = line.substring(1);
+                    File linkedFile = new File(linkedFilePath);
+                    if (linkedFile.isAbsolute()) {
+                    	if (linkedFile.exists()) {
+                            writeInlinedLstFileToBuffer(linkedFile, bw);
+                        }
+                    }// end if file linking to is absolute
+                    else {
+                        // Don't panic. Need to obtain an absolute path
+						// to the linked file.
+						linkedFile = new File(file.getParentFile()
+								.getAbsolutePath()
+								+ AspectJPlugin.NON_OS_SPECIFIC_SEPARATOR
+								+ linkedFilePath);
+						if (linkedFile.exists()) {
+							writeInlinedLstFileToBuffer(linkedFile, bw);
+						}
+                    }// end else linking using relative path
+                }// else line contains a link reference
+            }// end while more lines to read
+        }
+        catch (IOException e) {
+        }
+	}
+
+	/**
+	 * @param lstFile
+	 * @throws FileNotFoundException
+	 */
+	private static boolean lstFileContainsLinks(IPath lstFile)
+			throws FileNotFoundException {
+		boolean result = false;
+		String path = lstFile.toOSString();
+		BufferedReader in = new BufferedReader(new FileReader(path));
+		String line = null;
+		try {
+			while ((line = in.readLine()) != null) {
+				line = line.trim();
+				if (line.startsWith("@")) { //$NON-NLS-1$
+					result = true;
+					break;
+				}// end if lst link reference found
+			}
+		} catch (IOException e) {
+		}
+		return result;
+	}
+
+	/**
+	 * @param file
+	 * @param files
+	 * @param options
+	 * @param links
+	 * @throws FileNotFoundException
+	 */
+    public static void getLstFileContents(
+            IPath file,
+            List files,
+            List options,
+			List links) throws FileNotFoundException {
+    	// Check that we have been passed in the necessary
+        // INOUT instances.
+        if (file != null &&
+                files != null &&
+                options != null &&
+                links != null) {
+            String path = file.toOSString();
+            BufferedReader in = new BufferedReader(new FileReader(path));
+            String line = null;
+            try {
+				while ((line = in.readLine()) != null) {
+                    line = line.trim();
+                    if (line.startsWith("@")) { //$NON-NLS-1$
+                        links.add(line);
+                    }// end if lst link reference found
+                    else if (line.startsWith("-")) { //$NON-NLS-1$
+                        // Option. Determine whether or not
+						// the option requires an argument.
+						if (AjcOptionsChecker.optionWithArg(line)) {
+							// Grab the next line
+							String nextLine = in.readLine();
+							if (nextLine != null) {
+								options.add(line
+										+ OS_INDEPENDENT_LINE_SEPARATOR
+										+ nextLine.trim());
+							}// end if
+							else {
+								// Just add the option anyway
+								options.add(line);
+							}// end else arg expected but none found
+						}// end if argument expected
+                        else {
+                            options.add(line);
+                        }// end else no argument expected
+                    }// end else if option found
+                    else {
+                        // Source file reference ?
+                        // Check that the file actually exists
+                        // before adding to the files list ??
+                    	if (!line.equals("")) //$NON-NLS-1$
+                    		files.add(line);
+                    }// end else a possible source file reference found
+				}// while more lines to read
+			} catch (IOException e) {
+			}
+		}// end if valid inputs
+	}
+    
+    /**
+     * Helper class
+     */
+    static class AjcOptionsChecker {
+        private static Set optionsWithArgs;
+        
+        static {
+            initialiseOptionsWithArgs();
+        }// end static initialisation block
+
+        public static boolean optionWithArg(String option) {
+            boolean result = false;
+            if (optionsWithArgs.contains(option)) {
+            	result = true;
+            }
+            return result;
+        }
+        
+		/**
+		 * 
+		 */
+		private static void initialiseOptionsWithArgs() {
+			optionsWithArgs = new HashSet();
+            optionsWithArgs.add("-inpath"); //$NON-NLS-1$
+            optionsWithArgs.add("-injars"); //$NON-NLS-1$
+            optionsWithArgs.add("-aspectpath"); //$NON-NLS-1$
+            optionsWithArgs.add("-outjar"); //$NON-NLS-1$
+            optionsWithArgs.add("-argfile"); //$NON-NLS-1$
+            optionsWithArgs.add("-sourceroots"); //$NON-NLS-1$
+            optionsWithArgs.add("-Xlintfile"); //$NON-NLS-1$
+            optionsWithArgs.add("-cp"); //$NON-NLS-1$
+            optionsWithArgs.add("-classpath"); //$NON-NLS-1$
+            optionsWithArgs.add("-bootclasspath"); //$NON-NLS-1$
+            optionsWithArgs.add("-d"); //$NON-NLS-1$
+            optionsWithArgs.add("-encoding"); //$NON-NLS-1$
+            optionsWithArgs.add("-source"); //$NON-NLS-1$
+            optionsWithArgs.add("-target"); //$NON-NLS-1$
+            optionsWithArgs.add("-log"); //$NON-NLS-1$
+            optionsWithArgs.add("-repeat"); //$NON-NLS-1$
+            optionsWithArgs.add("-inpath"); //$NON-NLS-1$
+		}
+    }// end class AjcOptionsChecker
+    
+    // End LstSupport
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ActivateAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ActivateAction.java
new file mode 100644
index 0000000..b47c6a8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ActivateAction.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.BuildProperties;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * This action is triggered from a popup menu on a build configuration
+ * file. It makes the target the current build config file for the project.
+ */
+public class ActivateAction implements IWorkbenchWindowActionDelegate {
+
+	private IFile currentlySelectedBuildFile = null;
+	private IBuildConfigurator buildConfigurator;
+
+	public ActivateAction(){
+		buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+	}
+	
+	public static BuildProperties buildP;
+	
+	/**
+	 *  Executed when button clicked or popup menu "Select this build file" clicked
+	 */
+	public void run(IAction action) {
+
+		if (currentlySelectedBuildFile != null){
+			IProjectBuildConfigurator pbc = buildConfigurator.getProjectBuildConfigurator(currentlySelectedBuildFile.getProject());
+			if (pbc != null){
+				pbc.setActiveBuildConfiguration(currentlySelectedBuildFile);
+			}
+		}
+	}
+
+	/**
+	 * Selection has changed - if we've selected a build file then remember it
+	 * as the new project build config.
+	 */
+	public void selectionChanged(IAction action, ISelection selection) {
+
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+			Object first = structuredSelection.getFirstElement();
+			if (first instanceof IFile) {
+				currentlySelectedBuildFile = (IFile) first;
+			}
+		}
+	}
+
+	/**
+	 * From IWorkbenchWindowActionDelegate
+	 */
+	public void dispose() {}
+
+	/**
+	 * From IWorkbenchWindowActionDelegate
+	 */
+	public void init(IWorkbenchWindow window) {
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/BuildConfigurationChangeAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/BuildConfigurationChangeAction.java
new file mode 100644
index 0000000..1e488dd
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/BuildConfigurationChangeAction.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.internal.buildconfig.IBuildConfigurationChangedListener;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+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;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IActionDelegate;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * @author Luzius Meisser
+ *  
+ */
+public abstract class BuildConfigurationChangeAction implements
+		IObjectActionDelegate, IBuildConfigurationChangedListener {
+
+	protected IAction myAction;
+
+	protected IStructuredSelection strucSel;
+
+	protected IBuildConfigurator buildConfigurator;
+
+	protected String actionText;
+
+	/**
+	 * Constructor for Action1.
+	 */
+	public BuildConfigurationChangeAction() {
+		super();
+		buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+		((BuildConfigurator)buildConfigurator).addBuildConfigurationChangedListener(this);
+	}
+
+	ArrayList changedBCs;
+
+	/**
+	 * @see IActionDelegate#run(IAction)
+	 */
+
+	public void run(IAction action) {
+		changedBCs = new ArrayList();
+		Object mySel;
+		IProjectBuildConfigurator pbc = buildConfigurator
+				.getActiveProjectBuildConfigurator();
+
+		if (pbc != null) {
+			IProjectBuildConfigurator resourcepbc;
+			Iterator mySelIter = strucSel.iterator();
+			ArrayList itemsToManipulate = new ArrayList();
+			while (mySelIter.hasNext()) {
+				mySel = mySelIter.next();
+
+				if (mySel instanceof IJavaElement) {
+					try {
+						mySel = ((IJavaElement) mySel)
+								.getCorrespondingResource();
+					} catch (JavaModelException e) {
+						mySel = null;
+					}
+				}
+				if (mySel instanceof IResource) {
+					IResource res = (IResource) mySel;
+					resourcepbc = buildConfigurator
+							.getProjectBuildConfigurator(res.getProject());
+					if (pbc == resourcepbc) {
+						itemsToManipulate.add(res);
+					}
+				}
+			}
+			doMySpecificAction(pbc.getActiveBuildConfiguration(),
+					itemsToManipulate);
+		}
+
+	}
+	
+	protected abstract Job getJob(final IBuildConfiguration bc, final List fileList);
+
+	private void doMySpecificAction(IBuildConfiguration bc, List fileList) {
+		Job job = getJob(bc, fileList);
+		job.setPriority(Job.SHORT);
+		job.setRule(bc.getFile().getProject());
+		job.schedule();
+	}
+
+	/**
+	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+	 */
+	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+
+	}
+
+	public void buildConfigurationChanged(final IProjectBuildConfigurator pbc) {
+		if (pbc != null) {
+			myAction.setEnabled(true);
+			Job job = new Job(UIMessages.buildConfigurationChangeAction_job_name) {
+				protected IStatus run(IProgressMonitor monitor) {
+					IBuildConfiguration bc = pbc.getActiveBuildConfiguration();
+					myAction.setText(actionText.replaceAll("%bcname", bc //$NON-NLS-1$
+							.getName()));
+					return Status.OK_STATUS;
+				}
+			};
+			job.setPriority(Job.SHORT);
+			job.setRule(pbc.getJavaProject().getProject());
+			job.schedule();
+		} else {
+			myAction.setEnabled(false);
+		}
+	}
+
+	abstract boolean isObjectApplicable(Object o);
+
+	protected boolean isApplicable(Object sel) {
+		if (sel instanceof IPackageFragment) {
+			try {
+				IPackageFragment pack = ((IPackageFragment) sel);
+				Object[] children = pack.getChildren();
+				for (int i = 0; i < children.length; i++) {
+					if (isApplicable(children[i]))
+						return true;
+				}
+
+				children = pack.getNonJavaResources();
+				for (int i = 0; i < children.length; i++) {
+					if (isApplicable(children[i]))
+						return true;
+				}
+
+			} catch (CoreException e) {
+				//if this function fails, include/exlude files will fail as
+				// well so deactivate these acitons
+				return false;
+			}
+		} else {
+			return isObjectApplicable(sel);
+		}
+		return false;
+	}
+
+	protected boolean isApplicable(IStructuredSelection ssel) {
+		Iterator mySelIter = ssel.iterator();
+		while (mySelIter.hasNext()) {
+			Object sel = mySelIter.next();
+			if (isApplicable(sel))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
+	 */
+	public void selectionChanged(IAction action, ISelection selection) {
+		if (myAction == null) {
+			myAction = action;
+			IProjectBuildConfigurator pbc = buildConfigurator
+					.getActiveProjectBuildConfigurator();
+			if (pbc != null) {
+				myAction.setText(actionText.replaceAll("%bcname", pbc //$NON-NLS-1$
+						.getActiveBuildConfiguration().getName()));
+			}
+		}
+		if (selection instanceof IStructuredSelection) {
+			strucSel = (IStructuredSelection) selection;
+			action.setEnabled(isApplicable(strucSel));
+		} else {
+			strucSel = null;
+			action.setEnabled(false);
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExcludeAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExcludeAction.java
new file mode 100644
index 0000000..ca7e4a1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExcludeAction.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import java.util.List;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.ui.ajde.ErrorHandler;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+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;
+import org.eclipse.jdt.core.ICompilationUnit;
+
+/**
+ * @author Luzius Meisser
+ *  
+ */
+public class ExcludeAction extends BuildConfigurationChangeAction {
+	public ExcludeAction() {
+		super();
+		actionText = UIMessages.BCLabels_ExcludeAction;
+	}
+
+	protected Job getJob(final IBuildConfiguration bc,
+			final List fileList) {
+		return new Job(UIMessages.excludeAction_job_name) {
+			protected IStatus run(IProgressMonitor monitor) {
+				try {
+					((BuildConfiguration)bc).excludeFiles(fileList);
+				} catch (CoreException e) {
+					ErrorHandler.handleAJDTError(
+									UIMessages.buildConfig_exceptionIncluding,
+									e);
+				}
+				return Status.OK_STATUS;
+			}
+		};
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ajdt.buildconfigurator.popup.actions.BuildConfigurationChangeAction#isApplicable(java.lang.Object)
+	 */
+	boolean isObjectApplicable(Object o) {
+		try {
+			if (o instanceof ICompilationUnit) {
+				o = ((ICompilationUnit) o).getCorrespondingResource();
+			}
+			if (o instanceof IFile) {
+				IFile file = (IFile) o;
+				if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file
+						.getName())) {
+					IProjectBuildConfigurator pbc = buildConfigurator
+							.getProjectBuildConfigurator(file.getProject());
+					if (pbc != null)
+						return pbc.getActiveBuildConfiguration().isIncluded(
+								file);
+				}
+			}
+		} catch (CoreException e) {
+			// assume non-aj-project
+		}
+		return false;
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExportAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExportAction.java
new file mode 100644
index 0000000..d155ac7
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ExportAction.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * This action is triggered from a popup menu on a build configuration
+ * file. It makes the target the current build config file for the project.
+ */
+public class ExportAction implements IWorkbenchWindowActionDelegate {
+
+
+	private IFile currentlySelectedBuildFile = null;
+	private IBuildConfigurator buildConfigurator;
+
+	public ExportAction(){
+		buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+	}
+	
+	
+	/**
+	 *  Executed when button clicked or popup menu "Select this build file" clicked
+	 */
+	public void run(IAction action) {
+
+		if (currentlySelectedBuildFile != null){
+			IProjectBuildConfigurator pbc = buildConfigurator.getProjectBuildConfigurator(currentlySelectedBuildFile.getProject());
+			if (pbc != null){
+				IBuildConfiguration bc = pbc.getBuildConfiguration(currentlySelectedBuildFile);
+				if (bc != null){
+					((BuildConfiguration)bc).writeLstFile();
+				}
+			}
+		}
+	}
+
+	/**
+	 * Selection has changed - if we've selected a build file then remember it
+	 * as the new project build config.
+	 */
+	public void selectionChanged(IAction action, ISelection selection) {
+
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+			Object first = structuredSelection.getFirstElement();
+			if (first instanceof IFile) {
+				currentlySelectedBuildFile = (IFile) first;
+			}
+		}
+	}
+
+	/**
+	 * From IWorkbenchWindowActionDelegate
+	 */
+	public void dispose() {}
+
+	/**
+	 * From IWorkbenchWindowActionDelegate
+	 */
+	public void init(IWorkbenchWindow window) {
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ImportAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ImportAction.java
new file mode 100644
index 0000000..e3ed358
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/ImportAction.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * This action is triggered from a popup menu on a build configuration
+ * file. It makes the target the current build config file for the project.
+ */
+public class ImportAction implements IWorkbenchWindowActionDelegate {
+
+	private IFile currentlySelectedBuildFile = null;
+	private IBuildConfigurator buildConfigurator;
+
+	public ImportAction(){
+		buildConfigurator = DefaultBuildConfigurator.getBuildConfigurator();
+	}
+	
+	
+	/**
+	 *  Executed when button clicked or popup menu "Select this build file" clicked
+	 */
+	public void run(IAction action) {
+
+		if (currentlySelectedBuildFile != null){
+			IProjectBuildConfigurator pbc = buildConfigurator.getProjectBuildConfigurator(currentlySelectedBuildFile.getProject());
+			if (pbc != null){
+				Shell shell = AspectJUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell();
+				new BuildConfiguration(currentlySelectedBuildFile, shell, pbc);
+			}
+		}
+	}
+
+	/**
+	 * Selection has changed - if we've selected a build file then remember it
+	 * as the new project build config.
+	 */
+	public void selectionChanged(IAction action, ISelection selection) {
+
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+			Object first = structuredSelection.getFirstElement();
+			if (first instanceof IFile) {
+				currentlySelectedBuildFile = (IFile) first;
+			}
+		}
+	}
+
+	/**
+	 * From IWorkbenchWindowActionDelegate
+	 */
+	public void dispose() {}
+
+	/**
+	 * From IWorkbenchWindowActionDelegate
+	 */
+	public void init(IWorkbenchWindow window) {
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/IncludeAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/IncludeAction.java
new file mode 100644
index 0000000..ead3d78
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/actions/IncludeAction.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.actions;
+
+import java.util.List;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+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;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+/**
+ * @author Luzius Meisser
+ *  
+ */
+public class IncludeAction extends BuildConfigurationChangeAction {
+
+	public IncludeAction() {
+		super();
+		actionText = UIMessages.BCLabels_IncludeAction;
+	}
+
+	protected Job getJob(final IBuildConfiguration bc,
+			final List fileList) {
+		return new Job(UIMessages.includeAction_job_name) {
+			protected IStatus run(IProgressMonitor monitor) {
+				((BuildConfiguration)bc).includeFiles(fileList);
+				return Status.OK_STATUS;
+			}
+		};
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ajdt.buildconfigurator.popup.actions.BuildConfigurationChangeAction#isApplicable(java.lang.Object)
+	 */
+	boolean isObjectApplicable(Object o) {
+		try {
+			if (o instanceof ICompilationUnit) {
+				o = ((ICompilationUnit) o).getCorrespondingResource();
+			}
+			if (o instanceof IFile) {
+				IFile file = (IFile) o;
+				if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file
+						.getName())) {
+					IProjectBuildConfigurator pbc = buildConfigurator
+						.getProjectBuildConfigurator(file.getProject());
+					if ((pbc!=null) && pbc.getActiveBuildConfiguration().isIncluded(
+							file)) {
+						return false;
+					}
+					
+					// the file is not currently included but we only give the
+					// option to include it if it is contained in a source folder
+					IJavaProject jp = JavaCore.create(file.getProject());
+					IClasspathEntry[] cpes = jp.getRawClasspath();
+					IPath fp = file.getFullPath();
+					for (int i = 0; i < cpes.length; i++) {
+						if (cpes[i].getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+							IPath p = cpes[i].getPath();
+							if (p.isPrefixOf(fp)) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		} catch (CoreException e) {
+			// assume non-aj-project, do nothing
+			// can be ignored
+		}
+		return false;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildContentsSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildContentsSection.java
new file mode 100644
index 0000000..c53de49
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildContentsSection.java
@@ -0,0 +1,724 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Common Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildModel;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.IModelChangedListener;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+import org.eclipse.ajdt.pde.internal.ui.editor.TableSection;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+public abstract class BuildContentsSection extends TableSection
+		implements
+			IModelChangedListener,
+			IResourceChangeListener,
+			IResourceDeltaVisitor {
+
+	protected CheckboxTreeViewer fTreeViewer;
+	private boolean fDoRefresh = false;
+	protected IProject fProject;
+	protected IBuildModel fBuildModel;
+	protected IResource fOriginalResource, fParentResource;
+	protected boolean isChecked;
+
+	public class TreeContentProvider extends DefaultContentProvider
+			implements
+				ITreeContentProvider {
+
+		public Object[] getFilteredChildren(IContainer parent) {
+			if (parent.exists()) {
+				try{
+					IResource[] res = parent.members();
+					ArrayList children = new ArrayList();
+					for (int i=0; i<res.length; i++){
+						if (res[i] instanceof IFolder){
+							IJavaProject jp =JavaCore.create(res[i].getProject());
+							if (jp != null){
+								addElementsOnClasspath(children, jp, res[i]);
+							}
+						} else {
+							if (CoreUtils.ASPECTJ_SOURCE_FILTER.accept(res[i].getName()))
+								children.add(res[i]);
+						}
+	
+					}
+					return children.toArray();
+				} catch (CoreException e) {
+				}
+			}
+			return new Object[0];
+		}
+		
+		private void addElementsOnClasspath(List list, IJavaProject jp, IResource res){
+			if (jp.isOnClasspath(res)){
+				list.add(res);
+				return;
+			}
+			if (res.getType() == IResource.FOLDER){
+				try {
+					IResource[] mems = ((IFolder)res).members();
+					for (int i=0; i<mems.length; i++){
+						if (mems[i].getType() == IResource.FOLDER)
+							addElementsOnClasspath(list, jp, mems[i]);
+					}
+				} catch (CoreException e) {
+				}
+			}
+		}
+		
+		public Object[] getElements(Object parent) {
+			if (parent instanceof IContainer) {
+				return getFilteredChildren((IContainer)parent);
+			}
+			return new Object[0];
+		}
+
+		/**
+		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
+		 */
+		public Object[] getChildren(Object parent) {
+			if (parent instanceof IContainer)
+				return getFilteredChildren((IContainer)parent);
+			return new Object[0];
+		}
+
+		public Object[] getFolderChildren(Object parent) {
+			IResource[] members = null;
+			try {
+				if (!(parent instanceof IFolder))
+					return new Object[0];
+				members = ((IFolder) parent).members();
+				ArrayList results = new ArrayList();
+				for (int i = 0; i < members.length; i++) {
+					if ((members[i].getType() == IResource.FOLDER)) {
+						results.add(members[i]);
+					}
+				}
+				return results.toArray();
+			} catch (CoreException e) {
+			}
+			return new Object[0];
+		}
+
+		/**
+		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
+		 */
+		public Object getParent(Object element) {
+			if (element != null && element instanceof IResource) {
+				return ((IResource) element).getParent();
+			}
+			return null;
+		}
+
+		/**
+		 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
+		 */
+		public boolean hasChildren(Object element) {
+			if (element instanceof IContainer)
+				return getChildren(element).length > 0;
+			return false;
+		}
+	}
+	protected void createViewerPartControl(Composite parent, int style, int span, FormToolkit toolkit) {
+		MenuManager popupMenuManager = new MenuManager();
+		IMenuListener listener = new IMenuListener() {
+			public void menuAboutToShow(IMenuManager mng) {
+				fillContextMenu(mng);
+			}
+		};
+		popupMenuManager.addMenuListener(listener);
+		popupMenuManager.setRemoveAllWhenShown(true);
+		Control control = fTreeViewer.getControl();
+		Menu menu = popupMenuManager.createContextMenu(control);
+		control.setMenu(menu);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.editor.StructuredViewerSection#fillContextMenu(org.eclipse.jface.action.IMenuManager)
+	 */
+	protected void fillContextMenu(IMenuManager manager) {
+		manager.add(getPage().getPDEEditor().getContributor().getRevertAction());
+		getPage().getPDEEditor().getContributor().contextMenuAboutToShow(
+				manager, false);
+	}
+	private IBuildModel getBuildModel() {
+		InputContext context = getPage().getPDEEditor().getContextManager()
+				.findContext(BuildInputContext.CONTEXT_ID);
+		return (IBuildModel) context.getModel();
+	}
+
+	public BuildContentsSection(PDEFormPage page, Composite parent) {
+		super(page, parent, Section.DESCRIPTION, new String[0]);
+		PDEPlugin.getWorkspace().addResourceChangeListener(this);
+	}
+
+	public void createClient(final Section section, FormToolkit toolkit) {
+		Composite container = createClientContainer(section, 2, toolkit);
+		fBuildModel = getBuildModel();
+		if (fBuildModel.getUnderlyingResource() != null)
+			fProject = fBuildModel.getUnderlyingResource().getProject();
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = layout.marginWidth = 2;
+		container.setLayout(layout);
+		fTreeViewer = new CheckboxTreeViewer(toolkit.createTree(container,
+				SWT.CHECK));
+		fTreeViewer.setContentProvider(new TreeContentProvider());
+		fTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
+		fTreeViewer.setAutoExpandLevel(0);
+		fTreeViewer.addCheckStateListener(new ICheckStateListener() {
+
+			public void checkStateChanged(final CheckStateChangedEvent event) {
+				final Object element = event.getElement();
+				BusyIndicator.showWhile(section.getDisplay(), new Runnable() {
+
+					public void run() {
+						if (element instanceof IFile) {
+							IFile file = (IFile) event.getElement();
+							handleCheckStateChanged(file, event.getChecked());
+						} else if (element instanceof IFolder) {
+							IFolder folder = (IFolder) event.getElement();
+							handleCheckStateChanged(folder, event.getChecked());
+						}
+					}
+				});
+			}
+		});
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.heightHint = 100;
+		gd.widthHint = 100;
+		fTreeViewer.getTree().setLayoutData(gd);
+		initialize();
+		initializeCheckState();
+		toolkit.paintBordersFor(container);
+		createViewerPartControl(container, SWT.FULL_SELECTION, 2, toolkit);
+		section.setClient(container);
+	}
+
+	public void enableSection(boolean enable) {
+		fTreeViewer.getTree().setEnabled(enable);
+	}
+
+	protected void handleCheckStateChanged(IResource resource, boolean checked) {
+		fOriginalResource = resource;
+		isChecked = checked;
+		boolean wasTopParentChecked = isIncluded(fOriginalResource
+				.getParent());
+		if (!isChecked) {
+			resource = handleAllUnselected(resource, resource.getName());
+		}
+		fParentResource = resource;
+		handleBuildCheckStateChange(wasTopParentChecked);
+	}
+
+	protected IResource handleAllUnselected(IResource resource, String name) {
+		IResource parent = resource.getParent();
+		if (parent == resource.getProject()) {
+			return resource;
+		}
+		try {
+			boolean uncheck = true;
+			IResource[] members = ((IFolder) parent).members();
+			for (int i = 0; i < members.length; i++) {
+				if (isIncluded(members[i])
+						&& !members[i].getName().equals(name))
+					uncheck = false;
+			}
+			if (uncheck) {
+				return handleAllUnselected(parent, parent.getName());
+			}
+			return resource;
+		} catch (CoreException e) {
+			return null;
+		}
+	}
+
+	protected void setChildrenGrayed(IResource folder, boolean isGray) {
+		fTreeViewer.setGrayed(folder, isGray);
+		if (((TreeContentProvider) fTreeViewer.getContentProvider())
+				.hasChildren(folder)) {
+			Object[] members = ((TreeContentProvider) fTreeViewer
+					.getContentProvider()).getFolderChildren(folder);
+			for (int i = 0; i < members.length; i++) {
+				setChildrenGrayed((IFolder) members[i], isGray);
+			}
+		}
+	}
+
+	protected void setParentsChecked(IResource resource) {
+		if (resource.getParent() != resource.getProject()) {
+			fTreeViewer.setChecked(resource.getParent(), true);
+			setParentsChecked(resource.getParent());
+		}
+	}
+
+	/**
+	 * removes all child resources of the specified folder from build entries
+	 * 
+	 * @param folder -
+	 *            current folder being modified in tree
+	 * 
+	 * note: does not remove folder itself
+	 */
+	protected abstract void deleteFolderChildrenFromEntries(IFolder folder);
+
+	protected void initializeCheckState() {
+		uncheckAll();
+	}
+
+	protected void initializeCheckState(final IBuildEntry includes,
+			final IBuildEntry excludes) {
+		fTreeViewer.getTree().getDisplay().asyncExec(new Runnable() {
+
+			public void run() {
+				if (fTreeViewer.getTree().isDisposed()) return;
+				Vector fileExt = new Vector();
+				String[] inclTokens, exclTokens = new String[0];
+				if (fProject == null || includes == null)
+					return;
+				inclTokens = includes.getTokens();
+				if (excludes != null)
+					exclTokens = excludes.getTokens();
+				Set temp = new TreeSet();
+				for (int i = 0; i < inclTokens.length; i++)
+					temp.add(inclTokens[i]);
+				for (int i = 0; i < exclTokens.length; i++)
+					temp.add(exclTokens[i]);
+				Iterator iter = temp.iterator();
+				while (iter.hasNext()) {
+					String resource = iter.next().toString();
+					boolean isIncluded = includes.contains(resource);
+					if (resource.lastIndexOf(Path.SEPARATOR) == resource
+							.length() - 1) {
+						if (resource.length() == 1) {
+							try {
+								IResource[] members = fProject.members();
+								for (int i = 0; i < members.length; i++) {
+									fTreeViewer.setSubtreeChecked(members[i], isIncluded);
+								}
+							} catch (CoreException e) {
+							}
+						} else {
+							IFolder folder = fProject.getFolder(resource);
+							fTreeViewer.setSubtreeChecked(folder, isIncluded);
+							fTreeViewer.setParentsGrayed(folder, true);
+							if (isIncluded && folder.exists()) {
+								setParentsChecked(folder);
+								fTreeViewer.setGrayed(folder, false);
+							}
+						}
+					} else if (resource.startsWith("*.")) { //$NON-NLS-1$
+						if (isIncluded)
+							fileExt.add(resource.substring(2));
+					} else {
+						IFile file = fProject.getFile(resource);
+						fTreeViewer.setChecked(file, isIncluded);
+						fTreeViewer.setParentsGrayed(file, true);
+						if (isIncluded && file.exists()) {
+							fTreeViewer.setGrayed(file, false);
+							setParentsChecked(file);
+						}
+					}
+				}
+				
+				// set initial expanded state
+				try {
+					IResource[] members = fProject.members();
+					for (int i = 0; i < members.length; i++) {
+						fTreeViewer.setExpandedState(members[i],true);
+					}
+					Object[] exp = fTreeViewer.getVisibleExpandedElements();
+					IContentProvider cp = fTreeViewer.getContentProvider();
+					if ((cp instanceof ITreeContentProvider) && (exp.length>0)) {
+						ITreeContentProvider tcp = (ITreeContentProvider)cp;
+						Object obj = exp[0];
+						while (tcp.hasChildren(obj)) {
+							obj = tcp.getChildren(obj)[0];
+							fTreeViewer.setExpandedState(obj,true);
+						}
+					}
+				} catch (CoreException e) {
+				}
+				
+				if (fileExt.size() == 0)
+					return;
+				try {
+					IResource[] members = fProject.members();
+					for (int i = 0; i < members.length; i++) {
+						if (!(members[i] instanceof IFolder)
+								&& (fileExt.contains(members[i]
+										.getFileExtension()))) {
+							fTreeViewer.setChecked(members[i], includes
+									.contains("*." //$NON-NLS-1$
+											+ members[i].getFileExtension()));
+						}
+					}
+				} catch (CoreException e) {
+				}
+			}
+		});
+	}
+
+	protected abstract void handleBuildCheckStateChange(
+			boolean wasTopParentChecked);
+
+	protected void handleCheck(IBuildEntry includes, IBuildEntry excludes,
+			String resourceName, IResource resource,
+			boolean wasTopParentChecked, String PROPERTY_INCLUDES) {
+
+		try {
+			if (includes == null) {
+				includes = fBuildModel.getFactory().createEntry(
+						PROPERTY_INCLUDES);
+				IBuild build = fBuildModel.getBuild();
+				build.add(includes);
+			}
+			if ((!wasTopParentChecked && !includes.contains(resourceName))
+					|| isValidIncludeEntry(includes, excludes, resource,
+							resourceName)) {
+				includes.addToken(resourceName);
+			}
+			if (excludes != null && excludes.contains(resourceName))
+				excludes.removeToken(resourceName);
+
+		} catch (CoreException e) {
+		}
+	}
+
+	protected boolean isValidIncludeEntry(IBuildEntry includes,
+			IBuildEntry excludes, IResource resource, String resourceName) {
+		if (excludes == null)
+			return true;
+		IPath resPath = resource.getProjectRelativePath();
+		while (resPath.segmentCount() > 1) {
+			resPath = resPath.removeLastSegments(1);
+			if (includes.contains(resPath.toString() + Path.SEPARATOR))
+				return false;
+			else if (excludes != null
+					&& excludes.contains(resPath.toString() + Path.SEPARATOR))
+				return true;
+		}
+		return !excludes.contains(resourceName);
+	}
+
+	private boolean isIncluded(IResource res) {
+		
+		if (res.getType() == IResource.PROJECT){
+			IJavaProject jp = JavaCore.create((IProject)res);
+			return jp.isOnClasspath(res);
+		}
+		
+		if (fTreeViewer!=null) {
+			return fTreeViewer.getChecked(res);
+		}
+		return false;
+	}
+	
+	protected void handleUncheck(IBuildEntry includes, IBuildEntry excludes,
+			String resourceName, IResource resource, String PROPERTY_EXCLUDES) {
+
+		try {
+			if (isIncluded(resource.getParent())) {
+				if (excludes == null) {
+					excludes = fBuildModel.getFactory().createEntry(
+							PROPERTY_EXCLUDES);
+					IBuild build = fBuildModel.getBuild();
+					build.add(excludes);
+				}
+				if (!excludes.contains(resourceName)
+						&& (includes != null
+								? !includes.contains(resourceName)
+								: true))
+					excludes.addToken(resourceName);
+			}
+			if (includes != null) {
+				if (includes.contains(resourceName))
+					includes.removeToken(resourceName);
+					if(resource.getParent() instanceof IProject) {
+						// If we're removing a source folder add it to the excludes 
+						// list (part of the fix for bug 102493)
+						if (excludes == null) {
+							excludes = fBuildModel.getFactory().createEntry(
+									PROPERTY_EXCLUDES);
+							IBuild build = fBuildModel.getBuild();
+							build.add(excludes);
+						}
+						if (!excludes.contains(resourceName)
+								&& (includes != null
+										? !includes.contains(resourceName)
+										: true))
+							excludes.addToken(resourceName);
+					}
+				if (includes.contains("*." + resource.getFileExtension())) { //$NON-NLS-1$
+					IResource[] members = fProject.members();
+					for (int i = 0; i < members.length; i++) {
+						if (!(members[i] instanceof IFolder)
+								&& !members[i].getName().equals(
+										resource.getName())
+								&& (resource.getFileExtension()
+										.equals(members[i].getFileExtension()))) {
+							includes.addToken(members[i].getName());
+						}
+						IBuildEntry[] libraries = BuildUtil
+								.getBuildLibraries(fBuildModel.getBuild()
+										.getBuildEntries());
+						if (resource.getFileExtension().equals("jar") //$NON-NLS-1$
+								&& libraries.length != 0) {
+							for (int j = 0; j < libraries.length; j++) {
+								String libName = libraries[j].getName()
+										.substring(7);
+								IPath path = fProject.getFile(libName)
+										.getProjectRelativePath();
+								if (path.segmentCount() == 1
+										&& !includes.contains(libName)
+										&& !libName.equals(resource.getName()))
+									includes.addToken(libName);
+							}
+						}
+					}
+					includes.removeToken("*." + resource.getFileExtension()); //$NON-NLS-1$
+				}
+			}
+		} catch (CoreException e) {
+		}
+	}
+
+	protected String getResourceFolderName(String resourceName) {
+		return resourceName + Path.SEPARATOR;
+	}
+
+	/**
+	 * @param resource -
+	 *            file/folder being modified in tree
+	 * @param resourceName -
+	 *            name file/folder
+	 * @return relative path of folder if resource is folder, otherwise, return
+	 *         resourceName
+	 */
+	protected String handleResourceFolder(IResource resource,
+			String resourceName) {
+		if (resource instanceof IFolder) {
+			deleteFolderChildrenFromEntries((IFolder) resource);
+			return getResourceFolderName(resourceName);
+		}
+		return resourceName;
+	}
+
+	public void initialize() {
+		if (fTreeViewer.getInput() == null) {
+			fTreeViewer.setUseHashlookup(true);
+			fTreeViewer.setInput(fProject);
+		}
+		fBuildModel.addModelChangedListener(this);
+	}
+
+	public void dispose() {
+		fBuildModel.removeModelChangedListener(this);
+		PDEPlugin.getWorkspace().removeResourceChangeListener(this);
+		super.dispose();
+	}
+
+	protected void deleteEmptyEntries() {
+		IBuild build = fBuildModel.getBuild();
+		IBuildEntry[] entries = {
+				build.getEntry(IBuildPropertiesConstants.PROPERTY_BIN_EXCLUDES),
+				build.getEntry(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES),
+				build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES),
+				build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES)};
+		try {
+			for (int i = 0; i < entries.length; i++) {
+				if (entries[i] != null && entries[i].getTokens().length == 0)
+					build.remove(entries[i]);
+			}
+		} catch (CoreException e) {
+		}
+	}
+
+	public CheckboxTreeViewer getTreeViewer() {
+		return fTreeViewer;
+	}
+
+	protected ISelection getViewerSelection() {
+		return getTreeViewer().getSelection();
+	}
+
+	public void refresh() {
+		initializeCheckState();
+		super.refresh();
+	}
+
+	public void uncheckAll() {
+		fTreeViewer.setCheckedElements(new Object[0]);
+	}
+
+	protected void removeChildren(IBuildEntry entry, String parentFolder) {
+		try {
+			if (entry != null) {
+				String[] tokens = entry.getTokens();
+				for (int i = 0; i < tokens.length; i++) {
+					if (tokens[i].indexOf(Path.SEPARATOR) != -1
+							&& tokens[i].startsWith(parentFolder)
+							&& !tokens[i].equals(parentFolder)) {
+						entry.removeToken(tokens[i]);
+					}
+				}
+			}
+		} catch (CoreException e) {
+		}
+	}
+
+	public void resourceChanged(IResourceChangeEvent event) {
+		if (fTreeViewer.getControl().isDisposed())
+			return;
+		fDoRefresh = false;
+		IResourceDelta delta = event.getDelta();
+		try {
+			if (delta != null)
+				delta.accept(this);
+			if (fDoRefresh) {
+				asyncRefresh();
+				fDoRefresh = false;
+			}
+		} catch (CoreException e) {
+		}
+	}
+
+	public boolean visit(IResourceDelta delta) {
+		IResource resource = delta.getResource();
+		if ((resource instanceof IFile || resource instanceof IFolder)
+				&& resource.getProject().equals(
+						fBuildModel.getUnderlyingResource().getProject())) {
+			if (delta.getKind() == IResourceDelta.ADDED
+					|| delta.getKind() == IResourceDelta.REMOVED) {
+				fDoRefresh = true;
+				return false;
+			}
+		}
+		return true;
+	}
+
+	private void asyncRefresh() {
+		Control control = fTreeViewer.getControl();
+		if (!control.isDisposed()) {
+			control.getDisplay().asyncExec(new Runnable() {
+
+				public void run() {
+					if (!fTreeViewer.getControl().isDisposed()) {
+						fTreeViewer.refresh(true);
+						initializeCheckState();
+					}
+				}
+			});
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.pde.internal.ui.editor.TableSection#selectionChanged(org.eclipse.jface.viewers.IStructuredSelection)
+	 */
+	protected void selectionChanged(IStructuredSelection selection) {
+		getPage().getPDEEditor().setSelection(selection);
+
+	}
+
+	public void modelChanged(IModelChangedEvent event) {
+
+		if (event.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
+			markStale();
+		}
+		Object changeObject = event.getChangedObjects()[0];
+
+		if (!(changeObject instanceof IBuildEntry && (((IBuildEntry) changeObject)
+				.getName().equals(
+						IBuildPropertiesConstants.PROPERTY_BIN_EXCLUDES)
+				|| ((IBuildEntry) changeObject).getName().equals(
+						IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES)
+				|| ((IBuildEntry) changeObject).getName().equals(
+						IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES) || ((IBuildEntry) changeObject)
+				.getName().equals(
+						IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES))))
+			return;
+
+		if ((fParentResource == null && fOriginalResource != null)
+				|| (fOriginalResource == null && fParentResource != null)) {
+			initializeCheckState();
+			return;
+		}
+		if ((fParentResource == null && fOriginalResource == null)
+				|| (event.getChangedProperty() != null && event
+						.getChangedProperty()
+						.equals(IBuildPropertiesConstants.PROPERTY_BIN_INCLUDES))) {
+
+			return;
+		}
+
+		fTreeViewer.setChecked(fParentResource, isChecked);
+		fTreeViewer.setGrayed(fOriginalResource, false);
+		fTreeViewer.setParentsGrayed(fParentResource, true);
+		setParentsChecked(fParentResource);
+		fTreeViewer.setGrayed(fParentResource, false);
+		if (fParentResource instanceof IFolder) {
+			fTreeViewer.setSubtreeChecked(fParentResource, isChecked);
+			setChildrenGrayed(fParentResource, false);
+		}
+		while (!fOriginalResource.equals(fParentResource)) {
+			fTreeViewer.setChecked(fOriginalResource, isChecked);
+			fOriginalResource = fOriginalResource.getParent();
+		}
+		fParentResource = null;
+		fOriginalResource = null;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditor.java
new file mode 100644
index 0000000..685bc18
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditor.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ajdt.pde.internal.ui.editor.ISortableContentOutlinePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.MultiSourceEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDESourcePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileEditorInput;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContextManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.core.build.IBuildModel;
+import org.eclipse.pde.internal.core.build.IBuildObject;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.SWTError;
+import org.eclipse.swt.dnd.RTFTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+
+public class BuildEditor extends MultiSourceEditor {
+	public BuildEditor() {
+	}
+	protected void createResourceContexts(InputContextManager manager,
+			IFileEditorInput input) {
+		IFile file = input.getFile();
+
+		manager.putContext(input, new BuildInputContext(this, input, true));
+		manager.monitorFile(file);
+	}
+	
+	protected InputContextManager createInputContextManager() {
+		BuildInputContextManager manager =  new BuildInputContextManager(this);
+		manager.setUndoManager(new BuildUndoManager(this));
+		return manager;
+	}
+	
+	public void monitoredFileAdded(IFile file) {
+		if (!inputContextManager.hasContext(BuildInputContext.CONTEXT_ID)) {
+			IEditorInput in = new FileEditorInput(file);
+			inputContextManager.putContext(in, new BuildInputContext(this, in, false));
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void doSave(IProgressMonitor monitor) {
+		super.doSave(monitor);
+		// now perform a full rebuild if the file changed is the active configuration file
+		IEditorInput in = inputContextManager.getPrimaryContext().getInput();
+		if ((in instanceof IFileEditorInput)) { // && (pbc!=null)) {
+			IFile changedFile = ((IFileEditorInput)in).getFile();
+			AJLog.log("Build configuration file written: " + changedFile.getName()); //$NON-NLS-1$
+		}
+	}
+	
+	public boolean monitoredFileRemoved(IFile file) {
+		//TODO may need to check with the user if there
+		//are unsaved changes in the model for the
+		//file that just got removed under us.
+		return true;
+	}
+	public void contextAdded(InputContext context) {
+		addSourcePage(context.getId());
+	}
+	public void contextRemoved(InputContext context) {
+		if (context.isPrimary()) {
+			close(true);
+			return;
+		}
+		IFormPage page = findPage(context.getId());
+		if (page!=null)
+			removePage(context.getId());
+	}
+
+	protected void createSystemFileContexts(InputContextManager manager,
+			SystemFileEditorInput input) {
+		manager.putContext(input, new BuildInputContext(this, input, true));
+	}
+
+	protected void createStorageContexts(InputContextManager manager,
+			IStorageEditorInput input) {
+		manager.putContext(input, new BuildInputContext(this, input, true));
+	}
+
+	public boolean canCopy(ISelection selection) {
+		return true;
+	}
+	
+	protected void addPages() {
+		try {
+			if (getEditorInput() instanceof IFileEditorInput)
+				addPage(new BuildPage(this));			
+		} catch (PartInitException e) {
+			PDEPlugin.logException(e);
+		}
+		addSourcePage(BuildInputContext.CONTEXT_ID);
+	}
+
+	protected String computeInitialPageId() {
+		String firstPageId = super.computeInitialPageId();
+		if (firstPageId == null) {
+			InputContext primary = inputContextManager.getPrimaryContext();
+			if (primary.getId().equals(BuildInputContext.CONTEXT_ID))
+				firstPageId = BuildPage.PAGE_ID;
+			if (firstPageId == null)
+				firstPageId = BuildPage.PAGE_ID;
+		}
+		return firstPageId;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.MultiSourceEditor#createXMLSourcePage(org.eclipse.pde.internal.ui.neweditor.PDEFormEditor, java.lang.String, java.lang.String)
+	 */
+	protected PDESourcePage createSourcePage(PDEFormEditor editor, String title, String name, String contextId) {
+		return new BuildSourcePage(editor, title, name);
+	}
+	
+	protected ISortableContentOutlinePage createContentOutline() {
+		return new BuildOutlinePage(this);
+	}
+	
+	protected IPropertySheetPage getPropertySheet(PDEFormPage page) {
+		return null;
+	}
+
+	public String getTitle() {
+		return super.getTitle();
+	}
+
+	protected boolean isModelCorrect(Object model) {
+		return model != null ? ((IBuildModel) model).isValid() : false;
+	}
+	protected boolean hasKnownTypes() {
+		try {
+			TransferData[] types = getClipboard().getAvailableTypes();
+			Transfer[] transfers =
+				new Transfer[] { TextTransfer.getInstance(), RTFTransfer.getInstance()};
+			for (int i = 0; i < types.length; i++) {
+				for (int j = 0; j < transfers.length; j++) {
+					if (transfers[j].isSupportedType(types[i]))
+						return true;
+				}
+			}
+		} catch (SWTError e) {
+		}
+		return false;
+	}
+
+	public Object getAdapter(Class key) {
+		//No property sheet needed - block super
+		if (key.equals(IPropertySheetPage.class)) {
+			return null;
+		}
+		return super.getAdapter(key);
+	}	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.editor.PDEFormEditor#getInputContext(java.lang.Object)
+	 */
+	protected InputContext getInputContext(Object object) {
+		InputContext context = null;
+		if (object instanceof IBuildObject) {
+			context = inputContextManager.findContext(BuildInputContext.CONTEXT_ID);
+		} 
+		return context;
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditorContributor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditorContributor.java
new file mode 100644
index 0000000..5f6c03e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildEditorContributor.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditorContributor;
+
+public class BuildEditorContributor extends PDEFormEditorContributor {
+
+	public BuildEditorContributor() {
+		super("&Build"); //$NON-NLS-1$
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContext.java
new file mode 100644
index 0000000..f1d4f6a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContext.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.BuildModel;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileEditorInput;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.internal.core.text.AbstractEditingModel;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+
+public class BuildInputContext extends InputContext {
+	public static final String CONTEXT_ID = "build-context"; //$NON-NLS-1$
+	
+	private HashMap fOperationTable = new HashMap();
+
+	public BuildInputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+		super(editor, input, primary);
+		create();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#getCharSet()
+	 */
+	protected String getDefaultCharset() {
+		return "ISO-8859-1"; //$NON-NLS-1$
+	}
+
+	protected IBaseModel createModel(IEditorInput input) throws CoreException {
+		BuildModel model = null;
+		if (input instanceof IStorageEditorInput) {
+			boolean isReconciling = input instanceof IFileEditorInput;
+			IDocument document = getDocumentProvider().getDocument(input);
+			model = new BuildModel(document, isReconciling);
+			if (input instanceof IFileEditorInput) {
+				IFile file = ((IFileEditorInput)input).getFile();
+				model.setUnderlyingResource(file);
+				model.setCharset(file.getCharset());
+			} else if (input instanceof SystemFileEditorInput){
+				File file = (File)((SystemFileEditorInput)input).getAdapter(File.class);
+				model.setInstallLocation(file.getParent());
+				model.setCharset(getDefaultCharset());
+			} else {
+				model.setCharset(getDefaultCharset());				
+			}
+			model.load();
+		}
+		return model;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.InputContext#getId()
+	 */
+	public String getId() {
+		return CONTEXT_ID;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#addTextEditOperation(java.util.ArrayList, org.eclipse.pde.core.IModelChangedEvent)
+	 */
+	protected void addTextEditOperation(ArrayList ops, IModelChangedEvent event) {
+		Object[] objects = event.getChangedObjects();
+		if (objects != null) {
+			for (int i = 0; i < objects.length; i++) {
+				Object object = objects[i];
+				IDocumentKey key = (IDocumentKey)object;
+				TextEdit op = (TextEdit)fOperationTable.get(key);
+				if (op != null) {
+					fOperationTable.remove(key);
+					ops.remove(op);
+				}
+				switch (event.getChangeType()) {
+					case IModelChangedEvent.REMOVE :
+						deleteKey(key, ops);
+						break;
+					case IModelChangedEvent.INSERT :
+						insertKey(key, ops);
+						break;
+					case IModelChangedEvent.CHANGE :
+						modifyKey(key, ops);
+					default:
+						break;
+				}
+			}
+		}
+	}
+	
+	private void insertKey(IDocumentKey key, ArrayList ops) {
+		IDocument doc = getDocumentProvider().getDocument(getInput());
+		String preTermination = ""; //$NON-NLS-1$
+		if (doc.getNumberOfLines() > 0) {
+			try {
+				if (doc.getLineDelimiter(doc.getNumberOfLines() - 1) == null
+						&& doc.getLineLength(doc.getNumberOfLines() - 1) > 0) {
+					preTermination = getLineDelimiter(); 
+				}
+			} catch (BadLocationException ble) {
+			}
+		}
+		InsertEdit op = new InsertEdit(doc.getLength(), preTermination
+				+ key.write());
+		fOperationTable.put(key, op);
+		ops.add(op);
+	}
+	
+	private void deleteKey(IDocumentKey key, ArrayList ops) {
+		if (key.getOffset() >= 0) {
+			TextEdit op = new DeleteEdit(key.getOffset(), key.getLength());
+			fOperationTable.put(key, op);
+			ops.add(op);
+		}
+	}
+	
+	private void modifyKey(IDocumentKey key, ArrayList ops) {		
+		if (key.getOffset() == -1) {
+			insertKey(key, ops);
+		} else {
+			TextEdit op = new ReplaceEdit(key.getOffset(), key.getLength(), key.write());
+			fOperationTable.put(key, op);
+			ops.add(op);
+		}	
+	}
+	public void doRevert() {
+		fEditOperations.clear();
+		fOperationTable.clear();
+		AbstractEditingModel model = (AbstractEditingModel)getModel();
+		model.reconciled(model.getDocument());
+	}
+
+	protected String getPartitionName() {
+		return "___build_partition"; //$NON-NLS-1$
+	}	
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContextManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContextManager.java
new file mode 100644
index 0000000..ee24db5
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildInputContextManager.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.*;
+
+/**
+ * @author dejan
+ */
+public class BuildInputContextManager extends InputContextManager {
+	/**
+	 * 
+	 */
+	public BuildInputContextManager(PDEFormEditor editor) {
+		super(editor);
+	}
+
+	public IBaseModel getAggregateModel() {
+		return findBuildModel();
+	}
+
+	private IBaseModel findBuildModel() {
+		InputContext bcontext = findContext(BuildInputContext.CONTEXT_ID);
+		if (bcontext!=null)
+			return bcontext.getModel();
+		else
+			return null;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildOutlinePage.java
new file mode 100644
index 0000000..45e8b1c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildOutlinePage.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildModel;
+import org.eclipse.ajdt.pde.internal.ui.editor.FormOutlinePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+
+public class BuildOutlinePage extends FormOutlinePage {
+	/**
+	 * @param editor
+	 */
+	public BuildOutlinePage(PDEFormEditor editor) {
+		super(editor);
+	}
+	protected Object[] getChildren(Object parent) {
+		if (parent instanceof PDEFormPage) {
+			PDEFormPage page = (PDEFormPage) parent;
+			IBuildModel model = (IBuildModel) page.getModel();
+			if (model.isValid()) {
+				IBuild build = model.getBuild();
+				if (page.getId().equals(BuildPage.PAGE_ID))
+					return build.getBuildEntries();
+			}
+		}
+		return new Object[0];
+	}
+	protected String getParentPageId(Object item) {
+		String pageId = null;
+		if (item instanceof IBuildEntry)
+			pageId = BuildPage.PAGE_ID;
+		if (pageId != null)
+			return pageId;
+		return super.getParentPageId(item);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildPage.java
new file mode 100644
index 0000000..5599d39
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildPage.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Matt Chapman - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormPage;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+public class BuildPage extends PDEFormPage {
+	public static final String PAGE_ID = "build"; //$NON-NLS-1$
+	private BuildContentsSection srcSection;
+	
+	public BuildPage(FormEditor editor) {
+		super(editor, PAGE_ID, UIMessages.BuildPage_name);
+	}
+
+	protected void createFormContent(IManagedForm mform) {
+		super.createFormContent(mform);
+		GridLayout layout = new GridLayout();
+		ScrolledForm form = mform.getForm();
+		form.setText(UIMessages.AJPropsEditor_BuildPage_title);
+		layout.numColumns = 2;
+		layout.marginWidth = 10;
+		layout.horizontalSpacing = 15;
+		layout.verticalSpacing = 10;
+		layout.makeColumnsEqualWidth = true;
+		form.getBody().setLayout(layout);
+
+
+		
+		srcSection = new SrcSection(this, form.getBody());
+		GridData gd = new GridData(GridData.FILL_BOTH);
+		gd.horizontalSpan = 2;
+		srcSection.getSection().setLayoutData(gd);
+
+		mform.addPart(srcSection);
+	}
+
+	
+	public void enableAllSections(boolean enable){
+		srcSection.enableSection(enable);
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildProperties.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildProperties.java
new file mode 100644
index 0000000..c66949f
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildProperties.java
@@ -0,0 +1,545 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Matt Chapman - initial implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Vector;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ajdt.core.CoreUtils;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.Build;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.BuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.BuildModel;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildModel;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.pde.core.IBaseModel;
+
+/**
+ * This class is used by the build configuration functionality in the UI to
+ * support the including and excluding of resources in .ajproperties files.
+ * 
+ * @author Matt Chapman
+ *  
+ */
+public class BuildProperties {
+
+	private IFile myPropertiesFile;
+
+	private IBuild build;
+
+	private IBuildModel buildModel;
+
+	public BuildProperties(IFile file) {
+		myPropertiesFile = file;
+	}
+
+	/**
+	 * Create a new properties file with the given source folders included
+	 * @param file the properties file
+	 * @param sourceFolder the list of source filders to include
+	 */
+	public BuildProperties(IFile file, List sourceFolders) {
+		myPropertiesFile = file;
+		
+		initBuild(false);
+		
+		IBuildEntry srcIncl = buildModel.getFactory().createEntry(
+					IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		build.addWithoutNotify(srcIncl);
+		
+		IBuildEntry srcExcl = build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		if (srcExcl != null){
+			((Build)build).removeWithoutNotify(srcExcl);
+		}
+
+		for (Iterator iter = sourceFolders.iterator(); iter.hasNext();) {
+			Object next = iter.next();
+			IPath path;
+			String entry;
+			if (next instanceof IResource) {
+				entry = getNameFromResource(((IResource) next));
+			} else {
+				path = ((IPath) next).addTrailingSeparator();
+				entry = path.toString();
+			}
+
+			addTokenToBuildEntry((BuildEntry) srcIncl, entry);
+		}
+
+		writeFile();
+	}
+
+	/**
+	 * Returns a list of all files included by the current configuration.
+	 * 
+	 * @param forceReadingFile if set ensures properties file is always read
+	 * @return a list of file resources
+	 */
+	public List getFiles(boolean forceReadingFile) {
+		if (forceReadingFile){
+			//ensure latest contents are read
+			initBuild(true);
+		} else {
+			initBuild(false);
+		}
+
+		IBuildEntry srcIncl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		IBuildEntry srcExcl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		IProject fProject = myPropertiesFile.getProject();
+		List included = determineIncludedFiles(srcIncl, srcExcl, fProject);
+
+		return included;
+	}
+
+	/**
+	 * Includes the given resource from the active configuration, and writes the
+	 * updated configuration file.
+	 * 
+	 * @param res
+	 *            the resource to include
+	 */
+	public void include(IResource res) {
+		String name;
+		if (res.getType() == IResource.FOLDER) {
+			name = res.getProjectRelativePath().addTrailingSeparator()
+					.toString();
+		} else {
+			name = res.getProjectRelativePath().toString();
+		}
+		name = handleResourceFolder(res, name);
+		initBuild(false);
+
+		IBuildEntry srcIncl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		IBuildEntry srcExcl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		handleCheck(srcIncl, srcExcl, name, res);
+
+		if (srcIncl != null) {
+			build.addWithoutNotify(srcIncl);
+		}
+		if (srcExcl != null) {
+			build.addWithoutNotify(srcExcl);
+		}
+		deleteEmptyEntries();
+		//writeFile();
+	}
+
+	/**
+	 * Excludes the given resource from the active configuration, and writes the
+	 * updated configuration file.
+	 * 
+	 * @param res
+	 *            the resource to exclude
+	 * @throws CoreException
+	 */
+	public void exclude(IResource res) throws CoreException {
+		String name;
+		if (res.getType() == IResource.FOLDER) {
+			name = res.getProjectRelativePath().addTrailingSeparator()
+					.toString();
+		} else {
+			name = res.getProjectRelativePath().toString();
+		}
+		name = handleResourceFolder(res, name);
+
+		initBuild(false);
+
+		IBuildEntry srcIncl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		IBuildEntry srcExcl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		handleUncheck(srcIncl, srcExcl, name, res);
+
+		if (srcIncl != null) {
+			build.addWithoutNotify(srcIncl);
+		}
+		if (srcExcl != null) {
+			build.addWithoutNotify(srcExcl);
+		}
+		deleteEmptyEntries();
+	}
+
+	//once build was initialized, it must never be set to null again
+	//to force reinitialization, use forceInit paramter instead
+	//(prevents concurrent access trouble)
+	private void initBuild(boolean forceInit) {
+		if (build == null || forceInit) {
+			BuildEditor be = new BuildEditor();
+			AJLog.log("Build configuration file read: " + myPropertiesFile.getName()); //$NON-NLS-1$
+			be.monitoredFileAdded(myPropertiesFile);
+			IBaseModel ibm = be.getContextManager().findContext(
+					myPropertiesFile).getModel();
+			if (ibm instanceof BuildModel) {
+				buildModel = (BuildModel) ibm;
+				build = buildModel.getBuild();
+			}
+		}
+	}
+
+	//return a list of all file resources in the given folder, including all
+	// sub-folders
+	private List allFiles(IContainer folder) {
+		final List contents = new ArrayList();
+		if(folder.exists()) {
+			try {
+				folder.accept(new IResourceVisitor() {
+					public boolean visit(IResource res) {
+						if (res.getType() == IResource.FILE
+								&& CoreUtils.ASPECTJ_SOURCE_FILTER
+										.accept(res.getName())) {
+							contents.add(res);
+						}
+						return true;
+					}
+				});
+			} catch (CoreException e) {
+			}
+		}
+		return contents;
+	}
+
+	private List determineIncludedFiles(final IBuildEntry includes,
+			final IBuildEntry excludes, final IProject fProject) {
+		List includedFiles = new ArrayList();
+		Vector fileExt = new Vector();
+		String[] inclTokens, exclTokens = new String[0];
+		if (fProject == null || includes == null)
+			return includedFiles;
+		inclTokens = includes.getTokens();
+		if (excludes != null)
+			exclTokens = excludes.getTokens();
+		Set temp = new TreeSet();
+		for (int i = 0; i < inclTokens.length; i++)
+			temp.add(inclTokens[i]);
+		for (int i = 0; i < exclTokens.length; i++)
+			temp.add(exclTokens[i]);
+		Iterator iter = temp.iterator();
+		while (iter.hasNext()) {
+			String resource = iter.next().toString();
+			boolean isIncluded = includes.contains(resource);
+			if (resource.lastIndexOf(Path.SEPARATOR) == resource.length() - 1) {
+				IContainer folder;
+				if (resource.length() == 1) {
+					folder = fProject;
+				} else {
+					folder = fProject.getFolder(resource);
+				}
+				if (isIncluded) {
+					includedFiles.addAll(allFiles(folder));
+				} else {
+					includedFiles.removeAll(allFiles(folder));
+				}
+			} else if (resource.startsWith("*.")) { //$NON-NLS-1$
+				if (isIncluded)
+					fileExt.add(resource.substring(2));
+			} else {
+				IFile file = fProject.getFile(resource);
+				if (isIncluded
+						&& CoreUtils.ASPECTJ_SOURCE_FILTER.accept(file
+								.getName())) {
+					includedFiles.add(file);
+				} else {
+					includedFiles.remove(file);
+				}
+			}
+		}
+		if (fileExt.size() == 0)
+			return includedFiles;
+		return includedFiles;
+	}
+
+	public void writeFile() {
+		AJLog.log("Build configuration file written: " + myPropertiesFile.getName()); //$NON-NLS-1$
+		IBuildEntry[] entries = build.getBuildEntries();
+		final StringBuffer buff = new StringBuffer();
+		for (int i = 0; i < entries.length; i++) {
+			if (entries[i] instanceof BuildEntry) {
+				String s = ((BuildEntry) entries[i]).write();
+				buff.append(s);
+			}
+		}
+		
+		if (!myPropertiesFile.getWorkspace().isTreeLocked()) {
+			InputStream inputStream = new ByteArrayInputStream(buff
+					.toString().getBytes());
+			try {
+				if (!myPropertiesFile.exists()) {
+					myPropertiesFile.create(inputStream, false,
+							null);
+				} else {
+					myPropertiesFile.setContents(inputStream,
+							false, true, null);
+				}
+			} catch (CoreException e) {
+			}
+		} else {
+			AJLog.log("BuildProperties: resource tree locked"); //$NON-NLS-1$
+		}
+	}
+
+	private void addTokenToBuildEntry(BuildEntry entry, String token) {
+		if (!entry.contains(token)) {
+			entry.addTokenWithoutNotify(token);
+		}
+	}
+
+	private boolean contains(Object[] array, Object o){
+		if (array == null)
+			return false;
+		for (int i=0; i<array.length; i++){
+			if (array[i].equals(o))
+				return true;
+		}
+		return false;
+	}
+	
+	private String getNameFromResource(IResource res){
+		IPath p = res.getProjectRelativePath();
+		if ((res.getType() == IResource.FOLDER) || (res.getType() == IResource.PROJECT))
+			p = p.addTrailingSeparator();
+		return p.toString();
+	}
+	
+	private boolean isIncluded(IResource res, IBuildEntry includes, IBuildEntry excludes) {
+		if (res.getParent() == null)
+			return false;
+		String name = getNameFromResource(res);
+		if (includes != null){
+			if (contains(includes.getTokens(), name))
+				return true;
+		}
+		if (excludes != null){
+			if (contains(excludes.getTokens(), name))
+				return false;
+		}
+		return isIncluded(res.getParent(), includes, excludes);
+	}
+	
+
+	// from BuildContentsSection
+	/**
+	 * @param resource -
+	 *            file/folder being modified in tree
+	 * @param resourceName -
+	 *            name file/folder
+	 * @return relative path of folder if resource is folder, otherwise, return
+	 *         resourceName
+	 */
+	protected String handleResourceFolder(IResource resource,
+			String resourceName) {
+		if (resource instanceof IFolder) {
+			deleteFolderChildrenFromEntries((IFolder) resource);
+			return getResourceFolderName(resourceName);
+		}
+		return resourceName;
+	}
+
+	protected void deleteFolderChildrenFromEntries(IFolder folder) {
+		IBuild build = buildModel.getBuild();
+		IBuildEntry srcIncl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		IBuildEntry srcExcl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		String parentFolder = getResourceFolderName(folder
+				.getProjectRelativePath().toString());
+
+		removeChildren(srcIncl, parentFolder);
+		removeChildren(srcExcl, parentFolder);
+	}
+
+	protected String getResourceFolderName(String resourceName) {
+		return resourceName;
+	}
+
+	protected void removeChildren(IBuildEntry entry, String parentFolder) {
+		if (entry != null) {
+			String[] tokens = entry.getTokens();
+			for (int i = 0; i < tokens.length; i++) {
+				if (tokens[i].indexOf(Path.SEPARATOR) != -1
+						&& tokens[i].startsWith(parentFolder)
+						&& !tokens[i].equals(parentFolder)) {
+					((BuildEntry) entry).removeTokenWithoutNotify(tokens[i]);
+				}
+			}
+		}
+	}
+
+	// similar to BuildContentsSection.handleCheck
+	protected void handleCheck(IBuildEntry includes, IBuildEntry excludes,
+			String resourceName, IResource resource) {
+		if (includes == null) {
+			includes = buildModel.getFactory().createEntry(
+					IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+			IBuild build = buildModel.getBuild();
+			build.addWithoutNotify(includes);
+		}
+		if ((excludes != null) && excludes.contains(resourceName)) {
+			excludes.removeTokenWithoutNotify(resourceName);
+		}
+		if (!this.isIncluded(resource, includes, excludes)){
+			includes.addTokenWithoutNotify(resourceName);
+		}
+	}
+
+	// similar to BuildContentsSection.handleUnCheck
+	protected void handleUncheck(IBuildEntry includes, IBuildEntry excludes,
+			String resourceName, IResource resource) throws CoreException {
+		if (isIncluded(resource.getParent(), includes, excludes)) {
+			if (excludes == null) {
+				excludes = buildModel.getFactory().createEntry(
+						IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+				IBuild build = buildModel.getBuild();
+				build.addWithoutNotify(excludes);
+			}
+			if (!excludes.contains(resourceName)
+					&& (includes != null ? !includes.contains(resourceName)
+							: true))
+				excludes.addTokenWithoutNotify(resourceName);
+		}
+		if (includes != null) {
+			if (includes.contains(resourceName))
+				((BuildEntry) includes).removeTokenWithoutNotify(resourceName);
+			if (includes.contains("*." + resource.getFileExtension())) { //$NON-NLS-1$
+				IResource[] members = myPropertiesFile.getProject().members();
+				for (int i = 0; i < members.length; i++) {
+					if (!(members[i] instanceof IFolder)
+							&& !members[i].getName().equals(resource.getName())
+							&& (resource.getFileExtension().equals(members[i]
+									.getFileExtension()))) {
+						includes.addTokenWithoutNotify(members[i].getName());
+					}
+				}
+				includes
+						.removeTokenWithoutNotify("*." + resource.getFileExtension()); //$NON-NLS-1$
+			}
+		}
+	}
+
+	protected void deleteEmptyEntries() {
+		IBuild build = buildModel.getBuild();
+		IBuildEntry[] entries = {
+				build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES),
+				build.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES) };
+		for (int i = 0; i < entries.length; i++) {
+			if (entries[i] != null && entries[i].getTokens().length == 0)
+				((Build) build).removeWithoutNotify(entries[i]);
+		}
+	}
+
+	/**
+	 * @param sourcePathes
+	 */
+	public void updateSourceFolders(List sourcePathes) {
+		boolean changed = false;
+		
+		initBuild(false);
+		
+		IBuildEntry srcIncl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		if (srcIncl != null) {
+			changed |= removeOldSourceFolders(sourcePathes, srcIncl);
+		} else {
+			srcIncl = buildModel.getFactory().createEntry(
+					IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+			build.addWithoutNotify(srcIncl);
+		}
+		IBuildEntry srcExcl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		if (srcExcl != null) {
+			changed |= removeOldSourceFolders(sourcePathes, srcExcl);
+		}
+		changed |= addNewSourceFolders(sourcePathes, srcIncl, srcExcl);
+
+		if (changed) {
+			writeFile();
+		}
+	}
+
+	private boolean removeOldSourceFolders(List sourcePathes,
+			IBuildEntry srcIncl) {
+		boolean changed = false;
+		String[] entries = srcIncl.getTokens();
+		Iterator iter;
+		for (int i = 0; i < entries.length; i++) {
+			iter = sourcePathes.iterator();
+			boolean toBeRemoved = true;
+			while (iter.hasNext()) {
+				IPath p = (IPath) iter.next();
+				if (p.isPrefixOf(new Path(entries[i]))) {
+					toBeRemoved = false;
+					break;
+				}
+			}
+			if (toBeRemoved) {
+				srcIncl.removeTokenWithoutNotify(entries[i]);
+				changed = true;
+			}
+		}
+		return changed;
+	}
+
+	private boolean addNewSourceFolders(List sourcePathes, IBuildEntry srcIncl, IBuildEntry srcExcl) {
+		boolean changed = false;
+		String[] entries = srcIncl.getTokens();
+		String[] excludedEntries;
+		if(srcExcl != null) {
+			excludedEntries = srcExcl.getTokens();
+		} else {
+			excludedEntries = new String[0];
+		}
+		Iterator iter;
+
+		iter = sourcePathes.iterator();
+		while (iter.hasNext()) {
+			boolean isNewSrcPath = true;
+			IPath path = (IPath) iter.next();
+			for (int i = 0; i < entries.length; i++) {
+				if (path.isPrefixOf(new Path(entries[i]))) {
+					isNewSrcPath = false;
+					break;
+				}
+			}
+			// Part of the fix for bug 102493 - check excluded entries too
+			for (int i = 0; i < excludedEntries.length; i++) {
+				if (path.isPrefixOf(new Path(excludedEntries[i]))) {
+					isNewSrcPath = false;
+					break;
+				}
+			}
+			if (isNewSrcPath) {
+				srcIncl.addTokenWithoutNotify(path.addTrailingSeparator()
+						.toString());
+				changed = true;
+			}
+
+		}
+		return changed;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourcePage.java
new file mode 100644
index 0000000..516c057
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourcePage.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.KeyValueSourcePage;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.pde.core.build.IBuild;
+import org.eclipse.pde.core.build.IBuildEntry;
+import org.eclipse.pde.core.build.IBuildModel;
+import org.eclipse.pde.internal.core.text.IDocumentRange;
+import org.eclipse.pde.internal.core.text.build.BuildEntry;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.editor.text.ColorManager;
+import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
+import org.eclipse.swt.graphics.Image;
+
+public class BuildSourcePage extends KeyValueSourcePage {
+	public BuildSourcePage(PDEFormEditor editor, String id, String title) {
+		super(editor, id, title);
+	}
+	
+	protected ILabelProvider createOutlineLabelProvider() {
+		return new BuildLabelProvider();
+	}
+	
+	protected ITreeContentProvider createOutlineContentProvider() {
+		return new BuildOutlineContentProvider();
+	}
+	
+	class BuildOutlineContentProvider extends DefaultContentProvider
+			implements
+				ITreeContentProvider {
+		public Object[] getChildren(Object parent) {
+			return new Object[0];
+		}
+		public boolean hasChildren(Object parent) {
+			return false;
+		}
+		public Object getParent(Object child) {
+			if (child instanceof IBuildEntry)
+				return ((IBuildEntry) child).getModel();
+			return null;
+		}
+		public Object[] getElements(Object parent) {
+			if (parent instanceof IBuildModel) {
+				IBuildModel model = (IBuildModel) parent;
+				IBuild build = model.getBuild();
+				return build.getBuildEntries();
+			}
+			return new Object[0];
+		}
+	}
+	class BuildLabelProvider extends LabelProvider {
+		public String getText(Object obj) {
+			if (obj instanceof IBuildEntry) {
+				return ((IBuildEntry) obj).getName();
+			}
+			return super.getText(obj);
+		}
+		public Image getImage(Object obj) {
+			if (obj instanceof IBuildEntry)
+				return PDEPlugin.getDefault().getLabelProvider().get(
+					PDEPluginImages.DESC_BUILD_VAR_OBJ);
+			return null;
+		}
+	}
+/*
+	private ColorManager fColorManager;
+	
+	public BuildSourcePage(PDEFormEditor editor, String id, String title) {
+		super(editor, id, title);
+		IPreferenceStore store = JavaPlugin.getDefault().getCombinedPreferenceStore();
+		setPreferenceStore(store);
+		fColorManager = ColorManager.getDefault();
+		setSourceViewerConfiguration(new BuildSourceViewerConfiguration(fColorManager, store, this));
+	}
+	
+	public void dispose() {
+		fColorManager.dispose();
+		super.dispose();
+	}
+	
+	protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+		try {
+			ISourceViewer sourceViewer = getSourceViewer();
+			if (sourceViewer == null)
+				return;
+			((BuildSourceViewerConfiguration) getSourceViewerConfiguration()).handlePropertyChangeEvent(event);
+		} finally {
+			super.handlePreferenceStoreChanged(event);
+		}
+	}
+	
+	protected IDocumentRange getRangeElement(ITextSelection selection) {
+		if (selection.isEmpty())
+			return null;
+		IBuildModel model = (IBuildModel) getInputContext().getModel();
+		return findBuildNode(model.getBuild().getBuildEntries(), selection.getOffset());
+	}
+
+	private BuildEntry findBuildNode(IBuildEntry[] nodes, int offset) {
+		for (int i = 0; i < nodes.length; i++) {
+			BuildEntry node = (BuildEntry) nodes[i];
+			if (offset >= node.getOffset()
+					&& offset < node.getOffset() + node.getLength()) {
+				return node;
+			}
+		}
+		return null;
+	}
+	
+	protected String[] collectContextMenuPreferencePages() {
+		String[] ids= super.collectContextMenuPreferencePages();
+		String[] more= new String[ids.length + 1];
+		more[0]= "org.eclipse.jdt.ui.preferences.PropertiesFileEditorPreferencePage"; //$NON-NLS-1$
+		System.arraycopy(ids, 0, more, 1, ids.length);
+		return more;
+	}
+	
+	protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+		return ((BuildSourceViewerConfiguration)getSourceViewerConfiguration()).affectsTextPresentation(event) || super.affectsTextPresentation(event);
+	}
+	*/
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourceViewerConfiguration.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourceViewerConfiguration.java
new file mode 100644
index 0000000..93a17d8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildSourceViewerConfiguration.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+import org.eclipse.jface.text.rules.IWordDetector;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.pde.internal.ui.editor.text.ArgumentRule;
+import org.eclipse.pde.internal.ui.editor.text.BasePDEScanner;
+import org.eclipse.pde.internal.ui.editor.text.IColorManager;
+import org.eclipse.pde.internal.ui.editor.text.ReconcilingStrategy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+
+
+public class BuildSourceViewerConfiguration extends TextSourceViewerConfiguration {
+
+	protected static String PROPERTIES_FILE_PARTITIONING = "___pf_partitioning";  //$NON-NLS-1$
+	protected static String COMMENT = "__pf_comment"; //$NON-NLS-1$
+	protected static String PROPERTY_VALUE = "__pf_roperty_value"; //$NON-NLS-1$
+	protected static String[] PARTITIONS = new String[] { COMMENT, PROPERTY_VALUE };
+
+	private BasePDEScanner fPropertyKeyScanner;
+	private BasePDEScanner fCommentScanner;
+	private BasePDEScanner fPropertyValueScanner;
+	private IColorManager fColorManager;
+	
+	private MonoReconciler fReconciler;
+	private BuildSourcePage fSourcePage;
+	
+	private abstract class AbstractJavaScanner extends BasePDEScanner {
+		
+	    public void adaptToPreferenceChange(PropertyChangeEvent event) {
+	    	String property= event.getProperty();
+	    	if (affectsTextPresentation(property)) {
+	    		Token token = getTokenAffected(event);
+	    		if (property.endsWith(PreferenceConstants.EDITOR_BOLD_SUFFIX))
+	    			adaptToStyleChange(event, token, SWT.BOLD);
+	    		else if (property.endsWith(PreferenceConstants.EDITOR_ITALIC_SUFFIX))
+	    			adaptToStyleChange(event, token, SWT.ITALIC);
+	    		else if (property.endsWith(PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX))
+	    			adaptToStyleChange(event, token, TextAttribute.STRIKETHROUGH);
+	    		else if (property.endsWith(PreferenceConstants.EDITOR_UNDERLINE_SUFFIX))
+	    			adaptToStyleChange(event, token, TextAttribute.UNDERLINE);
+	    		else
+	    			adaptToColorChange(event, token);
+	    	}
+	    }
+		
+		protected TextAttribute createTextAttribute(String property) {
+			Color color = fColorManager.getColor(property);
+			int style = SWT.NORMAL;
+			if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_BOLD_SUFFIX))
+				style |= SWT.BOLD;
+			if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_ITALIC_SUFFIX))
+				style |= SWT.ITALIC;
+			if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX))
+				style |= TextAttribute.STRIKETHROUGH;
+			if (fPreferenceStore.getBoolean(property + PreferenceConstants.EDITOR_UNDERLINE_SUFFIX))
+				style |= TextAttribute.UNDERLINE;
+			return new TextAttribute(color, null, style);
+		}
+	}
+
+	private class SingleTokenJavaScanner extends AbstractJavaScanner {
+
+		private String fProperty;
+		public SingleTokenJavaScanner(String property) {
+			fProperty = property;
+			setColorManager(fColorManager);
+			initialize();
+		}
+
+		public boolean affectsTextPresentation(String property) {
+			return property.startsWith(fProperty);
+		}
+
+		protected Token getTokenAffected(PropertyChangeEvent event) {
+			return (Token)fDefaultReturnToken;
+		}
+
+		protected void initialize() {
+			setDefaultReturnToken(new Token(createTextAttribute(fProperty)));			
+		}
+	}
+
+	public class PropertyValueScanner extends AbstractJavaScanner {
+
+		public class AssignmentDetector implements IWordDetector {
+
+			public boolean isWordStart(char c) {
+				if ('=' != c && ':' != c || fDocument == null)
+					return false;
+
+				try {
+					// check whether it is the first '='
+					IRegion lineInfo = fDocument.getLineInformationOfOffset(fOffset);
+					int offset = lineInfo.getOffset();
+					String line = fDocument.get(offset, lineInfo.getLength());
+					int i = line.indexOf(c);
+					return i != -1 && i + lineInfo.getOffset() + 1 == fOffset;
+				} catch (BadLocationException ex) {
+					return false;
+				}
+			}
+
+			public boolean isWordPart(char c) {
+				return false;
+			}
+		}	
+
+		private Token fArgumentToken;
+		private Token fAssignmentToken;
+
+		public PropertyValueScanner() {
+			setColorManager(fColorManager);
+			initialize();
+		}
+		
+		public boolean affectsTextPresentation(String property) {
+			return property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_VALUE)
+					|| property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT) 
+					|| property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT);
+		}
+
+		protected Token getTokenAffected(PropertyChangeEvent event) {
+			String property = event.getProperty();
+			if (property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT))
+				return fArgumentToken;
+			if (property.startsWith(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT))
+				return fAssignmentToken;
+			return (Token)fDefaultReturnToken;
+		}
+
+		protected void initialize() {
+			IRule[] rules = new IRule[3];
+			fArgumentToken = new Token(createTextAttribute(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT));			
+			rules[0] = new ArgumentRule(fArgumentToken);
+			
+			fAssignmentToken = new Token(createTextAttribute(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT));
+			rules[1] = new WordRule(new AssignmentDetector(), fAssignmentToken);
+			
+			rules[2] = new WhitespaceRule(new IWhitespaceDetector() {
+				public boolean isWhitespace(char c) {
+					return Character.isWhitespace(c);
+				}			
+			});
+			setRules(rules);
+			setDefaultReturnToken(new Token(createTextAttribute(PreferenceConstants.PROPERTIES_FILE_COLORING_VALUE)));
+		}
+	}
+	
+	public BuildSourceViewerConfiguration(IColorManager colorManager, IPreferenceStore store, BuildSourcePage sourcePage) {
+		super(store);
+		fColorManager = colorManager;
+		fSourcePage = sourcePage;
+		initializeScanners();
+	}
+
+
+	private void initializeScanners() {
+		fPropertyKeyScanner = new SingleTokenJavaScanner(PreferenceConstants.PROPERTIES_FILE_COLORING_KEY);
+		fPropertyValueScanner = new PropertyValueScanner();
+		fCommentScanner = new SingleTokenJavaScanner(PreferenceConstants.PROPERTIES_FILE_COLORING_COMMENT);
+	}
+
+	public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+		PresentationReconciler reconciler = new PresentationReconciler();
+		reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+
+		DefaultDamagerRepairer dr = new DefaultDamagerRepairer(fPropertyKeyScanner);
+		reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+		reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+		dr = new DefaultDamagerRepairer(fCommentScanner);
+		reconciler.setDamager(dr, COMMENT);
+		reconciler.setRepairer(dr, COMMENT);
+
+		dr = new DefaultDamagerRepairer(fPropertyValueScanner);
+		reconciler.setDamager(dr, PROPERTY_VALUE);
+		reconciler.setRepairer(dr, PROPERTY_VALUE);
+
+		return reconciler;
+	}
+
+	public IReconciler getReconciler(ISourceViewer sourceViewer) {
+		if (fReconciler == null) {
+			IBaseModel model = fSourcePage.getInputContext().getModel();
+			if (model instanceof IReconcilingParticipant) {
+				ReconcilingStrategy strategy = new ReconcilingStrategy();
+				strategy.addParticipant((IReconcilingParticipant)model);
+				if (fSourcePage.getContentOutline() instanceof IReconcilingParticipant)
+					strategy.addParticipant((IReconcilingParticipant)fSourcePage.getContentOutline());
+				fReconciler = new MonoReconciler(strategy, false);
+				fReconciler.setDelay(500);
+			}
+		}
+		return fReconciler;
+	}
+	
+	public void handlePropertyChangeEvent(PropertyChangeEvent event) {
+		if (affectsColorPresentation(event.getProperty()))
+			fColorManager.handlePropertyChangeEvent(event);
+		fPropertyKeyScanner.adaptToPreferenceChange(event);
+		fCommentScanner.adaptToPreferenceChange(event);
+		fPropertyValueScanner.adaptToPreferenceChange(event);
+	}
+	
+	public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+		int length = PARTITIONS.length;
+		String[] contentTypes = new String[length + 1];
+		contentTypes[0] = IDocument.DEFAULT_CONTENT_TYPE;
+		for (int i = 0; i < length; i++)
+			contentTypes[i+1] = PARTITIONS[i];
+
+		return contentTypes;
+	}
+
+	public String getConfiguredDocumentPartitioning(ISourceViewer sourceViewer) {
+		return PROPERTIES_FILE_PARTITIONING;
+	}
+	
+	public boolean affectsTextPresentation(PropertyChangeEvent event) {
+		String property = event.getProperty();
+		return fCommentScanner.affectsTextPresentation(property)
+				|| fPropertyKeyScanner.affectsTextPresentation(property)
+				|| fPropertyValueScanner.affectsTextPresentation(property);
+	}
+	
+	private boolean affectsColorPresentation(String property) {
+		 return property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_VALUE)
+					|| property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_ARGUMENT) 
+					|| property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_ASSIGNMENT)
+	 				|| property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_KEY)
+	 				|| property.equals(PreferenceConstants.PROPERTIES_FILE_COLORING_COMMENT);
+	}
+}
+
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUndoManager.java
new file mode 100644
index 0000000..5d9a7d3
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUndoManager.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.ModelUndoManager;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.build.IBuild;
+import org.eclipse.pde.core.build.IBuildEntry;
+import org.eclipse.pde.core.build.IBuildModel;
+import org.eclipse.pde.internal.core.build.BuildObject;
+import org.eclipse.pde.internal.core.build.IBuildObject;
+
+public class BuildUndoManager extends ModelUndoManager {
+
+	public BuildUndoManager(PDEFormEditor editor) {
+		super(editor);
+		setUndoLevelLimit(30);
+	}
+
+	protected String getPageId(Object obj) {
+		if (obj instanceof IBuildEntry)
+			return BuildPage.PAGE_ID;
+		return null;
+	}
+
+	protected void execute(IModelChangedEvent event, boolean undo) {
+		Object[] elements = event.getChangedObjects();
+		int type = event.getChangeType();
+		String propertyName = event.getChangedProperty();
+		IBuildModel model = (IBuildModel)event.getChangeProvider();
+
+		switch (type) {
+			case IModelChangedEvent.INSERT :
+				if (undo)
+					executeRemove(model, elements);
+				else
+					executeAdd(model, elements);
+				break;
+			case IModelChangedEvent.REMOVE :
+				if (undo)
+					executeAdd(model, elements);
+				else
+					executeRemove(model, elements);
+				break;
+			case IModelChangedEvent.CHANGE :
+				if (undo)
+					executeChange(
+						elements[0],
+						propertyName,
+						event.getNewValue(),
+						event.getOldValue());
+				else
+					executeChange(
+						elements[0],
+						propertyName,
+						event.getOldValue(),
+						event.getNewValue());
+		}
+	}
+
+	private void executeAdd(IBuildModel model, Object[] elements) {
+		IBuild build = model.getBuild();
+
+		try {
+			for (int i = 0; i < elements.length; i++) {
+				Object element = elements[i];
+
+				if (element instanceof IBuildEntry) {
+					build.add((IBuildEntry)element);
+				}
+			}
+		} catch (CoreException e) {
+		}
+	}
+
+	private void executeRemove(IBuildModel model, Object[] elements) {
+		IBuild build = model.getBuild();
+
+		try {
+			for (int i = 0; i < elements.length; i++) {
+				Object element = elements[i];
+
+				if (element instanceof IBuildEntry) {
+					build.remove((IBuildEntry)element);
+				}
+			}
+		} catch (CoreException e) {
+		}
+	}
+
+	private void executeChange(
+		Object element,
+		String propertyName,
+		Object oldValue,
+		Object newValue) {
+		if (element instanceof BuildObject) {
+			BuildObject bobj = (BuildObject) element;
+			try {
+				bobj.restoreProperty(propertyName, oldValue, newValue);
+			} catch (CoreException e) {
+			}
+		}
+	}
+
+	public void modelChanged(IModelChangedEvent event) {
+		if (event.getChangeType() == IModelChangedEvent.CHANGE) {
+			Object obj = event.getChangedObjects()[0];
+			if (obj instanceof IBuildObject) {
+				IBuildObject bobj = (IBuildObject) event.getChangedObjects()[0];
+				//Ignore events from objects that are not yet in the model.
+				if (!(bobj instanceof IBuild) && bobj.isInTheModel() == false)
+					return;
+			}
+		}
+		super.modelChanged(event);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUtil.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUtil.java
new file mode 100644
index 0000000..0251a82
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/BuildUtil.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.util.Vector;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+
+public class BuildUtil {
+
+	public static IBuildEntry[] getBuildLibraries(IBuildEntry[] entries) {
+		Vector temp = new Vector();
+		for (int i = 0; i < entries.length; i++) {
+			if (entries[i].getName().startsWith(IBuildEntry.JAR_PREFIX))
+				temp.add(entries[i]);
+		}
+		IBuildEntry[] result = new IBuildEntry[temp.size()];
+		temp.copyInto(result);
+		return result;
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/IBuildPropertiesConstants.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/IBuildPropertiesConstants.java
new file mode 100644
index 0000000..663758c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/IBuildPropertiesConstants.java
@@ -0,0 +1,54 @@
+/**********************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+public interface IBuildPropertiesConstants {
+	public final static String PERMISSIONS = "permissions"; //$NON-NLS-1$
+	public final static String LINK = "link"; //$NON-NLS-1$
+	public final static String EXECUTABLE = "executable"; //$NON-NLS-1$
+	public final static String ROOT_PREFIX = "root."; //$NON-NLS-1$
+	public final static String ROOT = "root"; //$NON-NLS-1$
+
+	public final static String TRUE = "true"; //$NON-NLS-1$
+	public final static String FALSE = "false"; //$NON-NLS-1$
+
+	public static final String PROPERTY_JAR_EXTRA_CLASSPATH = "jars.extra.classpath"; //$NON-NLS-1$
+	public static final String PROPERTY_JAR_ORDER = "jars.compile.order"; //$NON-NLS-1$
+	public static final String PROPERTY_SOURCE_PREFIX = "source."; //$NON-NLS-1$
+	public static final String PROPERTY_OUTPUT_PREFIX = "output."; //$NON-NLS-1$
+	public static final String PROPERTY_EXTRAPATH_PREFIX = "extra."; //$NON-NLS-1$	
+	public static final String PROPERTY_JAR_SUFFIX = ".jar"; //$NON-NLS-1$
+
+	public static final String PROPERTY_QUALIFIER = "qualifier"; //$NON-NLS-1$
+	public static final String PROPERTY_NONE = "none"; //$NON-NLS-1$
+	public static final String PROPERTY_CONTEXT = "context"; //$NON-NLS-1$
+
+	public final static String GENERATION_SOURCE_PREFIX = "generate."; //$NON-NLS-1$
+	public final static String GENERATION_SOURCE_FEATURE_PREFIX = GENERATION_SOURCE_PREFIX + "feature@"; //$NON-NLS-1$
+	public final static String GENERATION_SOURCE_PLUGIN_PREFIX = GENERATION_SOURCE_PREFIX + "plugin@"; //$NON-NLS-1$
+	public final static String PROPERTY_SOURCE_FEATURE_NAME = "sourceFeature.name"; //$NON-NLS-1$
+	
+	public static final String PROPERTY_CUSTOM = "custom"; //$NON-NLS-1$
+	public static final String PROPERTY_ZIP_SUFFIX = ".zip"; //$NON-NLS-1$
+
+	public static final String PROPERTY_BIN_EXCLUDES = "bin.excludes"; //$NON-NLS-1$
+	public static final String PROPERTY_BIN_INCLUDES = "bin.includes"; //$NON-NLS-1$
+
+	public static final String PROPERTY_SRC_EXCLUDES = "src.excludes"; //$NON-NLS-1$
+	public static final String PROPERTY_SRC_INCLUDES = "src.includes"; //$NON-NLS-1$
+
+	public static final String DEFAULT_MATCH_ALL = "*"; //$NON-NLS-1$
+	public static final String DEFAULT_FINAL_SHAPE = "*"; //$NON-NLS-1$
+	
+	//Internal usage only
+	public static final String SOURCE_PLUGIN = "sourcePlugin"; //$NON-NLS-1$
+}
+
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/PropertiesUtil.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/PropertiesUtil.java
new file mode 100644
index 0000000..c4149d8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/PropertiesUtil.java
@@ -0,0 +1,130 @@
+/**********************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: 
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import java.io.PrintWriter;
+import java.util.Enumeration;
+
+/**
+ * @author dejan
+ *
+ */
+public class PropertiesUtil {
+	private static final char[] HEX =
+		{
+			'0',
+			'1',
+			'2',
+			'3',
+			'4',
+			'5',
+			'6',
+			'7',
+			'8',
+			'9',
+			'A',
+			'B',
+			'C',
+			'D',
+			'E',
+			'F' };
+
+	public static String createWritableName(String source) {
+		if (source.indexOf(' ') == -1)
+			return source;
+		// has blanks 
+		StringBuffer writableName = new StringBuffer();
+		for (int i = 0; i < source.length(); i++) {
+			char c = source.charAt(i);
+			if (c == ' ') {
+				writableName.append("\\ "); //$NON-NLS-1$
+			} else
+				writableName.append(c);
+		}
+		return writableName.toString();
+	}
+
+	public static String createEscapedValue(String value) {
+		// if required, escape property values as \\uXXXX		
+		StringBuffer buf = new StringBuffer(value.length() * 2);
+		// assume expansion by less than factor of 2
+		for (int i = 0; i < value.length(); i++) {
+			char character = value.charAt(i);
+			if (character == '\\'
+				|| character == '\t'
+				|| character == '\r'
+				|| character == '\n'
+				|| character == '\f') {
+				// handle characters requiring leading \
+				buf.append('\\');
+				buf.append(character);
+			} else if ((character < 0x0020) || (character > 0x007e)) {
+				// handle characters outside base range (encoded)
+				buf.append('\\');
+				buf.append('u');
+				buf.append(HEX[(character >> 12) & 0xF]); // first nibble
+				buf.append(HEX[(character >> 8) & 0xF]); // second nibble
+				buf.append(HEX[(character >> 4) & 0xF]); // third nibble
+				buf.append(HEX[character & 0xF]); // fourth nibble
+			} else {
+				// handle base characters
+				buf.append(character);
+			}
+		}
+		return buf.toString();
+	}
+	
+	public static void writeKeyValuePair(String name, String value, PrintWriter writer) {
+		String writableName = createWritableName(name);
+		writer.print(writableName + " = "); //$NON-NLS-1$
+
+		writer.println(PropertiesUtil.createEscapedValue(value));
+	}
+
+	public static void writeKeyValuePair(String name, Enumeration tokens, PrintWriter writer) {
+		String writableName = createWritableName(name);
+		writer.print(writableName + " = "); //$NON-NLS-1$
+		if (!tokens.hasMoreElements()) {
+			writer.println();
+			return;
+		}
+		int indentLength = name.length() + 3;
+		for (;tokens.hasMoreElements();) {
+			String token = tokens.nextElement().toString();
+			writer.print(PropertiesUtil.createEscapedValue(token));
+			if (tokens.hasMoreElements()) {
+				writer.println(",\\"); //$NON-NLS-1$
+				for (int j = 0; j < indentLength; j++) {
+					writer.print(" "); //$NON-NLS-1$
+				}
+			} else
+				writer.println(""); //$NON-NLS-1$
+		}
+	}
+	
+	public static String writeKeyValuePair(String name, String[] tokens) {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append(createWritableName(name));
+		buffer.append(" = "); //$NON-NLS-1$
+		int indentLength = name.length() + 3;
+		for (int i = 0; i < tokens.length; i++) {
+			buffer.append(createEscapedValue(tokens[i]));
+			if (i < tokens.length - 1) {
+				buffer.append(",\\" + System.getProperty("line.separator")); //$NON-NLS-1$ //$NON-NLS-2$
+				for (int j = 0; j < indentLength; j++) {
+					buffer.append(" "); //$NON-NLS-1$
+				}
+			}
+		}	
+		buffer.append(System.getProperty("line.separator")); //$NON-NLS-1$
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/SrcSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/SrcSection.java
new file mode 100644
index 0000000..186f7e8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/SrcSection.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Common Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuild;
+import org.eclipse.ajdt.internal.buildconfig.editor.model.IBuildEntry;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.core.resources.*;
+import org.eclipse.pde.core.IModelChangedListener;
+import org.eclipse.swt.widgets.Composite;
+
+public class SrcSection extends BuildContentsSection
+		implements
+			IModelChangedListener {
+
+	public SrcSection(BuildPage page, Composite parent) {
+		super(page, parent);
+		getSection().setText(UIMessages.AJPropsEditor_SrcSection_title);
+		getSection().setDescription(UIMessages.AJPropsEditor_SrcSection_desc);
+
+	}
+	
+	protected void initializeCheckState() {
+
+		super.initializeCheckState();
+		IBuild build = fBuildModel.getBuild();
+
+		IBuildEntry srcIncl = build
+			.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		IBuildEntry srcExcl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		
+		if (srcIncl == null)
+			return;
+
+		super.initializeCheckState(srcIncl, srcExcl);
+
+	}
+
+	protected void deleteFolderChildrenFromEntries(IFolder folder) {
+		IBuild build = fBuildModel.getBuild();
+		IBuildEntry srcIncl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		IBuildEntry srcExcl = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+		String parentFolder = getResourceFolderName(folder
+				.getProjectRelativePath().toString());
+
+		removeChildren(srcIncl, parentFolder);
+		removeChildren(srcExcl, parentFolder);
+	}
+
+	protected void handleBuildCheckStateChange(boolean wasTopParentChecked) {
+		IResource resource = fParentResource;
+		String resourceName = fParentResource.getFullPath()
+				.removeFirstSegments(1).toString();
+		IBuild build = fBuildModel.getBuild();
+		IBuildEntry includes = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		IBuildEntry excludes = build
+				.getEntry(IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+
+		resourceName = handleResourceFolder(resource, resourceName);
+
+		if (isChecked)
+			handleCheck(includes, excludes, resourceName, resource,
+					wasTopParentChecked,
+					IBuildPropertiesConstants.PROPERTY_SRC_INCLUDES);
+		else
+			handleUncheck(includes, excludes, resourceName, resource,
+					IBuildPropertiesConstants.PROPERTY_SRC_EXCLUDES);
+
+		deleteEmptyEntries();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/WriteThread.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/WriteThread.java
new file mode 100644
index 0000000..8e82e84
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/WriteThread.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.editor;
+
+public class WriteThread extends Thread{
+	
+	private static WriteThread instance;
+	//we only need to remember the last posted job and not the
+	//whole queue because jobs in the middle of the queue get
+	//overwritten anyway by the subsequent ones
+	private static Runnable nextJob;
+	
+	private WriteThread(){}
+	
+	public static synchronized void asyncExec(Runnable r){
+		nextJob = r;
+		if (instance == null){
+			instance = new WriteThread();
+			instance.start();
+		}
+	}
+	
+	private synchronized Runnable getNextJob(){
+		Runnable temp = nextJob;
+		if (temp == null){
+			instance = null;
+			return null;
+		}
+		nextJob = null;
+		return temp;
+	}
+	
+	public void run(){
+		Runnable myRunnable = getNextJob();
+		while(myRunnable != null){
+			myRunnable.run();
+			myRunnable = getNextJob();
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/Build.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/Build.java
new file mode 100644
index 0000000..78e3957
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/Build.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.ModelChangedEvent;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+
+public class Build implements IBuild {
+	
+	private BuildModel fModel;
+	private HashMap fEntries = new HashMap();
+
+	public Build(BuildModel model) {
+		fModel = model;	
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuild#add(org.eclipse.pde.core.build.IBuildEntry)
+	 */
+	public void add(IBuildEntry entry) {
+		fEntries.put(entry.getName(), entry);
+		fModel.fireModelChanged(new ModelChangedEvent(fModel,
+				IModelChangedEvent.INSERT, new Object[]{entry}, null));
+	}
+	public void addWithoutNotify(IBuildEntry entry) {
+		fEntries.put(entry.getName(), entry);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuild#getBuildEntries()
+	 */
+	public IBuildEntry[] getBuildEntries() {
+		return (IBuildEntry[])fEntries.values().toArray(new IBuildEntry[fEntries.size()]);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuild#getEntry(java.lang.String)
+	 */
+	public IBuildEntry getEntry(String name) {
+		return (IBuildEntry)fEntries.get(name);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuild#remove(org.eclipse.pde.core.build.IBuildEntry)
+	 */
+	public void remove(IBuildEntry entry) {
+		fEntries.remove(entry.getName());
+		fModel.fireModelChanged(new ModelChangedEvent(fModel,
+				IModelChangedEvent.REMOVE, new Object[]{entry}, null));
+	}
+	public void removeWithoutNotify(IBuildEntry entry) {
+		fEntries.remove(entry.getName());
+	}
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.pde.core.IWritable#write(java.lang.String,
+	 *      java.io.PrintWriter)
+	 */
+	public void write(String indent, PrintWriter writer) {
+	}
+	
+	public void load(InputStream source) throws IOException {
+		fEntries.clear();
+		Properties properties = new Properties();
+		properties.load(source);
+		Enumeration iter = properties.keys();
+		while (iter.hasMoreElements()) {
+			String name = iter.nextElement().toString();
+			BuildEntry entry = (BuildEntry)fModel.getFactory().createEntry(name);
+			entry.processEntry(properties.get(name).toString());
+			fEntries.put(name, entry);
+		}
+		adjustOffsets(fModel.getDocument());
+	}
+	
+	public void adjustOffsets(IDocument document) {	
+		int lines = document.getNumberOfLines();
+		try {
+			IDocumentKey currentKey = null;
+			for (int i = 0; i < lines; i++) {
+				int offset = document.getLineOffset(i);
+				int length = document.getLineLength(i);
+				String line = document.get(offset, length);
+				if (line.startsWith("#") | line.startsWith("!")) { //$NON-NLS-1$ //$NON-NLS-2$
+					if (currentKey != null) {
+						currentKey.setLength(offset - 1 - currentKey.getOffset());
+						currentKey = null;
+					}
+					continue;
+				}
+				
+				line = line.trim();
+				if (line.length() == 0)
+					continue;
+				
+				if (currentKey != null) {
+					if (!line.endsWith("\\")) { //$NON-NLS-1$
+						currentKey.setLength(offset + document.getLineLength(i) - currentKey.getOffset());
+						currentKey = null;
+					}
+				} else {
+					int index = line.indexOf('=');
+					if (index == -1) 
+						index = line.indexOf(':');
+					if (index == -1)
+						index = line.indexOf(' ');
+					if (index == -1)
+						index = line.indexOf('\t');
+					String name = (index != -1) ? line.substring(0, index).trim() : line;
+					currentKey = (IDocumentKey)getEntry(name);
+					if (currentKey != null) {
+						while (Character.isSpaceChar(document.getChar(offset))) {
+							offset += 1;
+						}
+						currentKey.setOffset(offset);
+						if (!line.endsWith("\\")) { //$NON-NLS-1$
+							currentKey.setLength(document.getLineOffset(i) + document.getLineLength(i) - currentKey.getOffset());
+							currentKey = null;
+						}
+					}
+				}
+			}
+		} catch (BadLocationException e) {
+		}
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildEntry.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildEntry.java
new file mode 100644
index 0000000..5cbebc7
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildEntry.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import org.eclipse.ajdt.internal.buildconfig.editor.PropertiesUtil;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+
+public class BuildEntry implements IBuildEntry, IDocumentKey {
+
+	private int fLength = -1;
+	private int fOffset = -1;
+	private IBuildModel fModel;
+	private String fName;
+	private ArrayList fTokens = new ArrayList();
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildEntry#addToken(java.lang.String)
+	 */
+	public void addToken(String token) {
+		fTokens.add(token);
+		getModel().fireModelObjectChanged(this, getName(), null, token);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildEntry#addToken(java.lang.String)
+	 */
+	public void addTokenWithoutNotify(String token) {
+		fTokens.add(token);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.IDocumentKey#getName()
+	 */
+	public String getName() {
+		return fName;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildEntry#getTokens()
+	 */
+	public String[] getTokens() {
+		return (String[])fTokens.toArray(new String[fTokens.size()]);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildEntry#contains(java.lang.String)
+	 */
+	public boolean contains(String token) {
+		return fTokens.contains(token);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildEntry#removeToken(java.lang.String)
+	 */
+	public void removeToken(String token) {
+		fTokens.remove(token);
+		getModel().fireModelObjectChanged(this, getName(), token, null);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildEntry#removeToken(java.lang.String)
+	 */
+	public void removeTokenWithoutNotify(String token) {
+		fTokens.remove(token);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildEntry#renameToken(java.lang.String, java.lang.String)
+	 */
+	public void renameToken(String oldToken, String newToken) {
+		int index = fTokens.indexOf(oldToken);
+		if (index != -1) {
+			fTokens.set(index, newToken);
+			getModel().fireModelObjectChanged(this, getName(), oldToken, newToken);
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.IDocumentKey#setName(java.lang.String)
+	 */
+	public void setName(String name) {
+		String oldName = fName;
+		fName = name;
+		if (getModel() != null)
+			getModel().fireModelObjectChanged(this, getName(), oldName, name);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.IDocumentKey#getOffset()
+	 */
+	public int getOffset() {
+		return fOffset;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.IDocumentKey#setOffset(int)
+	 */
+	public void setOffset(int offset) {
+		fOffset = offset;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.IDocumentKey#getLength()
+	 */
+	public int getLength() {
+		return fLength;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.IDocumentKey#setLength(int)
+	 */
+	public void setLength(int length) {
+		fLength = length;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.IWritable#write(java.lang.String, java.io.PrintWriter)
+	 */
+	public void write(String indent, PrintWriter writer) {
+	}
+	
+	public void setModel(IBuildModel model) {
+		fModel = model;
+	}
+	
+	public IBuildModel getModel() {
+		return fModel;
+	}
+	
+	public void processEntry(String value) {
+		StringTokenizer stok = new StringTokenizer(value, ","); //$NON-NLS-1$
+		while (stok.hasMoreTokens()) {
+			fTokens.add(stok.nextToken().trim());
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.IDocumentKey#write()
+	 */
+	public String write() {
+		return PropertiesUtil.writeKeyValuePair(getName(), getTokens());
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModel.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModel.java
new file mode 100644
index 0000000..aa66190
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModel.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.pde.internal.core.NLResourceHelper;
+import org.eclipse.pde.internal.core.text.AbstractEditingModel;
+
+
+public class BuildModel extends AbstractEditingModel implements IBuildModel {
+	
+	//private Properties fProperties;
+	private BuildModelFactory fFactory;
+	private Build fBuild;
+
+	/**
+	 * @param document
+	 * @param isReconciling
+	 */
+	public BuildModel(IDocument document, boolean isReconciling) {
+		super(document, isReconciling);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.AbstractEditingModel#createNLResourceHelper()
+	 */
+	protected NLResourceHelper createNLResourceHelper() {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.IModel#load(java.io.InputStream, boolean)
+	 */
+	public void load(InputStream source, boolean outOfSync) {
+		try {
+			fLoaded = true;
+			((Build)getBuild()).load(source);
+		} catch (IOException e) {
+			fLoaded = false;
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.model.AbstractEditingModel#adjustOffsets(org.eclipse.jface.text.IDocument)
+	 */
+	protected void adjustOffsets(IDocument document) {
+		((Build)getBuild()).adjustOffsets(document);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildModel#getBuild()
+	 */
+	public IBuild getBuild() {
+		if (fBuild == null)
+			fBuild = new Build(this);
+		return fBuild;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildModel#getFactory()
+	 */
+	public IBuildModelFactory getFactory() {
+		if (fFactory == null)
+			fFactory = new BuildModelFactory(this);
+		return fFactory;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModelFactory.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModelFactory.java
new file mode 100644
index 0000000..9e0bc8c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/BuildModelFactory.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+public class BuildModelFactory implements IBuildModelFactory {
+	
+	private IBuildModel fModel;
+	
+	public BuildModelFactory(IBuildModel model) {
+		fModel = model;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.core.build.IBuildModelFactory#createEntry(java.lang.String)
+	 */
+	public IBuildEntry createEntry(String name) {
+		BuildEntry entry = new BuildEntry();
+		entry.setName(name);
+		entry.setModel(fModel);
+		return entry;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuild.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuild.java
new file mode 100644
index 0000000..d5a8607
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuild.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.core.*;
+/**
+ * The top-level model object of the model that is created from
+ * "build.properties" file.
+ *  
+ */
+public interface IBuild extends IWritable {
+	/**
+	 * Adds a new build entry. This method can throw a CoreException if the
+	 * model is not editable.
+	 * 
+	 * @param entry
+	 *            an entry to be added
+	 */
+	void add(IBuildEntry entry) throws CoreException;
+	
+	/**
+	 * Adds a new build entry.
+	 * 
+	 * @param entry
+	 *            an entry to be added
+	 */
+	void addWithoutNotify(IBuildEntry entry);
+	
+	/**
+	 * Returns all the build entries in this object.
+	 * 
+	 * @return an array of build entries
+	 */
+	IBuildEntry[] getBuildEntries();
+	/**
+	 * Returns the build entry with the specified name.
+	 * 
+	 * @param the
+	 *            name of the desired entry
+	 * @return the entry object with the specified name, or <samp>null </samp>
+	 *         if not found.
+	 */
+	IBuildEntry getEntry(String name);
+	/**
+	 * Removes a build entry. This method can throw a CoreException if the model
+	 * is not editable.
+	 * 
+	 * @param entry
+	 *            an entry to be removed
+	 */
+	void remove(IBuildEntry entry) throws CoreException;
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildEntry.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildEntry.java
new file mode 100644
index 0000000..483a516
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildEntry.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.core.*;
+/**
+ * Jar entry represents one 'library=folder list' entry
+ * in plugin.jars file.
+ */
+public interface IBuildEntry extends IWritable {
+	/**
+	 * A property name for changes to the 'name' field.
+	 */
+	public static final String P_NAME = "name"; //$NON-NLS-1$
+	/**
+	 * A property name for changes to the '' field.
+	 */
+	public static final String JAR_PREFIX = "source."; //$NON-NLS-1$
+	/**
+	 * A property name for changes to the 'name' field.
+	 */	
+	public static final String OUTPUT_PREFIX = "output."; //$NON-NLS-1$
+	/**
+	 * A property name for changes to the 'name' field.
+	 */	
+	public static final String BIN_INCLUDES = "bin.includes"; //$NON-NLS-1$
+	/**
+	 * A property name for changes to the 'name' field.
+	 */	
+	public static final String SRC_INCLUDES = "src.includes"; //$NON-NLS-1$
+	/**
+	 * A property name for changes to the 'name' field.
+	 */	
+	public static final String JARS_EXTRA_CLASSPATH = "jars.extra.classpath"; //$NON-NLS-1$
+	/**
+	 * Adds the token to the list of token for this entry.
+	 * This method will throw a CoreException if
+	 * the model is not editable.
+	 *
+	 * @param token a name to be added to the list of tokens
+	 */
+	void addToken(String token) throws CoreException;
+	
+	/**
+	 * Adds the token to the list of token for this entry.
+	 *
+	 * @param token a name to be added to the list of tokens
+	 */
+	void addTokenWithoutNotify(String token);
+
+	/**
+	 * Returns a model that owns this entry
+	 * @return build.properties model
+	 */
+	IBuildModel getModel();
+	/**
+	 * Returns the name of this entry.
+	 * @return the entry name
+	 */
+	String getName();
+	/**
+	 * Returns an array of tokens for this entry
+	 * @return array of tokens
+	 */
+	String[] getTokens();
+
+	/**
+	 * Returns true if the provided token exists in this entry.
+	 * @return true if the token exists in the entry
+	 */
+	boolean contains(String token);
+	/**
+	 * Removes the token from the list of tokens for this entry.
+	 * This method will throw a CoreException if
+	 * the model is not editable.
+	 *
+	 * @param token a name to be removed from the list of tokens
+	 */
+	void removeToken(String token) throws CoreException;
+	
+	/**
+	 * Removes the token from the list of tokens for this entry.
+	 *
+	 * @param token a name to be removed from the list of tokens
+	 */
+	void removeTokenWithoutNotify(String token);
+	
+	/**
+	 * Changes the name of the token without changing its
+	 * position in the list. This method will throw
+	 * a CoreException if the model is not editable.
+	 *
+	 * @param oldToken the old token name
+	 * @param newToken the new token name
+	 */
+	void renameToken(String oldToken, String newToken) throws CoreException;
+	/**
+	 * Sets the name of this build entry. This
+	 * method will throw a CoreException if
+	 * model is not editable.
+	 *
+	 * @param name the new name for the entry
+	 */
+	void setName(String name) throws CoreException;
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModel.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModel.java
new file mode 100644
index 0000000..1726ef6
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModel.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+import org.eclipse.pde.core.*;
+/**
+ * This model is created from the "plugin.jars" file
+ * that defines what source folders in the plug-in are
+ * to be used to build require plug-in Jars.
+ * <p>
+ * If this model is editable, isEditable() will return
+ * true and the model instance will implement IEditable
+ * interface. The model is capable of providing
+ * change notification for the registered listeners.
+ */
+public interface IBuildModel extends IModel, IModelChangeProvider {
+	/**
+	 * Returns the top-level model object of this model.
+	 *
+	 * @return a build.properties top-level model object
+	 */
+	IBuild getBuild();
+	/**
+	 * Returns the factory that should be used
+	 * to create new instance of model objects.
+	 * @return the build.properties model factory
+	 */
+	IBuildModelFactory getFactory();
+	/**
+	 * Returns the location of the file
+	 * used to create the model.
+	 *
+	 * @return the location of the build.properties file
+	 * or <samp>null</samp> if the file
+	 * is in a workspace.
+	 */
+	String getInstallLocation();
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModelFactory.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModelFactory.java
new file mode 100644
index 0000000..3dbaf95
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/editor/model/IBuildModelFactory.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.editor.model;
+
+/**
+ * This model factory should be used to
+ * create new instances of plugin.jars model
+ * objects.
+ */
+public interface IBuildModelFactory {
+	/**
+	 * Creates a new build entry with
+	 * the provided name.
+	 * @return a new build.properties entry instance
+	 */
+	IBuildEntry createEntry(String name);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/AddBuildConfigurationAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/AddBuildConfigurationAction.java
new file mode 100644
index 0000000..3ca07f0
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/AddBuildConfigurationAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.menu;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurationCreationException;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.jface.action.Action;
+
+/**
+ * @author Luzius Meisser
+ *
+ * Action to add a Build Configuration
+ */
+public class AddBuildConfigurationAction extends Action {
+	static int counter = 0;
+
+	IBuildConfigurator buildconf;
+	
+	AddBuildConfigurationAction(){
+		super(UIMessages.BCLabels_SaveBCAs);
+		buildconf = DefaultBuildConfigurator.getBuildConfigurator();
+	}
+	
+	public void run(){
+		if (buildconf.getActiveProjectBuildConfigurator() == null){
+			return;
+		}
+		IProjectBuildConfigurator pbc = buildconf.getActiveProjectBuildConfigurator();
+		
+		try {
+			new BuildConfiguration(pbc, null);
+		} catch (BuildConfigurationCreationException e) {
+			// creation failed, maybe user has cancelled it, do nothing
+			// can be ignored
+		}
+		
+	}
+	
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/BuildConfigurationSelectedAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/BuildConfigurationSelectedAction.java
new file mode 100644
index 0000000..0c3a52a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/BuildConfigurationSelectedAction.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.menu;
+
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.jface.action.Action;
+
+/**
+ * @author Luzius Meisser
+ * 
+ * Action to select a build configuration
+ */
+
+public class BuildConfigurationSelectedAction extends Action {
+	IProjectBuildConfigurator pbc;
+	IBuildConfiguration myBC; 
+	
+	public BuildConfigurationSelectedAction(IBuildConfiguration bc){
+		super(bc.getName());
+		myBC = bc;
+		pbc = DefaultBuildConfigurator.getBuildConfigurator().getActiveProjectBuildConfigurator();
+	}
+	
+	public void run(){
+		pbc.setActiveBuildConfiguration(myBC);
+	}
+	
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/DynamicBuildConfigurationMenu.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/DynamicBuildConfigurationMenu.java
new file mode 100644
index 0000000..9840571
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/menu/DynamicBuildConfigurationMenu.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Luzius Meisser - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.menu;
+
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.internal.buildconfig.IBuildConfigurationChangedListener;
+import org.eclipse.ajdt.internal.ui.resources.AspectJImages;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+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;
+import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.progress.UIJob;
+
+/**
+ * @author Luzius Meisser
+ * 
+ * Submenu displayed in the Project menu.
+ *  
+ */
+public class DynamicBuildConfigurationMenu extends MenuManager implements
+		IBuildConfigurationChangedListener {
+	IBuildConfigurator buildconf;
+
+	IContributionItem separator;
+
+	private ImageDescriptor id;
+	
+	public DynamicBuildConfigurationMenu(String menuID) {
+		super(UIMessages.BCLabels_ConfigurationSelectionMenu, menuID);
+		separator = new Separator();
+
+		id = AspectJImages.BC_TICK.getImageDescriptor();
+		buildconf = DefaultBuildConfigurator.getBuildConfigurator();
+		((BuildConfigurator)buildconf).addBuildConfigurationChangedListener(this);
+		IAction addAction = new AddBuildConfigurationAction();
+		addAction.setEnabled(false);
+		this.add(addAction);
+	}
+
+	public void buildConfigurationChanged(final IProjectBuildConfigurator pbc) {
+		Job job = new UIJob(UIMessages.dynamicBuildConfigurationMenu_job_name) {
+			public IStatus runInUIThread(IProgressMonitor monitor) {
+				new AddBuildConfigurationAction();
+				rebuildMenu(pbc);
+				return Status.OK_STATUS;
+			}
+		};
+		job.setPriority(Job.SHORT);
+		job.schedule();
+	}
+
+	private void rebuildMenu(final IProjectBuildConfigurator pbc) {
+		final IAction addAction = new AddBuildConfigurationAction();
+		if (pbc == null) {
+			DynamicBuildConfigurationMenu.this.removeAll();
+			DynamicBuildConfigurationMenu.this.setVisible(true);
+			addAction.setEnabled(false);
+			DynamicBuildConfigurationMenu.this.add(separator);
+			DynamicBuildConfigurationMenu.this.add(addAction);
+			return;
+		}
+
+		BuildConfiguration[] bcs = (BuildConfiguration[]) pbc
+				.getBuildConfigurations().toArray(new BuildConfiguration[0]);
+		Util.sort(bcs);
+		final IBuildConfiguration activeBuildConfiguration = pbc.getActiveBuildConfiguration();
+		final BuildConfiguration[] bcs2 = new BuildConfiguration[bcs.length];
+		System.arraycopy(bcs, 0, bcs2, 0, bcs.length);
+		Display.getDefault().asyncExec(new Runnable() {
+			public void run() {
+				DynamicBuildConfigurationMenu.this.removeAll();
+				for (int i = 0; i < bcs2.length; i++) {
+					Action act = new BuildConfigurationSelectedAction(bcs2[i]);
+					if (bcs2[i] == activeBuildConfiguration)
+						act.setImageDescriptor(id);
+					DynamicBuildConfigurationMenu.this.add(act);
+				}
+				DynamicBuildConfigurationMenu.this.add(separator);
+				DynamicBuildConfigurationMenu.this.add(addAction);
+				DynamicBuildConfigurationMenu.this.setVisible(true);
+			}
+		});
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.action.IContributionItem#isDynamic()
+	 */
+	public boolean isDynamic() {
+		return true;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCContainerWorkbookPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCContainerWorkbookPage.java
new file mode 100644
index 0000000..b7d855b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCContainerWorkbookPage.java
@@ -0,0 +1,669 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.internal.corext.util.Messages;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.util.PixelConverter;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementSorter;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ExclusionInclusionDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.MultipleFolderSelectionDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.NewSourceFolderDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.OutputLocationDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceContainerWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.ITreeListAdapter;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.TreeListDialogField;
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.util.Assert;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.NewFolderDialog;
+import org.eclipse.ui.model.BaseWorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+
+/**
+ * Copied from org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceContainerWorkbookPage;
+ * Change marked with //AspectJ
+ * 
+ */
+
+public class BCContainerWorkbookPage extends SourceContainerWorkbookPage {
+
+	private ListDialogField fClassPathList;
+	private IJavaProject fCurrJProject;
+	private IPath fProjPath;
+	
+	private Control fSWTControl;
+	
+	private IWorkspaceRoot fWorkspaceRoot;
+	
+	private TreeListDialogField fFoldersList;
+	
+	private StringDialogField fOutputLocationField;
+	
+//	AspectJ Change Begin	
+//	Removed "Allow output folder for source folders" option
+//	private SelectionButtonDialogField fUseFolderOutputs;
+//	AspectJ Change End
+	
+	private final int IDX_ADD= 0;
+	private final int IDX_EDIT= 2;
+	private final int IDX_REMOVE= 3;	
+
+	public BCContainerWorkbookPage(ListDialogField classPathList, StringDialogField outputLocationField) {
+		super(classPathList, outputLocationField);
+		
+		fWorkspaceRoot= ResourcesPlugin.getWorkspace().getRoot();
+		fClassPathList= classPathList;
+	
+		fOutputLocationField= outputLocationField;
+		
+		fSWTControl= null;
+				
+		SourceContainerAdapter adapter= new SourceContainerAdapter();
+					
+		String[] buttonLabels;
+		
+
+		buttonLabels= new String[] { 
+			/* 0 = IDX_ADDEXIST */ NewWizardMessages.SourceContainerWorkbookPage_folders_add_button,
+			/* 1 */ null, 
+//			AspectJ Change Begin	
+//			Removed 'Edit' button as we have removed everything that could have been edited.
+			/* 2 */ null,
+//			/* 2 = IDX_EDIT */ NewWizardMessages.getString("SourceContainerWorkbookPage.folders.edit.button"), //$NON-NLS-1$
+//			AspectJ Change End
+			/* 3 = IDX_REMOVE */ NewWizardMessages.SourceContainerWorkbookPage_folders_remove_button
+		};
+		
+		fFoldersList= new TreeListDialogField(adapter, buttonLabels, new CPListLabelProvider());
+		fFoldersList.setDialogFieldListener(adapter);
+		fFoldersList.setLabelText(NewWizardMessages.SourceContainerWorkbookPage_folders_label);
+		
+		fFoldersList.setViewerSorter(new CPListElementSorter());
+		fFoldersList.enableButton(IDX_EDIT, false);
+
+//		AspectJ Change Begin
+//		Removed "Allow output folder for source folders" option
+//		fUseFolderOutputs= new SelectionButtonDialogField(SWT.CHECK);
+//		fUseFolderOutputs.setSelection(false);
+//		fUseFolderOutputs.setLabelText(NewWizardMessages.getString("SourceContainerWorkbookPage.folders.check")); //$NON-NLS-1$
+//		fUseFolderOutputs.setDialogFieldListener(adapter);
+//		AspectJ Change End
+	}
+	
+	public void init(IJavaProject jproject) {
+		fCurrJProject= jproject;
+		fProjPath= fCurrJProject.getProject().getFullPath();	
+		updateFoldersList();
+	}
+	
+	private void updateFoldersList() {	
+		ArrayList folders= new ArrayList();
+	
+		List cpelements= fClassPathList.getElements();
+		for (int i= 0; i < cpelements.size(); i++) {
+			CPListElement cpe= (CPListElement)cpelements.get(i);
+			if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+				folders.add(cpe);
+			}
+		}
+		fFoldersList.setElements(folders);
+//		AspectJ Change Begin	
+//		Removed "Allow output folder for source folders" option	
+//		fUseFolderOutputs.setSelection(useFolderOutputs);
+//		AspectJ Change End
+		
+		for (int i= 0; i < folders.size(); i++) {
+			CPListElement cpe= (CPListElement) folders.get(i);
+			IPath[] patterns= (IPath[]) cpe.getAttribute(CPListElement.EXCLUSION);
+			boolean hasOutputFolder= (cpe.getAttribute(CPListElement.OUTPUT) != null);
+			if (patterns.length > 0 || hasOutputFolder) {
+				fFoldersList.expandElement(cpe, 3);
+			}				
+		}
+	}			
+	
+	public Control getControl(Composite parent) {
+		PixelConverter converter= new PixelConverter(parent);
+		Composite composite= new Composite(parent, SWT.NONE);
+		
+		LayoutUtil.doDefaultLayout(composite, new DialogField[] { fFoldersList }, true);
+		LayoutUtil.setHorizontalGrabbing(fFoldersList.getTreeControl(null));
+		
+		int buttonBarWidth= converter.convertWidthInCharsToPixels(24);
+		fFoldersList.setButtonsMinWidth(buttonBarWidth);
+			
+		fSWTControl= composite;
+		
+		// expand
+		List elements= fFoldersList.getElements();
+		for (int i= 0; i < elements.size(); i++) {
+			CPListElement elem= (CPListElement) elements.get(i);
+			IPath[] exclusionPatterns= (IPath[]) elem.getAttribute(CPListElement.EXCLUSION);
+			IPath[] inclusionPatterns= (IPath[]) elem.getAttribute(CPListElement.INCLUSION);
+			IPath output= (IPath) elem.getAttribute(CPListElement.OUTPUT);
+			if (exclusionPatterns.length > 0 || inclusionPatterns.length > 0 || output != null) {
+				fFoldersList.expandElement(elem, 3);
+			}
+		}
+		return composite;
+	}
+	
+	private Shell getShell() {
+		if (fSWTControl != null) {
+			return fSWTControl.getShell();
+		}
+		return JavaPlugin.getActiveWorkbenchShell();
+	}
+	
+	
+	private class SourceContainerAdapter implements ITreeListAdapter, IDialogFieldListener {
+	
+		private final Object[] EMPTY_ARR= new Object[0];
+		
+		// -------- IListAdapter --------
+		public void customButtonPressed(TreeListDialogField field, int index) {
+			sourcePageCustomButtonPressed(field, index);
+		}
+		
+		public void selectionChanged(TreeListDialogField field) {
+			sourcePageSelectionChanged(field);
+		}
+		
+		public void doubleClicked(TreeListDialogField field) {
+			sourcePageDoubleClicked(field);
+		}
+		
+		public void keyPressed(TreeListDialogField field, KeyEvent event) {
+			sourcePageKeyPressed(field, event);
+		}	
+
+		public Object[] getChildren(TreeListDialogField field, Object element) {
+//			AspectJ Change Begin
+//			Removed "Allow output folder for source folders" option
+//			if (element instanceof CPListElement) {
+//				return ((CPListElement) element).getChildren(!fUseFolderOutputs.isSelected());
+//			}
+//			AspectJ Change End			
+			return EMPTY_ARR;
+		}
+
+		public Object getParent(TreeListDialogField field, Object element) {
+			if (element instanceof CPListElementAttribute) {
+				return ((CPListElementAttribute) element).getParent();
+			}
+			return null;
+		}
+
+		public boolean hasChildren(TreeListDialogField field, Object element) {
+			//AspectJ Change Begin
+			//We don't want the user to see inclusions or exclusion patterns
+			return false; //(element instanceof CPListElement);
+			//AspectJ Change End
+		}		
+		
+		// ---------- IDialogFieldListener --------
+		public void dialogFieldChanged(DialogField field) {
+			sourcePageDialogFieldChanged(field);
+		}
+
+	}
+	
+	protected void sourcePageKeyPressed(TreeListDialogField field, KeyEvent event) {
+		if (field == fFoldersList) {
+			if (event.character == SWT.DEL && event.stateMask == 0) {
+				List selection= field.getSelectedElements();
+				if (canRemove(selection)) {
+					removeEntry();
+				}
+			}
+		}	
+	}	
+	
+	protected void sourcePageDoubleClicked(TreeListDialogField field) {
+		if (field == fFoldersList) {
+			List selection= field.getSelectedElements();
+			if (canEdit(selection)) {
+				editEntry();
+			}
+		}
+	}
+	
+	private boolean hasFolders(IContainer container) {
+		try {
+			IResource[] members= container.members();
+			for (int i= 0; i < members.length; i++) {
+				if (members[i] instanceof IContainer) {
+					return true;
+				}
+			}
+		} catch (CoreException e) {
+			// ignore
+		}
+		return false;
+	}
+	
+	
+	protected void sourcePageCustomButtonPressed(DialogField field, int index) {
+		if (field == fFoldersList) {
+			if (index == IDX_ADD) {
+				List elementsToAdd= new ArrayList(10);
+				IProject project= fCurrJProject.getProject();
+				if (project.exists()) {
+					if (hasFolders(project)) {
+						CPListElement[] srcentries= openSourceContainerDialog(null);
+						if (srcentries != null) {
+							for (int i= 0; i < srcentries.length; i++) {
+								elementsToAdd.add(srcentries[i]);
+							}
+						}
+					} else {
+						CPListElement entry= openNewSourceContainerDialog(null, true);
+						if (entry != null) {
+							elementsToAdd.add(entry);
+						}	
+					}
+				} else {
+					CPListElement entry= openNewSourceContainerDialog(null, false);
+					if (entry != null) {
+						elementsToAdd.add(entry);
+					}
+				}
+				if (!elementsToAdd.isEmpty()) {
+					if (fFoldersList.getSize() == 1) {
+						CPListElement existing= (CPListElement) fFoldersList.getElement(0);
+						if (existing.getResource() instanceof IProject) {
+							askForChangingBuildPathDialog(existing);
+						}
+					}
+					HashSet modifiedElements= new HashSet();
+					askForAddingExclusionPatternsDialog(elementsToAdd, modifiedElements);
+					
+					fFoldersList.addElements(elementsToAdd);
+					fFoldersList.postSetSelection(new StructuredSelection(elementsToAdd));
+					
+					if (!modifiedElements.isEmpty()) {
+						for (Iterator iter= modifiedElements.iterator(); iter.hasNext();) {
+							Object elem= iter.next();
+							fFoldersList.refresh(elem);
+							fFoldersList.expandElement(elem, 3);
+						}
+					}
+
+				}				
+			} else if (index == IDX_EDIT) {
+				editEntry();
+			} else if (index == IDX_REMOVE) {
+				removeEntry();
+			}
+		}
+	}
+
+	private void editEntry() {
+		List selElements= fFoldersList.getSelectedElements();
+		if (selElements.size() != 1) {
+			return;
+		}
+		Object elem= selElements.get(0);
+		if (fFoldersList.getIndexOfElement(elem) != -1) {
+			editElementEntry((CPListElement) elem);
+		} else if (elem instanceof CPListElementAttribute) {
+			editAttributeEntry((CPListElementAttribute) elem);
+		}
+	}
+
+	private void editElementEntry(CPListElement elem) {
+		CPListElement res= null;
+		
+		res= openNewSourceContainerDialog(elem, true);
+		
+		if (res != null) {
+			fFoldersList.replaceElement(elem, res);
+		}
+	}
+
+	private void editAttributeEntry(CPListElementAttribute elem) {
+		String key= elem.getKey();
+		if (key.equals(CPListElement.OUTPUT)) {
+			CPListElement selElement=  elem.getParent();
+			OutputLocationDialog dialog= new OutputLocationDialog(getShell(), selElement, fClassPathList.getElements());
+			if (dialog.open() == Window.OK) {
+				selElement.setAttribute(CPListElement.OUTPUT, dialog.getOutputLocation());
+				fFoldersList.refresh();
+				fClassPathList.dialogFieldChanged(); // validate
+			}
+		} else if (key.equals(CPListElement.EXCLUSION)) {
+			showExclusionInclusionDialog(elem.getParent(), true);		
+		} else if (key.equals(CPListElement.INCLUSION)) {
+			showExclusionInclusionDialog(elem.getParent(), false);
+		}
+	}
+
+	private void showExclusionInclusionDialog(CPListElement selElement, boolean focusOnExclusion) {
+		ExclusionInclusionDialog dialog= new ExclusionInclusionDialog(getShell(), selElement, focusOnExclusion);
+		if (dialog.open() == Window.OK) {
+			selElement.setAttribute(CPListElement.INCLUSION, dialog.getInclusionPattern());
+			selElement.setAttribute(CPListElement.EXCLUSION, dialog.getExclusionPattern());
+			fFoldersList.refresh();
+			fClassPathList.dialogFieldChanged(); // validate
+		}
+	}
+
+	protected void sourcePageSelectionChanged(DialogField field) {
+		List selected= fFoldersList.getSelectedElements();
+		fFoldersList.enableButton(IDX_EDIT, canEdit(selected));
+		fFoldersList.enableButton(IDX_REMOVE, canRemove(selected));
+	}
+	
+	private void removeEntry() {
+		List selElements= fFoldersList.getSelectedElements();
+		for (int i= selElements.size() - 1; i >= 0 ; i--) {
+			Object elem= selElements.get(i);
+			if (elem instanceof CPListElementAttribute) {
+				CPListElementAttribute attrib= (CPListElementAttribute) elem;
+				String key= attrib.getKey();
+				Object value= null;
+				if (key.equals(CPListElement.EXCLUSION) || key.equals(CPListElement.INCLUSION)) {
+					value= new Path[0];
+				}
+				attrib.getParent().setAttribute(key, value);
+				selElements.remove(i);
+			}
+		}
+		if (selElements.isEmpty()) {
+			fFoldersList.refresh();
+			fClassPathList.dialogFieldChanged(); // validate
+		} else {
+			fFoldersList.removeElements(selElements);
+		}
+	}
+	
+	private boolean canRemove(List selElements) {
+		if (selElements.size() == 0) {
+			return false;
+		}
+		for (int i= 0; i < selElements.size(); i++) {
+			Object elem= selElements.get(i);
+			if (elem instanceof CPListElementAttribute) {
+				CPListElementAttribute attrib= (CPListElementAttribute) elem;
+				String key= attrib.getKey();
+				if (CPListElement.INCLUSION.equals(key)) {
+					if (((IPath[]) attrib.getValue()).length == 0) {
+						return false;
+					}
+				} else if (CPListElement.EXCLUSION.equals(key)) {
+					if (((IPath[]) attrib.getValue()).length == 0) {
+						return false;
+					}
+				} else if (attrib.getValue() == null) {
+					return false;
+				}
+			} else if (elem instanceof CPListElement) {
+				CPListElement curr= (CPListElement) elem;
+				if (curr.getParentContainer() != null) {
+					return false;
+				}
+			}
+		}
+		return true;
+	}		
+	
+	private boolean canEdit(List selElements) {
+		if (selElements.size() != 1) {
+			return false;
+		}
+		Object elem= selElements.get(0);
+		if (elem instanceof CPListElement) {
+			return false;
+		}
+		if (elem instanceof CPListElementAttribute) {
+			return true;
+		}
+		return false;
+	}	
+	
+	private void sourcePageDialogFieldChanged(DialogField field) {
+		if (fCurrJProject == null) {
+			// not initialized
+			return;
+		}
+
+//		AspectJ Change Begin		
+//		Removed "Allow output folder for source folders" option
+//		if (field == fUseFolderOutputs) {
+//			if (!fUseFolderOutputs.isSelected()) {
+//				int nFolders= fFoldersList.getSize();
+//				for (int i= 0; i < nFolders; i++) {
+//					CPListElement cpe= (CPListElement) fFoldersList.getElement(i);
+//					cpe.setAttribute(CPListElement.OUTPUT, null);
+//				}
+//			}
+//			fFoldersList.refresh();
+//		} else 
+//		AspectJ Change End
+		if (field == fFoldersList) {
+			updateClasspathList();
+		}
+	}	
+	
+		
+	private void updateClasspathList() {
+		List srcelements= fFoldersList.getElements();
+		
+		List cpelements= fClassPathList.getElements();
+		int nEntries= cpelements.size();
+		// backwards, as entries will be deleted
+		int lastRemovePos= nEntries;
+		int afterLastSourcePos= 0;
+		for (int i= nEntries - 1; i >= 0; i--) {
+			CPListElement cpe= (CPListElement)cpelements.get(i);
+			int kind= cpe.getEntryKind();
+			if (isEntryKind(kind)) {
+				if (!srcelements.remove(cpe)) {
+					cpelements.remove(i);
+					lastRemovePos= i;
+				} else if (lastRemovePos == nEntries) {
+					afterLastSourcePos= i + 1;
+				}
+			}
+		}
+
+		if (!srcelements.isEmpty()) {
+			int insertPos= Math.min(afterLastSourcePos, lastRemovePos);
+			cpelements.addAll(insertPos, srcelements);
+		}
+		
+		if (lastRemovePos != nEntries || !srcelements.isEmpty()) {
+			fClassPathList.setElements(cpelements);
+		}
+	}
+		
+	private CPListElement openNewSourceContainerDialog(CPListElement existing, boolean includeLinked) {	
+		if (includeLinked) {
+			NewFolderDialog dialog= new NewFolderDialog(getShell(), fCurrJProject.getProject());
+			dialog.setTitle(NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_new_title);
+			if (dialog.open() == Window.OK) {
+				IResource createdFolder= (IResource) dialog.getResult()[0];
+				return newCPSourceElement(createdFolder);
+			}
+			return null;
+		} else {
+			String title= (existing == null) ? NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_new_title : NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_edit_title; 
+	
+			IProject proj= fCurrJProject.getProject();
+			NewSourceFolderDialog dialog= new NewSourceFolderDialog(getShell(), title, proj, getExistingContainers(existing), existing);
+			dialog.setMessage(Messages.format(NewWizardMessages.SourceContainerWorkbookPage_NewSourceFolderDialog_description, fProjPath.toString())); 
+			if (dialog.open() == Window.OK) {
+				IResource folder= dialog.getSourceFolder();
+				return newCPSourceElement(folder);
+			}
+			return null;
+		}
+	}
+	
+	
+	
+	/**
+	 * Asks to change the output folder to 'proj/bin' when no source folders were existing
+	 */ 
+	private void askForChangingBuildPathDialog(CPListElement existing) {
+		IPath outputFolder= new Path(fOutputLocationField.getText());
+		
+		IPath newOutputFolder= null;
+		String message;
+		if (outputFolder.segmentCount() == 1) {
+			String outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
+			newOutputFolder= outputFolder.append(outputFolderName);
+			message= Messages.format(NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_project_and_output_message, newOutputFolder); 
+		} else {
+			message= NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_project_message; 
+		}
+		String title= NewWizardMessages.SourceContainerWorkbookPage_ChangeOutputLocationDialog_title; 
+		if (MessageDialog.openQuestion(getShell(), title, message)) {
+			fFoldersList.removeElement(existing);
+			if (newOutputFolder != null) {
+				fOutputLocationField.setText(newOutputFolder.toString());
+			}
+		}			
+	}
+	
+	private void askForAddingExclusionPatternsDialog(List newEntries, Set modifiedEntries) {
+		fixNestingConflicts(newEntries, fFoldersList.getElements(), modifiedEntries);
+		if (!modifiedEntries.isEmpty()) {
+			String title= NewWizardMessages.SourceContainerWorkbookPage_exclusion_added_title; 
+			String message= NewWizardMessages.SourceContainerWorkbookPage_exclusion_added_message; 
+			MessageDialog.openInformation(getShell(), title, message);
+		}
+	}
+	
+	private CPListElement[] openSourceContainerDialog(CPListElement existing) {
+		
+		Class[] acceptedClasses= new Class[] { IProject.class, IFolder.class };
+		List existingContainers= getExistingContainers(null);
+		
+		IProject[] allProjects= fWorkspaceRoot.getProjects();
+		ArrayList rejectedElements= new ArrayList(allProjects.length);
+		IProject currProject= fCurrJProject.getProject();
+		for (int i= 0; i < allProjects.length; i++) {
+			if (!allProjects[i].equals(currProject)) {
+				rejectedElements.add(allProjects[i]);
+			}
+		}
+		ViewerFilter filter= new TypedViewerFilter(acceptedClasses, rejectedElements.toArray());
+		
+		ILabelProvider lp= new WorkbenchLabelProvider();
+		ITreeContentProvider cp= new BaseWorkbenchContentProvider();
+
+		String title= (existing == null) ? NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_new_title : NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_edit_title; 
+		String message= (existing == null) ? NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_new_description : NewWizardMessages.SourceContainerWorkbookPage_ExistingSourceFolderDialog_edit_description; 
+
+		MultipleFolderSelectionDialog dialog= new MultipleFolderSelectionDialog(getShell(), lp, cp);
+		dialog.setExisting(existingContainers.toArray());
+		dialog.setTitle(title);
+		dialog.setMessage(message);
+		dialog.addFilter(filter);
+		dialog.setInput(fCurrJProject.getProject().getParent());
+		if (existing == null) {
+			dialog.setInitialFocus(fCurrJProject.getProject());
+		} else {
+			dialog.setInitialFocus(existing.getResource());
+		}		
+		if (dialog.open() == Window.OK) {
+			Object[] elements= dialog.getResult();	
+			CPListElement[] res= new CPListElement[elements.length];
+			for (int i= 0; i < res.length; i++) {
+				IResource elem= (IResource)elements[i];
+				res[i]= newCPSourceElement(elem);
+			}
+			return res;
+		}
+		return null;
+	}
+	
+	private List getExistingContainers(CPListElement existing) {
+		List res= new ArrayList();
+		List cplist= fFoldersList.getElements();
+		for (int i= 0; i < cplist.size(); i++) {
+			CPListElement elem= (CPListElement)cplist.get(i);
+			if (elem != existing) {
+				IResource resource= elem.getResource();
+				if (resource instanceof IContainer) { // defensive code
+					res.add(resource);	
+				}
+			}
+		}
+		return res;
+	}
+	
+	private CPListElement newCPSourceElement(IResource res) {
+		Assert.isNotNull(res);
+		return new CPListElement(fCurrJProject, IClasspathEntry.CPE_SOURCE, res.getFullPath(), res);
+	}
+	
+	/*
+	 * @see BuildPathBasePage#getSelection
+	 */
+	public List getSelection() {
+		return fFoldersList.getSelectedElements();
+	}
+
+	/*
+	 * @see BuildPathBasePage#setSelection
+	 */	
+	public void setSelection(List selElements) {
+		fFoldersList.selectElements(new StructuredSelection(selElements));
+	}	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage#isEntryKind(int)
+	 */
+	public boolean isEntryKind(int kind) {
+		return kind == IClasspathEntry.CPE_SOURCE;
+	}	
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCPropertyPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCPropertyPage.java
new file mode 100644
index 0000000..6341685
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BCPropertyPage.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.actions.WorkbenchRunnableAdapter;
+import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
+import org.eclipse.jdt.internal.ui.preferences.PreferencesMessages;
+import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferencePageContainer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PropertyPage;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+
+/**
+ * Copied from jdt Original name:
+ * org.eclipse.jdt.internal.ui.preferences.BuildPathsPropertyPage
+ * only change: use BuildPathsBlock of this package
+ *  
+ */
+public class BCPropertyPage extends PropertyPage implements IStatusChangeListener {
+	
+	
+private static final String PAGE_SETTINGS= "BuildPathsPropertyPage"; //$NON-NLS-1$
+private static final String INDEX= "pageIndex"; //$NON-NLS-1$
+	
+private BuildPathsBlock fBuildPathsBlock;
+
+/*
+ * @see PreferencePage#createControl(Composite)
+ */
+protected Control createContents(Composite parent) {
+	// ensure the page has no special buttons
+	noDefaultAndApplyButton();		
+	
+	IProject project= getProject();
+	Control result;
+	if (project == null || !isJavaProject(project)) {
+		result= createWithoutJava(parent);
+	} else if (!project.isOpen()) {
+		result= createForClosedProject(parent);
+	} else {
+		result= createWithJava(parent, project);
+	}
+	Dialog.applyDialogFont(result);
+	return result;
+}
+
+/*
+ * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+ */
+public void createControl(Composite parent) {
+	super.createControl(parent);
+	PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaHelpContextIds.BUILD_PATH_PROPERTY_PAGE);
+}	
+
+private IDialogSettings getSettings() {
+	IDialogSettings javaSettings= JavaPlugin.getDefault().getDialogSettings();
+	IDialogSettings pageSettings= javaSettings.getSection(PAGE_SETTINGS);
+	if (pageSettings == null) {
+		pageSettings= javaSettings.addNewSection(PAGE_SETTINGS);
+		pageSettings.put(INDEX, 3);
+	}
+	return pageSettings;
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
+ */
+public void setVisible(boolean visible) {
+	if (fBuildPathsBlock != null) {
+		if (!visible) {
+			if (fBuildPathsBlock.hasChangesInDialog()) {
+				String title= PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_title; 
+				String message= PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_message; 
+				String[] buttonLabels= new String[] {
+						PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_save, 
+						PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_discard, 
+						PreferencesMessages.BuildPathsPropertyPage_unsavedchanges_button_ignore
+				};
+				MessageDialog dialog= new MessageDialog(getShell(), title, null, message, MessageDialog.QUESTION, buttonLabels, 0);
+				int res= dialog.open();
+				if (res == 0) {
+					performOk();
+				} else if (res == 1) {
+					fBuildPathsBlock.init(JavaCore.create(getProject()), null, null);
+				} else {
+					fBuildPathsBlock.initializeTimeStamps();
+				}
+			}
+		} else {
+			if (!fBuildPathsBlock.hasChangesInDialog() && fBuildPathsBlock.hasChangesInClasspathFile()) {
+				fBuildPathsBlock.init(JavaCore.create(getProject()), null, null);
+			}
+		}
+	}
+	super.setVisible(visible);
+}
+
+
+/*
+ * Content for valid projects.
+ */
+private Control createWithJava(Composite parent, IProject project) {
+	IWorkbenchPreferenceContainer pageContainer= null;	
+	IPreferencePageContainer container= getContainer();
+	if (container instanceof IWorkbenchPreferenceContainer) {
+		pageContainer= (IWorkbenchPreferenceContainer) container;
+	}
+	
+	fBuildPathsBlock= new BuildPathsBlock(new BusyIndicatorRunnableContext(), this, getSettings().getInt(INDEX), false, pageContainer);
+
+	fBuildPathsBlock.init(JavaCore.create(project), null, null);
+	return fBuildPathsBlock.createControl(parent);
+}
+
+/*
+ * Content for non-Java projects.
+ */	
+private Control createWithoutJava(Composite parent) {
+	Label label= new Label(parent, SWT.LEFT);
+	label.setText(PreferencesMessages.BuildPathsPropertyPage_no_java_project_message); 
+	
+	fBuildPathsBlock= null;
+	setValid(true);
+	return label;
+}
+
+/*
+ * Content for closed projects.
+ */		
+private Control createForClosedProject(Composite parent) {
+	Label label= new Label(parent, SWT.LEFT);
+	label.setText(PreferencesMessages.BuildPathsPropertyPage_closed_project_message); 
+	
+	fBuildPathsBlock= null;
+	setValid(true);
+	return label;
+}
+
+private IProject getProject() {
+	IAdaptable adaptable= getElement();
+	if (adaptable != null) {
+		IJavaElement elem= (IJavaElement) adaptable.getAdapter(IJavaElement.class);
+		if (elem instanceof IJavaProject) {
+			return ((IJavaProject) elem).getProject();
+		}
+	}
+	return null;
+}
+
+private boolean isJavaProject(IProject proj) {
+	try {
+		return proj.hasNature(JavaCore.NATURE_ID);
+	} catch (CoreException e) {
+		JavaPlugin.log(e);
+	}
+	return false;
+}
+
+/*
+ * @see IPreferencePage#performOk
+ */
+public boolean performOk() {
+	if (fBuildPathsBlock != null) {
+		getSettings().put(INDEX, fBuildPathsBlock.getPageIndex());
+		IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
+			public void run(IProgressMonitor monitor)	throws CoreException, OperationCanceledException {
+				fBuildPathsBlock.configureJavaProject(monitor);
+			}
+		};
+		WorkbenchRunnableAdapter op= new WorkbenchRunnableAdapter(runnable);
+		op.runAsUserJob(PreferencesMessages.BuildPathsPropertyPage_job_title, null);  
+	}
+	return true;
+}
+
+/* (non-Javadoc)
+ * @see IStatusChangeListener#statusChanged
+ */
+public void statusChanged(IStatus status) {
+	setValid(!status.matches(IStatus.ERROR));
+	StatusUtil.applyToStatusLine(this, status);
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jface.preference.IPreferencePage#performCancel()
+ */
+public boolean performCancel() {
+	if (fBuildPathsBlock != null) {
+		getSettings().put(INDEX, fBuildPathsBlock.getPageIndex());
+	}
+	return super.performCancel();
+}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BuildPathsBlock.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BuildPathsBlock.java
new file mode 100644
index 0000000..d8aaf09
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/BuildPathsBlock.java
@@ -0,0 +1,869 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaModelStatus;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.corext.util.Messages;
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.JavaPluginImages;
+import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
+import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
+import org.eclipse.jdt.internal.ui.util.CoreUtility;
+import org.eclipse.jdt.internal.ui.util.PixelConverter;
+import org.eclipse.jdt.internal.ui.viewsupport.ImageDisposer;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator;
+import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ClasspathOrderingWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.FolderSelectionDialog;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.LibrariesWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.ProjectsWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceContainerWorkbookPage;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.model.WorkbenchContentProvider;
+import org.eclipse.ui.model.WorkbenchLabelProvider;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+import org.eclipse.ui.views.navigator.ResourceSorter;
+
+
+/**
+ * Copied from jdt Original name:
+ * org.eclipse.jdt.internal.ui.preferences.BuildPathsBlock
+ * change marked with //AspectJ
+ *  
+ */
+
+public class BuildPathsBlock {
+
+	public static interface IRemoveOldBinariesQuery {
+		
+		/**
+		 * Do the callback. Returns <code>true</code> if .class files should be removed from the
+		 * old output location.
+		 * @param oldOutputLocation The old output location
+		 * @return Returns true if .class files should be removed.
+		 * @throws OperationCanceledException
+		 */
+		boolean doQuery(IPath oldOutputLocation) throws OperationCanceledException;
+		
+	}
+
+
+	private IWorkspaceRoot fWorkspaceRoot;
+
+	private CheckedListDialogField fClassPathList;
+	private StringButtonDialogField fBuildPathDialogField;
+	
+	private StatusInfo fClassPathStatus;
+	private StatusInfo fOutputFolderStatus;	
+	private StatusInfo fBuildPathStatus;
+
+	private IJavaProject fCurrJProject;
+		
+	private IPath fOutputLocationPath;
+	
+	private IStatusChangeListener fContext;
+	private Control fSWTWidget;	
+	
+	private int fPageIndex;
+	
+	private BuildPathBasePage fSourceContainerPage;
+	private ProjectsWorkbookPage fProjectsPage;
+	private LibrariesWorkbookPage fLibrariesPage;
+	
+	private BuildPathBasePage fCurrPage;
+	
+	private String fUserSettingsTimeStamp;
+	private long fFileTimeStamp;
+
+	private final IWorkbenchPreferenceContainer fPageContainer; // null when invoked from a non-property page context
+		
+	public BuildPathsBlock(IRunnableContext runnableContext, IStatusChangeListener context, int pageToShow, boolean useNewPage, IWorkbenchPreferenceContainer pageContainer) {
+		fPageContainer= pageContainer;
+		fWorkspaceRoot= JavaPlugin.getWorkspace().getRoot();
+		fContext= context;
+		
+		fPageIndex= pageToShow;
+		
+		fSourceContainerPage= null;
+		fLibrariesPage= null;
+		fProjectsPage= null;
+		fCurrPage= null;
+       		
+		BuildPathAdapter adapter= new BuildPathAdapter();			
+	
+		String[] buttonLabels= new String[] {
+			NewWizardMessages.BuildPathsBlock_classpath_up_button, 
+			NewWizardMessages.BuildPathsBlock_classpath_down_button, 
+			/* 2 */ null,
+			NewWizardMessages.BuildPathsBlock_classpath_checkall_button, 
+			NewWizardMessages.BuildPathsBlock_classpath_uncheckall_button
+		
+		};
+		
+		fClassPathList= new CheckedListDialogField(null, buttonLabels, new CPListLabelProvider());
+		fClassPathList.setDialogFieldListener(adapter);
+		fClassPathList.setLabelText(NewWizardMessages.BuildPathsBlock_classpath_label);  
+		fClassPathList.setUpButtonIndex(0);
+		fClassPathList.setDownButtonIndex(1);
+		fClassPathList.setCheckAllButtonIndex(3);
+		fClassPathList.setUncheckAllButtonIndex(4);		
+			
+		fBuildPathDialogField= new StringButtonDialogField(adapter);
+		fBuildPathDialogField.setButtonLabel(NewWizardMessages.BuildPathsBlock_buildpath_button); 
+		fBuildPathDialogField.setDialogFieldListener(adapter);
+		fBuildPathDialogField.setLabelText(NewWizardMessages.BuildPathsBlock_buildpath_label); 
+
+		fBuildPathStatus= new StatusInfo();
+		fClassPathStatus= new StatusInfo();
+		fOutputFolderStatus= new StatusInfo();
+		
+		fCurrJProject= null;
+	}
+	
+	// -------- UI creation ---------
+	
+	public Control createControl(Composite parent) {
+		fSWTWidget= parent;
+		
+		PixelConverter converter= new PixelConverter(parent);
+		
+		Composite composite= new Composite(parent, SWT.NONE);	
+		composite.setFont(parent.getFont());
+		
+		GridLayout layout= new GridLayout();
+		layout.marginWidth= 0;
+		layout.marginHeight= 0;
+		layout.numColumns= 1;		
+		composite.setLayout(layout);
+		
+		TabFolder folder= new TabFolder(composite, SWT.NONE);
+		folder.setLayoutData(new GridData(GridData.FILL_BOTH));
+		folder.setFont(composite.getFont());
+		
+		TabItem item;
+		//AspectJ Extension Begin (by Luzius)
+		if (fCurrJProject != null) {
+			try {
+				if (fCurrJProject.getProject().hasNature("org.eclipse.ajdt.ui.ajnature")){ //$NON-NLS-1$
+					fSourceContainerPage = new BCContainerWorkbookPage(
+							fClassPathList, fBuildPathDialogField);
+				} else
+					fSourceContainerPage = new SourceContainerWorkbookPage(
+							fClassPathList, fBuildPathDialogField);
+			} catch (CoreException e1) {
+				fSourceContainerPage = new SourceContainerWorkbookPage(
+						fClassPathList, fBuildPathDialogField);
+			} 
+		} else { // Sian - added this else block so that this class can be used in the new Aspectj project wizard (bug 78264)
+			fSourceContainerPage= new BCContainerWorkbookPage(
+					 fClassPathList, fBuildPathDialogField);
+		}
+		//AspectJ Extension End (by Luzius)
+        item= new TabItem(folder, SWT.NONE);
+        item.setText(NewWizardMessages.BuildPathsBlock_tab_source); 
+        item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_PACKFRAG_ROOT));
+		
+//      AspectJ Extension Start
+//        if (fUseNewPage) {
+//			fSourceContainerPage= new NewSourceContainerWorkbookPage(fClassPathList, fBuildPathDialogField, fRunnableContext);
+//        } else {
+//			fSourceContainerPage= new SourceContainerWorkbookPage(fClassPathList, fBuildPathDialogField);
+//        }
+//      AspectJ Extension End
+        item.setData(fSourceContainerPage);     
+        item.setControl(fSourceContainerPage.getControl(folder));
+		
+		IWorkbench workbench= JavaPlugin.getDefault().getWorkbench();	
+		Image projectImage= workbench.getSharedImages().getImage(IDE.SharedImages.IMG_OBJ_PROJECT);
+		
+		fProjectsPage= new ProjectsWorkbookPage(fClassPathList, fPageContainer);		
+		item= new TabItem(folder, SWT.NONE);
+		item.setText(NewWizardMessages.BuildPathsBlock_tab_projects); 
+		item.setImage(projectImage);
+		item.setData(fProjectsPage);
+		item.setControl(fProjectsPage.getControl(folder));
+		
+		fLibrariesPage= new LibrariesWorkbookPage(fClassPathList, fPageContainer);		
+		item= new TabItem(folder, SWT.NONE);
+		item.setText(NewWizardMessages.BuildPathsBlock_tab_libraries); 
+		item.setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_LIBRARY));
+		item.setData(fLibrariesPage);
+		item.setControl(fLibrariesPage.getControl(folder));
+		
+		// a non shared image
+		Image cpoImage= JavaPluginImages.DESC_TOOL_CLASSPATH_ORDER.createImage();
+		composite.addDisposeListener(new ImageDisposer(cpoImage));	
+		
+		ClasspathOrderingWorkbookPage ordpage= new ClasspathOrderingWorkbookPage(fClassPathList);		
+		item= new TabItem(folder, SWT.NONE);
+		item.setText(NewWizardMessages.BuildPathsBlock_tab_order); 
+		item.setImage(cpoImage);
+		item.setData(ordpage);
+		item.setControl(ordpage.getControl(folder));
+				
+		if (fCurrJProject != null) {
+			fSourceContainerPage.init(fCurrJProject);
+			fLibrariesPage.init(fCurrJProject);
+			fProjectsPage.init(fCurrJProject);
+		}		
+						
+		Composite editorcomp= new Composite(composite, SWT.NONE);	
+	
+		DialogField[] editors= new DialogField[] { fBuildPathDialogField };
+		LayoutUtil.doDefaultLayout(editorcomp, editors, true, 0, 0);
+		
+		int maxFieldWidth= converter.convertWidthInCharsToPixels(40);
+		LayoutUtil.setWidthHint(fBuildPathDialogField.getTextControl(null), maxFieldWidth);
+		LayoutUtil.setHorizontalGrabbing(fBuildPathDialogField.getTextControl(null));
+	
+		editorcomp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		
+		folder.setSelection(fPageIndex);
+		fCurrPage= (BuildPathBasePage) folder.getItem(fPageIndex).getData();
+		folder.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				tabChanged(e.item);
+			}	
+		});		
+
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.BUILD_PATH_BLOCK);				
+		Dialog.applyDialogFont(composite);
+		return composite;
+	}
+	
+	private Shell getShell() {
+		if (fSWTWidget != null) {
+			return fSWTWidget.getShell();
+		}
+		return JavaPlugin.getActiveWorkbenchShell();
+	}
+	
+	/**
+	 * Initializes the classpath for the given project. Multiple calls to init are allowed,
+	 * but all existing settings will be cleared and replace by the given or default paths.
+	 * @param jproject The java project to configure. Does not have to exist.
+	 * @param outputLocation The output location to be set in the page. If <code>null</code>
+	 * is passed, jdt default settings are used, or - if the project is an existing Java project- the
+	 * output location of the existing project 
+	 * @param classpathEntries The classpath entries to be set in the page. If <code>null</code>
+	 * is passed, jdt default settings are used, or - if the project is an existing Java project - the
+	 * classpath entries of the existing project
+	 */	
+	public void init(IJavaProject jproject, IPath outputLocation, IClasspathEntry[] classpathEntries) {
+		fCurrJProject= jproject;
+		boolean projectExists= false;
+		List newClassPath= null;
+		IProject project= fCurrJProject.getProject();
+		projectExists= (project.exists() && project.getFile(".classpath").exists()); //$NON-NLS-1$
+		if  (projectExists) {
+			if (outputLocation == null) {
+				outputLocation=  fCurrJProject.readOutputLocation();
+			}
+			if (classpathEntries == null) {
+				classpathEntries=  fCurrJProject.readRawClasspath();
+			}
+		}
+		if (outputLocation == null) {
+			outputLocation= getDefaultBuildPath(jproject);
+		}			
+
+		if (classpathEntries != null) {
+			newClassPath= getExistingEntries(classpathEntries);
+		}
+		if (newClassPath == null) {
+			newClassPath= getDefaultClassPath(jproject);
+		}
+		
+		List exportedEntries = new ArrayList();
+		for (int i= 0; i < newClassPath.size(); i++) {
+			CPListElement curr= (CPListElement) newClassPath.get(i);
+			if (curr.isExported() || curr.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+				exportedEntries.add(curr);
+			}
+		}
+		
+		// inits the dialog field
+		fBuildPathDialogField.setText(outputLocation.makeRelative().toString());
+		fBuildPathDialogField.enableButton(project.exists());
+		fClassPathList.setElements(newClassPath);
+		fClassPathList.setCheckedElements(exportedEntries);
+		
+		initializeTimeStamps();
+		updateUI();
+	}
+	
+	protected void updateUI() {
+		if (fSWTWidget == null || fSWTWidget.isDisposed()) {
+			return;
+		}
+		
+		if (Display.getCurrent() != null) {
+			doUpdateUI();
+		} else {
+			Display.getDefault().asyncExec(new Runnable() {
+				public void run() {
+					if (fSWTWidget == null || fSWTWidget.isDisposed()) {
+						return;
+					}
+					doUpdateUI();
+				}
+			});
+		}
+	}
+
+	protected void doUpdateUI() {
+		fBuildPathDialogField.refresh();
+		fClassPathList.refresh();
+	
+		if (fSourceContainerPage != null) {
+			fSourceContainerPage.init(fCurrJProject);
+			fProjectsPage.init(fCurrJProject);
+			fLibrariesPage.init(fCurrJProject);
+		}
+		doStatusLineUpdate();
+	}
+	
+	private String getEncodedSettings() {
+		StringBuffer buf= new StringBuffer();	
+		CPListElement.appendEncodePath(fOutputLocationPath, buf).append(';');
+
+		int nElements= fClassPathList.getSize();
+		buf.append('[').append(nElements).append(']');
+		for (int i= 0; i < nElements; i++) {
+			CPListElement elem= (CPListElement) fClassPathList.getElement(i);
+			elem.appendEncodedSettings(buf);
+		}
+		return buf.toString();
+	}
+	
+	public boolean hasChangesInDialog() {
+		String currSettings= getEncodedSettings();
+		return !currSettings.equals(fUserSettingsTimeStamp);
+	}
+	
+	public boolean hasChangesInClasspathFile() {
+		IFile file= fCurrJProject.getProject().getFile(".classpath"); //$NON-NLS-1$
+		return fFileTimeStamp != file.getModificationStamp();
+	}
+	
+	public void initializeTimeStamps() {
+		IFile file= fCurrJProject.getProject().getFile(".classpath"); //$NON-NLS-1$
+		fFileTimeStamp= file.getModificationStamp();
+		fUserSettingsTimeStamp= getEncodedSettings();
+	}
+	
+	
+
+	private ArrayList getExistingEntries(IClasspathEntry[] classpathEntries) {
+		ArrayList newClassPath= new ArrayList();
+		for (int i= 0; i < classpathEntries.length; i++) {
+			IClasspathEntry curr= classpathEntries[i];
+			newClassPath.add(CPListElement.createFromExisting(curr, fCurrJProject));
+		}
+		return newClassPath;
+	}
+	
+	// -------- public api --------
+	
+	/**
+	 * @return Returns the Java project. Can return <code>null<code> if the page has not
+	 * been initialized.
+	 */
+	public IJavaProject getJavaProject() {
+		return fCurrJProject;
+	}
+	
+	/**
+	 *  @return Returns the current output location. Note that the path returned must not be valid.
+	 */	
+	public IPath getOutputLocation() {
+		return new Path(fBuildPathDialogField.getText()).makeAbsolute();
+	}
+	
+	/**
+	 *  @return Returns the current class path (raw). Note that the entries returned must not be valid.
+	 */	
+	public IClasspathEntry[] getRawClassPath() {
+		List elements=  fClassPathList.getElements();
+		int nElements= elements.size();
+		IClasspathEntry[] entries= new IClasspathEntry[elements.size()];
+
+		for (int i= 0; i < nElements; i++) {
+			CPListElement currElement= (CPListElement) elements.get(i);
+			entries[i]= currElement.getClasspathEntry();
+		}
+		return entries;
+	}
+	
+	public int getPageIndex() {
+		return fPageIndex;
+	}
+	
+	
+	// -------- evaluate default settings --------
+	
+	private List getDefaultClassPath(IJavaProject jproj) {
+		List list= new ArrayList();
+		IResource srcFolder;
+		IPreferenceStore store= PreferenceConstants.getPreferenceStore();
+		String sourceFolderName= store.getString(PreferenceConstants.SRCBIN_SRCNAME);
+		if (store.getBoolean(PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ) && sourceFolderName.length() > 0) {
+			srcFolder= jproj.getProject().getFolder(sourceFolderName);
+		} else {
+			srcFolder= jproj.getProject();
+		}
+
+		list.add(new CPListElement(jproj, IClasspathEntry.CPE_SOURCE, srcFolder.getFullPath(), srcFolder));
+
+		IClasspathEntry[] jreEntries= PreferenceConstants.getDefaultJRELibrary();
+		list.addAll(getExistingEntries(jreEntries));
+		return list;
+	}
+	
+	private IPath getDefaultBuildPath(IJavaProject jproj) {
+		IPreferenceStore store= PreferenceConstants.getPreferenceStore();
+		if (store.getBoolean(PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ)) {
+			String outputLocationName= store.getString(PreferenceConstants.SRCBIN_BINNAME);
+			return jproj.getProject().getFullPath().append(outputLocationName);
+		} else {
+			return jproj.getProject().getFullPath();
+		}
+	}	
+		
+	private class BuildPathAdapter implements IStringButtonAdapter, IDialogFieldListener {
+
+		// -------- IStringButtonAdapter --------
+		public void changeControlPressed(DialogField field) {
+			buildPathChangeControlPressed(field);
+		}
+		
+		// ---------- IDialogFieldListener --------
+		public void dialogFieldChanged(DialogField field) {
+			buildPathDialogFieldChanged(field);
+		}
+	}
+	
+	private void buildPathChangeControlPressed(DialogField field) {
+		if (field == fBuildPathDialogField) {
+			IContainer container= chooseContainer();
+			if (container != null) {
+				fBuildPathDialogField.setText(container.getFullPath().toString());
+			}
+		}
+	}
+	
+	private void buildPathDialogFieldChanged(DialogField field) {
+		if (field == fClassPathList) {
+			updateClassPathStatus();
+		} else if (field == fBuildPathDialogField) {
+			updateOutputLocationStatus();
+		}
+		doStatusLineUpdate();
+	}	
+	
+
+	
+	// -------- verification -------------------------------
+	
+	private void doStatusLineUpdate() {
+		if (Display.getCurrent() != null) {
+			IStatus res= findMostSevereStatus();
+			fContext.statusChanged(res);
+		}
+	}
+	
+	private IStatus findMostSevereStatus() {
+		return StatusUtil.getMostSevere(new IStatus[] { fClassPathStatus, fOutputFolderStatus, fBuildPathStatus });
+	}
+	
+	
+	/**
+	 * Validates the build path.
+	 */
+	public void updateClassPathStatus() {
+		fClassPathStatus.setOK();
+		
+		List elements= fClassPathList.getElements();
+	
+		CPListElement entryMissing= null;
+		int nEntriesMissing= 0;
+		IClasspathEntry[] entries= new IClasspathEntry[elements.size()];
+
+		for (int i= elements.size()-1 ; i >= 0 ; i--) {
+			CPListElement currElement= (CPListElement)elements.get(i);
+			boolean isChecked= fClassPathList.isChecked(currElement);
+			if (currElement.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+				if (!isChecked) {
+					fClassPathList.setCheckedWithoutUpdate(currElement, true);
+				}
+			} else {
+				currElement.setExported(isChecked);
+			}
+
+			entries[i]= currElement.getClasspathEntry();
+			if (currElement.isMissing()) {
+				nEntriesMissing++;
+				if (entryMissing == null) {
+					entryMissing= currElement;
+				}
+			}
+		}
+				
+		if (nEntriesMissing > 0) {
+			if (nEntriesMissing == 1) {
+				fClassPathStatus.setWarning(Messages.format(NewWizardMessages.BuildPathsBlock_warning_EntryMissing, entryMissing.getPath().toString())); 
+			} else {
+				fClassPathStatus.setWarning(Messages.format(NewWizardMessages.BuildPathsBlock_warning_EntriesMissing, String.valueOf(nEntriesMissing))); 
+			}
+		}
+				
+/*		if (fCurrJProject.hasClasspathCycle(entries)) {
+			fClassPathStatus.setWarning(NewWizardMessages.getString("BuildPathsBlock.warning.CycleInClassPath")); //$NON-NLS-1$
+		}
+*/		
+		updateBuildPathStatus();
+	}
+
+	/**
+	 * Validates output location & build path.
+	 */	
+	private void updateOutputLocationStatus() {
+		fOutputLocationPath= null;
+		
+		String text= fBuildPathDialogField.getText();
+		if ("".equals(text)) { //$NON-NLS-1$
+			fOutputFolderStatus.setError(NewWizardMessages.BuildPathsBlock_error_EnterBuildPath); 
+			return;
+		}
+		IPath path= getOutputLocation();
+		fOutputLocationPath= path;
+		
+		IResource res= fWorkspaceRoot.findMember(path);
+		if (res != null) {
+			// if exists, must be a folder or project
+			if (res.getType() == IResource.FILE) {
+				fOutputFolderStatus.setError(NewWizardMessages.BuildPathsBlock_error_InvalidBuildPath); 
+				return;
+			}
+		}	
+		fOutputFolderStatus.setOK();
+		updateBuildPathStatus();
+	}
+		
+	private void updateBuildPathStatus() {
+		List elements= fClassPathList.getElements();
+		IClasspathEntry[] entries= new IClasspathEntry[elements.size()];
+	
+		for (int i= elements.size()-1 ; i >= 0 ; i--) {
+			CPListElement currElement= (CPListElement)elements.get(i);
+			entries[i]= currElement.getClasspathEntry();
+		}
+		
+		IJavaModelStatus status= JavaConventions.validateClasspath(fCurrJProject, entries, fOutputLocationPath);
+		if (!status.isOK()) {
+			fBuildPathStatus.setError(status.getMessage());
+			return;
+		}
+		fBuildPathStatus.setOK();
+	}
+	
+	// -------- creation -------------------------------
+	
+	public static void createProject(IProject project, IPath locationPath, IProgressMonitor monitor) throws CoreException {
+		if (monitor == null) {
+			monitor= new NullProgressMonitor();
+		}				
+		monitor.beginTask(NewWizardMessages.BuildPathsBlock_operationdesc_project, 10); 
+
+		// create the project
+		try {
+			if (!project.exists()) {
+				IProjectDescription desc= project.getWorkspace().newProjectDescription(project.getName());
+				if (Platform.getLocation().equals(locationPath)) {
+					locationPath= null;
+				}
+				desc.setLocation(locationPath);
+				project.create(desc, monitor);
+				monitor= null;
+			}
+			if (!project.isOpen()) {
+				project.open(monitor);
+				monitor= null;
+			}
+		} finally {
+			if (monitor != null) {
+				monitor.done();
+			}
+		}
+	}
+
+	public static void addJavaNature(IProject project, IProgressMonitor monitor) throws CoreException {
+		if (monitor != null && monitor.isCanceled()) {
+			throw new OperationCanceledException();
+		}
+		if (!project.hasNature(JavaCore.NATURE_ID)) {
+			IProjectDescription description = project.getDescription();
+			String[] prevNatures= description.getNatureIds();
+			String[] newNatures= new String[prevNatures.length + 1];
+			System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
+			newNatures[prevNatures.length]= JavaCore.NATURE_ID;
+			description.setNatureIds(newNatures);
+			project.setDescription(description, monitor);
+		} else {
+			monitor.worked(1);
+		}
+	}
+	
+	public void configureJavaProject(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
+		if (monitor == null) {
+			monitor= new NullProgressMonitor();
+		}
+		monitor.setTaskName(NewWizardMessages.BuildPathsBlock_operationdesc_java); 
+		monitor.beginTask("", 10); //$NON-NLS-1$
+		try {
+			IRemoveOldBinariesQuery reorgQuery= getRemoveOldBinariesQuery(null);
+			// remove old .class files
+			if (reorgQuery != null) {
+				IPath oldOutputLocation= fCurrJProject.getOutputLocation();
+				if (!getOutputLocation().equals(oldOutputLocation)) {
+					IResource res= fWorkspaceRoot.findMember(oldOutputLocation);
+					if (res instanceof IContainer && hasClassfiles(res)) {
+						if (reorgQuery.doQuery(oldOutputLocation)) {
+							removeOldClassfiles(res);
+						}
+					}
+				}		
+			}
+			
+			internalConfigureJavaProject(fClassPathList.getElements(), getOutputLocation(), reorgQuery, monitor);
+		} finally {
+			monitor.done();
+		}
+		updateUI();
+	}
+    	
+	/*
+	 * Creates the Java project and sets the configured build path and output location.
+	 * If the project already exists only build paths are updated.
+	 */
+	private void internalConfigureJavaProject(List classPathEntries, IPath outputLocation, IRemoveOldBinariesQuery reorgQuery, IProgressMonitor monitor) throws CoreException, OperationCanceledException {
+		// 10 monitor steps to go
+		
+		// create and set the output path first
+		if (!fWorkspaceRoot.exists(outputLocation)) {
+			IFolder folder= fWorkspaceRoot.getFolder(outputLocation);
+			CoreUtility.createFolder(folder, true, true, null);
+			folder.setDerived(true);		
+		}
+		
+
+		if (monitor.isCanceled()) {
+			throw new OperationCanceledException();
+		}
+		monitor.worked(2);
+				
+		int nEntries= classPathEntries.size();
+		IClasspathEntry[] classpath= new IClasspathEntry[nEntries];
+		
+		// create and set the class path
+		for (int i= 0; i < nEntries; i++) {
+			CPListElement entry= ((CPListElement)classPathEntries.get(i));
+			IResource res= entry.getResource();
+			if ((res instanceof IFolder) && !res.exists()) {
+				CoreUtility.createFolder((IFolder)res, true, true, null);
+			}
+			if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+				IPath folderOutput= (IPath) entry.getAttribute(CPListElement.OUTPUT);
+				if (folderOutput != null && folderOutput.segmentCount() > 1) {
+					IFolder folder= fWorkspaceRoot.getFolder(folderOutput);
+					CoreUtility.createFolder(folder, true, true, null);
+				}
+			}
+			
+			classpath[i]= entry.getClasspathEntry();
+		}	
+		
+		if (monitor.isCanceled()) {
+			throw new OperationCanceledException();
+		}
+		monitor.worked(1);
+				
+		fCurrJProject.setRawClasspath(classpath, outputLocation, new SubProgressMonitor(monitor, 7));
+		initializeTimeStamps();
+	}
+	
+	public static boolean hasClassfiles(IResource resource) throws CoreException {
+		if (resource.isDerived()) { //$NON-NLS-1$
+			return true;
+		}		
+		if (resource instanceof IContainer) {
+			IResource[] members= ((IContainer) resource).members();
+			for (int i= 0; i < members.length; i++) {
+				if (hasClassfiles(members[i])) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+	
+
+	public static void removeOldClassfiles(IResource resource) throws CoreException {
+		if (resource.isDerived()) {
+			resource.delete(false, null);
+		} else if (resource instanceof IContainer) {
+			IResource[] members= ((IContainer) resource).members();
+			for (int i= 0; i < members.length; i++) {
+				removeOldClassfiles(members[i]);
+			}
+		}
+	}
+	
+	public static IRemoveOldBinariesQuery getRemoveOldBinariesQuery(final Shell shell) {
+		return new IRemoveOldBinariesQuery() {
+			public boolean doQuery(final IPath oldOutputLocation) throws OperationCanceledException {
+				final int[] res= new int[] { 1 };
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						Shell sh= shell != null ? shell : JavaPlugin.getActiveWorkbenchShell();
+						String title= NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_title; 
+						String message= Messages.format(NewWizardMessages.BuildPathsBlock_RemoveBinariesDialog_description, oldOutputLocation.toString()); 
+						MessageDialog dialog= new MessageDialog(sh, title, null, message, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
+						res[0]= dialog.open();
+					}
+				});
+				if (res[0] == 0) {
+					return true;
+				} else if (res[0] == 1) {
+					return false;
+				}
+				throw new OperationCanceledException();
+			}
+		};
+	}	
+
+	
+	// ---------- util method ------------
+		
+	private IContainer chooseContainer() {
+		Class[] acceptedClasses= new Class[] { IProject.class, IFolder.class };
+		ISelectionStatusValidator validator= new TypedElementSelectionValidator(acceptedClasses, false);
+		IProject[] allProjects= fWorkspaceRoot.getProjects();
+		ArrayList rejectedElements= new ArrayList(allProjects.length);
+		IProject currProject= fCurrJProject.getProject();
+		for (int i= 0; i < allProjects.length; i++) {
+			if (!allProjects[i].equals(currProject)) {
+				rejectedElements.add(allProjects[i]);
+			}
+		}
+		ViewerFilter filter= new TypedViewerFilter(acceptedClasses, rejectedElements.toArray());
+
+		ILabelProvider lp= new WorkbenchLabelProvider();
+		ITreeContentProvider cp= new WorkbenchContentProvider();
+
+		IResource initSelection= null;
+		if (fOutputLocationPath != null) {
+			initSelection= fWorkspaceRoot.findMember(fOutputLocationPath);
+		}
+		
+		FolderSelectionDialog dialog= new FolderSelectionDialog(getShell(), lp, cp);
+		dialog.setTitle(NewWizardMessages.BuildPathsBlock_ChooseOutputFolderDialog_title); 
+		dialog.setValidator(validator);
+		dialog.setMessage(NewWizardMessages.BuildPathsBlock_ChooseOutputFolderDialog_description); 
+		dialog.addFilter(filter);
+		dialog.setInput(fWorkspaceRoot);
+		dialog.setInitialSelection(initSelection);
+		dialog.setSorter(new ResourceSorter(ResourceSorter.NAME));
+		
+		if (dialog.open() == Window.OK) {
+			return (IContainer)dialog.getFirstResult();
+		}
+		return null;
+	}
+	
+	// -------- tab switching ----------
+	
+	private void tabChanged(Widget widget) {
+		if (widget instanceof TabItem) {
+			TabItem tabItem= (TabItem) widget;
+			BuildPathBasePage newPage= (BuildPathBasePage) tabItem.getData();
+			if (fCurrPage != null) {
+				List selection= fCurrPage.getSelection();
+				if (!selection.isEmpty()) {
+					newPage.setSelection(selection, false);
+				}
+			}
+			fCurrPage= newPage;
+			fPageIndex= tabItem.getParent().getSelectionIndex();
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/JavaCapabilityConfigurationPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/JavaCapabilityConfigurationPage.java
new file mode 100644
index 0000000..dfb9bab
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/propertypage/JavaCapabilityConfigurationPage.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.internal.buildconfig.propertypage;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
+import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
+import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
+import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
+import org.eclipse.jdt.ui.wizards.NewElementWizardPage;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Copied from same in org.eclipse.jdt.ui.wizards.  Only change is to use
+ * BuildPathsBlock in this package.
+ */
+public class JavaCapabilityConfigurationPage extends NewElementWizardPage {
+
+	private static final String PAGE_NAME= "JavaCapabilityConfigurationPage"; //$NON-NLS-1$
+	
+	private IJavaProject fJavaProject;
+	private BuildPathsBlock fBuildPathsBlock;
+	
+	/**
+	 * Creates a wizard page that can be used in a Java project creation wizard.
+	 * It contains UI to configure a the classpath and the output folder.
+	 * 
+	 * <p>
+	 * After constructing, a call to <code>init</code> is required.
+	 * </p>
+	 */	
+	public JavaCapabilityConfigurationPage() {
+        super(PAGE_NAME);
+        fJavaProject= null;
+        
+        setTitle(NewWizardMessages.JavaCapabilityConfigurationPage_title); 
+        setDescription(NewWizardMessages.JavaCapabilityConfigurationPage_description); 
+	}
+    
+    private BuildPathsBlock getBuildPathsBlock() {
+        if (fBuildPathsBlock == null) {
+            IStatusChangeListener listener= new IStatusChangeListener() {
+                public void statusChanged(IStatus status) {
+                    updateStatus(status);
+                }
+            };
+            fBuildPathsBlock= new BuildPathsBlock(new BusyIndicatorRunnableContext(), listener, 0, useNewSourcePage(), null);
+        }
+        return fBuildPathsBlock;
+    }
+	
+	/**
+	 * Clients can override this method to choose if the new source page is used. The new source page
+	 * requires that the project is already created as Java project. The page will directly manipulate the classpath.
+	 * By default <code>false</code> is returned.
+	 * @return Returns <code>true</code> if the new source page should be used.
+	 * @since 3.1
+	 */
+	protected boolean useNewSourcePage() {
+		return false;
+	}
+
+	/**
+	 * Initializes the page with the project and default classpaths.
+	 * <p>
+	 * The default classpath entries must correspond the the given project.
+	 * </p>
+	 * <p>
+	 * The caller of this method is responsible for creating the underlying project. The page will create the output,
+	 * source and library folders if required.
+	 * </p>
+	 * <p>
+	 * The project does not have to exist at the time of initialization, but must exist when executing the runnable
+	 * obtained by <code>getRunnable()</code>.
+	 * </p>
+	 * @param jproject The Java project.
+	 * @param defaultOutputLocation The default classpath entries or <code>null</code> to let the page choose the default
+	 * @param defaultEntries The folder to be taken as the default output path or <code>null</code> to let the page choose the default
+	 * @param defaultsOverrideExistingClasspath If set to <code>true</code>, an existing '.classpath' file is ignored. If set to <code>false</code>
+	 * the given default classpath and output location is only used if no '.classpath' exists.
+	 */
+	public void init(IJavaProject jproject, IPath defaultOutputLocation, IClasspathEntry[] defaultEntries, boolean defaultsOverrideExistingClasspath) {
+		if (!defaultsOverrideExistingClasspath && jproject.exists() && jproject.getProject().getFile(".classpath").exists()) { //$NON-NLS-1$
+			defaultOutputLocation= null;
+			defaultEntries= null;
+		}
+		getBuildPathsBlock().init(jproject, defaultOutputLocation, defaultEntries);
+		fJavaProject= jproject;
+	}	
+
+	/* (non-Javadoc)
+	 * @see WizardPage#createControl
+	 */	
+	public void createControl(Composite parent) {
+		Composite composite= new Composite(parent, SWT.NONE);
+		composite.setFont(parent.getFont());
+		composite.setLayout(new GridLayout(1, false));
+		Control control= getBuildPathsBlock().createControl(composite);
+		control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+		Dialog.applyDialogFont(composite);
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.NEW_JAVAPROJECT_WIZARD_PAGE);
+		setControl(composite);
+	}
+		
+	/**
+	 * Returns the currently configured output location. Note that the returned path 
+	 * might not be a valid path.
+	 * 
+	 * @return the currently configured output location
+	 */
+	public IPath getOutputLocation() {
+		return getBuildPathsBlock().getOutputLocation();
+	}
+
+	/**
+	 * Returns the currently configured classpath. Note that the classpath might 
+	 * not be valid.
+	 * 
+	 * @return the currently configured classpath
+	 */	
+	public IClasspathEntry[] getRawClassPath() {
+		return getBuildPathsBlock().getRawClassPath();
+	}
+	
+	/**
+	 * Returns the Java project that was passed in <code>init</code> or <code>null</code> if the 
+	 * page has not been initialized yet.
+	 * 
+	 * @return the managed Java project or <code>null</code>
+	 */	
+	public IJavaProject getJavaProject() {
+		return fJavaProject;
+	}	
+	
+
+	/**
+	 * Returns the runnable that will create the Java project or <code>null</code> if the page has 
+	 * not been initialized. The runnable sets the project's classpath and output location to the values 
+	 * configured in the page and adds the Java nature if not set yet. The method requires that the 
+	 * project is created and opened.
+	 *
+	 * @return the runnable that creates the new Java project
+	 */		
+	public IRunnableWithProgress getRunnable() {
+		if (getJavaProject() != null) {
+			return new IRunnableWithProgress() {
+				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+					try {
+						configureJavaProject(monitor);
+					} catch (CoreException e) {
+						throw new InvocationTargetException(e);
+					}
+				}
+			};
+		}
+		return null;	
+	}
+
+	/**
+	 * Helper method to create and open a IProject . The project location
+	 * is configured. No natures are added.
+	 * 
+	 * @param project The handle of the project to create.
+	 * @param locationPath The location of the project.
+	 * @param monitor a progress monitor to report progress or <code>null</code> if
+	 * progress reporting is not desired
+	 * @throws CoreException
+	 * @since 2.1
+	 */
+	public static void createProject(IProject project, IPath locationPath, IProgressMonitor monitor) throws CoreException {
+		BuildPathsBlock.createProject(project, locationPath, monitor);
+	}
+	
+	/**
+	 * Adds the Java nature to the project (if not set yet) and configures the build classpath.
+	 * 
+	 * @param monitor a progress monitor to report progress or <code>null</code> if
+	 * progress reporting is not desired
+	 * @throws CoreException Thrown when the configuring the Java project failed.
+	 * @throws InterruptedException Thrown when the operation has been cancelled.
+	 */
+	public void configureJavaProject(IProgressMonitor monitor) throws CoreException, InterruptedException {
+		if (monitor == null) {
+			monitor= new NullProgressMonitor();
+		}
+		
+		int nSteps= 6;			
+		monitor.beginTask(NewWizardMessages.JavaCapabilityConfigurationPage_op_desc_java, nSteps); 
+		
+		try {
+			IProject project= getJavaProject().getProject();
+			BuildPathsBlock.addJavaNature(project, new SubProgressMonitor(monitor, 1));
+			getBuildPathsBlock().configureJavaProject(new SubProgressMonitor(monitor, 5));
+		} catch (OperationCanceledException e) {
+			throw new InterruptedException();
+		} finally {
+			monitor.done();
+		}			
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationCreationPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationCreationPage.java
new file mode 100755
index 0000000..b299f35
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationCreationPage.java
@@ -0,0 +1,212 @@
+/**********************************************************************
+Copyright (c) 2002, 2005 IBM Corporation and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+Contributors:
+Adrian Colyer, Andy Clement, Tracy Gardner - initial version
+Sian January - updated for new style build configurations
+...
+**********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.wizards;
+
+import org.eclipse.ajdt.core.AJLog;
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfiguration;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.ajdt.ui.AspectJUIPlugin;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.IBuildConfiguration;
+import org.eclipse.ajdt.ui.buildconfig.IProjectBuildConfigurator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.dialogs.WizardNewFileCreationPage;
+import org.eclipse.ui.ide.IDE;
+
+/**
+ * This class is the only page of the ".lst" file resource creation wizard.  
+ * It subclasses the standard file resource creation page class, 
+ * and consequently inherits the file resource creation functionality.
+ */
+public class BuildConfigurationCreationPage extends WizardNewFileCreationPage {
+	private IWorkbench workbench;
+
+	// widgets
+	private Button openFileCheckbox;
+	private Button makeActiveCheckbox;
+
+	// constants
+	
+	private IStructuredSelection selection;
+		
+	
+	/**
+	 * Creates the page for the build configuration file creation wizard.
+	 *
+	 * @param workbench  the workbench on which the page should be created
+	 * @param selection  the current selection
+	 */
+	public BuildConfigurationCreationPage(
+		IWorkbench workbench,
+		IStructuredSelection selection) {
+		super("CreateBuildConfigurationFilePage1", selection); //$NON-NLS-1$
+		this.setTitle(UIMessages.BuildConfig_createLstFile); 
+		this.setDescription(UIMessages.BuildConfig_createLstDesc);
+		this.workbench = workbench;
+		this.selection = selection;
+	}
+	
+	/**
+     * Build the GUI representation of the page.
+	 */
+	public void createControl(Composite parent) {
+		// inherit default container and name specification widgets
+		super.createControl(parent);
+		Composite composite = (Composite) getControl();
+		
+        //ASCFIXME: Add help!
+		//WorkbenchHelp.setHelp(composite, new String[] {IReadmeConstants.CREATION_WIZARD_PAGE_CONTEXT});
+
+		this.setFileName(getFreeFileName() + "." + IBuildConfiguration.EXTENSION); //$NON-NLS-1$
+
+		// open file for editing checkbox
+		openFileCheckbox = new Button(composite, SWT.CHECK);
+		openFileCheckbox.setText(UIMessages.BuildConfig_openForEdit);
+		openFileCheckbox.setSelection(true);
+		
+		makeActiveCheckbox = new Button(composite, SWT.CHECK);
+		makeActiveCheckbox.setText(UIMessages.BuildConfig_activate);
+		makeActiveCheckbox.setSelection(true);
+
+		setPageComplete(validatePage());
+
+	}
+	
+	/**
+	 * Get a suitable and unused filename (without file extension)
+	 * @return
+	 */
+	private String getFreeFileName() {
+		IProject project = null;
+		if(selection.size() > 0) {
+			Object element = selection.getFirstElement();
+			if(element instanceof IResource) {
+				project = ((IResource)element).getProject(); 
+			} else if (element instanceof IJavaElement) {
+				project = ((IJavaElement)element).getJavaProject().getProject();
+			}
+		}
+		return BuildConfigurator.getFreeFileName(project);
+	}
+
+	/*
+	 * Override because linking to a file in the file system doesn't make a lot
+	 * of sense in this case
+	 */
+	protected void createAdvancedControls(Composite parent){}
+	
+	/*
+	 * Override because we overrode createAdvancedControls(..) 
+	 */
+	protected IStatus validateLinkedResource() {
+		return new Status(IStatus.OK, AspectJUIPlugin.PLUGIN_ID, IStatus.OK, "", null); //$NON-NLS-1$
+	}
+	
+	/*
+	 * Override because we overrode createAdvancedControls(..) 
+	 */	
+	protected void createLinkTarget() {}
+
+	/**
+	 * Creates a new file resource as requested by the user. If everything
+	 * is OK then answer true. If not, false will cause the dialog
+	 * to stay open.
+	 *
+	 * @return whether creation was successful
+	 * @see ReadmeCreationWizard#performFinish()
+	 */
+	public boolean finish() {
+		// create the new file resource
+		
+		IFile newFile = createNewFile();
+
+		
+		if (newFile == null)
+			return false; // ie.- creation was unsuccessful
+
+		// Since the file resource was created fine, open it for editing
+		// if requested by the user
+		IProject project = newFile.getProject();
+		IProjectBuildConfigurator pbc = DefaultBuildConfigurator.getBuildConfigurator().getProjectBuildConfigurator(project);
+		new BuildConfiguration(newFile, pbc, makeActiveCheckbox.getSelection());
+		try {
+			if (openFileCheckbox.getSelection()) {
+				IWorkbenchWindow dwindow = workbench.getActiveWorkbenchWindow();
+				IWorkbenchPage page = dwindow.getActivePage();
+				if (page != null) IDE.openEditor(page,newFile,true);
+			}
+		} catch (PartInitException e) {
+			return false;
+		} 
+		AJLog.log("New config file created: " + newFile.getName()); //$NON-NLS-1$
+		return true;
+	}
+	
+
+	/**
+	 * Validate the page
+	 */
+	protected boolean validatePage() {
+		if(super.validatePage()) {
+			if(!isProjectSelected()) {
+				setErrorMessage(UIMessages.BuildConfig_needToSelectProject);
+				return false;
+			} else {
+				return true;
+			}			
+		} else {
+			return false;
+		}
+	}
+	
+
+	/**
+	 * Test to see whether the selected parent is a project
+	 * @return
+	 */
+	private boolean isProjectSelected() {
+		IPath containerPath = getContainerFullPath();
+		IProject[] projects = AspectJPlugin.getWorkspace().getRoot().getProjects();
+		for (int i = 0; i < projects.length; i++) {
+			IProject project = projects[i];
+			IPath path = project.getFullPath();
+			if(path.equals(containerPath)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/** (non-Javadoc)
+	 * Method declared on WizardNewFileCreationPage.
+	 */
+	protected String getNewFileLabel() {
+		return UIMessages.BuildConfig_newBCFile;
+	}
+
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationFileWizard.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationFileWizard.java
new file mode 100755
index 0000000..eefc265
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/internal/buildconfig/wizards/BuildConfigurationFileWizard.java
@@ -0,0 +1,77 @@
+/**********************************************************************
+Copyright (c) 2002 IBM Corporation and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Common Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/cpl-v10.html
+Contributors:
+Adrian Colyer, Andy Clement, Tracy Gardner - initial version
+...
+**********************************************************************/
+package org.eclipse.ajdt.internal.buildconfig.wizards;
+
+import org.eclipse.ajdt.internal.ui.text.UIMessages;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * This class implements the interface required by the desktop
+ * for all 'New' wizards.  This wizard creates Aspect#J Build
+ * configuration files.
+ */
+public class BuildConfigurationFileWizard
+	extends Wizard
+	implements INewWizard {
+	protected IStructuredSelection selection;
+	protected IWorkbench workbench;
+	private BuildConfigurationCreationPage mainPage;
+
+	/** 
+	 * Adds the BuildConfigurationCreationPage
+	 */
+	public void addPages() {
+		mainPage = new BuildConfigurationCreationPage(workbench, selection);
+		addPage(mainPage);
+	}
+	
+	/** 
+	 * Set-up the title and icon.
+	 */
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		this.workbench = workbench;
+		if(selection instanceof StructuredSelection) {
+			if(((StructuredSelection)selection).size() > 0) {
+				Object firstObject = ((StructuredSelection)selection).getFirstElement();
+				if(firstObject instanceof IResource) {
+					IProject project = ((IResource)firstObject).getProject();
+					StructuredSelection newSelection = new StructuredSelection(project);
+					this.selection = newSelection;
+				} else if(firstObject instanceof IJavaElement) {
+					IJavaProject project = ((IJavaElement)firstObject).getJavaProject();
+					StructuredSelection newSelection = new StructuredSelection(project);
+					this.selection = newSelection;
+				}
+			}
+		}
+		if(this.selection == null) {
+			this.selection = selection;
+		}
+		setWindowTitle(UIMessages.newConfig); 
+		//setDefaultPageImageDescriptor( AspectJImages.getImageDescriptor( AspectJImages.FILE_LST ) );
+	}
+
+	
+	/** 
+	 * Complete generation of the build configuration file.
+	 */
+	public boolean performFinish() {
+		return mainPage.finish();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/EmptyOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/EmptyOutlinePage.java
new file mode 100755
index 0000000..2c2a4e5
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/EmptyOutlinePage.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Jan 28, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.IActionBars;
+
+
+public class EmptyOutlinePage implements ISortableContentOutlinePage {
+	private Composite control;
+	/**
+	 * 
+	 */
+	public EmptyOutlinePage() {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		control = new Composite(parent, SWT.NULL);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.part.IPage#dispose()
+	 */
+	public void dispose() {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.part.IPage#getControl()
+	 */
+	public Control getControl() {
+		return control;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.part.IPage#setActionBars(org.eclipse.ui.IActionBars)
+	 */
+	public void setActionBars(IActionBars actionBars) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.part.IPage#setFocus()
+	 */
+	public void setFocus() {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+	 */
+	public void addSelectionChangedListener(ISelectionChangedListener listener) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
+	 */
+	public ISelection getSelection() {
+		return new ISelection() { 
+			public boolean isEmpty() { return true; }
+		};
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
+	 */
+	public void removeSelectionChangedListener(
+			ISelectionChangedListener listener) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
+	 */
+	public void setSelection(ISelection selection) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.editor.ISortable#sort(boolean)
+	 */
+	public void sort(boolean sorting) {
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormEntryAdapter.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormEntryAdapter.java
new file mode 100644
index 0000000..3c0e64e
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormEntryAdapter.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Feb 27, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.ui.*;
+import org.eclipse.ui.forms.events.*;
+
+public class FormEntryAdapter implements IFormEntryListener {
+	private IContextPart contextPart;
+	protected IActionBars actionBars;
+
+	public FormEntryAdapter(IContextPart contextPart) {
+		this(contextPart, null);
+	}
+	public FormEntryAdapter(IContextPart contextPart, IActionBars actionBars) {
+		this.contextPart = contextPart;
+		this.actionBars = actionBars;
+	}
+	public void focusGained(FormEntry entry) {
+		ITextSelection selection = new TextSelection(1,1);
+		contextPart.getPage().getPDEEditor().getContributor().updateSelectableActions(selection);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.newparts.IFormEntryListener#textDirty(org.eclipse.pde.internal.ui.newparts.FormEntry)
+	 */
+	public void textDirty(FormEntry entry) {
+		contextPart.fireSaveNeeded();
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.newparts.IFormEntryListener#textValueChanged(org.eclipse.pde.internal.ui.newparts.FormEntry)
+	 */
+	public void textValueChanged(FormEntry entry) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.newparts.IFormEntryListener#browseButtonSelected(org.eclipse.pde.internal.ui.newparts.FormEntry)
+	 */
+	public void browseButtonSelected(FormEntry entry) {
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.events.HyperlinkListener#linkEntered(org.eclipse.ui.forms.events.HyperlinkEvent)
+	 */
+	public void linkEntered(HyperlinkEvent e) {
+		if (actionBars==null) return;
+		IStatusLineManager mng = actionBars.getStatusLineManager();
+		mng.setMessage(e.getLabel());
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.events.HyperlinkListener#linkExited(org.eclipse.ui.forms.events.HyperlinkEvent)
+	 */
+	public void linkExited(HyperlinkEvent e) {
+		if (actionBars==null) return;
+		IStatusLineManager mng = actionBars.getStatusLineManager();
+		mng.setMessage(null);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.events.HyperlinkListener#linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent)
+	 */
+	public void linkActivated(HyperlinkEvent e) {
+	}
+	public void selectionChanged(FormEntry entry) {
+		ITextSelection selection = new TextSelection(1,1);
+		contextPart.getPage().getPDEEditor().getContributor().updateSelectableActions(selection);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormOutlinePage.java
new file mode 100755
index 0000000..4f59255
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/FormOutlinePage.java
@@ -0,0 +1,232 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.util.ArrayList;
+
+import org.eclipse.jface.viewers.*;
+import org.eclipse.pde.core.*;
+import org.eclipse.pde.internal.core.plugin.ImportObject;
+import org.eclipse.pde.internal.core.text.IDocumentNode;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+public class FormOutlinePage extends ContentOutlinePage
+		implements
+			IModelChangedListener, ISortableContentOutlinePage {
+	private boolean stale;
+	private ViewerSorter fViewerSorter;
+	private boolean sorted;
+	public class BasicContentProvider extends DefaultContentProvider
+			implements
+				ITreeContentProvider {
+		public Object[] getElements(Object obj) {
+			return getPages();
+		}
+		public Object[] getChildren(Object obj) {
+			return FormOutlinePage.this.getChildren(obj);
+		}
+		public boolean hasChildren(Object obj) {
+			return getChildren(obj).length > 0;
+		}
+		public Object getParent(Object obj) {
+			return null;
+		}
+	}
+	public class BasicLabelProvider extends LabelProvider {
+		public String getText(Object obj) {
+			if (obj instanceof IFormPage)
+				return ((IFormPage)obj).getTitle();
+			return PDEPlugin.getDefault().getLabelProvider().getText(obj);
+		}
+		public Image getImage(Object obj) {
+			if (obj instanceof IFormPage)
+				return PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_PAGE_OBJ);
+			return PDEPlugin.getDefault().getLabelProvider().getImage(obj);
+		}
+	}
+	public class BasicSorter extends ViewerSorter {
+		/* (non-Javadoc)
+		 * @see org.eclipse.jface.viewers.ViewerSorter#category(java.lang.Object)
+		 */
+		public int category(Object element) {
+			Object[] pages = getPages();
+			for(int i=0; i<pages.length; i++){
+				if(pages[i]==element){
+					return i;
+				}
+			}
+			return Integer.MAX_VALUE;
+		}
+	}
+	protected TreeViewer treeViewer;
+	protected PDEFormEditor editor;
+	protected boolean editorSelection = false;
+	protected boolean outlineSelection = false;
+	public FormOutlinePage(PDEFormEditor editor) {
+		this.editor = editor;
+	}
+	protected ITreeContentProvider createContentProvider() {
+		return new BasicContentProvider();
+	}
+	protected ViewerSorter createOutlineSorter(){
+		fViewerSorter = new BasicSorter();
+		return fViewerSorter;
+	}
+	public void createControl(Composite parent) {
+		Tree widget = new Tree(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
+		treeViewer = new TreeViewer(widget);
+		treeViewer.addSelectionChangedListener(this);
+		treeViewer.setContentProvider(createContentProvider());
+		treeViewer.setLabelProvider(createLabelProvider());
+		createOutlineSorter();
+		if(sorted)
+			treeViewer.setSorter(fViewerSorter);
+		else
+			treeViewer.setSorter(null);
+		treeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
+		treeViewer.setUseHashlookup(true);
+		treeViewer.setInput(editor);
+		IBaseModel model = editor.getAggregateModel();
+		if (model instanceof IModelChangeProvider)
+			((IModelChangeProvider)model).addModelChangedListener(this);
+	}
+	protected ILabelProvider createLabelProvider() {
+		return new BasicLabelProvider();
+	}
+	public void dispose() {
+		IBaseModel model = editor.getAggregateModel();
+		if (model instanceof IModelChangeProvider)
+			((IModelChangeProvider)model).removeModelChangedListener(this);
+		super.dispose();
+	}
+	
+	public Control getControl() {
+		return treeViewer != null ? treeViewer.getControl() : null;
+	}
+	private Object[] getPages() {
+		ArrayList formPages = new ArrayList();
+		IFormPage [] pages = editor.getPages();
+		for (int i=0; i<pages.length; i++) {
+			if (pages[i].isEditor()==false)
+				formPages.add(pages[i]);
+		}
+		return formPages.toArray(); 
+	}
+
+	public void modelChanged(IModelChangedEvent event) {
+		IFormPage page = editor.getActivePageInstance();
+		stale=true;
+		if (page.isEditor()==false)
+			refresh();
+	}
+	
+	public void refresh() {
+		if (stale) {
+			treeViewer.refresh();
+			treeViewer.expandAll();
+			stale=false;
+		}
+	}
+	
+	protected String getParentPageId(Object item) {
+		if (item instanceof IFormPage)
+			return ((IFormPage)item).getId();
+		return null;
+	}
+	
+	protected Object[] getChildren(Object parent) {
+		return new Object[0];
+	}
+
+	public void selectionChanged(Object item) {
+		IFormPage page = editor.getActivePageInstance();
+		String id = getParentPageId(item);
+		IFormPage newPage=null;
+		if (id!=null && (page==null || !page.getId().equals(id)))
+			newPage = editor.setActivePage(id);
+		IFormPage revealPage = newPage!=null?newPage:page;
+		if (revealPage!=null && !(item instanceof IFormPage))
+			revealPage.selectReveal(item);
+	}
+	
+	public void selectionChanged(SelectionChangedEvent event) {
+		if (editorSelection)
+			return;
+		outlineSelection = true;
+		try {
+			ISelection selection = event.getSelection();
+			if (selection.isEmpty() == false
+					&& selection instanceof IStructuredSelection) {
+				IStructuredSelection ssel = (IStructuredSelection) selection;
+				Object item = ssel.getFirstElement();
+				selectionChanged(item);
+			}
+			fireSelectionChanged(selection);
+		} finally {
+			outlineSelection = false;
+		}
+	}
+	public void setFocus() {
+		if (treeViewer != null)
+			treeViewer.getTree().setFocus();
+	}
+	public ISelection getSelection() {
+		if (treeViewer == null)
+			return StructuredSelection.EMPTY;
+		return treeViewer.getSelection();
+	}
+	public void sort (boolean sorting){
+		sorted = sorting;
+		if(treeViewer!=null)
+			if(sorting)
+				treeViewer.setSorter(fViewerSorter);
+			else
+				treeViewer.setSorter(null);
+	}
+	/*
+	 * (non-Javadoc) Method declared on ISelectionProvider.
+	 */
+	public void setSelection(ISelection selection) {
+		if (outlineSelection)
+			return;
+		editorSelection = true;
+		try {
+			if (treeViewer == null)
+				return;
+			if (selection != null && !selection.isEmpty()
+					&& selection instanceof IStructuredSelection) {
+				Object item = ((IStructuredSelection) selection)
+						.getFirstElement();
+				if (item instanceof ImportObject) {
+					selection = new StructuredSelection(((ImportObject) item)
+							.getImport());
+				}
+				if (item instanceof IDocumentNode) {
+					while (null == treeViewer.testFindItem(item)) {
+						item = ((IDocumentNode) item).getParentNode();
+						if (item == null) {
+							break;
+						} 
+						selection = new StructuredSelection(item);					
+					}
+				}
+			}
+			treeViewer.setSelection(selection);
+		} finally {
+			editorSelection = false;
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/GenericSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/GenericSourcePage.java
new file mode 100755
index 0000000..cc61cc1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/GenericSourcePage.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.*;
+
+/**
+ *
+ */
+public class GenericSourcePage extends PDESourcePage {
+	/**
+	 * @param editor
+	 * @param id
+	 * @param title
+	 */
+	public GenericSourcePage(PDEFormEditor editor, String id, String title) {
+		super(editor, id, title);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createOutlineLabelProvider()
+	 */
+	protected ILabelProvider createOutlineLabelProvider() {
+		return null;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createOutlineContentProvider()
+	 */
+	protected ITreeContentProvider createOutlineContentProvider() {
+		return null;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createOutlineContentProvider()
+	 */
+	protected ViewerSorter createOutlineSorter() {
+		return null;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#outlineSelectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+	 */
+	protected void outlineSelectionChanged(SelectionChangedEvent e) {
+	}
+	protected ISortableContentOutlinePage createOutlinePage() {
+		return null;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IContextPart.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IContextPart.java
new file mode 100755
index 0000000..0f94e46
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IContextPart.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.pde.core.IModelChangedListener;
+
+public interface IContextPart extends IModelChangedListener {
+	boolean isEditable();
+	PDEFormPage getPage();
+	String getContextId();
+	void fireSaveNeeded();
+	void cancelEdit();
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IModelUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IModelUndoManager.java
new file mode 100755
index 0000000..e7a87c2
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/IModelUndoManager.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.pde.core.IModelChangeProvider;
+
+/**
+ * Classes that implement this interface provide undo/redo
+ * capability linked to changes reported by model change
+ * providers. Model change events carry sufficient data
+ * to be used in an undo/redo stack and reverted to or
+ * reapplied after the change.
+ * <p>Model undo manager adds itself as a change listener
+ * after being connected to the provider. It is expected
+ * to stop listening to change events after being disconnected.
+ * Changes reported while being connected are kept in the
+ * operation stack whose size can be controlled.
+ * <p>The part that uses the undo manager is responsible
+ * for supplying Undo and Redo action objects for
+ * the purpose of controlling their availability. 
+ * Undo manager should keep track of its current
+ * operation stack pointer and adjust Undo/Redo action
+ * availability by calling 'setEnabled' on the
+ * provided action objects. Implementation of this
+ * interface may also opt to modify Undo/Redo action
+ * labels in order to better indicate the effect
+ * of the operations if selected (for example,
+ * 'Undo Delete' instead of 'Undo').
+ */
+public interface IModelUndoManager {
+	/**
+	 * Connects to the change provider. Until disconnecting,
+	 * the manager will keep model changes in the operation
+	 * stack and will be able to revert or reapply these
+	 * changes in the source model.
+	 * @param provider the model change provider to connect to
+	 */
+	public void connect(IModelChangeProvider provider);
+	/**
+	 * Disconnects from the change provider. Upon disconnecting,
+	 * the manager will no longer be able to revert or reapply
+	 * changes in the source model.
+	 * @param provider the model change provider to disconnect from
+	 */
+	public void disconnect(IModelChangeProvider provider);
+	/**
+	 * Tests whether the current operation in the undo stack can
+	 * be reverted.
+	 * @return true if the current operation can be undone.
+	 */
+	public boolean isUndoable();
+	/**
+	 * Tests whether the current operation in the undo stack can
+	 * be reapplied.
+	 * @return true if the current operation can be redone.
+	 */
+	public boolean isRedoable();
+	/**
+	 * Reverts the current operation in the undo stack and decrements
+	 * the stack pointer.
+	 */
+	public void undo();
+	/**
+	 * Reapplies the next operation in the undo stack and sets
+	 * the stack pointer to that operation.
+	 * 
+	 */
+	public void redo();
+	/**
+	 * Sets the depth of the undo stack.
+	 * @param limit number of levels in the undo stack.
+	 */
+	public void setUndoLevelLimit(int limit);
+	/**
+	 * Temporarily suspends undo manager.
+	 * @param ignore if true, model changes reported by the 
+	 * model change provider will be ignore until this
+	 * property is set to <samp>false</samp> again.
+	 */
+	public void setIgnoreChanges(boolean ignore);
+	/**
+	 * Connects the undo manager with the undo and redo actions 
+	 * in the workbench part using the manager. The manager
+	 * uses these objects to enable or disable the actions
+	 * according to the state of the undo stack and the current
+	 * location of the stack pointer. 
+	 * @param undoAction the action in the workbench part that performs
+	 * the undo operation.
+	 * @param redoAction the action in the workbench part that performs
+	 * the redo operation.
+	 */
+	public void setActions(IAction undoAction, IAction redoAction);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ISortableContentOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ISortableContentOutlinePage.java
new file mode 100755
index 0000000..5c73170
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ISortableContentOutlinePage.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+/**
+ * IConentOutlinePage with externally enabled/disabled element sorting
+ */
+public interface ISortableContentOutlinePage extends IContentOutlinePage {
+	/**
+	 * Turns sorting on or off
+	 * @param sorting - boolean value indicating if sorting should be enabled
+	 */
+	public void sort(boolean sorting);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryEditorInput.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryEditorInput.java
new file mode 100644
index 0000000..d0cb27f
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryEditorInput.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+
+import java.io.*;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.*;
+
+
+/**
+ * An EditorInput for a JarEntryFile.
+ */
+public class JarEntryEditorInput implements IStorageEditorInput {
+		
+	private IStorage fJarEntryFile; 
+	
+	public JarEntryEditorInput(IStorage jarEntryFile) {
+		fJarEntryFile= jarEntryFile;
+	}
+	
+	/*
+	 */
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (!(obj instanceof JarEntryEditorInput))
+			return false;
+		JarEntryEditorInput other= (JarEntryEditorInput) obj;
+		return fJarEntryFile.equals(other.fJarEntryFile);
+	}
+		
+	/*
+	 * @see IEditorInput#getPersistable()
+	 */
+	public IPersistableElement getPersistable() {
+		return null;
+	}
+	
+	/*
+	 * @see IEditorInput#getName()
+	 */
+	public String getName() {
+		return fJarEntryFile.getName();
+	}
+	
+	/*
+	 * @see IEditorInput#getFullPath()
+	 */
+	public String getFullPath() {
+		return fJarEntryFile.getFullPath().toString();
+	}
+	
+	/*
+	 * @see IEditorInput#getContentType()
+	 */
+	public String getContentType() {
+		return fJarEntryFile.getFullPath().getFileExtension();
+	}
+	
+	/*
+	 * @see IEditorInput#getToolTipText()
+	 */
+	public String getToolTipText() {
+		return fJarEntryFile.getFullPath().toString();
+	}
+	
+	/*
+	 * @see IEditorInput#getImageDescriptor()
+	 */
+	public ImageDescriptor getImageDescriptor() {
+		IEditorRegistry registry= PlatformUI.getWorkbench().getEditorRegistry();
+		return registry.getImageDescriptor(fJarEntryFile.getFullPath().getFileExtension());
+	}
+	
+	/*
+	 * @see IEditorInput#exists()
+	 */
+	public boolean exists() {
+		// JAR entries can't be deleted
+		return true;
+	}
+	
+	/*
+	 * @see IAdaptable#getAdapter(Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(File.class))
+			return fJarEntryFile.getAdapter(File.class);
+		return null;
+	}
+		
+	/*
+	 * see IStorageEditorInput#getStorage()
+	 */
+	 public IStorage getStorage() {
+	 	return fJarEntryFile;
+	 }
+}
+
+
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryFile.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryFile.java
new file mode 100644
index 0000000..14b4abb
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/JarEntryFile.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import java.util.zip.*;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.internal.ui.*;
+
+
+public class JarEntryFile extends PlatformObject implements IStorage {
+	
+	private ZipFile fZipFile;
+	private String fEntryName;
+
+	public JarEntryFile(ZipFile zipFile, String entryName) {
+		fZipFile = zipFile;
+		fEntryName = entryName;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.resources.IStorage#getContents()
+	 */
+	public InputStream getContents() throws CoreException {
+		try {
+			ZipEntry zipEntry = fZipFile.getEntry(fEntryName);
+			return fZipFile.getInputStream(zipEntry);
+		} catch (Exception e){
+			throw new CoreException(new Status(IStatus.ERROR, PDEPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e));
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.resources.IStorage#getFullPath()
+	 */
+	public IPath getFullPath() {
+		return new Path(fEntryName);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.resources.IStorage#getName()
+	 */
+	public String getName() {
+		return getFullPath().lastSegment();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.resources.IStorage#isReadOnly()
+	 */
+	public boolean isReadOnly() {
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+	 */
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(ZipFile.class))
+			return fZipFile;
+		if (adapter.equals(File.class))
+			return new File(fZipFile.getName());
+		return super.getAdapter(adapter);
+	}
+	
+	public String toString() {
+		return "JarEntryFile["+ fZipFile.getName() + "::" + fEntryName + "]"; //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+	}
+	
+	public boolean equals(Object obj) {
+		if (!(obj instanceof JarEntryFile))
+			return false;
+		return toString().equals(obj.toString());
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/KeyValueSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/KeyValueSourcePage.java
new file mode 100755
index 0000000..1480f5b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/KeyValueSourcePage.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.pde.internal.core.text.IDocumentKey;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.pde.internal.core.util.PropertiesUtil;
+import org.eclipse.pde.internal.ui.editor.text.AnnotationHover;
+import org.eclipse.pde.internal.ui.editor.text.ReconcilingStrategy;
+import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
+
+public abstract class KeyValueSourcePage extends PDESourcePage {
+
+	class KeyValueSourceViewerConfiguration extends TextSourceViewerConfiguration {
+		private AnnotationHover fAnnotationHover;
+		public IReconciler getReconciler(ISourceViewer sourceViewer) {
+			ReconcilingStrategy strategy = new ReconcilingStrategy();
+			strategy.addParticipant((IReconcilingParticipant) getInputContext()
+					.getModel());
+			strategy.addParticipant((SourceOutlinePage)getContentOutline());
+			MonoReconciler reconciler = new MonoReconciler(strategy, false);
+			reconciler.setDelay(500);
+			return reconciler;
+		}
+		public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+			if (fAnnotationHover == null)
+				fAnnotationHover = new AnnotationHover();
+			return fAnnotationHover;
+		}
+	}
+	public KeyValueSourcePage(PDEFormEditor editor, String id, String title) {
+		super(editor, id, title);
+		setSourceViewerConfiguration(new KeyValueSourceViewerConfiguration());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.PDESourcePage#createViewerSorter()
+	 */
+	protected ViewerSorter createDefaultOutlineSorter() {
+		return new ViewerSorter() {
+			public int compare(Viewer viewer, Object e1, Object e2) {
+				IDocumentKey key1 = (IDocumentKey)e1;
+				IDocumentKey key2 = (IDocumentKey)e2;
+				return key1.getOffset() < key2.getOffset() ? -1 : 1;
+			}
+		};
+	}
+	
+	protected void outlineSelectionChanged(SelectionChangedEvent event) {
+		ISelection selection= event.getSelection();
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection structuredSelection= (IStructuredSelection) selection;
+			Object first= structuredSelection.getFirstElement();
+			if (first instanceof IDocumentKey) {
+				setHighlightRange((IDocumentKey)first);				
+			} else {
+				resetHighlightRange();
+			}
+		}
+	}
+	
+	public void setHighlightRange(IDocumentKey key) {
+		ISourceViewer sourceViewer = getSourceViewer();
+		if (sourceViewer == null)
+			return;
+
+		IDocument document = sourceViewer.getDocument();
+		if (document == null)
+			return;
+
+		int offset = key.getOffset();
+		int length = key.getLength();
+		setHighlightRange(offset, length, true);
+		int nameLength = PropertiesUtil.createWritableName(key.getName())
+				.length();
+		sourceViewer.setSelectedRange(offset, Math.min(nameLength, length));
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.editor.PDESourcePage#createOutlineSorter()
+	 */
+	protected ViewerSorter createOutlineSorter() {
+		return new ViewerSorter();
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/LinkSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/LinkSection.java
new file mode 100644
index 0000000..1acff42
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/LinkSection.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.events.*;
+import org.eclipse.ui.forms.widgets.*;
+/**
+ * This class can be used to show a standard section with an array of links.
+ * Links are objects from editor pages, and each one will select the owning
+ * page and reveal the element in it. If the number of objects from the content
+ * provider is greated than the preset limit, only the first 'limit' number of
+ * links will be shown, and a 'More...' button will show up (this is a change
+ * from 2.1 where 'More...' was visible all the time).
+ */
+public class LinkSection extends PDESection {
+	private ILinkLabelProvider labelProvider;
+	private IStructuredContentProvider contentProvider;
+	private Composite linkContainer;
+	private Composite container;
+	private Button moreButton;
+	private String morePageId;
+	private int linkNumberLimit = 20;
+	private LinkHandler linkHandler;
+	class LinkHandler implements IHyperlinkListener {
+		public void linkActivated(HyperlinkEvent e) {
+			doLinkActivated((Hyperlink) e.widget);
+		}
+		public void linkEntered(HyperlinkEvent e) {
+			doEnter((Hyperlink) e.widget);
+		}
+		public void linkExited(HyperlinkEvent e) {
+			doExit((Hyperlink) e.widget);
+		}
+	}
+	/**
+	 * @param page
+	 * @param parent
+	 * @param style
+	 */
+	public LinkSection(PDEFormPage page, Composite parent, int style) {
+		super(page, parent, style);
+		FormToolkit toolkit = page.getManagedForm().getToolkit();
+		linkHandler = new LinkHandler();
+		createClient(getSection(), toolkit);
+	}
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.pde.internal.ui.neweditor.PDESection#createClient(org.eclipse.ui.forms.widgets.Section,
+	 *      org.eclipse.ui.forms.widgets.FormToolkit)
+	 */
+	protected void createClient(Section section, FormToolkit toolkit) {
+		container = toolkit.createComposite(section);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		container.setLayout(layout);
+		section.setClient(container);
+		linkContainer = toolkit.createComposite(container);
+		linkContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+		GridLayout linkLayout = new GridLayout();
+		linkLayout.marginWidth = 0;
+		linkLayout.marginHeight = 0;
+		linkLayout.verticalSpacing = 0;
+		linkContainer.setLayout(linkLayout);
+	}
+	private void createMoreButton() {
+		moreButton = getManagedForm().getToolkit().createButton(container, "More...", //$NON-NLS-1$
+				SWT.PUSH);
+		moreButton.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent e) {
+				BusyIndicator.showWhile(getSection().getDisplay(),
+						new Runnable() {
+							public void run() {
+								getPage().getEditor().setActivePage(morePageId);
+							}
+						});
+			}
+		});
+		moreButton
+				.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
+	}
+	public void add(Object[] links) {
+		for (int i = 0; i < links.length; i++) {
+			createLink(links[i]);
+		}
+		updateMoreState(linkContainer.getChildren().length > linkNumberLimit);
+		reflow();
+	}
+	public void remove(Object[] links) {
+		for (int i = 0; i < links.length; i++) {
+			disposeLink(links[i]);
+		}
+		updateMoreState(linkContainer.getChildren().length > linkNumberLimit);
+		reflow();
+	}
+	private void disposeLink(Object obj) {
+		Hyperlink link = find(obj);
+		if (link != null)
+			link.dispose();
+	}
+	private Hyperlink find(Object object) {
+		Control[] children = linkContainer.getChildren();
+		for (int i = 0; i < children.length; i++) {
+			Control child = children[i];
+			if (child.getData().equals(object))
+				return (Hyperlink) child;
+		}
+		return null;
+	}
+	public void update(Object[] links) {
+		for (int i = 0; i < links.length; i++) {
+			update(links[i]);
+		}
+		reflow();
+	}
+	private void update(Object object) {
+		Hyperlink link = find(object);
+		if (link != null)
+			update(link, object);
+	}
+	private void update(Hyperlink hyperlink, Object object) {
+		String text = labelProvider != null
+				? labelProvider.getText(object)
+				: object.toString();
+		Image image = labelProvider != null
+				? labelProvider.getImage(object)
+				: null;
+		String tooltip = labelProvider != null ? labelProvider
+				.getToolTipText(object) : text;
+		hyperlink.setText(text);
+		hyperlink.setToolTipText(tooltip);
+		if (hyperlink instanceof ImageHyperlink)
+			((ImageHyperlink) hyperlink).setImage(image);
+		reflow();
+	}
+	public void refresh() {
+		// dispose old links
+		Control[] children = linkContainer.getChildren();
+		for (int i = 0; i < children.length; i++) {
+			children[i].dispose();
+		}
+		createLinks();
+		reflow();
+	}
+	private void reflow() {
+		linkContainer.layout();
+		container.layout();
+		getManagedForm().reflow(true);
+	}
+	private void createLinks() {
+		if (contentProvider == null)
+			return;
+		Object[] objects = contentProvider.getElements(getManagedForm().getInput());
+		for (int i = 0; i < objects.length; i++) {
+			if (i == linkNumberLimit)
+				break;
+			createLink(objects[i]);
+		}
+		if (objects.length > linkNumberLimit)
+			getManagedForm().getToolkit().createLabel(linkContainer, "...", SWT.NULL); //$NON-NLS-1$
+		updateMoreState(objects.length > linkNumberLimit);
+	}
+	private void updateMoreState(boolean needMore) {
+		if (needMore && moreButton == null) {
+			createMoreButton();
+		}
+		else if (!needMore && moreButton != null) {
+			moreButton.dispose();
+			moreButton = null;
+		}
+	}
+	private void createLink(Object object) {
+		Image image = labelProvider != null
+				? labelProvider.getImage(object)
+				: null;
+		Hyperlink hyperlink;
+		if (image != null) {
+			hyperlink = getManagedForm().getToolkit().createImageHyperlink(
+					linkContainer, SWT.NULL);
+			((ImageHyperlink) hyperlink).setImage(image);
+		} else
+			hyperlink = getManagedForm().getToolkit().createHyperlink(linkContainer,
+					null, SWT.NULL);
+		update(hyperlink, object);
+		hyperlink.setData(object);
+		hyperlink.addHyperlinkListener(linkHandler);
+	}
+	private void doEnter(Hyperlink link) {
+		String statusText = labelProvider != null ? labelProvider
+				.getStatusText(link.getData()) : link.getText();
+		getPage().getEditorSite().getActionBars().getStatusLineManager()
+				.setMessage(statusText);
+	}
+	private void doExit(Hyperlink link) {
+		getPage().getEditorSite().getActionBars().getStatusLineManager()
+				.setMessage(null);
+	}
+	protected void doLinkActivated(Hyperlink link) {
+		Object object = link.getData();
+		getPage().getEditor().setActivePage(morePageId, object);
+	}
+	public void setMorePageId(String id) {
+		this.morePageId = id;
+	}
+	public void setLinkNumberLimit(int limit) {
+		this.linkNumberLimit = limit;
+	}
+	public void setContentProvider(IStructuredContentProvider contentProvider) {
+		this.contentProvider = contentProvider;
+	}
+	public void setLabelProvider(ILinkLabelProvider provider) {
+		this.labelProvider = provider;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelDataTransfer.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelDataTransfer.java
new file mode 100755
index 0000000..74cc988
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelDataTransfer.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+
+import org.eclipse.swt.dnd.*;
+
+/**
+ * @version 	1.0
+ * @author
+ */
+public class ModelDataTransfer extends ByteArrayTransfer {
+	/**
+	 * Singleton instance.
+	 */
+	private static final ModelDataTransfer instance =
+		new ModelDataTransfer();
+	// Create a unique ID to make sure that different Eclipse
+	// applications use different "types" of <code>ModelDataTransfer</code>
+	
+	public static final String TYPE_PREFIX = "pde-model-transfer-format"; //$NON-NLS-1$
+	private static final String TYPE_NAME =
+		TYPE_PREFIX + ":" //$NON-NLS-1$
+			+ System.currentTimeMillis()
+			+ ":" //$NON-NLS-1$
+			+ instance.hashCode();
+
+	private static final int TYPEID = registerType(TYPE_NAME);
+	
+	public static ModelDataTransfer getInstance() {
+		return instance;
+	}
+
+	/**
+	 * Constructor for ModelDataTransfer.
+	 */
+	public ModelDataTransfer() {
+		super();
+	}
+
+	/* (non-Javadoc)
+	 * Method declared on Transfer.
+	 */
+	protected int[] getTypeIds() {
+		return new int[] { TYPEID };
+	}
+	/* (non-Javadoc)
+	 * Returns the type names.
+	 *
+	 * @return the list of type names
+	 */
+	protected String[] getTypeNames() {
+		return new String[] { TYPE_NAME };
+	}
+	/* (non-Javadoc)
+		* Method declared on Transfer.
+		*/
+	protected void javaToNative(Object data, TransferData transferData) {
+		if (!(data instanceof Object[])) {
+			return;
+		}
+		Object[] objects = (Object[]) data;
+		int count = objects.length;
+		
+		try {
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			ObjectOutputStream objectOut = new ObjectOutputStream(out);
+
+			//write the number of resources
+			objectOut.writeInt(count);
+
+			//write each object
+			for (int i = 0; i < objects.length; i++) {
+				objectOut.writeObject(objects[i]);
+			}
+
+			//cleanup
+			objectOut.close();
+			out.close();
+			byte[] bytes = out.toByteArray();
+			super.javaToNative(bytes, transferData);
+		} catch (IOException e) {
+			//it's best to send nothing if there were problems
+			System.out.println(e);
+		}
+			
+	}
+	/* (non-Javadoc)
+	 * Method declared on Transfer.
+	 */
+	protected Object nativeToJava(TransferData transferData) {
+		byte[] bytes = (byte[]) super.nativeToJava(transferData);
+		if (bytes == null)
+			return null;
+		try {
+			ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
+
+			int count = in.readInt();
+			Object[] objects = new Object[count];
+			for (int i = 0; i < count; i++) {
+				objects[i] = in.readObject();
+			}
+			in.close();
+			return objects;
+		} catch (ClassNotFoundException e) {
+			return null;
+		} catch (IOException e) {
+			return null;
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelUndoManager.java
new file mode 100755
index 0000000..8db3fb0
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ModelUndoManager.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.util.*;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.pde.core.*;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.ui.forms.editor.IFormPage;
+
+/**
+ * @version 	1.0
+ * @author
+ */
+public abstract class ModelUndoManager
+	implements IModelUndoManager, IModelChangedListener {
+	private boolean ignoreChanges;
+	private List operations;
+	private int undoLevelLimit = 10;
+	private int cursor = -1;
+	private IAction undoAction;
+	private IAction redoAction;
+	private PDEFormEditor editor;
+	
+	public ModelUndoManager(PDEFormEditor editor) {
+		this.editor = editor;
+		operations = new Vector();
+	}
+
+	/*
+	 * @see IModelUndoManager#connect(IModelChangeProvider)
+	 */
+	public void connect(IModelChangeProvider provider) {
+		provider.addModelChangedListener(this);
+		if (operations==null) initialize();
+	}
+
+	/*
+	 * @see IModelUndoManager#disconnect(IModelChangeProvider)
+	 */
+	public void disconnect(IModelChangeProvider provider) {
+		provider.removeModelChangedListener(this);
+	}
+
+	private void initialize() {
+		operations = new Vector();
+		cursor = -1;
+		updateActions();
+	}
+
+	/*
+	 * @see IModelUndoManager#isUndoable()
+	 */
+	public boolean isUndoable() {
+		return cursor>=0;
+	}
+
+	/*
+	 * @see IModelUndoManager#isRedoable()
+	 */
+	public boolean isRedoable() {
+		if (operations == null) initialize();
+		return (cursor+1)<operations.size();
+	}
+
+	/*
+	 * @see IModelUndoManager#undo()
+	 */
+	public void undo() {
+		IModelChangedEvent op = getCurrentOperation();
+		if (op==null) return;
+		ignoreChanges = true;
+		openRelatedPage(op);
+		execute(op, true);
+		cursor --;
+		updateActions();
+		ignoreChanges = false;
+	}
+
+	/*
+	 * @see IModelUndoManager#redo()
+	 */
+	public void redo() {
+		cursor ++;
+		IModelChangedEvent op = getCurrentOperation();
+		if (op==null) return;
+		ignoreChanges = true;
+		openRelatedPage(op);
+		execute(op, false);
+		ignoreChanges = false;
+		updateActions();
+	}
+	
+	protected abstract String getPageId(Object object);
+	
+	protected abstract void execute(IModelChangedEvent op, boolean undo);
+	
+	private void openRelatedPage(IModelChangedEvent op) {
+		Object obj = op.getChangedObjects()[0];
+		String pageId = getPageId(obj);
+		if (pageId!=null) {
+			IFormPage cpage = editor.getActivePageInstance();
+			IFormPage newPage = editor.findPage(pageId);
+			if (cpage != newPage)
+				editor.setActivePage(newPage.getId());
+		}
+	}
+
+	/*
+	 * @see IModelChangedListener#modelChanged(IModelChangedEvent)
+	 */
+	public void modelChanged(IModelChangedEvent event) {
+		if (ignoreChanges)
+			return;
+			
+		if (event.getChangeType()==IModelChangedEvent.WORLD_CHANGED) {
+			initialize();
+			return;
+		}
+		addOperation(event);
+	}
+	
+	private IModelChangedEvent getCurrentOperation() {
+		if (cursor == -1 || cursor == operations.size()) return null;
+		return (IModelChangedEvent)operations.get(cursor);
+	}
+	
+	private IModelChangedEvent getNextOperation() {
+		int peekCursor = cursor+1;
+		if (peekCursor >= operations.size()) return null;
+		return (IModelChangedEvent)operations.get(peekCursor);
+	}
+	
+	private void addOperation(IModelChangedEvent operation) {
+		operations.add(operation);
+		int size = operations.size();
+		if (size > undoLevelLimit) {
+			int extra = size-undoLevelLimit;
+			// trim
+			for (int i=0; i<extra; i++) {
+				operations.remove(i);
+			}
+		}
+		cursor = operations.size() -1;
+		updateActions();
+	}
+	
+	public void setActions(IAction undoAction, IAction redoAction) {
+		this.undoAction = undoAction;
+		this.redoAction = redoAction;
+		updateActions();
+	}
+	
+	private void updateActions() {
+		if (undoAction!=null && redoAction!=null) {
+			undoAction.setEnabled(isUndoable());
+			undoAction.setText(getUndoText());
+			redoAction.setEnabled(isRedoable());
+			redoAction.setText(getRedoText());
+		}
+	}
+	
+	private String getUndoText() {
+		IModelChangedEvent op = getCurrentOperation();
+		if (op == null) {
+			return PDEUIMessages.UpdateManager_noUndo;
+		}
+		return NLS.bind(PDEUIMessages.UpdateManager_undo, getOperationText(op));	
+	}
+
+	private String getRedoText() {
+		IModelChangedEvent op = getNextOperation();
+		if (op == null) {
+			return PDEUIMessages.UpdateManager_noRedo;
+		}
+		return NLS.bind(PDEUIMessages.UpdateManager_redo, getOperationText(op));
+	}
+		
+	private String getOperationText(IModelChangedEvent op) {
+		String opText=""; //$NON-NLS-1$
+		switch (op.getChangeType()) {
+			case IModelChangedEvent.INSERT:
+			opText = PDEUIMessages.UpdateManager_op_add;
+			break;
+			case IModelChangedEvent.REMOVE:
+			opText = PDEUIMessages.UpdateManager_op_remove;
+			break;
+			case IModelChangedEvent.CHANGE:
+			opText = PDEUIMessages.UpdateManager_op_change;
+			break;
+		}
+		return opText;
+	}
+	
+	public void setUndoLevelLimit(int limit) {
+		this.undoLevelLimit = limit;
+	}
+
+	public void setIgnoreChanges(boolean ignore) {
+		this.ignoreChanges = ignore;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/MultiSourceEditor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/MultiSourceEditor.java
new file mode 100755
index 0000000..84bd288
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/MultiSourceEditor.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.forms.editor.IFormPage;
+
+public abstract class MultiSourceEditor extends PDEFormEditor {
+	protected void addSourcePage(String contextId) {
+		InputContext context = inputContextManager.findContext(contextId);
+		if (context == null)
+			return;
+		PDESourcePage sourcePage;
+		// Don't duplicate
+		if (findPage(contextId)!=null) return;
+		sourcePage = createSourcePage(this, contextId, context.getInput().getName(), context.getId());
+		sourcePage.setInputContext(context);
+		try {
+			addPage(sourcePage, context.getInput());
+		} catch (PartInitException e) {
+			PDEPlugin.logException(e);
+		}
+	}
+	
+	protected void removePage(String pageId) {
+		IFormPage page = findPage(pageId);
+		if (page == null)
+			return;
+		if (page.isDirty()) {
+			// need to ask the user about this
+		} else {
+			removePage(page.getIndex());
+			if (!page.isEditor())
+				page.dispose();
+		}
+	}
+	
+	protected PDESourcePage createSourcePage(PDEFormEditor editor, String title, String name, String contextId) {
+		return new GenericSourcePage(editor, title, name);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/NullUndoManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/NullUndoManager.java
new file mode 100644
index 0000000..0047549
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/NullUndoManager.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.pde.core.IModelChangeProvider;
+
+/**
+ * @version 	1.0
+ * @author
+ */
+public class NullUndoManager implements IModelUndoManager {
+
+	/*
+	 * @see IModelUndoManager#connect(IModelChangeProvider)
+	 */
+	public void connect(IModelChangeProvider provider) {
+	}
+
+	/*
+	 * @see IModelUndoManager#disconnect(IModelChangeProvider)
+	 */
+	public void disconnect(IModelChangeProvider provider) {
+	}
+
+	/*
+	 * @see IModelUndoManager#isUndoable()
+	 */
+	public boolean isUndoable() {
+		return false;
+	}
+
+	/*
+	 * @see IModelUndoManager#isRedoable()
+	 */
+	public boolean isRedoable() {
+		return false;
+	}
+
+	/*
+	 * @see IModelUndoManager#undo()
+	 */
+	public void undo() {
+	}
+
+	/*
+	 * @see IModelUndoManager#redo()
+	 */
+	public void redo() {
+	}
+
+	/*
+	 * @see IModelUndoManager#setUndoLevelLimit(int)
+	 */
+	public void setUndoLevelLimit(int limit) {
+	}
+
+	/*
+	 * @see IModelUndoManager#setIgnoreChanges(boolean)
+	 */
+	public void setIgnoreChanges(boolean ignore) {
+	}
+	
+	public void setActions(IAction undoAction, IAction redoAction) {
+		if (undoAction!=null) undoAction.setEnabled(false);
+		if (redoAction!=null) redoAction.setEnabled(false);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetails.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetails.java
new file mode 100755
index 0000000..637f5b6
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetails.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public abstract class PDEDetails extends AbstractFormPart implements IDetailsPage, IContextPart {
+
+	public PDEDetails() {
+	}
+	
+	public boolean canPaste(Clipboard clipboard) {
+		return true;
+	}
+	
+	public boolean doGlobalAction(String actionId) {
+		return false;
+	}
+	
+	protected void markDetailsPart(Control control) {
+		control.setData("part", this); //$NON-NLS-1$
+	}
+	
+	protected void createSpacer(FormToolkit toolkit, Composite parent, int span) {
+		Label spacer = toolkit.createLabel(parent, ""); //$NON-NLS-1$
+		GridData gd = new GridData();
+		gd.horizontalSpan = span;
+		spacer.setLayoutData(gd);
+	}
+	public void cancelEdit() {
+		super.refresh();
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetailsSections.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetailsSections.java
new file mode 100644
index 0000000..824cdac
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEDetailsSections.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.IFormPart;
+
+/**
+ * Wrapper for PDESections, implemens IDetailsPage for use in MasterDetailsBlock
+ */
+public abstract class PDEDetailsSections extends PDEDetails {
+	private PDESection sections[];
+
+	protected abstract PDESection[] createSections(PDEFormPage page,
+			Composite parent);
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.forms.IDetailsPage#createContents(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createContents(Composite parent) {
+		sections = createSections(getPage(), parent);
+		GridLayout layout = new GridLayout();
+		layout.verticalSpacing = 30;
+		parent.setLayout(layout);
+		for (int i = 0; i < sections.length; i++) {
+			getManagedForm().addPart(sections[i]);
+		}
+	}
+
+	public void dispose() {
+		for (int i = 0; i < sections.length; i++) {
+			sections[i].dispose();
+		}
+	}
+
+	public void fireSaveNeeded() {
+		markDirty();
+		getPage().getPDEEditor().fireSaveNeeded(getContextId(), false);
+	}
+
+	public abstract String getContextId();
+
+	public PDEFormPage getPage() {
+		return (PDEFormPage) getManagedForm().getContainer();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.forms.AbstractFormPart#isDirty()
+	 */
+	public boolean isDirty() {
+		for (int i = 0; i < sections.length; i++) {
+			if (sections[i].isDirty()) {
+				return true;
+			}
+		}
+		return super.isDirty();
+	}
+
+	public boolean isEditable() {
+		return getPage().getPDEEditor().getAggregateModel().isEditable();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.forms.AbstractFormPart#isStale()
+	 */
+	public boolean isStale() {
+		for (int i = 0; i < sections.length; i++) {
+			if (sections[i].isStale()) {
+				return true;
+			}
+		}
+		return super.isStale();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.pde.core.IModelChangedListener#modelChanged(org.eclipse.pde.core.IModelChangedEvent)
+	 */
+	public void modelChanged(IModelChangedEvent event) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.forms.IDetailsPage#inputChanged(org.eclipse.jface.viewers.IStructuredSelection)
+	 */
+	public void selectionChanged(IFormPart masterPart, ISelection selection) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.forms.IDetailsPage#setFocus()
+	 */
+	public void setFocus() {
+		if (sections.length > 0) {
+			sections[0].setFocus();
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditor.java
new file mode 100755
index 0000000..28bc311
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditor.java
@@ -0,0 +1,757 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.context.IInputContextListener;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContextManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IWritable;
+import org.eclipse.pde.internal.ui.IPDEUIConstants;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.search.ui.text.ISearchEditorAccess;
+import org.eclipse.search.ui.text.Match;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IEditorActionBarContributor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.editors.text.ILocationProvider;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.part.MultiPageEditorPart;
+import org.eclipse.ui.part.MultiPageEditorSite;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+/**
+ * A simple multi-page form editor that uses Eclipse Forms support. Example
+ * plug-in is configured to create one instance of form colors that is shared
+ * between multiple editor instances.
+ */
+public abstract class PDEFormEditor extends FormEditor
+		implements
+			IInputContextListener,
+			IGotoMarker, ISearchEditorAccess {
+	/**
+	 * Updates the OutlinePage selection.
+	 * 
+	 * @since 3.0
+	 */
+	private class PDEFormEditorChangeListener implements
+			ISelectionChangedListener {
+
+		/**
+		 * Installs this selection changed listener with the given selection
+		 * provider. If the selection provider is a post selection provider,
+		 * post selection changed events are the preferred choice, otherwise
+		 * normal selection changed events are requested.
+		 * 
+		 * @param selectionProvider
+		 */
+		public void install(ISelectionProvider selectionProvider) {
+			if (selectionProvider == null) {
+				return;
+			}
+
+			if (selectionProvider instanceof IPostSelectionProvider) {
+				IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+				provider.addPostSelectionChangedListener(this);
+			} else {
+				selectionProvider.addSelectionChangedListener(this);
+			}
+		}
+
+		/*
+		 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+		 */
+		public void selectionChanged(SelectionChangedEvent event) {
+			if (PDEPlugin.getDefault().getPreferenceStore().getBoolean(
+					"ToggleLinkWithEditorAction.isChecked")) //$NON-NLS-1$
+				if (getFormOutline() != null) {
+					getFormOutline().setSelection(event.getSelection());
+				}
+		}
+
+		/**
+		 * Removes this selection changed listener from the given selection
+		 * provider.
+		 * 
+		 * @param selectionProviderstyle
+		 */
+		public void uninstall(ISelectionProvider selectionProvider) {
+			if (selectionProvider == null) {
+				return;
+			}
+
+			if (selectionProvider instanceof IPostSelectionProvider) {
+				IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+				provider.removePostSelectionChangedListener(this);
+			} else {
+				selectionProvider.removeSelectionChangedListener(this);
+			}
+		}
+
+	}
+
+	/**
+	 * The editor selection changed listener.
+	 * 
+	 * @since 3.0
+	 */
+	private PDEFormEditorChangeListener fEditorSelectionChangedListener;
+	private Clipboard clipboard;
+	private Menu contextMenu;
+	protected InputContextManager inputContextManager;
+	private ISortableContentOutlinePage formOutline;
+	private PDEMultiPagePropertySheet propertySheet;
+	private PDEMultiPageContentOutline contentOutline;
+	private String lastActivePageId;
+	private boolean lastDirtyState;
+
+	private static class PDEMultiPageEditorSite extends MultiPageEditorSite {
+		public PDEMultiPageEditorSite(MultiPageEditorPart multiPageEditor,
+				IEditorPart editor) {
+			super(multiPageEditor, editor);
+		}
+		public IEditorActionBarContributor getActionBarContributor() {
+			PDEFormEditor editor = (PDEFormEditor) getMultiPageEditor();
+			PDEFormEditorContributor contributor = editor.getContributor();
+			return contributor.getSourceContributor();
+		}
+		
+		public IWorkbenchPart getPart() {
+			return getMultiPageEditor();
+		}
+	}
+	/**
+	 *  
+	 */
+	public PDEFormEditor() {
+		PDEPlugin.getDefault().getLabelProvider().connect(this);
+		inputContextManager = createInputContextManager();
+	}
+	/**
+	 * We must override nested site creation so that we properly pass the source
+	 * editor contributor when asked.
+	 */
+	protected IEditorSite createSite(IEditorPart editor) {
+		return new PDEMultiPageEditorSite(this, editor);
+	}
+	public IProject getCommonProject() {
+		return inputContextManager.getCommonProject();
+	}
+	public IBaseModel getAggregateModel() {
+		if (inputContextManager != null)
+			return inputContextManager.getAggregateModel();
+		return null;
+	}
+	protected abstract InputContextManager createInputContextManager();
+	/**
+	 * Tests whether this editor has a context with a provided id. The test can
+	 * be used to check whether to add certain pages.
+	 * 
+	 * @param contextId
+	 * @return <code>true</code> if provided context is present,
+	 *         <code>false</code> otherwise.
+	 */
+	public boolean hasInputContext(String contextId) {
+		return inputContextManager.hasContext(contextId);
+	}
+	public InputContextManager getContextManager() {
+		return inputContextManager;
+	}
+	protected void createInputContexts(InputContextManager contextManager) {
+		IEditorInput input = getEditorInput();
+		if (input instanceof IFileEditorInput) {
+			// resource - find the project
+			createResourceContexts(contextManager, (IFileEditorInput) input);
+		} else if (input instanceof SystemFileEditorInput) {
+			// system file - find the file system folder
+			createSystemFileContexts(contextManager,
+					(SystemFileEditorInput) input);
+		} else if (input instanceof IStorageEditorInput) {
+			createStorageContexts(contextManager, (IStorageEditorInput) input);
+		} else if (input instanceof ILocationProvider) {
+			IPath path = ((ILocationProvider) input).getPath(input);
+			File file = path.toFile();
+			SystemFileEditorInput sinput = new SystemFileEditorInput(file);
+			createSystemFileContexts(contextManager, sinput);
+		}
+	}
+	protected abstract void createResourceContexts(
+			InputContextManager contexts, IFileEditorInput input);
+	protected abstract void createSystemFileContexts(
+			InputContextManager contexts, SystemFileEditorInput input);
+	protected abstract void createStorageContexts(InputContextManager contexts,
+			IStorageEditorInput input);
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.forms.editor.FormEditor#createToolkit(org.eclipse.swt.widgets.Display)
+	 */
+	protected FormToolkit createToolkit(Display display) {
+		// Create a toolkit that shares colors between editors.
+		return new FormToolkit(PDEPlugin.getDefault().getFormColors(display));
+	}
+	/*
+	 * When subclassed, don't forget to call 'super'
+	 */
+	protected void createPages() {
+		clipboard = new Clipboard(getContainer().getDisplay());
+		MenuManager manager = new MenuManager();
+		IMenuListener listener = new IMenuListener() {
+			public void menuAboutToShow(IMenuManager manager) {
+				contextMenuAboutToShow(manager);
+			}
+		};
+		manager.setRemoveAllWhenShown(true);
+		manager.addMenuListener(listener);
+		contextMenu = manager.createContextMenu(getContainer());
+		getContainer().setMenu(contextMenu);
+		createInputContexts(inputContextManager);
+		super.createPages();
+		inputContextManager.addInputContextListener(this);
+		String pageToShow = computeInitialPageId();
+		if (pageToShow != null)
+			setActivePage(pageToShow);
+		updateTitle();
+	}
+	protected void pageChange(int newPageIndex) {
+		super.pageChange(newPageIndex);
+		IFormPage page = getActivePageInstance();
+		updateContentOutline(page);
+		updatePropertySheet(page);
+		if (page!=null)
+			lastActivePageId = page.getId();
+	}
+	public Clipboard getClipboard() {
+		return clipboard;
+	}
+	protected void contextMenuAboutToShow(IMenuManager manager) {
+		PDEFormEditorContributor contributor = getContributor();
+		IFormPage page = getActivePageInstance();
+		if (page instanceof PDEFormPage)
+			((PDEFormPage) page).contextMenuAboutToShow(manager);
+		if (contributor != null)
+			contributor.contextMenuAboutToShow(manager);
+	}
+	public PDEFormEditorContributor getContributor() {
+		return (PDEFormEditorContributor) getEditorSite()
+				.getActionBarContributor();
+	}
+	protected String computeInitialPageId() {
+		String firstPageId = null;
+		String storedFirstPageId = loadDefaultPage();
+		if (storedFirstPageId != null)
+			firstPageId = storedFirstPageId;
+		// Regardless what is the stored value,
+		// use source page if model is not valid
+		String invalidContextId = getFirstInvalidContextId();
+		if (invalidContextId != null)
+			return invalidContextId;
+		return firstPageId;
+	}
+
+	private String getFirstInvalidContextId() {
+		InputContext[] invalidContexts = inputContextManager
+				.getInvalidContexts();
+		if (invalidContexts.length == 0)
+			return null;
+		// If primary context is among the invalid ones, return that.
+		for (int i = 0; i < invalidContexts.length; i++) {
+			if (invalidContexts[i].isPrimary())
+				return invalidContexts[i].getId();
+		}
+		// Return the first one
+		return invalidContexts[0].getId();
+	}
+
+	public String getTitle() {
+		if (inputContextManager == null)
+			return super.getTitle();
+		InputContext context = inputContextManager.getPrimaryContext();
+		if (context == null)
+			return super.getTitle();
+		return context.getInput().getName();
+	}
+	
+	public void updateTitle() {
+		firePropertyChange(IWorkbenchPart.PROP_TITLE);
+	}
+
+	public String getTitleProperty() {
+		return ""; //$NON-NLS-1$
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	public void doSave(IProgressMonitor monitor) {
+		commitFormPages(true);
+		inputContextManager.save(monitor);
+		editorDirtyStateChanged();
+	}
+	public void doRevert() {
+		IFormPage currentPage = getActivePageInstance();
+		if (currentPage != null && currentPage instanceof PDEFormPage)
+			((PDEFormPage) currentPage).cancelEdit();
+		IFormPage[] pages = getPages();
+		for (int i = 0; i < pages.length; i++) {
+			if (pages[i] instanceof PDESourcePage) {
+				((PDESourcePage) pages[i]).doRevertToSaved();
+			}
+		}
+		editorDirtyStateChanged();
+	}
+	public void doRevert(IEditorInput input) {
+		IFormPage currentPage = getActivePageInstance();
+		if (currentPage != null && currentPage instanceof PDEFormPage)
+			((PDEFormPage) currentPage).cancelEdit();
+		InputContext context = inputContextManager.getContext(input);
+		IFormPage page = findPage(context.getId());
+		if (page!=null && page instanceof PDESourcePage) {
+			PDESourcePage spage = (PDESourcePage) page;
+		    spage.doRevertToSaved();
+		}
+		editorDirtyStateChanged();
+	}
+	private void commitFormPages(boolean onSave) {
+		IFormPage[] pages = getPages();
+		for (int i = 0; i < pages.length; i++) {
+			IFormPage page = pages[i];
+			IManagedForm mform = page.getManagedForm();
+			if (mform != null && mform.isDirty())
+				mform.commit(true);
+		}
+	}
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#doSaveAs()
+	 */
+	public void doSaveAs() {
+	}
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
+	 */
+	public boolean isSaveAsAllowed() {
+		return false;
+	}
+
+	private void storeDefaultPage() {
+		IEditorInput input = getEditorInput();
+		String pageId = lastActivePageId;
+		if (pageId == null)
+			return;
+		if (input instanceof IFileEditorInput) {
+			IFile file = ((IFileEditorInput) input).getFile();
+			if (file != null) {
+				//set the settings on the resouce
+				try {
+					file
+							.setPersistentProperty(
+									IPDEUIConstants.DEFAULT_EDITOR_PAGE_KEY_NEW,
+									pageId);
+				} catch (CoreException e) {
+				}
+			}
+		} else if (input instanceof SystemFileEditorInput) {
+			File file = (File) ((SystemFileEditorInput) input)
+					.getAdapter(File.class);
+			if (file == null)
+				return;
+			IDialogSettings section = getSettingsSection();
+			section.put(file.getPath(), pageId);
+		}
+	}
+	private String loadDefaultPage() {
+		IEditorInput input = getEditorInput();
+		if (input instanceof IFileEditorInput) {
+			// load the setting from the resource
+			IFile file = ((IFileEditorInput) input).getFile();
+			try {
+				return file
+						.getPersistentProperty(IPDEUIConstants.DEFAULT_EDITOR_PAGE_KEY_NEW);
+			} catch (CoreException e) {
+				return null;
+			}
+		} else if (input instanceof SystemFileEditorInput) {
+			File file = (File) ((SystemFileEditorInput) input)
+					.getAdapter(File.class);
+			if (file == null)
+				return null;
+			IDialogSettings section = getSettingsSection();
+			String key = file.getPath();
+			return section.get(key);
+		}
+		return null;
+	}
+	public void dispose() {
+		storeDefaultPage();
+		if (fEditorSelectionChangedListener != null)  {
+			fEditorSelectionChangedListener.uninstall(getSite().getSelectionProvider());
+			fEditorSelectionChangedListener= null;
+		}
+		//setSelection(new StructuredSelection());
+		PDEPlugin.getDefault().getLabelProvider().disconnect(this);
+		if (clipboard != null) {
+			clipboard.dispose();
+			clipboard = null;
+		}
+		super.dispose();
+		inputContextManager.dispose();
+		inputContextManager = null;
+	}
+	public boolean isDirty() {
+		lastDirtyState = computeDirtyState();
+		return lastDirtyState;
+	}
+	
+	private boolean computeDirtyState() {
+		IFormPage page = getActivePageInstance();
+		if ((page != null && page.isDirty())
+				|| (inputContextManager != null && inputContextManager
+						.isDirty()))
+			return true;
+		return super.isDirty();
+	}
+	
+	public boolean getLastDirtyState() {
+		return lastDirtyState;
+	}
+
+	public void fireSaveNeeded(String contextId, boolean notify) {
+		if (contextId == null)
+			return;
+		InputContext context = inputContextManager.findContext(contextId);
+		if (context != null)
+			fireSaveNeeded(context.getInput(), notify);
+	}
+	public void fireSaveNeeded(IEditorInput input, boolean notify) {
+		if (notify)
+			editorDirtyStateChanged();
+		if (isDirty())
+			validateEdit(input);
+	}
+	public void editorDirtyStateChanged() {
+		super.editorDirtyStateChanged();
+		PDEFormEditorContributor contributor = getContributor();
+		if (contributor != null)
+			contributor.updateActions();
+	}
+	private void validateEdit(IEditorInput input) {
+		final InputContext context = inputContextManager.getContext(input);
+		if (!context.validateEdit()) {
+			getSite().getShell().getDisplay().asyncExec(new Runnable() {
+				public void run() {
+					doRevert(context.getInput());
+					context.setValidated(false);
+				}
+			});
+		}
+	}
+	private IDialogSettings getSettingsSection() {
+		// store the setting in dialog settings
+		IDialogSettings root = PDEPlugin.getDefault().getDialogSettings();
+		IDialogSettings section = root.getSection("multi-page-editor"); //$NON-NLS-1$
+		if (section == null)
+			section = root.addNewSection("multi-page-editor"); //$NON-NLS-1$
+		return section;
+	}
+	public void gotoMarker(IMarker marker) {
+		IResource resource = marker.getResource();
+		InputContext context = inputContextManager.findContext(resource);
+		if (context == null)
+			return;
+		IFormPage page = getActivePageInstance();
+		if (!context.getId().equals(page.getId()))
+			page = setActivePage(context.getId());
+		IDE.gotoMarker(page, marker);
+	}
+	
+	public void openToSourcePage(Object object, int offset, int length) {
+		InputContext context = getInputContext(object);
+		if (context != null) {
+			PDESourcePage page = (PDESourcePage)setActivePage(context.getId());
+			if (page != null)
+				page.selectAndReveal(offset, length);
+		}
+	}
+
+	public void setSelection(ISelection selection) {
+		getSite().getSelectionProvider().setSelection(selection);
+		getContributor().updateSelectableActions(selection);
+	}
+	public ISelection getSelection() {
+		return getSite().getSelectionProvider().getSelection();
+	}
+	public Object getAdapter(Class key) {
+		if (key.equals(IContentOutlinePage.class)) {
+			return getContentOutline();
+		}
+		if (key.equals(IPropertySheetPage.class)) {
+			return getPropertySheet();
+		}
+		if (key.equals(IGotoMarker.class)) {
+			return this;
+		}
+		if (key.equals(ISearchEditorAccess.class)) {
+			return this;
+		}
+		return super.getAdapter(key);
+	}
+	public Menu getContextMenu() {
+		return contextMenu;
+	}
+	public PDEMultiPageContentOutline getContentOutline() {
+		if (contentOutline == null || contentOutline.isDisposed()) {
+			contentOutline = new PDEMultiPageContentOutline(this);
+			updateContentOutline(getActivePageInstance());
+		}
+		return contentOutline;
+	}
+	public PDEMultiPagePropertySheet getPropertySheet() {
+		if (propertySheet == null || propertySheet.isDisposed()) {
+			propertySheet = new PDEMultiPagePropertySheet();
+			updatePropertySheet(getActivePageInstance());
+		}
+		return propertySheet;
+	}
+	/**
+	 * 
+	 * @return outline page or null
+	 */
+	protected ISortableContentOutlinePage getFormOutline() {
+		if (formOutline == null) {
+			formOutline = createContentOutline();
+			if (formOutline != null) {
+				fEditorSelectionChangedListener = new PDEFormEditorChangeListener();
+				fEditorSelectionChangedListener.install(getSite()
+						.getSelectionProvider());
+			}
+		}
+		return formOutline;
+	}
+	abstract protected ISortableContentOutlinePage createContentOutline();
+	
+	private void updateContentOutline(IFormPage page) {
+		if (contentOutline == null)
+			return;
+		ISortableContentOutlinePage outline = null;
+		if (page instanceof PDESourcePage) {
+			outline = ((PDESourcePage) page).getContentOutline();
+		} else {
+			outline = getFormOutline();
+			if (outline != null && outline instanceof FormOutlinePage)
+				((FormOutlinePage) outline).refresh();
+		}
+		contentOutline.setPageActive(outline);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.FormEditor#setActivePage(java.lang.String)
+	 */
+	public IFormPage setActivePage(String pageId) {
+		IFormPage page = super.setActivePage(pageId);
+		if (page != null)
+			updateContentOutline(page);
+		return page;
+	}
+	protected IPropertySheetPage getPropertySheet(PDEFormPage page) {
+		return page.getPropertySheetPage();
+	}
+	void updatePropertySheet(IFormPage page) {
+		if (propertySheet == null)
+			return;
+		if (page instanceof PDEFormPage) {
+			IPropertySheetPage propertySheetPage = getPropertySheet((PDEFormPage) page);
+			if (propertySheetPage != null) {
+				propertySheet.setPageActive(propertySheetPage);
+			}
+		} else
+			propertySheet.setDefaultPageActive();
+	}
+	/* package */IFormPage[] getPages() {
+		ArrayList formPages = new ArrayList();
+		for (int i = 0; i < pages.size(); i++) {
+			Object page = pages.get(i);
+			if (page instanceof IFormPage)
+				formPages.add(page);
+		}
+		return (IFormPage[]) formPages.toArray(new IFormPage[formPages.size()]);
+	}
+	protected void performGlobalAction(String id) {
+		// preserve selection
+		ISelection selection = getSelection();
+		boolean handled = ((PDEFormPage) getActivePageInstance())
+				.performGlobalAction(id);
+		if (!handled) {
+			IFormPage page = getActivePageInstance();
+			if (page instanceof PDEFormPage) {
+				if (id.equals(ActionFactory.UNDO.getId())) {
+					inputContextManager.undo();
+					return;
+				}
+				if (id.equals(ActionFactory.REDO.getId())) {
+					inputContextManager.redo();
+					return;
+				}
+				if (id.equals(ActionFactory.CUT.getId())
+						|| id.equals(ActionFactory.COPY.getId())) {
+					copyToClipboard(selection);
+					return;
+				}
+			}
+		}
+	}
+	private void copyToClipboard(ISelection selection) {
+		Object[] objects = null;
+		String textVersion = null;		
+		if (selection instanceof IStructuredSelection) {
+			IStructuredSelection ssel = (IStructuredSelection) selection;
+			if (ssel == null || ssel.size() == 0)
+				return;
+			objects = ssel.toArray();
+			StringWriter writer = new StringWriter();
+			PrintWriter pwriter = new PrintWriter(writer);
+			Class objClass = null;
+			for (int i = 0; i < objects.length; i++) {
+				Object obj = objects[i];
+				if (objClass == null)
+					objClass = obj.getClass();
+				else if (objClass.equals(obj.getClass()) == false)
+					return;
+				if (obj instanceof IWritable) {
+					((IWritable) obj).write("", pwriter); //$NON-NLS-1$
+				}
+			}
+			pwriter.flush();
+			textVersion = writer.toString();
+			try {
+				pwriter.close();
+				writer.close();
+			} catch (IOException e) {
+			}
+		} else if (selection instanceof ITextSelection) {
+			textVersion = ((ITextSelection) selection).getText();
+		}
+		if ((textVersion == null || textVersion.length() == 0) && objects == null)
+			return;
+		// set the clipboard contents
+		Object[]o = null;
+		Transfer[] t = null;
+		if (objects == null ) {
+			o = new Object[] {textVersion};
+			t = new Transfer[] {TextTransfer.getInstance()};
+		} else if (textVersion == null || textVersion.length() == 0) {
+			o = new Object[] {objects};
+			t = new Transfer[] {ModelDataTransfer.getInstance()};
+		} else {
+			o = new Object[] {objects, textVersion};
+			t = new Transfer[] {ModelDataTransfer.getInstance(), TextTransfer.getInstance()};
+		}
+		clipboard.setContents(o, t);
+	}
+	public boolean canPasteFromClipboard() {
+		IFormPage page = getActivePageInstance();
+		if (page instanceof PDEFormPage) {
+			return ((PDEFormPage) page).canPaste(getClipboard());
+		}
+		return false;
+	}
+	public boolean canCopy(ISelection selection) {
+		if (selection == null)
+			return false;
+		if (selection instanceof IStructuredSelection)
+			return !selection.isEmpty();
+		if (selection instanceof ITextSelection) {
+			ITextSelection textSelection = (ITextSelection) selection;
+			return textSelection.getLength() > 0;
+		}
+		return false;
+	}
+	void updateUndo(IAction undoAction, IAction redoAction) {
+		IModelUndoManager undoManager = inputContextManager.getUndoManager();
+		if (undoManager != null)
+			undoManager.setActions(undoAction, redoAction);
+	}
+	void synchronizeOutlinePage() {
+		if (getFormOutline() != null) {
+			getFormOutline().setSelection(getSelection());
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.search.ui.text.ISearchEditorAccess#getDocument(org.eclipse.search.ui.text.Match)
+	 */
+	public IDocument getDocument(Match match) {
+		InputContext context = getInputContext(match.getElement());
+		return context == null ? null : context.getDocumentProvider().getDocument(context.getInput());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.search.ui.text.ISearchEditorAccess#getAnnotationModel(org.eclipse.search.ui.text.Match)
+	 */
+	public IAnnotationModel getAnnotationModel(Match match) {
+		InputContext context = getInputContext(match.getElement());
+		return context == null ? null : context.getDocumentProvider().getAnnotationModel(context.getInput());
+	}
+	
+	protected abstract InputContext getInputContext(Object object);
+	
+	public int getOrientation() {
+		return SWT.LEFT_TO_RIGHT;
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditorContributor.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditorContributor.java
new file mode 100755
index 0000000..39f5455
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormEditorContributor.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import java.util.*;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.pde.core.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.ui.*;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.editors.text.TextEditorActionContributor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.ide.IDEActionFactory;
+import org.eclipse.ui.part.MultiPageEditorActionBarContributor;
+import org.eclipse.ui.texteditor.IUpdate;
+
+public class PDEFormEditorContributor
+		extends
+			MultiPageEditorActionBarContributor {
+	private SubActionBars sourceActionBars;
+	private PDEFormEditor editor;
+	private IFormPage page;
+	private SaveAction saveAction;
+	private RevertAction revertAction;
+	private ClipboardAction cutAction;
+	private ClipboardAction copyAction;
+	private ClipboardAction pasteAction;
+	private Hashtable globalActions = new Hashtable();
+	private TextEditorActionContributor sourceContributor;
+	class GlobalAction extends Action implements IUpdate {
+		private String id;
+		public GlobalAction(String id) {
+			this.id = id;
+		}
+		public void run() {
+			editor.performGlobalAction(id);
+			updateSelectableActions(editor.getSelection());
+		}
+		public void update() {
+			getActionBars().updateActionBars();
+		}
+	}
+	class ClipboardAction extends GlobalAction {
+		public ClipboardAction(String id) {
+			super(id);
+			setEnabled(false);
+		}
+		public void selectionChanged(ISelection selection) {
+		}
+		public boolean isEditable() {
+			if (editor == null)
+				return false;
+			IBaseModel model = editor.getAggregateModel();
+			if (model instanceof IEditable)
+				return ((IEditable) model).isEditable();
+			return false;
+		}
+	}
+	class CutAction extends ClipboardAction {
+		public CutAction() {
+			super(ActionFactory.CUT.getId());
+			setText(PDEUIMessages.EditorActions_cut);
+		}
+		public void selectionChanged(ISelection selection) {
+			setEnabled(isEditable() && editor.canCopy(selection));
+		}
+	}
+	class CopyAction extends ClipboardAction {
+		public CopyAction() {
+			super(ActionFactory.COPY.getId());
+			setText(PDEUIMessages.EditorActions_copy);
+		}
+		public void selectionChanged(ISelection selection) {
+			setEnabled(editor.canCopy(selection));
+		}
+	}
+	class PasteAction extends ClipboardAction {
+		public PasteAction() {
+			super(ActionFactory.PASTE.getId());
+			setText(PDEUIMessages.EditorActions_paste);
+			//selectionChanged(null);
+		}
+		public void selectionChanged(ISelection selection) {
+			setEnabled(isEditable() && editor.canPasteFromClipboard());
+		}
+	}
+	class SaveAction extends Action implements IUpdate {
+		public SaveAction() {
+		}
+		public void run() {
+			if (editor != null)
+				PDEPlugin.getActivePage().saveEditor(editor, false);
+		}
+		public void update() {
+			if (editor != null) {
+				setEnabled(editor.isDirty());
+			} else
+				setEnabled(false);
+		}
+	}
+	class RevertAction extends Action implements IUpdate {
+		public RevertAction() {
+		}
+		public void run() {
+			if (editor != null)
+				editor.doRevert();
+		}
+		public void update() {
+			if (editor != null) {
+				setEnabled(editor.isDirty());
+			} else
+				setEnabled(false);
+		}
+	}
+	public PDEFormEditorContributor(String menuName) {
+		sourceContributor = new TextEditorActionContributor();
+		makeActions();
+	}
+	
+	public IEditorActionBarContributor getSourceContributor() {
+		return sourceContributor;
+	}
+	private void addGlobalAction(String id) {
+		GlobalAction action = new GlobalAction(id);
+		addGlobalAction(id, action);
+	}
+	private void addGlobalAction(String id, Action action) {
+		globalActions.put(id, action);
+	}
+	public void addClipboardActions(IMenuManager mng) {
+		mng.add(cutAction);
+		mng.add(copyAction);
+		mng.add(pasteAction);
+		mng.add(new Separator());
+		mng.add(revertAction);
+	}
+	public void contextMenuAboutToShow(IMenuManager mng) {
+		contextMenuAboutToShow(mng, true);
+	}
+	public void contextMenuAboutToShow(IMenuManager mng, boolean addClipboard) {
+		if (editor != null)
+			updateSelectableActions(editor.getSelection());
+		if (addClipboard) {
+			addClipboardActions(mng);
+		}
+		mng.add(saveAction);
+	}
+	public void contributeToMenu(IMenuManager mm) {
+	}
+	public void contributeToStatusLine(IStatusLineManager slm) {
+	}
+	public void contributeToToolBar(IToolBarManager tbm) {
+	}
+	public void contributeToCoolBar(ICoolBarManager cbm) {
+	}
+	public void dispose() {
+		sourceContributor.dispose();
+		sourceActionBars.dispose();
+		super.dispose();
+	}
+	public void init(IActionBars bars) {
+		super.init(bars);
+		sourceActionBars = new SubActionBars(bars);
+		sourceContributor.init(sourceActionBars);
+	}
+	
+	public PDEFormEditor getEditor() {
+		return editor;
+	}
+	public IAction getGlobalAction(String id) {
+		return (IAction) globalActions.get(id);
+	}
+	public IAction getSaveAction() {
+		return saveAction;
+	}
+	public IAction getRevertAction() {
+		return revertAction;
+	}
+	public IStatusLineManager getStatusLineManager() {
+		return getActionBars().getStatusLineManager();
+	}
+	protected void makeActions() {
+		// clipboard actions
+		cutAction = new CutAction();
+		copyAction = new CopyAction();
+		pasteAction = new PasteAction();
+		addGlobalAction(ActionFactory.CUT.getId(), cutAction);
+		addGlobalAction(ActionFactory.COPY.getId(), copyAction);
+		addGlobalAction(ActionFactory.PASTE.getId(), pasteAction);
+		addGlobalAction(ActionFactory.DELETE.getId());
+		// undo/redo
+		addGlobalAction(ActionFactory.UNDO.getId());
+		addGlobalAction(ActionFactory.REDO.getId());
+		// select/find
+		addGlobalAction(ActionFactory.SELECT_ALL.getId());
+		addGlobalAction(ActionFactory.FIND.getId());
+		// bookmark
+		addGlobalAction(IDEActionFactory.BOOKMARK.getId());
+		// save/revert
+		saveAction = new SaveAction();
+		saveAction.setText(PDEUIMessages.EditorActions_save);
+		revertAction = new RevertAction();
+		revertAction.setText(PDEUIMessages.EditorActions_revert);
+	}
+	public void setActiveEditor(IEditorPart targetEditor) {
+		//if (editor != null)
+		//	editor.updateUndo(null, null);
+		if (targetEditor instanceof PDESourcePage) {
+			// Fixing the 'goto line' problem -
+			// the action is thinking that source page
+			// is a standalone editor and tries to activate it
+			// #19361
+			PDESourcePage page = (PDESourcePage) targetEditor;
+			PDEPlugin.getActivePage().activate(page.getEditor());
+			return;
+		}
+		if (targetEditor instanceof PDEFormEditor)
+			this.editor = (PDEFormEditor) targetEditor;
+		else
+			return;
+		editor.updateUndo(getGlobalAction(ActionFactory.UNDO.getId()),
+				getGlobalAction(ActionFactory.REDO.getId()));
+		IEditorPart page = editor.getActiveEditor();
+		setActivePage(page);
+		updateSelectableActions(editor.getSelection());
+	}
+	public void setActivePage(IEditorPart newEditor) {
+		if (editor == null)
+			return;
+		IFormPage oldPage = page;
+		IFormPage newPage = editor.getActivePageInstance();
+		this.page = newPage;
+		if (newPage == null)
+			return;
+		updateActions();
+		if (oldPage != null && oldPage.isEditor() == false
+				&& newPage.isEditor() == false) {
+			getActionBars().updateActionBars();
+			return;
+		}
+		PDESourcePage sourcePage = null;
+		if (newPage instanceof PDESourcePage)
+			sourcePage = (PDESourcePage) newPage;
+		if (sourcePage != null && sourcePage.equals(oldPage))
+			return;
+		sourceContributor.setActiveEditor(sourcePage);
+		setSourceActionBarsActive(sourcePage != null);
+	}
+	private void setSourceActionBarsActive(boolean active) {
+		IActionBars rootBars = getActionBars();
+		rootBars.clearGlobalActionHandlers();
+		//PlatformUI.getWorkbench().getCommandSupport().removeHandlerSubmissions(new ArrayList());
+		rootBars.updateActionBars();
+		if (active) {
+			sourceActionBars.activate();
+			Map handlers = sourceActionBars.getGlobalActionHandlers();
+			if (handlers != null) {
+				Set keys = handlers.keySet();
+				for (Iterator iter = keys.iterator(); iter.hasNext();) {
+					String id = (String) iter.next();
+					rootBars.setGlobalActionHandler(id, (IAction) handlers
+							.get(id));
+				}
+			}
+		} else {
+			sourceActionBars.deactivate();
+			registerGlobalActionHandlers();
+		}
+		rootBars.updateActionBars();
+	}
+	private void registerGlobalActionHandlers() {
+		registerGlobalAction(ActionFactory.DELETE.getId());
+		registerGlobalAction(ActionFactory.UNDO.getId());
+		registerGlobalAction(ActionFactory.REDO.getId());
+		registerGlobalAction(ActionFactory.CUT.getId());
+		registerGlobalAction(ActionFactory.COPY.getId());
+		registerGlobalAction(ActionFactory.PASTE.getId());
+		registerGlobalAction(ActionFactory.SELECT_ALL.getId());
+		registerGlobalAction(ActionFactory.FIND.getId());
+		// hook revert
+		getActionBars().setGlobalActionHandler(ActionFactory.REVERT.getId(), revertAction);
+	}
+	private void registerGlobalAction(String id) {
+		IAction action = getGlobalAction(id);
+		getActionBars().setGlobalActionHandler(id, action);
+	}
+	public void updateActions() {
+		saveAction.update();
+		revertAction.update();
+	}
+	public void updateSelectableActions(ISelection selection) {
+		if (editor != null) {
+			cutAction.selectionChanged(selection);
+			copyAction.selectionChanged(selection);
+			pasteAction.selectionChanged(selection);
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormPage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormPage.java
new file mode 100755
index 0000000..352badb
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEFormPage.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.forms.AbstractFormPart;
+import org.eclipse.ui.forms.IFormPart;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.eclipse.ui.views.properties.IPropertySheetPage;
+
+public abstract class PDEFormPage extends FormPage {
+	/**
+	 * @param editor
+	 * @param id
+	 * @param title
+	 */
+	public PDEFormPage(FormEditor editor, String id, String title) {
+		super(editor, id, title);
+	}
+
+	protected void createFormContent(IManagedForm managedForm) {
+		final ScrolledForm form = managedForm.getForm();
+		//form.setBackgroundImage(PDEPlugin.getDefault().getLabelProvider().get(
+		//		PDEPluginImages.DESC_FORM_BANNER));
+		final String href = getHelpResource();
+		if (href != null) {
+			IToolBarManager manager = form.getToolBarManager();
+			Action helpAction = new Action("help") { //$NON-NLS-1$
+				public void run() {
+					BusyIndicator.showWhile(form.getDisplay(), new Runnable() {
+						public void run() {
+							PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(href);
+						}
+					});
+				}
+			};
+			helpAction.setToolTipText(PDEUIMessages.PDEFormPage_help); 
+			helpAction.setImageDescriptor(PDEPluginImages.DESC_HELP);
+			manager.add(helpAction);
+			form.updateToolBar();
+		}
+	}
+	public PDEFormEditor getPDEEditor() {
+		return (PDEFormEditor) getEditor();
+	}
+	protected String getHelpResource() {
+		return null;
+	}
+	public IBaseModel getModel() {
+		return getPDEEditor().getAggregateModel();
+	}
+	public void contextMenuAboutToShow(IMenuManager menu) {
+	}
+	
+	protected Control getFocusControl() {
+		IManagedForm form = getManagedForm();
+		if (form == null)
+			return null;
+		Control control = form.getForm();
+		if (control == null || control.isDisposed())
+			return null;
+		Display display = control.getDisplay();
+		Control focusControl = display.getFocusControl();
+		if (focusControl == null || focusControl.isDisposed())
+			return null;
+		return focusControl;
+	}
+	public boolean performGlobalAction(String actionId) {
+		Control focusControl = getFocusControl();
+		if (focusControl == null)
+			return false;
+
+		if (canPerformDirectly(actionId, focusControl))
+			return true;
+		AbstractFormPart focusPart = getFocusSection();
+		if (focusPart!=null) {
+			if (focusPart instanceof PDESection)
+				return ((PDESection)focusPart).doGlobalAction(actionId);
+			if (focusPart instanceof PDEDetails)
+				return ((PDEDetails)focusPart).doGlobalAction(actionId);
+		}
+		return false;
+	}
+
+	public boolean canPaste(Clipboard clipboard) {
+		AbstractFormPart focusPart = getFocusSection();
+		if (focusPart != null) {
+			if (focusPart instanceof PDESection) {
+				return ((PDESection)focusPart).canPaste(clipboard);
+			}
+			if (focusPart instanceof PDEDetails) {
+				return ((PDEDetails)focusPart).canPaste(clipboard);
+			}
+		}
+		return false;
+	}
+	
+	private AbstractFormPart getFocusSection() {
+		Control focusControl = getFocusControl();
+		if (focusControl == null)
+			return null;
+		Composite parent = focusControl.getParent();
+		AbstractFormPart targetPart = null;
+		while (parent != null) {
+			Object data = parent.getData("part"); //$NON-NLS-1$
+			if (data != null && data instanceof AbstractFormPart) {
+				targetPart = (AbstractFormPart) data;
+				break;
+			}
+			parent = parent.getParent();
+		}
+		return targetPart;
+	}
+	public IPropertySheetPage getPropertySheetPage() {
+		return null;
+	}
+	protected boolean canPerformDirectly(String id, Control control) {
+		if (control instanceof Text) {
+			Text text = (Text) control;
+			if (id.equals(ActionFactory.CUT.getId())) {
+				text.cut();
+				return true;
+			}
+			if (id.equals(ActionFactory.COPY.getId())) {
+				text.copy();
+				return true;
+			}
+			if (id.equals(ActionFactory.PASTE.getId())) {
+				text.paste();
+				return true;
+			}
+			if (id.equals(ActionFactory.SELECT_ALL.getId())) {
+				text.selectAll();
+				return true;
+			}
+			if (id.equals(ActionFactory.DELETE.getId())) {
+				int count = text.getSelectionCount();
+				if (count == 0) {
+					int caretPos = text.getCaretPosition();
+					text.setSelection(caretPos, caretPos + 1);
+				}
+				text.insert(""); //$NON-NLS-1$
+				return true;
+			}
+		}
+		return false;
+	}	
+	public void cancelEdit() {
+		IFormPart [] parts = getManagedForm().getParts();
+		for (int i=0; i<parts.length; i++) {
+			IFormPart part = parts[i];
+			if (part instanceof IContextPart)
+				((IContextPart)part).cancelEdit();
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMasterDetailsBlock.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMasterDetailsBlock.java
new file mode 100644
index 0000000..4dd4c4a
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMasterDetailsBlock.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.*;
+import org.eclipse.ui.forms.widgets.*;
+
+public abstract class PDEMasterDetailsBlock extends MasterDetailsBlock {
+	private PDEFormPage page;
+	
+	public PDEMasterDetailsBlock(PDEFormPage page) {
+		this.page = page;
+	}
+	
+	public PDEFormPage getPage() {
+		return page;
+	}
+	
+	protected abstract PDESection createMasterSection(IManagedForm managedForm, Composite parent);
+
+	protected void createMasterPart(final IManagedForm managedForm,
+			Composite parent) {
+		PDESection section = createMasterSection(managedForm, parent);
+		managedForm.addPart(section);
+		Section sc = section.getSection();
+		sc.marginWidth = 5;
+		sc.marginHeight = 5;
+	}
+	protected void createToolBarActions(IManagedForm managedForm) {
+		final ScrolledForm form = managedForm.getForm();
+	
+		Action haction = new Action("hor", Action.AS_RADIO_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				sashForm.setOrientation(SWT.HORIZONTAL);
+				form.reflow(true);
+			}
+		};
+		haction.setChecked(true);
+		haction.setToolTipText(PDEUIMessages.DetailsBlock_horizontal); 
+		haction.setImageDescriptor(PDEPluginImages.DESC_HORIZONTAL);
+		haction.setDisabledImageDescriptor(PDEPluginImages.DESC_HORIZONTAL_DISABLED);
+
+		Action vaction = new Action("ver", Action.AS_RADIO_BUTTON) { //$NON-NLS-1$
+			public void run() {
+				sashForm.setOrientation(SWT.VERTICAL);
+				form.reflow(true);
+			}
+		};
+		vaction.setChecked(false);
+		vaction.setToolTipText(PDEUIMessages.DetailsBlock_vertical); 
+		vaction.setImageDescriptor(PDEPluginImages.DESC_VERTICAL);
+		vaction.setDisabledImageDescriptor(PDEPluginImages.DESC_VERTICAL_DISABLED);
+		form.getToolBarManager().add(haction);
+		form.getToolBarManager().add(vaction);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPageContentOutline.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPageContentOutline.java
new file mode 100755
index 0000000..375ab50
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPageContentOutline.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.util.ArrayList;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.pde.internal.ui.IHelpContextIds;
+import org.eclipse.pde.internal.ui.IPreferenceConstants;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.Page;
+import org.eclipse.ui.part.PageBook;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+
+public class PDEMultiPageContentOutline extends Page 
+	implements IContentOutlinePage, ISelectionProvider, ISelectionChangedListener, IPreferenceConstants {
+	private PageBook pagebook;
+	private ISelection selection;
+	private ArrayList listeners;
+	private ISortableContentOutlinePage currentPage;
+	private ISortableContentOutlinePage emptyPage;
+	private IActionBars actionBars;
+	private boolean sortingOn;
+	private PDEFormEditor editor;
+
+	public PDEMultiPageContentOutline(PDEFormEditor editor) {
+		this.editor=editor;
+		listeners = new ArrayList();
+		sortingOn= PDEPlugin.getDefault().getPreferenceStore().getBoolean("PDEMultiPageContentOutline.SortingAction.isChecked"); //$NON-NLS-1$
+		
+	}
+	
+	public void addFocusListener(FocusListener listener) {
+	}
+	public void addSelectionChangedListener(ISelectionChangedListener listener) {
+		listeners.add(listener);
+	}
+	public void createControl(Composite parent) {
+		pagebook = new PageBook(parent, SWT.NONE);
+	}
+
+	public void dispose() {
+		if (pagebook != null && !pagebook.isDisposed())
+			pagebook.dispose();
+		if (emptyPage!=null) {
+			emptyPage.dispose();
+			emptyPage=null;
+		}
+		pagebook = null;
+		listeners = null;
+	}
+
+	public boolean isDisposed() {
+		return listeners==null;
+	}
+
+	public Control getControl() {
+		return pagebook;
+	}
+	public PageBook getPagebook() {
+		return pagebook;
+	}
+	public ISelection getSelection() {
+		return selection;
+	}
+	public void makeContributions(
+		IMenuManager menuManager,
+		IToolBarManager toolBarManager,
+		IStatusLineManager statusLineManager) {
+	}
+	public void removeFocusListener(FocusListener listener) {
+	}
+	public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+		listeners.remove(listener);
+	}
+	public void selectionChanged(SelectionChangedEvent event) {
+		setSelection(event.getSelection());
+	}
+
+	public void setActionBars(IActionBars actionBars) {
+		this.actionBars = actionBars;
+		registerToolbarActions(actionBars);
+		if (currentPage != null)
+			setPageActive(currentPage);
+
+	}
+	public IActionBars getActionBars() {
+		return actionBars;
+	}
+	public void setFocus() {
+		if (currentPage != null)
+			currentPage.setFocus();
+	}
+	private ISortableContentOutlinePage getEmptyPage() {
+		if (emptyPage==null)
+			emptyPage = new EmptyOutlinePage();
+		return emptyPage;
+	}
+	public void setPageActive(ISortableContentOutlinePage page) {
+		if (page==null) {
+			page = getEmptyPage();
+		}
+		if (currentPage != null) {
+			currentPage.removeSelectionChangedListener(this);
+		}
+		//page.init(getSite());
+		page.sort(sortingOn);
+		page.addSelectionChangedListener(this);
+		this.currentPage = page;
+		if (pagebook == null) {
+			// still not being made
+			return;
+		}
+		Control control = page.getControl();
+		if (control == null || control.isDisposed()) {
+			// first time
+			page.createControl(pagebook);
+			page.setActionBars(getActionBars());			
+			control = page.getControl();
+		}
+		pagebook.showPage(control);
+		this.currentPage = page;
+	}
+	/**
+	 * Set the selection.
+	 */
+	public void setSelection(ISelection selection) {
+		this.selection =selection;
+		if (listeners == null)
+			return;
+		SelectionChangedEvent e = new SelectionChangedEvent(this, selection);
+		for (int i=0; i<listeners.size(); i++) {
+			((ISelectionChangedListener)listeners.get(i)).selectionChanged(e);
+		}	
+	}
+	private void registerToolbarActions(IActionBars actionBars) {
+		
+		IToolBarManager toolBarManager= actionBars.getToolBarManager();
+		if (toolBarManager != null) {	
+			toolBarManager.add(new ToggleLinkWithEditorAction(editor));
+			toolBarManager.add(new SortingAction());
+		}
+	}
+	
+	class SortingAction extends Action {
+		
+		public SortingAction() {
+			super();
+			PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IHelpContextIds.OUTLINE_SORT_ACTION);
+			setText(PDEUIMessages.PDEMultiPageContentOutline_SortingAction_label); 
+			setImageDescriptor(PDEPluginImages.DESC_ALPHAB_SORT_CO);
+			setDisabledImageDescriptor(PDEPluginImages.DESC_ALPHAB_SORT_CO_DISABLED);
+			setToolTipText(PDEUIMessages.PDEMultiPageContentOutline_SortingAction_tooltip); 
+			setDescription(PDEUIMessages.PDEMultiPageContentOutline_SortingAction_description); 
+			setChecked(sortingOn);
+		}
+		
+		public void run() {
+			setChecked(isChecked());
+			valueChanged(isChecked());
+		}
+		private void valueChanged(final boolean on) {
+			sortingOn=on;
+			if(currentPage!=null)
+				currentPage.sort(on);
+			PDEPlugin.getDefault().getPreferenceStore().setValue("PDEMultiPageContentOutline.SortingAction.isChecked", on); //$NON-NLS-1$
+		}
+		
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPagePropertySheet.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPagePropertySheet.java
new file mode 100755
index 0000000..fa51492
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDEMultiPagePropertySheet.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ui.*;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.ui.part.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.views.properties.*;
+import org.eclipse.swt.*;
+import java.util.*;
+
+public class PDEMultiPagePropertySheet implements IPropertySheetPage {
+	private PageBook pagebook;
+	private Hashtable recMap = new Hashtable();
+	private PropertySheetPage defaultPage;
+	private IActionBars actionBars;
+	private IPropertySheetPage currentPage;
+	private boolean disposed = false;
+
+	class PageRec {
+		IPropertySheetPage page;
+		SubActionBars bars;
+		void setBarsActive(boolean active) {
+			if (active)
+				bars.activate();
+			else
+				bars.deactivate();
+		}
+		void dispose() {
+			if (bars!=null) {
+				bars.dispose();
+				bars = null;
+			}
+			if (page!=null) {
+				page.dispose();
+				page = null;
+			}
+		}
+	}
+
+	public PDEMultiPagePropertySheet() {
+		defaultPage = new PropertySheetPage();
+	}
+
+	public void createControl(Composite parent) {
+		disposed = false;
+		pagebook = new PageBook(parent, SWT.NULL);
+		defaultPage.createControl(pagebook);
+		if (currentPage != null)
+			setPageActive(currentPage);
+	}
+	private PageRec createPageRec(IPropertySheetPage page) {
+		if (actionBars == null)
+			return null;
+		PageRec rec = new PageRec();
+		rec.page = page;
+
+		rec.bars = new SubActionBars(actionBars);
+		getPageControl(page);
+
+		page.setActionBars(rec.bars);
+		recMap.put(page, rec);
+		return rec;
+	}
+	public void dispose() {
+		updateActionBars();
+		
+		for (Enumeration enm=recMap.elements(); enm.hasMoreElements();) {
+			PageRec rec = (PageRec)enm.nextElement();
+			rec.dispose();
+		}
+		recMap.clear();
+
+		if (pagebook != null && !pagebook.isDisposed()) {
+			pagebook.dispose();
+		}
+		if (defaultPage!=null) {
+			defaultPage.dispose();
+			defaultPage=null;
+		}
+		pagebook = null;
+		disposed = true;
+	}
+
+	public boolean isDisposed() {
+		return disposed;
+	}
+
+	public Control getControl() {
+		return pagebook;
+	}
+	
+	public void closeActiveEditor() {
+		if (currentPage==null) return;
+	}
+	
+	private Control getPageControl(IPropertySheetPage page) {
+		Control control = page.getControl();
+		if (control == null || control.isDisposed()) {
+			// first time
+			page.createControl(pagebook);
+			control = page.getControl();
+		}
+		return control;
+	}
+	public void selectionChanged(IWorkbenchPart part, ISelection sel) {
+		if (currentPage != null)
+			currentPage.selectionChanged(part, sel);
+	}
+	public void setActionBars(IActionBars bars) {
+		this.actionBars = bars;
+
+		createPageRec(defaultPage);
+
+		if (currentPage != null) {
+			PageRec rec = createPageRec(currentPage);
+			setPageActive(rec);
+			updateActionBars();
+		}
+	}
+	public void setDefaultPageActive() {
+		setPageActive(defaultPage);
+	}
+	public void setFocus() {
+		if (currentPage != null)
+			currentPage.setFocus();
+	}
+	private void setPageActive(PageRec pageRec) {
+		IPropertySheetPage page = pageRec.page;
+		Control control = getPageControl(page);
+		pagebook.showPage(control);
+		pageRec.setBarsActive(true);
+	}
+	public void setPageActive(IPropertySheetPage page) {
+		IPropertySheetPage oldPage = currentPage;
+		this.currentPage = page;
+		if (pagebook == null) {
+			// still not being made
+			return;
+		}
+		if (oldPage != null) {
+			PageRec oldRec = (PageRec) recMap.get(oldPage);
+			if (oldRec != null) {
+				oldRec.setBarsActive(false);
+			}
+		}
+		PageRec rec = (PageRec) recMap.get(page);
+		if (rec == null) {
+			rec = createPageRec(page);
+		}
+		if (rec != null) {
+			setPageActive(rec);
+			updateActionBars();
+		}
+	}
+	private void updateActionBars() {
+		refreshGlobalActionHandlers();
+		actionBars.updateActionBars();
+	}
+	private void refreshGlobalActionHandlers() {
+		// Clear old actions.
+		actionBars.clearGlobalActionHandlers();
+
+		// Set new actions.
+		if (recMap == null || currentPage == null)
+			return;
+		PageRec activeRec = (PageRec) recMap.get(currentPage);
+		Map newActionHandlers = activeRec.bars.getGlobalActionHandlers();
+		if (newActionHandlers != null) {
+			Set keys = newActionHandlers.entrySet();
+			Iterator iter = keys.iterator();
+			while (iter.hasNext()) {
+				Map.Entry entry = (Map.Entry) iter.next();
+				actionBars.setGlobalActionHandler(
+					(String) entry.getKey(),
+					(IAction) entry.getValue());
+			}
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESection.java
new file mode 100755
index 0000000..83bbb80
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESection.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.pde.core.*;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.SectionPart;
+import org.eclipse.ui.forms.widgets.*;
+
+public abstract class PDESection extends SectionPart implements IModelChangedListener, IContextPart {
+	public static final int CLIENT_VSPACING = 4;
+	private PDEFormPage page;
+	public PDESection(PDEFormPage page, Composite parent, int style) {
+		this(page, parent, style, true);
+	}	
+	/**
+	 * @param section
+	 *	 
+	 */
+	public PDESection(PDEFormPage page, Composite parent, int style, boolean titleBar) {
+		super(parent, page.getManagedForm().getToolkit(), titleBar?(ExpandableComposite.TITLE_BAR | style): style);
+		this.page = page;
+		initialize(page.getManagedForm());
+		getSection().clientVerticalSpacing = CLIENT_VSPACING;
+		getSection().setData("part", this); //$NON-NLS-1$
+		//createClient(getSection(), page.getManagedForm().getToolkit());
+	}
+	
+	protected abstract void createClient(Section section, FormToolkit toolkit);
+
+	public PDEFormPage getPage() {
+		return page;
+	}
+	
+	public boolean doGlobalAction(String actionId) {
+		return false;
+	}
+
+	public void modelChanged(IModelChangedEvent e) {
+		if (e.getChangeType()==IModelChangedEvent.WORLD_CHANGED)
+			markStale();
+	}
+	
+	public String getContextId() {
+		return null;
+	}
+	public void fireSaveNeeded() {
+		markDirty();
+		if (getContextId()!=null)
+			getPage().getPDEEditor().fireSaveNeeded(getContextId(), false);
+	}
+	public boolean isEditable() {
+		return getPage().getPDEEditor().getAggregateModel().isEditable();
+	}
+	public boolean canPaste(Clipboard clipboard) {
+		return false;
+	}
+	public void cancelEdit() {
+		super.refresh();
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESourcePage.java
new file mode 100755
index 0000000..7b6057b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PDESourcePage.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Jan 26, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.context.InputContext;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.pde.internal.core.text.IDocumentRange;
+import org.eclipse.pde.internal.core.text.IEditingModel;
+import org.eclipse.pde.internal.ui.IHelpContextIds;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormEditor;
+import org.eclipse.ui.forms.editor.IFormPage;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.ide.IGotoMarker;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.DefaultRangeIndicator;
+
+public abstract class PDESourcePage extends TextEditor implements IFormPage, IGotoMarker {
+	/**
+	 * Updates the OutlinePage selection and this editor's range indicator.
+	 * 
+	 * @since 3.0
+	 */
+	private class PDESourcePageChangedListener implements
+			ISelectionChangedListener {
+
+		/**
+		 * Installs this selection changed listener with the given selection
+		 * provider. If the selection provider is a post selection provider,
+		 * post selection changed events are the preferred choice, otherwise
+		 * normal selection changed events are requested.
+		 * 
+		 * @param selectionProvider
+		 */
+		public void install(ISelectionProvider selectionProvider) {
+			if (selectionProvider == null) {
+				return;
+			}
+
+			if (selectionProvider instanceof IPostSelectionProvider) {
+				IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+				provider.addPostSelectionChangedListener(this);
+			} else {
+				selectionProvider.addSelectionChangedListener(this);
+			}
+		}
+
+		/*
+		 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+		 */
+		public void selectionChanged(SelectionChangedEvent event) {
+			ISelection selection = event.getSelection();
+			if (!selection.isEmpty() && selection instanceof ITextSelection) {
+				IDocumentRange rangeElement = getRangeElement((ITextSelection) selection);
+				if (rangeElement != null) {
+					setHighlightRange(rangeElement, false);
+				} else {
+					resetHighlightRange();
+				}
+				// notify outline page
+				if (PDEPlugin.getDefault().getPreferenceStore().getBoolean(
+						"ToggleLinkWithEditorAction.isChecked")) { //$NON-NLS-1$
+					outlinePage
+							.removeSelectionChangedListener(outlineSelectionChangedListener);
+					if (rangeElement != null) {
+						outlinePage.setSelection(new StructuredSelection(
+								rangeElement));
+					} else {
+						outlinePage.setSelection(StructuredSelection.EMPTY);
+					}
+					outlinePage
+							.addSelectionChangedListener(outlineSelectionChangedListener);
+				}
+			}
+		}
+
+		/**
+		 * Removes this selection changed listener from the given selection
+		 * provider.
+		 * 
+		 * @param selectionProviderstyle
+		 */
+		public void uninstall(ISelectionProvider selectionProvider) {
+			if (selectionProvider == null) {
+				return;
+			}
+
+			if (selectionProvider instanceof IPostSelectionProvider) {
+				IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+				provider.removePostSelectionChangedListener(this);
+			} else {
+				selectionProvider.removeSelectionChangedListener(this);
+			}
+		}
+
+	}
+
+	/**
+	 * The editor selection changed listener.
+	 * 
+	 * @since 3.0
+	 */
+	private PDESourcePageChangedListener fEditorSelectionChangedListener;
+	private PDEFormEditor editor;
+	private Control control;
+	private int index;
+	private String id;
+	private InputContext inputContext;
+	private ISortableContentOutlinePage outlinePage;
+	private ISelectionChangedListener outlineSelectionChangedListener;
+	/**
+	 * 
+	 */
+	public PDESourcePage(PDEFormEditor editor, String id, String title) {
+		this.id = id;
+		initialize(editor);
+		IPreferenceStore[] stores = new IPreferenceStore[2];
+		stores[0] = PDEPlugin.getDefault().getPreferenceStore();
+		stores[1] = EditorsUI.getPreferenceStore();
+		setPreferenceStore(new ChainedPreferenceStore(stores));
+		setRangeIndicator(new DefaultRangeIndicator());
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#initialize(org.eclipse.ui.forms.editor.FormEditor)
+	 */
+	public void initialize(FormEditor editor) {
+		this.editor = (PDEFormEditor)editor;
+	}
+	public void dispose() {
+		if (fEditorSelectionChangedListener != null)  {
+			fEditorSelectionChangedListener.uninstall(getSelectionProvider());
+			fEditorSelectionChangedListener= null;
+		}
+		if (outlinePage != null) {
+			outlinePage.dispose();
+			outlinePage = null;
+		}
+		super.dispose();
+	}
+
+	protected void editorSaved() {
+		super.editorSaved();
+	}
+	
+	protected abstract ILabelProvider createOutlineLabelProvider();
+	protected abstract ITreeContentProvider createOutlineContentProvider();
+	protected abstract ViewerSorter createOutlineSorter();
+	protected abstract void outlineSelectionChanged(SelectionChangedEvent e);
+	protected ViewerSorter createDefaultOutlineSorter() {
+		return null;
+	}
+	protected ISortableContentOutlinePage createOutlinePage() {
+		SourceOutlinePage sourceOutlinePage=
+		new SourceOutlinePage(
+				(IEditingModel) getInputContext().getModel(),
+				createOutlineLabelProvider(), createOutlineContentProvider(),
+				createDefaultOutlineSorter(), createOutlineSorter());
+		outlinePage = sourceOutlinePage;
+		outlineSelectionChangedListener = new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				outlineSelectionChanged(event);
+			}
+		};
+		outlinePage.addSelectionChangedListener(outlineSelectionChangedListener);
+		getSelectionProvider().addSelectionChangedListener(sourceOutlinePage);
+		fEditorSelectionChangedListener= new PDESourcePageChangedListener();
+		fEditorSelectionChangedListener.install(getSelectionProvider());
+		return outlinePage;
+	}
+
+	public ISortableContentOutlinePage getContentOutline() {
+		if (outlinePage==null)
+			outlinePage = createOutlinePage();
+		return outlinePage;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#getEditor()
+	 */
+	public FormEditor getEditor() {
+		return editor;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#getManagedForm()
+	 */
+	public IManagedForm getManagedForm() {
+		// not a form page
+		return null;
+	}
+	protected void firePropertyChange(int type) {
+		if (type == PROP_DIRTY) {
+			editor.fireSaveNeeded(getEditorInput(), true);
+		} else
+			super.firePropertyChange(type);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#setActive(boolean)
+	 */
+	public void setActive(boolean active) {
+		inputContext.setSourceEditingMode(active);
+	}
+
+	public boolean canLeaveThePage() {
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#isActive()
+	 */
+	public boolean isActive() {
+		return this.equals(editor.getActivePageInstance());
+	}
+	public void createPartControl(Composite parent) {
+		super.createPartControl(parent);
+		Control[] children = parent.getChildren();
+		control = children[children.length - 1];
+		
+		PlatformUI.getWorkbench().getHelpSystem().setHelp(control, IHelpContextIds.MANIFEST_SOURCE_PAGE);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#getPartControl()
+	 */
+	public Control getPartControl() {
+		return control;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#getId()
+	 */
+	public String getId() {
+		return id;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#getIndex()
+	 */
+	public int getIndex() {
+		return index;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#setIndex(int)
+	 */
+	public void setIndex(int index) {
+		this.index = index;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#isSource()
+	 */
+	public boolean isEditor() {
+		return true;
+	}
+	/**
+	 * @return Returns the inputContext.
+	 */
+	public InputContext getInputContext() {
+		return inputContext;
+	}
+	/**
+	 * @param inputContext The inputContext to set.
+	 */
+	public void setInputContext(InputContext inputContext) {
+		this.inputContext = inputContext;
+		setDocumentProvider(inputContext.getDocumentProvider());
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.forms.editor.IFormPage#focusOn(java.lang.Object)
+	 */
+	public boolean selectReveal(Object object) {
+		if (object instanceof IMarker) {
+			IDE.gotoMarker(this, (IMarker)object);
+			return true;
+		}
+		return false;
+	}
+	
+	protected IDocumentRange getRangeElement(ITextSelection selection) {
+		return null;
+	}
+
+	public void setHighlightRange(IDocumentRange node, boolean moveCursor) {
+		ISourceViewer sourceViewer = getSourceViewer();
+		if (sourceViewer == null)
+			return;
+
+		IDocument document = sourceViewer.getDocument();
+		if (document == null)
+			return;
+
+		int offset = node.getOffset();
+		int length = node.getLength();
+		setHighlightRange(offset, length == -1 ? 1 : length, moveCursor);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PropertiesAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PropertiesAction.java
new file mode 100644
index 0000000..602a699
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/PropertiesAction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.pde.internal.ui.*;
+import org.eclipse.ui.*;
+
+public class PropertiesAction extends Action {
+	private PDEFormEditor editor;
+	public PropertiesAction(PDEFormEditor editor) {
+		this.editor = editor;
+		setText(PDEUIMessages.Actions_properties_label);
+		setImageDescriptor(PDEPluginImages.DESC_PROPERTIES);
+		setDisabledImageDescriptor(PDEPluginImages.DESC_PROPERTIES_DISABLED);
+	}
+	public void run() {
+		try {
+			String viewId = IPageLayout.ID_PROP_SHEET;
+			IWorkbenchPage perspective = PDEPlugin.getActivePage();
+			IViewPart view = perspective.showView(viewId);
+			editor.updatePropertySheet(editor.getActivePageInstance());
+			perspective.activate(editor);
+			perspective.bringToTop(view);
+		} catch (PartInitException e) {
+			PDEPlugin.logException(e);
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SourceOutlinePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SourceOutlinePage.java
new file mode 100755
index 0000000..461a9ba
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SourceOutlinePage.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.pde.internal.core.text.IEditingModel;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.part.IPageSite;
+import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
+
+/**
+ * Content outline page for the XML editor.
+ */
+public class SourceOutlinePage extends ContentOutlinePage implements IReconcilingParticipant, ISortableContentOutlinePage{
+	
+	private IEditingModel fModel;
+	private IBaseLabelProvider fLabelProvider;
+	private IContentProvider fContentProvider;
+	private ViewerSorter fDefaultSorter;
+	private ViewerSorter fViewerSorter;
+	private boolean sorted;
+	TreeViewer viewer;
+	
+	public SourceOutlinePage(IEditingModel model, IBaseLabelProvider lProvider,
+			IContentProvider cProvider, ViewerSorter defaultSorter,
+			ViewerSorter sorter) {
+		super();
+		fModel = model;
+		fLabelProvider = lProvider;
+		fContentProvider = cProvider;
+		fDefaultSorter = defaultSorter;
+		fViewerSorter = sorter;
+	}
+		
+	/**  
+	 * Creates the control for this outline page.
+	 */
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		viewer= getTreeViewer();
+		viewer.setContentProvider(fContentProvider);
+		viewer.setLabelProvider(fLabelProvider);
+		if(sorted)
+			viewer.setSorter(fViewerSorter);
+		else
+			viewer.setSorter(fDefaultSorter);
+		viewer.setInput(fModel);
+		viewer.expandAll();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.views.contentoutline.ContentOutlinePage#init(org.eclipse.ui.part.IPageSite)
+	 */
+	public void init(IPageSite pageSite) {
+		super.init(pageSite);
+	}
+	
+	public void makeContributions(
+			IMenuManager menuManager, 
+			IToolBarManager toolBarManager, 
+			IStatusLineManager statusLineManager) {
+		//Create actions and contribute into the provided managers
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.editor.text.IReconcilingParticipant#reconciled(org.eclipse.jface.text.IDocument)
+	 */
+	public void reconciled(IDocument document) {
+		final Control control = getControl();
+		if (control == null)
+			return;
+		control.getDisplay().asyncExec(new Runnable() {
+			public void run() {
+				if(control.isDisposed()){
+					return;
+				}
+				control.setRedraw(false);
+				getTreeViewer().refresh();
+				getTreeViewer().expandAll();
+				control.setRedraw(true);
+			}
+		});
+	}
+	public void sort (boolean sorting){
+		sorted = sorting;
+		if(viewer!=null)
+			if(sorting)
+				viewer.setSorter(fViewerSorter);
+			else
+				viewer.setSorter(fDefaultSorter);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StorageDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StorageDocumentProvider.java
new file mode 100644
index 0000000..4eae315
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StorageDocumentProvider.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.ui.IStorageEditorInput;
+
+public class StorageDocumentProvider extends StreamDocumentProvider {
+
+	public StorageDocumentProvider(IDocumentPartitioner partitioner) {
+		this(partitioner, null);
+	}
+
+	public StorageDocumentProvider(
+		IDocumentPartitioner partitioner,
+		String encoding) {
+		super(partitioner, encoding);
+	}
+
+	protected IDocument createDocument(Object element) throws CoreException {
+		if (element instanceof IStorageEditorInput) {
+			IDocument document = createEmptyDocument();
+			IDocumentPartitioner part = getPartitioner();
+			if (part != null) {
+				part.connect(document);
+				document.setDocumentPartitioner(part);
+			}
+			IStorage storage = ((IStorageEditorInput)element).getStorage();
+			setDocumentContent(document, storage);
+			return document;
+		}
+		return null;
+	}
+	protected void setDocumentContent(IDocument document, IStorage storage) {
+		try {
+			InputStream contentStream = storage.getContents();
+			setDocumentContent(document, contentStream);
+			contentStream.close();
+		} catch (Exception e) {
+			PDEPlugin.logException(e);
+		}
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StreamDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StreamDocumentProvider.java
new file mode 100644
index 0000000..fe5defe
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StreamDocumentProvider.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+
+import org.eclipse.jface.operation.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.text.source.*;
+import org.eclipse.ui.texteditor.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public abstract class StreamDocumentProvider extends AbstractDocumentProvider {
+	private IDocumentPartitioner partitioner;
+
+	private String enc;
+
+	public StreamDocumentProvider(IDocumentPartitioner partitioner,
+			String encoding) {
+		this.partitioner = partitioner;
+		this.enc = encoding;
+	}
+
+	protected IDocumentPartitioner getPartitioner() {
+		return partitioner;
+	}
+
+	protected String getEncoding() {
+		return enc;
+	}
+
+	protected IAnnotationModel createAnnotationModel(Object element)
+			throws CoreException {
+		return new SystemFileMarkerAnnotationModel();
+	}
+
+	protected void doSaveDocument(IProgressMonitor monitor, Object element,
+			IDocument document, boolean force) throws CoreException {
+	}
+
+	protected void setDocumentContent(IDocument document,
+			InputStream contentStream) {
+		try {
+			Reader in;
+			if (enc == null)
+				in = new InputStreamReader(contentStream);
+			else
+				in = new InputStreamReader(contentStream, enc);
+			int chunkSize = contentStream.available();
+			StringBuffer buffer = new StringBuffer(chunkSize);
+			char[] readBuffer = new char[chunkSize];
+			int n = in.read(readBuffer);
+			while (n > 0) {
+				buffer.append(readBuffer);
+				n = in.read(readBuffer);
+			}
+			in.close();
+			document.set(buffer.toString());
+
+		} catch (IOException e) {
+			PDEPlugin.logException(e);
+		}
+	}
+
+	public long getSynchronizationStamp(Object element) {
+		return 0;
+	}
+
+	public long getModificationStamp(Object element) {
+		return 0;
+	}
+
+	public boolean isDeleted(Object element) {
+		return false;
+	}
+
+	protected IDocument createEmptyDocument() {
+		return new Document();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getOperationRunner(org.eclipse.core.runtime.IProgressMonitor)
+	 */
+	protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
+		// TODO figure out what this method does
+		return null;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StructuredViewerSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StructuredViewerSection.java
new file mode 100755
index 0000000..78ec361
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/StructuredViewerSection.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * @version 	1.0
+ * @author
+ */
+public abstract class StructuredViewerSection extends PDESection {
+	protected StructuredViewerPart viewerPart;
+	/**
+	 * Constructor for StructuredViewerSection.
+	 * @param formPage
+	 */
+	public StructuredViewerSection(PDEFormPage formPage, Composite parent, int style, String [] buttonLabels) {
+		this(formPage, parent, style, true, buttonLabels);
+	}
+
+	/**
+	 * Constructor for StructuredViewerSection.
+	 * @param formPage
+	 */
+	public StructuredViewerSection(PDEFormPage formPage, Composite parent, int style, boolean titleBar, String [] buttonLabels) {
+		super(formPage, parent, style, titleBar);
+		viewerPart = createViewerPart(buttonLabels);
+		viewerPart.setMinimumSize(50, 50);
+		FormToolkit toolkit = formPage.getManagedForm().getToolkit();
+		createClient(getSection(), toolkit);
+	}
+
+	protected void createViewerPartControl(Composite parent, int style, int span, FormToolkit toolkit) {
+		viewerPart.createControl(parent, style, span, toolkit);
+		MenuManager popupMenuManager = new MenuManager();
+		IMenuListener listener = new IMenuListener() {
+			public void menuAboutToShow(IMenuManager mng) {
+				fillContextMenu(mng);
+			}
+		};
+		popupMenuManager.addMenuListener(listener);
+		popupMenuManager.setRemoveAllWhenShown(true);
+		Control control = viewerPart.getControl();
+		Menu menu = popupMenuManager.createContextMenu(control);
+		control.setMenu(menu);
+	}
+	
+	protected Composite createClientContainer(Composite parent, int span, FormToolkit toolkit) {
+		Composite container = toolkit.createComposite(parent);
+		GridLayout layout = new GridLayout();
+		layout.marginWidth = layout.marginHeight = 2;
+		layout.numColumns = span;
+		container.setLayout(layout);
+		return container;
+	}
+	
+	protected abstract StructuredViewerPart createViewerPart(String [] buttonLabels);
+	
+	protected void fillContextMenu(IMenuManager manager) {
+	}
+	
+	protected void buttonSelected(int index) {
+	}
+
+	protected void doPaste() {
+		ISelection selection = getViewerSelection();
+		IStructuredSelection ssel = (IStructuredSelection)selection;
+		if (ssel.size()>1) return;
+		
+		Object target = ssel.getFirstElement();
+		
+		Clipboard clipboard = getPage().getPDEEditor().getClipboard();
+		ModelDataTransfer modelTransfer = ModelDataTransfer.getInstance();
+		Object [] objects = (Object[])clipboard.getContents(modelTransfer);
+		if (objects!=null) {
+			doPaste(target, objects);
+		}
+	}
+	public boolean canPaste(Clipboard clipboard) {
+		ISelection selection = getViewerSelection();
+		IStructuredSelection ssel = (IStructuredSelection)selection;
+		if (ssel.size()>1) return false;
+			
+		Object target = ssel.getFirstElement();
+		ModelDataTransfer modelTransfer = ModelDataTransfer.getInstance();
+		Object [] objects = (Object[])clipboard.getContents(modelTransfer);
+		if (objects!=null && objects.length>0) {
+			return canPaste(target, objects);
+		}
+		return clipboard.getContents(TextTransfer.getInstance()) != null;
+	}
+	protected ISelection getViewerSelection() {
+		return viewerPart.getViewer().getSelection();
+	}
+	protected void doPaste(Object target, Object[] objects) {
+	}
+	
+	protected boolean canPaste(Object target, Object [] objects) {
+		return false;
+	}
+	public void setFocus() {
+		viewerPart.getControl().setFocus();
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileDocumentProvider.java
new file mode 100644
index 0000000..1f3eb55
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileDocumentProvider.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.core.runtime.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public class SystemFileDocumentProvider extends StreamDocumentProvider {
+
+	public SystemFileDocumentProvider(IDocumentPartitioner partitioner) {
+		this(partitioner, null);
+	}
+
+	public SystemFileDocumentProvider(
+		IDocumentPartitioner partitioner,
+		String encoding) {
+		super(partitioner, encoding);
+	}
+	/*
+	 * @see AbstractDocumentProvider#createAnnotationModel(Object)
+	 */
+	protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
+		if (element instanceof SystemFileEditorInput) {
+			SystemFileEditorInput input= (SystemFileEditorInput) element;
+			File file = (File)input.getAdapter(File.class);
+			if (file!=null) {
+				return new SystemFileMarkerAnnotationModel();
+			}
+		}
+		return super.createAnnotationModel(element);
+	}
+
+	protected IDocument createDocument(Object element) throws CoreException {
+		if (element instanceof SystemFileEditorInput) {
+			IDocument document = createEmptyDocument();
+			IDocumentPartitioner part = getPartitioner();
+			if (part != null) {
+				part.connect(document);
+				document.setDocumentPartitioner(part);
+			}
+			File file =
+				(File) ((SystemFileEditorInput) element).getAdapter(File.class);
+			setDocumentContent(document, file);
+			return document;
+		}
+		return null;
+	}
+	protected void doSaveDocument(
+		IProgressMonitor monitor,
+		Object element,
+		IDocument document,
+		boolean force)
+		throws CoreException {
+	}
+	protected void setDocumentContent(IDocument document, File file) {
+		try {
+			InputStream contentStream = new FileInputStream(file);
+			setDocumentContent(document, contentStream);
+			contentStream.close();
+		} catch (IOException e) {
+			PDEPlugin.logException(e);
+		}
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInput.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInput.java
new file mode 100755
index 0000000..348898c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInput.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import org.eclipse.ui.*;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public class SystemFileEditorInput implements IStorageEditorInput, IPersistableElement {
+	private SystemFileStorage storage;
+	private static final String FACTORY_ID = PDEPlugin.getPluginId()+".systemFileEditorInputFactory"; //$NON-NLS-1$
+
+	public SystemFileEditorInput(File file) {
+		storage = new SystemFileStorage(file);
+	}
+	public boolean exists() {
+		return storage.getFile().exists();
+	}
+	public Object getAdapter(Class adapter) {
+		if (adapter.equals(File.class))
+			return storage.getFile();
+		return null;
+	}
+	public ImageDescriptor getImageDescriptor() {
+		return null;
+	}
+	public String getName() {
+		return storage.getFile().getName();
+	}
+	public IPersistableElement getPersistable() {
+		return this;
+	}
+	public void saveState(IMemento memento) {
+		memento.putString("path", storage.getFile().getAbsolutePath()); //$NON-NLS-1$
+	}
+	public String getFactoryId() {
+		return FACTORY_ID;
+	}
+	public IStorage getStorage() {
+		return storage;
+	}
+	public String getToolTipText() {
+		return storage.getFile().getAbsolutePath();
+	}
+	public boolean equals(Object object) {
+		return object instanceof SystemFileEditorInput &&
+		 getStorage().equals(((SystemFileEditorInput)object).getStorage());
+	}
+	
+	public int hashCode() {
+		return getStorage().hashCode();
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInputFactory.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInputFactory.java
new file mode 100644
index 0000000..9398501
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileEditorInputFactory.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.ui.IElementFactory;
+import org.eclipse.ui.IMemento;
+import org.eclipse.core.runtime.IAdaptable;
+import java.io.*;
+
+/**
+ * Insert the type's description here.
+ */
+public class SystemFileEditorInputFactory implements IElementFactory {
+	/**
+	 * The constructor.
+	 */
+	public SystemFileEditorInputFactory() {
+	}
+	
+	public IAdaptable createElement (IMemento memento) {
+		String path = memento.getString("path"); //$NON-NLS-1$
+		File file = new File(path);
+		SystemFileEditorInput input = new SystemFileEditorInput(file);
+		return input;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileMarkerAnnotationModel.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileMarkerAnnotationModel.java
new file mode 100644
index 0000000..464f397
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileMarkerAnnotationModel.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ui.texteditor.*;
+
+/**
+ * A marker annotation model whose underlying source of markers is 
+ * a resource in the workspace.
+ * <p>
+ * This class may be instantiated; it is not intended to be subclassed.
+ * </p>
+ */
+public class SystemFileMarkerAnnotationModel
+	extends AbstractMarkerAnnotationModel {
+
+	protected IMarker[] retrieveMarkers() throws CoreException {
+		return null;
+	}
+
+	protected void deleteMarkers(IMarker[] markers) throws CoreException {
+	}
+
+	protected void listenToMarkerChanges(boolean listen) {
+	}
+
+	protected boolean isAcceptable(IMarker marker) {
+		return true;
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileStorage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileStorage.java
new file mode 100755
index 0000000..871324f
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/SystemFileStorage.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import java.io.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.*;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+
+public class SystemFileStorage extends PlatformObject implements IStorage {
+	private File file;
+	/**
+	 * Constructor for SystemFileStorage.
+	 */
+	public SystemFileStorage(File file) {
+		this.file = file;
+	}
+
+	public File getFile() {
+		return file;
+	}
+	public InputStream getContents() throws CoreException {
+		try {
+			return new FileInputStream(file);
+		} catch (FileNotFoundException e) {
+			IStatus status =
+				new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.OK, null, e);
+			throw new CoreException(status);
+		}
+	}
+	public IPath getFullPath() {
+		return new Path(file.getAbsolutePath());
+	}
+	public String getName() {
+		return file.getName();
+	}
+	public boolean isReadOnly() {
+		return true;
+	}
+
+	public boolean equals(Object object) {
+		return object instanceof SystemFileStorage
+			&& getFile().equals(((SystemFileStorage) object).getFile());
+	}
+
+	public int hashCode() {
+		return getFile().hashCode();
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TableSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TableSection.java
new file mode 100755
index 0000000..247bec8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TableSection.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+/**
+ * @version 1.0
+ * @author
+ */
+public abstract class TableSection extends StructuredViewerSection {
+	protected boolean handleDefaultButton = true;
+	class PartAdapter extends EditableTablePart {
+		public PartAdapter(String[] buttonLabels) {
+			super(buttonLabels);
+		}
+		public void entryModified(Object entry, String value) {
+			TableSection.this.entryModified(entry, value);
+		}
+		public void selectionChanged(IStructuredSelection selection) {
+			getManagedForm().fireSelectionChanged(TableSection.this, selection);
+			TableSection.this.selectionChanged(selection);
+		}
+		public void handleDoubleClick(IStructuredSelection selection) {
+			TableSection.this.handleDoubleClick(selection);
+		}
+		public void buttonSelected(Button button, int index) {
+			TableSection.this.buttonSelected(index);
+			if (handleDefaultButton)
+				button.getShell().setDefaultButton(null);
+		}
+		protected void createButtons(Composite parent, FormToolkit toolkit) {
+			super.createButtons(parent, toolkit);
+			enableButtons();
+		}
+	}
+	/**
+	 * Constructor for TableSection.
+	 * 
+	 * @param formPage
+	 */
+	public TableSection(PDEFormPage formPage, Composite parent, int style,
+			String[] buttonLabels) {
+		this (formPage, parent, style, true, buttonLabels);
+	}
+	/**
+	 * Constructor for TableSection.
+	 * 
+	 * @param formPage
+	 */
+	public TableSection(PDEFormPage formPage, Composite parent, int style,
+			boolean titleBar, String[] buttonLabels) {
+		super(formPage, parent, style, titleBar, buttonLabels);
+	}
+	protected StructuredViewerPart createViewerPart(String[] buttonLabels) {
+		return new PartAdapter(buttonLabels);
+	}
+	protected IAction getRenameAction() {
+		return getTablePart().getRenameAction();
+	}
+	protected EditableTablePart getTablePart() {
+		return (EditableTablePart) viewerPart;
+	}
+	protected void entryModified(Object entry, String value) {
+	}
+	protected void selectionChanged(IStructuredSelection selection) {
+	}
+	protected void handleDoubleClick(IStructuredSelection selection) {
+	}
+	protected void enableButtons() {
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ToggleLinkWithEditorAction.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ToggleLinkWithEditorAction.java
new file mode 100755
index 0000000..4f4d7c8
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/ToggleLinkWithEditorAction.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEPluginImages;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+
+/**
+ * This action toggles whether the Outline page links its selection to the
+ * active editor.
+ * 
+ * @since 3.0
+ */
+public class ToggleLinkWithEditorAction extends Action {
+
+	PDEFormEditor fEditor;
+
+	public ToggleLinkWithEditorAction(PDEFormEditor editor) {
+		super(PDEUIMessages.ToggleLinkWithEditorAction_label); 
+		boolean isLinkingEnabled = PDEPlugin.getDefault().getPreferenceStore()
+				.getBoolean("ToggleLinkWithEditorAction.isChecked"); //$NON-NLS-1$
+		setChecked(isLinkingEnabled);
+		fEditor = editor;
+		setToolTipText(PDEUIMessages.ToggleLinkWithEditorAction_toolTip); 
+		setDescription(PDEUIMessages.ToggleLinkWithEditorAction_description); 
+		setImageDescriptor(PDEPluginImages.DESC_LINK_WITH_EDITOR);
+		setDisabledImageDescriptor(PDEPluginImages.DESC_LINK_WITH_EDITOR_DISABLED);
+	}
+
+	public void run() {
+		PDEPlugin.getDefault().getPreferenceStore().setValue(
+				"ToggleLinkWithEditorAction.isChecked", isChecked()); //$NON-NLS-1$
+		if (isChecked())
+			fEditor.synchronizeOutlinePage();
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TreeSection.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TreeSection.java
new file mode 100644
index 0000000..e3bdf8b
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/TreeSection.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.pde.internal.ui.parts.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * @version 	1.0
+ * @author
+ */
+public abstract class TreeSection extends StructuredViewerSection {
+	protected boolean handleDefaultButton=true;
+	class PartAdapter extends TreePart {
+		public PartAdapter(String[] buttonLabels) {
+			super(buttonLabels);
+		}
+		public void selectionChanged(IStructuredSelection selection) {
+			getManagedForm().fireSelectionChanged(TreeSection.this, selection);
+			TreeSection.this.selectionChanged(selection);
+		}
+		public void handleDoubleClick(IStructuredSelection selection) {
+			TreeSection.this.handleDoubleClick(selection);
+		}
+		public void buttonSelected(Button button, int index) {
+			TreeSection.this.buttonSelected(index);
+			if (handleDefaultButton)
+				button.getShell().setDefaultButton(null);
+		}
+		protected void createButtons(Composite parent, FormToolkit toolkit) {
+			super.createButtons(parent, toolkit);
+			enableButtons();
+		}
+	}
+	/**
+	 * Constructor for TableSection.
+	 * @param formPage
+	 */
+	public TreeSection(PDEFormPage formPage, Composite parent, int style, String[] buttonLabels) {
+		super(formPage, parent, style, buttonLabels);
+	}
+
+	protected StructuredViewerPart createViewerPart(String[] buttonLabels) {
+		return new PartAdapter(buttonLabels);
+	}
+
+	protected TreePart getTreePart() {
+		return (TreePart) viewerPart;
+	}
+
+	protected void selectionChanged(IStructuredSelection selection) {
+	}
+	protected void handleDoubleClick(IStructuredSelection selection) {
+	}
+	protected void enableButtons() {
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLConfiguration.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLConfiguration.java
new file mode 100644
index 0000000..d757fbf
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLConfiguration.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.editor.text.AnnotationHover;
+import org.eclipse.pde.internal.ui.editor.text.BasePDEScanner;
+import org.eclipse.pde.internal.ui.editor.text.ChangeAwareSourceViewerConfiguration;
+import org.eclipse.pde.internal.ui.editor.text.IColorManager;
+import org.eclipse.pde.internal.ui.editor.text.IPDEColorConstants;
+import org.eclipse.pde.internal.ui.editor.text.MultilineDamagerRepairer;
+import org.eclipse.pde.internal.ui.editor.text.XMLPartitionScanner;
+import org.eclipse.pde.internal.ui.editor.text.XMLScanner;
+import org.eclipse.pde.internal.ui.editor.text.XMLTagScanner;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+
+
+public class XMLConfiguration extends ChangeAwareSourceViewerConfiguration {
+	private AnnotationHover fAnnotationHover;
+	private XMLDoubleClickStrategy fDoubleClickStrategy;
+	private XMLTagScanner fTagScanner;
+	private XMLScanner fPdeScanner;
+	private IColorManager fColorManager;
+
+	private TextAttribute fXMLCommentAttr;
+	private MultilineDamagerRepairer fDamagerRepairer;
+	
+	public XMLConfiguration(IColorManager colorManager) {
+		super(PDEPlugin.getDefault().getPreferenceStore());
+		fColorManager = colorManager;
+	}
+	
+	public String[] getConfiguredContentTypes(ISourceViewer sourceViewer) {
+		return new String[] {
+			IDocument.DEFAULT_CONTENT_TYPE,
+			XMLPartitionScanner.XML_COMMENT,
+			XMLPartitionScanner.XML_TAG };
+	}
+	
+	public ITextDoubleClickStrategy getDoubleClickStrategy(
+		ISourceViewer sourceViewer,
+		String contentType) {
+		if (fDoubleClickStrategy == null)
+			fDoubleClickStrategy = new XMLDoubleClickStrategy();
+		return fDoubleClickStrategy;
+	}
+	
+	protected XMLScanner getPDEScanner() {
+		if (fPdeScanner == null)
+			fPdeScanner = new XMLScanner(fColorManager);
+		return fPdeScanner;
+	}
+	
+	protected XMLTagScanner getPDETagScanner() {
+		if (fTagScanner == null) 
+			fTagScanner = new XMLTagScanner(fColorManager);
+		return fTagScanner;
+	}
+	
+	public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
+		PresentationReconciler reconciler = new PresentationReconciler();
+
+		MultilineDamagerRepairer dr = new MultilineDamagerRepairer(getPDEScanner());
+		reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+		reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+		dr = new MultilineDamagerRepairer(getPDETagScanner());
+		reconciler.setDamager(dr, XMLPartitionScanner.XML_TAG);
+		reconciler.setRepairer(dr, XMLPartitionScanner.XML_TAG);
+
+		// TODO: 3.2M3+
+//		fXMLCommentAttr = BasePDEScanner.createTextAttribute(fColorManager, IPDEColorConstants.P_XML_COMMENT);
+		fDamagerRepairer = new MultilineDamagerRepairer(null, fXMLCommentAttr);
+		reconciler.setDamager(fDamagerRepairer, XMLPartitionScanner.XML_COMMENT);
+		reconciler.setRepairer(fDamagerRepairer, XMLPartitionScanner.XML_COMMENT);
+
+		return reconciler;
+	}
+	
+	public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+		if (fAnnotationHover == null)
+			fAnnotationHover = new AnnotationHover();
+		return fAnnotationHover;
+	}
+	
+	public IColorManager getColorManager(){
+		return fColorManager;	
+	}
+	
+	/**
+	 * Preference colors or fonts have changed.  
+	 * Update the default tokens of the scanners.
+	 */
+	public void adaptToPreferenceChange(PropertyChangeEvent event) {
+		if (fTagScanner == null)
+			return; //property change before the editor is fully created
+		if (affectsColorPresentation(event))
+			fColorManager.handlePropertyChangeEvent(event);
+		fTagScanner.adaptToPreferenceChange(event);
+		fPdeScanner.adaptToPreferenceChange(event);
+		String property= event.getProperty();
+		if (property.startsWith(IPDEColorConstants.P_XML_COMMENT)) {
+	    	adaptTextAttribute(event);
+		} 
+	}
+	
+	private void adaptTextAttribute(PropertyChangeEvent event) {
+		String property = event.getProperty();
+		if (property.endsWith(IPDEColorConstants.P_BOLD_SUFFIX)) {
+			fXMLCommentAttr = adaptToStyleChange(event, SWT.BOLD, fXMLCommentAttr);
+		} else if (property.endsWith(IPDEColorConstants.P_ITALIC_SUFFIX)) {
+			fXMLCommentAttr = adaptToStyleChange(event, SWT.ITALIC, fXMLCommentAttr);
+		} else {
+	    	fXMLCommentAttr = new TextAttribute(fColorManager.getColor(event.getProperty()), 
+	    									   fXMLCommentAttr.getBackground(), 
+	    									   fXMLCommentAttr.getStyle());
+		}
+		fDamagerRepairer.setDefaultTextAttribute(fXMLCommentAttr);
+	}
+	
+	private TextAttribute adaptToStyleChange(PropertyChangeEvent event, int styleAttribute, TextAttribute textAttribute) {
+		boolean eventValue = false;
+		Object value = event.getNewValue();
+		if (value instanceof Boolean)
+			eventValue = ((Boolean)value).booleanValue();
+		
+		boolean activeValue = (textAttribute.getStyle() & styleAttribute) == styleAttribute;
+		if (activeValue != eventValue) { 
+			Color foreground = textAttribute.getForeground();
+			Color background = textAttribute.getBackground();
+			int style = eventValue ? textAttribute.getStyle() | styleAttribute : textAttribute.getStyle() & ~styleAttribute;
+			textAttribute= new TextAttribute(foreground, background, style);
+		}	
+		return textAttribute;
+	}
+	
+	public boolean affectsTextPresentation(PropertyChangeEvent event) {
+		String property = event.getProperty();
+		return property.startsWith(IPDEColorConstants.P_DEFAULT) ||
+			property.startsWith(IPDEColorConstants.P_PROC_INSTR) ||
+			property.startsWith(IPDEColorConstants.P_STRING) || 
+			property.startsWith(IPDEColorConstants.P_TAG) || 
+			property.startsWith(IPDEColorConstants.P_XML_COMMENT);
+	}
+	
+	public boolean affectsColorPresentation(PropertyChangeEvent event) {
+		String property = event.getProperty();
+		return property.equals(IPDEColorConstants.P_DEFAULT) ||
+			property.equals(IPDEColorConstants.P_PROC_INSTR) ||
+			property.equals(IPDEColorConstants.P_STRING) || 
+			property.equals(IPDEColorConstants.P_TAG) || 
+			property.equals(IPDEColorConstants.P_XML_COMMENT);
+	}
+	
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLDoubleClickStrategy.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLDoubleClickStrategy.java
new file mode 100644
index 0000000..7a6d829
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLDoubleClickStrategy.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.text.*;
+
+public class XMLDoubleClickStrategy implements ITextDoubleClickStrategy {
+	protected ITextViewer fText;
+
+	public void doubleClicked(ITextViewer part) {
+		int pos = part.getSelectedRange().x;
+		if (pos > 0) {
+			fText = part;
+			selectWord(pos);
+		}
+	}
+	
+	protected boolean selectWord(int caretPos) {
+
+		IDocument doc = fText.getDocument();
+		int startPos, endPos;
+
+		try {
+
+			int pos = caretPos;
+			char c;
+
+			while (pos >= 0) {
+				c = doc.getChar(pos);
+				if (!Character.isJavaIdentifierPart(c) && c != '.')
+					break;
+				--pos;
+			}
+
+			startPos = pos;
+
+			pos = caretPos;
+			int length = doc.getLength();
+
+			while (pos < length) {
+				c = doc.getChar(pos);
+				if (!Character.isJavaIdentifierPart(c) && c != '.')
+					break;
+				++pos;
+			}
+
+			endPos = pos;
+			selectRange(startPos, endPos);
+			return true;
+
+		} catch (BadLocationException x) {
+		}
+
+		return false;
+	}
+	
+	private void selectRange(int startPos, int stopPos) {
+		int offset = startPos+1;
+		int length = stopPos - offset;
+		fText.setSelectedRange(offset, length);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLSourcePage.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLSourcePage.java
new file mode 100644
index 0000000..bbbd3a1
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/XMLSourcePage.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.reconciler.MonoReconciler;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.pde.internal.ui.PDEUIMessages;
+import org.eclipse.pde.internal.ui.editor.text.ColorManager;
+import org.eclipse.pde.internal.ui.editor.text.IColorManager;
+import org.eclipse.pde.internal.ui.editor.text.IPDEColorConstants;
+import org.eclipse.pde.internal.ui.editor.text.ReconcilingStrategy;
+import org.eclipse.pde.internal.ui.editor.text.XMLConfiguration;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.DefaultRangeIndicator;
+
+public abstract class XMLSourcePage extends PDESourcePage {
+	
+	class XMLSourceViewerConfiguration extends XMLConfiguration {
+		private MonoReconciler fReconciler;
+
+		public XMLSourceViewerConfiguration(IColorManager colorManager) {
+			super(colorManager);
+		}
+		
+		public IReconciler getReconciler(ISourceViewer sourceViewer) {
+			if (fReconciler == null) {
+				IBaseModel model = getInputContext().getModel();
+				if (model instanceof IReconcilingParticipant) {
+					ReconcilingStrategy strategy = new ReconcilingStrategy();
+					strategy.addParticipant((IReconcilingParticipant)model);
+					ISortableContentOutlinePage outline = getContentOutline();
+					if (outline instanceof IReconcilingParticipant)
+						strategy.addParticipant((IReconcilingParticipant)outline);
+					fReconciler = new MonoReconciler(strategy, false);
+					fReconciler.setDelay(500);
+				}
+			}
+			return fReconciler;
+		}
+	}
+	
+	protected IColorManager fColorManager;
+
+	public XMLSourcePage(PDEFormEditor editor, String id, String title) {
+		super(editor, id, title);
+		fColorManager = ColorManager.getDefault();
+		setSourceViewerConfiguration(new XMLSourceViewerConfiguration(fColorManager));
+		setRangeIndicator(new DefaultRangeIndicator());
+	}
+	
+	public void dispose() {
+		super.dispose();
+		fColorManager.dispose();
+	}
+	
+	public boolean canLeaveThePage() {
+		boolean cleanModel = getInputContext().isModelCorrect();
+		if (!cleanModel) {
+			Display.getCurrent().beep();
+			String title = getEditor().getSite().getRegisteredName();
+			MessageDialog.openError(
+				PDEPlugin.getActiveWorkbenchShell(),
+				title,
+				PDEUIMessages.SourcePage_errorMessage);
+		}
+		return cleanModel;
+	}
+
+	protected boolean affectsTextPresentation(PropertyChangeEvent event){
+		String property = event.getProperty();
+		return property.startsWith(IPDEColorConstants.P_DEFAULT) 
+					|| property.startsWith(IPDEColorConstants.P_PROC_INSTR) 
+					|| property.startsWith(IPDEColorConstants.P_STRING) 
+					|| property.startsWith(IPDEColorConstants.P_TAG) 
+					|| property.startsWith(IPDEColorConstants.P_XML_COMMENT);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#handlePreferenceStoreChanged(org.eclipse.jface.util.PropertyChangeEvent)
+	 */
+	protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+		XMLSourceViewerConfiguration sourceViewerConfiguration= (XMLSourceViewerConfiguration)getSourceViewerConfiguration();
+		if (affectsTextPresentation(event)) {
+			sourceViewerConfiguration.adaptToPreferenceChange(event);
+			setSourceViewerConfiguration(sourceViewerConfiguration);
+		}						
+		super.handlePreferenceStoreChanged(event);
+	}
+	
+	protected String[] collectContextMenuPreferencePages() {
+		String[] ids= super.collectContextMenuPreferencePages();
+		String[] more= new String[ids.length + 1];
+		more[0]= "org.eclipse.pde.ui.EditorPreferencePage"; //$NON-NLS-1$
+		System.arraycopy(ids, 0, more, 1, ids.length);
+		return more;
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/DocumentReader.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/DocumentReader.java
new file mode 100644
index 0000000..122ce83
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/DocumentReader.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+
+
+/**
+ * A <code>Reader</code> that reads from an <code>IDocument</code>.
+ * The reader ensures that its content is the same as the document
+ * content when the stream was created.
+ * <p>
+ * Note that {@link #close()} must be called to release any acquired
+ * resources.
+ * </p>
+ *
+ * @since 3.1
+ */
+// copied from same class in org.eclipse.ui.editors.text - no changes
+class DocumentReader extends Reader {
+
+	/**
+	 * Document based character sequence.
+	 */
+	private static class DocumentCharSequence implements CharSequence {
+
+		/** Document */
+		private IDocument fDocument;
+
+		/**
+		 * Initialize with the sequence of characters in the given
+		 * document.
+		 *
+		 * @param document the document
+		 */
+		public DocumentCharSequence(IDocument document) {
+			fDocument= document;
+		}
+
+		/*
+		 * @see java.lang.CharSequence#length()
+		 */
+		public int length() {
+			return fDocument.getLength();
+		}
+
+		/*
+		 * @see java.lang.CharSequence#charAt(int)
+		 */
+		public char charAt(int index) {
+			try {
+				return fDocument.getChar(index);
+			} catch (BadLocationException x) {
+				throw new IndexOutOfBoundsException(x.getLocalizedMessage());
+			}
+		}
+
+		/*
+		 * @see java.lang.CharSequence#subSequence(int, int)
+		 */
+		public CharSequence subSequence(int start, int end) {
+			try {
+				return fDocument.get(start, end - start);
+			} catch (BadLocationException x) {
+				throw new IndexOutOfBoundsException(x.getLocalizedMessage());
+			}
+		}
+	}
+
+	/**
+	 * Internal document listener.
+	 */
+	private class InternalDocumentListener implements IDocumentListener {
+
+		/*
+		 * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+		 */
+		public void documentAboutToBeChanged(DocumentEvent event) {
+			handleDocumentAboutToBeChanged();
+		}
+
+		/*
+		 * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+		 */
+		public void documentChanged(DocumentEvent event) {
+		}
+	}
+
+	/** The character sequence. */
+	private volatile CharSequence fCharSequence;
+
+	/** Document length. */
+	private int fLength;
+
+	/** The current offset. */
+	private int fOffset= 0;
+
+	/** The document. */
+	private IDocument fDocument;
+
+	/** The document listener. */
+	private IDocumentListener fDocumentListener= new InternalDocumentListener();
+
+	/**
+	 * Creates a new document input stream and initializes
+	 * the stream to read from the given document.
+	 *
+	 * @param document the document
+	 */
+	public DocumentReader(IDocument document) {
+		Assert.isNotNull(document);
+		fDocument= document;
+		fCharSequence= new DocumentCharSequence(fDocument);
+		fDocument.addDocumentListener(fDocumentListener);
+		fLength= fCharSequence.length();
+	}
+
+	/*
+	 * @see java.io.InputStream#close()
+	 */
+	public void close() throws IOException {
+		synchronized (this) {
+			fCharSequence= null;
+		}
+		releaseDocument();
+	}
+
+	/**
+	 * Copies the document prior to modification and removes the document listener.
+	 */
+	private void handleDocumentAboutToBeChanged() {
+		IDocument document= fDocument;
+		if (fCharSequence == null || document == null)
+			return;
+		String content= document.get();
+		synchronized (this) {
+			if (fCharSequence == null)
+				return;
+			fCharSequence= content;
+		}
+		releaseDocument();
+	}
+
+	/**
+	 * Removes the document listener.
+	 */
+	private synchronized void releaseDocument() {
+		if (fDocument != null)
+			fDocument.removeDocumentListener(fDocumentListener);
+		fDocument= null;
+		fDocumentListener= null;
+	}
+
+	/*
+	 * @see java.io.Reader#read(char[], int, int)
+	 * @since 3.1
+	 */
+	public int read(char[] cbuf, int off, int len) throws IOException {
+		int i= 0;
+		try {
+			for (; i < len && fOffset < fLength; i++)
+				cbuf[off + i]=  fCharSequence.charAt(fOffset++);
+			if (i > 0)
+				return i;
+
+			return -1;
+		} catch (NullPointerException x) {
+			throw new IOException(TextEditorMessages.DocumentInputStream_error_streamClosed);
+		} catch (IndexOutOfBoundsException x) {
+			return i-1;
+		}
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/FileDocumentProvider.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/FileDocumentProvider.java
new file mode 100644
index 0000000..003c28c
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/FileDocumentProvider.java
@@ -0,0 +1,1182 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.filebuffers.manipulation.ContainerCreator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IResourceRuleFactory;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.content.IContentDescription;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.StorageDocumentProvider;
+import org.eclipse.ui.internal.editors.text.NLSUtility;
+import org.eclipse.ui.internal.editors.text.WorkspaceOperationRunner;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
+import org.eclipse.ui.texteditor.ResourceMarkerAnnotationModel;
+
+
+/**
+ * Shared document provider specialized for file resources (<code>IFile</code>).
+ * <p>
+ * This class may be instantiated or be subclassed.</p>
+ */
+// copied from same class in org.eclipse.ui.editors.text 
+// as part of the fix for 86467 - changes marked // AspectJ Change
+public class FileDocumentProvider extends StorageDocumentProvider {
+
+	/**
+	 * Qualified name for the encoding key.
+	 *
+	 * @since 2.1
+	 */
+	private static final QualifiedName ENCODING_KEY = new QualifiedName(EditorsUI.PLUGIN_ID, "encoding"); //$NON-NLS-1$
+	/**
+	 * Constant denoting UTF-8 encoding.
+	 * @since 3.0
+	 */
+	private static final String CHARSET_UTF_8= "UTF-8"; //$NON-NLS-1$
+
+
+	/**
+	 * The runnable context for that provider.
+	 * @since 3.0
+	 */
+	private WorkspaceOperationRunner fOperationRunner;
+	/**
+	 * The scheduling rule factory.
+	 * @since 3.0
+	 */
+	private IResourceRuleFactory fResourceRuleFactory;
+
+	/**
+	 * Runnable encapsulating an element state change. This runnable ensures
+	 * that a element change failed message is sent out to the element state listeners
+	 * in case an exception occurred.
+	 *
+	 * @since 2.0
+	 */
+	protected class SafeChange implements Runnable {
+
+		/** The input that changes. */
+		private IFileEditorInput fInput;
+
+		/**
+		 * Creates a new safe runnable for the given input.
+		 *
+		 * @param input the input
+		 */
+		public SafeChange(IFileEditorInput input) {
+			fInput= input;
+		}
+
+		/**
+		 * Execute the change.
+		 * Subclass responsibility.
+		 *
+		 * @param input the input
+		 * @throws Exception an exception in case of error
+		 */
+		protected void execute(IFileEditorInput input) throws Exception {
+		}
+
+		/*
+		 * @see java.lang.Runnable#run()
+		 */
+		public void run() {
+
+			if (getElementInfo(fInput) == null) {
+				fireElementStateChangeFailed(fInput);
+				return;
+			}
+
+			try {
+				execute(fInput);
+			} catch (Exception e) {
+				fireElementStateChangeFailed(fInput);
+			}
+		}
+	}
+
+
+	/**
+	 * Synchronizes the document with external resource changes.
+	 */
+	protected class FileSynchronizer implements IResourceChangeListener, IResourceDeltaVisitor {
+
+		/** The file editor input. */
+		protected IFileEditorInput fFileEditorInput;
+		/**
+		 * A flag indicating whether this synchronizer is installed or not.
+		 *
+		 * @since 2.1
+		 */
+		protected boolean fIsInstalled= false;
+
+		/**
+		 * Creates a new file synchronizer. Is not yet installed on a resource.
+		 *
+		 * @param fileEditorInput the editor input to be synchronized
+		 */
+		public FileSynchronizer(IFileEditorInput fileEditorInput) {
+			fFileEditorInput= fileEditorInput;
+		}
+
+		/**
+		 * Creates a new file synchronizer which is not yet installed on a resource.
+		 *
+		 * @param fileEditorInput the editor input to be synchronized
+		 * @deprecated use <code>FileSynchronizer(IFileEditorInput)</code>
+		 */
+		public FileSynchronizer(FileEditorInput fileEditorInput) {
+			fFileEditorInput= fileEditorInput;
+		}
+
+		/**
+		 * Returns the file wrapped by the file editor input.
+		 *
+		 * @return the file wrapped by the editor input associated with that synchronizer
+		 */
+		protected IFile getFile() {
+			return fFileEditorInput.getFile();
+		}
+
+		/**
+		 * Installs the synchronizer on the input's file.
+		 */
+		public void install() {
+			getFile().getWorkspace().addResourceChangeListener(this);
+			fIsInstalled= true;
+		}
+
+		/**
+		 * Uninstalls the synchronizer from the input's file.
+		 */
+		public void uninstall() {
+			getFile().getWorkspace().removeResourceChangeListener(this);
+			fIsInstalled= false;
+		}
+
+		/*
+		 * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
+		 */
+		public void resourceChanged(IResourceChangeEvent e) {
+			IResourceDelta delta= e.getDelta();
+			try {
+				if (delta != null && fIsInstalled)
+					delta.accept(this);
+			} catch (CoreException x) {
+				handleCoreException(x, "FileDocumentProvider.resourceChanged"); //$NON-NLS-1$
+			}
+		}
+
+		/*
+		 * @see IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta)
+		 */
+		public boolean visit(IResourceDelta delta) throws CoreException {
+			if (delta == null)
+				return false;
+
+			delta= delta.findMember(getFile().getFullPath());
+
+			if (delta == null)
+				return false;
+
+			Runnable runnable= null;
+
+			switch (delta.getKind()) {
+				case IResourceDelta.CHANGED:
+					FileInfo info= (FileInfo) getElementInfo(fFileEditorInput);
+					if (info == null || info.fCanBeSaved)
+						break;
+
+					boolean isSynchronized= computeModificationStamp(getFile()) == info.fModificationStamp;
+					if ((IResourceDelta.ENCODING & delta.getFlags()) != 0 && isSynchronized) {
+						runnable= new SafeChange(fFileEditorInput) {
+							protected void execute(IFileEditorInput input) throws Exception {
+								handleElementContentChanged(input);
+							}
+						};
+					}
+					// AspectJ Change
+					if ((IResourceDelta.CONTENT & delta.getFlags()) != 0 && !isSynchronized) {
+						runnable= new SafeChange(fFileEditorInput) {
+							protected void execute(IFileEditorInput input) throws Exception {
+								handleElementContentChanged(input);
+							}
+						};
+					}
+					break;
+
+				case IResourceDelta.REMOVED:
+					if ((IResourceDelta.MOVED_TO & delta.getFlags()) != 0) {
+						final IPath path= delta.getMovedToPath();
+						runnable= new SafeChange(fFileEditorInput) {
+							protected void execute(IFileEditorInput input) throws Exception {
+								handleElementMoved(input, path);
+							}
+						};
+					} else {
+						info= (FileInfo) getElementInfo(fFileEditorInput);
+						if (info != null && !info.fCanBeSaved) {
+							runnable= new SafeChange(fFileEditorInput) {
+								protected void execute(IFileEditorInput input) throws Exception {
+									handleElementDeleted(input);
+								}
+							};
+						}
+					}
+					break;
+			}
+
+			if (runnable != null)
+				update(runnable);
+
+			return false;
+		}
+
+		/**
+		 * Posts the update code "behind" the running operation.
+		 *
+		 * @param runnable the update code
+		 */
+		protected void update(Runnable runnable) {
+
+			if (runnable instanceof SafeChange)
+				fireElementStateChanging(fFileEditorInput);
+
+			IWorkbench workbench= PlatformUI.getWorkbench();
+			IWorkbenchWindow[] windows= workbench.getWorkbenchWindows();
+			if (windows != null && windows.length > 0) {
+				Display display= windows[0].getShell().getDisplay();
+				display.asyncExec(runnable);
+			} else {
+				runnable.run();
+			}
+		}
+	}
+
+
+
+	/**
+	 * Bundle of all required information to allow files as underlying document resources.
+	 */
+	protected class FileInfo extends StorageInfo {
+
+		/** The file synchronizer. */
+		public FileSynchronizer fFileSynchronizer;
+		/** The time stamp at which this provider changed the file. */
+		public long fModificationStamp= IResource.NULL_STAMP;
+		/**
+		 * Tells whether the file on disk has a BOM.
+		 */
+		private boolean fHasBOM;
+
+		/**
+		 * Creates and returns a new file info.
+		 *
+		 * @param document the document
+		 * @param model the annotation model
+		 * @param fileSynchronizer the file synchronizer
+		 */
+		public FileInfo(IDocument document, IAnnotationModel model, FileSynchronizer fileSynchronizer) {
+			super(document, model);
+			fFileSynchronizer= fileSynchronizer;
+		}
+	}
+
+
+	/**
+	 * Creates and returns a new document provider.
+	 */
+	public FileDocumentProvider() {
+		super();
+		fResourceRuleFactory= ResourcesPlugin.getWorkspace().getRuleFactory();
+	}
+
+	/**
+	 * Overrides <code>StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput)</code>.
+	 *
+	 * @see StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput)
+	 * @deprecated use file encoding based version
+	 * @since 2.0
+	 */
+	protected boolean setDocumentContent(IDocument document, IEditorInput editorInput) throws CoreException {
+		if (editorInput instanceof IFileEditorInput) {
+			IFile file= ((IFileEditorInput) editorInput).getFile();
+			InputStream stream= file.getContents(false);
+			try {
+				setDocumentContent(document, stream);
+			} finally {
+				try {
+					stream.close();
+				} catch (IOException x) {
+				}
+			}
+			return true;
+		}
+		return super.setDocumentContent(document, editorInput);
+	}
+
+	/*
+	 * @see StorageDocumentProvider#setDocumentContent(IDocument, IEditorInput, String)
+	 * @since 2.0
+	 */
+	protected boolean setDocumentContent(IDocument document, IEditorInput editorInput, String encoding) throws CoreException {
+		if (editorInput instanceof IFileEditorInput) {
+			IFile file= ((IFileEditorInput) editorInput).getFile();
+			// AspectJ Change - stop errors in the log when a new project is created
+			if(file.exists()) {
+				InputStream contentStream= file.getContents(false);
+				try {
+	
+					FileInfo info= (FileInfo)getElementInfo(editorInput);
+	
+					/*
+					 * XXX:
+					 * This is a workaround for a corresponding bug in Java readers and writer,
+					 * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+					 */
+					if (info != null && info.fHasBOM && CHARSET_UTF_8.equals(encoding)) {
+						int n= 0;
+						do {
+							int bytes= contentStream.read(new byte[IContentDescription.BOM_UTF_8.length]);
+							if (bytes == -1)
+								throw new IOException();
+							n += bytes;
+						} while (n < IContentDescription.BOM_UTF_8.length);
+					}
+	
+					setDocumentContent(document, contentStream, encoding);
+	
+				} catch (IOException ex) {
+					String message= (ex.getMessage() != null ? ex.getMessage() : ""); //$NON-NLS-1$
+					IStatus s= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, message, ex);
+					throw new CoreException(s);
+				} finally {
+					try {
+						contentStream.close();
+					} catch (IOException e1) {
+					}
+				}
+			}
+			return true;
+		}
+		return super.setDocumentContent(document, editorInput, encoding);
+	}
+
+	/*
+	 * @see AbstractDocumentProvider#createAnnotationModel(Object)
+	 */
+	protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			return new ResourceMarkerAnnotationModel(input.getFile());
+		}
+
+		return super.createAnnotationModel(element);
+	}
+
+	/**
+	 * Checks whether the given resource has been changed on the
+	 * local file system by comparing the actual time stamp with the
+	 * cached one. If the resource has been changed, a <code>CoreException</code>
+	 * is thrown.
+	 *
+	 * @param cachedModificationStamp the cached modification stamp
+	 * @param resource the resource to check
+	 * @throws org.eclipse.core.runtime.CoreException if resource has been changed on the file system
+	 */
+	protected void checkSynchronizationState(long cachedModificationStamp, IResource resource) throws CoreException {
+		if (cachedModificationStamp != computeModificationStamp(resource)) {
+			Status status= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IResourceStatus.OUT_OF_SYNC_LOCAL, TextEditorMessages.FileDocumentProvider_error_out_of_sync, null);
+			throw new CoreException(status);
+		}
+	}
+
+	/**
+	 * Computes the initial modification stamp for the given resource.
+	 *
+	 * @param resource the resource
+	 * @return the modification stamp
+	 */
+	protected long computeModificationStamp(IResource resource) {
+		long modificationStamp= resource.getModificationStamp();
+
+		IPath path= resource.getLocation();
+		if (path == null)
+			return modificationStamp;
+
+		modificationStamp= path.toFile().lastModified();
+		return modificationStamp;
+	}
+
+	/*
+	 * @see IDocumentProvider#getModificationStamp(Object)
+	 */
+	public long getModificationStamp(Object element) {
+
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			return computeModificationStamp(input.getFile());
+		}
+
+		return super.getModificationStamp(element);
+	}
+
+	/*
+	 * @see IDocumentProvider#getSynchronizationStamp(Object)
+	 */
+	public long getSynchronizationStamp(Object element) {
+
+		if (element instanceof IFileEditorInput) {
+			FileInfo info= (FileInfo) getElementInfo(element);
+			if (info != null)
+				return info.fModificationStamp;
+		}
+
+		return super.getSynchronizationStamp(element);
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doSynchronize(java.lang.Object)
+	 * @since 3.0
+	 */
+	protected void doSynchronize(Object element, IProgressMonitor monitor)  throws CoreException {
+		if (element instanceof IFileEditorInput) {
+
+			IFileEditorInput input= (IFileEditorInput) element;
+
+			FileInfo info= (FileInfo) getElementInfo(element);
+			if (info != null) {
+
+				if (info.fFileSynchronizer != null) {
+					info.fFileSynchronizer.uninstall();
+					refreshFile(input.getFile(), monitor);
+					info.fFileSynchronizer.install();
+				} else {
+					refreshFile(input.getFile(), monitor);
+				}
+
+				handleElementContentChanged((IFileEditorInput) element);
+			}
+			return;
+
+		}
+		super.doSynchronize(element, monitor);
+	}
+
+	/*
+	 * @see IDocumentProvider#isDeleted(Object)
+	 */
+	public boolean isDeleted(Object element) {
+
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+
+			IPath path= input.getFile().getLocation();
+			if (path == null)
+				return true;
+
+			return !path.toFile().exists();
+		}
+
+		return super.isDeleted(element);
+	}
+
+	/*
+	 * @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument, boolean)
+	 */
+	protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
+		if (element instanceof IFileEditorInput) {
+
+			IFileEditorInput input= (IFileEditorInput) element;
+			String encoding= null;
+			try {
+				FileInfo info= (FileInfo) getElementInfo(element);
+				IFile file= input.getFile();
+				encoding= getCharsetForNewFile(file, document, info);
+
+				byte[] bytes= document.get().getBytes(encoding);
+
+				/*
+				 * XXX:
+				 * This is a workaround for a corresponding bug in Java readers and writer,
+				 * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+				 */
+				if (info != null && info.fHasBOM && CHARSET_UTF_8.equals(encoding)) {
+					int bomLength= IContentDescription.BOM_UTF_8.length;
+					byte[] bytesWithBOM= new byte[bytes.length + bomLength];
+					System.arraycopy(IContentDescription.BOM_UTF_8, 0, bytesWithBOM, 0, bomLength);
+					System.arraycopy(bytes, 0, bytesWithBOM, bomLength, bytes.length);
+					bytes= bytesWithBOM;
+				}
+
+				InputStream stream= new ByteArrayInputStream(bytes);
+
+				if (file.exists()) {
+
+					if (info != null && !overwrite)
+						checkSynchronizationState(info.fModificationStamp, file);
+
+					// inform about the upcoming content change
+					fireElementStateChanging(element);
+					try {
+						file.setContents(stream, overwrite, true, monitor);
+					} catch (CoreException x) {
+						// inform about failure
+						fireElementStateChangeFailed(element);
+						throw x;
+					} catch (RuntimeException x) {
+						// inform about failure
+						fireElementStateChangeFailed(element);
+						throw x;
+					}
+
+					// If here, the editor state will be flipped to "not dirty".
+					// Thus, the state changing flag will be reset.
+
+					if (info != null) {
+
+						ResourceMarkerAnnotationModel model= (ResourceMarkerAnnotationModel) info.fModel;
+						model.updateMarkers(info.fDocument);
+
+						info.fModificationStamp= computeModificationStamp(file);
+					}
+
+				} else {
+					try {
+						monitor.beginTask(TextEditorMessages.FileDocumentProvider_task_saving, 2000);
+						ContainerCreator creator = new ContainerCreator(file.getWorkspace(), file.getParent().getFullPath());
+						creator.createContainer(new SubProgressMonitor(monitor, 1000));
+						file.create(stream, false, new SubProgressMonitor(monitor, 1000));
+					}
+					finally {
+						monitor.done();
+					}
+				}
+
+			} catch (UnsupportedEncodingException x) {
+				String message= NLSUtility.format(TextEditorMessages.Editor_error_unsupported_encoding_message_arg, encoding);
+				IStatus s= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, message, x);
+				throw new CoreException(s);
+			}
+
+		} else {
+			super.doSaveDocument(monitor, element, document, overwrite);
+		}
+	}
+
+	/*
+	 * @since 3.0
+	 */
+	private String getCharsetForNewFile(IFile targetFile, IDocument document, FileInfo info) {
+		// User-defined encoding has first priority
+		String encoding;
+		try {
+			encoding= targetFile.getCharset(false);
+		} catch (CoreException ex) {
+			encoding= null;
+		}
+		if (encoding != null)
+			return encoding;
+
+		// Probe content
+		Reader reader= new DocumentReader(document);
+		try {
+			QualifiedName[] options= new QualifiedName[] { IContentDescription.CHARSET, IContentDescription.BYTE_ORDER_MARK };
+			IContentDescription description= Platform.getContentTypeManager().getDescriptionFor(reader, targetFile.getName(), options);
+			if (description != null) {
+				encoding= description.getCharset();
+				if (encoding != null)
+					return encoding;
+			}
+		} catch (IOException ex) {
+			// continue with next strategy
+		} finally {
+			try {
+				if (reader != null)
+					reader.close();
+			} catch (IOException x) {
+			}
+		}
+
+		// Use file's encoding if the file has a BOM
+		if (info != null && info.fHasBOM)
+			return info.fEncoding;
+
+		// Use parent chain
+		try {
+			return targetFile.getParent().getDefaultCharset();
+		} catch (CoreException ex) {
+			// Use global default
+			return ResourcesPlugin.getEncoding();
+		}
+	}
+
+	/*
+	 * @see AbstractDocumentProvider#createElementInfo(Object)
+	 */
+	protected ElementInfo createElementInfo(Object element) throws CoreException {
+		if (element instanceof IFileEditorInput) {
+
+			IFileEditorInput input= (IFileEditorInput) element;
+
+			try {
+				refreshFile(input.getFile());
+			} catch (CoreException x) {
+				handleCoreException(x, TextEditorMessages.FileDocumentProvider_createElementInfo);
+			}
+
+			IDocument d= null;
+			IStatus s= null;
+
+			try {
+				d= createDocument(element);
+			} catch (CoreException x) {
+				handleCoreException(x, TextEditorMessages.FileDocumentProvider_createElementInfo);
+				s= x.getStatus();
+				d= createEmptyDocument();
+			}
+			
+			// Set the initial line delimiter
+			if (d instanceof IDocumentExtension4) {
+				String initalLineDelimiter= getLineDelimiterPreference(input.getFile()); 
+				if (initalLineDelimiter != null)
+					((IDocumentExtension4)d).setInitialLineDelimiter(initalLineDelimiter);
+			}
+
+			IAnnotationModel m= createAnnotationModel(element);
+			FileSynchronizer f= new FileSynchronizer(input);
+			f.install();
+
+			FileInfo info= new FileInfo(d, m, f);
+			info.fModificationStamp= computeModificationStamp(input.getFile());
+			info.fStatus= s;
+			cacheEncodingState(element);
+
+			return info;
+		}
+
+		return super.createElementInfo(element);
+	}
+	
+	/**
+	 * Returns the default line delimiter preference for the given file.
+	 * 
+	 * @param file the file 
+	 * @return the default line delimiter
+	 * @since 3.1
+	 */
+	private String getLineDelimiterPreference(IFile file) {
+		IScopeContext[] scopeContext;
+		if (file != null && file.getProject() != null) {
+			// project preference
+			scopeContext= new IScopeContext[] { new ProjectScope(file.getProject()) };
+			String lineDelimiter= Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+			if (lineDelimiter != null)
+				return lineDelimiter;
+		}
+		// workspace preference
+		scopeContext= new IScopeContext[] { new InstanceScope() };
+		return Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
+	}
+
+	/*
+	 * @see AbstractDocumentProvider#disposeElementInfo(Object, ElementInfo)
+	 */
+	protected void disposeElementInfo(Object element, ElementInfo info) {
+		if (info instanceof FileInfo) {
+			FileInfo fileInfo= (FileInfo) info;
+			if (fileInfo.fFileSynchronizer != null)
+				fileInfo.fFileSynchronizer.uninstall();
+		}
+
+		super.disposeElementInfo(element, info);
+	}
+
+	/**
+	 * Updates the element info to a change of the file content and sends out
+	 * appropriate notifications.
+	 *
+	 * @param fileEditorInput the input of an text editor
+	 */
+	protected void handleElementContentChanged(IFileEditorInput fileEditorInput) {
+		FileInfo info= (FileInfo) getElementInfo(fileEditorInput);
+		if (info == null)
+			return;
+
+		IDocument document= createEmptyDocument();
+		IStatus status= null;
+
+		try {
+
+			try {
+				refreshFile(fileEditorInput.getFile());
+			} catch (CoreException x) {
+				handleCoreException(x, "FileDocumentProvider.handleElementContentChanged"); //$NON-NLS-1$
+			}
+
+			cacheEncodingState(fileEditorInput);
+			setDocumentContent(document, fileEditorInput, info.fEncoding);
+
+		} catch (CoreException x) {
+			status= x.getStatus();
+		}
+
+		String newContent= document.get();
+
+		if ( !newContent.equals(info.fDocument.get())) {
+
+			// set the new content and fire content related events
+			fireElementContentAboutToBeReplaced(fileEditorInput);
+
+			removeUnchangedElementListeners(fileEditorInput, info);
+
+			info.fDocument.removeDocumentListener(info);
+			info.fDocument.set(newContent);
+			info.fCanBeSaved= false;
+			info.fModificationStamp= computeModificationStamp(fileEditorInput.getFile());
+			info.fStatus= status;
+
+			addUnchangedElementListeners(fileEditorInput, info);
+
+			fireElementContentReplaced(fileEditorInput);
+
+		} else {
+
+			removeUnchangedElementListeners(fileEditorInput, info);
+
+			// fires only the dirty state related event
+			info.fCanBeSaved= false;
+			info.fModificationStamp= computeModificationStamp(fileEditorInput.getFile());
+			info.fStatus= status;
+
+			addUnchangedElementListeners(fileEditorInput, info);
+
+			fireElementDirtyStateChanged(fileEditorInput, false);
+		}
+	}
+
+	/**
+	 * Sends out the notification that the file serving as document input has been moved.
+	 *
+	 * @param fileEditorInput the input of an text editor
+	 * @param path the path of the new location of the file
+	 */
+	protected void handleElementMoved(IFileEditorInput fileEditorInput, IPath path) {
+		IWorkspace workspace= ResourcesPlugin.getWorkspace();
+		IFile newFile= workspace.getRoot().getFile(path);
+		fireElementMoved(fileEditorInput, newFile == null ? null : new FileEditorInput(newFile));
+	}
+
+	/**
+	 * Sends out the notification that the file serving as document input has been deleted.
+	 *
+	 * @param fileEditorInput the input of an text editor
+	 */
+	protected void handleElementDeleted(IFileEditorInput fileEditorInput) {
+		fireElementDeleted(fileEditorInput);
+	}
+
+	/*
+	 * @see AbstractDocumentProvider#getElementInfo(Object)
+	 * It's only here to circumvent visibility issues with certain compilers.
+	 */
+	protected ElementInfo getElementInfo(Object element) {
+		return super.getElementInfo(element);
+	}
+
+	/*
+	 * @see AbstractDocumentProvider#doValidateState(Object, Object)
+	 * @since 2.0
+	 */
+	protected void doValidateState(Object element, Object computationContext) throws CoreException {
+
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			FileInfo info= (FileInfo) getElementInfo(input);
+			if (info != null) {
+				IFile file= input.getFile();
+				if (file.isReadOnly()) { // do not use cached state here
+					IWorkspace workspace= file.getWorkspace();
+					workspace.validateEdit(new IFile[] { file }, computationContext);
+				}
+			}
+		}
+
+		super.doValidateState(element, computationContext);
+	}
+
+	/*
+	 * @see IDocumentProviderExtension#isModifiable(Object)
+	 * @since 2.0
+	 */
+	public boolean isModifiable(Object element) {
+		if (!isStateValidated(element)) {
+			if (element instanceof IFileEditorInput)
+				return true;
+		}
+		return super.isModifiable(element);
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#doResetDocument(java.lang.Object, org.eclipse.core.runtime.IProgressMonitor)
+	 * @since 3.0
+	 */
+	protected void doResetDocument(Object element, IProgressMonitor monitor) throws CoreException {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			try {
+				refreshFile(input.getFile(), monitor);
+				cacheEncodingState(element);
+			} catch (CoreException x) {
+				handleCoreException(x,TextEditorMessages.FileDocumentProvider_resetDocument);
+			}
+		}
+
+		super.doResetDocument(element, monitor);
+
+		IAnnotationModel model= getAnnotationModel(element);
+		if (model instanceof AbstractMarkerAnnotationModel) {
+			AbstractMarkerAnnotationModel markerModel= (AbstractMarkerAnnotationModel) model;
+			markerModel.resetMarkers();
+		}
+	}
+
+	/**
+	 * Refreshes the given file resource.
+	 *
+	 * @param file
+	 * @throws CoreException if the refresh fails
+	 * @since 2.1
+	 */
+	protected void refreshFile(IFile file) throws CoreException {
+		refreshFile(file, getProgressMonitor());
+	}
+
+	/**
+	 * Refreshes the given file resource.
+	 *
+	 * @param file the file to be refreshed
+	 * @param monitor the progress monitor
+	 * @throws  org.eclipse.core.runtime.CoreException if the refresh fails
+	 * @since 3.0
+	 */
+	protected void refreshFile(IFile file, IProgressMonitor monitor) throws CoreException {
+		try {
+			file.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+		} catch (OperationCanceledException x) {
+		}
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.IDocumentProviderExtension3#isSynchronized(java.lang.Object)
+	 * @since 3.0
+	 */
+	public boolean isSynchronized(Object element) {
+		if (element instanceof IFileEditorInput) {
+			if (getElementInfo(element) != null) {
+				IFileEditorInput input= (IFileEditorInput) element;
+				IResource resource= input.getFile();
+				return resource.isSynchronized(IResource.DEPTH_ZERO);
+			}
+			return false;
+		}
+		return super.isSynchronized(element);
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.IDocumentProviderExtension4#getContentType(java.lang.Object)
+	 * @since 3.1
+	 */
+	public IContentType getContentType(Object element) throws CoreException {
+		IContentType contentType= null;
+		if (!canSaveDocument(element) && element instanceof IFileEditorInput)
+			contentType= getContentType((IFileEditorInput) element);
+
+		if (contentType == null)
+			contentType= super.getContentType(element);
+
+		if (contentType == null && element instanceof IFileEditorInput)
+			contentType= getContentType((IFileEditorInput) element);
+
+		return contentType;
+	}
+
+	/**
+	 * Returns the content type of for the given file editor input or
+	 * <code>null</code> if none could be determined.
+	 *
+	 * @param input the element
+	 * @return the content type or <code>null</code>
+	 * @throws CoreException if reading or accessing the underlying store
+	 *                 fails
+	 * @since 3.1
+	 */
+	private IContentType getContentType(IFileEditorInput input) throws CoreException {
+		IContentDescription desc= input.getFile().getContentDescription();
+		if (desc != null)
+			return desc.getContentType();
+		return null;
+	}
+
+	// --------------- Encoding support ---------------
+
+	/**
+	 * Returns the persisted encoding for the given element.
+	 *
+	 * @param element the element for which to get the persisted encoding
+	 * @return the persisted encoding
+	 * @since 2.1
+	 */
+	protected String getPersistedEncoding(Object element) {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput editorInput= (IFileEditorInput)element;
+			IFile file= editorInput.getFile();
+			// AspectJ Change - check file exists
+			if (file != null && file.exists()) {
+				String encoding= null;
+				try {
+					encoding= file.getPersistentProperty(ENCODING_KEY);
+				} catch (CoreException x) {
+					// we ignore exceptions here because we support the ENCODING_KEY property only for compatibility reasons
+				}
+				if (encoding != null) {
+					// if we found an old encoding property, we try to migrate it to the new core.resources encoding support
+					try {
+						file.setCharset(encoding, getProgressMonitor());
+						// if successful delete old property
+						file.setPersistentProperty(ENCODING_KEY, null);
+					} catch (CoreException ex) {
+						handleCoreException(ex, TextEditorMessages.FileDocumentProvider_getPersistedEncoding);
+					}
+				} else {
+					try {
+						encoding= file.getCharset();
+					} catch (CoreException e) {
+						encoding= null;
+					}
+				}
+				return encoding;
+			}
+		}
+		return super.getPersistedEncoding(element);
+	}
+
+	/**
+	 * Persists the given encoding for the given element.
+	 *
+	 * @param element the element for which to store the persisted encoding
+	 * @param encoding the encoding
+	 * @throws org.eclipse.core.runtime.CoreException if persisting the encoding fails
+	 * @since 2.1
+	 */
+	protected void persistEncoding(Object element, String encoding) throws CoreException {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput editorInput= (IFileEditorInput)element;
+			IFile file= editorInput.getFile();
+			if (file != null) {
+				file.setCharset(encoding, getProgressMonitor());
+				StorageInfo info= (StorageInfo)getElementInfo(element);
+				if (info != null) {
+					if (encoding == null)
+						info.fEncoding= file.getCharset();
+					if (info instanceof FileInfo)
+						((FileInfo)info).fHasBOM= hasBOM(element);
+				}
+			}
+		}
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getOperationRunner(org.eclipse.core.runtime.IProgressMonitor)
+	 * @since 3.0
+	 */
+	protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
+		if (fOperationRunner == null)
+			fOperationRunner = new WorkspaceOperationRunner();
+		fOperationRunner.setProgressMonitor(monitor);
+		return fOperationRunner;
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getResetRule(java.lang.Object)
+	 * @since 3.0
+	 */
+	protected ISchedulingRule getResetRule(Object element) {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			return fResourceRuleFactory.modifyRule(input.getFile());
+		}
+		return null;
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getSaveRule(java.lang.Object)
+	 * @since 3.0
+	 */
+	protected ISchedulingRule getSaveRule(Object element) {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			return computeSchedulingRule(input.getFile());
+		}
+		return null;
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getSynchronizeRule(java.lang.Object)
+	 * @since 3.0
+	 */
+	protected ISchedulingRule getSynchronizeRule(Object element) {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			return fResourceRuleFactory.refreshRule(input.getFile());
+		}
+		return null;
+	}
+
+	/*
+	 * @see org.eclipse.ui.texteditor.AbstractDocumentProvider#getValidateStateRule(java.lang.Object)
+	 * @since 3.0
+	 */
+	protected ISchedulingRule getValidateStateRule(Object element) {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput input= (IFileEditorInput) element;
+			return fResourceRuleFactory.validateEditRule(new IResource[] { input.getFile() });
+		}
+		return null;
+	}
+
+	/**
+	 * Returns whether the underlying file has a BOM.
+	 *
+	 * @param element the element, or <code>null</code>
+	 * @return <code>true</code> if the underlying file has BOM
+	 */
+	private boolean hasBOM(Object element) {
+		if (element instanceof IFileEditorInput) {
+			IFile file= ((IFileEditorInput)element).getFile();
+			if (file != null) {
+				try {
+					IContentDescription description= file.getContentDescription();
+					return  description != null && description.getProperty(IContentDescription.BYTE_ORDER_MARK) != null;
+				} catch (CoreException ex) {
+					return false;
+				}
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Reads the file's UTF-8 BOM if any and stores it.
+	 * <p>
+	 * XXX:
+	 * This is a workaround for a corresponding bug in Java readers and writer,
+	 * see: http://developer.java.sun.com/developer/bugParade/bugs/4508058.html
+	 * </p>
+	 * @param file the file
+	 * @param encoding the encoding
+	 * @param element the element, or <code>null</code>
+	 * @throws org.eclipse.core.runtime.CoreException if reading the BOM fails
+	 * @since 3.0
+	 * @deprecated as of 3.0 this method is no longer in use and does nothing
+	 */
+	protected void readUTF8BOM(IFile file, String encoding, Object element) throws CoreException {
+	}
+
+	/**
+	 * Internally caches the file's encoding data.
+	 *
+	 * @param element the element, or <code>null</code>
+	 * @throws CoreException if the encoding cannot be retrieved
+	 * @since 3.1
+	 */
+	protected void cacheEncodingState(Object element) throws CoreException {
+		if (element instanceof IFileEditorInput) {
+			IFileEditorInput editorInput= (IFileEditorInput)element;
+			IFile file= editorInput.getFile();
+			if (file != null) {
+				ElementInfo info= getElementInfo(element);
+				if (info instanceof StorageInfo)
+					((StorageInfo)info).fEncoding= getPersistedEncoding(element);
+
+				if (info instanceof FileInfo)
+					((FileInfo)info).fHasBOM= hasBOM(element);
+			}
+		}
+	}
+
+	/**
+	 * Computes the scheduling rule needed to create or modify a resource. If
+	 * the resource exists, its modify rule is returned. If it does not, the
+	 * resource hierarchy is iterated towards the workspace root to find the
+	 * first parent of <code>toCreateOrModify</code> that exists. Then the
+	 * 'create' rule for the last non-existing resource is returned.
+	 *
+	 * @param toCreateOrModify the resource to create or modify
+	 * @return the minimal scheduling rule needed to modify or create a resource
+	 */
+	private ISchedulingRule computeSchedulingRule(IResource toCreateOrModify) {
+		if (toCreateOrModify.exists())
+			return fResourceRuleFactory.modifyRule(toCreateOrModify);
+
+		IResource parent= toCreateOrModify;
+		do {
+			 /*
+			 * XXX This is a workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=67601
+			 * IResourceRuleFactory.createRule should iterate the hierarchy itself.
+			 */
+			toCreateOrModify= parent;
+			parent= toCreateOrModify.getParent();
+		} while (parent != null && !parent.exists());
+
+		return fResourceRuleFactory.createRule(toCreateOrModify);
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/IInputContextListener.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/IInputContextListener.java
new file mode 100755
index 0000000..7e584aa
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/IInputContextListener.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import org.eclipse.core.resources.IFile;
+
+public interface IInputContextListener {
+/**
+ * Informs the listener that a new context has been added.
+ * This should result in a new source tab.
+ * @param context
+ */
+	void contextAdded(InputContext context);
+/**
+ * Informs the listener that the context has been removed.
+ * This should result in removing the source tab.
+ * @param context
+ */
+	void contextRemoved(InputContext context);
+/**
+ * Informs the listener that a monitored file has
+ * been added.
+ * @param monitoredFile the file we were monitoring
+ */
+	void monitoredFileAdded(IFile monitoredFile);
+/**
+ * Informs the listener that a monitored file has
+ * been removed.
+ * @param monitoredFile
+ * @return <code>true</code> if it is OK to remove
+ * the associated context, <code>false</code> otherwise.
+ */
+	boolean monitoredFileRemoved(IFile monitoredFile);
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContext.java
new file mode 100755
index 0000000..4c1e042
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContext.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+import java.util.ArrayList;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ajdt.pde.internal.ui.editor.StorageDocumentProvider;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileDocumentProvider;
+import org.eclipse.ajdt.pde.internal.ui.editor.SystemFileEditorInput;
+import org.eclipse.core.filebuffers.*;
+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.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IEditable;
+import org.eclipse.pde.core.IModelChangeProvider;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.core.IModelChangedListener;
+import org.eclipse.pde.internal.core.text.IEditingModel;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.MoveSourceEdit;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.editors.text.*;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.IElementStateListener;
+/**
+ * This class maintains objects associated with a single editor input.
+ */
+/*
+ * Changes marked // AspectJ change
+ */
+public abstract class InputContext {
+	
+	private PDEFormEditor fEditor;
+	private IEditorInput fEditorInput;
+	private IBaseModel fModel;
+	private IModelChangedListener fModelListener;
+	private IDocumentProvider fDocumentProvider;
+	private IElementStateListener fElementListener;
+	protected ArrayList fEditOperations = new ArrayList();
+	
+	private boolean fValidated;
+	private boolean fPrimary;
+	private boolean fIsSourceMode;
+	private boolean fMustSynchronize;
+
+	class ElementListener implements IElementStateListener {
+		public void elementContentAboutToBeReplaced(Object element) {
+		}
+		public void elementContentReplaced(Object element) {
+			doRevert();
+		}
+		public void elementDeleted(Object element) {
+            dispose();
+		}
+		public void elementDirtyStateChanged(Object element, boolean isDirty) {
+			fMustSynchronize=true;
+		}
+		public void elementMoved(Object originalElement, Object movedElement) {
+            dispose();
+			fEditor.close(true);
+		}
+	}
+	public InputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+		this.fEditor = editor;
+		this.fEditorInput = input;
+		setPrimary(primary);
+	}
+	public abstract String getId();
+
+	public IEditorInput getInput() {
+		return fEditorInput;
+	}
+	public PDEFormEditor getEditor() {
+		return fEditor;
+	}
+	public IBaseModel getModel() {
+		return fModel;
+	}
+	public IDocumentProvider getDocumentProvider() {
+		return fDocumentProvider;
+	}
+	private IDocumentProvider createDocumentProvider(IEditorInput input) {
+		if (input instanceof IFileEditorInput) {
+			return createFileDocumentProvider();
+		} else if (input instanceof SystemFileEditorInput) {
+			return new SystemFileDocumentProvider(createDocumentPartitioner(), getDefaultCharset());
+		} else if (input instanceof IStorageEditorInput) {
+			return new StorageDocumentProvider(createDocumentPartitioner(), getDefaultCharset());
+		}
+		return null;
+	}
+	
+	private IDocumentProvider createFileDocumentProvider() {
+		// AspectJ change begin
+		// use our own document provider
+		return new FileDocumentProvider() {
+			public IDocument createDocument(Object element) throws CoreException {
+				IDocument document = super.createDocument(element);
+				if (document != null) {
+					IDocumentPartitioner partitioner = createDocumentPartitioner();
+					if (partitioner != null) {
+						partitioner.connect(document);
+						document.setDocumentPartitioner(partitioner);
+					}
+				}
+				return document;
+			}
+		};
+//		return new ForwardingDocumentProvider(getPartitionName(),
+//				getDocumentSetupParticipant(), new TextFileDocumentProvider());
+		// AspectJ change end
+	}
+	
+	protected IDocumentSetupParticipant getDocumentSetupParticipant() {
+		return new IDocumentSetupParticipant() {
+			public void setup(IDocument document) {
+			}			
+		};
+	}
+	
+	protected abstract String getPartitionName();
+		
+	protected IDocumentPartitioner createDocumentPartitioner() {
+		return null;
+	}
+	
+	protected abstract String getDefaultCharset();
+	
+	protected abstract IBaseModel createModel(IEditorInput input) throws CoreException;
+	
+	protected void create() {
+		fDocumentProvider = createDocumentProvider(fEditorInput);
+		if (fDocumentProvider == null)
+			return;
+		try {
+			fDocumentProvider.connect(fEditorInput);
+			fModel = createModel(fEditorInput);
+			if (fModel instanceof IModelChangeProvider) {
+				fModelListener = new IModelChangedListener() {
+					public void modelChanged(IModelChangedEvent e) {
+						if (e.getChangeType() != IModelChangedEvent.WORLD_CHANGED) {
+							if (!fEditor.getLastDirtyState())
+								fEditor.fireSaveNeeded(fEditorInput, true);
+							if (!fIsSourceMode) {
+								IModelChangeProvider provider = e.getChangeProvider();
+								if (provider instanceof IEditingModel) {
+									// this is to guard against false notifications
+									// when a revert operation is performed, focus is taken away from a FormEntry
+									// and a text edit operation is falsely requested
+									if (((IEditingModel)provider).isDirty())
+										addTextEditOperation(fEditOperations, e);
+								}
+							}
+						} 
+					}
+				};
+				((IModelChangeProvider) fModel).addModelChangedListener(fModelListener);
+			}
+
+			IAnnotationModel amodel = fDocumentProvider
+					.getAnnotationModel(fEditorInput);
+			if (amodel != null)
+				amodel.connect(fDocumentProvider.getDocument(fEditorInput));
+			fElementListener = new ElementListener();
+			fDocumentProvider.addElementStateListener(fElementListener);
+		} catch (CoreException e) {
+			PDEPlugin.logException(e);
+		}
+		
+	}
+	
+	public synchronized boolean validateEdit() {
+		if (!fValidated) {
+			if (fEditorInput instanceof IFileEditorInput) {
+				IFile file = ((IFileEditorInput) fEditorInput).getFile();
+				if (file.isReadOnly()) {
+					Shell shell = fEditor.getEditorSite().getShell();
+					IStatus validateStatus = PDEPlugin.getWorkspace().validateEdit(
+						new IFile[]{file}, shell);
+					fValidated=true; // to prevent loops
+					if (validateStatus.getSeverity() != IStatus.OK)
+						ErrorDialog.openError(shell, fEditor.getTitle(), null,
+							validateStatus);
+					return validateStatus.getSeverity() == IStatus.OK;
+				}
+			}
+		}
+		return true;
+	}
+	public void doSave(IProgressMonitor monitor) {
+		try {
+			IDocument doc = fDocumentProvider.getDocument(fEditorInput);
+			fDocumentProvider.aboutToChange(fEditorInput);
+			flushModel(doc);			
+			fDocumentProvider.saveDocument(monitor, fEditorInput, doc, true);
+			fDocumentProvider.changed(fEditorInput);
+			fValidated=false;
+		}
+		catch (CoreException e) {
+			PDEPlugin.logException(e);
+		}
+	}
+	
+	protected abstract void addTextEditOperation(ArrayList ops, IModelChangedEvent event);
+	
+	protected void flushModel(IDocument doc) {
+		if (fEditOperations.size() > 0) {
+			try {
+				MultiTextEdit edit = new MultiTextEdit();
+				for (int i = 0; i < fEditOperations.size(); i++) {
+					insert(edit, (TextEdit)fEditOperations.get(i));
+				}
+				if (fModel instanceof IEditingModel)
+					((IEditingModel)fModel).setStale(true);				
+				edit.apply(doc);
+				fEditOperations.clear();
+				if (fModel instanceof IEditable)
+					((IEditable)fModel).setDirty(false);
+			} catch (MalformedTreeException e) {
+				PDEPlugin.logException(e);
+			} catch (BadLocationException e) {
+				PDEPlugin.logException(e);
+			}
+		}	
+	}
+	
+	protected static void insert(TextEdit parent, TextEdit edit) {
+		if (!parent.hasChildren()) {
+			parent.addChild(edit);
+			if (edit instanceof MoveSourceEdit) {
+				parent.addChild(((MoveSourceEdit)edit).getTargetEdit());
+			}
+			return;
+		}
+		TextEdit[] children= parent.getChildren();
+		// First dive down to find the right parent.
+		for (int i= 0; i < children.length; i++) {
+			TextEdit child= children[i];
+			if (covers(child, edit)) {
+				insert(child, edit);
+				return;
+			}
+		}
+		// We have the right parent. Now check if some of the children have to
+		// be moved under the new edit since it is covering it.
+		for (int i= children.length - 1; i >= 0; i--) {
+			TextEdit child= children[i];
+			if (covers(edit, child)) {
+				parent.removeChild(i);
+				edit.addChild(child);
+			}
+		}
+		parent.addChild(edit);
+		if (edit instanceof MoveSourceEdit) {
+			parent.addChild(((MoveSourceEdit)edit).getTargetEdit());
+		}
+	}
+	
+	protected static boolean covers(TextEdit thisEdit, TextEdit otherEdit) {
+		if (thisEdit.getLength() == 0)	// an insertion point can't cover anything
+			return false;
+		
+		int thisOffset= thisEdit.getOffset();
+		int thisEnd= thisEdit.getExclusiveEnd();	
+		if (otherEdit.getLength() == 0) {
+			int otherOffset= otherEdit.getOffset();
+			return thisOffset < otherOffset && otherOffset < thisEnd;
+		}
+		int otherOffset= otherEdit.getOffset();
+		int otherEnd= otherEdit.getExclusiveEnd();
+		return thisOffset <= otherOffset && otherEnd <= thisEnd;
+	}		
+
+	public boolean mustSave() {
+		if (!fIsSourceMode) {
+			if (fModel instanceof IEditable) {
+				if (((IEditable)fModel).isDirty()) {
+					return true;
+				}
+			}
+		}
+		return fDocumentProvider.canSaveDocument(fEditorInput);
+	}
+	
+	public void dispose() {
+		IAnnotationModel amodel = fDocumentProvider.getAnnotationModel(fEditorInput);
+		if (amodel != null)
+			amodel.disconnect(fDocumentProvider.getDocument(fEditorInput));
+		fDocumentProvider.removeElementStateListener(fElementListener);
+		fDocumentProvider.disconnect(fEditorInput);
+		if (fModelListener != null && fModel instanceof IModelChangeProvider) {
+			((IModelChangeProvider) fModel)
+					.removeModelChangedListener(fModelListener);
+			//if (undoManager != null)
+			//undoManager.disconnect((IModelChangeProvider) model);
+		}
+		if (fModel!=null)
+			fModel.dispose();
+	}
+	/**
+	 * @return Returns the primary.
+	 */
+	public boolean isPrimary() {
+		return fPrimary;
+	}
+	/**
+	 * @param primary The primary to set.
+	 */
+	public void setPrimary(boolean primary) {
+		this.fPrimary = primary;
+	}
+	
+	public boolean setSourceEditingMode(boolean sourceMode) {
+		fIsSourceMode = sourceMode;
+		if (sourceMode) {
+			// entered source editing mode; in this mode,
+			// this context's document will be edited directly
+			// in the source editor. All changes in the model
+			// are caused by reconciliation and should not be 
+			// fired to the world.
+			flushModel(fDocumentProvider.getDocument(fEditorInput));
+			fMustSynchronize=true;
+			return true;
+		}
+		// leaving source editing mode; if the document
+		// has been modified while in this mode,
+		// fire the 'world changed' event from the model
+		// to cause all the model listeners to become stale.
+		return synchronizeModelIfNeeded();
+	}
+	
+	private boolean synchronizeModelIfNeeded() {
+		if (fMustSynchronize) {
+			boolean result = synchronizeModel(fDocumentProvider.getDocument(fEditorInput));
+			fMustSynchronize=false;
+			return result;
+		}
+		return true;
+	}
+
+	public void doRevert() {
+		fMustSynchronize=true;
+		synchronizeModelIfNeeded();
+		/*
+		if (model instanceof IEditable) {
+			((IEditable)model).setDirty(false);
+		}
+		*/
+	}
+
+	public boolean isInSourceMode() {
+		return fIsSourceMode;
+	}
+
+	public boolean isModelCorrect() {
+		synchronizeModelIfNeeded();
+		return fModel!=null ? fModel.isValid() : false;
+	}
+	
+	protected boolean synchronizeModel(IDocument doc) {
+		return true;
+	}
+	public boolean matches(IResource resource) {
+		if (fEditorInput instanceof IFileEditorInput) {
+			IFileEditorInput finput = (IFileEditorInput)fEditorInput;
+			IFile file = finput.getFile();
+			if (file.equals(resource))
+				return true;
+		}
+		return false;
+	}
+	/**
+	 * @return Returns the validated.
+	 */
+	public boolean isValidated() {
+		return fValidated;
+	}
+	/**
+	 * @param validated The validated to set.
+	 */
+	public void setValidated(boolean validated) {
+		this.fValidated = validated;
+	}
+	
+	public String getLineDelimiter() {
+		if (fDocumentProvider != null) {
+			IDocument document = fDocumentProvider.getDocument(fEditorInput);
+			if (document != null) {
+				return TextUtilities.getDefaultLineDelimiter(document);
+			}
+		}
+		return System.getProperty("line.separator"); //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContextManager.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContextManager.java
new file mode 100755
index 0000000..2198ef9
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/InputContextManager.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.IModelUndoManager;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.pde.core.IBaseModel;
+import org.eclipse.pde.core.IModelChangeProvider;
+import org.eclipse.pde.internal.ui.PDEPlugin;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+
+public abstract class InputContextManager implements IResourceChangeListener {
+	private PDEFormEditor editor;
+	private Hashtable inputContexts;
+	private ArrayList monitoredFiles;
+	private ArrayList listeners;
+	private IModelUndoManager undoManager;
+	/**
+	 *  
+	 */
+	public InputContextManager(PDEFormEditor editor) {
+		this.editor = editor;
+		inputContexts = new Hashtable();
+		listeners = new ArrayList();
+		PDEPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
+	}
+
+	public void addInputContextListener(IInputContextListener listener) {
+		if (!listeners.contains(listener))
+			listeners.add(listener);
+	}
+	public void removeInputContextListener(IInputContextListener listener) {
+		listeners.remove(listener);
+	}
+	/**
+	 * 
+	 *
+	 */
+	public void dispose() {
+		PDEPlugin.getWorkspace().removeResourceChangeListener(this);
+		// dispose input contexts
+		for (Enumeration contexts = inputContexts.elements(); contexts
+				.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			unhookUndo(context);
+			context.dispose();
+		}
+		inputContexts.clear();
+		undoManager = null;
+	}
+	/**
+	 * Saves dirty contexts.
+	 * @param monitor
+	 */
+	public void save(IProgressMonitor monitor) {
+		for (Enumeration contexts = inputContexts.elements(); contexts
+				.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			if (context.mustSave())
+				context.doSave(monitor);
+		}
+	}
+	public IProject getCommonProject() {
+		for (Enumeration contexts = inputContexts.elements(); contexts
+		.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			IEditorInput input = context.getInput();
+			if (input instanceof IFileEditorInput) 
+				return ((IFileEditorInput)input).getFile().getProject();
+		}
+		return null;
+	}
+	public boolean hasContext(String id) {
+		return findContext(id) != null;
+	}
+	public InputContext findContext(String id) {
+		for (Enumeration contexts = inputContexts.elements(); contexts
+				.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			if (context.getId().equals(id))
+				return context;
+		}
+		return null;
+	}
+	public InputContext findContext(IResource resource) {
+		for (Enumeration contexts = inputContexts.elements(); contexts
+		.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			if (context.matches(resource))
+				return context;
+		}
+		return null;
+	}
+	
+	public abstract IBaseModel getAggregateModel();
+	
+	public InputContext getContext(IEditorInput input) {
+		return (InputContext)inputContexts.get(input);
+	}
+	public void putContext(IEditorInput input, InputContext context) {
+		inputContexts.put(input, context);
+		fireContextChange(context, true);
+	}
+	public InputContext getPrimaryContext() {
+		for (Enumeration contexts = inputContexts.elements(); contexts
+				.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			if (context.isPrimary())
+				return context;
+		}
+		return null;
+	}
+	public InputContext [] getInvalidContexts() {
+		ArrayList result = new ArrayList();
+		for (Enumeration contexts = inputContexts.elements(); contexts
+				.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			if (context.isModelCorrect()==false)
+				result.add(context);
+		}
+		return (InputContext[])result.toArray(new InputContext[result.size()]);
+	}
+	
+	public boolean isDirty() {
+		for (Enumeration contexts=inputContexts.elements(); contexts.hasMoreElements();) {
+			InputContext context = (InputContext)contexts.nextElement();
+			if (context.mustSave())
+				return true;
+		}
+		return false;
+	}
+
+	public void monitorFile(IFile file) {
+		if (monitoredFiles==null) monitoredFiles = new ArrayList();
+		monitoredFiles.add(file);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
+	 */
+	public void resourceChanged(IResourceChangeEvent event) {
+		IResourceDelta delta = event.getDelta();
+
+		try {
+			delta.accept(new IResourceDeltaVisitor() {
+				public boolean visit(IResourceDelta delta) {
+					int kind = delta.getKind();
+					IResource resource = delta.getResource();
+					if (resource instanceof IFile) {
+						if (kind == IResourceDelta.ADDED)
+							asyncStructureChanged((IFile)resource, true);
+						else if (kind==IResourceDelta.REMOVED)
+							asyncStructureChanged((IFile)resource, false);
+						return false;
+					}
+					return true;
+				}
+			});
+		} catch (CoreException e) {
+			PDEPlugin.logException(e);
+		}
+	}
+	
+	private void asyncStructureChanged(final IFile file, final boolean added) {
+		if (editor == null || editor.getEditorSite() == null)
+			return;
+		Shell shell = editor.getEditorSite().getShell();
+		Display display = shell != null ? shell.getDisplay() : Display.getDefault();
+
+		display.asyncExec(new Runnable() {
+			public void run() {
+				structureChanged(file, added);
+			}
+		});
+	}
+	
+	private void structureChanged(IFile file, boolean added) {
+		if (monitoredFiles==null) return;
+		for (int i=0; i<monitoredFiles.size(); i++) {
+			IFile ifile = (IFile)monitoredFiles.get(i);
+			if (ifile.equals(file)) {
+				if (added) {
+					fireStructureChange(file, true);
+				}
+				else {
+					fireStructureChange(file, false);
+					removeContext(file);
+				}
+			}
+		}
+	}
+	
+	private void removeContext(IFile file) {
+		for (Enumeration contexts = inputContexts.elements(); contexts
+		.hasMoreElements();) {
+			InputContext context = (InputContext) contexts.nextElement();
+			IEditorInput input = context.getInput();
+			if (input instanceof IFileEditorInput) {
+				IFileEditorInput fileInput = (IFileEditorInput)input;
+				if (file.equals(fileInput.getFile())) {
+					inputContexts.remove(input);
+					fireContextChange(context, false);
+					return;
+				}
+			}
+		}
+	}
+	protected void fireStructureChange(IFile file, boolean added) {
+		for (int i=0; i<listeners.size(); i++) {
+			IInputContextListener listener = (IInputContextListener)listeners.get(i);
+			if (added)
+				listener.monitoredFileAdded(file);
+			else
+				listener.monitoredFileRemoved(file);
+		}
+	}
+	protected void fireContextChange(InputContext context, boolean added) {
+		for (int i=0; i<listeners.size(); i++) {
+			IInputContextListener listener = (IInputContextListener)listeners.get(i);
+			if (added)
+				listener.contextAdded(context);
+			else
+				listener.contextRemoved(context);
+		}		
+		if (added)
+			hookUndo(context);
+		else
+			unhookUndo(context);
+	}
+	public void undo() {
+		if (undoManager!=null && undoManager.isUndoable())
+			undoManager.undo();
+	}
+	
+	public void redo() {
+		if (undoManager!=null && undoManager.isRedoable())
+			undoManager.redo();
+	}
+	
+	private void hookUndo(InputContext context) {
+		if (undoManager==null) return;
+		IBaseModel model = context.getModel();
+		if (model instanceof IModelChangeProvider)
+		undoManager.connect((IModelChangeProvider)model);
+	}
+	
+	private void unhookUndo(InputContext context) {
+		if (undoManager==null) return;
+		IBaseModel model = context.getModel();
+		if (model instanceof IModelChangeProvider)
+		undoManager.disconnect((IModelChangeProvider)model);
+	}
+	/**
+	 * @return Returns the undoManager.
+	 */
+	public IModelUndoManager getUndoManager() {
+		return undoManager;
+	}
+	/**
+	 * @param undoManager The undoManager to set.
+	 */
+	public void setUndoManager(IModelUndoManager undoManager) {
+		this.undoManager = undoManager;
+	}
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.java
new file mode 100644
index 0000000..aad1d27
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import java.util.ResourceBundle;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Helper class to get NLSed messages.
+ */
+//copied from same class in org.eclipse.ui.editors.text - no changes
+final class TextEditorMessages extends NLS {
+
+	private static final String BUNDLE_FOR_CONSTRUCTED_KEYS= "org.eclipse.ui.editors.text.ConstructedTextEditorMessages";//$NON-NLS-1$
+	private static ResourceBundle fgBundleForConstructedKeys= ResourceBundle.getBundle(BUNDLE_FOR_CONSTRUCTED_KEYS);
+
+	/**
+	 * Returns the message bundle which contains constructed keys.
+	 *
+	 * @since 3.1
+	 * @return the message bundle
+	 */
+	public static ResourceBundle getBundleForConstructedKeys() {
+		return fgBundleForConstructedKeys;
+	}
+
+	private static final String BUNDLE_NAME= TextEditorMessages.class.getName();
+
+	private TextEditorMessages() {
+		// Do not instantiate
+	}
+
+	public static String PreferencePage_description;
+	public static String PreferencePage_fontEditor;
+	public static String FileDocumentProvider_createElementInfo;
+	public static String FileDocumentProvider_error_out_of_sync;
+	public static String FileDocumentProvider_task_saving;
+	public static String FileDocumentProvider_resetDocument;
+	public static String FileDocumentProvider_getPersistedEncoding;
+	public static String StorageDocumentProvider_updateCache;
+	public static String StorageDocumentProvider_isReadOnly;
+	public static String StorageDocumentProvider_isModifiable;
+	public static String StorageDocumentProvider_getContentDescriptionFor;
+	public static String StorageDocumentProvider_getContentDescription;
+	public static String TextFileDocumentProvider_beginTask_saving;
+	public static String TextFileDocumentProvider_error_doesNotExist;
+	public static String TextFileDocumentProvider_saveAsTargetOpenInEditor;
+	public static String Editor_error_save_message;
+	public static String Editor_error_save_title;
+	public static String Editor_warning_save_delete;
+	public static String Editor_error_unreadable_encoding_header;
+	public static String Editor_error_unreadable_encoding_banner;
+	public static String Editor_error_unreadable_encoding_message_arg;
+	public static String Editor_error_unreadable_encoding_message;
+	public static String Editor_error_unsupported_encoding_header;
+	public static String Editor_error_unsupported_encoding_banner;
+	public static String Editor_error_unsupported_encoding_message_arg;
+	public static String Editor_error_unsupported_encoding_message;
+	public static String Editor_ConvertEncoding_submenu_label;
+	public static String Editor_ConvertEncoding_Custom_dialog_title;
+	public static String Editor_ConvertEncoding_Custom_dialog_message;
+	public static String NullProvider_error;
+	public static String FileBufferOperationAction_collectionFiles_label;
+	public static String FileBufferOperationHandler_collectionFiles_label;
+	public static String ResourceInfo_fileContentEncodingFormat;
+	public static String ResourceInfo_fileContainerEncodingFormat;
+	public static String WorkbenchPreference_encoding_BOM_UTF_8;
+	public static String WorkbenchPreference_encoding_BOM_UTF_16BE;
+	public static String WorkbenchPreference_encoding_BOM_UTF_16LE;
+	public static String DocumentInputStream_error_read;
+	public static String DocumentInputStream_error_streamClosed;
+
+	static {
+		NLS.initializeMessages(BUNDLE_NAME, TextEditorMessages.class);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.properties b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.properties
new file mode 100644
index 0000000..3159244
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/TextEditorMessages.properties
@@ -0,0 +1,65 @@
+###############################################################################
+# Copyright (c) 2000, 2005 IBM Corporation and others.
+# 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:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+
+# copied from same file in org.eclipse.ui.editors.text - no changes
+
+PreferencePage_description=Default Text Editor Settings
+PreferencePage_fontEditor=Text Font:
+
+FileDocumentProvider_createElementInfo=FileDocumentProvider.createElementInfo
+FileDocumentProvider_error_out_of_sync=Has been changed on the file system
+FileDocumentProvider_task_saving=Saving
+FileDocumentProvider_resetDocument=FileDocumentProvider.resetDocument
+FileDocumentProvider_getPersistedEncoding=Cannot migrate encoding property
+
+StorageDocumentProvider_updateCache=StorageDocumentProvider.updateCache
+StorageDocumentProvider_isReadOnly=StorageDocumentProvider.isReadOnly
+StorageDocumentProvider_isModifiable=StorageDocumentProvider.isModifiable
+StorageDocumentProvider_getContentDescriptionFor= Could not query content description for: {0}
+StorageDocumentProvider_getContentDescription= Could not query content description.
+
+TextFileDocumentProvider_beginTask_saving= Saving
+TextFileDocumentProvider_error_doesNotExist= File {0} does not exist.
+TextFileDocumentProvider_saveAsTargetOpenInEditor=Target file is already open in another editor.
+
+Editor_error_save_message=Save could not be completed. {0}
+Editor_error_save_title=Problems During Save As...
+Editor_warning_save_delete=The original file ''{0}'' has been deleted.
+
+Editor_error_unreadable_encoding_header=Character Encoding Problems
+Editor_error_unreadable_encoding_banner=
+Editor_error_unreadable_encoding_message_arg=This file is unreadable using the \"{0}\" character encoding.
+Editor_error_unreadable_encoding_message=This file is unreadable using the current character encoding.
+
+Editor_error_unsupported_encoding_header=Unsupported Character Encoding
+Editor_error_unsupported_encoding_banner=
+Editor_error_unsupported_encoding_message_arg=Character encoding \"{0}\" is not supported by this platform.
+Editor_error_unsupported_encoding_message= The current character encoding is not supported by this platform.
+
+Editor_ConvertEncoding_submenu_label=Enc&oding
+
+Editor_ConvertEncoding_Custom_dialog_title=Character Encoding
+Editor_ConvertEncoding_Custom_dialog_message=Enter the name of the character encoding:
+
+NullProvider_error= ERROR
+
+FileBufferOperationAction_collectionFiles_label=collecting files
+FileBufferOperationHandler_collectionFiles_label=collecting files
+
+# Copied from org.eclipse.ui.ide/org/eclipse/ui/internal/ide/messages.properties
+ResourceInfo_fileContentEncodingFormat= Default (determined from content: {0})
+ResourceInfo_fileContainerEncodingFormat= Default (inherited from container: {0})
+WorkbenchPreference_encoding_BOM_UTF_8= UTF-8 (BOM)
+WorkbenchPreference_encoding_BOM_UTF_16BE= UTF-16 Big-Endian (BOM)
+WorkbenchPreference_encoding_BOM_UTF_16LE= UTF-16 Little-Endian (BOM)
+
+DocumentInputStream_error_read= Could not read document:\n{0}
+DocumentInputStream_error_streamClosed= Stream closed
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/UTF8InputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/UTF8InputContext.java
new file mode 100644
index 0000000..5aab356
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/UTF8InputContext.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+/*
+ * Created on Jan 27, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+import org.eclipse.ajdt.pde.internal.ui.editor.*;
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.ui.*;
+
+
+public abstract class UTF8InputContext extends InputContext {
+	/**
+	 * @param editor
+	 * @param input
+	 */
+	public UTF8InputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+		super(editor, input, primary);
+	}
+	
+	protected String getDefaultCharset() {
+		return "UTF-8"; //$NON-NLS-1$
+	}
+	
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLDocumentSetupParticpant.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLDocumentSetupParticpant.java
new file mode 100644
index 0000000..35a5b19
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLDocumentSetupParticpant.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+
+import org.eclipse.core.filebuffers.*;
+import org.eclipse.jface.text.*;
+import org.eclipse.jface.text.rules.*;
+import org.eclipse.pde.internal.ui.editor.text.*;
+
+public class XMLDocumentSetupParticpant implements IDocumentSetupParticipant {
+
+	public void setup(IDocument document) {
+		IDocumentPartitioner partitioner = createDocumentPartitioner();
+		if (partitioner != null) {
+			partitioner.connect(document);
+			document.setDocumentPartitioner(partitioner);
+		}
+	}
+	
+	private IDocumentPartitioner createDocumentPartitioner() {
+		FastPartitioner partitioner = new FastPartitioner(
+				new XMLPartitionScanner(), new String[]{
+						XMLPartitionScanner.XML_TAG,
+						XMLPartitionScanner.XML_COMMENT});
+		return partitioner;
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLInputContext.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLInputContext.java
new file mode 100644
index 0000000..1ae70f9
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/pde/internal/ui/editor/context/XMLInputContext.java
@@ -0,0 +1,453 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2005 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ajdt.pde.internal.ui.editor.context;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.ajdt.pde.internal.ui.editor.PDEFormEditor;
+import org.eclipse.core.filebuffers.IDocumentSetupParticipant;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.pde.core.IModelChangedEvent;
+import org.eclipse.pde.internal.core.text.IDocumentAttribute;
+import org.eclipse.pde.internal.core.text.IDocumentNode;
+import org.eclipse.pde.internal.core.text.IDocumentTextNode;
+import org.eclipse.pde.internal.core.util.CoreUtility;
+import org.eclipse.pde.internal.ui.editor.text.XMLPartitionScanner;
+import org.eclipse.text.edits.DeleteEdit;
+import org.eclipse.text.edits.InsertEdit;
+import org.eclipse.text.edits.MoveSourceEdit;
+import org.eclipse.text.edits.MoveTargetEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.ui.IEditorInput;
+
+public abstract class XMLInputContext extends UTF8InputContext {
+	protected HashMap fOperationTable = new HashMap();
+	protected HashMap fMoveOperations = new HashMap();
+
+	/**
+	 * @param editor
+	 * @param input
+	 */
+	public XMLInputContext(PDEFormEditor editor, IEditorInput input, boolean primary) {
+		super(editor, input, primary);
+	}	
+
+	protected IDocumentPartitioner createDocumentPartitioner() {
+		FastPartitioner partitioner = new FastPartitioner(
+				new XMLPartitionScanner(), new String[]{
+						XMLPartitionScanner.XML_TAG,
+						XMLPartitionScanner.XML_COMMENT});
+		return partitioner;
+	}
+	
+	protected IDocumentSetupParticipant getDocumentSetupParticipant() {
+		return new XMLDocumentSetupParticpant();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#addTextEditOperation(java.util.ArrayList, org.eclipse.pde.core.IModelChangedEvent)
+	 */
+	protected void addTextEditOperation(ArrayList ops, IModelChangedEvent event) {
+		Object[] objects = event.getChangedObjects();
+		if (objects != null) {
+			for (int i = 0; i < objects.length; i++) {
+				Object object = objects[i];
+				switch (event.getChangeType()) {
+					case IModelChangedEvent.REMOVE :
+						if (object instanceof IDocumentNode)
+							removeNode((IDocumentNode) object, ops);
+						break;
+					case IModelChangedEvent.INSERT :
+						if (object instanceof IDocumentNode)
+							insertNode((IDocumentNode) object, ops);
+						break;
+					case IModelChangedEvent.CHANGE :
+						if (object instanceof IDocumentNode) {
+							IDocumentNode node = (IDocumentNode) object;
+							IDocumentAttribute attr = node.getDocumentAttribute(event.getChangedProperty());
+							if (attr != null) {
+								addAttributeOperation(attr, ops, event);
+							} else {
+								if (event.getOldValue() instanceof IDocumentTextNode) {
+									addElementContentOperation((IDocumentTextNode)event.getOldValue(), ops);
+								} else if (event.getOldValue() instanceof IDocumentNode && event.getNewValue() instanceof IDocumentNode){
+									// swapping of nodes
+									modifyNode(node, ops, event);
+								}
+							}
+						}
+					default:
+						break;
+				}
+			}
+		}
+	}
+	
+	private void removeNode(IDocumentNode node, ArrayList ops) {
+		// delete previous op on this node, if any
+		TextEdit old = (TextEdit)fOperationTable.get(node);
+		if (old != null) {
+			ops.remove(old);
+			fOperationTable.remove(node);
+		}
+		TextEdit oldMove= (TextEdit)fMoveOperations.get(node);
+		if (oldMove != null) {
+			ops.remove(oldMove);
+			fMoveOperations.remove(node);
+		}
+		// if node has an offset, delete it
+		if (node.getOffset() > -1) {
+			// Create a delete op for this node
+			TextEdit op = getDeleteNodeOperation(node);
+			ops.add(op);
+			fOperationTable.put(node, op);			
+		} else if (old == null && oldMove == null){
+			// No previous op on this non-offset node, just rewrite highest ancestor with an offset
+			insertNode(node, ops);
+		}
+	}
+
+	private void insertNode(IDocumentNode node, ArrayList ops) {
+		TextEdit op = null;
+		node = getHighestNodeToBeWritten(node);
+		if (node.getParentNode() == null) {
+			op = new InsertEdit(0, node.write(true));
+		} else {
+			if (node.getOffset() > -1) {
+				// this is an element that was of the form <element/>
+				// it now needs to be broken up into <element><new/></element>
+				op = new ReplaceEdit(node.getOffset(), node.getLength(), node.write(false));
+			} else {
+				// try to insert after last sibling that has an offset
+				op = insertAfterSibling(node);
+				// insert as first child of its parent
+				if (op == null) {
+					op = insertAsFirstChild(node);
+				}
+			}
+		}
+		TextEdit old = (TextEdit) fOperationTable.get(node);
+		if (old != null)
+			ops.remove(old);
+		ops.add(op);
+		fOperationTable.put(node, op);				
+	}
+
+	private InsertEdit insertAfterSibling(IDocumentNode node) {
+		IDocumentNode sibling = node.getPreviousSibling();
+		for (;;) {
+			if (sibling == null)
+				break;
+			if (sibling.getOffset() > -1) {
+				node.setLineIndent(sibling.getLineIndent());
+				String sep = TextUtilities.getDefaultLineDelimiter(getDocumentProvider().getDocument(getInput()));
+				return new InsertEdit(sibling.getOffset() + sibling.getLength(), sep + node.write(true)); 
+			}
+			sibling = sibling.getPreviousSibling();
+		}
+		return null;
+	}
+	
+	private InsertEdit insertAsFirstChild(IDocumentNode node) {
+		int offset = node.getParentNode().getOffset();
+		int length = getNextPosition(getDocumentProvider().getDocument(getInput()), offset, '>');
+		node.setLineIndent(node.getParentNode().getLineIndent() + 3);
+		String sep = TextUtilities.getDefaultLineDelimiter(getDocumentProvider().getDocument(getInput()));
+		return new InsertEdit(offset+ length + 1, sep + node.write(true));	 
+	}
+	
+
+	private void modifyNode(IDocumentNode node, ArrayList ops, IModelChangedEvent event) {
+		IDocumentNode oldNode = (IDocumentNode)event.getOldValue();
+		IDocumentNode newNode = (IDocumentNode)event.getNewValue();
+		
+		IDocumentNode node1 = (oldNode.getPreviousSibling() == null || oldNode.equals(newNode.getPreviousSibling())) ? oldNode : newNode;
+		IDocumentNode node2 = node1.equals(oldNode) ? newNode : oldNode;
+		
+		if (node1.getOffset() < 0 && node2.getOffset() < 2) {
+			TextEdit op = (TextEdit)fOperationTable.get(node1);
+			if (op == null) {
+				// node 1 has no rule, so node 2 has no rule, therefore rewrite parent/ancestor
+				insertNode(node, ops);
+			} else {
+				// swap order of insert operations
+				TextEdit op2 = (TextEdit)fOperationTable.get(node2);
+				ops.set(ops.indexOf(op), op2);
+				ops.set(ops.indexOf(op2), op);
+			}
+		} else if (node1.getOffset() > -1 && node2.getOffset() > -1) {
+			// both nodes have offsets, so create a move target/source combo operation
+			IRegion region = getMoveRegion(node1);
+			MoveSourceEdit source = new MoveSourceEdit(region.getOffset(), region.getLength());
+			region = getMoveRegion(node2);
+			source.setTargetEdit(new MoveTargetEdit(region.getOffset()));
+			MoveSourceEdit op = (MoveSourceEdit)fMoveOperations.get(node1);
+			if (op != null) {
+				ops.set(ops.indexOf(op), source);
+			} else {
+				op = (MoveSourceEdit)fMoveOperations.get(node2);
+				if (op != null && op.getTargetEdit().getOffset() == source.getOffset()) {
+					fMoveOperations.remove(node2);
+					ops.remove(op);
+					return;
+				} 
+				ops.add(source);
+			}			
+			fMoveOperations.put(node1, source);
+		} else {
+			// one node with offset, the other without offset.  Delete/reinsert the one without offset
+			insertNode((node1.getOffset() < 0) ? node1 : node2, ops);
+		}		
+	}
+	
+	private IRegion getMoveRegion(IDocumentNode node) {
+		int offset = node.getOffset();
+		int length = node.getLength();
+		int i = 1;
+		try {
+			IDocument doc = getDocumentProvider().getDocument(getInput());
+			for (;;i++) {
+				char ch = doc.get(offset - i, 1).toCharArray()[0];
+				if (!Character.isWhitespace(ch)) {
+					i -= 1;
+					break;
+				}
+			}
+		} catch (BadLocationException e) {
+		}
+		return new Region(offset - i, length + i);		
+	}
+
+	private void addAttributeOperation(IDocumentAttribute attr, ArrayList ops, IModelChangedEvent event) {
+		int offset = attr.getValueOffset();
+		Object newValue = event.getNewValue();
+		Object changedObject = attr;
+		TextEdit op = null;
+		if (offset > -1) {
+			if (newValue == null || newValue.toString().length() == 0) {
+				int length = attr.getValueOffset() + attr.getValueLength() + 1 - attr.getNameOffset();
+				op = getAttributeDeleteEditOperation(attr.getNameOffset(), length);
+			} else {
+				op = new ReplaceEdit(offset, attr.getValueLength(), getWritableString(event.getNewValue().toString()));
+			}
+		} 
+				
+		if (op == null) {
+			IDocumentNode node = attr.getEnclosingElement();
+			IDocument doc = getDocumentProvider().getDocument(getInput());
+			if (node.getOffset() > -1) {
+				changedObject = node;
+				int len = getNextPosition(doc, node.getOffset(), '>');
+				op = new ReplaceEdit(node.getOffset(), len + 1, node.writeShallow(shouldTerminateElement(doc, node.getOffset() + len)));		
+			} else {
+				insertNode(node, ops);
+				return;
+			}		
+		}
+		TextEdit oldOp = (TextEdit)fOperationTable.get(changedObject);
+		if (oldOp != null)
+			ops.remove(oldOp);
+		ops.add(op);
+		fOperationTable.put(changedObject, op);
+	}
+	
+	private void addElementContentOperation(IDocumentTextNode textNode, ArrayList ops) {
+		TextEdit op = null;
+		Object changedObject = textNode;
+		if (textNode.getOffset() > -1) {
+			String newText = getWritableString(textNode.getText());
+			op = new ReplaceEdit(textNode.getOffset(), textNode.getLength(), newText);
+		} else {
+			IDocumentNode parent = textNode.getEnclosingElement();
+			if (parent.getOffset() > -1) {
+				IDocument doc = getDocumentProvider().getDocument(getInput());
+				try {
+					String endChars = doc.get(parent.getOffset() + parent.getLength() - 2, 2);
+					if ("/>".equals(endChars)) { //$NON-NLS-1$
+						// parent element is of the form <element/>, rewrite it
+						insertNode(parent, ops);
+						return;
+					}
+				} catch (BadLocationException e) {
+				}
+				// add text as first child
+				changedObject = parent;
+				String sep = TextUtilities.getDefaultLineDelimiter(getDocumentProvider().getDocument(getInput()));
+				StringBuffer buffer = new StringBuffer(sep); 
+				for (int i = 0; i < parent.getLineIndent(); i++) 
+					buffer.append(" "); //$NON-NLS-1$
+				buffer.append("   " + getWritableString(textNode.getText())); //$NON-NLS-1$
+				int offset = parent.getOffset();
+				int length = getNextPosition(doc, offset, '>');
+				op = new InsertEdit(offset+ length + 1, buffer.toString());	
+			} else {
+				insertNode(parent, ops);
+				return;
+			}
+		}
+		TextEdit oldOp = (TextEdit)fOperationTable.get(changedObject);
+		if (oldOp != null)
+			ops.remove(oldOp);
+		ops.add(op);
+		fOperationTable.put(changedObject, op);		
+	}
+
+	private boolean shouldTerminateElement(IDocument doc, int offset) {
+		try {
+			return doc.get(offset-1, 1).toCharArray()[0] == '/';
+		} catch (BadLocationException e) {
+		}
+		return false;
+	}
+	
+	private int getNextPosition(IDocument doc, int offset, char ch) {
+		int i = 0;
+		try {
+			for (i = 0; i + offset < doc.getLength() ;i++) {
+				if (ch == doc.get(offset + i, 1).toCharArray()[0])
+					break;
+			}
+		} catch (BadLocationException e) {
+		}
+		return i;
+	}
+	
+	private DeleteEdit getAttributeDeleteEditOperation(int offset, int length) {
+		try {
+			IDocument doc = getDocumentProvider().getDocument(getInput());
+			for (;;) {
+				char ch = doc.get(offset + length, 1).toCharArray()[0];
+				if (!Character.isWhitespace(ch)) {
+					break;
+				}
+				
+				length += 1;
+			}
+		} catch (BadLocationException e) {
+		}
+		return new DeleteEdit(offset, length);		
+	}
+	
+
+	private DeleteEdit getDeleteNodeOperation(IDocumentNode node) {
+		int offset = node.getOffset();
+		int length = node.getLength();
+		int indent = 0;
+		try {
+			IDocument doc = getDocumentProvider().getDocument(getInput());
+			int line = doc.getLineOfOffset(offset + length);
+			for (;;) {
+				char ch = doc.get(offset + length, 1).toCharArray()[0];
+				if (doc.getLineOfOffset(offset + length) > line || !Character.isWhitespace(ch)) {
+					length -= 1;
+					break;
+				}
+				length += 1;
+			}
+			
+			for (indent = 1; indent <= node.getLineIndent(); indent++) {
+				char ch = doc.get(offset - indent, 1).toCharArray()[0];
+				if (!Character.isWhitespace(ch)) {
+					indent -= 1;
+					break;
+				}
+					
+			}
+			//System.out.println("\"" + getDocumentProvider().getDocument(getInput()).get(offset-indent, length + indent) + "\"");
+		} catch (BadLocationException e) {
+		}
+		return new DeleteEdit(offset - indent, length + indent);
+		
+	}
+
+	private IDocumentNode getHighestNodeToBeWritten(IDocumentNode node) {
+		IDocumentNode parent = node.getParentNode();
+		if (parent == null)
+			return node;
+		if (parent.getOffset() > -1) {
+			IDocument doc = getDocumentProvider().getDocument(getInput());
+			try {
+				String endChars = doc.get(parent.getOffset() + parent.getLength() - 2, 2);
+				return ("/>".equals(endChars)) ? parent : node; //$NON-NLS-1$
+			} catch (BadLocationException e) {
+				return node;
+			}
+			
+		}
+		return getHighestNodeToBeWritten(parent);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.pde.internal.ui.neweditor.context.InputContext#flushModel(org.eclipse.jface.text.IDocument)
+	 */
+	protected void flushModel(IDocument doc) {
+		removeUnnecessaryOperations();
+		if (fOperationTable.size() == 1) {
+			Object object = fOperationTable.keySet().iterator().next();
+			if (object instanceof IDocumentNode && fEditOperations.get(0) instanceof InsertEdit) {
+				if (((IDocumentNode)object).getParentNode() == null) {
+					doc.set(((IDocumentNode)object).write(true));
+					fOperationTable.clear();
+					fEditOperations.clear();
+					return;
+				}
+			} 
+		}
+		reorderInsertEdits(fEditOperations);
+		fOperationTable.clear();
+		fMoveOperations.clear();
+		super.flushModel(doc);
+	}
+	
+	protected abstract void reorderInsertEdits(ArrayList ops);
+
+	protected void removeUnnecessaryOperations() {
+		Iterator iter = fOperationTable.values().iterator();
+		while (iter.hasNext()) {
+			Object object = iter.next();
+			if (object instanceof IDocumentNode) {
+				IDocumentNode node = (IDocumentNode)object;
+				if (node.getOffset() > -1) {
+					IDocumentAttribute[] attrs = node.getNodeAttributes();
+					for (int i = 0; i < attrs.length; i++) {
+						Object op = fOperationTable.remove(attrs[i]);
+						if (op != null)
+							fEditOperations.remove(op);
+					}
+					IDocumentTextNode textNode = node.getTextNode();
+					if (textNode != null) {
+						Object op = fOperationTable.remove(textNode);
+						if (op != null)
+							fEditOperations.remove(op);						
+					}
+				}
+			}
+		}		
+	}
+	
+	
+	public String getWritableString(String source) {
+		return CoreUtility.getWritableString(source);
+	}
+	
+	protected HashMap getOperationTable() {
+		return fOperationTable;
+	}
+
+}
diff --git a/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/ui/buildconfig/BuildConfigPlugin.java b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/ui/buildconfig/BuildConfigPlugin.java
new file mode 100644
index 0000000..247eb26
--- /dev/null
+++ b/org.eclipse.ajdt.ui.buildconfig/src/org/eclipse/ajdt/ui/buildconfig/BuildConfigPlugin.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Matt Chapman - initial version
+ *******************************************************************************/
+package org.eclipse.ajdt.ui.buildconfig;
+
+import org.eclipse.ajdt.core.AspectJPlugin;
+import org.eclipse.ajdt.internal.buildconfig.BCResourceChangeListener;
+import org.eclipse.ajdt.internal.buildconfig.BCWorkbenchWindowInitializer;
+import org.eclipse.ajdt.internal.buildconfig.BuildConfigurator;
+import org.eclipse.ajdt.ui.buildconfig.DefaultBuildConfigurator;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.ui.IStartup;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+public class BuildConfigPlugin extends AbstractUIPlugin implements IStartup {
+	public void start(BundleContext context) throws Exception {
+		// register the our build config implementations with ajdt.ui
+		DefaultBuildConfigurator.setBuildConfigurator(new BuildConfigurator());
+		
+		super.start(context);
+		
+		// Update project menu and listen for project selections
+		new BCWorkbenchWindowInitializer();
+
+		// listener for build configurator
+		AspectJPlugin.getWorkspace().addResourceChangeListener(
+				new BCResourceChangeListener(),
+				IResourceChangeEvent.PRE_CLOSE
+						| IResourceChangeEvent.PRE_DELETE
+						| IResourceChangeEvent.POST_CHANGE
+						| IResourceChangeEvent.PRE_BUILD);
+	}
+
+	public void earlyStartup() {
+	}
+}