package org.mobicents.plugins.library; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.apache.maven.archiver.MavenArchiveConfiguration; import org.apache.maven.archiver.MavenArchiver; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.installer.ArtifactInstallationException; import org.apache.maven.artifact.installer.ArtifactInstaller; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; import org.apache.maven.project.MavenProjectHelper; import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.mobicents.plugins.library.pojos.LibraryJar; import org.mobicents.plugins.library.pojos.LibraryRef; /** * Base class for creating a library jar. * * @author <a href="brainslog@gmail.com"> Alexandre Mendonca </a> */ public abstract class AbstractLibraryMojo extends AbstractMojo { private LibraryRef libraryId; private List<LibraryRef> libraryRefs = new ArrayList<LibraryRef>(); private List<LibraryJar> libraryJars = new ArrayList<LibraryJar>(); /** * Base directory. * * @parameter expression="${basedir}" * @required * @readonly */ private File basedir; // /////////////////////////////////////////////// // REACTOR // /////////////////////////////////////////////// /** * Project builder * * @component */ protected MavenProjectBuilder mavenProjectBuilder; /** * The local repository. * * @parameter expression="${localRepository}" */ protected ArtifactRepository localRepository; /** * Used to look up Artifacts in the remote repository. * * @parameter expression="${component.org.apache.maven.artifact.factory.ArtifactFactory}" * @required * @readonly */ protected org.apache.maven.artifact.factory.ArtifactFactory factory; /** * Used to look up Artifacts in the remote repository. * * @parameter expression="${component.org.apache.maven.artifact.resolver.ArtifactResolver}" * @required * @readonly */ protected org.apache.maven.artifact.resolver.ArtifactResolver resolver; /** * List of Remote Repositories used by the resolver * * @parameter expression="${project.remoteArtifactRepositories}" * @readonly * @required */ protected java.util.List remoteRepos; // /////////////////////////////////////////////// // RESOURCES // /////////////////////////////////////////////// /** * The list of resources we want to transfer. * * @parameter expression="${project.resources}" * @required */ private List resources; /** * The character encoding scheme to be applied. * * @parameter */ private String encoding; /** * The list of additional key-value pairs aside from that of the System, and that of the project, which would be * used for the filtering. * * @parameter expression="${project.build.filters}" */ private List filters; /** * @parameter expression="${component.org.apache.maven.artifact.installer.ArtifactInstaller}" * @required @ readonly */ protected ArtifactInstaller installer; /** * Default artifact handler. * * @parameter expression="${component.org.apache.maven.artifact.handler.ArtifactHandler}" @ readonly * @required */ protected org.apache.maven.artifact.handler.ArtifactHandler artifactHandler; /** * The location of the deployment descriptor xml file to be used within the library jar. * * @parameter expression="${basedir}/src/main/resources/META-INF/library-jar.xml" */ private File libraryDD; // ///////////////////////////////////////////////////////////////////// // JAR // ///////////////////////////////////////////////////////////////////// /** * Directory containing the generated JAR. * * @parameter expression="${project.build.outputDirectory}" * @required */ private File outputDirectory; /** * Directory target. * * @parameter expression="${project.build.output}" */ private File targetDirectory; /** * Name of the generated JAR. * * @parameter alias="jarName" expression="${jar.finalName}" default-value="${project.build.finalName}" * @required */ private String finalName; /** * The Jar archiver. * * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#jar}" * @required */ private JarArchiver jarArchiver; /** * The Maven project. * * @parameter expression="${project}" * @required * @readonly */ private MavenProject project; /** * The archive configuration to use. See <a href="http://maven.apache.org/shared/maven-archiver/index.html">the * documentation for Maven Archiver</a>. * * @parameter */ private MavenArchiveConfiguration archive = new MavenArchiveConfiguration(); /** * Path to the default MANIFEST file to use. It will be used if <code>useDefaultManifestFile</code> is set to * <code>true</code>. * * @parameter expression="${project.build.outputDirectory}/META-INF/MANIFEST.MF" * @required * @readonly * @since 2.2 */ private File defaultManifestFile; /** * Set this to <code>true</code> to enable the use of the <code>defaultManifestFile</code>. * * @parameter expression="${jar.useDefaultManifestFile}" default-value="false" * @since 2.2 */ private boolean useDefaultManifestFile; /** * @component */ private MavenProjectHelper projectHelper; /** * Whether creating the archive should be forced. * * @parameter expression="${jar.forceCreation}" default-value="false" */ private boolean forceCreation; /** * Return the specific output directory to serve as the root for the archive. */ // protected abstract File getClassesDirectory(); protected final MavenProject getProject() { return project; } /** * Overload this to produce a jar with another classifier, for example a test-jar. */ protected abstract String getClassifier(); /** * Overload this to produce a test-jar, for example. */ protected abstract String getType(); protected static File getJarFile(File basedir, String finalName, String classifier) { if (classifier == null) { classifier = ""; } else if (classifier.trim().length() > 0 && !classifier.startsWith("-")) { classifier = "-" + classifier; } return new File(basedir, finalName + classifier + ".jar"); } /** * Default Manifest location. Can point to a non existing file. Cannot return null. */ protected File getDefaultManifestFile() { return defaultManifestFile; } /* * (non-Javadoc) * @see org.apache.maven.plugin.AbstractMojo#execute() */ public void execute() throws MojoExecutionException { if(getLog().isDebugEnabled()) { getLog().debug("Executing Maven JAIN SLEE 1.1 Library Plugin"); } // Initialize the plugin initialize(); // Obtain the name#vendor#version from pom this.libraryId = getLibraryRef( project ); if( this.libraryId == null ) { throw new MojoExecutionException("Unable to get Library ID from pom, please verify."); } else { if(getLog().isDebugEnabled()) { getLog().info( libraryId.getName() + "#" + libraryId.getVendor() + "#" + libraryId.getVersion() ); } } for(Object dep : project.getDependencyArtifacts()) { Artifact depArtifact = (Artifact) dep; String depGroupId = depArtifact.getGroupId(); String depArtifactId = depArtifact.getArtifactId(); String depVersion = depArtifact.getVersion(); String depScope = depArtifact.getScope(); if(depScope.equals("compile")) { this.libraryJars.add(new LibraryJar(depArtifact.getFile())); } else if(depScope.equals("runtime")) { MavenProject depPom = getDependency(depGroupId, depArtifactId, depVersion, "pom"); LibraryRef depRef = getLibraryRef(depPom); if(depRef != null) { this.libraryRefs.add(depRef); } } getLog().info("I depend on: [" + depGroupId + "#" + depArtifactId + "#" + depVersion + "] @ " + depScope); } scanResources( new File("./src/main/resources/"), this.libraryJars ); generateLibraryDeploymentDescritptor(); copyJars(); File libraryJar = createArchive(); // verify is works String classifier = getClassifier(); if (classifier != null) { projectHelper.attachArtifact(getProject(), getType(), classifier, libraryJar); } else { getProject().getArtifact().setFile(libraryJar); } // install in local repo try { Artifact duArtifact = new DefaultArtifact(project.getGroupId(), project.getArtifactId(), VersionRange.createFromVersion(project.getVersion()), Artifact.SCOPE_RUNTIME, "jar", getClassifier(), artifactHandler); duArtifact.setFile(libraryJar); installer.install(libraryJar, duArtifact, localRepository); } catch (ArtifactInstallationException e) { throw new MojoExecutionException("Cannot install library jar in local repository", e); } } /** * Initiaizes the plugin (directory init/creation) * * @throws MojoExecutionException */ private void initialize() throws MojoExecutionException { if (outputDirectory == null) { outputDirectory = new File(basedir.getAbsolutePath(), "target"); } if (!outputDirectory.exists()) { outputDirectory.mkdirs(); } } /** * Generates the deployment descriptor for the library jar, based on the library-ref * element, library jars and jars present at resources folder. * * @throws MojoExecutionException */ private void generateLibraryDeploymentDescritptor() throws MojoExecutionException { File libraryDescriptorDir = new File(outputDirectory, "META-INF"); if (!libraryDescriptorDir.exists()) { libraryDescriptorDir.mkdirs(); } File libraryDD = new File(libraryDescriptorDir.getAbsolutePath(), "library-jar.xml"); String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + "<!DOCTYPE library-jar PUBLIC \r\n" + "\t\t\"-//Sun Microsystems, Inc.//DTD JAIN SLEE Library 1.1//EN\" \r\n" + "\t\t\"http://java.sun.com/dtd/slee-library-jar_1_1.dtd\">\r\n\r\n" + "<library-jar>\r\n\t<library>\r\n"; xml += this.libraryId.toXmlEntry() + "\r\n"; for(LibraryRef libraryRef : this.libraryRefs) { xml += libraryRef.toXmlEntryWithRef(); } xml += "\r\n"; for(LibraryJar libraryJar : this.libraryJars) { xml += libraryJar.toXmlEntry(); } xml += "\t</library>\r\n</library-jar>\r\n"; getLog().info("Generated Library descriptor: " + libraryDD.getAbsolutePath() + "\n" + xml + "\n"); try { BufferedWriter out = new BufferedWriter(new FileWriter(libraryDD)); out.write(xml); out.close(); } catch ( IOException e ) { getLog().error( "Failed to create deployment descriptor in " + libraryDD.getAbsolutePath(), e ); } this.libraryDD = libraryDD; } /** * Gets the dependency identified by group, artifact id and version. If no packaging is defined, defaults to jar. * * @param depGroupId * @param depArtifactId * @param depVersion * @param depPackaging */ private MavenProject getDependency(String depGroupId, String depArtifactId,String depVersion, String depPackaging) { if(depPackaging == null || depPackaging.equals("")) { depPackaging = "jar"; } try { Artifact pomArtifact = this.factory.createArtifact( depGroupId, depArtifactId, depVersion, "", depPackaging ); this.resolver.resolve( pomArtifact, remoteRepos, this.localRepository ); MavenProject projectDependencyArtifactMavenProject = mavenProjectBuilder.buildFromRepository( pomArtifact, this.remoteRepos, this.localRepository, false ); return projectDependencyArtifactMavenProject; } catch (Exception e) { getLog().error( "Failed to obtain dependency", e ); } return null; } /** * Obtains the library-name, library-vendor, library-version into a LibraryRef element. * * @param mavenProject the maven project to obtain it from * @return */ private LibraryRef getLibraryRef(MavenProject mavenProject) { String libraryName; String libraryVendor; String libraryVersion; String libraryDescription = null; for(Object pObject : mavenProject.getBuildPlugins()) { Plugin plugin = (Plugin)pObject; if( plugin.getArtifactId().equals( "maven-library-plugin" ) ) { Xpp3Dom configuration = (Xpp3Dom)plugin.getConfiguration(); if(configuration != null) { if(configuration.getChildren("library-name").length > 0) { libraryName = configuration.getChildren("library-name")[0].getValue(); } else { getLog().error( "Library Name missing in plugin configuration!" ); return null; } if(configuration.getChildren("library-vendor").length > 0) { libraryVendor = configuration.getChildren("library-vendor")[0].getValue(); } else { getLog().error( "Library Vendor missing in plugin configuration!" ); return null; } if(configuration.getChildren("library-version").length > 0) { libraryVersion = configuration.getChildren("library-version")[0].getValue(); } else { getLog().error( "Library Version missing in plugin configuration!" ); return null; } if(configuration.getChildren("description").length > 0) { libraryDescription = configuration.getChildren("description")[0].getValue(); } } else { getLog().error( "Configuration missing in plugin!" ); return null; } return new LibraryRef(libraryName, libraryVendor, libraryVersion, libraryDescription); } } return null; } /** * Scans a folder in a recursive way to find jars to be included in the library. * * @param file * @param jars */ private void scanResources(File file, Collection<LibraryJar> jars) { if(getLog().isDebugEnabled()) { getLog().debug( "Scanning " + file.getAbsolutePath() + " ..." ); } final File[] children = file.listFiles(); if (children != null) { for (File child : children) { if(!child.isDirectory() && child.getName().toLowerCase().endsWith(".jar")) { jars.add(new LibraryJar(child)); } else if(child.isDirectory()) { scanResources(child, jars); } } } } /** * Copies the jars from maven repository and/or src/main/resources folder to target folder. * * @throws MojoExecutionException */ private void copyJars() throws MojoExecutionException { try { File jarsFolder = new File(outputDirectory, "jars"); if(!jarsFolder.exists()) { jarsFolder.mkdir(); } for(LibraryJar libJar : libraryJars) { FileUtils.copyFile( libJar.getFile(), new File(jarsFolder, libJar.getFile().getName()) ); } } catch (Exception e) { throw new MojoExecutionException("Failed to copy jars to destination folder.", e); } } /** * Creates the library archive. * * @return * @throws MojoExecutionException */ public File createArchive() throws MojoExecutionException { try { if (targetDirectory == null) { targetDirectory = new File(basedir.getAbsolutePath(), "target"); } if (!targetDirectory.exists()) { targetDirectory.mkdir(); } File jarFile = getJarFile(targetDirectory, finalName, getClassifier()); MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver(jarArchiver); archiver.setOutputFile(jarFile); archive.setForced(forceCreation); // add output directory archiver.getArchiver().addDirectory(outputDirectory); // create archive archiver.createArchive(project, archive); return jarFile; } catch (Exception e) { throw new MojoExecutionException("Failed to create library jar.", e); } } }