initial checkin
This commit is contained in:
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Maven
|
||||||
|
target
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
|
.settings
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
|
117
pom.xml
Normal file
117
pom.xml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.inteligr8.alfresco</groupId>
|
||||||
|
<artifactId>maven-amp-plugin</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>maven-plugin</packaging>
|
||||||
|
|
||||||
|
<name>A Maven plugin to generate AMP files</name>
|
||||||
|
<description>Generate Alfresco Module Packages (AMP) files in a way simialr to WAR files</description>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<id>brian.long</id>
|
||||||
|
<name>Brian Long</name>
|
||||||
|
<email>brian@inteligr8.com</email>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>1.7</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.7</maven.compiler.target>
|
||||||
|
<maven.version>3.6.3</maven.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.aether</groupId>
|
||||||
|
<artifactId>aether-util</artifactId>
|
||||||
|
<version>1.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-plugin-api</artifactId>
|
||||||
|
<version>${maven.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugin-tools</groupId>
|
||||||
|
<artifactId>maven-plugin-annotations</artifactId>
|
||||||
|
<version>3.6.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-core</artifactId>
|
||||||
|
<version>${maven.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugin-testing</groupId>
|
||||||
|
<artifactId>maven-plugin-testing-harness</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-compat</artifactId>
|
||||||
|
<version>${maven.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-plugin-plugin</artifactId>
|
||||||
|
<version>3.6.0</version>
|
||||||
|
<configuration>
|
||||||
|
<goalPrefix>amp</goalPrefix>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>mojo-descriptor</id>
|
||||||
|
<goals>
|
||||||
|
<goal>descriptor</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>help-goal</id>
|
||||||
|
<goals>
|
||||||
|
<goal>helpmojo</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>inteligr8-release</id>
|
||||||
|
<name>Inteligr8 Releases</name>
|
||||||
|
<url>http://repos.yateslong.us/nexus/repository/inteligr8-public</url>
|
||||||
|
</repository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
</project>
|
||||||
|
|
323
src/main/java/com/inteligr8/alfresco/amp/AmpMojo.java
Normal file
323
src/main/java/com/inteligr8/alfresco/amp/AmpMojo.java
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
package com.inteligr8.alfresco.amp;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.maven.execution.MavenSession;
|
||||||
|
import org.apache.maven.model.Exclusion;
|
||||||
|
import org.apache.maven.model.FileSet;
|
||||||
|
import org.apache.maven.model.Resource;
|
||||||
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
|
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||||
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
|
import org.apache.maven.project.DefaultDependencyResolutionRequest;
|
||||||
|
import org.apache.maven.project.DependencyResolutionException;
|
||||||
|
import org.apache.maven.project.DependencyResolutionRequest;
|
||||||
|
import org.apache.maven.project.DependencyResolutionResult;
|
||||||
|
import org.apache.maven.project.MavenProject;
|
||||||
|
import org.apache.maven.project.ProjectDependenciesResolver;
|
||||||
|
import org.codehaus.plexus.component.annotations.Component;
|
||||||
|
import org.codehaus.plexus.component.annotations.Requirement;
|
||||||
|
import org.codehaus.plexus.util.FileUtils;
|
||||||
|
import org.codehaus.plexus.util.IOUtil;
|
||||||
|
import org.eclipse.aether.graph.Dependency;
|
||||||
|
import org.eclipse.aether.util.filter.DependencyFilterUtils;
|
||||||
|
import org.eclipse.aether.util.filter.ExclusionsDependencyFilter;
|
||||||
|
import org.eclipse.aether.util.filter.ScopeDependencyFilter;
|
||||||
|
|
||||||
|
@Mojo( name = "amp", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true,
|
||||||
|
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME )
|
||||||
|
@Component( role = org.apache.maven.plugin.Mojo.class )
|
||||||
|
public class AmpMojo extends AbstractMojo {
|
||||||
|
|
||||||
|
private final Pattern modulePropertiesPattern = Pattern.compile("^alfresco/module/[^/]+/module\\.properties$");
|
||||||
|
private final int streamBufferSize = 16384;
|
||||||
|
|
||||||
|
@Parameter( defaultValue = "${project}", readonly = true )
|
||||||
|
protected MavenProject project;
|
||||||
|
|
||||||
|
@Parameter( defaultValue = "${session}", readonly = true )
|
||||||
|
protected MavenSession session;
|
||||||
|
|
||||||
|
@Requirement
|
||||||
|
private ProjectDependenciesResolver resolver;
|
||||||
|
|
||||||
|
@Parameter( property = "outputFile", required = true, defaultValue = "${project.build.directory}/${project.artifactId}-${project.version}.amp" )
|
||||||
|
protected String outputAmpFile;
|
||||||
|
|
||||||
|
@Parameter( property = "moduleFile", required = true, defaultValue = "${project.build.directory}/${project.build.finalName}.${project.artifact.type}" )
|
||||||
|
protected String moduleJarFile;
|
||||||
|
|
||||||
|
@Parameter( property = "modulePropertyFile", required = false )
|
||||||
|
protected String modulePropFile;
|
||||||
|
|
||||||
|
@Parameter( property = "resources", required = false )
|
||||||
|
protected List<Resource> resources;
|
||||||
|
|
||||||
|
@Parameter( property = "dependencyIncludeScopes", required = true, defaultValue = "compile,runtime" )
|
||||||
|
protected String includeScopes;
|
||||||
|
|
||||||
|
@Parameter( property = "dependencyExclusions", required = false )
|
||||||
|
protected List<Exclusion> excludeDependencies;
|
||||||
|
|
||||||
|
@Parameter( property = "lib", required = false )
|
||||||
|
protected List<FileSet> libDirectories;
|
||||||
|
|
||||||
|
@Parameter( property = "charset", required = true, defaultValue = "utf-8" )
|
||||||
|
protected String charsetName;
|
||||||
|
|
||||||
|
@Parameter( property = "skip", required = true, defaultValue = "false" )
|
||||||
|
protected boolean skip;
|
||||||
|
|
||||||
|
public void execute() throws MojoExecutionException {
|
||||||
|
if (this.skip) {
|
||||||
|
this.getLog().debug("Skipped AMP packaging");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.getLog().debug("Executing AMP packaging");
|
||||||
|
|
||||||
|
this.normalize();
|
||||||
|
|
||||||
|
File ampFile = this.getOutputFile();
|
||||||
|
this.getLog().debug("Writing AMP file: " + ampFile.getAbsolutePath());
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileOutputStream fostream = new FileOutputStream(ampFile, false);
|
||||||
|
BufferedOutputStream bostream = new BufferedOutputStream(fostream, this.streamBufferSize);
|
||||||
|
ZipOutputStream zstream = new ZipOutputStream(bostream, Charset.forName(this.charsetName));
|
||||||
|
try {
|
||||||
|
this.zip(zstream);
|
||||||
|
|
||||||
|
zstream.finish();
|
||||||
|
} finally {
|
||||||
|
zstream.close();
|
||||||
|
}
|
||||||
|
} catch (DependencyResolutionException dre) {
|
||||||
|
throw new MojoExecutionException("The dependencies could not be properly resolved", dre);
|
||||||
|
} catch (IOException ie) {
|
||||||
|
throw new MojoExecutionException("An I/O issue occurred", ie);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getLog().debug("Wrote AMP file: " + ampFile.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalize() {
|
||||||
|
this.outputAmpFile = StringUtils.trimToNull(this.outputAmpFile);
|
||||||
|
this.moduleJarFile = StringUtils.trimToNull(this.moduleJarFile);
|
||||||
|
this.modulePropFile = StringUtils.trimToNull(this.modulePropFile);
|
||||||
|
if (this.resources == null)
|
||||||
|
this.resources = Collections.emptyList();
|
||||||
|
this.includeScopes = this.includeScopes.trim();
|
||||||
|
if (this.libDirectories == null)
|
||||||
|
this.libDirectories = Collections.emptyList();
|
||||||
|
|
||||||
|
this.getLog().debug("Normalized parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getOutputFile() {
|
||||||
|
File ampFile = new File(this.outputAmpFile);
|
||||||
|
if (ampFile.exists())
|
||||||
|
ampFile.delete();
|
||||||
|
return ampFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getModuleFile() throws MojoExecutionException {
|
||||||
|
File jarFile = new File(this.moduleJarFile);
|
||||||
|
if (!jarFile.exists())
|
||||||
|
throw new MojoExecutionException("The module JAR file does not exist: " + this.moduleJarFile);
|
||||||
|
return jarFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getModulePropertyFile() throws MojoExecutionException {
|
||||||
|
File propFile = null;
|
||||||
|
if (this.modulePropFile != null) {
|
||||||
|
propFile = new File(this.modulePropFile);
|
||||||
|
} else {
|
||||||
|
String outputDirectory = this.project.getBuild().getOutputDirectory();
|
||||||
|
File modulesDirectory = new File(outputDirectory, "alfresco/module");
|
||||||
|
if (!modulesDirectory.exists() || !modulesDirectory.isDirectory())
|
||||||
|
throw new MojoExecutionException("The module.properties file could not be found: 'alfresco/module' path does not exist");
|
||||||
|
|
||||||
|
File moduleDirectory = new File(modulesDirectory, this.project.getGroupId() + "." + this.project.getArtifactId());
|
||||||
|
if (!moduleDirectory.exists())
|
||||||
|
moduleDirectory = new File(modulesDirectory, this.project.getArtifactId());
|
||||||
|
if (!moduleDirectory.exists()) {
|
||||||
|
File[] files = modulesDirectory.listFiles();
|
||||||
|
if (files.length > 0) {
|
||||||
|
moduleDirectory = files[0];
|
||||||
|
if (!moduleDirectory.exists())
|
||||||
|
throw new MojoExecutionException("The module.properties file could not be found: 'alfresco/module' path does not exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
propFile = new File(moduleDirectory, "module.properties");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!propFile.exists())
|
||||||
|
throw new MojoExecutionException("The module.properties file does not exist: " + propFile.getAbsolutePath());
|
||||||
|
return propFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zip(ZipOutputStream zstream) throws IOException, MojoExecutionException, DependencyResolutionException {
|
||||||
|
for (Resource resource : this.resources)
|
||||||
|
this.zipResource(zstream, resource);
|
||||||
|
|
||||||
|
File jarFile = this.getModuleFile();
|
||||||
|
this.zipFile(zstream, jarFile, "lib");
|
||||||
|
|
||||||
|
File propFile = this.getModulePropertyFile();
|
||||||
|
this.zipFile(zstream, propFile, "");
|
||||||
|
|
||||||
|
Collection<Dependency> deps = this.getDependencies();
|
||||||
|
if (deps.isEmpty()) {
|
||||||
|
this.getLog().info("Zipped 0 dependencies");
|
||||||
|
} else {
|
||||||
|
for (Dependency dependency : deps) {
|
||||||
|
File file = dependency.getArtifact().getFile();
|
||||||
|
if (this.isAlfrescoModule(file)) {
|
||||||
|
this.getLog().info("Not packaging JAR; detected as Alfresco JAR Module: " + dependency.getArtifact().getArtifactId());
|
||||||
|
} else {
|
||||||
|
this.zipFile(zstream, file, "lib");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.getLog().isInfoEnabled())
|
||||||
|
this.getLog().info("Zipped " + deps.size() + " dependencies");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FileSet fileset : this.libDirectories)
|
||||||
|
this.zipFileset(zstream, fileset, "lib");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getExclusions() {
|
||||||
|
List<String> exclusions = new ArrayList<>(this.excludeDependencies.size());
|
||||||
|
for (Exclusion exclusion : this.excludeDependencies)
|
||||||
|
exclusions.add(exclusion.getGroupId() + ":" + exclusion.getArtifactId());
|
||||||
|
return exclusions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<Dependency> getDependencies() throws DependencyResolutionException {
|
||||||
|
String[] includeScopes = StringUtils.split(this.includeScopes, ",");
|
||||||
|
|
||||||
|
ScopeDependencyFilter scopeFilter = new ScopeDependencyFilter(Arrays.asList(includeScopes), new ArrayList<String>(0));
|
||||||
|
ExclusionsDependencyFilter exclusionFilter = new ExclusionsDependencyFilter(this.getExclusions());
|
||||||
|
|
||||||
|
DependencyResolutionRequest request = new DefaultDependencyResolutionRequest(this.project, this.session.getRepositorySession());
|
||||||
|
request.setResolutionFilter(DependencyFilterUtils.andFilter(scopeFilter, exclusionFilter));
|
||||||
|
|
||||||
|
DependencyResolutionResult result = this.resolver.resolve(request);
|
||||||
|
return result.getResolvedDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zipResource(ZipOutputStream zstream, Resource resource) throws MojoExecutionException, IOException {
|
||||||
|
String baseZipPath = resource.getTargetPath();
|
||||||
|
if (baseZipPath == null)
|
||||||
|
baseZipPath = "";
|
||||||
|
else if (!baseZipPath.endsWith("/"))
|
||||||
|
baseZipPath += "/";
|
||||||
|
this.zipFileset(zstream, resource, baseZipPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zipFileset(ZipOutputStream zstream, FileSet fileset, String targetPath) throws MojoExecutionException, IOException {
|
||||||
|
targetPath = StringUtils.trimToEmpty(targetPath);
|
||||||
|
if (targetPath.length() > 0 && !targetPath.endsWith("/"))
|
||||||
|
targetPath += "/";
|
||||||
|
|
||||||
|
File directory = new File(this.project.getBasedir(), fileset.getDirectory());
|
||||||
|
if (!directory.exists())
|
||||||
|
return;
|
||||||
|
if (!directory.isDirectory())
|
||||||
|
throw new MojoExecutionException("The fileset 'directory' must be a directory: " + fileset.getDirectory());
|
||||||
|
|
||||||
|
String includes = StringUtils.join(fileset.getIncludes(), ",");
|
||||||
|
String excludes = StringUtils.join(fileset.getExcludes(), ",");
|
||||||
|
List<String> filenames = FileUtils.getFileNames(directory, includes, excludes, false, true);
|
||||||
|
|
||||||
|
if (this.getLog().isDebugEnabled())
|
||||||
|
this.getLog().debug("Zipping files in: " + fileset.getDirectory());
|
||||||
|
for (String filename : filenames) {
|
||||||
|
if (this.getLog().isDebugEnabled())
|
||||||
|
this.getLog().debug("Zipping file: " + filename);
|
||||||
|
|
||||||
|
zstream.putNextEntry(new ZipEntry(filename));
|
||||||
|
|
||||||
|
File file = new File(directory, filename);
|
||||||
|
FileReader freader = new FileReader(file);
|
||||||
|
try {
|
||||||
|
IOUtil.copy(freader, zstream);
|
||||||
|
} finally {
|
||||||
|
freader.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
zstream.closeEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.getLog().isInfoEnabled())
|
||||||
|
this.getLog().info("Zipped " + filenames.size() + " files: " + fileset.getDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zipFile(ZipOutputStream zstream, File file, String targetPath) throws IOException {
|
||||||
|
targetPath = StringUtils.trimToEmpty(targetPath);
|
||||||
|
if (targetPath.length() > 0 && !targetPath.endsWith("/"))
|
||||||
|
targetPath += "/";
|
||||||
|
|
||||||
|
if (this.getLog().isDebugEnabled())
|
||||||
|
this.getLog().debug("Zipping file: " + file.toString());
|
||||||
|
|
||||||
|
zstream.putNextEntry(new ZipEntry(targetPath + file.getName()));
|
||||||
|
|
||||||
|
FileReader freader = new FileReader(file);
|
||||||
|
try {
|
||||||
|
IOUtil.copy(freader, zstream);
|
||||||
|
} finally {
|
||||||
|
freader.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
zstream.closeEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAlfrescoModule(File file) throws IOException {
|
||||||
|
FileInputStream fistream = new FileInputStream(file);
|
||||||
|
BufferedInputStream bistream = new BufferedInputStream(fistream, this.streamBufferSize);
|
||||||
|
ZipInputStream zstream = new ZipInputStream(bistream, Charset.forName(this.charsetName));
|
||||||
|
try {
|
||||||
|
ZipEntry zentry = zstream.getNextEntry();
|
||||||
|
while (zentry != null) {
|
||||||
|
this.getLog().debug("dep entry: " + zentry.getName());
|
||||||
|
try {
|
||||||
|
Matcher modPropsMatcher = this.modulePropertiesPattern.matcher(zentry.getName());
|
||||||
|
if (modPropsMatcher.find())
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
zstream.closeEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
zentry = zstream.getNextEntry();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
zstream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user