bug 309030 - support for xml artifacts in plugin bundle root folder
diff --git a/jpa/plugins/org.eclipse.jpt.core/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.core/META-INF/MANIFEST.MF
index a7d88c3..978199b 100644
--- a/jpa/plugins/org.eclipse.jpt.core/META-INF/MANIFEST.MF
+++ b/jpa/plugins/org.eclipse.jpt.core/META-INF/MANIFEST.MF
@@ -22,6 +22,7 @@
  org.eclipse.jst.common.project.facet.core;bundle-version="[1.3.100,2.0.0)",
  org.eclipse.jst.j2ee;bundle-version="[1.1.200,1.2.0)",
  org.eclipse.jst.j2ee.core;bundle-version="[1.1.200,1.3.0)",
+ org.eclipse.pde.core;bundle-version="[3.6.0,4.0.0)";resolution:=optional,
  org.eclipse.wst.common.emf;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.wst.common.emfworkbench.integration;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.wst.common.frameworks;bundle-version="[1.1.200,1.3.0)",
diff --git a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties
index 9eeede5..923fca3 100644
--- a/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties
+++ b/jpa/plugins/org.eclipse.jpt.core/property_files/jpa_core.properties
@@ -15,7 +15,6 @@
 VALIDATE_SOURCE_FOLDER_ILLEGAL=Source folder path is illegal
 VALIDATE_SOURCE_FOLDER_DOES_NOT_EXIST=Source folder ''{0}'' does not exist
 VALIDATE_SOURCE_FOLDER_NOT_IN_PROJECT=Source folder ''{0}'' is not in project ''{1}''
-VALIDATE_SOURCE_FOLDER_NOT_SOURCE_FOLDER=Source folder ''{0}'' is not an actual source folder
 VALIDATE_FILE_PATH_NOT_SPECIFIED=File path must be specified
 VALIDATE_FILE_ALREADY_EXISTS=File already exists at this location
 VALIDATE_FILE_VERSION_NOT_SUPPORTED=File version not supported
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JptCorePlugin.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JptCorePlugin.java
index 8047e52..eae7089 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JptCorePlugin.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JptCorePlugin.java
@@ -10,7 +10,6 @@
 package org.eclipse.jpt.core;
 
 import javax.xml.parsers.SAXParserFactory;
-
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.ProjectScope;
@@ -34,6 +33,7 @@
 import org.eclipse.jpt.core.internal.JpaPlatformRegistry;
 import org.eclipse.jpt.core.internal.JptCoreMessages;
 import org.eclipse.jpt.core.internal.jpa2.Generic2_0JpaPlatformProvider;
+import org.eclipse.jpt.core.internal.prefs.JpaPreferenceInitializer;
 import org.eclipse.jpt.utility.internal.StringTools;
 import org.eclipse.jst.j2ee.internal.J2EEConstants;
 import org.eclipse.osgi.util.NLS;
@@ -304,6 +304,20 @@
 	public static boolean projectHasWebFacet(IProject project) {
 		return projectHasFacet(project, WEB_PROJECT_FACET_ID);
 	}
+	
+	/**
+	 * Return whether the specified Eclipse project has a Plug-in nature.
+	 */
+	public static boolean projectHasPluginNature(IProject project) {
+		try {
+			return project.hasNature("org.eclipse.pde.PluginNature");
+		}
+		catch (CoreException ce) {
+			// fall through
+			log(ce);
+		}
+		return false;
+	}
 
 	/**
 	 * Checked exceptions bite.
@@ -346,10 +360,9 @@
 	 * has a Web facet.
 	 */
 	public static String getDeploymentURI(IProject project, String defaultURI) {
-		return projectHasWebFacet(project) ?
-				WEB_PROJECT_DEPLOY_PREFIX + '/' + defaultURI
-			:
-				defaultURI;
+		return (projectHasWebFacet(project) && ! projectHasPluginNature(project))
+				? WEB_PROJECT_DEPLOY_PREFIX + '/' + defaultURI
+				: defaultURI;
 	}
 
 	/**
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java
index e33e507..dceee4e 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java
@@ -15,6 +15,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.Vector;
+import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IProject;
@@ -24,6 +25,7 @@
 import org.eclipse.core.resources.IResourceProxy;
 import org.eclipse.core.resources.IResourceProxyVisitor;
 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;
@@ -78,9 +80,13 @@
 import org.eclipse.jpt.utility.internal.iterables.SubIterableWrapper;
 import org.eclipse.jpt.utility.internal.iterables.TransformationIterable;
 import org.eclipse.jst.j2ee.model.internal.validation.ValidationCancelledException;
+import org.eclipse.pde.core.project.IBundleProjectDescription;
+import org.eclipse.pde.core.project.IBundleProjectService;
 import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;
 import org.eclipse.wst.validation.internal.provisional.core.IMessage;
 import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 
 /**
  * JPA project. Holds all the JPA stuff.
@@ -189,8 +195,8 @@
 	 * generated.
 	 */
 	protected String metamodelSourceFolderName;
