/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package com.alibaba.citrus.maven.eclipse.base.eclipse.writers;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import com.alibaba.citrus.maven.eclipse.base.eclipse.BuildCommand;
import com.alibaba.citrus.maven.eclipse.base.eclipse.LinkedResource;
import com.alibaba.citrus.maven.eclipse.base.eclipse.Messages;
import com.alibaba.citrus.maven.eclipse.base.ide.IdeDependency;
import com.alibaba.citrus.maven.eclipse.base.ide.IdeUtils;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
import org.codehaus.plexus.util.xml.XMLWriter;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* Writes eclipse .project file.
*
* @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a>
* @author <a href="mailto:kenney@neonics.com">Kenney Westerhof</a>
* @author <a href="mailto:fgiust@apache.org">Fabrizio Giustina</a>
* @version $Id: EclipseProjectWriter.java 1185446 2011-10-18 01:00:41Z baerrach $
*/
public class EclipseProjectWriter extends AbstractEclipseWriter {
private static final String ELT_NAME = "name"; //$NON-NLS-1$
private static final String ELT_COMMENT = "comment"; //$NON-NLS-1$
private static final String ELT_BUILD_COMMAND = "buildCommand"; //$NON-NLS-1$
private static final String ELT_LINK = "link"; //$NON-NLS-1$
private static final String ELT_BUILD_SPEC = "buildSpec"; //$NON-NLS-1$
private static final String ELT_LINKED_RESOURCES = "linkedResources"; //$NON-NLS-1$
private static final String ELT_NATURE = "nature"; //$NON-NLS-1$
private static final String ELT_NATURES = "natures"; //$NON-NLS-1$
private static final String FILE_DOT_PROJECT = ".project"; //$NON-NLS-1$
/** Constant for links to files. */
private static final int LINK_TYPE_FILE = 1;
/** Constant for links to directories. */
private static final int LINK_TYPE_DIRECTORY = 2;
/** To Store the link names */
ArrayList linkNames = new ArrayList();
/** @see com.alibaba.citrus.maven.eclipse.base.eclipse.writers.EclipseWriter#write() */
public void write()
throws MojoExecutionException {
Set projectnatures = new LinkedHashSet();
Set buildCommands = new LinkedHashSet();
Set linkedResources = new LinkedHashSet();
File dotProject = new File(config.getEclipseProjectDirectory(), FILE_DOT_PROJECT);
if (dotProject.exists()) {
log.info(Messages.getString("EclipsePlugin.keepexisting", dotProject.getAbsolutePath())); //$NON-NLS-1$
// parse existing file in order to keep manually-added entries
Reader reader = null;
try {
reader = new InputStreamReader(new FileInputStream(dotProject), "UTF-8");
Xpp3Dom dom = Xpp3DomBuilder.build(reader);
Xpp3Dom naturesElement = dom.getChild(ELT_NATURES);
if (naturesElement != null) {
Xpp3Dom[] existingNatures = naturesElement.getChildren(ELT_NATURE);
for (int j = 0; j < existingNatures.length; j++) {
// adds all the existing natures
projectnatures.add(existingNatures[j].getValue());
}
}
Xpp3Dom buildSpec = dom.getChild(ELT_BUILD_SPEC);
if (buildSpec != null) {
Xpp3Dom[] existingBuildCommands = buildSpec.getChildren(ELT_BUILD_COMMAND);
for (int j = 0; j < existingBuildCommands.length; j++) {
Xpp3Dom buildCommandName = existingBuildCommands[j].getChild(ELT_NAME);
if (buildCommandName != null) {
buildCommands.add(new BuildCommand(existingBuildCommands[j]));
}
}
}
// Added the below code to preserve the Symbolic links
Xpp3Dom linkedResourcesElement = dom.getChild(ELT_LINKED_RESOURCES);
if (linkedResourcesElement != null) {
Xpp3Dom[] existingLinks = linkedResourcesElement.getChildren(ELT_LINK);
for (int j = 0; j < existingLinks.length; j++) {
Xpp3Dom linkName = existingLinks[j].getChild(ELT_NAME);
if (linkName != null) {
// add all the existing symbolic links
linkNames.add(existingLinks[j].getChild(ELT_NAME).getValue());
linkedResources.add(new LinkedResource(existingLinks[j]));
}
}
}
} catch (XmlPullParserException e) {
log.warn(Messages.getString("EclipsePlugin.cantparseexisting",
dotProject.getAbsolutePath())); //$NON-NLS-1$
} catch (IOException e) {
log.warn(Messages.getString("EclipsePlugin.cantparseexisting",
dotProject.getAbsolutePath())); //$NON-NLS-1$
} finally {
IOUtil.close(reader);
}
}
// adds new entries after the existing ones
for (Iterator iter = config.getProjectnatures().iterator(); iter.hasNext(); ) {
projectnatures.add(iter.next());
}
for (Iterator iter = config.getBuildCommands().iterator(); iter.hasNext(); ) {
buildCommands.add((BuildCommand) iter.next());
}
for (Iterator iter = config.getLinkedResources().iterator(); iter.hasNext(); ) {
linkedResources.add((LinkedResource) iter.next());
}
Writer w;
try {
w = new OutputStreamWriter(new FileOutputStream(dotProject), "UTF-8");
} catch (IOException ex) {
throw new MojoExecutionException(Messages.getString("EclipsePlugin.erroropeningfile"), ex); //$NON-NLS-1$
}
XMLWriter writer = new PrettyPrintXMLWriter(w, "UTF-8", null);
writer.startElement("projectDescription"); //$NON-NLS-1$
writer.startElement(ELT_NAME);
writer.writeText(config.getEclipseProjectName());
writer.endElement();
addComment(writer, config.getProject().getDescription());
writer.startElement("projects"); //$NON-NLS-1$
IdeDependency[] dependencies = config.getDeps();
// referenced projects should not be added for plugins
if (!config.isPde()) {
List duplicates = new ArrayList();
for (int j = 0; j < dependencies.length; j++) {
IdeDependency dep = dependencies[j];
// Avoid duplicates entries when same project is refered using multiple types
// (ejb, test-jar ...)
if (dep.isReferencedProject() && !duplicates.contains(dep.getEclipseProjectName())) {
writer.startElement("project"); //$NON-NLS-1$
writer.writeText(dep.getEclipseProjectName());
writer.endElement();
duplicates.add(dep.getEclipseProjectName());
}
}
}
writer.endElement(); // projects
writer.startElement(ELT_BUILD_SPEC);
for (Iterator it = buildCommands.iterator(); it.hasNext(); ) {
((BuildCommand) it.next()).print(writer);
}
writer.endElement(); // buildSpec
writer.startElement(ELT_NATURES);
for (Iterator it = projectnatures.iterator(); it.hasNext(); ) {
writer.startElement(ELT_NATURE);
writer.writeText((String) it.next());
writer.endElement(); // name
}
writer.endElement(); // natures
boolean addLinks = !config.getProjectBaseDir().equals(config.getEclipseProjectDirectory());
if (addLinks || (config.isPde() && dependencies.length > 0) || linkedResources.size() > 0) {
writer.startElement("linkedResources"); //$NON-NLS-1$
// preserve the symbolic links
if (linkedResources.size() > 0) {
for (Iterator it = linkedResources.iterator(); it.hasNext(); ) {
((LinkedResource) it.next()).print(writer);
}
}
if (addLinks) {
addFileLink(writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
config.getProject().getFile());
addSourceLinks(writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
config.getProject().getCompileSourceRoots());
addResourceLinks(writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
config.getProject().getBuild().getResources());
addSourceLinks(writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
config.getProject().getTestCompileSourceRoots());
addResourceLinks(writer, config.getProjectBaseDir(), config.getEclipseProjectDirectory(),
config.getProject().getBuild().getTestResources());
}
writeResourceLinksForPdeProject(writer, dependencies);
writer.endElement(); // linkedResources
}
writer.endElement(); // projectDescription
IOUtil.close(w);
}
protected void writeResourceLinksForPdeProject(XMLWriter writer, IdeDependency[] dependencies)
throws MojoExecutionException {
if (config.isPde()) {
for (int j = 0; j < dependencies.length; j++) {
IdeDependency dep = dependencies[j];
if (dep.isAddedToClasspath() && !dep.isProvided() && !dep.isReferencedProject()
&& !dep.isTestDependency() && !dep.isOsgiBundle()) {
String name = dep.getFile().getName();
addLink(writer, name, IdeUtils.fixSeparator(IdeUtils.getCanonicalPath(dep.getFile())),
LINK_TYPE_FILE);
}
}
}
}
private void addFileLink(XMLWriter writer, File projectBaseDir, File basedir, File file)
throws MojoExecutionException {
if (file.isFile()) {
String name = IdeUtils.toRelativeAndFixSeparator(projectBaseDir, file, true);
String location = IdeUtils.fixSeparator(IdeUtils.getCanonicalPath(file));
addLink(writer, name, location, LINK_TYPE_FILE);
} else {
log.warn(Messages.getString("EclipseProjectWriter.notafile", file)); //$NON-NLS-1$
}
}
private void addSourceLinks(XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots)
throws MojoExecutionException {
for (Iterator it = sourceRoots.iterator(); it.hasNext(); ) {
String sourceRootString = (String) it.next();
File sourceRoot = new File(sourceRootString);
if (sourceRoot.isDirectory()) {
String name = IdeUtils.toRelativeAndFixSeparator(projectBaseDir, sourceRoot, true);
String location = IdeUtils.fixSeparator(IdeUtils.getCanonicalPath(sourceRoot));
addLink(writer, name, location, LINK_TYPE_DIRECTORY);
}
}
}
private void addResourceLinks(XMLWriter writer, File projectBaseDir, File basedir, List sourceRoots)
throws MojoExecutionException {
for (Iterator it = sourceRoots.iterator(); it.hasNext(); ) {
String resourceDirString = ((Resource) it.next()).getDirectory();
File resourceDir = new File(resourceDirString);
if (resourceDir.isDirectory()) {
String name = IdeUtils.toRelativeAndFixSeparator(projectBaseDir, resourceDir, true);
String location = IdeUtils.fixSeparator(IdeUtils.getCanonicalPath(resourceDir));
addLink(writer, name, location, LINK_TYPE_DIRECTORY);
}
}
}
/**
* @param writer
* @param name
* @param location
*/
private void addLink(XMLWriter writer, String name, String location, int type) {
// Avoid duplicates entries of the link..
if (!linkNames.contains(name)) {
writer.startElement("link"); //$NON-NLS-1$
writer.startElement(ELT_NAME);
writer.writeText(name);
writer.endElement(); // name
writer.startElement("type"); //$NON-NLS-1$
writer.writeText(Integer.toString(type));
writer.endElement(); // type
writer.startElement("location"); //$NON-NLS-1$
writer.writeText(location);
writer.endElement(); // location
writer.endElement(); // link
}
}
private void addComment(XMLWriter writer, String projectDescription) {
String comment = "";
if (projectDescription != null) {
comment = projectDescription.trim();
if (comment.length() > 0) {
if (!comment.endsWith(".")) {
comment += ".";
}
comment += " ";
}
}
//
// Project files that are generated with m-p-e cannot be supported by M2Eclipse
//
comment += "NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse.";
writer.startElement(ELT_COMMENT);
writer.writeText(comment);
writer.endElement();
}
}