[469037] RuntimeClasspathProviderDelegate does not update the classpath
container in certain cases
diff --git a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java
index bdae750..91bc0d0 100644
--- a/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java
+++ b/plugins/org.eclipse.jst.server.core/src/org/eclipse/jst/server/core/RuntimeClasspathProviderDelegate.java
@@ -1,390 +1,406 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2011 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - Initial API and implementation
- *******************************************************************************/
-package org.eclipse.jst.server.core;
-
-import java.io.File;
-import java.util.*;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.IClasspathAttribute;
-import org.eclipse.jdt.core.IClasspathContainer;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jst.server.core.internal.IMemento;
-import org.eclipse.jst.server.core.internal.JavaServerPlugin;
-import org.eclipse.jst.server.core.internal.RuntimeClasspathContainer;
-import org.eclipse.jst.server.core.internal.Trace;
-import org.eclipse.jst.server.core.internal.XMLMemento;
-import org.eclipse.wst.server.core.IRuntime;
-/**
- * A runtime classpath provider provides the classpath for a Java server runtime.
- * This provider is scoped by runtime type and may provide the classpath for multiple
- * runtime instances.
- * <p>
- * This abstract class is intended to be extended only by clients
- * to extend the <code>runtimeClasspathProviders</code> extension point.
- * </p>
- * <p>
- * <b>Provisional API:</b> This class/interface is part of an interim API that is still under development and expected to
- * change significantly before reaching stability. It is being made 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.
- * </p>
- *
- * @plannedfor 3.0
- */
-public abstract class RuntimeClasspathProviderDelegate {
- protected class SourceAttachmentUpdate {
- String runtimeId;
- IPath entry;
- IPath sourceAttachmentPath;
- IPath sourceAttachmentRootPath;
- IClasspathAttribute[] attributes;
- }
-
- private volatile List<SourceAttachmentUpdate> sourceAttachments;
-
- private String extensionId;
-
- private Map<String, IPath> runtimePathMap = Collections.synchronizedMap(new HashMap<String, IPath>());
-
- private Map<String, Integer> previousClasspath = Collections.synchronizedMap(new HashMap<String, Integer>());
-
- public RuntimeClasspathProviderDelegate() {
- // default constructor
- }
-
- /**
- * Initializes this classpath provider with its life-long id.
- * <p>
- * This method is called by the framework.
- * Clients should never call this method.
- * </p>
- * @param id the extension id
- */
- public final void initialize(String id) {
- extensionId = id;
- }
-
- /**
- * Resolves (creates the classpath entries for) the classpath container with
- * the given runtime and the given classpath container id (returned from
- * getClasspathEntryIds()). If the classpath container cannot be resolved
- * (for instance, if the runtime does not exist), return null.
- *
- * @param runtime the runtime to resolve the container for
- * @return an array of classpath entries for the container, or null if the
- * container could not be resolved
- * @deprecated use resolveClasspathContainer(IProject, IRuntime) instead
- */
- public IClasspathEntry[] resolveClasspathContainer(IRuntime runtime) {
- return null;
- }
-
- /**
- * Resolves (creates the classpath entries for) the classpath container with
- * the given runtime and the given classpath container id (returned from
- * getClasspathEntryIds()). If the classpath container cannot be resolved
- * (for instance, if the runtime does not exist), return null.
- *
- * @param project the project to resolve
- * @param runtime the runtime to resolve the container for
- * @return an array of classpath entries for the container, or null if the
- * container could not be resolved
- */
- public IClasspathEntry[] resolveClasspathContainer(IProject project, IRuntime runtime) {
- return null;
- }
-
- /**
- * Resolve the classpath container.
- *
- * @param runtime a runtime
- * @return a possibly empty array of classpath entries
- * @deprecated should use resolveClasspathContainerImpl(IProject, IRuntime) instead
- */
- public IClasspathEntry[] resolveClasspathContainerImpl(IRuntime runtime) {
- return resolveClasspathContainerImpl(null, runtime);
- }
-
- /**
- * Resolve the classpath container.
- *
- * @param project a project
- * @param runtime a runtime
- * @return a possibly empty array of classpath entries
- */
- public IClasspathEntry[] resolveClasspathContainerImpl(IProject project, IRuntime runtime) {
- if (runtime == null)
- return new IClasspathEntry[0];
- runtimePathMap.put(runtime.getId(), runtime.getLocation());
- IClasspathEntry[] entries = resolveClasspathContainer(project, runtime);
- if (entries == null)
- entries = resolveClasspathContainer(runtime);
-
- if (entries == null)
- entries = new IClasspathEntry[0];
-
- synchronized (this) {
- if (sourceAttachments == null)
- load();
- }
- List<SourceAttachmentUpdate> srcAttachments = sourceAttachments;
-
- if (srcAttachments != null) {
- int size = entries.length;
- int size2 = srcAttachments.size();
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size2; j++) {
- SourceAttachmentUpdate sau = srcAttachments.get(j);
- if (sau.runtimeId.equals(runtime.getId()) && sau.entry.equals(entries[i].getPath())) {
- IClasspathAttribute[] consolidatedClasspathAttributes = consolidateClasspathAttributes(sau.attributes, entries[i].getExtraAttributes());
- entries[i] = JavaCore.newLibraryEntry(entries[i].getPath(), sau.sourceAttachmentPath, sau.sourceAttachmentRootPath, entries[i].getAccessRules(), consolidatedClasspathAttributes, false);
- break;
- }
- }
- }
- }
-
- String key = project.getName() + "/" + runtime.getId();
- if (!previousClasspath.containsKey(key))
- previousClasspath.put(key, new Integer(entries.length));
- else {
- Integer previousEntries = previousClasspath.get(key);
-
- if ((previousEntries == null) || (previousEntries.intValue() != entries.length)) {
- if (Trace.FINEST) {
- Trace.trace(Trace.STRING_FINEST, "Classpath update: " + key + " " + entries);
- }
- previousClasspath.put(key, new Integer(entries.length));
-
- IPath path = new Path(RuntimeClasspathContainer.SERVER_CONTAINER);
- path = path.append(extensionId).append(runtime.getId());
- try {
- IJavaProject javaProject = JavaCore.create(project);
- JavaCore.setClasspathContainer(path, new IJavaProject[] { javaProject },
- new IClasspathContainer[] { null }, new NullProgressMonitor());
- } catch (Exception e) {
- if (Trace.WARNING) {
- Trace.trace(Trace.STRING_WARNING, "Error updating classpath", e);
- }
- }
- }
- }
-
- return entries;
- }
-
- /*
- * Returns true if there are any changes in the runtime since the last time that the
- * classpath was resolved which may affect the classpath, and false otherwise. This
- * method is used to check projects when a runtime changes and automatically rebuild
- * them if necessary.
- *
- * @param runtime a runtime
- * @return <code>true</code> if the classpath may change due to a change in the runtime,
- * and <code>false</code> if there are no changes
- */
- public boolean hasRuntimeClasspathChanged(IRuntime runtime) {
- try {
- IPath path = runtimePathMap.get(runtime.getId());
- return (path != null && !path.equals(runtime.getLocation()));
- } catch (Exception e) {
- // ignore
- }
- return false;
- }
-
- private static void addJarFiles(File dir, List<IClasspathEntry> list, boolean includeSubdirectories) {
- int depth = 0;
- if (includeSubdirectories)
- depth = 2;
- addJarFiles(dir, list, depth);
- }
-
- private static void addJarFiles(File dir, List<IClasspathEntry> list, int depth) {
- if (dir == null)
- throw new IllegalArgumentException();
-
- File[] files = dir.listFiles();
- if (files != null) {
- for (File file : files) {
- if (file.isDirectory() && depth > 0) {
- addJarFiles(file, list, depth - 1);
- } else if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".zip")) {
- IPath path = new Path(file.getAbsolutePath());
- list.add(JavaCore.newLibraryEntry(path, null, null));
- }
- }
- }
- }
-
- /**
- * Add library entries to the given list for every jar file found in the
- * given directory. Optionally search subdirectories as well.
- *
- * @param list a list
- * @param dir a directory
- * @param includeSubdirectories <code>true</code> to include subdirectories, and
- * <code>false</code> otherwise
- */
- protected static void addLibraryEntries(List<IClasspathEntry> list, File dir, boolean includeSubdirectories) {
- if (dir == null)
- throw new IllegalArgumentException();
- addJarFiles(dir, list, includeSubdirectories);
- }
-
- /**
- * Request that the classpath container for the given runtime and id be updated
- * with the given classpath container entries.
- *
- * @param runtime a runtime
- * @param entries an array of classpath entries
- */
- public void requestClasspathContainerUpdate(IRuntime runtime, IClasspathEntry[] entries) {
- // default behaviour is to save the source path entries
- if (runtime == null || entries == null)
- return;
-
- // find the source attachments
- List<SourceAttachmentUpdate> srcAttachments = new ArrayList<SourceAttachmentUpdate>();
-
- for (IClasspathEntry entry : entries) {
- if (entry.getSourceAttachmentPath() != null || (entry.getExtraAttributes() != null && entry.getExtraAttributes().length > 0)) {
- SourceAttachmentUpdate sau = new SourceAttachmentUpdate();
- sau.runtimeId = runtime.getId();
- sau.entry = entry.getPath();
- sau.sourceAttachmentPath = entry.getSourceAttachmentPath();
- sau.sourceAttachmentRootPath = entry.getSourceAttachmentRootPath();
- sau.attributes = entry.getExtraAttributes();
- srcAttachments.add(sau);
- }
- }
- sourceAttachments = srcAttachments;
- save();
- }
-
- /**
- * Load source attachment info.
- */
- private void load() {
- List<SourceAttachmentUpdate> srcAttachments = new ArrayList<SourceAttachmentUpdate>();
-
- String id = extensionId;
- String filename = JavaServerPlugin.getInstance().getStateLocation().append(id + ".xml").toOSString();
- if (!(new File(filename)).exists())
- return;
-
- try {
- IMemento memento = XMLMemento.loadMemento(filename);
-
- IMemento[] children = memento.getChildren("source-attachment");
- for (IMemento child : children) {
- try {
- SourceAttachmentUpdate sau = new SourceAttachmentUpdate();
- sau.runtimeId = child.getString("runtime-id");
- String temp = child.getString("entry");
- if (temp != null)
- sau.entry = new Path(temp);
- temp = child.getString("source-attachment-path");
- if (temp != null)
- sau.sourceAttachmentPath = new Path(temp);
- temp = child.getString("source-attachment-root-path");
- if (temp != null)
- sau.sourceAttachmentRootPath = new Path(temp);
- IMemento[] attrChildren = child.getChildren("attribute");
- if (attrChildren != null) {
- int size2 = attrChildren.length;
- sau.attributes = new IClasspathAttribute[size2];
- for (int j = 0; j < size2; j++) {
- String name = attrChildren[j].getString("name");
- String value = attrChildren[j].getString("value");
- sau.attributes[j] = JavaCore.newClasspathAttribute(name, value);
- }
- }
- srcAttachments.add(sau);
- } catch (Exception e) {
- if (Trace.WARNING) {
- Trace.trace(Trace.STRING_WARNING, "Could not load source attachment: " + e);
- }
- }
- }
- } catch (Exception e) {
- if (Trace.WARNING) {
- Trace.trace(Trace.STRING_WARNING, "Could not load source path info", e);
- }
- }
- sourceAttachments = srcAttachments;
- }
-
- /**
- * Save source attachment info.
- */
- private synchronized void save() {
- List<SourceAttachmentUpdate> srcAttachments = sourceAttachments;
- if (srcAttachments == null)
- return;
- String id = extensionId;
- String filename = JavaServerPlugin.getInstance().getStateLocation().append(id + ".xml").toOSString();
- try {
- XMLMemento memento = XMLMemento.createWriteRoot("classpath");
-
- Iterator iterator = srcAttachments.iterator();
- while (iterator.hasNext()) {
- SourceAttachmentUpdate sau = (SourceAttachmentUpdate) iterator.next();
- IMemento child = memento.createChild("source-attachment");
- child.putString("runtime-id", sau.runtimeId);
- if (sau.entry != null)
- child.putString("entry", sau.entry.toPortableString());
- if (sau.sourceAttachmentPath != null)
- child.putString("source-attachment-path", sau.sourceAttachmentPath.toPortableString());
- if (sau.sourceAttachmentRootPath != null)
- child.putString("source-attachment-root-path", sau.sourceAttachmentRootPath.toPortableString());
- if (sau.attributes != null) {
- for (IClasspathAttribute attr : sau.attributes) {
- IMemento attrChild = child.createChild("attribute");
- attrChild.putString("name", attr.getName());
- attrChild.putString("value", attr.getValue());
- }
- }
- }
-
- memento.saveToFile(filename);
- } catch (Exception e) {
- if (Trace.SEVERE) {
- Trace.trace(Trace.STRING_SEVERE, "Error saving source path info", e);
- }
- }
- }
-
- public IClasspathAttribute[] consolidateClasspathAttributes(IClasspathAttribute[] sourceAttachmentAttributes, IClasspathAttribute[] classpathEntryAttributes) {
- List classpathAttributeList = new ArrayList();
- classpathAttributeList.addAll(Arrays.asList(sourceAttachmentAttributes));
- for (int i = 0; i < classpathEntryAttributes.length; i++) {
- boolean attributeCollision = false;
- for (int j = 0; j < sourceAttachmentAttributes.length; j++) {
- String name = classpathEntryAttributes[i].getName();
- if(name != null && name.equals(sourceAttachmentAttributes[j].getName())) {
- attributeCollision = true;
- break;
- }
- }
- if(!attributeCollision) {
- classpathAttributeList.add(classpathEntryAttributes[i]);
- }
- }
- return (IClasspathAttribute[]) classpathAttributeList.toArray(new IClasspathAttribute[classpathAttributeList.size()]);
- }
+/*******************************************************************************
+ * Copyright (c) 2003, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jst.server.core;
+
+import java.io.File;
+import java.util.*;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.IClasspathAttribute;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jst.server.core.internal.IMemento;
+import org.eclipse.jst.server.core.internal.JavaServerPlugin;
+import org.eclipse.jst.server.core.internal.RuntimeClasspathContainer;
+import org.eclipse.jst.server.core.internal.Trace;
+import org.eclipse.jst.server.core.internal.XMLMemento;
+import org.eclipse.wst.server.core.IRuntime;
+/**
+ * A runtime classpath provider provides the classpath for a Java server runtime.
+ * This provider is scoped by runtime type and may provide the classpath for multiple
+ * runtime instances.
+ * <p>
+ * This abstract class is intended to be extended only by clients
+ * to extend the <code>runtimeClasspathProviders</code> extension point.
+ * </p>
+ * <p>
+ * <b>Provisional API:</b> This class/interface is part of an interim API that is still under development and expected to
+ * change significantly before reaching stability. It is being made 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.
+ * </p>
+ *
+ * @plannedfor 3.0
+ */
+public abstract class RuntimeClasspathProviderDelegate {
+ protected class SourceAttachmentUpdate {
+ String runtimeId;
+ IPath entry;
+ IPath sourceAttachmentPath;
+ IPath sourceAttachmentRootPath;
+ IClasspathAttribute[] attributes;
+ }
+
+ private volatile List<SourceAttachmentUpdate> sourceAttachments;
+
+ private String extensionId;
+
+ private Map<String, IPath> runtimePathMap = Collections.synchronizedMap(new HashMap<String, IPath>());
+
+ private Map<String, IClasspathEntry[]> previousClasspath = Collections.synchronizedMap(new HashMap<String, IClasspathEntry[]>());
+
+ public RuntimeClasspathProviderDelegate() {
+ // default constructor
+ }
+
+ /**
+ * Initializes this classpath provider with its life-long id.
+ * <p>
+ * This method is called by the framework.
+ * Clients should never call this method.
+ * </p>
+ * @param id the extension id
+ */
+ public final void initialize(String id) {
+ extensionId = id;
+ }
+
+ /**
+ * Resolves (creates the classpath entries for) the classpath container with
+ * the given runtime and the given classpath container id (returned from
+ * getClasspathEntryIds()). If the classpath container cannot be resolved
+ * (for instance, if the runtime does not exist), return null.
+ *
+ * @param runtime the runtime to resolve the container for
+ * @return an array of classpath entries for the container, or null if the
+ * container could not be resolved
+ * @deprecated use resolveClasspathContainer(IProject, IRuntime) instead
+ */
+ public IClasspathEntry[] resolveClasspathContainer(IRuntime runtime) {
+ return null;
+ }
+
+ /**
+ * Resolves (creates the classpath entries for) the classpath container with
+ * the given runtime and the given classpath container id (returned from
+ * getClasspathEntryIds()). If the classpath container cannot be resolved
+ * (for instance, if the runtime does not exist), return null.
+ *
+ * @param project the project to resolve
+ * @param runtime the runtime to resolve the container for
+ * @return an array of classpath entries for the container, or null if the
+ * container could not be resolved
+ */
+ public IClasspathEntry[] resolveClasspathContainer(IProject project, IRuntime runtime) {
+ return null;
+ }
+
+ /**
+ * Resolve the classpath container.
+ *
+ * @param runtime a runtime
+ * @return a possibly empty array of classpath entries
+ * @deprecated should use resolveClasspathContainerImpl(IProject, IRuntime) instead
+ */
+ public IClasspathEntry[] resolveClasspathContainerImpl(IRuntime runtime) {
+ return resolveClasspathContainerImpl(null, runtime);
+ }
+
+ /**
+ * Resolve the classpath container.
+ *
+ * @param project a project
+ * @param runtime a runtime
+ * @return a possibly empty array of classpath entries
+ */
+ public IClasspathEntry[] resolveClasspathContainerImpl(IProject project, IRuntime runtime) {
+ if (runtime == null)
+ return new IClasspathEntry[0];
+ runtimePathMap.put(runtime.getId(), runtime.getLocation());
+ IClasspathEntry[] entries = resolveClasspathContainer(project, runtime);
+ if (entries == null)
+ entries = resolveClasspathContainer(runtime);
+
+ if (entries == null)
+ entries = new IClasspathEntry[0];
+
+ synchronized (this) {
+ if (sourceAttachments == null)
+ load();
+ }
+ List<SourceAttachmentUpdate> srcAttachments = sourceAttachments;
+
+ if (srcAttachments != null) {
+ int size = entries.length;
+ int size2 = srcAttachments.size();
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size2; j++) {
+ SourceAttachmentUpdate sau = srcAttachments.get(j);
+ if (sau.runtimeId.equals(runtime.getId()) && sau.entry.equals(entries[i].getPath())) {
+ IClasspathAttribute[] consolidatedClasspathAttributes = consolidateClasspathAttributes(sau.attributes, entries[i].getExtraAttributes());
+ entries[i] = JavaCore.newLibraryEntry(entries[i].getPath(), sau.sourceAttachmentPath, sau.sourceAttachmentRootPath, entries[i].getAccessRules(), consolidatedClasspathAttributes, false);
+ break;
+ }
+ }
+ }
+ }
+
+ String key = project.getName() + "/" + runtime.getId();
+ if (!previousClasspath.containsKey(key))
+ previousClasspath.put(key, entries);
+ else {
+ IClasspathEntry[] previousClasspathEntries = previousClasspath.get(key);
+
+ if (previousClasspathEntries == null
+ || previousClasspathEntries.length != entries.length
+ || entriesChanged(previousClasspathEntries,entries)) {
+ if (Trace.FINEST) {
+ Trace.trace(Trace.STRING_FINEST, "Classpath update: " + key + " " + entries);
+ }
+ previousClasspath.put(key, entries);
+
+ IPath path = new Path(RuntimeClasspathContainer.SERVER_CONTAINER);
+ path = path.append(extensionId).append(runtime.getId());
+ try {
+ IJavaProject javaProject = JavaCore.create(project);
+ JavaCore.setClasspathContainer(path, new IJavaProject[] { javaProject },
+ new IClasspathContainer[] { null }, new NullProgressMonitor());
+ } catch (Exception e) {
+ if (Trace.WARNING) {
+ Trace.trace(Trace.STRING_WARNING, "Error updating classpath", e);
+ }
+ }
+ }
+ }
+
+ return entries;
+ }
+
+ private boolean entriesChanged(IClasspathEntry[] previousEntries, IClasspathEntry[] entries) {
+ if (previousEntries.length != entries.length) {
+ return true;
+ }
+ for (int i=0; i<previousEntries.length; i++) {
+ if ((previousEntries[i] == null && entries[i] != null)
+ || (previousEntries[i].getPath() == null && entries[i].getPath() != null)
+ || !previousEntries[i].getPath().equals(entries[i].getPath())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Returns true if there are any changes in the runtime since the last time that the
+ * classpath was resolved which may affect the classpath, and false otherwise. This
+ * method is used to check projects when a runtime changes and automatically rebuild
+ * them if necessary.
+ *
+ * @param runtime a runtime
+ * @return <code>true</code> if the classpath may change due to a change in the runtime,
+ * and <code>false</code> if there are no changes
+ */
+ public boolean hasRuntimeClasspathChanged(IRuntime runtime) {
+ try {
+ IPath path = runtimePathMap.get(runtime.getId());
+ return (path != null && !path.equals(runtime.getLocation()));
+ } catch (Exception e) {
+ // ignore
+ }
+ return false;
+ }
+
+ private static void addJarFiles(File dir, List<IClasspathEntry> list, boolean includeSubdirectories) {
+ int depth = 0;
+ if (includeSubdirectories)
+ depth = 2;
+ addJarFiles(dir, list, depth);
+ }
+
+ private static void addJarFiles(File dir, List<IClasspathEntry> list, int depth) {
+ if (dir == null)
+ throw new IllegalArgumentException();
+
+ File[] files = dir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory() && depth > 0) {
+ addJarFiles(file, list, depth - 1);
+ } else if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".zip")) {
+ IPath path = new Path(file.getAbsolutePath());
+ list.add(JavaCore.newLibraryEntry(path, null, null));
+ }
+ }
+ }
+ }
+
+ /**
+ * Add library entries to the given list for every jar file found in the
+ * given directory. Optionally search subdirectories as well.
+ *
+ * @param list a list
+ * @param dir a directory
+ * @param includeSubdirectories <code>true</code> to include subdirectories, and
+ * <code>false</code> otherwise
+ */
+ protected static void addLibraryEntries(List<IClasspathEntry> list, File dir, boolean includeSubdirectories) {
+ if (dir == null)
+ throw new IllegalArgumentException();
+ addJarFiles(dir, list, includeSubdirectories);
+ }
+
+ /**
+ * Request that the classpath container for the given runtime and id be updated
+ * with the given classpath container entries.
+ *
+ * @param runtime a runtime
+ * @param entries an array of classpath entries
+ */
+ public void requestClasspathContainerUpdate(IRuntime runtime, IClasspathEntry[] entries) {
+ // default behaviour is to save the source path entries
+ if (runtime == null || entries == null)
+ return;
+
+ // find the source attachments
+ List<SourceAttachmentUpdate> srcAttachments = new ArrayList<SourceAttachmentUpdate>();
+
+ for (IClasspathEntry entry : entries) {
+ if (entry.getSourceAttachmentPath() != null || (entry.getExtraAttributes() != null && entry.getExtraAttributes().length > 0)) {
+ SourceAttachmentUpdate sau = new SourceAttachmentUpdate();
+ sau.runtimeId = runtime.getId();
+ sau.entry = entry.getPath();
+ sau.sourceAttachmentPath = entry.getSourceAttachmentPath();
+ sau.sourceAttachmentRootPath = entry.getSourceAttachmentRootPath();
+ sau.attributes = entry.getExtraAttributes();
+ srcAttachments.add(sau);
+ }
+ }
+ sourceAttachments = srcAttachments;
+ save();
+ }
+
+ /**
+ * Load source attachment info.
+ */
+ private void load() {
+ List<SourceAttachmentUpdate> srcAttachments = new ArrayList<SourceAttachmentUpdate>();
+
+ String id = extensionId;
+ String filename = JavaServerPlugin.getInstance().getStateLocation().append(id + ".xml").toOSString();
+ if (!(new File(filename)).exists())
+ return;
+
+ try {
+ IMemento memento = XMLMemento.loadMemento(filename);
+
+ IMemento[] children = memento.getChildren("source-attachment");
+ for (IMemento child : children) {
+ try {
+ SourceAttachmentUpdate sau = new SourceAttachmentUpdate();
+ sau.runtimeId = child.getString("runtime-id");
+ String temp = child.getString("entry");
+ if (temp != null)
+ sau.entry = new Path(temp);
+ temp = child.getString("source-attachment-path");
+ if (temp != null)
+ sau.sourceAttachmentPath = new Path(temp);
+ temp = child.getString("source-attachment-root-path");
+ if (temp != null)
+ sau.sourceAttachmentRootPath = new Path(temp);
+ IMemento[] attrChildren = child.getChildren("attribute");
+ if (attrChildren != null) {
+ int size2 = attrChildren.length;
+ sau.attributes = new IClasspathAttribute[size2];
+ for (int j = 0; j < size2; j++) {
+ String name = attrChildren[j].getString("name");
+ String value = attrChildren[j].getString("value");
+ sau.attributes[j] = JavaCore.newClasspathAttribute(name, value);
+ }
+ }
+ srcAttachments.add(sau);
+ } catch (Exception e) {
+ if (Trace.WARNING) {
+ Trace.trace(Trace.STRING_WARNING, "Could not load source attachment: " + e);
+ }
+ }
+ }
+ } catch (Exception e) {
+ if (Trace.WARNING) {
+ Trace.trace(Trace.STRING_WARNING, "Could not load source path info", e);
+ }
+ }
+ sourceAttachments = srcAttachments;
+ }
+
+ /**
+ * Save source attachment info.
+ */
+ private synchronized void save() {
+ List<SourceAttachmentUpdate> srcAttachments = sourceAttachments;
+ if (srcAttachments == null)
+ return;
+ String id = extensionId;
+ String filename = JavaServerPlugin.getInstance().getStateLocation().append(id + ".xml").toOSString();
+ try {
+ XMLMemento memento = XMLMemento.createWriteRoot("classpath");
+
+ Iterator iterator = srcAttachments.iterator();
+ while (iterator.hasNext()) {
+ SourceAttachmentUpdate sau = (SourceAttachmentUpdate) iterator.next();
+ IMemento child = memento.createChild("source-attachment");
+ child.putString("runtime-id", sau.runtimeId);
+ if (sau.entry != null)
+ child.putString("entry", sau.entry.toPortableString());
+ if (sau.sourceAttachmentPath != null)
+ child.putString("source-attachment-path", sau.sourceAttachmentPath.toPortableString());
+ if (sau.sourceAttachmentRootPath != null)
+ child.putString("source-attachment-root-path", sau.sourceAttachmentRootPath.toPortableString());
+ if (sau.attributes != null) {
+ for (IClasspathAttribute attr : sau.attributes) {
+ IMemento attrChild = child.createChild("attribute");
+ attrChild.putString("name", attr.getName());
+ attrChild.putString("value", attr.getValue());
+ }
+ }
+ }
+
+ memento.saveToFile(filename);
+ } catch (Exception e) {
+ if (Trace.SEVERE) {
+ Trace.trace(Trace.STRING_SEVERE, "Error saving source path info", e);
+ }
+ }
+ }
+
+ public IClasspathAttribute[] consolidateClasspathAttributes(IClasspathAttribute[] sourceAttachmentAttributes, IClasspathAttribute[] classpathEntryAttributes) {
+ List classpathAttributeList = new ArrayList();
+ classpathAttributeList.addAll(Arrays.asList(sourceAttachmentAttributes));
+ for (int i = 0; i < classpathEntryAttributes.length; i++) {
+ boolean attributeCollision = false;
+ for (int j = 0; j < sourceAttachmentAttributes.length; j++) {
+ String name = classpathEntryAttributes[i].getName();
+ if(name != null && name.equals(sourceAttachmentAttributes[j].getName())) {
+ attributeCollision = true;
+ break;
+ }
+ }
+ if(!attributeCollision) {
+ classpathAttributeList.add(classpathEntryAttributes[i]);
+ }
+ }
+ return (IClasspathAttribute[]) classpathAttributeList.toArray(new IClasspathAttribute[classpathAttributeList.size()]);
+ }
}
\ No newline at end of file