[58349] Handle class shape changes, pass #1
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoAdapterFactory.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoAdapterFactory.java index f750a45..bf8d231 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoAdapterFactory.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoAdapterFactory.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: BeaninfoAdapterFactory.java,v $ - * $Revision: 1.3 $ $Date: 2004/05/05 21:03:09 $ + * $Revision: 1.4 $ $Date: 2004/06/09 22:46:55 $ */ import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; @@ -152,6 +152,28 @@ } } } + + public void markStaleIntrospectionPlusInner(String sourceName, boolean clearResults) { + processQueue(); + String sourceNameForInner = sourceName + '$'; + synchronized (this) { + Iterator itr = fIntrospected.entrySet().iterator(); + while (itr.hasNext()) { + Map.Entry entry = (Map.Entry) itr.next(); + String entryName = (String) entry.getKey(); + if (entryName.equals(sourceName) || entryName.startsWith(sourceNameForInner)) { + // It is the item or one of its inner classes. + WeakValue ref = (WeakValue) entry.getValue(); + BeaninfoClassAdapter a = (BeaninfoClassAdapter) ref.get(); + if (a != null) { + if (clearResults) + a.clearIntrospection(); + a.markStaleFactory(isRegistryCreated() ? getRegistry() : null); // Mark it stale with the current registry. + } + } + } + } + } /** * Register an adapter for introspection. @@ -166,46 +188,6 @@ fIntrospected.put(sourceName, new WeakValue(sourceName, adapter, fRefQ)); } } - - /** - * Unregister the introspection and remove the adapter and clear out any introspection it may of done. - * @param sourceName Fully qualified source name, use type for reflection, i.e. "a.b.c.Class1$InnerClass" - */ - public void unregisterIntrospection(String sourceName) { - processQueue(); - synchronized (this) { - WeakValue ref = (WeakValue) fIntrospected.remove(sourceName); - if (ref != null) { - BeaninfoClassAdapter a = (BeaninfoClassAdapter) ref.get(); - a.clearIntrospection(); - a.getTarget().eAdapters().remove(a); - } - } - } - - /** - * Unregister this class and all inner classes (denoted by having same name plus '$' plus stuff) - * @param sourceName Fully qualified source name, use type for reflection, i.e. "a.b.c.Class1$InnerClass" - */ - public void unregisterIntrospectionPlusInner(String sourceName) { - processQueue(); - String sourceNameForInner = sourceName + '$'; - synchronized (this) { - Iterator itr = fIntrospected.entrySet().iterator(); - while (itr.hasNext()) { - Map.Entry entry = (Map.Entry) itr.next(); - String entryName = (String) entry.getKey(); - if (entryName.equals(sourceName) || entryName.startsWith(sourceNameForInner)) { - // It is the item or one of its inner classes. - WeakValue ref = (WeakValue) entry.getValue(); - itr.remove(); // Since I removed it BEFORE sending removeAdapter, I won't get a concurrentmodification exception from removeAdapter also removing it, since it won't be there then. - BeaninfoClassAdapter a = (BeaninfoClassAdapter) ref.get(); - a.clearIntrospection(); - a.getTarget().eAdapters().remove(a); - } - } - } - } /** * Remove adapter. This happens in the case that adapter is being removed and
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoClassAdapter.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoClassAdapter.java index d72bace..c7c4300 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoClassAdapter.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoClassAdapter.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: BeaninfoClassAdapter.java,v $ - * $Revision: 1.13 $ $Date: 2004/06/02 19:42:39 $ + * $Revision: 1.14 $ $Date: 2004/06/09 22:46:55 $ */ import java.io.FileNotFoundException; @@ -423,7 +423,9 @@ retrievedExtensionDocument = NEVER_RETRIEVED_EXTENSION_DOCUMENT; } if (retrievedExtensionDocument == NEVER_RETRIEVED_EXTENSION_DOCUMENT) - applyExtensionDocument(true); // Add in Root stuff so that it will work correctly even though undefined. + applyExtensionDocument(true); // Add in Root stuff so that it will work correctly even though undefined. + // Mark that we've done all introspections so as not to waste time until we get notified that it has been added + // back in. hasIntrospected = hasIntrospectedOperations = hasIntrospectedProperties = hasIntrospectedEvents = true; } else { if (retrievedExtensionDocument == RETRIEVED_ROOT_ONLY) { @@ -952,7 +954,7 @@ // allow discovered duplicates unless they are different types. HashMap supers = new HashMap(50); BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass()); - if (bd.isMergeSuperProperties()) { + if (bd == null || bd.isMergeSuperProperties()) { JavaClass superType = getJavaClass().getSupertype(); if (superType != null) { Iterator superAllItr = superType.getAllProperties().iterator(); @@ -1343,7 +1345,7 @@ // will be allowed and we will not override them. HashMap supers = new HashMap(50); BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass()); - if (bd.isMergeSuperBehaviors()) { + if (bd == null || bd.isMergeSuperBehaviors()) { EClass superType = getJavaClass().getSupertype(); if (superType != null) { Iterator superAllItr = superType.getEAllOperations().iterator(); @@ -1590,7 +1592,7 @@ // allow discovered duplicates. HashMap supers = new HashMap(50); BeanDecorator bd = Utilities.getBeanDecorator(getJavaClass()); - if (bd.isMergeSuperEvents()) { + if (bd == null || bd.isMergeSuperEvents()) { JavaClass superType = (JavaClass) getJavaClass().getSupertype(); if (superType != null) { Iterator superAllItr = superType.getAllEvents().iterator();
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoModelSynchronizer.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoModelSynchronizer.java index 5b12900..96a82e1 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoModelSynchronizer.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoModelSynchronizer.java
@@ -11,14 +11,9 @@ *******************************************************************************/ /* * $RCSfile: BeaninfoModelSynchronizer.java,v $ - * $Revision: 1.4 $ $Date: 2004/03/24 15:07:44 $ + * $Revision: 1.5 $ $Date: 2004/06/09 22:46:55 $ */ -import java.util.*; - -import org.eclipse.core.resources.*; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.*; @@ -32,22 +27,27 @@ public class BeaninfoModelSynchronizer extends JavaModelListener { protected BeaninfoAdapterFactory fAdapterFactory; protected IJavaProject fProject; // The project this listener is opened on. - protected IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); - private static final IPath CLASSPATH_PATH = new Path(".classpath"); //$NON-NLS-1$ private static final IPath BEANINFOCONFIG_PATH = new Path(BeaninfoNature.P_BEANINFO_SEARCH_PATH); //$NON-NLS-1$ public BeaninfoModelSynchronizer(BeaninfoAdapterFactory aFactory, IJavaProject aProject) { - super(); + super(ElementChangedEvent.POST_CHANGE); fAdapterFactory = aFactory; fProject = aProject; - // We're really only interested in Post_Change, not the others, so we will - // remove ourself (since super ctor added ourself) and then add ourself - // back with only post change. (Post change is after everything has been - // reconciled and build). - JavaCore.removeElementChangedListener(this); - JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE); } + /* (non-Javadoc) + * @see org.eclipse.jem.internal.adapters.jdom.JavaModelListener#getJavaProject() + */ + protected IJavaProject getJavaProject() { + return fProject; + } + /* (non-Javadoc) + * @see org.eclipse.jem.internal.adapters.jdom.JavaModelListener#isAlsoClasspathChange(org.eclipse.core.runtime.IPath) + */ + protected boolean isAlsoClasspathChange(IPath path) { + return path.equals(BEANINFOCONFIG_PATH); + } + /** * Stop the synchronizer from listening to any more changes. */ @@ -60,97 +60,6 @@ return fAdapterFactory; } - protected IJavaProject getJavaProject(IClasspathEntry entry) { - IProject proj = workspaceRoot.getProject(entry.getPath().segment(0)); - if (proj != null) - return (IJavaProject) JavaCore.create(proj); - return null; - } - - private boolean isClassPathChange(IJavaElementDelta delta) { - int flags = delta.getFlags(); - return ( - delta.getKind() == IJavaElementDelta.CHANGED - && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) - || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) - || ((flags & IJavaElementDelta.F_REORDER) != 0)); - } - - /** - * This method will check to see if a <code>javaProject</code> is a project in the - * classpath of the adapterFactory java project. - */ - protected boolean isInClasspath(IJavaProject javaProject) { - IJavaProject adapterJavaProject = fProject; - if (javaProject.equals(adapterJavaProject)) - return true; - return isInClasspath(javaProject, adapterJavaProject, true, new HashSet()); - } - - protected boolean isInClasspath(IJavaProject testProject, IJavaProject targetProject, boolean isFirstLevel, Set visited) { - if (visited.contains(targetProject)) - return false; - visited.add(targetProject); - IClasspathEntry[] entries = null; - try { - entries = targetProject.getRawClasspath(); - } catch (JavaModelException e) { - return false; - } - IClasspathEntry entry, resEntry; - IJavaProject proj = null; - List projects = null; - for (int i = 0; i < entries.length; i++) { - entry = entries[i]; - if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { - resEntry = JavaCore.getResolvedClasspathEntry(entry); - proj = getJavaProject(resEntry); - if (isFirstLevel || resEntry.isExported()) { - if (proj.equals(testProject)) - return true; - else { - if (projects == null) - projects = new ArrayList(); - projects.add(proj); - } - } - } - } - return isInClasspath(testProject, projects, false, visited); - } - - protected boolean isInClasspath(IJavaProject testProject, List someJavaProjects, boolean isFirstLevel, Set visited) { - if (someJavaProjects == null) - return false; - int size = someJavaProjects.size(); - IJavaProject javaProj = null; - for (int i = 0; i < size; i++) { - javaProj = (IJavaProject) someJavaProjects.get(i); - return isInClasspath(testProject, javaProj, isFirstLevel, visited); - } - return false; - } - - /* - * Test if .classpath/.beaninfoconfig is part of the change. This is necessary - * because .classpath/.beaninfoconfig changes of DEPENDENT PROJECTS are not signaled - * through classpath change mechanisms of the top project. - */ - private boolean isClasspathResourceChange(IJavaElementDelta delta) { - IResourceDelta[] resources = delta.getResourceDeltas(); - if (resources == null) - return false; - IPath path = null; - for (int i = 0; i < resources.length; i++) { - if (resources[i].getKind() != IResourceDelta.NO_CHANGE) { - path = resources[i].getProjectRelativePath(); - if (path.equals(CLASSPATH_PATH) || path.equals(BEANINFOCONFIG_PATH)) - return true; - } - } - return false; - } - protected void processJavaElementChanged(IJavaProject element, IJavaElementDelta delta) { if (isInClasspath(element)) { if (delta.getKind() == IJavaElementDelta.REMOVED || delta.getKind() == IJavaElementDelta.ADDED) { @@ -163,7 +72,7 @@ } return; } else if (isClasspathResourceChange(delta)) { - getAdapterFactory().markAllStale(); // The .classpath file itself in SOME DEPENDENT PROJECT has changed. + getAdapterFactory().markAllStale(); // The .classpath file (or .beaninfoconfig) itself in SOME DEPENDENT PROJECT has changed. return; } processChildren(element, delta); @@ -178,26 +87,26 @@ * If it is not a content change then process the children. */ protected void processJavaElementChanged(ICompilationUnit element, IJavaElementDelta delta) { - if (!element.isWorkingCopy()) { - if (((delta.getKind() == IJavaElementDelta.CHANGED && (delta.getFlags() & IJavaElementDelta.F_PRIMARY_WORKING_COPY) == 0) || delta.getKind() == IJavaElementDelta.ADDED)) { - try { - IType[] flushTypes = element.getAllTypes(); - for (int i = 0; i < flushTypes.length; i++) { - getAdapterFactory().markStaleIntrospection(flushTypes[i].getFullyQualifiedName(), false); - } - } catch (JavaModelException e) { - } - } - if (delta.getKind() == IJavaElementDelta.REMOVED) { - // It doesn't matter if totally removed or just moved somewhere else, we will clear out and remove the + switch (delta.getKind()) { + case IJavaElementDelta.CHANGED : + // A file save had occurred. It doesn't matter if currently working copy or not. + // It means something has changed to the file on disk, but don't know what. + if ((delta.getFlags() & IJavaElementDelta.F_PRIMARY_RESOURCE) != 0) { + getAdapterFactory().markStaleIntrospectionPlusInner(getFullNameFromElement(element), false); // Flush everything, including inner classes. + } + + break; + case IJavaElementDelta.ADDED: + case IJavaElementDelta.REMOVED: + // Need to know for add because we optimize the beaninfo such that once found as undefined, it won't + // introspect again until we mark it stale. So we need to mark it stale to refresh it. + + // It doesn't matter if totally removed or just moved somewhere else, we will clear out // adapter because there could be a rename which would be a different class. - // Currently the element is already deleted and there is no way to find the types in the unit to remove. - // So instead we ask factory to remove all it any that start with it plus for inner classes. - getAdapterFactory().unregisterIntrospectionPlusInner(getFullNameFromElement(element)); - return; - // Since the compilation unit was removed we don't need to process the children (actually the children list will be empty - } - processChildren(element, delta); + // Currently the element is already deleted or added and there is no way to find the types in the unit to flush. + // So instead we ask factory to flush all it any that start with it plus for inner classes. + getAdapterFactory().markStaleIntrospectionPlusInner(getFullNameFromElement(element), true); // Flush everything, including inner classes. + break; } } @@ -210,7 +119,7 @@ // adapter because there could be a rename which would be a different class. // Currently the element is already deleted and there is no way to find the types in the unit to remove. // So instead we ask factory to remove all it any that start with it plus for inner classes. - getAdapterFactory().unregisterIntrospectionPlusInner(getFullNameFromElement(element)); + getAdapterFactory().markStaleIntrospectionPlusInner(getFullNameFromElement(element), true); return; // Since the classfile was removed we don't need to process the children (actually the children list will be empty } IJavaElementDelta[] children = delta.getAffectedChildren(); @@ -251,6 +160,20 @@ else super.processJavaElementChanged(element, delta); } + + protected void processJavaElementChanged(IPackageFragment element, IJavaElementDelta delta) { + switch (delta.getKind()) { + case IJavaElementDelta.ADDED: + break; // Don't need to do anything on a new package. If this was from a new fragroot, we would recycle already. Otherwise, it will find this package on the first use. + case IJavaElementDelta.REMOVED: + if (delta.getAffectedChildren().length == 0) + fAdapterFactory.markAllStale(); + break; + default : + super.processJavaElementChanged(element, delta); + } + } + /** * Handle the change for a single element, children will be handled separately. @@ -259,7 +182,11 @@ */ protected void processJavaElementChanged(IType element, IJavaElementDelta delta) { if (delta.getKind() == IJavaElementDelta.REMOVED) { - getAdapterFactory().unregisterIntrospectionPlusInner(element.getFullyQualifiedName()); // Close it out. Doesn't matter if moved_to, that would be a rename which requires brand new class. + // Close it out. Doesn't matter if moved_to, that would be a rename which requires brand new class. + // We can't actually get rid of the beaninfo adapter because it may be asked for again + // just to see if not defined. It may also come back later and we want to know about + // it to recycle the vm. + getAdapterFactory().markStaleIntrospection(element.getFullyQualifiedName(), true); } else getAdapterFactory().markStaleIntrospection(element.getFullyQualifiedName(), false); // Just mark it stale processChildren(element, delta);
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java index 30befeb..c2f7848 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/BeaninfoNature.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: BeaninfoNature.java,v $ - * $Revision: 1.18 $ $Date: 2004/06/04 15:29:34 $ + * $Revision: 1.19 $ $Date: 2004/06/09 22:46:55 $ */ import java.io.*; @@ -352,6 +352,7 @@ return fRegistry; } + private Object createSemaphore = new Object(); // Semaphore so that only one create can happen at a time. /* * This is <package-protected> so that only the appropriate create job in this * package can call it. This is because this must be controlled to only be @@ -359,24 +360,29 @@ * If waitForBuild is passed onto launching the registry. If we suspended the builds, then we must not * wait, or a deadlock will occur. */ - synchronized void createRegistry(IProgressMonitor pm, boolean waitForBuild) { - pm.beginTask(BeanInfoAdapterMessages.getString("UICreateRegistryJobHandler.StartBeaninfoRegistry"), 100); //$NON-NLS-1$ - // synchronized on this nature so that only one can create on this particular project at a time. - if (fRegistry != null) { - pm.done(); - return; // It had already been created. Could of been because threads were racing to do the creation, and one got there first. - } + void createRegistry(IProgressMonitor pm, boolean waitForBuild) { + // synchronized on createsemaphore so that only one can create on this particular project at a time. + synchronized (createSemaphore) { + pm.beginTask(BeanInfoAdapterMessages.getString("UICreateRegistryJobHandler.StartBeaninfoRegistry"), 100); //$NON-NLS-1$ + if (isRegistryCreated()) { + pm.done(); + return; // It had already been created. Could of been because threads were racing to do the creation, and one got there first. + } - try { - ConfigurationContributor configurationContributor = (ConfigurationContributor) getConfigurationContributor(); - configurationContributor.setNature(this); - fRegistry = ProxyLaunchSupport.startImplementation(fProject, "Beaninfo", //$NON-NLS-1$ - new IConfigurationContributor[] { configurationContributor}, waitForBuild, new SubProgressMonitor(pm, 100)); - fRegistry.addRegistryListener(registryListener); - } catch (CoreException e) { - BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus()); - } finally { - pm.done(); + try { + ConfigurationContributor configurationContributor = (ConfigurationContributor) getConfigurationContributor(); + configurationContributor.setNature(this); + ProxyFactoryRegistry registry = ProxyLaunchSupport.startImplementation(fProject, "Beaninfo", //$NON-NLS-1$ + new IConfigurationContributor[] { configurationContributor}, waitForBuild, new SubProgressMonitor(pm, 100)); + registry.addRegistryListener(registryListener); + synchronized(this) { + fRegistry = registry; + } + } catch (CoreException e) { + BeaninfoPlugin.getPlugin().getLogger().log(e.getStatus()); + } finally { + pm.done(); + } } } @@ -645,10 +651,6 @@ // First time for this nature, or first time after registry reset. Need to compute the info. // It is possible for this to be called BEFORE the first usage of BeanInfo. The editor usually // brings up the editor's registry before it gets anything from BeanInfo. - - // Save it for override processing. That happens over and over later after all config processing is done. - info.getJavaProject().getProject().setSessionProperty(CONFIG_INFO_SESSION_KEY, info); - List contributorsList = new ArrayList(10); if (!info.getContainerIds().isEmpty()) { // Run through all of the visible container ids that are applicable and get BeanInfo contributors. @@ -699,6 +701,11 @@ // Save it for all beaninfo processing (and configuration processing if they implement proxy configuration contributor). explicitContributors = (IBeanInfoContributor[]) contributorsList.toArray(new IBeanInfoContributor[contributorsList.size()]); info.getJavaProject().getProject().setSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY, explicitContributors); + // Save it for override processing. That happens over and over later after all config processing is done. + // Do it last so that if there is a race condition, since this property is a flag to indicate we have data, + // we need to make sure the Beaninfo data is already set at the point we set this. + // We could actually set it twice because of this, but it is the same data, so, so what. + info.getJavaProject().getProject().setSessionProperty(CONFIG_INFO_SESSION_KEY, info); } else { explicitContributors = (IBeanInfoContributor[]) info.getJavaProject().getProject().getSessionProperty(BEANINFO_CONTRIBUTORS_SESSION_KEY); }
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java index 196deee..38fb4d0 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/adapters/CreateRegistryJobHandler.java
@@ -10,7 +10,7 @@ *******************************************************************************/ /* * $RCSfile: CreateRegistryJobHandler.java,v $ - * $Revision: 1.4 $ $Date: 2004/06/04 15:29:34 $ + * $Revision: 1.5 $ $Date: 2004/06/09 22:46:55 $ */ package org.eclipse.jem.internal.beaninfo.adapters; @@ -64,6 +64,41 @@ } private int suspendedCount = 0; // Number of nested suspends. Resume will occur only when it goes back to zero. + + private boolean[] startSemaphore = new boolean[1]; // Used to tell caller when suspend job has suspended the build ruile. + private boolean[] stopSemaphore = new boolean[1]; // Used to tell when to stop. The [0] value is whether stop requested or not. + // The purpose of this job is to suspend the builds while beaninfo is creating its registries. This is to + // prevent deadlocks between a beaninfo start reqistry request and a start request for beaninfo coming from + // a builder. It is a separate job so that if several overlapping beaninfo registry requests come in, then + // the first one in will suspend the build, and the build will not resume until the last one out. The first + // one in my finish before the next one, so we don't want builds to resume until all have completed. + private Job suspendJob = new Job("Suspend builds for BeanInfo") { //$NON-NLS-1$ + + { + this.setSystem(true); // Don't show these to users. + // The rule for running this is build rule. This is how it stops the builders + this.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().buildRule()); + } + + protected IStatus run(IProgressMonitor monitor) { + synchronized (startSemaphore) { + startSemaphore[0] = true; + startSemaphore.notifyAll(); + } + + // Now we just wait until suspend count goes to 0. We will be told when this happens. + synchronized (stopSemaphore) { + while (!stopSemaphore[0]) { + try { + stopSemaphore.wait(); + } catch (InterruptedException e) { + } + } + } + return Status.OK_STATUS; + } + }; + /* * Do the creation. * @@ -76,7 +111,6 @@ pm.beginTask("", 400); //$NON-NLS-1$ IJobManager jobManager = Platform.getJobManager(); Job currentJob = jobManager.currentJob(); - ISchedulingRule suspendedBuildRule = null; // The build rule. This will be null if I don't suspend. try { if (currentJob == null || (!currentJob.belongsTo(ResourcesPlugin.FAMILY_AUTO_BUILD) && !currentJob.belongsTo(ResourcesPlugin.FAMILY_MANUAL_BUILD))) { // We are not in the build, so suspend the rule. But first, wait for the builds to complete. This @@ -96,9 +130,25 @@ pm.worked(200); synchronized(this) { - ++suspendedCount; // We need to keep track of nesting of suspends because Eclipse doesn't. The first resume will cause it to resume. - suspendedBuildRule = ResourcesPlugin.getWorkspace().getRuleFactory().buildRule(); - jobManager.suspend(suspendedBuildRule, new SubProgressMonitor(pm, 100)); + if (suspendedCount++ == 0) { + // Only start the suspend job on the first suspend request. + // We can not let anyone else get past here until we know the + // build has been halted. + synchronized (stopSemaphore) { + stopSemaphore[0] = false; // Reset it for next start + stopSemaphore.notifyAll(); // Just in case job is still waiting. + } + synchronized (startSemaphore) { + startSemaphore[0] = false; + suspendJob.schedule(); + while (!startSemaphore[0]) { + try { + startSemaphore.wait(); // Wait for suspend job to say it has the build rule suspended. + } catch (InterruptedException e) { + } + } + } + } } } else pm.worked(300); @@ -107,12 +157,16 @@ nature.createRegistry(new SubProgressMonitor(pm, 100), false); } finally { synchronized (this) { - if (suspendedBuildRule != null) { - if (--suspendedCount<= 0) { - suspendedCount = 0; // Just to be safe. - jobManager.resume(suspendedBuildRule); + // No matter what happens we need to stop the suspend job if we are the last. + if (--suspendedCount <= 0) + suspendedCount = 0; + if (suspendJob.getState() != Job.NONE) { + // The job is running. + synchronized (stopSemaphore) { + stopSemaphore[0] = true; + stopSemaphore.notifyAll(); // Tell suspend job to stop. + } } - } } pm.done(); }
diff --git a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeaninfoPlugin.java b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeaninfoPlugin.java index 2b2f1fc..8f9bd53 100644 --- a/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeaninfoPlugin.java +++ b/plugins/org.eclipse.jem.beaninfo/beaninfo/org/eclipse/jem/internal/beaninfo/core/BeaninfoPlugin.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: BeaninfoPlugin.java,v $ - * $Revision: 1.4 $ $Date: 2004/05/24 23:23:31 $ + * $Revision: 1.5 $ $Date: 2004/06/09 22:46:55 $ */ @@ -84,25 +84,25 @@ private static final OverrideContribution[] EMPTY_OC = new OverrideContribution[0]; // Used for an empty contribution list for a fragment. - public BeaninfoEntry[] getContainerIdBeanInfos(String containerID) { + public synchronized BeaninfoEntry[] getContainerIdBeanInfos(String containerID) { if (containerIdsToBeaninfoEntryContributions == null) processBeanInfoContributionExtensionPoint(); return (BeaninfoEntry[]) containerIdsToBeaninfoEntryContributions.get(containerID); } - public BeaninfoEntry[] getPluginBeanInfos(String pluginid) { + public synchronized BeaninfoEntry[] getPluginBeanInfos(String pluginid) { if (pluginToBeaninfoEntryContributions == null) processBeanInfoContributionExtensionPoint(); return (BeaninfoEntry[]) pluginToBeaninfoEntryContributions.get(pluginid); } - public IConfigurationElement[] getPluginContributors(String pluginid) { + public synchronized IConfigurationElement[] getPluginContributors(String pluginid) { if (pluginToContributors == null) processBeanInfoContributionExtensionPoint(); return (IConfigurationElement[]) pluginToContributors.get(pluginid); } - public IConfigurationElement[] getContainerIdContributors(String containerID) { + public synchronized IConfigurationElement[] getContainerIdContributors(String containerID) { if (containerIdsToContributors == null) processBeanInfoContributionExtensionPoint(); return (IConfigurationElement[]) containerIdsToContributors.get(containerID); @@ -116,7 +116,7 @@ public static final String PI_PACKAGE = "package"; public static final String PI_PATH = "path"; - protected void processBeanInfoContributionExtensionPoint() { + protected synchronized void processBeanInfoContributionExtensionPoint() { ContributorExtensionPointInfo info = ProxyPlugin.processContributionExtensionPoint(PI_BEANINFO_CONTRIBUTION_EXTENSION_POINT); ConfigurationElementReader reader = new ConfigurationElementReader(); // Process the container IDs first. @@ -431,8 +431,10 @@ try { IConfigurationContributionInfo info = (IConfigurationContributionInfo) project.getSessionProperty(BeaninfoNature.CONFIG_INFO_SESSION_KEY); final IBeanInfoContributor[] explicitContributors = (IBeanInfoContributor[]) project.getSessionProperty(BeaninfoNature.BEANINFO_CONTRIBUTORS_SESSION_KEY); - if (ocFragments == null) - processBeanInfoContributionExtensionPoint(); // We haven't processed them yet. + synchronized (this) { + if (ocFragments == null) + processBeanInfoContributionExtensionPoint(); // We haven't processed them yet. + } for (int fragmentIndex = 0; fragmentIndex < ocFragments.length; fragmentIndex++) { if (ocFragments[fragmentIndex].isPrefixOf(packagePath)) { String leftOver = null; // The left over portion of the package. This will be set first time needed.
diff --git a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyPlugin.java b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyPlugin.java index 9e29f35..02e33ed 100644 --- a/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyPlugin.java +++ b/plugins/org.eclipse.jem.proxy/proxy/org/eclipse/jem/internal/proxy/core/ProxyPlugin.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: ProxyPlugin.java,v $ - * $Revision: 1.24 $ $Date: 2004/06/02 19:58:49 $ + * $Revision: 1.25 $ $Date: 2004/06/09 22:46:57 $ */ @@ -674,7 +674,7 @@ * * @since 1.0.0 */ - public IConfigurationElement[] getContainerConfigurations(String containerid) { + public synchronized IConfigurationElement[] getContainerConfigurations(String containerid) { if (containerToContributions == null) processProxyContributionExtensionPoint(); return (IConfigurationElement[]) containerToContributions.get(containerid); @@ -688,13 +688,13 @@ * * @since 1.0.0 */ - public IConfigurationElement[] getPluginConfigurations(String pluginid) { + public synchronized IConfigurationElement[] getPluginConfigurations(String pluginid) { if (pluginToContributions == null) processProxyContributionExtensionPoint(); return (IConfigurationElement[]) pluginToContributions.get(pluginid); } - protected void processProxyContributionExtensionPoint() { + protected synchronized void processProxyContributionExtensionPoint() { ContributorExtensionPointInfo info = processContributionExtensionPoint(PI_CONFIGURATION_CONTRIBUTION_EXTENSION_POINT); containerToContributions = info.containerToContributions; pluginToContributions = info.pluginToContributions;
diff --git a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java index 31a7046..9a3cd9b 100644 --- a/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java +++ b/plugins/org.eclipse.jem.proxy/proxyRemote/org/eclipse/jem/internal/proxy/remote/REMMethodProxy.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: REMMethodProxy.java,v $ - * $Revision: 1.5 $ $Date: 2004/05/24 23:23:36 $ + * $Revision: 1.6 $ $Date: 2004/06/09 22:46:57 $ */ import org.eclipse.core.runtime.IStatus; @@ -61,14 +61,10 @@ return fMethodName; } - public IBeanTypeProxy[] getParameterTypes() { + public synchronized IBeanTypeProxy[] getParameterTypes() { if (fParameterTypes == null) { - IArrayBeanProxy parmTypes = - (IArrayBeanProxy) REMStandardBeanProxyConstants - .getConstants(fFactory) - .getMethodParameterTypesMessage() - .invokeCatchThrowableExceptions( - this); + IArrayBeanProxy parmTypes = (IArrayBeanProxy) REMStandardBeanProxyConstants.getConstants(fFactory) + .getMethodParameterTypesMessage().invokeCatchThrowableExceptions(this); if (parmTypes == null) fParameterTypes = new IBeanTypeProxy[0]; // There was some error, only way null is returned else {
diff --git a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaClassJDOMAdaptor.java b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaClassJDOMAdaptor.java index 7109c34..fc960c8 100644 --- a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaClassJDOMAdaptor.java +++ b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaClassJDOMAdaptor.java
@@ -11,12 +11,13 @@ *******************************************************************************/ /* * $RCSfile: JavaClassJDOMAdaptor.java,v $ - * $Revision: 1.5 $ $Date: 2004/02/24 19:33:35 $ + * $Revision: 1.6 $ $Date: 2004/06/09 22:47:06 $ */ import java.util.*; import java.util.logging.Level; +import org.eclipse.core.resources.IResource; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.ecore.EObject; @@ -253,21 +254,32 @@ primFlushReflectedValues(); boolean isHeadless = UIContextDetermination.getCurrentContext() == UIContextDetermination.HEADLESS_CONTEXT; if (getSourceProject() != null && getSourceType() != null && getSourceType().exists()) { - setModifiers(); - setNaming(); - try { - setSuper(); - } catch (InheritanceCycleException e) { - JavaPlugin.getDefault().getLogger().log(e); - } - setImplements(); - addMethods(); - addFields(); - reflectInnerClasses(); - //addImports(); - if (isHeadless) { - registerWithFactory(); - return true; + ICompilationUnit cu = getSourceType().getCompilationUnit(); + boolean isWC = cu != null ? cu.isWorkingCopy() : false; + IResource res = isWC ? getSourceType().getResource() : null; + // We are only interested in physical classes. If still just in working copy and not yet put out to + // disk, we don't should treat as not exist. Anything else is considered existing because we got past + // getSourceType.exists. This will return the truth for non-wc. But for wc types it will return true, + // even though not physically on disk (such as just creating it and hadn't saved it yet). So for wc types + // we need to test the actual resource. + // Test is OK if not wc, or if wc, then there is a res. and it is accessible. + if (!isWC || (res != null && res.isAccessible())) { + setModifiers(); + setNaming(); + try { + setSuper(); + } catch (InheritanceCycleException e) { + JavaPlugin.getDefault().getLogger().log(e); + } + setImplements(); + addMethods(); + addFields(); + reflectInnerClasses(); + //addImports(); + if (isHeadless) { + registerWithFactory(); + return true; + } } } if (isHeadless)
diff --git a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaJDOMAdapterFactory.java b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaJDOMAdapterFactory.java index 628a388..da4f411 100644 --- a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaJDOMAdapterFactory.java +++ b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaJDOMAdapterFactory.java
@@ -11,13 +11,15 @@ *******************************************************************************/ /* * $RCSfile: JavaJDOMAdapterFactory.java,v $ - * $Revision: 1.1 $ $Date: 2003/10/27 17:33:53 $ + * $Revision: 1.2 $ $Date: 2004/06/09 22:47:06 $ */ import java.util.*; +import org.eclipse.emf.common.notify.*; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.jdt.core.*; +import org.eclipse.jem.internal.java.adapters.*; import org.eclipse.jem.internal.java.adapters.JavaReflectionAdapterFactory; import org.eclipse.jem.internal.java.adapters.ReflectionAdaptor; /** @@ -144,6 +146,35 @@ return a.flushReflectedValuesIfNecessaryNoNotification(false); return null; } + +public Notification flushReflectionPlusInnerNoNotification(String source) { + isBusyIteratingReflected = true; + Notification notification = null; + try { + String innerName = source + '$'; + Iterator it = reflected.entrySet().iterator(); + Map.Entry entry; + String key; + JavaReflectionAdaptor adaptor; + while (it.hasNext()) { + entry = (Map.Entry) it.next(); + key = (String) entry.getKey(); + if (key.equals(source) || key.startsWith(innerName)) { + adaptor = (JavaReflectionAdaptor) reflected.get(key); + if (adaptor != null) { + if (notification == null) + notification = adaptor.flushReflectedValuesIfNecessaryNoNotification(false); + else + ((NotificationChain) notification).add(adaptor.flushReflectedValuesIfNecessaryNoNotification(false)); + } + } + } + } finally { + finishedIteratingReflected(); + } + return notification; + +} /** * Insert the method's description here. * Creation date: (11/2/2000 3:02:31 PM)
diff --git a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaModelListener.java b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaModelListener.java index e9a9256..54e46a1 100644 --- a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaModelListener.java +++ b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaModelListener.java
@@ -11,9 +11,16 @@ *******************************************************************************/ /* * $RCSfile: JavaModelListener.java,v $ - * $Revision: 1.2 $ $Date: 2004/01/13 16:17:42 $ + * $Revision: 1.3 $ $Date: 2004/06/09 22:47:06 $ */ +import java.util.*; + +import org.eclipse.core.resources.*; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.*; /** @@ -21,14 +28,17 @@ * Creation date: (10/31/2000 1:13:12 PM) * @author: Administrator */ -public class JavaModelListener implements IElementChangedListener { +public abstract class JavaModelListener implements IElementChangedListener { /** * JavaModelListener constructor comment. */ public JavaModelListener() { - super(); - JavaCore.addElementChangedListener(this, ElementChangedEvent.POST_CHANGE | ElementChangedEvent.POST_RECONCILE); + this(ElementChangedEvent.POST_CHANGE); +} + +public JavaModelListener(int eventsToListen) { + JavaCore.addElementChangedListener(this, eventsToListen); } /** * One or more attributes of one or more elements maintained by @@ -142,4 +152,115 @@ protected void processJavaElementChanged(IType element, IJavaElementDelta delta) { // override to implement specific behavior } +private static final IPath CLASSPATH_PATH = new Path(".classpath"); +protected boolean isClassPathChange(IJavaElementDelta delta) { + int flags = delta.getFlags(); + return (delta.getKind() == IJavaElementDelta.CHANGED && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REORDER) != 0)); +} + +/** + * Method isClasspathResourceChange. + * @param delta + * @return boolean + */ +protected boolean isClasspathResourceChange(IJavaElementDelta delta) { + IResourceDelta[] resources = delta.getResourceDeltas(); + if (resources == null) + return false; + IPath path = null; + for (int i = 0; i < resources.length; i++) { + if (resources[i].getKind() == IResourceDelta.CHANGED) { + path = resources[i].getProjectRelativePath(); + if (path.equals(CLASSPATH_PATH) || isAlsoClasspathChange(path)) + return true; + } + } + return false; +} + +/** + * Is this path also a classpath change type of resource. If so, return true. + * Subclasses may override. Default is false. + * @param path + * @return + * + * @since 1.0.0 + */ +protected boolean isAlsoClasspathChange(IPath path) { + return false; +} + +/** + * This method will check to see if a <code>javaProject</code> is a project in the + * classpath of the adapterFactory java project. + */ +protected boolean isInClasspath(IJavaProject javaProject) { + IJavaProject adapterJavaProject = getJavaProject(); + if (javaProject.equals(adapterJavaProject)) + return true; + return isInClasspath(javaProject, adapterJavaProject, true, new HashSet()); +} + +/** + * Get the java project that we are interested in. + * @return + * + * @since 1.0.0 + */ +protected abstract IJavaProject getJavaProject(); + +protected boolean isInClasspath(IJavaProject testProject, IJavaProject targetProject, boolean isFirstLevel, Set visited) { + if (visited.contains(targetProject)) + return false; + visited.add(targetProject); + IClasspathEntry[] entries = null; + try { + entries = targetProject.getRawClasspath(); + } catch (JavaModelException e) { + return false; + } + IClasspathEntry entry, resEntry; + IJavaProject proj = null; + List projects = null; + for (int i = 0; i < entries.length; i++) { + entry = entries[i]; + if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { + resEntry = JavaCore.getResolvedClasspathEntry(entry); + proj = getJavaProject(entry); + if (isFirstLevel || resEntry.isExported()) { + if (proj.equals(testProject)) + return true; + else { + if (projects == null) + projects = new ArrayList(); + projects.add(proj); + } + } + } + } + return isInClasspath(testProject, projects, false, visited); +} + +protected boolean isInClasspath(IJavaProject testProject, List someJavaProjects, boolean isFirstLevel, Set visited) { + if (someJavaProjects == null) + return false; + int size = someJavaProjects.size(); + IJavaProject javaProj = null; + for (int i = 0; i < size; i++) { + javaProj = (IJavaProject) someJavaProjects.get(i); + return isInClasspath(testProject, javaProj, isFirstLevel, visited); + } + return false; +} + +protected IJavaProject getJavaProject(IClasspathEntry entry) { + IProject proj = getWorkspaceRoot().getProject(entry.getPath().segment(0)); + if (proj != null) + return (IJavaProject) JavaCore.create(proj); + return null; +} + +protected IWorkspaceRoot getWorkspaceRoot() { + return ResourcesPlugin.getWorkspace().getRoot(); +} }
diff --git a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaReflectionSynchronizer.java b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaReflectionSynchronizer.java index 7eb682a..b91e1a8 100644 --- a/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaReflectionSynchronizer.java +++ b/plugins/org.eclipse.jem.workbench/workbench/org/eclipse/jem/internal/adapters/jdom/JavaReflectionSynchronizer.java
@@ -11,15 +11,13 @@ *******************************************************************************/ /* * $RCSfile: JavaReflectionSynchronizer.java,v $ - * $Revision: 1.3 $ $Date: 2004/02/20 00:44:17 $ + * $Revision: 1.4 $ $Date: 2004/06/09 22:47:06 $ */ -import java.util.*; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.jdt.core.*; @@ -32,10 +30,11 @@ */ public class JavaReflectionSynchronizer extends JavaModelListener { - private static final IPath CLASSPATH_PATH = new Path(".classpath"); //$NON-NLS-1$ protected JavaJDOMAdapterFactory fAdapterFactory; + protected boolean flushedAll = false; protected List flushTypes = new ArrayList(); + protected List flushTypePlusInner = new ArrayList(); protected List notifications = new ArrayList(); /** * JavaReflectionSynchronizer constructor comment. @@ -44,69 +43,81 @@ super(); fAdapterFactory = synchronizee; } + /* (non-Javadoc) + * @see org.eclipse.jem.internal.adapters.jdom.JavaModelListener#getJavaProject() + */ + protected IJavaProject getJavaProject() { + return getAdapterFactory().getJavaProject(); + } /** * Tell the reflection factory to flush the passed IType */ protected Notification doFlush(IType element) { return getAdapterFactory().flushReflectionNoNotification(element.getFullyQualifiedName()); } + + /* + * Flush the compilation unit and any inner classes since we don't if they may or may not of changed. + */ + protected Notification doFlush(ICompilationUnit element) { + return getAdapterFactory().flushReflectionPlusInnerNoNotification(getFullNameFromElement(element)); + } + protected void flush(IType element) { if (!flushTypes.contains(element)) flushTypes.add(element); } + /* + * flush the compilation unit. Since we don't know if inner classes may also + * of been affected, they to will be flushed. + */ + protected void flush(ICompilationUnit element) { + if (!flushTypePlusInner.contains(element)) + flushTypePlusInner.add(element); + } protected void flushPackage(String packageName, boolean noFlushIfSourceFound) { notifications.addAll(getAdapterFactory().flushPackageNoNotification(packageName, true)); } protected JavaJDOMAdapterFactory getAdapterFactory() { return fAdapterFactory; } - private boolean isClassPathChange(IJavaElementDelta delta) { - int flags = delta.getFlags(); - return (delta.getKind() == IJavaElementDelta.CHANGED && ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) || ((flags & IJavaElementDelta.F_REORDER) != 0)); - } /** * If the complation unit's content has changed, notify all adapters which point to it. * This change may not require a call to flush() if the structure of the entity has not changed. * Creation date: (8/17/2001 3:58:31 PM) * @param param org.eclipse.jdt.core.IJavaElementDelta */ - public void processContentChanged(IJavaElementDelta delta) { - if (delta == null) - return; - // Any change will be notified, as changes to childrens may impact the text-location of this element. - IJavaElement element = delta.getElement(); - if (element.getElementType() == IJavaElement.COMPILATION_UNIT) - if (((delta.getFlags()) & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_MODIFIERS | IJavaElementDelta.F_CHILDREN | IJavaElementDelta.F_MOVED_TO | IJavaElementDelta.F_MOVED_FROM)) != 0) { - getAdapterFactory().notifyContentChanged((ICompilationUnit) element); - } - } +// This doesn't really apply anymore. If the file has been physically changed, we cannot determine if it +// just content like this. So we just ignore this for now. +// public void processContentChanged(IJavaElementDelta delta) { +// if (delta == null) +// return; +// // Any change will be notified, as changes to childrens may impact the text-location of this element. +// IJavaElement element = delta.getElement(); +// if (element.getElementType() == IJavaElement.COMPILATION_UNIT) +// if (((delta.getFlags()) & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_MODIFIERS | IJavaElementDelta.F_CHILDREN | IJavaElementDelta.F_MOVED_TO | IJavaElementDelta.F_MOVED_FROM)) != 0) { +// getAdapterFactory().notifyContentChanged((ICompilationUnit) element); +// } +// } /** * Handle the change for a single element, children will be handled separately. * */ protected void processJavaElementChanged(ICompilationUnit element, IJavaElementDelta delta) { - if (!element.isWorkingCopy()) { - switch (delta.getKind()) { - case IJavaElementDelta.CHANGED : { - if ((delta.getFlags() & IJavaElementDelta.F_PRIMARY_WORKING_COPY) != 0) { - try { - IType[] flushTypes = element.getAllTypes(); - for (int i = 0; i < flushTypes.length; i++) - flush(flushTypes[i]); - } catch (JavaModelException e) { - } - - } - - break; - } - case IJavaElementDelta.ADDED : - case IJavaElementDelta.REMOVED : { - disAssociateSourcePlusInner(getFullNameFromElement(element)); - return; - } + switch (delta.getKind()) { + case IJavaElementDelta.CHANGED : { + // A file save had occurred. It doesn't matter if currently working copy or not. + // It means something has changed to the file on disk, but don't know what. + if ((delta.getFlags() & IJavaElementDelta.F_PRIMARY_RESOURCE) != 0) { + flush(element); // Flush everything, including inner classes. + } + break; } - processChildren(element, delta); + case IJavaElementDelta.REMOVED : { + if (!element.isWorkingCopy()) + disAssociateSourcePlusInner(getFullNameFromElement(element)); + break; + } } } /** @@ -147,25 +158,6 @@ } } /** - * Method isClasspathResourceChange. - * @param delta - * @return boolean - */ - private boolean isClasspathResourceChange(IJavaElementDelta delta) { - IResourceDelta[] resources = delta.getResourceDeltas(); - if (resources == null) - return false; - IPath path = null; - for (int i = 0; i < resources.length; i++) { - if (resources[i].getKind() == IResourceDelta.CHANGED) { - path = resources[i].getProjectRelativePath(); - if (path.equals(CLASSPATH_PATH)) - return true; - } - } - return false; - } - /** * Handle the change for a single element, children will be handled separately. * */ @@ -189,12 +181,12 @@ case IJavaElementDelta.ADDED : { if (delta.getAffectedChildren().length == 0) flushPackage(delta.getElement().getElementName(), true); - break; + break; } case IJavaElementDelta.REMOVED :{ if (delta.getAffectedChildren().length == 0) getAdapterFactory().flushPackage(delta.getElement().getElementName(), false); - break; + break; } default : super.processJavaElementChanged(element, delta); @@ -221,6 +213,7 @@ * that the type's name is package.filename (without the .java) * If we are wrong (if, then a rare case), we will flush. * Next access will induce a reflection attempt. + * @deprecated This doesn't look like it is ever called. It someone else calls it, please contact development to see if right method to be called. */ protected void processRemoveOrAdd(ICompilationUnit element) { disAssociateSource(getFullNameFromElement(element)); @@ -249,72 +242,12 @@ JavaCore.removeElementChangedListener(this); } /** - * This method will check to see if a <code>javaProject</code> is a project in the - * classpath of the adapterFactory java project. - */ - protected boolean isInClasspath(IJavaProject javaProject) { - IJavaProject adapterJavaProject = getAdapterFactory().getJavaProject(); - if (javaProject.equals(adapterJavaProject)) - return true; - return isInClasspath(javaProject, adapterJavaProject, true, new HashSet()); - } - protected boolean isInClasspath(IJavaProject testProject, IJavaProject targetProject, boolean isFirstLevel, Set visited) { - if (visited.contains(targetProject)) - return false; - visited.add(targetProject); - IClasspathEntry[] entries = null; - try { - entries = targetProject.getRawClasspath(); - } catch (JavaModelException e) { - return false; - } - IClasspathEntry entry, resEntry; - IJavaProject proj = null; - List projects = null; - for (int i = 0; i < entries.length; i++) { - entry = entries[i]; - if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { - resEntry = JavaCore.getResolvedClasspathEntry(entry); - proj = getJavaProject(entry); - if (isFirstLevel || resEntry.isExported()) { - if (proj.equals(testProject)) - return true; - else { - if (projects == null) - projects = new ArrayList(); - projects.add(proj); - } - } - } - } - return isInClasspath(testProject, projects, false, visited); - } - protected boolean isInClasspath(IJavaProject testProject, List someJavaProjects, boolean isFirstLevel, Set visited) { - if (someJavaProjects == null) - return false; - int size = someJavaProjects.size(); - IJavaProject javaProj = null; - for (int i = 0; i < size; i++) { - javaProj = (IJavaProject) someJavaProjects.get(i); - return isInClasspath(testProject, javaProj, isFirstLevel, visited); - } - return false; - } - protected IJavaProject getJavaProject(IClasspathEntry entry) { - IProject proj = getWorkspaceRoot().getProject(entry.getPath().segment(0)); - if (proj != null) - return (IJavaProject) JavaCore.create(proj); - return null; - } - protected IWorkspaceRoot getWorkspaceRoot() { - return ResourcesPlugin.getWorkspace().getRoot(); - } - /** * @see org.eclipse.jem.internal.adapters.jdom.JavaModelListener#elementChanged(ElementChangedEvent) */ public void elementChanged(ElementChangedEvent event) { try { flushTypes.clear(); + flushTypePlusInner.clear(); notifications.clear(); super.elementChanged(event); flushTypes(); @@ -322,6 +255,7 @@ } finally { flushedAll = false; flushTypes.clear(); + flushTypePlusInner.clear(); notifications.clear(); } } @@ -339,6 +273,16 @@ notifications.add(not); } } + if (!flushTypePlusInner.isEmpty()) { + ICompilationUnit unit = null; + Notification not; + for (int i = 0; i < flushTypePlusInner.size(); i++) { + unit = (ICompilationUnit) flushTypePlusInner.get(i); + not = doFlush(unit); + if (not != null) + notifications.add(not); + } + } } /** * @param notifications
diff --git a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java index c2c7701..427d1de 100644 --- a/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java +++ b/plugins/org.eclipse.jem/mofjava/org/eclipse/jem/java/impl/JavaClassImpl.java
@@ -11,7 +11,7 @@ *******************************************************************************/ /* * $RCSfile: JavaClassImpl.java,v $ - * $Revision: 1.4 $ $Date: 2004/05/05 21:03:07 $ + * $Revision: 1.5 $ $Date: 2004/06/09 22:46:53 $ */ import java.util.ArrayList; @@ -446,7 +446,8 @@ /** * Return an IntrospectionAdaptor which can introspect our Java properties */ - protected IIntrospectionAdapter getIntrospectionAdapter() { + protected synchronized IIntrospectionAdapter getIntrospectionAdapter() { + // Need to sync this because we are now in multi-thread env. return (IIntrospectionAdapter) EcoreUtil.getRegisteredAdapter(this, IIntrospectionAdapter.ADAPTER_KEY); } @@ -702,7 +703,8 @@ /** * Return a ReadAdaptor which can reflect our Java properties */ - protected ReadAdaptor getReadAdaptor() { + protected synchronized ReadAdaptor getReadAdaptor() { + // Need to sync because now in a multi-thread env. return (ReadAdaptor) EcoreUtil.getRegisteredAdapter(this, ReadAdaptor.TYPE_KEY); }