package org.ops4j.pax.construct.lifecycle;
/*
* Copyright 2007 Stuart McCulloch
*
* 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.
*/
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.regex.Pattern;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.eclipse.EclipsePlugin;
import org.apache.maven.plugin.eclipse.EclipseSourceDir;
import org.apache.maven.plugin.eclipse.writers.EclipseClasspathWriter;
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.ide.IdeDependency;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.apache.maven.project.path.PathTranslator;
import org.apache.maven.shared.osgi.Maven2OsgiConverter;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.Xpp3DomWriter;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.ops4j.pax.construct.util.DirUtils;
import org.ops4j.pax.construct.util.DirUtils.EntryFilter;
import org.ops4j.pax.construct.util.PomUtils;
import org.ops4j.pax.construct.util.ReflectMojo;
import org.ops4j.pax.construct.util.StreamFactory;
/**
* Extends <a href="http://maven.apache.org/plugins/maven-eclipse-plugin/eclipse-mojo.html">EclipsePlugin</a> to
* provide customized Eclipse project files for Pax-Construct projects.<br/>Inherited parameters can still be used, but
* unfortunately don't appear in the generated docs.
*
* @extendsPlugin eclipse
* @goal eclipse
* @phase package
*
* @execute phase="none"
*/
public class EclipseOSGiMojo extends EclipsePlugin
{
/**
* Component factory for Maven projects
*
* @component
*/
private MavenProjectBuilder m_mavenProjectBuilder;
/**
* Component to convert between Maven and OSGi versions
*
* @component
*/
private Maven2OsgiConverter m_maven2OsgiConverter;
/**
* Project path translation (needed for backwards compatibility)
*
* @component
*/
private PathTranslator m_pathTranslator;
/**
* Switch to turn on/off fixing of dependency entries in the classpath file.
*
* @parameter expression="${fixDependencies}" default-value="EXTERNAL"
*/
private String fixDependencies;
/**
* Provide access to the private fields of the Eclipse mojo
*/
private ReflectMojo m_eclipseMojo;
/**
* The main project when generating Eclipse project files for imported bundles
*/
private MavenProject m_provisionProject;
/**
* IDE dependencies that might be embedded inside the bundle
*/
private List m_embeddableDependencies;
/**
* {@inheritDoc}
*/
public boolean setup()
throws MojoExecutionException
{
// we don't fork eclipse goal
setExecutedProject( project );
if( null != m_provisionProject )
{
enablePDE(); // imported OSGi bundle
}
else if( PomUtils.isBundleProject( executedProject ) )
{
enablePDE(); // compiled OSGi bundle
setUseProjectReferences( false );
}
else if( ProvisionMojo.isProvisioningPom( executedProject ) )
{
try
{
/*
* unpack imported bundles and generate Eclipse files one-by-one
*/
setupImportedBundles();
}
catch( InvalidDependencyVersionException e )
{
getLog().warn( "Unable to generate Eclipse files for project " + executedProject.getId() );
}
/*
* don't create Eclipse files for the provisioning POM itself!
*/
return false;
}
// default to normal behaviour
return super.setup();
}
/**
* Enable PDE support
*/
private void enablePDE()
{
if( null == m_eclipseMojo )
{
// by default enable creation of PDE project files for OSGi
m_eclipseMojo = new ReflectMojo( this, EclipsePlugin.class );
}
m_eclipseMojo.setField( "pde", Boolean.TRUE );
setWtpversion( "none" );
List containers = getClasspathContainers();
if( null != containers && !containers.contains( REQUIRED_PLUGINS_CONTAINER ) )
{
containers.add( REQUIRED_PLUGINS_CONTAINER );
}
}
/**
* {@inheritDoc}
*/
public void writeConfiguration( IdeDependency[] deps )
throws MojoExecutionException
{
if( !isPdeProject() )
{
// non-OSGi project
super.writeConfiguration( deps );
}
else
{
m_embeddableDependencies = new ArrayList();
if( null == m_provisionProject )
{
// compiled OSGi bundle / wrapper
writeBundleConfiguration( deps );
}
else
{
// imported (external) OSGi bundle
writeImportedConfiguration();
}
}
}
/**
* Customize Eclipse project files for Pax-Construct generated bundles
*
* @param deps resolved project dependencies, potentially with sources and javadocs
* @throws MojoExecutionException
*/
private void writeBundleConfiguration( IdeDependency[] deps )
throws MojoExecutionException
{
for( int i = 0; i < deps.length; i++ )
{
if( deps[i].isAddedToClasspath() )
{
// cache here so we can attach sources to embedded entries
if( !deps[i].isTestDependency() && !deps[i].isProvided() )
{
m_embeddableDependencies.add( deps[i] );
}
/*
* Change potential test dependencies to be non-OSGi otherwise they won't appear as Required Libraries.
* We include provided dependencies here because PDE might not add them as Plug-in Dependencies, it all
* depends on the manifest (which won't necessarily import packages used during testing)
*/
deps[i] = fixOSGiTestDependency( deps[i] );
}
}
EclipseWriterConfig config = createEclipseWriterConfig( deps );
config.setEclipseProjectName( getEclipseProjectName( executedProject, true ) );
new EclipseSettingsWriter().init( getLog(), config ).write();
new EclipseClasspathWriter().init( getLog(), config ).write();
new EclipseProjectWriter().init( getLog(), config ).write();
/*
* copy bundle manifest to where PDE expects it, but tweak it to fix embedded paths
*/
refactorForEclipse( getBundleFile( executedProject ) );
writeAdditionalConfig();
}
/**
* @param bundleProject bundle project
* @return recently built bundle
*/
private File getBundleFile( MavenProject bundleProject )
{
Artifact artifact = bundleProject.getArtifact();
File bundleFile = artifact.getFile();
if( null == bundleFile || !bundleFile.exists() )
{
// no file attached in this cycle, so check local build
String name = bundleProject.getBuild().getFinalName() + ".jar";
bundleFile = new File( bundleProject.getBuild().getDirectory(), name );
}
if( !bundleFile.exists() )
{
// last chance: see if it is already has been installed locally
PomUtils.getFile( artifact, artifactResolver, localRepository );
bundleFile = artifact.getFile();
}
return bundleFile;
}
/**
* The maven-eclipse-plugin has a bug where test dependencies that are also OSGi bundles are excluded from the
* .classpath because they are expected to be on the Bundle-ClassPath. However, this is not a valid assumption
* because the Maven test-cases and their dependencies do not necessarily end-up packaged inside the bundle.
*
* @param dependency an IDE test dependency
* @return fixed IDE test dependency
*/
private IdeDependency fixOSGiTestDependency( IdeDependency dependency )
{
if( "FALSE".equalsIgnoreCase( fixDependencies ) )
{
return dependency;
}
// by default, don't fix dependencies pointing to local projects found in the same tree
if( "EXTERNAL".equalsIgnoreCase( fixDependencies ) && isReactorDependency( dependency ) )
{
return dependency;
}
// previous behaviour in 1.3 was exhaustive search of the poms in the local file-system
if( "CUSTOM".equalsIgnoreCase( fixDependencies ) )
{
String id = dependency.getGroupId() + ':' + dependency.getArtifactId();
File baseDir = executedProject.getBasedir();
if( DirUtils.findPom( baseDir, id ) != null )
{
return dependency;
}
}
// unfortunately there's no setIsOsgiBundle() method, so we have to replace the whole dependency...
IdeDependency testDependency = new IdeDependency( dependency.getGroupId(), dependency.getArtifactId(),
dependency.getVersion(), dependency.getClassifier(), dependency.isReferencedProject(), true, false, false,
dependency.isAddedToClasspath(), dependency.getFile(), dependency.getType(), false, null, 0,
dependency.getEclipseProjectName() );
testDependency.setSourceAttachment( dependency.getSourceAttachment() );
testDependency.setJavadocAttachment( dependency.getJavadocAttachment() );
return testDependency;
}
private boolean isReactorDependency( IdeDependency dependency )
{
// check current reactor...
if( reactorProjects != null )
{
for( Iterator i = reactorProjects.iterator(); i.hasNext(); )
{
MavenProject reactorProject = (MavenProject) i.next();
if( reactorProject.getGroupId().equals( dependency.getGroupId() )
&& reactorProject.getArtifactId().equals( dependency.getArtifactId() ) )
{
return true;
}
}
}
return false;
}
/**
* Provide better naming for Pax-Construct generated OSGi bundles
*
* @param project current Maven project
* @param addVersion when true, add the project version to the name
* @return an Eclipse friendly name for the bundle
*/
private static String getEclipseProjectName( MavenProject project, boolean addVersion )
{
String projectName = project.getProperties().getProperty( "bundle.symbolicName" );
if( null == projectName )
{
// fall back to standard "groupId.artifactId" but try to eliminate duplicate segments
projectName = PomUtils.getCompoundId( project.getGroupId(), project.getArtifactId() );
}
if( addVersion )
{
// check for wrapper version, which reflects the version of the wrapped contents
String projectVersion = project.getProperties().getProperty( "wrapped.version" );
if( null == projectVersion )
{
projectVersion = project.getVersion();
}
return projectName + " [" + projectVersion + ']';
}
return projectName;
}
/**
* Select files for unpacking that don't exist locally under target/classes
*/
private static class IncludedContentFilter
implements EntryFilter
{
private final File m_outputDir;
/**
* @param outputDir build output directory
*/
public IncludedContentFilter( File outputDir )
{
m_outputDir = outputDir;
}
/**
* {@inheritDoc}
*/
public boolean accept( String name )
{
// always select metadata folders as we may need to refactor them
if( name.startsWith( "META-INF" ) || name.startsWith( "OSGI-INF" ) )
{
return true;
}
// also select any embedded jars
else if( name.endsWith( ".jar" ) )
{
return true;
}
// do we already have this file locally?
return new File( m_outputDir, name ).exists() == false;
}
}
/**
* Copy OSGi metadata to where Eclipse PDE expects it, but adjust the Bundle-ClassPath so Eclipse can find any
* embedded jars or directories in the unpacked bundle contents under the temporary directory
*
* @param bundleFile the packaged bundle
*/
private void refactorForEclipse( File bundleFile )
{
// temporary location in the output folder
String tempPath = "target/pax-eclipse";
boolean refactorManifest = false;
// make relative to the provisioning POM
File baseDir = executedProject.getBasedir();
File unpackDir = new File( baseDir, tempPath );
if( bundleFile == null || !bundleFile.exists() )
{
getLog().warn( "Bundle has not been built, reverting to basic behaviour" );
}
else
{
DirUtils.unpackBundle( bundleFile, unpackDir, new IncludedContentFilter( getBuildOutputDirectory() ) );
moveMetadata( unpackDir, "META-INF", baseDir );
moveMetadata( unpackDir, "OSGI-INF", baseDir );
// test to see if it's empty
unpackDir.delete();
refactorManifest = unpackDir.exists();
}
File manifestFile = new File( baseDir, "META-INF/MANIFEST.MF" );
Manifest manifest = getBundleManifest( manifestFile );
Attributes mainAttributes = manifest.getMainAttributes();
if( mainAttributes.getValue( "Bundle-SymbolicName" ) == null )
{
// Eclipse mis-behaves if the bundle has no symbolic name :(
String name = getEclipseProjectName( executedProject, false );
mainAttributes.putValue( "Bundle-SymbolicName", name.replace( '-', '_' ) );
}
String bundleClassPath = mainAttributes.getValue( "Bundle-ClassPath" );
/*
* refactor Bundle-ClassPath to help Eclipse find the unpacked contents
*/
if( refactorManifest )
{
bundleClassPath = ".," + DirUtils.rebasePaths( bundleClassPath, tempPath, ',' );
mainAttributes.putValue( "Bundle-ClassPath", bundleClassPath );
// add the embedded entries back to the Eclipse classpath
addEmbeddedEntriesToEclipseClassPath( tempPath, bundleClassPath );
}
try
{
manifestFile.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream( manifestFile );
manifest.write( out );
IOUtil.close( out );
}
catch( IOException e )
{
getLog().warn( "Unable to update Eclipse manifest: " + manifestFile );
}
createBuildProperties( baseDir, tempPath );
}
/**
* Create simple build.properties file so the export functionality from Eclipse/PDE works
*
* @param baseDir project base directory
* @param unpackPath path where the additional bundle contents were unpacked
*/
private void createBuildProperties( File baseDir, String unpackPath )
{
File buildPropertiesFile = new File( baseDir, "build.properties" );
if( !buildPropertiesFile.exists() )
{
BufferedWriter writer = null;
try
{
writer = new BufferedWriter( new FileWriter( buildPropertiesFile ) );
/* compiled/wrapped bundle */
if( null != unpackPath )
{
File sourceDir = new File( baseDir, "src/main/java" );
if( sourceDir.exists() )
{
writer.write( "source.. = src/main/java/,src/main/resources/" );
writer.newLine();
}
writer.write( "output.. = target/classes/" );
writer.newLine();
writer.write( "bin.includes = META-INF/,." );
if( new File( baseDir, unpackPath ).exists() )
{
writer.write( ',' + unpackPath + '/' );
}
writer.newLine();
}
/* imported bundle */
else
{
File bundleFile = executedProject.getArtifact().getFile();
if( null != bundleFile && bundleFile.isFile() )
{
writer.write( "install.location = " + bundleFile.toURI() );
writer.newLine();
}
writer.write( "source.. = ." );
writer.newLine();
writer.write( "output.. = ." );
writer.newLine();
writer.write( "bin.includes = META-INF/,." );
writer.newLine();
}
}
catch( IOException e )
{
getLog().warn( "Unable to create build.properties file" );
}
finally
{
IOUtil.close( writer );
}
}
}
/**
* @param manifestFile path to the local bundle manifest
* @return the bundle manifest, or sane defaults if the manifest couldn't be opened
*/
private Manifest getBundleManifest( File manifestFile )
{
Manifest manifest = new Manifest();
try
{
FileInputStream in = new FileInputStream( manifestFile );
manifest.read( in );
IOUtil.close( in );
}
catch( IOException e )
{
Attributes mainAttributes = manifest.getMainAttributes();
String osgiVersion = m_maven2OsgiConverter.getVersion( project.getVersion() );
// standard OSGi entries
mainAttributes.putValue( "Manifest-Version", "1" );
mainAttributes.putValue( "Bundle-ManifestVersion", "2" );
mainAttributes.putValue( "Bundle-Name", project.getName() );
mainAttributes.putValue( "Bundle-Version", osgiVersion );
// some basic OSGi dependencies, to help people get their code compiling...
mainAttributes.putValue( "Import-Package", "org.osgi.framework,org.osgi.util.tracker" );
}
return manifest;
}
/**
* @param fromDir source directory
* @param metadata metadata folder
* @param toDir target directory
*/
private void moveMetadata( File fromDir, String metadata, File toDir )
{
File metadataDir = new File( fromDir, metadata );
if( metadataDir.exists() )
{
try
{
FileUtils.copyDirectoryStructure( metadataDir, new File( toDir, metadata ) );
FileUtils.deleteDirectory( metadataDir );
}
catch( IOException e )
{
getLog().warn( "Unable to copy " + metadata + " contents to base directory" );
}
}
}
/**
* Add any embedded Bundle-ClassPath entries to the Eclipse classpath and re-attach sources/javadocs
*
* @param bundleLocation relative path to the unpacked bundle
* @param bundleClassPath the refactored Bundle-ClassPath
*/
private void addEmbeddedEntriesToEclipseClassPath( String bundleLocation, String bundleClassPath )
{
String[] classPath = bundleClassPath.split( "," );
File basedir = executedProject.getBasedir();
try
{
File classPathFile = new File( basedir, ".classpath" );
Reader reader = StreamFactory.newXmlReader( classPathFile );
Xpp3Dom classPathXML = Xpp3DomBuilder.build( reader );
IOUtil.close( reader );
for( int i = 0; i < classPath.length; i++ )
{
String binaryPath = classPath[i].trim();
if( !".".equals( binaryPath ) && new File( basedir, binaryPath ).exists() )
{
// embedded jar/directory needs to be a 'lib' entry
Xpp3Dom classPathEntry = new Xpp3Dom( "classpathentry" );
classPathEntry.setAttribute( "exported", "true" );
classPathEntry.setAttribute( "kind", "lib" );
classPathEntry.setAttribute( "path", binaryPath );
// find attached sources using the previously cached IDE dependencies
File sourcePath = findAttachedSource( bundleLocation, binaryPath );
if( sourcePath != null )
{
classPathEntry.setAttribute( "sourcepath", sourcePath.getPath() );
}
classPathXML.addChild( classPathEntry );
}
}
Writer writer = StreamFactory.newXmlWriter( classPathFile );
Xpp3DomWriter.write( new PrettyPrintXMLWriter( writer ), classPathXML );
IOUtil.close( writer );
}
catch( IOException e )
{
getLog().warn( "Unable to find Eclipse .classpath file" );
}
catch( XmlPullParserException e )
{
getLog().warn( "Unable to parse Eclipse .classpath file" );
}
}
/**
* Search cached IDE dependencies for an entry matching the given classpath element
*
* @param bundleLocation relative path to the unpacked bundle
* @param classPathEntry classpath element
* @return path to the attached sources
*/
private File findAttachedSource( String bundleLocation, String classPathEntry )
{
for( Iterator i = m_embeddableDependencies.iterator(); i.hasNext(); )
{
IdeDependency dependency = (IdeDependency) i.next();
// equivalent to '.' - source is first in list
if( bundleLocation.equals( classPathEntry ) )
{
return dependency.getSourceAttachment();
}
else if( Pattern.matches( "^.*[/\\\\]" + dependency.getArtifactId() + "[-.][^/\\\\]*$", classPathEntry ) )
{
return dependency.getSourceAttachment();
}
}
return null;
}
/**
* Unpack each imported bundle in turn and generate the relevant Eclipse project files
*
* @throws InvalidDependencyVersionException
* @throws MojoExecutionException
*/
private void setupImportedBundles()
throws InvalidDependencyVersionException,
MojoExecutionException
{
// don't process dependencies of imported bundles
m_provisionProject = getExecutedProject();
setResolveDependencies( false );
Set artifacts = m_provisionProject.createArtifacts( artifactFactory, null, null );
for( Iterator i = artifacts.iterator(); i.hasNext(); )
{
Artifact artifact = (Artifact) i.next();
// store project locally underneath the provisioning POM's directory
File groupDir = new File( m_provisionProject.getBasedir(), "target/" + artifact.getGroupId() );
File baseDir = new File( groupDir, artifact.getArtifactId() + '-' + artifact.getVersion() );
// download and unpack the bundle
if( !PomUtils.downloadFile( artifact, artifactResolver, remoteArtifactRepositories, localRepository ) )
{
getLog().warn( "Skipping missing bundle " + artifact );
continue;
}
DirUtils.unpackBundle( artifact.getFile(), baseDir, null );
// download the bundle POM and store locally
MavenProject dependencyProject = writeProjectPom( baseDir, artifact );
if( null == dependencyProject )
{
getLog().warn( "Skipping missing bundle " + artifact );
continue;
}
dependencyProject.setArtifact( artifact );
setExecutedProject( dependencyProject );
setProject( dependencyProject );
// trick Eclipse plugin to do the right thing
setBuildOutputDirectory( new File( baseDir, ".ignore" ) );
setEclipseProjectDir( baseDir );
try
{
// call the Eclipse plugin
getLog().info( "Generating Eclipse project for bundle " + artifact );
execute();
}
catch( MojoFailureException e )
{
getLog().warn( "Problem generating Eclipse files for artifact " + artifact );
}
}
}
/**
* Download and save the Maven POM for the given artifact
*
* @param baseDir base directory
* @param artifact Maven artifact
* @return the downloaded project
*/
private MavenProject writeProjectPom( File baseDir, Artifact artifact )
{
MavenProject pom = null;
String groupId = artifact.getGroupId();
String artifactId = artifact.getArtifactId();
String version = artifact.getVersion();
Artifact pomArtifact = artifactFactory.createProjectArtifact( groupId, artifactId, version );
try
{
pom = m_mavenProjectBuilder.buildFromRepository( pomArtifact, remoteArtifactRepositories, localRepository );
// need this when using Maven 2.1 which doesn't do any alignment
m_pathTranslator.alignToBaseDirectory( pom.getModel(), baseDir );
File pomFile = new File( baseDir, "pom.xml" );
Writer writer = StreamFactory.newXmlWriter( pomFile );
pom.writeModel( writer );
pom.setFile( pomFile );
IOUtil.close( writer );
}
catch( ProjectBuildingException e )
{
getLog().warn( "Unable to build POM for artifact " + pomArtifact );
}
catch( IOException e )
{
getLog().warn( "Unable to write POM for artifact " + pomArtifact );
}
return pom;
}
/**
* Customize Eclipse project files for imported (unpacked) bundles
*
* @throws MojoExecutionException
*/
private void writeImportedConfiguration()
throws MojoExecutionException
{
EclipseWriterConfig config = createEclipseWriterConfig( new IdeDependency[0] );
config.setEclipseProjectName( getEclipseProjectName( executedProject, true ) );
config.setClasspathContainers( Collections.EMPTY_LIST );
config.setSourceDirs( new EclipseSourceDir[0] );
// not compiling, so just need project and classpath files
new EclipseClasspathWriter().init( getLog(), config ).write();
new EclipseProjectWriter().init( getLog(), config ).write();
Artifact sourceArtifact = artifactFactory.createArtifactWithClassifier( executedProject.getGroupId(),
executedProject.getArtifactId(), executedProject.getVersion(), "java-source", "sources" );
if( downloadSources )
{
PomUtils.downloadFile( sourceArtifact, artifactResolver, remoteArtifactRepositories, localRepository );
}
else
{
// check to see if we already have the source downloaded...
PomUtils.getFile( sourceArtifact, artifactResolver, localRepository );
}
// set PDE classpath to point to unpacked bundle
attachImportedContent( sourceArtifact.getFile() );
String baseDir = executedProject.getBasedir().getPath();
File manifestFile = new File( baseDir, "META-INF/MANIFEST.MF" );
Manifest manifest = getBundleManifest( manifestFile );
Attributes mainAttributes = manifest.getMainAttributes();
String bundleClassPath = mainAttributes.getValue( "Bundle-ClassPath" );
if( null != bundleClassPath )
{
// add any embedded entries to the default Eclipse classpath
addEmbeddedEntriesToEclipseClassPath( baseDir, bundleClassPath );
}
createBuildProperties( new File( baseDir ), null );
}
/**
* Add a classpath entry for the unpacked imported bundle and attach it to the given source
*
* @param sources attached bundle sources
*/
private void attachImportedContent( File sources )
{
try
{
File classPathFile = new File( executedProject.getBasedir(), ".classpath" );
Reader reader = StreamFactory.newXmlReader( classPathFile );
Xpp3Dom classPathXML = Xpp3DomBuilder.build( reader );
IOUtil.close( reader );
Xpp3Dom classPathEntry = new Xpp3Dom( "classpathentry" );
classPathEntry.setAttribute( "exported", "true" );
classPathEntry.setAttribute( "kind", "lib" );
classPathEntry.setAttribute( "path", "." );
if( sources != null && sources.exists() )
{
classPathEntry.setAttribute( "sourcepath", sources.getPath() );
}
classPathXML.addChild( classPathEntry );
Writer writer = StreamFactory.newXmlWriter( classPathFile );
Xpp3DomWriter.write( new PrettyPrintXMLWriter( writer ), classPathXML );
IOUtil.close( writer );
}
catch( IOException e )
{
getLog().warn( "Unable to find Eclipse .classpath file" );
}
catch( XmlPullParserException e )
{
getLog().warn( "Unable to parse Eclipse .classpath file" );
}
}
}