blob: 17c4ce3aa60b8b7df3669ca73c9fdeb74ebb3f46 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2010 Sonatype, Inc.
* 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:
* Sonatype, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.m2e.jdt.internal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.apache.maven.artifact.Artifact;
import org.eclipse.m2e.core.embedder.ArtifactKey;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.jdt.IClasspathDescriptor;
import org.eclipse.m2e.jdt.IClasspathEntryDescriptor;
/**
* This class is an attempt to encapsulate list of IClasspathEntry's and operations on the list such as "removeEntry",
* "addSourceEntry" and "addEntryAttribute". The idea is to provide JavaProjectConfigurator's classpath whiteboard they
* can use to incrementally define classpath in a consistent manner.
*
* @author igor
*/
public class ClasspathDescriptor implements IClasspathDescriptor {
private final ArrayList<IClasspathEntryDescriptor> entries = new ArrayList<IClasspathEntryDescriptor>();
private final Map<IPath, IClasspathEntryDescriptor> staleEntries = new LinkedHashMap<IPath, IClasspathEntryDescriptor>();
private final boolean uniquePaths;
public ClasspathDescriptor(boolean uniquePaths) {
this.uniquePaths = uniquePaths;
}
public ClasspathDescriptor(IJavaProject javaProject) throws JavaModelException {
this(true);
for(IClasspathEntry cpe : javaProject.getRawClasspath()) {
if(!javaProject.getProject().getFullPath().equals(cpe.getPath())) {
ClasspathEntryDescriptor entry = new ClasspathEntryDescriptor(cpe);
entries.add(entry);
staleEntries.put(entry.getPath(), entry);
}
}
}
/**
* @return true if classpath contains entry with specified path, false otherwise.
*/
public boolean containsPath(IPath path) {
for(IClasspathEntryDescriptor descriptor : entries) {
if(path.equals(descriptor.getPath())) {
return true;
}
}
return false;
}
public ClasspathEntryDescriptor addSourceEntry(IPath sourcePath, IPath outputLocation, boolean generated) {
return addSourceEntry(sourcePath, //
outputLocation, //
new IPath[0] /* inclusion */, //
new IPath[0] /* exclusion */, //
generated);
}
public List<IClasspathEntryDescriptor> removeEntry(final IPath path) {
return removeEntry(new EntryFilter() {
public boolean accept(IClasspathEntryDescriptor descriptor) {
return path.equals(descriptor.getPath());
}
});
}
public List<IClasspathEntryDescriptor> removeEntry(EntryFilter filter) {
ArrayList<IClasspathEntryDescriptor> result = new ArrayList<IClasspathEntryDescriptor>();
Iterator<IClasspathEntryDescriptor> iter = entries.iterator();
while(iter.hasNext()) {
IClasspathEntryDescriptor descriptor = iter.next();
if(filter.accept(descriptor)) {
staleEntries.remove(descriptor.getPath());
result.add(descriptor);
iter.remove();
}
}
return result;
}
public ClasspathEntryDescriptor addSourceEntry(IPath sourcePath, IPath outputLocation, IPath[] inclusion,
IPath[] exclusion, boolean generated) {
// IWorkspaceRoot workspaceRoot = project.getProject().getWorkspace().getRoot();
//
// Util.createFolder(workspaceRoot.getFolder(sourcePath), generated);
ClasspathEntryDescriptor descriptor = new ClasspathEntryDescriptor(IClasspathEntry.CPE_SOURCE, sourcePath);
descriptor.setOutputLocation(outputLocation);
descriptor.setInclusionPatterns(inclusion);
descriptor.setExclusionPatterns(exclusion);
//Bug 388541: preserve existing classpath attributes
IClasspathEntryDescriptor oldEntry = staleEntries.get(sourcePath);
if(oldEntry != null) {
for(Entry<String, String> entry : oldEntry.getClasspathAttributes().entrySet()) {
descriptor.setClasspathAttribute(entry.getKey(), entry.getValue());
}
}
if(generated) {
descriptor.setClasspathAttribute(IClasspathAttribute.OPTIONAL, "true"); //$NON-NLS-1$
}
addEntryDescriptor(descriptor);
return descriptor;
}
public IClasspathEntry[] getEntries() {
List<IClasspathEntry> result = new ArrayList<IClasspathEntry>();
for(IClasspathEntryDescriptor entry : entries) {
if(!entry.isPomDerived() || !staleEntries.containsKey(entry.getPath())) {
result.add(entry.toClasspathEntry());
}
}
return result.toArray(new IClasspathEntry[result.size()]);
}
public List<IClasspathEntryDescriptor> getEntryDescriptors() {
return entries;
}
public ClasspathEntryDescriptor addEntry(IClasspathEntry cpe) {
ClasspathEntryDescriptor entry = new ClasspathEntryDescriptor(cpe);
addEntryDescriptor(entry);
return entry;
}
public IClasspathEntryDescriptor replaceEntry(EntryFilter filter, IClasspathEntry cpe) {
ListIterator<IClasspathEntryDescriptor> iter = entries.listIterator();
while(iter.hasNext()) {
IClasspathEntryDescriptor descriptor = iter.next();
if(filter.accept(descriptor)) {
staleEntries.remove(descriptor.getPath());
ClasspathEntryDescriptor entry = new ClasspathEntryDescriptor(cpe);
entry.setPomDerived(true);
iter.set(entry);
return entry;
}
}
return null;
}
@SuppressWarnings("deprecation")
public ClasspathEntryDescriptor addProjectEntry(Artifact a, IMavenProjectFacade projectFacade) {
ClasspathEntryDescriptor entry = addProjectEntry(projectFacade.getFullPath());
entry.setArtifactKey(new ArtifactKey(a.getGroupId(), a.getArtifactId(), a.getBaseVersion(), a.getClassifier()));
entry.setScope(a.getScope());
entry.setOptionalDependency(a.isOptional());
return entry;
}
public ClasspathEntryDescriptor addProjectEntry(IPath entryPath) {
ClasspathEntryDescriptor entry = new ClasspathEntryDescriptor(IClasspathEntry.CPE_PROJECT, entryPath);
addEntryDescriptor(entry);
return entry;
}
@SuppressWarnings("deprecation")
public ClasspathEntryDescriptor addLibraryEntry(Artifact artifact, IPath srcPath, IPath srcRoot, String javaDocUrl) {
ArtifactKey artifactKey = new ArtifactKey(artifact);
IPath entryPath = new Path(artifact.getFile().getAbsolutePath());
ClasspathEntryDescriptor entry = addLibraryEntry(entryPath);
entry.setArtifactKey(artifactKey);
if(javaDocUrl != null) {
entry.setClasspathAttribute(IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME, javaDocUrl);
}
return entry;
}
public ClasspathEntryDescriptor addLibraryEntry(IPath entryPath) {
ClasspathEntryDescriptor entry = new ClasspathEntryDescriptor(IClasspathEntry.CPE_LIBRARY, entryPath);
addEntryDescriptor(entry);
return entry;
}
private void addEntryDescriptor(ClasspathEntryDescriptor descriptor) {
staleEntries.remove(descriptor.getPath());
descriptor.setPomDerived(true);
ListIterator<IClasspathEntryDescriptor> iter = entries.listIterator();
if(uniquePaths) {
while(iter.hasNext()) {
if(iter.next().getPath().equals(descriptor.getPath())) {
iter.set(descriptor);
return; // PAY ATTENTION to this early return. Ain't pretty, but works.
}
}
}
entries.add(descriptor);
}
}