blob: aa72674f541708acac251cb7a31011534c109436 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2006 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.j2ee.internal.common.operations;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jst.j2ee.application.internal.operations.ClassPathSelection;
import org.eclipse.jst.j2ee.application.internal.operations.ClasspathElement;
import org.eclipse.wst.common.frameworks.internal.DoNotUseMeThisWillBeDeletedPost15;
import org.eclipse.wst.common.frameworks.internal.enablement.nonui.WFTWrappedException;
import org.eclipse.wst.common.frameworks.internal.operations.IHeadlessRunnableWithProgress;
/**
* {@link DoNotUseMeThisWillBeDeletedPost15}
*
* @deprecated This should no longer be necessary because of the new EAR & Web Lib classpath
* containers
*/
public class UpdateJavaBuildPathOperation implements IHeadlessRunnableWithProgress {
protected IJavaProject javaProject;
protected ClassPathSelection classPathSelection;
// All the Java build path entries created by the classpath selection
protected Set allClasspathEntries;
protected List allUnselectedClasspathEntries;
/**
* UpdateJavaBuildPathOperation constructor comment.
*/
public UpdateJavaBuildPathOperation(IJavaProject aJavaProject, ClassPathSelection aClassPathSelection) {
super();
javaProject = aJavaProject;
classPathSelection = aClassPathSelection;
allClasspathEntries = new HashSet();
IClasspathEntry[] classpathEntry = aClassPathSelection.getClasspathEntriesForSelected();
if (classpathEntry != null)
allClasspathEntries.addAll(Arrays.asList(classpathEntry));
}
/**
* UpdateJavaBuildPathOperation constructor comment.
*/
public UpdateJavaBuildPathOperation(IJavaProject aJavaProject, ClassPathSelection selected, ClassPathSelection unselected) {
super();
javaProject = aJavaProject;
classPathSelection = selected;
allClasspathEntries = new HashSet();
if (selected != null && !selected.getClasspathElements().isEmpty())
allClasspathEntries.addAll(Arrays.asList(selected.getClasspathEntriesForSelected()));
allUnselectedClasspathEntries = new ArrayList();
if (unselected != null && !unselected.getClasspathElements().isEmpty())
allUnselectedClasspathEntries.addAll(unselected.getClasspathElements());
}
public UpdateJavaBuildPathOperation(IJavaProject aJavaProject, ClassPathSelection selected, List unselected) {
super();
javaProject = aJavaProject;
classPathSelection = selected;
allClasspathEntries = new HashSet();
if (selected != null && !selected.getClasspathElements().isEmpty())
allClasspathEntries.addAll(Arrays.asList(selected.getClasspathEntriesForSelected()));
allUnselectedClasspathEntries = new ArrayList();
if (unselected != null && !unselected.isEmpty())
allUnselectedClasspathEntries.addAll(unselected);
}
protected void ensureClasspathEntryIsExported(List cp, IClasspathEntry entry) {
if (entry.isExported())
return;
int index = getIndex(cp, entry);
IClasspathEntry newEntry = null;
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_PROJECT :
newEntry = JavaCore.newProjectEntry(entry.getPath(), true);
break;
case IClasspathEntry.CPE_LIBRARY :
newEntry = JavaCore.newLibraryEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), true);
break;
case IClasspathEntry.CPE_VARIABLE :
newEntry = JavaCore.newVariableEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath());
}
cp.set(index, newEntry);
}
protected IClasspathEntry ensureElementInList(List cp, ClasspathElement element, IClasspathEntry predecessor) {
IClasspathEntry addedEntry = null;
// The element might have multiple entries in the case of
// the imported_classes.jar file
IClasspathEntry[] cpEntries = element.newClasspathEntries();
if (cpEntries == null || cpEntries.length == 0)
// indicates an invalid entry
return null;
int predecessorPos = predecessor == null ? -1 : getIndex(cp, predecessor);
addedEntry = cpEntries[0];
// Ensure that the first item is in the list, and follows
// the predecessor if specified; preserve existing items in
// the case of source attachments
int pos = getIndex(cp, addedEntry);
if (pos == -1) {
if (predecessorPos == -1)
cp.add(addedEntry);
else
cp.add(predecessorPos + 1, addedEntry);
} else {
addedEntry = (IClasspathEntry) cp.get(pos);
if (pos < predecessorPos) {
cp.remove(addedEntry);
cp.add(predecessorPos, addedEntry);
}
}
ensureClasspathEntryIsExported(cp, addedEntry);
// Remove and add so we can ensure the proper order; this
// is the case of the imported_classes.jar; we always want it
// directly after the project
for (int i = 1; i < cpEntries.length; i++) {
int index = getIndex(cp, cpEntries[i]);
if (index != -1) {
addedEntry = (IClasspathEntry) cp.get(index);
cp.remove(index);
} else
addedEntry = cpEntries[i];
pos = getIndex(cp, cpEntries[0]);
cp.add(pos + 1, addedEntry);
}
return addedEntry;
}
protected int getIndex(List cp, IClasspathEntry entry) {
for (int i = 0; i < cp.size(); i++) {
IClasspathEntry elmt = (IClasspathEntry) cp.get(i);
if (elmt.getPath().equals(entry.getPath()))
return i;
}
return -1;
}
protected void ensureElementNotInList(List cp, ClasspathElement element) {
IClasspathEntry[] cpEntries = element.newClasspathEntries();
if (cpEntries == null || cpEntries.length == 0)
return;
for (int i = 0; i < cpEntries.length; i++) {
if (allClasspathEntries.contains(cpEntries[i]))
// This may be included indirectly by a transitive dependency
continue;
int index = getIndex(cp, cpEntries[i]);
if (index != -1)
cp.remove(index);
}
}
protected void ensureRemoveElementInList(List cp, ClasspathElement element) {
IClasspathEntry[] cpEntries = element.newClasspathEntries();
if (cpEntries == null || cpEntries.length == 0)
return;
for (int i = 0; i < cpEntries.length; i++) {
if (cp.contains(cpEntries[i])) {
int index = getIndex(cp, cpEntries[i]);
if (index != -1)
cp.remove(index);
}
}
}
/**
* Runs this operation. Progress should be reported to the given progress monitor. This method
* is usually invoked by an <code>IRunnableContext</code>'s<code>run</code> method, which
* supplies the progress monitor. A request to cancel the operation should be honored and
* acknowledged by throwing <code>InterruptedException</code>.
*
* @param monitor
* the progress monitor to use to display progress and receive requests for
* cancelation
* @exception InvocationTargetException
* if the run method must propagate a checked exception, it should wrap it inside
* an <code>InvocationTargetException</code>; runtime exceptions are
* automatically wrapped in an <code>InvocationTargetException</code> by the
* calling context
* @exception InterruptedException
* if the operation detects a request to cancel, using
* <code>IProgressMonitor.isCanceled()</code>, it should exit by throwing
* <code>InterruptedException</code>
*
* @see IRunnableContext#run
*/
public void run(org.eclipse.core.runtime.IProgressMonitor monitor) throws java.lang.reflect.InvocationTargetException, InterruptedException {
try {
String[] prevRequiredProjects = javaProject.getRequiredProjectNames();
List cp = new ArrayList(Arrays.asList(javaProject.getRawClasspath()));
List classpathElements = classPathSelection.getClasspathElements();
IClasspathEntry predecessor = null;
IClasspathEntry result = null;
for (int i = 0; i < classpathElements.size(); i++) {
ClasspathElement element = (ClasspathElement) classpathElements.get(i);
if (element.isSelected()) {
result = ensureElementInList(cp, element, predecessor);
if (result != null)
predecessor = result;
} else
ensureElementNotInList(cp, element);
}
filterUnselectedEntries(cp);
IClasspathEntry[] newCp = ((IClasspathEntry[]) cp.toArray(new IClasspathEntry[cp.size()]));
javaProject.setRawClasspath(newCp, monitor);
updateRequiredProjects(javaProject, prevRequiredProjects, new SubProgressMonitor(monitor, 1));
} catch (Exception ex) {
throw new WFTWrappedException(ex);
}
}
private void filterUnselectedEntries(List cp) {
if (allUnselectedClasspathEntries != null) {
for (int i = 0; i < allUnselectedClasspathEntries.size(); i++) {
ClasspathElement element = (ClasspathElement) allUnselectedClasspathEntries.get(i);
ensureRemoveElementInList(cp, element);
}
}
}
protected void updateRequiredProjects(IJavaProject jproject, String[] prevRequiredProjects, IProgressMonitor monitor) throws CoreException {
String[] newRequiredProjects = jproject.getRequiredProjectNames();
ArrayList prevEntries = new ArrayList(Arrays.asList(prevRequiredProjects));
ArrayList newEntries = new ArrayList(Arrays.asList(newRequiredProjects));
IProject proj = jproject.getProject();
IProjectDescription projDesc = proj.getDescription();
ArrayList newRefs = new ArrayList();
IProject[] referencedProjects = projDesc.getReferencedProjects();
for (int i = 0; i < referencedProjects.length; i++) {
String curr = referencedProjects[i].getName();
if (newEntries.remove(curr) || !prevEntries.contains(curr)) {
newRefs.add(referencedProjects[i]);
}
}
IWorkspaceRoot root = proj.getWorkspace().getRoot();
for (int i = 0; i < newEntries.size(); i++) {
String curr = (String) newEntries.get(i);
newRefs.add(root.getProject(curr));
}
projDesc.setReferencedProjects((IProject[]) newRefs.toArray(new IProject[newRefs.size()]));
proj.setDescription(projDesc, monitor);
}
}