initial checkin

This commit is contained in:
2021-01-25 10:16:29 -05:00
commit 813c9c7ac0
3 changed files with 449 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# Maven
target
pom.xml.versionsBackup
# Eclipse
.settings
.project
.classpath

117
pom.xml Normal file
View 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>

View 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;
}
}