Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbvosburgh2009-10-28 17:46:10 +0000
committerbvosburgh2009-10-28 17:46:10 +0000
commit267dda422e19750a8746f265dc0d6469e3aac014 (patch)
tree0afb6f533e2c7fed4907a5d2eeeb479661fdbce1 /jpa/plugins/org.eclipse.jpt.core/src/org
parentb9beac12764ad3ce59b39a98fc7a0665e8af36f4 (diff)
downloadwebtools.dali-267dda422e19750a8746f265dc0d6469e3aac014.tar.gz
webtools.dali-267dda422e19750a8746f265dc0d6469e3aac014.tar.xz
webtools.dali-267dda422e19750a8746f265dc0d6469e3aac014.zip
rework JPA project locking
Diffstat (limited to 'jpa/plugins/org.eclipse.jpt.core/src/org')
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/GenericJpaModel.java1076
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java5
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaModel.java47
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java4
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JptCorePlugin.java117
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java3
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaProject.java38
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java528
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java590
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JptCoreMessages.java1
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java3
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationDataModelProvider.java5
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/operations/AbstractJpaFileCreationOperation.java25
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/SimpleSchedulingRule.java22
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidator.java4
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/AbstractXmlResourceProvider.java2
-rw-r--r--jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/xml/JpaXmlResource.java21
17 files changed, 1257 insertions, 1234 deletions
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/GenericJpaModel.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/GenericJpaModel.java
new file mode 100644
index 0000000000..913b48d54d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/GenericJpaModel.java
@@ -0,0 +1,1076 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2009 Oracle. 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:
+ * Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.core;
+
+import java.util.Vector;
+
+import org.eclipse.core.commands.ExecutionException;
+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.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.jobs.IJobManager;
+import org.eclipse.core.runtime.jobs.ILock;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.ElementChangedEvent;
+import org.eclipse.jdt.core.IElementChangedListener;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jpt.core.internal.AsynchronousJpaProjectUpdater;
+import org.eclipse.jpt.core.internal.JptCoreMessages;
+import org.eclipse.jpt.core.internal.SimpleJpaProjectConfig;
+import org.eclipse.jpt.core.internal.facet.JpaFacetInstallDataModelProperties;
+import org.eclipse.jpt.core.internal.operations.JpaFileCreationDataModelProperties;
+import org.eclipse.jpt.core.internal.operations.OrmFileCreationDataModelProvider;
+import org.eclipse.jpt.core.internal.operations.PersistenceFileCreationDataModelProvider;
+import org.eclipse.jpt.utility.internal.AsynchronousCommandExecutor;
+import org.eclipse.jpt.utility.internal.BitTools;
+import org.eclipse.jpt.utility.internal.CallbackStatefulCommandExecutor;
+import org.eclipse.jpt.utility.internal.SimpleCommandExecutor;
+import org.eclipse.jpt.utility.internal.StringTools;
+import org.eclipse.jpt.utility.internal.SynchronizedBoolean;
+import org.eclipse.jpt.utility.internal.iterables.LiveCloneIterable;
+import org.eclipse.jpt.utility.internal.model.AbstractModel;
+import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
+import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
+import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
+import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectEvent;
+import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectListener;
+import org.eclipse.wst.common.project.facet.core.events.IProjectFacetActionEvent;
+
+/**
+ * The JPA model maintains a list of all JPA projects in the workspace.
+ * It keeps the list (and the state of the JPA projects themselves)
+ * synchronized with the workspace by listening for various
+ * changes:<ul>
+ * <li>Resource
+ * <li>Java
+ * <li>Faceted Project
+ * </ul>
+ * We use an Eclipse {@link ILock lock} to synchronize access to the JPA
+ * projects when dealing with these events. In an effort to reduce deadlocks,
+ * the simple Resource and Java change events are dispatched to a background
+ * thread, allowing us to handle the events outside of the workspace lock held
+ * during resource and Java change notifications.
+ * <p>
+ * Events that trigger either the adding or removing of a JPA project (e.g.
+ * {@link IFacetedProjectEvent.Type#POST_INSTALL}) are handled "synchronously"
+ * by allowing the background thread to handle any outstanding events before
+ * updating the list of JPA projects and returning execution to the event
+ * source.
+ * <p>
+ * Various things that cause us to add or remove a JPA project:<ul>
+ * <li>Startup of the Dali plug-in will trigger all the pre-existing JPA
+ * projects to be added
+ *
+ * <li>Project created and facet installed<p>
+ * {@link IFacetedProjectEvent.Type#POST_INSTALL}
+ * <li>Project facet uninstalled<p>
+ * {@link IFacetedProjectEvent.Type#PRE_UNINSTALL}
+ *
+ * <li>Project opened<p>
+ * {@link IFacetedProjectEvent.Type#PROJECT_MODIFIED}
+ * <li>Project closed<p>
+ * {@link IFacetedProjectEvent.Type#PROJECT_MODIFIED}
+ *
+ * <li>Pre-existing project imported from directory or archive (created and opened)<p>
+ * {@link IResourceChangeEvent#POST_CHANGE}
+ * -> {@link IResource#PROJECT}
+ * -> {@link IResourceDelta#ADDED}
+ * -> {@link IResourceDelta#OPEN}
+ * <li>Project renamed<p>
+ * {@link IResourceChangeEvent#POST_CHANGE}
+ * -> {@link IResource#PROJECT}
+ * -> {@link IResourceDelta#ADDED}
+ * -> {@link IResourceDelta#MOVED_FROM}
+ * <li>Project deleted<p>
+ * {@link IResourceChangeEvent#PRE_DELETE}
+ *
+ * <li>Project facet installed by editing the facets settings file directly<p>
+ * {@link IFacetedProjectEvent.Type#PROJECT_MODIFIED}
+ * <li>Project facet uninstalled by editing the facets settings file directly<p>
+ * {@link IFacetedProjectEvent.Type#PROJECT_MODIFIED}
+ * </ul>
+ */
+class GenericJpaModel
+ extends AbstractModel
+ implements JpaModel
+{
+ /**
+ * All the JPA projects in the workspace.
+ */
+ private final Vector<JpaProject> jpaProjects = new Vector<JpaProject>();
+
+ /**
+ * Synchronize access to the JPA projects.
+ */
+ /* private */ final ILock lock = this.getJobManager().newLock();
+
+ /**
+ * Determine how Resource and Java change events are
+ * handled (i.e. synchronously or asynchronously).
+ */
+ private volatile CallbackStatefulCommandExecutor eventHandler = new AsynchronousCommandExecutor(JptCoreMessages.DALI_EVENT_HANDLER_THREAD_NAME);
+
+ /**
+ * Listen for<ul>
+ * <li>changes to projects and files
+ * <li>deleted projects
+ * <li>clean builds
+ * </ul>
+ */
+ private final IResourceChangeListener resourceChangeListener = new ResourceChangeListener();
+
+ /**
+ * The types of resource change events that interest
+ * {@link #resourceChangeListener}.
+ */
+ private static final int RESOURCE_CHANGE_EVENT_TYPES =
+ IResourceChangeEvent.PRE_DELETE |
+ IResourceChangeEvent.POST_CHANGE |
+ IResourceChangeEvent.POST_BUILD;
+
+ /**
+ * Listen for the JPA facet being added to or removed from a "faceted" project.
+ */
+ private final IFacetedProjectListener facetedProjectListener = new FacetedProjectListener();
+
+ /**
+ * Listen for Java changes (unless the Dali UI is active).
+ * @see #javaElementChangeListenerIsActive
+ */
+ private final JavaElementChangeListener javaElementChangeListener = new JavaElementChangeListener();
+
+
+ // ********** constructor **********
+
+ /**
+ * internal - called by the Dali plug-in
+ */
+ GenericJpaModel() {
+ super();
+ }
+
+
+ // ********** plug-in controlled life-cycle **********
+
+ /**
+ * internal - called by the Dali plug-in
+ */
+ void start() {
+ try {
+ this.lock.acquire();
+ this.start_();
+ } finally {
+ this.lock.release();
+ }
+ }
+
+ private void start_() {
+ debug("*** JPA model START ***"); //$NON-NLS-1$
+ try {
+ this.buildJpaProjects();
+ this.eventHandler.start();
+ this.getWorkspace().addResourceChangeListener(this.resourceChangeListener, RESOURCE_CHANGE_EVENT_TYPES);
+ FacetedProjectFramework.addListener(this.facetedProjectListener, IFacetedProjectEvent.Type.values());
+ JavaCore.addElementChangedListener(this.javaElementChangeListener);
+ } catch (RuntimeException ex) {
+ JptCorePlugin.log(ex);
+ this.stop_();
+ }
+ }
+
+ private void buildJpaProjects() {
+ try {
+ this.buildJpaProjects_();
+ } catch (CoreException ex) {
+ // our visitor does not throw any exceptions
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private void buildJpaProjects_() throws CoreException {
+ this.getWorkspace().getRoot().accept(new ResourceProxyVisitor(), IResource.NONE);
+ }
+
+ /**
+ * internal - called by the Dali plug-in
+ */
+ void stop() throws Exception {
+ try {
+ this.lock.acquire();
+ this.stop_();
+ } finally {
+ this.lock.release();
+ }
+ }
+
+ private void stop_() {
+ debug("*** JPA model STOP ***"); //$NON-NLS-1$
+ JavaCore.removeElementChangedListener(this.javaElementChangeListener);
+ FacetedProjectFramework.removeListener(this.facetedProjectListener);
+ this.getWorkspace().removeResourceChangeListener(this.resourceChangeListener);
+ this.eventHandler.stop();
+ this.clearJpaProjects();
+ }
+
+ private void clearJpaProjects() {
+ // clone to prevent concurrent modification exceptions
+ for (JpaProject jpaProject : this.getJpaProjects_()) {
+ this.removeJpaProject(jpaProject);
+ }
+ }
+
+
+ // ********** JpaModel implementation **********
+
+ public Iterable<JpaProject> getJpaProjects() {
+ try {
+ this.lock.acquire();
+ return this.getJpaProjects_();
+ } finally {
+ this.lock.release();
+ }
+ }
+
+ private Iterable<JpaProject> getJpaProjects_() {
+ return new LiveCloneIterable<JpaProject>(this.jpaProjects);
+ }
+
+ public int getJpaProjectsSize() {
+ return this.jpaProjects.size();
+ }
+
+ public JpaProject getJpaProject(IProject project) {
+ try {
+ this.lock.acquire();
+ return this.getJpaProject_(project);
+ } finally {
+ this.lock.release();
+ }
+ }
+
+ private JpaProject getJpaProject_(IProject project) {
+ for (JpaProject jpaProject : this.jpaProjects) {
+ if (jpaProject.getProject().equals(project)) {
+ return jpaProject;
+ }
+ }
+ return null;
+ }
+
+ public JpaFile getJpaFile(IFile file) {
+ JpaProject jpaProject = this.getJpaProject(file.getProject());
+ return (jpaProject == null) ? null : jpaProject.getJpaFile(file);
+ }
+
+ public void rebuildJpaProject(IProject project) {
+ try {
+ this.lock.acquire();
+ this.rebuildJpaProject_(project);
+ } finally {
+ this.lock.release();
+ }
+ }
+
+ /**
+ * assumption: the JPA project holder exists
+ */
+ private void rebuildJpaProject_(IProject project) {
+ this.removeJpaProject(this.getJpaProject_(project));
+ this.addJpaProject(project);
+ }
+
+ public boolean javaElementChangeListenerIsActive() {
+ return this.javaElementChangeListener.isActive();
+ }
+
+ public void setJavaElementChangeListenerIsActive(boolean javaElementChangeListenerIsActive) {
+ this.javaElementChangeListener.setActive(javaElementChangeListenerIsActive);
+ }
+
+ public IWorkspace getWorkspace() {
+ return ResourcesPlugin.getWorkspace();
+ }
+
+ public IJobManager getJobManager() {
+ return Job.getJobManager();
+ }
+
+
+ // ********** adding/removing JPA projects **********
+
+ /* private */ void addJpaProject(IProject project) {
+ this.addJpaProject(this.buildJpaProject(project));
+ }
+
+ private void addJpaProject(JpaProject jpaProject) {
+ // figure out exactly when JPA projects are added
+ dumpStackTrace("add: ", jpaProject); //$NON-NLS-1$
+ // the jpa project can be null if we have problems getting the jpa platform
+ if (jpaProject != null) {
+ this.addItemToCollection(jpaProject, this.jpaProjects, JPA_PROJECTS_COLLECTION);
+ }
+ }
+
+ private JpaProject buildJpaProject(IProject project) {
+ return this.buildJpaProject(this.buildJpaProjectConfig(project));
+ }
+
+ private JpaProject buildJpaProject(JpaProject.Config config) {
+ JpaPlatform jpaPlatform = config.getJpaPlatform();
+ if (jpaPlatform == null) {
+ return null;
+ }
+ JpaProject result = jpaPlatform.getJpaFactory().buildJpaProject(config);
+ result.setUpdater(new AsynchronousJpaProjectUpdater(result));
+ return result;
+ }
+
+ private JpaProject.Config buildJpaProjectConfig(IProject project) {
+ SimpleJpaProjectConfig config = new SimpleJpaProjectConfig();
+ config.setProject(project);
+ config.setJpaPlatform(JptCorePlugin.getJpaPlatform(project));
+ config.setConnectionProfileName(JptCorePlugin.getConnectionProfileName(project));
+ config.setUserOverrideDefaultCatalog(JptCorePlugin.getUserOverrideDefaultCatalog(project));
+ config.setUserOverrideDefaultSchema(JptCorePlugin.getUserOverrideDefaultSchema(project));
+ config.setDiscoverAnnotatedClasses(JptCorePlugin.discoverAnnotatedClasses(project));
+ config.setMetamodelSourceFolderName(JptCorePlugin.getMetamodelSourceFolderName(project));
+ return config;
+ }
+
+ private void removeJpaProject(JpaProject jpaProject) {
+ // figure out exactly when JPA projects are removed
+ dumpStackTrace("remove: ", jpaProject); //$NON-NLS-1$
+ this.removeItemFromCollection(jpaProject, this.jpaProjects, JPA_PROJECTS_COLLECTION);
+ jpaProject.dispose();
+ }
+
+
+ // ********** Project POST_CHANGE **********
+
+ /**
+ * Forward the specified resource delta to all our JPA projects;
+ * they will each determine whether the event is significant.
+ */
+ /* private */ void projectChanged(IResourceDelta delta) {
+ this.eventHandler.execute(this.buildProjectChangedCommand(delta));
+ }
+
+ private Command buildProjectChangedCommand(final IResourceDelta delta) {
+ return new Command() {
+ @Override
+ void execute_() {
+ GenericJpaModel.this.projectChanged_(delta);
+ }
+ };
+ }
+
+ /* private */ void projectChanged_(IResourceDelta delta) {
+ for (JpaProject jpaProject : this.jpaProjects) {
+ jpaProject.projectChanged(delta);
+ }
+ }
+
+
+ // ********** Project POST_BUILD (CLEAN_BUILD) **********
+
+ /* private */ void projectPostCleanBuild(IProject project) {
+ this.waitForExecution(this.buildProjectPostCleanBuildCommand(project));
+ }
+
+ private Command buildProjectPostCleanBuildCommand(final IProject project) {
+ return new Command() {
+ @Override
+ void execute_() {
+ GenericJpaModel.this.projectPostCleanBuild_(project);
+ }
+ };
+ }
+
+ /* private */ void projectPostCleanBuild_(IProject project) {
+ JpaProject jpaProject = this.getJpaProject_(project);
+ if (jpaProject != null) {
+ this.removeJpaProject(jpaProject);
+ this.addJpaProject(project);
+ }
+ }
+
+
+ // ********** Project PRE_DELETE **********
+
+ /**
+ * A project is being deleted. Remove its corresponding
+ * JPA project if appropriate.
+ */
+ /* private */ void projectPreDelete(IProject project) {
+ this.waitForExecution(this.buildProjectPreDeleteCommand(project));
+ }
+
+ private Command buildProjectPreDeleteCommand(final IProject project) {
+ return new Command() {
+ @Override
+ void execute_() {
+ GenericJpaModel.this.projectPreDelete_(project);
+ }
+ };
+ }
+
+ /* private */ void projectPreDelete_(IProject project) {
+ JpaProject jpaProject = this.getJpaProject(project);
+ if (jpaProject != null) {
+ this.removeJpaProject(jpaProject);
+ }
+ }
+
+
+ // ********** Resource and/or Facet events **********
+
+ /**
+ * Check whether the JPA facet has been added or removed.
+ */
+ /* private */ void checkForJpaFacetTransition(IProject project) {
+ this.waitForExecution(this.buildCheckForJpaFacetTransitionCommand(project));
+ }
+
+ private Command buildCheckForJpaFacetTransitionCommand(final IProject project) {
+ return new Command() {
+ @Override
+ void execute_() {
+ GenericJpaModel.this.checkForJpaFacetTransition_(project);
+ }
+ };
+ }
+
+ /* private */ void checkForJpaFacetTransition_(IProject project) {
+ JpaProject jpaProject = this.getJpaProject_(project);
+
+ if (JptCorePlugin.projectHasJpaFacet(project)) {
+ if (jpaProject == null) { // JPA facet added
+ this.addJpaProject(project);
+ }
+ } else {
+ if (jpaProject != null) { // JPA facet removed
+ this.removeJpaProject(jpaProject);
+ }
+ }
+ }
+
+
+ // ********** FacetedProject POST_INSTALL **********
+
+ /* private */ void jpaFacetedProjectPostInstall(IProjectFacetActionEvent event) {
+ this.waitForExecution(this.buildJpaFacetedProjectPostInstallCommand(event));
+ }
+
+ private Command buildJpaFacetedProjectPostInstallCommand(final IProjectFacetActionEvent event) {
+ return new Command() {
+ @Override
+ void execute_() {
+ GenericJpaModel.this.jpaFacetedProjectPostInstall_(event);
+ }
+ };
+ }
+
+ /* private */ void jpaFacetedProjectPostInstall_(IProjectFacetActionEvent event) {
+ IProject project = event.getProject().getProject();
+ IDataModel dataModel = (IDataModel) event.getActionConfig();
+
+ // assume(?) this is the first event to indicate we need to add the JPA project to the JPA model
+ this.addJpaProject(project);
+
+ boolean buildOrmXml = dataModel.getBooleanProperty(JpaFacetInstallDataModelProperties.CREATE_ORM_XML);
+ this.createProjectXml(project, buildOrmXml);
+ }
+
+ private void createProjectXml(IProject project, boolean buildOrmXml) {
+ this.createPersistenceXml(project);
+
+ if (buildOrmXml) {
+ this.createOrmXml(project);
+ }
+ }
+
+ private void createPersistenceXml(IProject project) {
+ IDataModel config = DataModelFactory.createDataModel(new PersistenceFileCreationDataModelProvider());
+ config.setProperty(JpaFileCreationDataModelProperties.PROJECT_NAME, project.getName());
+ // default values for all other properties should suffice
+ try {
+ config.getDefaultOperation().execute(null, null);
+ } catch (ExecutionException ex) {
+ JptCorePlugin.log(ex);
+ }
+ }
+
+ private void createOrmXml(IProject project) {
+ IDataModel config = DataModelFactory.createDataModel(new OrmFileCreationDataModelProvider());
+ config.setProperty(JpaFileCreationDataModelProperties.PROJECT_NAME, project.getName());
+ // default values for all other properties should suffice
+ try {
+ config.getDefaultOperation().execute(null, null);
+ } catch (ExecutionException ex) {
+ JptCorePlugin.log(ex);
+ }
+ }
+
+
+ // ********** FacetedProject PRE_UNINSTALL **********
+
+ /* private */ void jpaFacetedProjectPreUninstall(IProjectFacetActionEvent event) {
+ IProject project = event.getProject().getProject();
+ this.waitForExecution(this.buildJpaFacetedProjectPreUninstallCommand(project));
+ }
+
+ private Command buildJpaFacetedProjectPreUninstallCommand(final IProject project) {
+ return new Command() {
+ @Override
+ void execute_() {
+ GenericJpaModel.this.jpaFacetedProjectPreUninstall_(project);
+ }
+ };
+ }
+
+ /* private */ void jpaFacetedProjectPreUninstall_(IProject project) {
+ // assume(?) this is the first event to indicate we need to remove the JPA project to the JPA model
+ this.removeJpaProject(this.getJpaProject_(project));
+ }
+
+
+ // ********** Java element changed **********
+
+ /**
+ * Forward the Java element changed event to all the JPA projects
+ * because the event could affect multiple projects.
+ */
+ /* private */ void javaElementChanged(ElementChangedEvent event) {
+ this.eventHandler.execute(this.buildJavaElementChangedCommand(event));
+ }
+
+ private Command buildJavaElementChangedCommand(final ElementChangedEvent event) {
+ return new Command() {
+ @Override
+ void execute_() {
+ GenericJpaModel.this.javaElementChanged_(event);
+ }
+ };
+ }
+
+ /* private */ void javaElementChanged_(ElementChangedEvent event) {
+ for (JpaProject jpaProject : this.jpaProjects) {
+ jpaProject.javaElementChanged(event);
+ }
+ }
+
+
+ // ********** miscellaneous **********
+
+ @Override
+ public void toString(StringBuilder sb) {
+ sb.append(this.jpaProjects);
+ }
+
+
+ // ********** event handler **********
+
+ private void waitForExecution(Command command) {
+ SynchronizedBoolean flag = new SynchronizedBoolean(false);
+ org.eclipse.jpt.utility.Command markerCommand = this.buildMarkerCommand();
+ EventHandlerListener listener = new EventHandlerListener(markerCommand, flag);
+ this.eventHandler.addListener(listener);
+ this.eventHandler.execute(markerCommand);
+ try {
+ flag.waitUntilTrue();
+ } catch (InterruptedException ex) {
+ // ignore - not sure why this thread would be interrupted
+ }
+ this.eventHandler.removeListener(listener);
+ command.execute();
+ }
+
+ private org.eclipse.jpt.utility.Command buildMarkerCommand() {
+ return new org.eclipse.jpt.utility.Command() {
+ public void execute() {
+ // do nothing
+ }
+ };
+ }
+
+ private static class EventHandlerListener implements CallbackStatefulCommandExecutor.Listener {
+ private final org.eclipse.jpt.utility.Command command;
+ private final SynchronizedBoolean flag;
+
+ EventHandlerListener(org.eclipse.jpt.utility.Command command, SynchronizedBoolean flag) {
+ super();
+ this.command = command;
+ this.flag = flag;
+ }
+
+ public void commandExecuted(org.eclipse.jpt.utility.Command c) {
+ if (c == this.command) {
+ this.flag.setTrue();
+ }
+ }
+ }
+
+ public void handleEventsSynchronously() {
+ try {
+ this.lock.acquire();
+ this.handleEventsSynchronously_();
+ } finally {
+ this.lock.release();
+ }
+ }
+
+ private void handleEventsSynchronously_() {
+ this.eventHandler.stop();
+ this.eventHandler = new SimpleCommandExecutor();
+ this.eventHandler.start();
+ }
+
+
+ // ********** resource proxy visitor **********
+
+ /**
+ * Visit the workspace resource tree, adding a JPA project to the
+ * JPA model for each open Eclipse project that has a JPA facet.
+ */
+ private class ResourceProxyVisitor implements IResourceProxyVisitor {
+ ResourceProxyVisitor() {
+ super();
+ }
+
+ public boolean visit(IResourceProxy resourceProxy) {
+ switch (resourceProxy.getType()) {
+ case IResource.ROOT :
+ return true; // all projects are in the "root"
+ case IResource.PROJECT :
+ this.checkProject(resourceProxy);
+ return false; // no nested projects
+ case IResource.FOLDER :
+ return false; // ignore
+ case IResource.FILE :
+ return false; // ignore
+ default :
+ return false;
+ }
+ }
+
+ private void checkProject(IResourceProxy resourceProxy) {
+ if (resourceProxy.isAccessible()) { // the project exists and is open
+ IProject project = (IProject) resourceProxy.requestResource();
+ if (JptCorePlugin.projectHasJpaFacet(project)) {
+ GenericJpaModel.this.addJpaProject(project);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+ }
+
+
+ // ********** command **********
+
+ /**
+ * Abstract class that holds the JPA model lock while
+ * executing.
+ */
+ private abstract class Command
+ implements org.eclipse.jpt.utility.Command
+ {
+ Command() {
+ super();
+ }
+
+ public final void execute() {
+ try {
+ GenericJpaModel.this.lock.acquire();
+ this.execute_();
+ } finally {
+ GenericJpaModel.this.lock.release();
+ }
+ }
+
+ abstract void execute_();
+
+ }
+
+
+ // ********** resource change listener **********
+
+ private class ResourceChangeListener implements IResourceChangeListener {
+
+ ResourceChangeListener() {
+ super();
+ }
+
+ /**
+ * Check for:<ul>
+ * <li>project close/delete
+ * <li>file add/remove
+ * <li>project open/rename
+ * </ul>
+ */
+ public void resourceChanged(IResourceChangeEvent event) {
+ switch (event.getType()) {
+ case IResourceChangeEvent.POST_CHANGE :
+ this.resourcePostChange(event);
+ break;
+
+ // workspace or project events
+ case IResourceChangeEvent.PRE_REFRESH :
+ break; // ignore
+ case IResourceChangeEvent.PRE_BUILD :
+ break; // ignore
+ case IResourceChangeEvent.POST_BUILD :
+ this.resourcePostBuild(event);
+ break;
+
+ // project-only events
+ case IResourceChangeEvent.PRE_CLOSE :
+ break; // ignore
+ case IResourceChangeEvent.PRE_DELETE :
+ this.resourcePreDelete(event);
+ break;
+ default :
+ break;
+ }
+ }
+
+ /**
+ * A resource has changed somehow.
+ * Check for files being added or removed.
+ * (The JPA project only handles added and removed files here
+ * File changes are handled via the Java Element Changed event.)
+ * Also check for opened projects.
+ */
+ private void resourcePostChange(IResourceChangeEvent event) {
+ debug("Resource POST_CHANGE"); //$NON-NLS-1$
+ this.resourceChanged(event.getDelta());
+ }
+
+ private void resourceChanged(IResourceDelta delta) {
+ IResource resource = delta.getResource();
+ switch (resource.getType()) {
+ case IResource.ROOT :
+ this.resourceChangedChildren(delta);
+ break;
+ case IResource.PROJECT :
+ this.projectChanged((IProject) resource, delta);
+ break;
+ case IResource.FOLDER :
+ break; // ignore
+ case IResource.FILE :
+ break; // ignore
+ default :
+ break;
+ }
+ }
+
+ private void resourceChangedChildren(IResourceDelta delta) {
+ for (IResourceDelta child : delta.getAffectedChildren()) {
+ this.resourceChanged(child); // recurse
+ }
+ }
+
+ private void projectChanged(IProject project, IResourceDelta delta) {
+ GenericJpaModel.this.projectChanged(delta);
+ this.checkForOpenedProject(project, delta);
+ }
+
+
+ /**
+ * Crawl the specified delta, looking for projects being opened.
+ * Projects being deleted are handled in {@link IResourceChangeEvent#PRE_DELETE}.
+ * Projects being closed are handled in {@link IFacetedProjectEvent.Type#PROJECT_MODIFIED}.
+ */
+ private void checkForOpenedProject(IProject project, IResourceDelta delta) {
+ switch (delta.getKind()) {
+ case IResourceDelta.ADDED : // all but project import and rename handled with the facet POST_INSTALL event
+ this.checkDeltaFlagsForOpenedProject(project, delta);
+ this.checkDeltaFlagsForRenamedProject(project, delta);
+ break;
+ case IResourceDelta.REMOVED : // already handled with the PRE_DELETE event
+ break;
+ case IResourceDelta.CHANGED :
+ this.checkDeltaFlagsForOpenedProject(project, delta);
+ break;
+ case IResourceDelta.ADDED_PHANTOM :
+ break; // ignore
+ case IResourceDelta.REMOVED_PHANTOM :
+ break; // ignore
+ default :
+ break;
+ }
+ }
+
+ /**
+ * We don't get any events from the Facets Framework when a pre-existing
+ * project is imported, so we need to check for the newly imported project here.
+ * <p>
+ * This event also occurs when a project is simply opened. Project opening
+ * also triggers a {@link IFacetedProjectEvent.Type#PROJECT_MODIFIED} event
+ * and that is where we add the JPA project, not here.
+ */
+ private void checkDeltaFlagsForOpenedProject(IProject project, IResourceDelta delta) {
+ if (BitTools.flagIsSet(delta.getFlags(), IResourceDelta.OPEN) && project.isOpen()) {
+ debug("\tProject CHANGED - OPEN: ", project.getName()); //$NON-NLS-1$
+ GenericJpaModel.this.checkForJpaFacetTransition(project);
+ }
+ }
+
+ /**
+ * We don't get any events from the Facets Framework when a project is renamed,
+ * so we need to check for the renamed projects here.
+ */
+ private void checkDeltaFlagsForRenamedProject(IProject project, IResourceDelta delta) {
+ if (BitTools.flagIsSet(delta.getFlags(), IResourceDelta.MOVED_FROM) && project.isOpen()) {
+ debug("\tProject ADDED - MOVED_FROM: ", delta.getMovedFromPath()); //$NON-NLS-1$
+ GenericJpaModel.this.checkForJpaFacetTransition(project);
+ }
+ }
+
+ /**
+ * A post build event has occurred.
+ * Check for whether the build was a "clean" build and trigger project update.
+ */
+ private void resourcePostBuild(IResourceChangeEvent event) {
+ debug("Resource POST_BUILD: ", event.getResource()); //$NON-NLS-1$
+ if (event.getBuildKind() == IncrementalProjectBuilder.CLEAN_BUILD) {
+ this.resourcePostCleanBuild(event.getDelta());
+ }
+ }
+
+ private void resourcePostCleanBuild(IResourceDelta delta) {
+ IResource resource = delta.getResource();
+ switch (resource.getType()) {
+ case IResource.ROOT :
+ this.resourcePostCleanBuildChildren(delta);
+ break;
+ case IResource.PROJECT :
+ this.projectPostCleanBuild((IProject) resource);
+ break;
+ case IResource.FOLDER :
+ break; // ignore
+ case IResource.FILE :
+ break; // ignore
+ default :
+ break;
+ }
+ }
+
+ private void resourcePostCleanBuildChildren(IResourceDelta delta) {
+ for (IResourceDelta child : delta.getAffectedChildren()) {
+ this.resourcePostCleanBuild(child); // recurse
+ }
+ }
+
+ private void projectPostCleanBuild(IProject project) {
+ debug("\tProject CLEAN: ", project.getName()); //$NON-NLS-1$
+ GenericJpaModel.this.projectPostCleanBuild(project);
+ }
+
+ /**
+ * A project is being deleted. Remove its corresponding
+ * JPA project if appropriate.
+ */
+ private void resourcePreDelete(IResourceChangeEvent event) {
+ IProject project = (IProject) event.getResource();
+ debug("Resource (Project) PRE_DELETE: ", project); //$NON-NLS-1$
+ GenericJpaModel.this.projectPreDelete(project);
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+ }
+
+
+ // ********** faceted project listener **********
+
+ /**
+ * Forward the Faceted project change event back to the JPA model.
+ */
+ private class FacetedProjectListener implements IFacetedProjectListener {
+
+ FacetedProjectListener() {
+ super();
+ }
+
+ /**
+ * Check for:<ul>
+ * <li>install of JPA facet
+ * <li>un-install of JPA facet
+ * <li>any other appearance or disappearance of the JPA facet
+ * </ul>
+ */
+ public void handleEvent(IFacetedProjectEvent event) {
+ switch (event.getType()) {
+ case POST_INSTALL :
+ this.facetedProjectPostInstall((IProjectFacetActionEvent) event);
+ break;
+ case PRE_UNINSTALL :
+ this.facetedProjectPreUninstall((IProjectFacetActionEvent) event);
+ break;
+ case PROJECT_MODIFIED :
+ this.facetedProjectModified(event.getProject().getProject());
+ break;
+ default :
+ break;
+ }
+ }
+
+ private void facetedProjectPostInstall(IProjectFacetActionEvent event) {
+ debug("Facet POST_INSTALL: ", event.getProjectFacet()); //$NON-NLS-1$
+ if (event.getProjectFacet().getId().equals(JptCorePlugin.FACET_ID)) {
+ GenericJpaModel.this.jpaFacetedProjectPostInstall(event);
+ }
+ }
+
+ private void facetedProjectPreUninstall(IProjectFacetActionEvent event) {
+ debug("Facet PRE_UNINSTALL: ", event.getProjectFacet()); //$NON-NLS-1$
+ if (event.getProjectFacet().getId().equals(JptCorePlugin.FACET_ID)) {
+ GenericJpaModel.this.jpaFacetedProjectPreUninstall(event);
+ }
+ }
+
+ /**
+ * This event is triggered for any change to a faceted project.
+ * We use the event to watch for the following:<ul>
+ * <li>an open project is closed
+ * <li>a closed project is opened
+ * <li>one of a project's (facet) metadata files is edited directly
+ * </ul>
+ */
+ private void facetedProjectModified(IProject project) {
+ debug("Facet PROJECT_MODIFIED: ", project.getName()); //$NON-NLS-1$
+ GenericJpaModel.this.checkForJpaFacetTransition(project);
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+ }
+
+
+ // ********** Java element change listener **********
+
+ /**
+ * Forward the Java element change event back to the JPA model.
+ */
+ private class JavaElementChangeListener implements IElementChangedListener {
+ /**
+ * A flag to activate/deactivate the listener
+ * so we can ignore Java events whenever Dali is manipulating the Java
+ * source code via the Dali model. We do this because the 0.5 sec delay
+ * between the Java source being changed and the corresponding event
+ * being fired causes us no end of pain.
+ */
+ private volatile boolean active = true;
+
+ JavaElementChangeListener() {
+ super();
+ }
+
+ public void elementChanged(ElementChangedEvent event) {
+ if (this.active) {
+ GenericJpaModel.this.javaElementChanged(event);
+ }
+ }
+
+ void setActive(boolean active) {
+ this.active = active;
+ }
+
+ boolean isActive() {
+ return this.active;
+ }
+
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
+ }
+
+
+ // ********** DEBUG **********
+
+ // @see JpaModelTests#testDEBUG()
+ private static final boolean DEBUG = false;
+
+ /**
+ * trigger #toString() call and string concatenation only if DEBUG is true
+ */
+ /* private */ static void debug(String message, Object object) {
+ if (DEBUG) {
+ debug_(message + object);
+ }
+ }
+
+ /* private */ static void debug(String message) {
+ if (DEBUG) {
+ debug_(message);
+ }
+ }
+
+ private static void debug_(String message) {
+ System.out.println(Thread.currentThread().getName() + ": " + message); //$NON-NLS-1$
+ }
+
+ /* private */ static void dumpStackTrace() {
+ dumpStackTrace(null);
+ }
+
+ /* private */ static void dumpStackTrace(String message, Object object) {
+ if (DEBUG) {
+ dumpStackTrace_(message + object);
+ }
+ }
+
+ /* private */ static void dumpStackTrace(String message) {
+ if (DEBUG) {
+ dumpStackTrace_(message);
+ }
+ }
+
+ private static void dumpStackTrace_(String message) {
+ // lock System.out so the stack elements are printed out contiguously
+ synchronized (System.out) {
+ if (message != null) {
+ debug_(message);
+ }
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ // skip the first 3 elements - those are this method and 2 methods in Thread
+ for (int i = 3; i < stackTrace.length; i++) {
+ StackTraceElement element = stackTrace[i];
+ if (element.getMethodName().equals("invoke0")) { //$NON-NLS-1$
+ break; // skip all elements outside of the JUnit test
+ }
+ System.out.println("\t" + element); //$NON-NLS-1$
+ }
+ }
+ }
+
+}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java
index 63133feab0..ed3693e965 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaFactory.java
@@ -10,7 +10,6 @@
package org.eclipse.jpt.core;
import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jpt.core.context.AssociationOverride;
import org.eclipse.jpt.core.context.AssociationOverrideContainer;
@@ -68,8 +67,6 @@ import org.eclipse.jpt.core.context.java.JavaTransientMapping;
import org.eclipse.jpt.core.context.java.JavaTypeMapping;
import org.eclipse.jpt.core.context.java.JavaUniqueConstraint;
import org.eclipse.jpt.core.context.java.JavaVersionMapping;
-import org.eclipse.jpt.core.context.orm.EntityMappings;
-import org.eclipse.jpt.core.context.persistence.PersistenceUnit;
import org.eclipse.jpt.core.resource.java.AssociationOverrideAnnotation;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentAttribute;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember;
@@ -111,7 +108,7 @@ public interface JpaFactory
* added to the specified JPA project. Return null if unable to create
* the JPA file (e.g. the content type is unrecognized).
*/
- JpaProject buildJpaProject(JpaProject.Config config) throws CoreException;
+ JpaProject buildJpaProject(JpaProject.Config config);
JpaDataSource buildJpaDataSource(JpaProject jpaProject, String connectionProfileName);
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaModel.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaModel.java
index 97d817d02c..09518e5a70 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaModel.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaModel.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2008 Oracle. All rights reserved.
+ * Copyright (c) 2006, 2009 Oracle. 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.
@@ -9,15 +9,13 @@
******************************************************************************/
package org.eclipse.jpt.core;
-import java.util.Iterator;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.jpt.utility.model.Model;
/**
- * The JPA model holds all the JPA projects.
- *
+ * The JPA model holds all the JPA projects in the workspace.
+ * <p>
* Provisional API: This interface is part of an interim API that is still
* under development and expected to change significantly before reaching
* stability. It is available at this early stage to solicit feedback from
@@ -27,34 +25,45 @@ import org.eclipse.jpt.utility.model.Model;
public interface JpaModel extends Model {
/**
+ * Return the JPA model's JPA projects.
+ */
+ Iterable<JpaProject> getJpaProjects();
+ public static final String JPA_PROJECTS_COLLECTION = "jpaProjects"; //$NON-NLS-1$
+
+ /**
+ * Return the size of the JPA model's list of JPA projects.
+ */
+ int getJpaProjectsSize();
+
+ /**
* Return the JPA project corresponding to the specified Eclipse project.
* Return null if unable to associate the specified Eclipse project
* with a JPA project.
*/
- JpaProject getJpaProject(IProject project) throws CoreException;
+ JpaProject getJpaProject(IProject project);
/**
- * Return whether the JPA model contains a JPA project corresponding
- * to the specified Eclipse project.
+ * Return the JPA file corresponding to the specified Eclipse file,
+ * or null if unable to associate the specified file with a JPA file.
*/
- boolean containsJpaProject(IProject project);
+ JpaFile getJpaFile(IFile file);
/**
- * Return the JPA model's JPA projects. This has performance implications,
- * it will build all the JPA projects.
+ * The JPA settings associated with the specified Eclipse project
+ * have changed in such a way as to require the associated
+ * JPA project to be completely rebuilt
+ * (e.g. when the user changes a project's JPA platform).
*/
- Iterator<JpaProject> jpaProjects() throws CoreException;
- public static final String JPA_PROJECTS_COLLECTION = "jpaProjects"; //$NON-NLS-1$
+ void rebuildJpaProject(IProject project);
/**
- * Return the size of the JPA model's list of JPA projects.
+ * Return whether the model's Java change listener is active.
*/
- int jpaProjectsSize();
-
+ boolean javaElementChangeListenerIsActive();
+
/**
- * Return the JPA file corresponding to the specified Eclipse file,
- * or null if unable to associate the specified file with a JPA file.
+ * Set whether the model's Java change listener is active.
*/
- JpaFile getJpaFile(IFile file) throws CoreException;
+ void setJavaElementChangeListenerIsActive(boolean javaElementChangeListenerIsActive);
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java
index 55a7ca4bf5..4f63da8621 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/JpaProject.java
@@ -10,10 +10,10 @@
package org.eclipse.jpt.core;
import java.util.Iterator;
+
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.ElementChangedEvent;
@@ -202,7 +202,7 @@ public interface JpaProject
* Synchronize the JPA project with the specified project resource
* delta, watching for added and removed files in particular.
*/
- void projectChanged(IResourceDelta delta) throws CoreException;
+ void projectChanged(IResourceDelta delta);
/**
* Synchronize the JPA project with the specified Java change.
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 cc92e43820..98260f81f8 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,6 +10,7 @@
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;
@@ -28,10 +29,8 @@ import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jpt.core.internal.GenericJpaPlatformProvider;
-import org.eclipse.jpt.core.internal.JpaModelManager;
import org.eclipse.jpt.core.internal.JpaPlatformRegistry;
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.wst.common.componentcore.ComponentCore;
@@ -44,20 +43,21 @@ import org.osgi.service.prefs.Preferences;
import org.osgi.util.tracker.ServiceTracker;
/**
- * The JPT plug-in lifecycle implementation.
+ * The Dali core plug-in lifecycle implementation.
* A number of globally-available constants and methods.
- *
+ * <p>
* Provisional API: This class is part of an interim API that is still
* under development and expected to change significantly before reaching
* stability. It is available at this early stage to solicit feedback from
* pioneering adopters on the understanding that any code that uses this API
* will almost certainly be broken (repeatedly) as the API evolves.
*/
-// TODO keep preferences in synch with the JPA project
-// (connection profile name, "discover" flag)
-// use listeners?
public class JptCorePlugin extends Plugin {
+ private volatile GenericJpaModel jpaModel;
+ private volatile ServiceTracker parserTracker;
+
+
// ********** public constants **********
/**
@@ -145,18 +145,18 @@ public class JptCorePlugin extends Plugin {
public static final JpaResourceType JAVA_SOURCE_RESOURCE_TYPE = new JpaResourceType(JAVA_SOURCE_CONTENT_TYPE);
/**
- * The content type for persistence.xml files.
+ * The content type for <code>persistence.xml</code> files.
*/
public static final IContentType PERSISTENCE_XML_CONTENT_TYPE = getJpaContentType("persistence"); //$NON-NLS-1$
/**
- * The resource type for persistence.xml version 1.0 files
+ * The resource type for <code>persistence.xml</code> version 1.0 files
*/
public static final JpaResourceType PERSISTENCE_XML_1_0_RESOURCE_TYPE =
new JpaResourceType(PERSISTENCE_XML_CONTENT_TYPE, org.eclipse.jpt.core.resource.persistence.JPA.SCHEMA_VERSION);
/**
- * The resource type for persistence.xml version 2.0 files
+ * The resource type for <code>persistence.xml</code> version 2.0 files
*/
public static final JpaResourceType PERSISTENCE_XML_2_0_RESOURCE_TYPE =
new JpaResourceType(PERSISTENCE_XML_CONTENT_TYPE, org.eclipse.jpt.core.resource.persistence.v2_0.JPA2_0.SCHEMA_VERSION);
@@ -167,18 +167,18 @@ public class JptCorePlugin extends Plugin {
public static final IContentType MAPPING_FILE_CONTENT_TYPE = getJpaContentType("mappingFile"); //$NON-NLS-1$
/**
- * The content type for orm.xml mapping files.
+ * The content type for <code>orm.xml</code> mapping files.
*/
public static final IContentType ORM_XML_CONTENT_TYPE = getJpaContentType("orm"); //$NON-NLS-1$
/**
- * The resource type for orm.xml version 1.0 mapping files
+ * The resource type for <code>orm.xml</code> version 1.0 mapping files
*/
public static final JpaResourceType ORM_XML_1_0_RESOURCE_TYPE =
new JpaResourceType(ORM_XML_CONTENT_TYPE, org.eclipse.jpt.core.resource.orm.JPA.SCHEMA_VERSION);
/**
- * The resource type for orm.xml version 2.0 mapping files
+ * The resource type for <code>orm.xml</code> version 2.0 mapping files
*/
public static final JpaResourceType ORM_XML_2_0_RESOURCE_TYPE =
new JpaResourceType(ORM_XML_CONTENT_TYPE, org.eclipse.jpt.core.resource.orm.v2_0.JPA2_0.SCHEMA_VERSION);
@@ -189,7 +189,7 @@ public class JptCorePlugin extends Plugin {
public static final IContentType JAR_CONTENT_TYPE = getJpaContentType("jar"); //$NON-NLS-1$
/**
- * The resource type for Java archives (JARs)
+ * The resource type for Java archives (JARs).
*/
public static final JpaResourceType JAR_RESOURCE_TYPE = new JpaResourceType(JAR_CONTENT_TYPE);
@@ -220,14 +220,12 @@ public class JptCorePlugin extends Plugin {
}
- private ServiceTracker parserTracker;
-
// ********** singleton **********
private static JptCorePlugin INSTANCE;
/**
- * Return the singleton JPT plug-in.
+ * Return the singleton Dali core plug-in.
*/
public static JptCorePlugin instance() {
return INSTANCE;
@@ -240,34 +238,34 @@ public class JptCorePlugin extends Plugin {
* Return the singular JPA model corresponding to the current workspace.
*/
public static JpaModel getJpaModel() {
- return JpaModelManager.instance().getJpaModel();
+ return INSTANCE.getJpaModel_();
}
/**
* Return the JPA project corresponding to the specified Eclipse project,
- * or null if unable to associate the specified project with a
+ * or <code>null</code> if unable to associate the specified project with a
* JPA project.
*/
public static JpaProject getJpaProject(IProject project) {
- try {
- return JpaModelManager.instance().getJpaProject(project);
- } catch (CoreException ex) {
- log(ex);
- return null;
- }
+ return getJpaModel().getJpaProject(project);
}
/**
* Return the JPA file corresponding to the specified Eclipse file,
- * or null if unable to associate the specified file with a JPA file.
+ * or <code>null</code> if unable to associate the specified file with a JPA file.
*/
public static JpaFile getJpaFile(IFile file) {
- try {
- return JpaModelManager.instance().getJpaFile(file);
- } catch (CoreException ex) {
- log(ex);
- return null;
- }
+ return getJpaModel().getJpaFile(file);
+ }
+
+ /**
+ * The JPA settings associated with the specified Eclipse project
+ * have changed in such a way as to require the associated
+ * JPA project to be completely rebuilt
+ * (e.g. when the user changes a project's JPA platform).
+ */
+ public static void rebuildJpaProject(IProject project) {
+ getJpaModel().rebuildJpaProject(project);
}
/**
@@ -278,7 +276,7 @@ public class JptCorePlugin extends Plugin {
}
/**
- * Return whether the specified Eclipse project has a JPA facet.
+ * Return whether the specified Eclipse project has a Web facet.
*/
public static boolean projectHasWebFacet(IProject project) {
return projectHasFacet(project, WEB_PROJECT_FACET_ID);
@@ -297,7 +295,7 @@ public class JptCorePlugin extends Plugin {
}
/**
- * Return the persistence.xml (specified as "META-INF/persistence.xml")
+ * Return the <code>persistence.xml</code> (specified as <code>"META-INF/persistence.xml"</code>)
* deployment URI for the specified project.
*/
public static String getPersistenceXmlDeploymentURI(IProject project) {
@@ -305,7 +303,7 @@ public class JptCorePlugin extends Plugin {
}
/**
- * Return the default mapping file (specified as "META-INF/orm.xml")
+ * Return the default mapping file (specified as <code>"META-INF/orm.xml"</code>)
* deployment URI for the specified project.
*/
public static String getDefaultOrmXmlDeploymentURI(IProject project) {
@@ -313,7 +311,7 @@ public class JptCorePlugin extends Plugin {
}
/**
- * Return the mapping file (specified as "META-INF/<mappingFileName>")
+ * Return the mapping file (specified as {@code"META-INF/<mappingFileName>"})
* deployment URI for the specified project.
*/
public static String getOrmXmlDeploymentURI(IProject project, String mappingFileName) {
@@ -322,7 +320,7 @@ public class JptCorePlugin extends Plugin {
/**
* Tweak the specified deployment URI if the specified project
- * has a web facet.
+ * has a Web facet.
*/
public static String getDeploymentURI(IProject project, String defaultURI) {
return projectHasWebFacet(project) ?
@@ -332,9 +330,9 @@ public class JptCorePlugin extends Plugin {
}
/**
- * Return the deployment path to which jars are relatively specified for
- * the given project
- * (Web projects have a different deployment structure than non-web projects)
+ * Return the deployment path to which JARs are relatively specified for
+ * the given project.
+ * (Web projects have a different deployment structure than non-web projects.)
*/
public static IPath getJarDeploymentRootPath(IProject project) {
return new Path(getJarDeploymentRootPathName(project));
@@ -415,12 +413,10 @@ public class JptCorePlugin extends Plugin {
if (jpaFacetVersion.equals(JPA_FACET_VERSION_1_0)) {
return GenericJpaPlatformProvider.ID;
}
- else if (jpaFacetVersion.equals(JPA_FACET_VERSION_2_0)) {
+ if (jpaFacetVersion.equals(JPA_FACET_VERSION_2_0)) {
return Generic2_0JpaPlatformProvider.ID;
}
- else {
- throw new IllegalArgumentException("Illegal JPA facet version: " + jpaFacetVersion);
- }
+ throw new IllegalArgumentException("Illegal JPA facet version: " + jpaFacetVersion); //$NON-NLS-1$
}
private static String getDefaultJpaPlatformId(Preferences... nodes) {
@@ -602,6 +598,20 @@ public class JptCorePlugin extends Plugin {
}
/**
+ * Return whether the model manager's Java change listener is active.
+ */
+ public static boolean javaElementChangeListenerIsActive() {
+ return getJpaModel().javaElementChangeListenerIsActive();
+ }
+
+ /**
+ * Set whether the model manager's Java change listener is active.
+ */
+ public static void setJavaElementChangeListenerIsActive(boolean javaElementChangeListenerIsActive) {
+ getJpaModel().setJavaElementChangeListenerIsActive(javaElementChangeListenerIsActive);
+ }
+
+ /**
* Log the specified status.
*/
public static void log(IStatus status) {
@@ -638,13 +648,16 @@ public class JptCorePlugin extends Plugin {
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
- JpaModelManager.instance().start();
+ // nothing yet...
}
@Override
public void stop(BundleContext context) throws Exception {
try {
- JpaModelManager.instance().stop();
+ if (this.jpaModel != null) {
+ this.jpaModel.stop();
+ this.jpaModel = null;
+ }
if (this.parserTracker != null) {
this.parserTracker.close();
this.parserTracker = null;
@@ -654,6 +667,18 @@ public class JptCorePlugin extends Plugin {
}
}
+ private synchronized GenericJpaModel getJpaModel_() {
+ if (this.jpaModel == null) {
+ this.jpaModel = this.buildJpaModel();
+ this.jpaModel.start();
+ }
+ return this.jpaModel;
+ }
+
+ private GenericJpaModel buildJpaModel() {
+ return new GenericJpaModel();
+ }
+
public synchronized SAXParserFactory getSAXParserFactory() {
SAXParserFactory factory = (SAXParserFactory) this.getParserTracker().getService();
if (factory != null) {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
index efacae6803..4ce3c05476 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/AbstractJpaFactory.java
@@ -10,7 +10,6 @@
package org.eclipse.jpt.core.internal;
import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jpt.core.JpaDataSource;
import org.eclipse.jpt.core.JpaFile;
@@ -155,7 +154,7 @@ public abstract class AbstractJpaFactory
// ********** Core Model **********
- public JpaProject buildJpaProject(JpaProject.Config config) throws CoreException {
+ public JpaProject buildJpaProject(JpaProject.Config config) {
return new GenericJpaProject((JpaProject2_0.Config) config);
}
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 ca0ed219c7..0058ec7e0d 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
@@ -191,7 +191,7 @@ public abstract class AbstractJpaProject
// ********** constructor/initialization **********
- protected AbstractJpaProject(JpaProject2_0.Config config) throws CoreException {
+ protected AbstractJpaProject(JpaProject2_0.Config config) {
super(null); // JPA project is the root of the containment tree
if ((config.getProject() == null) || (config.getJpaPlatform() == null)) {
throw new NullPointerException();
@@ -207,7 +207,8 @@ public abstract class AbstractJpaProject
this.resourceModelListener = this.buildResourceModelListener();
// build the JPA files corresponding to the Eclipse project's files
- this.project.accept(this.buildInitialResourceProxyVisitor(), IResource.NONE);
+ InitialResourceProxyVisitor visitor = this.buildInitialResourceProxyVisitor();
+ visitor.visitProject(this.project);
this.externalJavaResourcePersistentTypeCache = this.buildExternalJavaResourcePersistentTypeCache();
@@ -243,7 +244,7 @@ public abstract class AbstractJpaProject
return new DefaultResourceModelListener();
}
- protected IResourceProxyVisitor buildInitialResourceProxyVisitor() {
+ protected InitialResourceProxyVisitor buildInitialResourceProxyVisitor() {
return new InitialResourceProxyVisitor();
}
@@ -286,8 +287,16 @@ public abstract class AbstractJpaProject
protected InitialResourceProxyVisitor() {
super();
}
+ protected void visitProject(IProject p) {
+ try {
+ p.accept(this, IResource.NONE);
+ } catch (CoreException ex) {
+ // we don't throw any CoreExceptions
+ throw new RuntimeException(ex);
+ }
+ }
// add a JPA file for every [appropriate] file encountered by the visitor
- public boolean visit(IResourceProxy resource) throws CoreException {
+ public boolean visit(IResourceProxy resource) {
switch (resource.getType()) {
case IResource.ROOT : // shouldn't happen
return true; // visit children
@@ -1227,7 +1236,7 @@ public abstract class AbstractJpaProject
// ********** resource events **********
// TODO need to do the same thing for external projects and compilation units
- public void projectChanged(IResourceDelta delta) throws CoreException {
+ public void projectChanged(IResourceDelta delta) {
if (delta.getResource().equals(this.getProject())) {
this.internalProjectChanged(delta);
} else {
@@ -1235,9 +1244,9 @@ public abstract class AbstractJpaProject
}
}
- protected void internalProjectChanged(IResourceDelta delta) throws CoreException {
+ protected void internalProjectChanged(IResourceDelta delta) {
ResourceDeltaVisitor resourceDeltaVisitor = this.buildInternalResourceDeltaVisitor();
- delta.accept(resourceDeltaVisitor);
+ resourceDeltaVisitor.visitDelta(delta);
// at this point, if we have added and/or removed JpaFiles, an "update" will have been triggered;
// any changes to the resource model during the "resolve" will trigger further "updates";
// there should be no need to "resolve" external Java types (they can't have references to
@@ -1304,10 +1313,10 @@ public abstract class AbstractJpaProject
}
}
- protected void externalProjectChanged(IResourceDelta delta) throws CoreException {
+ protected void externalProjectChanged(IResourceDelta delta) {
if (this.getJavaProject().isOnClasspath(delta.getResource())) {
ResourceDeltaVisitor resourceDeltaVisitor = this.buildExternalResourceDeltaVisitor();
- delta.accept(resourceDeltaVisitor);
+ resourceDeltaVisitor.visitDelta(delta);
// force an "update" here since adding and/or removing an external Java type
// will only trigger an "update" if the "resolve" causes something in the resource model to change
if (resourceDeltaVisitor.encounteredSignificantChange()) {
@@ -1396,7 +1405,16 @@ public abstract class AbstractJpaProject
super();
}
- public boolean visit(IResourceDelta delta) throws CoreException {
+ protected void visitDelta(IResourceDelta delta) {
+ try {
+ delta.accept(this);
+ } catch (CoreException ex) {
+ // we don't throw any CoreExceptions
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public boolean visit(IResourceDelta delta) {
IResource res = delta.getResource();
switch (res.getType()) {
case IResource.ROOT :
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java
deleted file mode 100644
index 9bdaceb461..0000000000
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/GenericJpaModel.java
+++ /dev/null
@@ -1,528 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2009 Oracle. 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:
- * Oracle - initial API and implementation
- ******************************************************************************/
-package org.eclipse.jpt.core.internal;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IResourceProxy;
-import org.eclipse.core.resources.IResourceProxyVisitor;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.ElementChangedEvent;
-import org.eclipse.jpt.core.JpaFile;
-import org.eclipse.jpt.core.JpaModel;
-import org.eclipse.jpt.core.JpaPlatform;
-import org.eclipse.jpt.core.JpaProject;
-import org.eclipse.jpt.core.JptCorePlugin;
-import org.eclipse.jpt.core.JpaProject.Config;
-import org.eclipse.jpt.core.internal.facet.JpaFacetInstallDataModelProperties;
-import org.eclipse.jpt.core.internal.operations.OrmFileCreationDataModelProperties;
-import org.eclipse.jpt.core.internal.operations.OrmFileCreationDataModelProvider;
-import org.eclipse.jpt.core.internal.operations.PersistenceFileCreationDataModelProperties;
-import org.eclipse.jpt.core.internal.operations.PersistenceFileCreationDataModelProvider;
-import org.eclipse.jpt.utility.internal.ClassTools;
-import org.eclipse.jpt.utility.internal.StringTools;
-import org.eclipse.jpt.utility.internal.model.AbstractModel;
-import org.eclipse.wst.common.frameworks.datamodel.DataModelFactory;
-import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
-import org.eclipse.wst.common.project.facet.core.events.IProjectFacetActionEvent;
-
-/**
- * The JPA model is synchronized so all changes to the list of JPA projects
- * are thread-safe.
- *
- * The JPA model holds on to a list of JPA project configs and only instantiates
- * their associated JPA projects when necessary. Other than performance,
- * this should be transparent to clients.
- */
-public class GenericJpaModel
- extends AbstractModel
- implements JpaModel
-{
-
- /** maintain a list of all the current JPA projects */
- private final ArrayList<JpaProjectHolder> jpaProjectHolders = new ArrayList<JpaProjectHolder>();
-
-
- // ********** constructor **********
-
- /**
- * Construct a JPA model and populate it with JPA projects for all the
- * current Eclipse projects with JPA facets.
- * The JPA model can only be instantiated by the JPA model manager.
- */
- GenericJpaModel() throws CoreException {
- super();
- ResourcesPlugin.getWorkspace().getRoot().accept(new ResourceProxyVisitor(), IResource.NONE);
- }
-
-
- // ********** IJpaModel implementation **********
-
- /**
- * This will trigger the instantiation of the JPA project associated with the
- * specified Eclipse project.
- */
- public synchronized JpaProject getJpaProject(IProject project) throws CoreException {
- return this.getJpaProjectHolder(project).jpaProject();
- }
-
- /**
- * We can answer this question without instantiating the
- * associated JPA project.
- */
- public synchronized boolean containsJpaProject(IProject project) {
- return this.getJpaProjectHolder(project).holdsJpaProjectFor(project);
- }
-
- /**
- * This will trigger the instantiation of all the JPA projects.
- */
- public synchronized Iterator<JpaProject> jpaProjects() throws CoreException {
- // force the CoreException to occur here (instead of later, in Iterator#next())
- ArrayList<JpaProject> jpaProjects = new ArrayList<JpaProject>(this.jpaProjectHolders.size());
- for (JpaProjectHolder holder : this.jpaProjectHolders) {
- jpaProjects.add(holder.jpaProject());
- }
- return jpaProjects.iterator();
- }
-
- /**
- * We can answer this question without instantiating any JPA projects.
- */
- public synchronized int jpaProjectsSize() {
- return this.jpaProjectHolders.size();
- }
-
- /**
- * This will trigger the instantiation of the JPA project associated with the
- * specified file.
- */
- public synchronized JpaFile getJpaFile(IFile file) throws CoreException {
- JpaProject jpaProject = this.getJpaProject(file.getProject());
- return (jpaProject == null) ? null : jpaProject.getJpaFile(file);
- }
-
-
- // ********** internal methods **********
-
- /**
- * never return null
- */
- private JpaProjectHolder getJpaProjectHolder(IProject project) {
- for (JpaProjectHolder holder : this.jpaProjectHolders) {
- if (holder.holdsJpaProjectFor(project)) {
- return holder;
- }
- }
- return NullJpaProjectHolder.instance();
- }
-
- private JpaProject.Config buildJpaProjectConfig(IProject project) {
- SimpleJpaProjectConfig config = new SimpleJpaProjectConfig();
- config.setProject(project);
- config.setJpaPlatform(JptCorePlugin.getJpaPlatform(project));
- config.setConnectionProfileName(JptCorePlugin.getConnectionProfileName(project));
- config.setUserOverrideDefaultCatalog(JptCorePlugin.getUserOverrideDefaultCatalog(project));
- config.setUserOverrideDefaultSchema(JptCorePlugin.getUserOverrideDefaultSchema(project));
- config.setDiscoverAnnotatedClasses(JptCorePlugin.discoverAnnotatedClasses(project));
- config.setMetamodelSourceFolderName(JptCorePlugin.getMetamodelSourceFolderName(project));
- return config;
- }
-
- /* private */ void addJpaProject(IProject project) {
- this.addJpaProject(this.buildJpaProjectConfig(project));
- }
-
- /**
- * Add a JPA project to the JPA model for the specified Eclipse project.
- * JPA projects can only be added by the JPA model manager.
- * The JPA project will only be instantiated later, on demand.
- */
- private void addJpaProject(JpaProject.Config config) {
- dumpStackTrace(); // figure out exactly when JPA projects are added
- this.jpaProjectHolders.add(this.getJpaProjectHolder(config.getProject()).buildJpaProjectHolder(this, config));
- }
-
- /**
- * Remove the JPA project corresponding to the specified Eclipse project
- * from the JPA model. Return whether the removal actually happened.
- * JPA projects can only be removed by the JPA model manager.
- */
- private void removeJpaProject(IProject project) {
- dumpStackTrace(); // figure out exactly when JPA projects are removed
- this.getJpaProjectHolder(project).remove();
- }
-
-
- // ********** Resource events **********
-
- /**
- * A project is being deleted. Remove its corresponding
- * JPA project if appropriate.
- */
- synchronized void projectPreDelete(IProject project) {
- this.removeJpaProject(project);
- }
-
- /**
- * Forward the specified resource delta to all our JPA projects;
- * they will each determine whether the event is significant.
- */
- synchronized void projectChanged(IResourceDelta delta) throws CoreException {
- for (JpaProjectHolder holder : this.jpaProjectHolders) {
- holder.projectChanged(delta);
- }
- }
-
-
- // ********** Resource and/or Facet events **********
-
- /**
- * Check whether the JPA facet has been added or removed.
- */
- synchronized void checkForTransition(IProject project) {
- boolean jpaFacet = JptCorePlugin.projectHasJpaFacet(project);
- boolean jpaProject = this.containsJpaProject(project);
-
- if (jpaFacet) {
- if ( ! jpaProject) { // JPA facet added
- this.addJpaProject(project);
- }
- } else {
- if (jpaProject) { // JPA facet removed
- this.removeJpaProject(project);
- }
- }
- }
-
-
- // ********** Facet events **********
-
- synchronized void jpaFacetedProjectPostInstall(IProjectFacetActionEvent event) {
- IProject project = event.getProject().getProject();
- IDataModel dataModel = (IDataModel) event.getActionConfig();
-
- boolean buildOrmXml = dataModel.getBooleanProperty(JpaFacetInstallDataModelProperties.CREATE_ORM_XML);
- this.createProjectXml(project, buildOrmXml);
-
- // assume(?) this is the first event to indicate we need to add the JPA project to the JPA model
- this.addJpaProject(project);
- }
-
- private void createProjectXml(IProject project, boolean buildOrmXml) {
- this.createPersistenceXml(project);
-
- if (buildOrmXml) {
- this.createOrmXml(project);
- }
- }
-
- private void createPersistenceXml(IProject project) {
- IDataModel config =
- DataModelFactory.createDataModel(new PersistenceFileCreationDataModelProvider());
- config.setProperty(PersistenceFileCreationDataModelProperties.PROJECT_NAME, project.getName());
- // default values for all other properties should suffice
- try {
- config.getDefaultOperation().execute(null, null);
- }
- catch (ExecutionException e) {
- JptCorePlugin.log(e);
- }
- }
-
- private void createOrmXml(IProject project) {
- IDataModel config =
- DataModelFactory.createDataModel(new OrmFileCreationDataModelProvider());
- config.setProperty(OrmFileCreationDataModelProperties.PROJECT_NAME, project.getName());
- // default values for all other properties should suffice
- try {
- config.getDefaultOperation().execute(null, null);
- }
- catch (ExecutionException e) {
- JptCorePlugin.log(e);
- }
- }
-
- // TODO remove classpath items? persistence.xml? orm.xml?
- synchronized void jpaFacetedProjectPreUninstall(IProjectFacetActionEvent event) {
- // assume(?) this is the first event to indicate we need to remove the JPA project to the JPA model
- this.removeJpaProject(event.getProject().getProject());
- }
-
-
- // ********** Java events **********
-
- /**
- * Forward the Java element changed event to all the JPA projects
- * because the event could affect multiple projects.
- */
- synchronized void javaElementChanged(ElementChangedEvent event) {
- for (JpaProjectHolder jpaProjectHolder : this.jpaProjectHolders) {
- jpaProjectHolder.javaElementChanged(event);
- }
- }
-
-
- // ********** miscellaneous **********
-
- /**
- * The JPA settings associated with the specified Eclipse project
- * have changed in such a way as to require the associated
- * JPA project to be completely rebuilt
- * (e.g. when the user changes a project's JPA platform).
- */
- synchronized void rebuildJpaProject(IProject project) {
- this.removeJpaProject(project);
- this.addJpaProject(project);
- }
-
- /**
- * Dispose the JPA model by disposing and removing all its JPA projects.
- * The JPA model can only be disposed by the JPA model manager.
- */
- synchronized void dispose() {
- // clone the list to prevent concurrent modification exceptions
- JpaProjectHolder[] holders = this.jpaProjectHolders.toArray(new JpaProjectHolder[this.jpaProjectHolders.size()]);
- for (JpaProjectHolder holder : holders) {
- holder.remove();
- }
- }
-
- @Override
- public void toString(StringBuilder sb) {
- sb.append("JPA projects size: " + this.jpaProjectsSize()); //$NON-NLS-1$
- }
-
-
- // ********** holder callbacks **********
-
- /**
- * called by the JPA project holder when the JPA project is actually
- * instantiated
- */
- /* private */ void jpaProjectBuilt(JpaProject jpaProject) {
- this.fireItemAdded(JPA_PROJECTS_COLLECTION, jpaProject);
- }
-
- /**
- * called by the JPA project holder if the JPA project has been
- * instantiated and we need to remove it
- */
- /* private */ void jpaProjectRemoved(JpaProject jpaProject) {
- this.fireItemRemoved(JPA_PROJECTS_COLLECTION, jpaProject);
- }
-
- /**
- * called by the JPA project holder
- */
- /* private */ void removeJpaProjectHolder(JpaProjectHolder jpaProjectHolder) {
- this.jpaProjectHolders.remove(jpaProjectHolder);
- }
-
-
- // ********** JPA project holders **********
-
- private interface JpaProjectHolder {
-
- boolean holdsJpaProjectFor(IProject project);
-
- JpaProject jpaProject() throws CoreException;
-
- void projectChanged(IResourceDelta delta) throws CoreException;
-
- void javaElementChanged(ElementChangedEvent event);
-
- JpaProjectHolder buildJpaProjectHolder(GenericJpaModel jpaModel, JpaProject.Config config);
-
- void remove();
-
- }
-
- private static class NullJpaProjectHolder implements JpaProjectHolder {
- private static final JpaProjectHolder INSTANCE = new NullJpaProjectHolder();
-
- static JpaProjectHolder instance() {
- return INSTANCE;
- }
-
- // ensure single instance
- private NullJpaProjectHolder() {
- super();
- }
-
- public boolean holdsJpaProjectFor(IProject project) {
- return false;
- }
-
- public JpaProject jpaProject() throws CoreException {
- return null;
- }
-
- public void projectChanged(IResourceDelta delta) throws CoreException {
- // do nothing
- }
-
- public void javaElementChanged(ElementChangedEvent event) {
- // do nothing
- }
-
- public JpaProjectHolder buildJpaProjectHolder(GenericJpaModel jpaModel, Config config) {
- return new DefaultJpaProjectHolder(jpaModel, config);
- }
-
- public void remove() {
- // do nothing
- }
-
- @Override
- public String toString() {
- return ClassTools.shortClassNameForObject(this);
- }
- }
-
- /**
- * Pair a JPA project config with its lazily-initialized JPA project.
- */
- private static class DefaultJpaProjectHolder implements JpaProjectHolder {
- private final GenericJpaModel jpaModel;
- private final JpaProject.Config config;
- private JpaProject jpaProject;
-
- DefaultJpaProjectHolder(GenericJpaModel jpaModel, JpaProject.Config config) {
- super();
- this.jpaModel = jpaModel;
- this.config = config;
- }
-
- public boolean holdsJpaProjectFor(IProject project) {
- return this.config.getProject().equals(project);
- }
-
- public JpaProject jpaProject() throws CoreException {
- if (this.jpaProject == null) {
- this.jpaProject = this.buildJpaProject();
- // notify listeners of the JPA model
- this.jpaModel.jpaProjectBuilt(this.jpaProject);
- }
- return this.jpaProject;
- }
-
- private JpaProject buildJpaProject() throws CoreException {
- JpaPlatform jpaPlatform = this.config.getJpaPlatform();
- if (jpaPlatform == null) {
- return null;
- }
- JpaProject result = jpaPlatform.getJpaFactory().buildJpaProject(this.config);
- result.setUpdater(new AsynchronousJpaProjectUpdater(result));
- return result;
- }
-
- public void projectChanged(IResourceDelta delta) throws CoreException {
- if (this.jpaProject != null) {
- this.jpaProject.projectChanged(delta);
- }
- }
-
- public void javaElementChanged(ElementChangedEvent event) {
- if (this.jpaProject != null) {
- this.jpaProject.javaElementChanged(event);
- }
- }
-
- public JpaProjectHolder buildJpaProjectHolder(GenericJpaModel jm, Config c) {
- throw new IllegalArgumentException(c.getProject().getName());
- }
-
- public void remove() {
- this.jpaModel.removeJpaProjectHolder(this);
- if (this.jpaProject != null) {
- this.jpaModel.jpaProjectRemoved(this.jpaProject);
- this.jpaProject.dispose();
- }
- }
-
- @Override
- public String toString() {
- return StringTools.buildToStringFor(this, this.config.getProject().getName());
- }
-
- }
-
-
- // ********** resource proxy visitor **********
-
- /**
- * Visit the workspace resource tree, adding a JPA project to the
- * JPA model for each open Eclipse project that has a JPA facet.
- */
- private class ResourceProxyVisitor implements IResourceProxyVisitor {
-
- ResourceProxyVisitor() {
- super();
- }
-
- public boolean visit(IResourceProxy resourceProxy) throws CoreException {
- switch (resourceProxy.getType()) {
- case IResource.ROOT :
- return true; // all projects are in the "root"
- case IResource.PROJECT :
- this.checkProject(resourceProxy);
- return false; // no nested projects
- default :
- return false;
- }
- }
-
- private void checkProject(IResourceProxy resourceProxy) {
- if (resourceProxy.isAccessible()) { // the project exists and is open
- IProject project = (IProject) resourceProxy.requestResource();
- if (JptCorePlugin.projectHasJpaFacet(project)) {
- GenericJpaModel.this.addJpaProject(project);
- }
- }
- }
-
- @Override
- public String toString() {
- return StringTools.buildToStringFor(this);
- }
-
- }
-
-
- // ********** DEBUG **********
-
- // @see JpaModelTests#testDEBUG()
- private static final boolean DEBUG = false;
-
- private static void dumpStackTrace() {
- if (DEBUG) {
- // lock System.out so the stack elements are printed out contiguously
- synchronized (System.out) {
- StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
- // skip the first 3 elements - those are this method and 2 methods in Thread
- for (int i = 3; i < stackTrace.length; i++) {
- StackTraceElement element = stackTrace[i];
- if (element.getMethodName().equals("invoke0")) { //$NON-NLS-1$
- break; // skip all elements outside of the JUnit test
- }
- System.out.println("\t" + element); //$NON-NLS-1$
- }
- }
- }
- }
-
-}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java
deleted file mode 100644
index b4ec22bef0..0000000000
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/JpaModelManager.java
+++ /dev/null
@@ -1,590 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006, 2008 Oracle. 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:
- * Oracle - initial API and implementation
- ******************************************************************************/
-package org.eclipse.jpt.core.internal;
-
-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.IWorkspace;
-import org.eclipse.core.resources.IncrementalProjectBuilder;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.jdt.core.ElementChangedEvent;
-import org.eclipse.jdt.core.IElementChangedListener;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaElementDelta;
-import org.eclipse.jdt.core.IOpenable;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jpt.core.JpaFile;
-import org.eclipse.jpt.core.JpaModel;
-import org.eclipse.jpt.core.JpaProject;
-import org.eclipse.jpt.core.JptCorePlugin;
-import org.eclipse.jpt.utility.internal.BitTools;
-import org.eclipse.jpt.utility.internal.StringTools;
-import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework;
-import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectEvent;
-import org.eclipse.wst.common.project.facet.core.events.IFacetedProjectListener;
-import org.eclipse.wst.common.project.facet.core.events.IProjectFacetActionEvent;
-
-/**
- * "Internal" global stuff.
- * Provide access via a singleton.
- * Hold and manage the JPA model (which holds all the JPA projects)
- * and the various global listeners. We attempt to determine whether events
- * are relevant before forwarding them to the JPA model.
- *
- * Various things that cause us to add or remove a JPA project:
- * - Startup of the Dali plug-in will trigger all the JPA projects to be added
- *
- * - Project created and facet installed
- * facet POST_INSTALL
- * - Project facet uninstalled
- * facet PRE_UNINSTALL
- *
- * - Project opened
- * facet PROJECT_MODIFIED
- * - Project closed
- * facet PROJECT_MODIFIED
- *
- * - Pre-existing project imported from directory or archive (created and opened)
- * resource POST_CHANGE -> PROJECT -> ADDED -> OPEN
- * - Project deleted
- * resource PRE_DELETE
- *
- * - Project facet installed by editing the facets settings file directly
- * facet PROJECT_MODIFIED
- * - Project facet uninstalled by editing the facets settings file directly
- * facet PROJECT_MODIFIED
- */
-public class JpaModelManager {
-
- /**
- * The JPA model - null until the plug-in is started.
- */
- private GenericJpaModel jpaModel;
-
- /**
- * Listen for changes to projects and files.
- */
- private final IResourceChangeListener resourceChangeListener;
-
- /**
- * Listen for the JPA facet being added or removed from a project.
- */
- private final IFacetedProjectListener facetedProjectListener;
-
- /**
- * Listen for Java changes and forward them to the JPA model,
- * which will forward them to the JPA projects.
- */
- private final IElementChangedListener javaElementChangeListener;
- private boolean javaElementChangeListenerIsActive;
-
-
- // ********** singleton **********
-
- private static final JpaModelManager INSTANCE = new JpaModelManager();
-
- /**
- * Return the singleton JPA model manager.
- */
- public static JpaModelManager instance() {
- return INSTANCE;
- }
-
-
- // ********** constructor **********
-
- /**
- * Private - ensure single instance.
- */
- private JpaModelManager() {
- super();
- this.resourceChangeListener = new ResourceChangeListener();
- this.facetedProjectListener = new FacetedProjectListener();
- this.javaElementChangeListener = new JavaElementChangeListener();
- this.javaElementChangeListenerIsActive = true;
- }
-
-
- // ********** plug-in controlled life-cycle **********
-
- /**
- * internal - called by JptCorePlugin
- */
- public synchronized void start() throws Exception {
- debug("*** START JPA model manager ***"); //$NON-NLS-1$
- try {
- this.jpaModel = new GenericJpaModel();
- ResourcesPlugin.getWorkspace().addResourceChangeListener(
- this.resourceChangeListener,
- IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.POST_BUILD);
- FacetedProjectFramework.addListener(this.facetedProjectListener, IFacetedProjectEvent.Type.values());
- JavaCore.addElementChangedListener(this.javaElementChangeListener);
- } catch (RuntimeException ex) {
- this.log(ex);
- this.stop();
- }
- }
-
- /**
- * internal - called by JptCorePlugin
- */
- public synchronized void stop() throws Exception {
- debug("*** STOP JPA model manager ***"); //$NON-NLS-1$
- JavaCore.removeElementChangedListener(this.javaElementChangeListener);
- FacetedProjectFramework.removeListener(this.facetedProjectListener);
- ResourcesPlugin.getWorkspace().removeResourceChangeListener(this.resourceChangeListener);
- this.jpaModel.dispose();
- this.jpaModel = null;
- }
-
-
- // ********** API **********
-
- /**
- * Return the workspace-wide JPA model.
- */
- public JpaModel getJpaModel() {
- return this.jpaModel;
- }
-
- /**
- * Return the JPA project corresponding to the specified Eclipse project,
- * or null if unable to associate the specified project with a
- * JPA project.
- */
- public JpaProject getJpaProject(IProject project) throws CoreException {
- return this.jpaModel.getJpaProject(project);
- }
-
- /**
- * Return the JPA file corresponding to the specified Eclipse file,
- * or null if unable to associate the specified file with a JPA file.
- */
- public JpaFile getJpaFile(IFile file) throws CoreException {
- return this.jpaModel.getJpaFile(file);
- }
-
- /**
- * The JPA settings associated with the specified Eclipse project
- * have changed in such a way as to require the associated
- * JPA project to be completely rebuilt
- * (e.g. when the user changes a project's JPA platform).
- */
- public void rebuildJpaProject(IProject project) {
- this.jpaModel.rebuildJpaProject(project);
- }
-
- /**
- * Return whether the model manager's Java change listener is active.
- */
- public boolean javaElementChangeListenerIsActive() {
- return this.javaElementChangeListenerIsActive;
- }
-
- /**
- * Set whether the model manager's Java change listener is active.
- */
- public void setJavaElementChangeListenerIsActive(boolean javaElementChangeListenerIsActive) {
- this.javaElementChangeListenerIsActive = javaElementChangeListenerIsActive;
- }
-
- /**
- * Log the specified status.
- */
- public void log(IStatus status) {
- JptCorePlugin.log(status);
- }
-
- /**
- * Log the specified message.
- */
- public void log(String msg) {
- JptCorePlugin.log(msg);
- }
-
- /**
- * Log the specified exception or error.
- */
- public void log(Throwable throwable) {
- JptCorePlugin.log(throwable);
- }
-
-
- // ********** resource changed **********
-
- /**
- * Check for:
- * - project close/delete
- * - file add/remove
- * - project open/rename
- */
- /* private */ void resourceChanged(IResourceChangeEvent event) {
- // build events can have the workspace or project as source
- if (event.getType() == IResourceChangeEvent.POST_BUILD) {
- this.resourcePostBuild(event);
- return;
- }
-
- if (! (event.getSource() instanceof IWorkspace)) {
- return; // this probably shouldn't happen...
- }
-
- switch (event.getType()) {
- case IResourceChangeEvent.PRE_DELETE : // project-only event
- this.resourcePreDelete(event);
- break;
- case IResourceChangeEvent.POST_CHANGE :
- this.resourcePostChange(event);
- break;
- default :
- break;
- }
- }
-
- /**
- * A project is being deleted. Remove its corresponding
- * JPA project if appropriate.
- */
- private void resourcePreDelete(IResourceChangeEvent event) {
- IProject project = (IProject) event.getResource();
- debug("Resource (Project) PRE_DELETE: ", project); //$NON-NLS-1$
- this.jpaModel.projectPreDelete(project);
- }
-
- /**
- * A resource has changed somehow.
- * Check for files being added or removed.
- * (The JPA project only handles added and removed files here
- * Changed files are handlded via the Java Element Changed event.)
- * Also check for opened projects.
- */
- private void resourcePostChange(IResourceChangeEvent event) {
- debug("Resource POST_CHANGE"); //$NON-NLS-1$
- this.resourceChanged(event.getDelta());
- }
-
- private void resourceChanged(IResourceDelta delta) {
- IResource resource = delta.getResource();
- switch (resource.getType()) {
- case IResource.ROOT :
- this.resourceChangedChildren(delta);
- break;
- case IResource.PROJECT :
- this.projectChanged((IProject) resource, delta);
- break;
- case IResource.FILE :
- case IResource.FOLDER :
- default :
- break;
- }
- }
-
- private void resourceChangedChildren(IResourceDelta delta) {
- for (IResourceDelta child : delta.getAffectedChildren()) {
- this.resourceChanged(child); // recurse
- }
- }
-
- private void projectChanged(IProject project, IResourceDelta delta) {
- this.projectChanged_(delta);
- this.checkForOpenedProject(project, delta);
- }
-
-
- /**
- * Checked exceptions bite.
- */
- private void projectChanged_(IResourceDelta delta) {
- try {
- this.jpaModel.projectChanged(delta);
- } catch (CoreException ex) {
- this.log(ex); // problem traversing the project's resources - not much we can do
- }
- }
-
- /**
- * Crawl the specified delta, looking for projects being opened.
- * Projects being deleted are handled in IResourceChangeEvent.PRE_DELETE.
- * Projects being closed are handled in IFacetedProjectEvent.Type.PROJECT_MODIFIED.
- */
- private void checkForOpenedProject(IProject project, IResourceDelta delta) {
- switch (delta.getKind()) {
- case IResourceDelta.ADDED : // all but project import and rename handled with the facet POST_INSTALL event
- this.checkDeltaFlagsForOpenedProject(project, delta);
- this.checkDeltaFlagsForRenamedProject(project, delta);
- break;
- case IResourceDelta.REMOVED : // already handled with the PRE_DELETE event
- break;
- case IResourceDelta.CHANGED :
- this.checkDeltaFlagsForOpenedProject(project, delta);
- break;
- case IResourceDelta.ADDED_PHANTOM : // ignore
- break;
- case IResourceDelta.REMOVED_PHANTOM : // ignore
- break;
- default :
- break;
- }
- }
-
- /**
- * We don't get any events from the Facets Framework when a pre-existing
- * project is imported, so we need to check for the newly imported project here.
- *
- * This event also occurs when a project is simply opened. Project opening
- * also triggers a Facet PROJECT_MODIFIED event and that is where we add
- * the JPA project, not here
- */
- private void checkDeltaFlagsForOpenedProject(IProject project, IResourceDelta delta) {
- if (BitTools.flagIsSet(delta.getFlags(), IResourceDelta.OPEN) && project.isOpen()) {
- debug("\tProject CHANGED - OPEN: ", project.getName()); //$NON-NLS-1$
- this.jpaModel.checkForTransition(project);
- }
- }
-
- /**
- * We don't get any events from the Facets Framework when a project is renamed,
- * so we need to check for the renamed projects here.
- */
- private void checkDeltaFlagsForRenamedProject(IProject project, IResourceDelta delta) {
- if (BitTools.flagIsSet(delta.getFlags(), IResourceDelta.MOVED_FROM) && project.isOpen()) {
- debug("\tProject ADDED - MOVED_FROM: ", delta.getMovedFromPath()); //$NON-NLS-1$
- this.jpaModel.checkForTransition(project);
- }
- }
-
- /**
- * A post build event has occurred.
- * Check for whether the build was a "clean" build and trigger project update.
- */
- private void resourcePostBuild(IResourceChangeEvent event) {
- debug("Resource POST_BUILD"); //$NON-NLS-1$
- if (event.getBuildKind() == IncrementalProjectBuilder.CLEAN_BUILD) {
- this.resourcePostClean(event.getDelta());
- }
- }
-
- private void resourcePostClean(IResourceDelta delta) {
- IResource resource = delta.getResource();
- switch (resource.getType()) {
- case IResource.ROOT :
- this.resourcePostCleanChildren(delta);
- break;
- case IResource.PROJECT :
- this.projectPostClean((IProject) resource);
- break;
- case IResource.FILE :
- case IResource.FOLDER :
- default :
- break;
- }
- }
-
- private void resourcePostCleanChildren(IResourceDelta delta) {
- for (IResourceDelta child : delta.getAffectedChildren()) {
- this.resourcePostClean(child); // recurse
- }
- }
-
- private void projectPostClean(IProject project) {
- JpaProject jpaProject = null;
- try {
- jpaProject = getJpaProject(project);
- }
- catch (CoreException ce) {
- // nothing to do, we won't be able to update anyway
- }
- if (jpaProject != null) {
- rebuildJpaProject(project);
- }
- }
-
-
- // ********** faceted project changed **********
-
- /**
- * Check for:
- * - install of JPA facet
- * - un-install of JPA facet
- * - any other appearance or disappearance of the JPA facet
- */
- /* private */ void facetedProjectChanged(IFacetedProjectEvent event) {
- switch (event.getType()) {
- case POST_INSTALL :
- this.facetedProjectPostInstall((IProjectFacetActionEvent) event);
- break;
- case PRE_UNINSTALL :
- this.facetedProjectPreUninstall((IProjectFacetActionEvent) event);
- break;
- case PROJECT_MODIFIED :
- this.facetedProjectModified(event.getProject().getProject());
- break;
- default :
- break;
- }
- }
-
- private void facetedProjectPostInstall(IProjectFacetActionEvent event) {
- debug("Facet POST_INSTALL: ", event.getProjectFacet()); //$NON-NLS-1$
- if (event.getProjectFacet().getId().equals(JptCorePlugin.FACET_ID)) {
- this.jpaModel.jpaFacetedProjectPostInstall(event);
- }
- }
-
- private void facetedProjectPreUninstall(IProjectFacetActionEvent event) {
- debug("Facet PRE_UNINSTALL: ", event.getProjectFacet()); //$NON-NLS-1$
- if (event.getProjectFacet().getId().equals(JptCorePlugin.FACET_ID)) {
- this.jpaModel.jpaFacetedProjectPreUninstall(event);
- }
- }
-
- /**
- * This event is triggered for any change to a faceted project.
- * We use the event to watch for the following:
- * - an open project is closed
- * - a closed project is opened
- * - one of a project's (facet) metadata files is edited directly
- */
- private void facetedProjectModified(IProject project) {
- debug("Facet PROJECT_MODIFIED: ", project.getName()); //$NON-NLS-1$
- this.jpaModel.checkForTransition(project);
- }
-
-
- // ********** Java element changed **********
-
- /**
- * Forward the event to the JPA model.
- */
- /* private */ void javaElementChanged(ElementChangedEvent event) {
- if ( ! this.javaElementChangeListenerIsActive) {
- return; // ignore Java events
- }
- if (this.eventIndicatesProjectAddedButNotOpen(event)) {
- return;
- }
- this.jpaModel.javaElementChanged(event);
- }
-
- //209275 - This particular event only causes problems in a clean workspace the first time a JPA project
- //is created through the JPA wizard. The second time a JPA project is created, this event occurs, but
- //it occurs as the wizard is closing so it does not cause a deadlock.
- private boolean eventIndicatesProjectAddedButNotOpen(ElementChangedEvent event) {
- IJavaElementDelta delta = event.getDelta();
- if (delta.getKind() == IJavaElementDelta.CHANGED) {
- if (delta.getElement().getElementType() == IJavaElement.JAVA_MODEL) {
- IJavaElementDelta[] children = delta.getAffectedChildren();
- if (children.length == 1) {
- IJavaElementDelta childDelta = children[0];
- if (childDelta.getKind() == IJavaElementDelta.ADDED) {
- IJavaElement childElement = childDelta.getElement();
- if (childElement.getElementType() == IJavaElement.JAVA_PROJECT) {
- if (childDelta.getAffectedChildren().length == 0) {
- if (!((IOpenable) childElement).isOpen()) {
- return true;
- }
- }
- }
- }
- }
- }
- }
- return false;
- }
-
-
- // ********** resource change listener **********
-
- /**
- * Forward the Resource change event back to the JPA model manager.
- */
- private class ResourceChangeListener implements IResourceChangeListener {
- ResourceChangeListener() {
- super();
- }
- public void resourceChanged(IResourceChangeEvent event) {
- JpaModelManager.this.resourceChanged(event);
- }
- @Override
- public String toString() {
- return StringTools.buildToStringFor(this);
- }
- }
-
-
- // ********** faceted project listener **********
-
- /**
- * Forward the Faceted project change event back to the JPA model manager.
- */
- private class FacetedProjectListener implements IFacetedProjectListener {
- FacetedProjectListener() {
- super();
- }
- public void handleEvent(IFacetedProjectEvent event) {
- JpaModelManager.this.facetedProjectChanged(event);
- }
- @Override
- public String toString() {
- return StringTools.buildToStringFor(this);
- }
- }
-
-
- // ********** Java element change listener **********
-
- /**
- * Forward the Java element change event back to the JPA model manager.
- */
- private class JavaElementChangeListener implements IElementChangedListener {
- JavaElementChangeListener() {
- super();
- }
- public void elementChanged(ElementChangedEvent event) {
- JpaModelManager.this.javaElementChanged(event);
- }
- @Override
- public String toString() {
- return StringTools.buildToStringFor(this);
- }
- }
-
-
- // ********** debug **********
-
- // @see JpaModelTests#testDEBUG()
- private static final boolean DEBUG = false;
-
- /**
- * trigger #toString() call and string concatenation only if DEBUG is true
- */
- private static void debug(String message, Object object) {
- if (DEBUG) {
- debug_(message + object);
- }
- }
-
- private static void debug(String message) {
- if (DEBUG) {
- debug_(message);
- }
- }
-
- private static void debug_(String message) {
- System.out.println(Thread.currentThread().getName() + ": " + message); //$NON-NLS-1$
- }
-
-}
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 9e64af61ba..df58bc8729 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
@@ -53,6 +53,7 @@ public class JptCoreMessages {
public static String UPDATE_JOB_NAME;
public static String SYNCHRONIZE_METAMODEL_JOB_NAME;
public static String PLATFORM_ID_DOES_NOT_EXIST;
+ public static String DALI_EVENT_HANDLER_THREAD_NAME;
private static final String BUNDLE_NAME = "jpa_core"; //$NON-NLS-1$
private static final Class<?> BUNDLE_CLASS = JptCoreMessages.class;
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java
index afa4628b0b..5fdd73fc23 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jpa1/GenericJpaProject.java
@@ -9,7 +9,6 @@
******************************************************************************/
package org.eclipse.jpt.core.internal.jpa1;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.jpt.core.internal.AbstractJpaProject;
import org.eclipse.jpt.core.jpa2.JpaProject2_0;
@@ -22,7 +21,7 @@ public class GenericJpaProject
// ********** constructor/initialization **********
- public GenericJpaProject(JpaProject2_0.Config config) throws CoreException {
+ public GenericJpaProject(JpaProject2_0.Config config) {
super(config);
}
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 bfb0b96642..db52d48cf4 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
@@ -232,10 +232,7 @@ public abstract class AbstractJpaFileCreationDataModelProvider
protected JpaProject getJpaProject() {
IProject project = getProject();
- if (project == null) {
- return null;
- }
- return JptCorePlugin.getJpaProject(project);
+ return (project == null) ? null : JptCorePlugin.getJpaProject(project);
}
/**
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 1510d8ed9c..806bc48a52 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
@@ -1,12 +1,11 @@
/*******************************************************************************
- * Copyright (c) 2009 Oracle.
- * 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:
- * Oracle - initial API and implementation
+ * Copyright (c) 2009 Oracle. 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:
+ * Oracle - initial API and implementation
*******************************************************************************/
package org.eclipse.jpt.core.internal.operations;
@@ -19,6 +18,7 @@ import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.jem.util.emf.workbench.ProjectUtilities;
import org.eclipse.jpt.core.JpaProject;
import org.eclipse.jpt.core.JptCorePlugin;
@@ -111,5 +111,14 @@ public abstract class AbstractJpaFileCreationOperation
this.createdFile = newFile;
}
+ @Override
+ public ISchedulingRule getSchedulingRule() {
+ try {
+ return this.getProject();
+ } catch (ExecutionException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
protected abstract AbstractXmlResourceProvider getXmlResourceProvider(IFile file);
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/SimpleSchedulingRule.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/SimpleSchedulingRule.java
index a77b0c03aa..b51b33c87e 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/SimpleSchedulingRule.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/utility/SimpleSchedulingRule.java
@@ -10,6 +10,7 @@
package org.eclipse.jpt.core.internal.utility;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jpt.utility.internal.StringTools;
/**
* A job scheduling rule that conflicts only with itself.
@@ -17,21 +18,7 @@ import org.eclipse.core.runtime.jobs.ISchedulingRule;
public final class SimpleSchedulingRule
implements ISchedulingRule
{
-
- // singleton
- private static final SimpleSchedulingRule INSTANCE = new SimpleSchedulingRule();
-
- /**
- * Return the singleton.
- */
- public static ISchedulingRule instance() {
- return INSTANCE;
- }
-
- /**
- * Ensure single instance.
- */
- private SimpleSchedulingRule() {
+ public SimpleSchedulingRule() {
super();
}
@@ -43,4 +30,9 @@ public final class SimpleSchedulingRule
return rule == this;
}
+ @Override
+ public String toString() {
+ return StringTools.buildToStringFor(this);
+ }
+
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidator.java
index 68f3fac1c4..f5d7ac64e8 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/validation/JpaValidator.java
@@ -37,6 +37,10 @@ import org.eclipse.wst.validation.internal.provisional.core.IValidator;
*/
public class JpaValidator extends AbstractValidator implements IValidator {
+ public JpaValidator() {
+ super();
+ }
+
// ********** IValidator implementation **********
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/AbstractXmlResourceProvider.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/AbstractXmlResourceProvider.java
index 9b532bdc7c..48be5bd41c 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/AbstractXmlResourceProvider.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/AbstractXmlResourceProvider.java
@@ -173,7 +173,7 @@ public abstract class AbstractXmlResourceProvider
createResourceAndUnderlyingFile(config);
}
};
- workspace.run(runnable, workspace.getRoot(), IWorkspace.AVOID_UPDATE, new NullProgressMonitor());
+ workspace.run(runnable, this.project, IWorkspace.AVOID_UPDATE, null);
return this.resource;
}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/xml/JpaXmlResource.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/xml/JpaXmlResource.java
index 232f8f80ff..8f4a2c9a2f 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/xml/JpaXmlResource.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/resource/xml/JpaXmlResource.java
@@ -21,6 +21,7 @@ import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jem.util.emf.workbench.WorkbenchResourceHelperBase;
import org.eclipse.jem.util.plugin.JEMUtilPlugin;
import org.eclipse.jpt.core.JpaResourceModel;
@@ -75,16 +76,30 @@ public class JpaXmlResource
// ********** BasicNotifierImpl override **********
/**
- * override to prevent notification when the resource's state is unchanged
- * or the resource is not loaded
+ * override to fire notification only when
+ * - the resource's state has actually changed; and
+ * - the resource is loaded; and
+ * - the resource's resource set is still present (EMF will fire an
+ * notification when the resource set is set to 'null', just before
+ * the resource is "unloaded" - we want to swallow this notification)
*/
@Override
public void eNotify(Notification notification) {
- if ( ! notification.isTouch() && this.isLoaded()) {
+ if ( ! notification.isTouch() && this.isLoaded() && (this.resourceSet != null)) {
super.eNotify(notification);
this.resourceModelChanged();
}
}
+
+ /**
+ * we could use this method to suppress some notifications; or we could just
+ * check whether 'resourceSet' is 'null' (which is what we do)
+ */
+ protected boolean resultSetCleared(Notification notification) {
+ return (notification.getNotifier() == this) &&
+ (notification.getFeatureID(Resource.class) == RESOURCE__RESOURCE_SET) &&
+ (notification.getNewValue() == null);
+ }
// ********** TranslatorResource implementation **********

Back to the top