/* * 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 org.apache.maven.plugin.eclipse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.ArtifactHandler; import org.apache.maven.model.Plugin; import org.apache.maven.model.Resource; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.eclipse.reader.ReadWorkspaceLocations; import org.apache.maven.plugin.eclipse.writers.EclipseAjdtWriter; import org.apache.maven.plugin.eclipse.writers.EclipseClasspathWriter; import org.apache.maven.plugin.eclipse.writers.EclipseManifestWriter; import org.apache.maven.plugin.eclipse.writers.EclipseOSGiManifestWriter; import org.apache.maven.plugin.eclipse.writers.EclipseProjectWriter; import org.apache.maven.plugin.eclipse.writers.EclipseSettingsWriter; import org.apache.maven.plugin.eclipse.writers.EclipseWriterConfig; import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpApplicationXMLWriter; import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpComponent15Writer; import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpComponentWriter; import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpFacetsWriter; import org.apache.maven.plugin.eclipse.writers.wtp.EclipseWtpmodulesWriter; import org.apache.maven.plugin.ide.AbstractIdeSupportMojo; import org.apache.maven.plugin.ide.IdeDependency; import org.apache.maven.plugin.ide.IdeUtils; import org.apache.maven.plugin.ide.JeeUtils; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.resource.ResourceManager; import org.codehaus.plexus.resource.loader.FileResourceLoader; import org.codehaus.plexus.resource.loader.ResourceNotFoundException; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Generates the following eclipse configuration files: *
.project and .classpath files.setting/org.eclipse.jdt.core.prefs with project specific compiler settingswtpversion is set to a
* valid version (WTP configuration is not generated by default)useProjectReferences is set to false).
*
* @author Trygve Laugstøl
* @author Fabrizio Giustina
* @version $Id: EclipsePlugin.java 641616 2008-03-26 22:42:42Z aheritier $
* @goal eclipse
* @execute phase="generate-resources"
*/
public class EclipsePlugin
extends AbstractIdeSupportMojo
{
private static final String WEAVE_DEPENDENCY = "weaveDependency";
private static final String WEAVE_DEPENDENCIES = "weaveDependencies";
private static final String ASPECT_LIBRARY = "aspectLibrary";
private static final String ASPECT_LIBRARIES = "aspectLibraries";
private static final String ASPECT_DIRECTORY = "aspectDirectory";
private static final String TEST_ASPECT_DIRECTORY = "testAspectDirectory";
private static final String ASPECTJ_MAVEN_PLUGIN = "aspectj-maven-plugin";
private static final String ORG_CODEHAUS_MOJO = "org.codehaus.mojo";
private static final String DEFAULT_TEST_ASPECT_DIRECTORY = "src/test/aspect";
private static final String DEFAULT_ASPECT_DIRECTORY = "src/main/aspect";
private static final String NATURE_WST_FACET_CORE_NATURE = "org.eclipse.wst.common.project.facet.core.nature"; //$NON-NLS-1$
private static final String BUILDER_WST_COMPONENT_STRUCTURAL_DEPENDENCY_RESOLVER =
"org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver"; //$NON-NLS-1$
protected static final String BUILDER_WST_VALIDATION = "org.eclipse.wst.validation.validationbuilder"; //$NON-NLS-1$
private static final String BUILDER_JDT_CORE_JAVA = "org.eclipse.jdt.core.javabuilder"; //$NON-NLS-1$
private static final String BUILDER_WST_COMPONENT_STRUCTURAL =
"org.eclipse.wst.common.modulecore.ComponentStructuralBuilder"; //$NON-NLS-1$
private static final String BUILDER_WST_FACET = "org.eclipse.wst.common.project.facet.core.builder"; //$NON-NLS-1$
private static final String BUILDER_PDE_MANIFEST = "org.eclipse.pde.ManifestBuilder"; //$NON-NLS-1$
private static final String BUILDER_PDE_SCHEMA = "org.eclipse.pde.SchemaBuilder"; //$NON-NLS-1$
private static final String BUILDER_AJDT_CORE_JAVA = "org.eclipse.ajdt.core.ajbuilder"; //$NON-NLS-1$
private static final String NATURE_WST_MODULE_CORE_NATURE = "org.eclipse.wst.common.modulecore.ModuleCoreNature"; //$NON-NLS-1$
private static final String NATURE_JDT_CORE_JAVA = "org.eclipse.jdt.core.javanature"; //$NON-NLS-1$
private static final String NATURE_JEM_WORKBENCH_JAVA_EMF = "org.eclipse.jem.workbench.JavaEMFNature"; //$NON-NLS-1$
private static final String NATURE_PDE_PLUGIN = "org.eclipse.pde.PluginNature"; //$NON-NLS-1$
private static final String NATURE_AJDT_CORE_JAVA = "org.eclipse.ajdt.ui.ajnature"; //$NON-NLS-1$
protected static final String COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER = "org.eclipse.jdt.launching.JRE_CONTAINER"; //$NON-NLS-1$
protected static final String ASPECTJ_RT_CONTAINER = "org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"; //$NON-NLS-1$
protected static final String REQUIRED_PLUGINS_CONTAINER = "org.eclipse.pde.core.requiredPlugins"; //$NON-NLS-1$
// warning, order is important for binary search
public static final String[] WTP_SUPPORTED_VERSIONS = new String[] { "1.0", "1.5", "2.0", "R7", "none" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
/**
* Constant for 'artifactId' element in POM.xml.
*/
private static final String POM_ELT_ARTIFACT_ID = "artifactId"; //$NON-NLS-1$
/**
* Constant for 'groupId' element in POM.xml.
*/
private static final String POM_ELT_GROUP_ID = "groupId"; //$NON-NLS-1$
/**
* List of eclipse project natures. By default the org.eclipse.jdt.core.javanature nature plus the
* needed WTP natures are added. Natures added using this property replace the default list.
*
*
* <projectnatures>
* <projectnature>org.eclipse.jdt.core.javanature</projectnature>
* <projectnature>org.eclipse.wst.common.modulecore.ModuleCoreNature</projectnature>
* </projectnatures>
*
*
* @parameter
*/
private List projectnatures;
/**
* List of artifact to exclude from eclipse classpath, beeing provided by some eclipse classPathContainer
* [MECLIPSE-79]
*
* @since 2.5
* @parameter
*/
private List excludes;
/**
* List of eclipse project natures to be added to the default ones.
*
*
* <additionalProjectnatures>
* <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
* </additionalProjectnatures>
*
*
* @parameter
*/
private List additionalProjectnatures;
/**
* List of eclipse project facets to be added to the default ones.
*
*
* <additionalProjectFacets>
* <jst.jsf>1.1<jst.jsf/>
* </additionalProjectFacets>
*
*
* @parameter
*/
private Map additionalProjectFacets;
/**
* List of eclipse build commands. By default the org.eclipse.jdt.core.javabuilder builder plus the
* needed WTP builders are added. If you specify any configuration for this parameter, only those buildcommands
* specified will be used; the defaults won't be added. Use the additionalBuildCommands parameter for
* that. Configuration example: Old style:
*
*
* <buildcommands>
* <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilder</buildcommand>
* <buildcommand>org.eclipse.jdt.core.javabuilder</buildcommand>
* <buildcommand>org.eclipse.wst.common.modulecore.ComponentStructuralBuilderDependencyResolver</buildcommand>
* </buildcommands>
*
*
* For new style, see additionalBuildCommands.
*
* @parameter
*/
private List buildcommands;
/**
* List of eclipse build commands to be added to the default ones. Old style:
*
*
* <additionalBuildcommands>
* <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
* </additionalBuildcommands>
*
*
* New style:
*
*
* <additionalBuildcommands>
* <buildCommand>
* <name>org.ui.externaltools.ExternalToolBuilder</name>
* <triggers>auto,full,incremental,</triggers>
* <arguments>
* <LaunchConfigHandle><project>./externalToolBuilders/MavenBuilder.launch</LaunchConfighandle>
* </arguments>
* </buildCommand>
* </additionalBuildcommands>
*
*
* Note the difference between buildcommand and
* buildCommand. You can mix and match old and new-style configuration entries.
*
* @parameter
*/
private List additionalBuildcommands;
/**
* List of container classpath entries. By default the org.eclipse.jdt.launching.JRE_CONTAINER
* classpath container is added. Configuration example:
*
*
* <classpathContainers>
* <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
* <classpathContainer>org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v5.5</classpathContainer>
* <classpathContainer>org.eclipse.jst.j2ee.internal.web.container/artifact</classpathContainer>
* </classpathContainers>
*
*
* @parameter
*/
private List classpathContainers;
/**
* Enables/disables the downloading of source attachments. Defaults to false. DEPRECATED - use downloadSources
*
* @parameter expression="${eclipse.downloadSources}"
* @deprecated use downloadSources
*/
private boolean eclipseDownloadSources;
/**
* Eclipse workspace directory.
*
* @parameter expression="${eclipse.projectDir}" alias="outputDir"
*/
private File eclipseProjectDir;
/**
* When set to false, the plugin will not create sub-projects and instead reference those sub-projects using the
* installed package in the local repository
*
* @parameter expression="${eclipse.useProjectReferences}" default-value="true"
* @required
*/
private boolean useProjectReferences;
/**
* The default output directory
*
* @parameter expression="${outputDirectory}" alias="outputDirectory"
* default-value="${project.build.outputDirectory}"
* @required
*/
private File buildOutputDirectory;
/**
* The version of WTP for which configuration files will be generated. The default value is "none" (don't generate
* WTP configuration), supported versions are "R7", "1.0", and "1.5"
*
* @parameter expression="${wtpversion}" default-value="none"
*/
private String wtpversion;
/**
* JEE context name of the WTP module. ( ex. WEB context name ).
*
* @parameter expression="${wtpContextName}"
*/
private String wtpContextName;
/**
* Is it an PDE project? If yes, the plugin adds the necessary natures and build commands to the .project file.
* Additionally it copies all libraries to a project local directory and references them instead of referencing the
* files in the local Maven repository. It also ensured that the "Bundle-Classpath" in META-INF/MANIFEST.MF is
* synchronized.
*
* @parameter expression="${eclipse.pde}" default-value="false"
*/
private boolean pde;
/**
* Is it an AJDT project? If yes, the plugin adds the necessary natures and build commands to
* the .project file.
*/
private boolean ajdt;
/**
* The relative path of the manifest file
*
* @parameter expression="${eclipse.manifest}" default-value="${basedir}/META-INF/MANIFEST.MF"
*/
private File manifest;
/**
* Allow to configure additional generic configuration files for eclipse that will be written out to disk when
* running eclipse:eclipse. FOr each file you can specify the name and the text content.
*
*
* <plugin>
* <groupId>org.apache.maven.plugins</groupId>
* <artifactId>maven-eclipse-plugin</artifactId>
* <configuration>
* <additionalConfig>
* <file>
* <name>.checkstyle</name>
* <content>
* <![CDATA[<fileset-config file-format-version="1.2.0" simple-config="true">
* <fileset name="all" enabled="true" check-config-name="acme corporate style" local="false">
* <file-match-pattern match-pattern="." include-pattern="true"/>
* </fileset>
* <filter name="NonSrcDirs" enabled="true"/>
* </fileset-config>]]>
* </content>
* </file>
* </additionalConfig>
* </configuration>
* </plugin>
*
*
* Instead of the content you can also define (from version 2.5) an url to download the file :
*
*
* <plugin>
* <groupId>org.apache.maven.plugins</groupId>
* <artifactId>maven-eclipse-plugin</artifactId>
* <configuration>
* <additionalConfig>
* <file>
* <name>.checkstyle</name>
* <url>http://some.place.org/path/to/file</url>
* </file>
* </additionalConfig>
* </configuration>
*
*
* or a location :
*
*
* <plugin>
* <groupId>org.apache.maven.plugins</groupId>
* <artifactId>maven-eclipse-plugin</artifactId>
* <configuration>
* <additionalConfig>
* <file>
* <name>.checkstyle</name>
* <location>/checkstyle-config.xml</location>
* </file>
* </additionalConfig>
* </configuration>
* <dependencies>
* <!-- The file defined in the location is stored in this dependency -->
* <dependency>
* <groupId>eclipsetest</groupId>
* <artifactId>checkstyle-config</artifactId>
* <version>1.0</version>
* </dependency>
* </dependencies>
* </plugin>
*
*
* @parameter
*/
private EclipseConfigFile[] additionalConfig;
/**
* If set to true, the version number of the artifact is appended to the name of the generated
* Eclipse project. See projectNameTemplate for other options.
*
* @parameter expression="${eclipse.addVersionToProjectName}" default-value="false"
*/
private boolean addVersionToProjectName;
/**
* If set to true, the groupId of the artifact is appended to the name of the generated Eclipse
* project. See projectNameTemplate for other options.
*
* @parameter expression="${eclipse.addGroupIdToProjectName}" default-value="false"
*/
private boolean addGroupIdToProjectName;
/**
* Allows configuring the name of the eclipse projects. This property if set wins over addVersionToProjectName and
* addGroupIdToProjectName You can use [groupId], [artifactId] and
* [version] variables. eg. [groupId].[artifactId]-[version]
*
* @parameter expression="${eclipse.projectNameTemplate}"
*/
private String projectNameTemplate;
/**
* Parsed wtp version.
*/
private float wtpVersionFloat;
/**
* Not a plugin parameter. Is this a java project?
*/
private boolean isJavaProject;
/**
* Must the manifest files be written for java projects so that that the jee classpath for wtp is correct.
*
* @parameter expression="${eclipse.wtpmanifest}" default-value="false"
*/
private boolean wtpmanifest;
/**
* Must the application files be written for ear projects in a separate directory.
*
* @parameter expression="${eclipse.wtpapplicationxml}" default-value="false"
*/
private boolean wtpapplicationxml;
/**
* What WTP defined server to use for deployment informations.
*
* @parameter expression="${eclipse.wtpdefaultserver}"
*/
private String wtpdefaultserver;
private WorkspaceConfiguration workspaceConfiguration;
/**
* ResourceManager for getting additonalConfig files from resources
*
* @component
* @required
* @readonly
*/
private ResourceManager locator;
/**
* This eclipse workspace is read and all artifacts detected there will be connected as eclipse projects and will
* not be linked to the jars in the local repository. Requirement is that it was created with the similar wtp
* settings as the reactor projects, but the project name template my differ. The pom's in the workspace projects
* may not contain variables in the artefactId, groupId and version tags.
*
* @since 2.5
* @parameter expression="${eclipse.workspace}"
*/
protected String workspace;
/**
* Limit the use of project references to the current workspace. No project references will be created to projects
* in the reactor when they are not available in the workspace.
*
* @parameter expression="${eclipse.limitProjectReferencesToWorkspace}" default-value="false"
*/
protected boolean limitProjectReferencesToWorkspace;
/**
* The version of AJDT for which configuration files will be generated. The default value is "1.5", supported versions
* are "none", "1.4", and "1.5".
*
* @parameter expression="${eclipse.ajdtVersion}" default-value="1.5"
*/
private String ajdtVersion;
protected boolean isJavaProject()
{
return isJavaProject;
}
protected boolean isPdeProject()
{
return pde;
}
/**
* Getter for buildcommands.
*
* @return Returns the buildcommands.
*/
public List getBuildcommands()
{
return buildcommands;
}
/**
* Setter for buildcommands.
*
* @param buildcommands The buildcommands to set.
*/
public void setBuildcommands( List buildcommands )
{
this.buildcommands = buildcommands;
}
/**
* Getter for buildOutputDirectory.
*
* @return Returns the buildOutputDirectory.
*/
public File getBuildOutputDirectory()
{
return buildOutputDirectory;
}
/**
* Setter for buildOutputDirectory.
*
* @param buildOutputDirectory The buildOutputDirectory to set.
*/
public void setBuildOutputDirectory( File buildOutputDirectory )
{
this.buildOutputDirectory = buildOutputDirectory;
}
/**
* Getter for classpathContainers.
*
* @return Returns the classpathContainers.
*/
public List getClasspathContainers()
{
return classpathContainers;
}
/**
* Setter for classpathContainers.
*
* @param classpathContainers The classpathContainers to set.
*/
public void setClasspathContainers( List classpathContainers )
{
this.classpathContainers = classpathContainers;
}
/**
* Getter for eclipseProjectDir.
*
* @return Returns the eclipseProjectDir.
*/
public File getEclipseProjectDir()
{
return eclipseProjectDir;
}
/**
* Setter for eclipseProjectDir.
*
* @param eclipseProjectDir The eclipseProjectDir to set.
*/
public void setEclipseProjectDir( File eclipseProjectDir )
{
this.eclipseProjectDir = eclipseProjectDir;
}
/**
* Getter for projectnatures.
*
* @return Returns the projectnatures.
*/
public List getProjectnatures()
{
return projectnatures;
}
/**
* Setter for projectnatures.
*
* @param projectnatures The projectnatures to set.
*/
public void setProjectnatures( List projectnatures )
{
this.projectnatures = projectnatures;
}
/**
* Getter for useProjectReferences.
*
* @return Returns the useProjectReferences.
*/
public boolean getUseProjectReferences()
{
return useProjectReferences;
}
/**
* Setter for useProjectReferences.
*
* @param useProjectReferences The useProjectReferences to set.
*/
public void setUseProjectReferences( boolean useProjectReferences )
{
this.useProjectReferences = useProjectReferences;
}
/**
* Getter for wtpversion.
*
* @return Returns the wtpversion.
*/
public String getWtpversion()
{
return wtpversion;
}
/**
* Setter for wtpversion.
*
* @param wtpversion The wtpversion to set.
*/
public void setWtpversion( String wtpversion )
{
this.wtpversion = wtpversion;
}
/**
* Getter for additionalBuildcommands.
*
* @return Returns the additionalBuildcommands.
*/
public List getAdditionalBuildcommands()
{
return additionalBuildcommands;
}
/**
* Setter for additionalBuildcommands.
*
* @param additionalBuildcommands The additionalBuildcommands to set.
*/
public void setAdditionalBuildcommands( List additionalBuildcommands )
{
this.additionalBuildcommands = additionalBuildcommands;
}
/**
* Getter for additionalProjectnatures.
*
* @return Returns the additionalProjectnatures.
*/
public List getAdditionalProjectnatures()
{
return additionalProjectnatures;
}
/**
* Setter for additionalProjectnatures.
*
* @param additionalProjectnatures The additionalProjectnatures to set.
*/
public void setAdditionalProjectnatures( List additionalProjectnatures )
{
this.additionalProjectnatures = additionalProjectnatures;
}
/**
* Getter for addVersionToProjectName.
*/
public boolean isAddVersionToProjectName()
{
return addVersionToProjectName;
}
/**
* Setter for addVersionToProjectName.
*/
public void setAddVersionToProjectName( boolean addVersionToProjectName )
{
this.addVersionToProjectName = addVersionToProjectName;
}
/**
* Getter for addGroupIdToProjectName.
*/
public boolean isAddGroupIdToProjectName()
{
return addGroupIdToProjectName;
}
/**
* Setter for addGroupIdToProjectName.
*/
public void setAddGroupIdToProjectName( boolean addGroupIdToProjectName )
{
this.addGroupIdToProjectName = addGroupIdToProjectName;
}
public String getProjectNameTemplate()
{
return projectNameTemplate;
}
public void setProjectNameTemplate( String projectNameTemplate )
{
this.projectNameTemplate = projectNameTemplate;
}
/**
* @see org.apache.maven.plugin.Mojo#execute()
*/
public boolean setup()
throws MojoExecutionException
{
boolean ready = true;
checkDeprecations();
ajdt = enableAjdt( executedProject ) && !ajdtVersion.equals( "none" );
ready = validate();
// TODO: Why are we using project in some places, and executedProject in others??
ArtifactHandler artifactHandler = project.getArtifact().getArtifactHandler();
// ear projects don't contain java sources
// pde projects are always java projects
isJavaProject =
pde ||
( Constants.LANGUAGE_JAVA.equals( artifactHandler.getLanguage() ) && !Constants.PROJECT_PACKAGING_EAR.equals( packaging ) );
setupExtras();
parseConfigurationOptions();
// defaults
if ( projectnatures == null )
{
fillDefaultNatures( packaging );
}
if ( additionalProjectnatures != null )
{
projectnatures.addAll( additionalProjectnatures );
}
if ( buildcommands == null )
{
fillDefaultBuilders( packaging );
}
else
{
convertBuildCommandList( buildcommands );
}
if ( additionalBuildcommands != null )
{
convertBuildCommandList( additionalBuildcommands );
buildcommands.addAll( additionalBuildcommands );
}
if ( classpathContainers == null )
{
fillDefaultClasspathContainers( packaging );
}
else
{
verifyClasspathContainerListIsComplete();
}
locator.addSearchPath( FileResourceLoader.ID, project.getFile().getParentFile().getAbsolutePath() );
locator.setOutputDirectory( new File( project.getBuild().getDirectory() ) );
// ready to start
return ready;
}
protected void convertBuildCommandList( List commands )
{
if ( commands != null )
{
for ( ListIterator i = commands.listIterator(); i.hasNext(); )
{
Object command = i.next();
if ( command instanceof String )
{
command = new BuildCommand( (String) command );
i.set( command );
}
}
}
}
private void parseConfigurationOptions()
{
if ( "R7".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
{
wtpVersionFloat = 0.7f;
}
else if ( "1.0".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
{
wtpVersionFloat = 1.0f;
}
else if ( "1.5".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
{
wtpVersionFloat = 1.5f;
}
else if ( "2.0".equalsIgnoreCase( wtpversion ) ) //$NON-NLS-1$
{
wtpVersionFloat = 2.0f;
}
if ( !"none".equalsIgnoreCase( wtpversion ) )
{
getLog().info( Messages.getString( "EclipsePlugin.wtpversion", wtpversion ) );
}
}
protected void setupExtras()
throws MojoExecutionException
{
// extension point.
}
protected void verifyClasspathContainerListIsComplete()
{
boolean containsJREContainer = false;
// Check if classpathContainer contains a JRE (default, alternate or
// Execution Environment)
for ( Iterator iter = classpathContainers.iterator(); iter.hasNext(); )
{
Object classPathContainer = iter.next();
if ( classPathContainer != null &&
classPathContainer.toString().startsWith( COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER ) )
{
containsJREContainer = true;
break;
}
}
if ( !containsJREContainer )
{
getLog().warn( Messages.getString( "EclipsePlugin.missingjrecontainer" ) ); //$NON-NLS-1$
classpathContainers.add( 0, COMMON_PATH_JDT_LAUNCHING_JRE_CONTAINER );
}
}
private boolean validate()
throws MojoExecutionException
{
// validate sanity of the current m2 project
if ( Arrays.binarySearch( WTP_SUPPORTED_VERSIONS, wtpversion ) < 0 )
{
throw new MojoExecutionException(
Messages.getString( "EclipsePlugin.unsupportedwtp", new Object[] { //$NON-NLS-1$
wtpversion,
StringUtils.join( WTP_SUPPORTED_VERSIONS, " " ) } ) ); //$NON-NLS-1$
}
assertNotEmpty( executedProject.getGroupId(), POM_ELT_GROUP_ID );
assertNotEmpty( executedProject.getArtifactId(), POM_ELT_ARTIFACT_ID );
if ( executedProject.getFile() == null || !executedProject.getFile().exists() )
{
throw new MojoExecutionException( Messages.getString( "EclipsePlugin.missingpom" ) ); //$NON-NLS-1$
}
if ( "pom".equals( packaging ) && eclipseProjectDir == null ) //$NON-NLS-1$
{
getLog().info( Messages.getString( "EclipsePlugin.pompackaging" ) ); //$NON-NLS-1$
return false;
}
if ( "eclipse-plugin".equals( packaging ) )
{
pde = true;
}
if ( eclipseProjectDir == null )
{
eclipseProjectDir = executedProject.getFile().getParentFile();
}
if ( !eclipseProjectDir.exists() && !eclipseProjectDir.mkdirs() )
{
throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantcreatedir", eclipseProjectDir ) ); //$NON-NLS-1$
}
if ( !eclipseProjectDir.equals( executedProject.getFile().getParentFile() ) )
{
if ( !eclipseProjectDir.isDirectory() )
{
throw new MojoExecutionException( Messages.getString( "EclipsePlugin.notadir", eclipseProjectDir ) ); //$NON-NLS-1$
}
eclipseProjectDir = new File( eclipseProjectDir, executedProject.getArtifactId() );
if ( !eclipseProjectDir.isDirectory() && !eclipseProjectDir.mkdirs() )
{
throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantcreatedir", eclipseProjectDir ) ); //$NON-NLS-1$
}
}
validateExtras();
return true;
}
protected void validateExtras()
{
// provided for extension.
}
private void checkDeprecations()
{
if ( eclipseDownloadSources )
{
// deprecated warning
getLog().warn( Messages.getString( "EclipsePlugin.deprecatedpar", new Object[] { //$NON-NLS-1$
"eclipse.downloadSources", //$NON-NLS-1$
"downloadSources" } ) ); //$NON-NLS-1$
downloadSources = true;
}
checkExtraDeprecations();
}
protected void checkExtraDeprecations()
{
// provided for extension.
}
public void writeConfiguration( IdeDependency[] deps )
throws MojoExecutionException
{
EclipseWriterConfig config = createEclipseWriterConfig( deps );
if ( wtpmanifest && isJavaProject() )
{
EclipseManifestWriter.addManifestResource( getLog(), config );
}
// NOTE: This could change the config!
writeExtraConfiguration( config );
if ( wtpVersionFloat == 0.7f )
{
new EclipseWtpmodulesWriter().init( getLog(), config ).write();
}
if ( wtpVersionFloat >= 1.0f )
{
new EclipseWtpFacetsWriter().init( getLog(), config ).write();
}
if ( wtpVersionFloat == 1.0f )
{
new EclipseWtpComponentWriter().init( getLog(), config ).write();
}
if ( wtpVersionFloat >= 1.5 )
{
new EclipseWtpComponent15Writer().init( getLog(), config ).write();
}
new EclipseSettingsWriter().init( getLog(), config ).write();
if ( isJavaProject )
{
new EclipseClasspathWriter().init( getLog(), config ).write();
if ( ajdt && ajdtVersion.equals( "1.4" ) )
{
new EclipseAjdtWriter().init( getLog(), config ).write();
}
}
if ( wtpapplicationxml )
{
new EclipseWtpApplicationXMLWriter().init( getLog(), config ).write();
}
if ( pde )
{
this.getLog().info( "The Maven Eclipse plugin runs in 'pde'-mode." );
new EclipseOSGiManifestWriter().init( getLog(), config ).write();
}
// NOTE: This one MUST be after EclipseClasspathwriter, and possibly others,
// since currently EclipseClasspathWriter does some magic to detect nested
// output folders and modifies the configuration by adding new (Ant) builders.
// So the .project file must be written AFTER those have run!
new EclipseProjectWriter().init( getLog(), config ).write();
writeAdditionalConfig();
getLog().info( Messages.getString( "EclipsePlugin.wrote", new Object[] { //$NON-NLS-1$
config.getEclipseProjectName(), eclipseProjectDir.getAbsolutePath() } ) );
}
protected void writeAdditionalConfig()
throws MojoExecutionException
{
if ( additionalConfig != null )
{
for ( int j = 0; j < additionalConfig.length; j++ )
{
EclipseConfigFile file = additionalConfig[j];
File projectRelativeFile = new File( eclipseProjectDir, file.getName() );
if ( projectRelativeFile.isDirectory() )
{
// just ignore?
getLog().warn( Messages.getString( "EclipsePlugin.foundadir", //$NON-NLS-1$
projectRelativeFile.getAbsolutePath() ) );
}
try
{
projectRelativeFile.getParentFile().mkdirs();
if ( file.getContent() == null )
{
InputStream inStream;
if ( file.getLocation() != null )
{
inStream = locator.getResourceAsInputStream( file.getLocation() );
}
else
{
inStream = file.getURL().openConnection().getInputStream();
}
OutputStream outStream = new FileOutputStream( projectRelativeFile );
try
{
IOUtil.copy( inStream, outStream );
}
finally
{
inStream.close();
outStream.close();
}
}
else
{
FileUtils.fileWrite( projectRelativeFile.getAbsolutePath(), file.getContent() );
}
}
catch ( IOException e )
{
throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantwritetofile", //$NON-NLS-1$
projectRelativeFile.getAbsolutePath() ) );
}
catch ( ResourceNotFoundException e )
{
throw new MojoExecutionException( Messages.getString( "EclipsePlugin.cantfindresource", //$NON-NLS-1$
file.getLocation() ) );
}
}
}
}
protected EclipseWriterConfig createEclipseWriterConfig( IdeDependency[] deps )
throws MojoExecutionException
{
File projectBaseDir = executedProject.getFile().getParentFile();
// build a list of UNIQUE source dirs (both src and resources) to be
// used in classpath and wtpmodules
EclipseSourceDir[] sourceDirs = buildDirectoryList( executedProject, eclipseProjectDir, buildOutputDirectory );
EclipseWriterConfig config = new EclipseWriterConfig();
config.setWorkspaceConfiguration( getWorkspaceConfiguration() );
config.setProjectNameTemplate( calculateProjectNameTemplate() );
String projectName = IdeUtils.getProjectName( config.getProjectNameTemplate(), project );
config.setEclipseProjectName( projectName );
config.setWtpapplicationxml( wtpapplicationxml );
config.setWtpVersion( wtpVersionFloat );
float ajdtVersionFloat;
try
{
ajdtVersionFloat = Float.parseFloat( ajdtVersion );
}
catch( NumberFormatException e )
{
ajdtVersionFloat = 0.0f;
}
config.setAjdtVersion( ajdtVersionFloat );
Set convertedBuildCommands = new LinkedHashSet();
if ( buildcommands != null )
{
for ( Iterator it = buildcommands.iterator(); it.hasNext(); )
{
Object cmd = it.next();
if ( cmd instanceof BuildCommand )
{
convertedBuildCommands.add( cmd );
}
else
{
convertedBuildCommands.add( new BuildCommand( (String) cmd ) );
}
}
}
if( ajdt )
{
buildAjdtWeaveDeps( deps );
buildAspectjDeps( deps );
}
config.setBuildCommands( new LinkedList( convertedBuildCommands ) );
config.setBuildOutputDirectory( buildOutputDirectory );
config.setClasspathContainers( classpathContainers );
config.setDeps( deps );
config.setEclipseProjectDirectory( eclipseProjectDir );
config.setLocalRepository( localRepository );
config.setOSGIManifestFile( manifest );
config.setPde( pde );
config.setProject( project );
config.setProjectBaseDir( projectBaseDir );
config.setProjectnatures( projectnatures );
config.setProjectFacets( additionalProjectFacets );
config.setSourceDirs( sourceDirs );
config.setAddVersionToProjectName( isAddVersionToProjectName() );
config.setPackaging( packaging );
collectWarContextRootsFromReactorEarConfiguration( config );
return config;
}
/**
* If this is a war module peek into the reactor an search for an ear module that defines the context root of this
* module.
*
* @param config config to save the context root.
*/
private void collectWarContextRootsFromReactorEarConfiguration( EclipseWriterConfig config )
{
if ( reactorProjects != null && wtpContextName == null &&
Constants.PROJECT_PACKAGING_WAR.equals( project.getPackaging() ) )
{
for ( Iterator iter = reactorProjects.iterator(); iter.hasNext(); )
{
MavenProject reactorProject = (MavenProject) iter.next();
if ( Constants.PROJECT_PACKAGING_EAR.equals( reactorProject.getPackaging() ) )
{
Xpp3Dom[] warDefinitions =
IdeUtils.getPluginConfigurationDom( reactorProject, JeeUtils.ARTIFACT_MAVEN_EAR_PLUGIN,
new String[] { "modules", "webModule" } );
for ( int index = 0; index < warDefinitions.length; index++ )
{
Xpp3Dom groupId = warDefinitions[index].getChild( "groupId" );
Xpp3Dom artifactId = warDefinitions[index].getChild( "artifactId" );
Xpp3Dom contextRoot = warDefinitions[index].getChild( "contextRoot" );
if ( groupId != null && artifactId != null && contextRoot != null &&
groupId.getValue() != null && artifactId.getValue() != null &&
contextRoot.getValue() != null )
{
getLog().info(
"Found context root definition for " + groupId.getValue() + ":" +
artifactId.getValue() + " " + contextRoot.getValue() );
if ( project.getArtifactId().equals( artifactId.getValue() ) &&
project.getGroupId().equals( groupId.getValue() ) )
{
config.setContextName( contextRoot.getValue() );
}
}
else
{
getLog().info(
"Found incomplete ear configuration in " + reactorProject.getGroupId() +
":" + reactorProject.getGroupId() + " found " +
warDefinitions[index].toString() );
}
}
}
}
}
if ( config.getContextName() == null && Constants.PROJECT_PACKAGING_WAR.equals( project.getPackaging() ) )
{
if ( wtpContextName == null )
{
config.setContextName( project.getArtifactId() );
}
else
{
config.setContextName( wtpContextName );
}
}
}
/**
* Write any extra configuration information for the Eclipse project. This is an extension point, called before the
* main configurations are written. true if the artifact is produced by a reactor projectart.
*/
private boolean isAvailableAsAWorkspaceProject( Artifact artifact )
{
IdeDependency[] workspaceArtefacts = getWorkspaceArtefacts();
for ( int index = 0; workspaceArtefacts != null && index < workspaceArtefacts.length; index++ )
{
IdeDependency workspaceArtefact = workspaceArtefacts[index];
if ( workspaceArtefact.getGroupId().equals( artifact.getGroupId() ) &&
workspaceArtefact.getArtifactId().equals( artifact.getArtifactId() ) )
{
if ( workspaceArtefact.getVersion().equals( artifact.getVersion() ) )
{
workspaceArtefact.setAddedToClasspath( true );
getLog().debug( "Using workspace project: " + workspaceArtefact.getEclipseProjectName() );
return true;
}
else
{
getLog().info(
"Artifact " +
artifact.getId() +
" already available as a workspace project, but with different version. Expected: " +
artifact.getVersion() + ", found: " + workspaceArtefact.getVersion() );
}
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see org.apache.maven.plugin.ide.AbstractIdeSupportMojo#doDependencyResolution()
*/
protected IdeDependency[] doDependencyResolution()
throws MojoExecutionException
{
return super.doDependencyResolution();
}
/**
* Checks if jar has to be resolved for the given artifact
*
* @param art the artifact to check
* @return true if resolution should happen
*/
protected boolean hasToResolveJar( Artifact art )
{
return !( getUseProjectReferences() && isAvailableAsAReactorProject( art ) ) ||
( limitProjectReferencesToWorkspace && !( getUseProjectReferences() && isAvailableAsAWorkspaceProject( art ) ) );
}
/**
* Checks if a projects reference has to be used for the given artifact
*
* @param art the artifact to check
* @return true if a project reference has to be used.
*/
protected boolean useProjectReference( Artifact art )
{
boolean isReactorProject = getUseProjectReferences() && isAvailableAsAReactorProject( art );
boolean isWorkspaceProject = getUseProjectReferences() && isAvailableAsAWorkspaceProject( art );
return ( isReactorProject && !limitProjectReferencesToWorkspace ) || // default
( limitProjectReferencesToWorkspace && isWorkspaceProject ) || // limitProjectReferencesToWorkspace
( !isReactorProject && isWorkspaceProject ); // default + workspace projects
}
}