-
-
+	
+	
 	// ********** constructor/initialization **********
 
 	protected AbstractJpaProject(JpaProject.Config config) {
@@ -515,8 +521,8 @@
 	 * Return the new JPA file, null if it was not created.
 	 */
 	protected JpaFile addJpaFile_(IFile file) {
-		if ( ! this.getJavaProject().isOnClasspath(file)) {
-			return null;  // the file must be on the Java classpath
+		if (! getJavaProject().isOnClasspath(file) && ! isInBundleRoot(file)) {
+			return null; // the file must be on the Java classpath or in the bundle root
 		}
 
 		JpaFile jpaFile = null;
@@ -535,7 +541,53 @@
 		this.jpaFiles.add(jpaFile);
 		return jpaFile;
 	}
-
+	
+	/**
+	 * Returns <code>true</code> if the given resource is within the PDE bundle root,
+	 * and <code>false</code> otherwise.
+	 */
+	private boolean isInBundleRoot(IResource resource) {
+		IContainer root = getBundleRoot(project);
+		if (root != null) {
+				return root.getFullPath().isPrefixOf(resource.getFullPath());
+		}
+		return false;
+	}
+	
+	/**
+	 * Returns the {@link IContainer} representing the PDE bundle root, <code>null</code> otherwise.
+	 */
+	public static IContainer getBundleRoot(IProject project) {
+		try {
+			if (JptCorePlugin.projectHasPluginNature(project)) {
+				IBundleProjectService service = getBundleProjectService();
+				if (service != null) {
+					IBundleProjectDescription description = service.getDescription(project);
+					if (description != null) {
+						IPath path = description.getBundleRoot();
+						return (path == null) ? project : project.getFolder(path);
+					}
+				}
+			}
+		} 
+		catch (CoreException ce) {
+			// ignore, no PDE bundle root
+		}
+		return null;
+	}
+	
+	private static IBundleProjectService getBundleProjectService() {
+		BundleContext context = JptCorePlugin.instance().getBundle().getBundleContext();
+		ServiceReference reference = context.getServiceReference(IBundleProjectService.class.getName());
+		if (reference == null)
+			return null;
+		IBundleProjectService service = (IBundleProjectService) context.getService(reference);
+		if (service != null)
+			context.ungetService(reference);
+		
+		return service;
+	}
+	
 	/**
 	 * Remove the JPA file corresponding to the specified IFile, if it exists.
 	 * Return true if a JPA File was removed, false otherwise
@@ -1206,7 +1258,7 @@
 	 */
 	protected boolean jpaFileIsAlive(JpaFile jpaFile) {
 		IFile file = jpaFile.getFile();
-		return this.getJavaProject().isOnClasspath(file) &&
+		return (this.getJavaProject().isOnClasspath(file) || isInBundleRoot(file)) &&
 				file.exists();
 	}
 
@@ -1463,7 +1515,7 @@
 	}
 
 	protected void externalProjectChanged(IResourceDelta delta) {
-		if (this.getJavaProject().isOnClasspath(delta.getResource())) {
+		if (this.getJavaProject().isOnClasspath(delta.getResource()) || isInBundleRoot(delta.getResource())) {
 			ResourceDeltaVisitor resourceDeltaVisitor = this.buildExternalResourceDeltaVisitor();
 			resourceDeltaVisitor.visitDelta(delta);
 			// force an "update" here since adding and/or removing an external Java type
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java
index ec15ff5..3f2de58 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java
@@ -23,7 +23,6 @@
 	public static String VALIDATE_SOURCE_FOLDER_ILLEGAL;
 	public static String VALIDATE_SOURCE_FOLDER_DOES_NOT_EXIST;
 	public static String VALIDATE_SOURCE_FOLDER_NOT_IN_PROJECT;
-	public static String VALIDATE_SOURCE_FOLDER_NOT_SOURCE_FOLDER;
 	public static String VALIDATE_FILE_PATH_NOT_SPECIFIED;
 	public static String VALIDATE_FILE_ALREADY_EXISTS;
 	public static String VALIDATE_FILE_VERSION_NOT_SUPPORTED;
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationDataModelProvider.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationDataModelProvider.java
index 3600851..cbed042 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationDataModelProvider.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationDataModelProvider.java
@@ -11,19 +11,20 @@
 
 import java.util.Iterator;
 import java.util.Set;
+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.IWorkspaceRoot;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
-import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
 import org.eclipse.jpt.core.JpaProject;
 import org.eclipse.jpt.core.JptCorePlugin;
+import org.eclipse.jpt.core.internal.AbstractJpaProject;
 import org.eclipse.jpt.core.internal.JptCoreMessages;
 import org.eclipse.jpt.utility.Filter;
 import org.eclipse.jpt.utility.internal.ArrayTools;
@@ -63,7 +64,7 @@
 	@Override
 	public Object getDefaultProperty(String propertyName) {
 		if (propertyName.equals(SOURCE_FOLDER)) {
-			IFolder sourceFolder = getDefaultSourceFolder();
+			IContainer sourceFolder = getDefaultSourceFolder();
 			if (sourceFolder != null && sourceFolder.exists()) {
 				return sourceFolder.getFullPath().toPortableString();
 			}
@@ -169,11 +170,6 @@
 				IStatus.ERROR, JptCorePlugin.PLUGIN_ID,
 				NLS.bind(JptCoreMessages.VALIDATE_SOURCE_FOLDER_DOES_NOT_EXIST, sourceFolderPath));
 		}
-		if (getVerifiedJavaSourceFolder() == null) {
-			return new Status(
-				IStatus.ERROR, JptCorePlugin.PLUGIN_ID,
-				NLS.bind(JptCoreMessages.VALIDATE_SOURCE_FOLDER_NOT_SOURCE_FOLDER, sourceFolderPath));
-		}
 		String filePath = getStringProperty(FILE_PATH);
 		if (StringTools.stringIsEmpty(filePath)) {
 			return new Status(
@@ -235,14 +231,17 @@
 	}
 	
 	/**
-	 * Return a best guess java source folder for the specified project
+	 * Return a best guess source folder for the specified project
 	 */
-	// Copied from NewJavaClassDataModelProvider
-	protected IFolder getDefaultSourceFolder() {
+	protected IContainer getDefaultSourceFolder() {
 		IProject project = getProject();
 		if (project == null) {
 			return null;
 		}
+		IContainer folder = AbstractJpaProject.getBundleRoot(project);
+		if (folder != null) {
+			return folder;
+		}
 		IPackageFragmentRoot[] sources = J2EEProjectUtilities.getSourceContainers(project);
 		// Try and return the first source folder
 		if (sources.length > 0) {
@@ -256,20 +255,20 @@
 	}
 	
 	/**
-	 * Return whether the path provided can not be a valid IFolder path
+	 * Return whether the path provided can not be a valid IContainer path
 	 */
-	protected boolean sourceFolderIsIllegal(String folderPath) {
+	protected boolean sourceFolderIsIllegal(String containerPath) {
 		IProject project = getProject();
 		if (project == null) {
 			return false;
 		}
 		try {
-			project.getWorkspace().getRoot().getFolder(new Path(folderPath));
+			IWorkspaceRoot root = project.getWorkspace().getRoot();
+			return root.getContainerForLocation(root.getLocation().append(new Path(containerPath))) == null;
 		}
 		catch (IllegalArgumentException e) {
 			return true;
 		}
-		return false;
 	}
 	
 	/**
@@ -291,55 +290,36 @@
 	}
 	
 	/**
-	 * Return an IFolder represented by the SOURCE_FOLDER property, verified
+	 * Return an IContainer represented by the SOURCE_FOLDER property, verified
 	 * to exist
 	 */
-	protected IFolder getVerifiedSourceFolder() {
+	protected IContainer getVerifiedSourceFolder() {
 		String folderPath = getStringProperty(SOURCE_FOLDER);
 		IProject project = getProject();
 		if (project == null) {
 			return null;
 		}
-		IFolder folder;
+		IContainer container;
 		try {
-			folder = project.getWorkspace().getRoot().getFolder(new Path(folderPath));
+			IWorkspaceRoot root = project.getWorkspace().getRoot();
+			container = root.getContainerForLocation(root.getLocation().append(new Path(folderPath)));
 		}
 		catch (IllegalArgumentException e) {
 			return null;
 		}
-		if (folder == null || ! folder.exists()) {
+		if (container == null || ! container.exists()) {
 			return null;
 		}
-		return folder;
-	}
-	
-	/**
-	 * Return the source folder, provided it is verified to be an actual java
-	 * source folder
-	 */
-	protected IFolder getVerifiedJavaSourceFolder() {
-		IFolder folder = getVerifiedSourceFolder();
-		if (folder == null) {
-			return null;
-		}
-		IJavaProject jProject = JavaCore.create(getProject());
-		if (jProject == null) {
-			return null;
-		}
-		IPackageFragmentRoot packageFragmentRoot = jProject.getPackageFragmentRoot(folder);
-		if (packageFragmentRoot == null || ! packageFragmentRoot.exists()) {
-			return null;
-		}
-		return folder;
+		return container;
 	}
 	
 	protected IFile getExistingFile() {
-		IFolder folder = getVerifiedSourceFolder();
-		if (folder == null) {
+		IContainer container = getVerifiedSourceFolder();
+		if (container == null) {
 			return null;
 		}
 		String filePath = getStringProperty(FILE_PATH);
-		IFile existingFile = folder.getFile(new Path(filePath));
+		IFile existingFile = container.getFile(new Path(filePath));
 		if (! existingFile.exists()) {
 			return null;
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationOperation.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationOperation.java
index 806bc48..922308d 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationOperation.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationOperation.java
@@ -10,9 +10,11 @@
 package org.eclipse.jpt.core.internal.operations;
 
 import org.eclipse.core.commands.ExecutionException;
+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.IWorkspaceRoot;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -23,6 +25,8 @@
 import org.eclipse.jpt.core.JpaProject;
 import org.eclipse.jpt.core.JptCorePlugin;
 import org.eclipse.jpt.core.resource.AbstractXmlResourceProvider;
+import org.eclipse.wst.common.componentcore.ComponentCore;
+import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
 import org.eclipse.wst.common.frameworks.datamodel.AbstractDataModelOperation;
 import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
 
@@ -33,7 +37,7 @@
 	/**
 	 * Will be null until folder is created
 	 */
-	protected IFolder createdSourceFolder;
+	protected IContainer createdSourceFolder;
 	
 	/**
 	 * Will be null until file is created
@@ -84,17 +88,42 @@
 		// Get the source folder name from the data model
 		String folderPath = model.getStringProperty(SOURCE_FOLDER);
 		IProject project = getProject();
-		IFolder folder = project.getWorkspace().getRoot().getFolder(new Path(folderPath));
-		// If folder does not exist, create the folder with the specified path
-		if (! folder.exists()) {
-			try {
-				folder.create(true, true, null);
-			} catch (CoreException e) {
-				throw new ExecutionException("Could not create folder", e); //$NON-NLS-1$
+		IWorkspaceRoot root = project.getWorkspace().getRoot();
+		IContainer container = root.getContainerForLocation(root.getLocation().append(new Path(folderPath)));
+		boolean createVirtualReference = ComponentCore.createFolder(project, new Path("")).exists();
+		if (container instanceof IFolder) {
+			IFolder folder = (IFolder) container;
+			// If folder does not exist, create the folder with the specified path
+			if (! folder.exists()) {
+				try {
+					folder.create(true, true, null);
+				} catch (CoreException e) {
+					throw new ExecutionException("Could not create folder", e); //$NON-NLS-1$
+				}
+			}
+			if (createVirtualReference) {
+				IVirtualFolder rootFolder = ComponentCore.createComponent(project).getRootFolder();
+				try {
+					rootFolder.getFolder(new Path("/")).createLink(container.getProjectRelativePath(), 0, null);
+				}
+				catch (CoreException ce) {
+					JptCorePlugin.log(ce);
+				}
+			}
+		}
+		else if (container instanceof IProject) {
+			if (createVirtualReference) {
+				IVirtualFolder rootFolder = ComponentCore.createComponent(project).getRootFolder();
+				try {
+					rootFolder.getFolder(new Path("/META-INF")).createLink(container.getProjectRelativePath().append("META-INF"), 0, null);
+				}
+				catch (CoreException ce) {
+					JptCorePlugin.log(ce);
+				}
 			}
 		}
 		// Return the source folder
-		this.createdSourceFolder = folder;
+		this.createdSourceFolder = container;
 	}
 	
 	protected void createFile() {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java
index 86d5cdb..a8c27f1 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/OrmFileCreationDataModelProvider.java
@@ -156,6 +156,9 @@
 	
 	@Override
 	public DataModelPropertyDescriptor getPropertyDescriptor(String propertyName) {
+		if (propertyName.equals(DEFAULT_ACCESS)) {
+			return accessPropertyDescriptor((AccessType) getProperty(DEFAULT_ACCESS));
+		}
 		if (propertyName.equals(PERSISTENCE_UNIT)) {
 			return persistenceUnitPropertyDescriptor(getStringProperty(PERSISTENCE_UNIT));
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/orm/MappingFileWizardPage.java b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/orm/MappingFileWizardPage.java
index 7ad77b4..ff8abe4 100644
--- a/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/orm/MappingFileWizardPage.java
+++ b/jpa/plugins/org.eclipse.jpt.ui/src/org/eclipse/jpt/ui/internal/wizards/orm/MappingFileWizardPage.java
@@ -11,7 +11,6 @@
 package org.eclipse.jpt.ui.internal.wizards.orm;
 
 import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IStatus;
@@ -26,6 +25,7 @@
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerFilter;
 import org.eclipse.jface.window.Window;
+import org.eclipse.jpt.core.internal.AbstractJpaProject;
 import org.eclipse.jpt.core.internal.operations.OrmFileCreationDataModelProperties;
 import org.eclipse.jpt.core.internal.utility.jdt.JDTTools;
 import org.eclipse.jpt.ui.JptUiPlugin;
@@ -247,8 +247,16 @@
 	private ISelectionStatusValidator getSourceFolderDialogSelectionValidator() {
 		return new ISelectionStatusValidator() {
 			public IStatus validate(Object[] selection) {
-				if (selection != null && selection[0] != null && ! (selection[0] instanceof IProject)) {
-					return Status.OK_STATUS;
+				if (selection != null && selection[0] != null) {
+					if (selection[0] instanceof IProject) {
+						IProject project = (IProject) selection[0];
+						if (project.equals(AbstractJpaProject.getBundleRoot(project))) {
+							return Status.OK_STATUS;
+						}
+					}
+					else {
+						return Status.OK_STATUS;
+					}
 				}
 				return new Status(IStatus.ERROR, JptUiPlugin.PLUGIN_ID, JptUiMessages.MappingFileWizardPage_incorrectSourceFolderError);
 			}
@@ -263,12 +271,16 @@
 					IProject project = (IProject) element;
 					return project.getName().equals(model.getProperty(PROJECT_NAME));
 				} 
-				else if (element instanceof IFolder) {
-					IFolder folder = (IFolder) element;
+				else if (element instanceof IContainer) {
+					IContainer container = (IContainer) element;
 					// only show source folders
 					IProject project = ProjectUtilities.getProject(model.getStringProperty(PROJECT_NAME));
 					IJavaProject javaProject = JavaCore.create(project);
-					if (JDTTools.packageFragmentRootIsSourceFolder(javaProject.getPackageFragmentRoot(folder))) {
+					if (JDTTools.packageFragmentRootIsSourceFolder(javaProject.getPackageFragmentRoot(container))) {
+						return true;
+					}
+					// add bundle root, if it exists
+					if (element.equals(AbstractJpaProject.getBundleRoot(project))) {
 						return true;
 					}
 				}