org.bluestemsoftware.open.eoa.plugin.eclipse.ClasspathWriter Maven / Gradle / Ivy
/**
* Copyright 2008 Bluestem Software LLC. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
package org.bluestemsoftware.open.eoa.plugin.eclipse;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.eclipse.EclipseSourceDir;
import org.apache.maven.plugin.eclipse.Messages;
import org.apache.maven.plugin.ide.IdeDependency;
import org.apache.maven.plugin.ide.IdeUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
import org.codehaus.plexus.util.xml.XMLWriter;
/*
* Adapted from org.apache.maven.plugin.eclipse.writers.EclipseClasspathWriter which was
* released under the following license: Copyright 2001-2005 The Apache Software
* Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
@SuppressWarnings("unchecked")
public class ClasspathWriter extends org.apache.maven.plugin.eclipse.writers.AbstractEclipseWriter {
/**
* Eclipse build path variable M2_REPO
*/
private static final String M2_REPO = "M2_REPO"; //$NON-NLS-1$
/**
* Attribute for sourcepath.
*/
private static final String ATTR_SOURCEPATH = "sourcepath"; //$NON-NLS-1$
/**
* Attribute for output.
*/
private static final String ATTR_OUTPUT = "output"; //$NON-NLS-1$
/**
* Attribute for path.
*/
private static final String ATTR_PATH = "path"; //$NON-NLS-1$
/**
* Attribute for kind - Container (con), Variable (var)..etc.
*/
private static final String ATTR_KIND = "kind"; //$NON-NLS-1$
/**
* Attribute value for kind: var
*/
private static final String ATTR_VAR = "var"; //$NON-NLS-1$
/**
* Attribute value for kind: lib
*/
private static final String ATTR_LIB = "lib"; //$NON-NLS-1$
/**
* Attribute value for kind: src
*/
private static final String ATTR_SRC = "src"; //$NON-NLS-1$
/**
* Attribute name for source file includes in a path.
*/
private static final String ATTR_INCLUDING = "including";
/**
* Attribute name for source file excludes in a path.
*/
private static final String ATTR_EXCLUDING = "excluding";
/**
* Element for classpathentry.
*/
private static final String ELT_CLASSPATHENTRY = "classpathentry"; //$NON-NLS-1$
/**
* Element for classpath.
*/
private static final String ELT_CLASSPATH = "classpath"; //$NON-NLS-1$
/**
* File name that stores project classpath settings.
*/
private static final String FILE_DOT_CLASSPATH = ".classpath"; //$NON-NLS-1$
/**
* @see org.apache.maven.plugin.eclipse.writers.EclipseWriter#write()
*/
public void write() throws MojoExecutionException {
FileWriter w;
try {
w = new FileWriter(new File(config.getEclipseProjectDirectory(), FILE_DOT_CLASSPATH));
} catch (IOException ex) {
throw new MojoExecutionException(Messages.getString("EclipsePlugin.erroropeningfile"), ex); //$NON-NLS-1$
}
XMLWriter writer = new PrettyPrintXMLWriter(w);
writer.startElement(ELT_CLASSPATH);
String defaultOutput = IdeUtils.toRelativeAndFixSeparator(config.getProjectBaseDir(), config
.getBuildOutputDirectory(), false);
// ----------------------------------------------------------------------
// Source roots and resources
// ----------------------------------------------------------------------
// List
List specialSources = new ArrayList();
// Map>
Map byOutputDir = new HashMap();
for (int j = 0; j < config.getSourceDirs().length; j++) {
EclipseSourceDir dir = config.getSourceDirs()[j];
// List
List byOutputDirs = (List)byOutputDir.get(dir.getOutput());
if (byOutputDirs == null) {
// ArrayList
byOutputDir.put(dir.getOutput() == null ? defaultOutput : dir.getOutput(),
byOutputDirs = new ArrayList());
}
byOutputDirs.add(dir);
}
for (int j = 0; j < config.getSourceDirs().length; j++) {
EclipseSourceDir dir = config.getSourceDirs()[j];
log.debug("Processing "
+ (dir.isResource() ? "re" : "")
+ "source "
+ dir.getPath()
+ ": output="
+ dir.getOutput()
+ "; default output="
+ defaultOutput);
boolean isSpecial = false;
// handle resource with nested output folders
if (dir.isResource()) {
// Check if the output is a subdirectory of the default output,
// and if the default output has any sources that copy there.
if (dir.getOutput() != null // resource output dir is set
&& !dir.getOutput().equals(defaultOutput) // output dir is not
// default target/classes
&& dir.getOutput().startsWith(defaultOutput) // ... but is nested
&& byOutputDir.get(defaultOutput) != null // ???
&& !((List)byOutputDir.get(defaultOutput)).isEmpty() // ???
) {
// do not specify as source since the output will be nested. Instead, mark
// it as a todo, and handle it with a custom build.xml file later.
log.debug("Marking as special to prevent output folder nesting: "
+ dir.getPath()
+ " (output="
+ dir.getOutput()
+ ")");
isSpecial = true;
specialSources.add(dir);
}
}
writer.startElement(ELT_CLASSPATHENTRY);
writer.addAttribute(ATTR_KIND, "src"); //$NON-NLS-1$
writer.addAttribute(ATTR_PATH, dir.getPath());
if (!isSpecial && dir.getOutput() != null && !defaultOutput.equals(dir.getOutput())) {
writer.addAttribute(ATTR_OUTPUT, dir.getOutput());
}
if (StringUtils.isNotEmpty(dir.getInclude())) {
writer.addAttribute(ATTR_INCLUDING, dir.getInclude());
}
String excludes = dir.getExclude();
if (dir.isResource()) {
// automatically exclude java files: eclipse doesn't have the concept of
// resource directory so it will
// try to compile any java file found in maven resource dirs
excludes = StringUtils.isEmpty(excludes) ? "**/*.java" : excludes + "|**/*.java";
}
if (StringUtils.isNotEmpty(excludes)) {
writer.addAttribute(ATTR_EXCLUDING, excludes);
}
writer.endElement();
}
// ----------------------------------------------------------------------
// The default output
// ----------------------------------------------------------------------
writer.startElement(ELT_CLASSPATHENTRY);
writer.addAttribute(ATTR_KIND, ATTR_OUTPUT);
writer.addAttribute(ATTR_PATH, defaultOutput);
writer.endElement();
// ----------------------------------------------------------------------
// Container classpath entries
// ----------------------------------------------------------------------
for (Iterator it = config.getClasspathContainers().iterator(); it.hasNext();) {
writer.startElement(ELT_CLASSPATHENTRY);
writer.addAttribute(ATTR_KIND, "con"); //$NON-NLS-1$
writer.addAttribute(ATTR_PATH, (String)it.next());
writer.endElement(); // name
}
// ----------------------------------------------------------------------
// The dependencies
// ----------------------------------------------------------------------
Set addedDependencies = new HashSet();
for (int j = 0; j < config.getDeps().length; j++) {
IdeDependency dep = config.getDeps()[j];
if (dep.isAddedToClasspath()) {
String depId = dep.getGroupId()
+ ":"
+ dep.getArtifactId()
+ ":"
+ dep.getClassifier()
+ ":"
+ dep.getVersion();
/*
* avoid duplicates in the classpath for artifacts with different types (like
* ejbs)
*/
if (!addedDependencies.contains(depId)) {
addDependency(writer, dep);
addedDependencies.add(depId);
}
}
}
writer.endElement();
IOUtil.close(w);
}
private void addDependency(XMLWriter writer, IdeDependency dep) throws MojoExecutionException {
String path;
String kind;
String sourcepath = null;
String javadocpath = null;
if (dep.isReferencedProject() && !config.isPde()) {
path = "/" + IdeUtils.getProjectName(config.getProjectNameTemplate(), dep); //$NON-NLS-1$
kind = ATTR_SRC;
} else if (dep.isReferencedProject() && config.isPde()) {
// don't do anything, referenced projects are automatically handled by eclipse in
// PDE builds
return;
} else {
File artifactPath = dep.getFile();
if (artifactPath == null) {
log.error(Messages.getString("EclipsePlugin.artifactpathisnull", dep.getId())); //$NON-NLS-1$
return;
}
if (dep.isSystemScoped()) {
path = IdeUtils
.toRelativeAndFixSeparator(config.getEclipseProjectDirectory(), artifactPath, false);
if (log.isDebugEnabled()) {
log.debug(Messages.getString("EclipsePlugin.artifactissystemscoped", //$NON-NLS-1$
new Object[] { dep.getArtifactId(), path }));
}
kind = ATTR_LIB;
if (dep.getSourceAttachment() != null) {
sourcepath = dep.getSourceAttachment().getAbsolutePath();
}
if (dep.getJavadocAttachment() != null) {
javadocpath = dep.getJavadocAttachment().getAbsolutePath();
}
} else {
File localRepositoryFile = new File(config.getLocalRepository().getBasedir());
// if the dependency is not provided and the plugin runs in "pde mode", the
// dependency is
// added to the Bundle-Classpath:
if (config.isPde() && (dep.isProvided() || dep.isOsgiBundle())) {
return;
} else if (config.isPde() && !dep.isProvided() && !dep.isTestDependency()) {
// path for link created in .project, not to the actual file
path = dep.getFile().getName();
kind = ATTR_LIB;
}
// running in PDE mode and the dependency is provided means, that it is
// provided by
// the target platform. This case is covered by adding the plugin container
else {
String fullPath = artifactPath.getPath();
path = M2_REPO + "/" //$NON-NLS-1$
+ IdeUtils.toRelativeAndFixSeparator(localRepositoryFile, new File(fullPath), false);
kind = ATTR_VAR; //$NON-NLS-1$
}
if (dep.getSourceAttachment() != null) {
if (ATTR_VAR.equals(kind)) {
sourcepath = M2_REPO + "/" //$NON-NLS-1$
+ IdeUtils.toRelativeAndFixSeparator(localRepositoryFile, dep
.getSourceAttachment(), false);
} else {
// source archive must be referenced with the full path, we can't mix a
// lib with a variable
sourcepath = IdeUtils.getCanonicalPath(dep.getSourceAttachment());
}
}
if (dep.getJavadocAttachment() != null) {
// NB eclipse (3.1) doesn't support variables in javadoc paths, so we need
// to add the
// full path for the maven repo
javadocpath = StringUtils.replace(IdeUtils.getCanonicalPath(dep.getJavadocAttachment()),
"\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
writer.startElement(ELT_CLASSPATHENTRY);
writer.addAttribute(ATTR_KIND, kind);
writer.addAttribute(ATTR_PATH, path);
if (sourcepath != null) {
writer.addAttribute(ATTR_SOURCEPATH, sourcepath);
}
if (javadocpath != null) {
writer.startElement("attributes"); //$NON-NLS-1$
writer.startElement("attribute"); //$NON-NLS-1$
writer.addAttribute("value", "jar:file:/" + javadocpath + "!/"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
writer.addAttribute("name", "javadoc_location"); //$NON-NLS-1$ //$NON-NLS-2$
writer.endElement();
writer.endElement();
}
writer.endElement();
}
}