blob: 091d42684fb988c2ab0f241f2363f4bfc119c2cd [file] [log] [blame]
/*
* 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.jackrabbit.filevault.maven.packaging;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.jar.JarFile;
import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
import org.apache.jackrabbit.vault.util.Constants;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
/**
* Common ancestor of all mojos dealing with package metadata.
*/
public abstract class AbstractMetadataPackageMojo extends AbstractMojo {
private static final String PROPERTIES_EMBEDDEDFILESMAP_KEY = "embeddedfiles.map";
protected static File getFirstExistingDirectory(File[] directories) {
for (File dir: directories) {
if (dir.exists() && dir.isDirectory()) {
return dir;
}
}
return null;
}
/**
* The Maven project.
*/
@Parameter(property = "project", readonly = true, required = true)
protected MavenProject project;
/**
* The directory that contains the META-INF/vault. Multiple directories can be specified as a comma separated list,
* which will act as a search path and cause the plugin to look for the first existing directory.
* <p>
* This directory is added as fileset to the package archiver before the the {@link #workDirectory}. This means that
* files specified in this directory have precedence over the one present in the {@link #workDirectory}. For example,
* if this directory contains a {@code properties.xml} it will not be overwritten by the generated one. A special
* case is the {@code filter.xml} which will be merged with inline filters if present.
*/
@Parameter(property = "vault.metaInfVaultDirectory", required = true, defaultValue = "${project.basedir}/META-INF/vault,"
+ "${project.basedir}/src/main/META-INF/vault," + "${project.basedir}/src/main/content/META-INF/vault,"
+ "${project.basedir}/src/content/META-INF/vault")
File[] metaInfVaultDirectory;
/**
* The directory containing the metadata to be packaged up into the content package.
* Basically containing all files/folders being generated by goal "generate-metadata".
*/
@Parameter(
defaultValue = "${project.build.directory}/vault-work",
required = true)
File workDirectory;
/**
* Adds a path prefix to all resources. Useful for shallower source trees.
* This does not apply to files in {@link #workDirectory} nor {@link #metaInfVaultDirectory}
* but e.g. is relevant for the default filter and for the jcr_root of the package.
* Must start with "/" if not empty. As separator only forward slashes are allowed.
* The trailing slash is automatically appended if not there.
*/
@Parameter(property = "vault.prefix", defaultValue = "")
String prefix = "";
/**
* Timestamp for reproducible output archive entries, either formatted as ISO 8601
* <code>yyyy-MM-dd'T'HH:mm:ssXXX</code> or as an int representing seconds since the epoch (like
* <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
*
* @since 1.1.0
*/
@Parameter( defaultValue = "${project.build.outputTimestamp}" )
protected String outputTimestamp;
public void setPrefix(String prefix) {
if (prefix.startsWith("/")) {
throw new IllegalArgumentException("Parameter 'prefix' must start with a slash!");
}
if (prefix.length() > 0 && !prefix.endsWith("/")) {
prefix += "/";
}
this.prefix = prefix;
}
/**
* Sets the map of embedded files as project properties as a helper to pass data between the goals
* @param embeddedFiles map of embedded files (key=destination file name, value = source file)
*/
@SuppressWarnings("unchecked")
void setEmbeddedFilesMap(Map<String, File> embeddedFiles) {
getPluginContext().put(PROPERTIES_EMBEDDEDFILESMAP_KEY, embeddedFiles);
}
/**
* Reads the map of embedded files from the project properties. This is a helper to pass data between the goals.
* @return the map of embedded files (key=destination file name, value = source file)
*/
@SuppressWarnings("unchecked")
Map<String, File> getEmbeddedFilesMap() {
Object value = getPluginContext().get(PROPERTIES_EMBEDDEDFILESMAP_KEY);
if (value == null) {
return Collections.emptyMap();
} else {
if (value instanceof Map<?,?>) {
return (Map<String, File>) value;
} else {
throw new IllegalStateException("The Maven property " + PROPERTIES_EMBEDDEDFILESMAP_KEY + " is not containing a Map but rather " + value.getClass());
}
}
}
/**
*
* @return the META-INF/vault directory below the {@link #workDirectory}
*/
File getGeneratedVaultDir() {
return new File(workDirectory, Constants.META_DIR);
}
File getGeneratedManifestFile() {
return new File(workDirectory, JarFile.MANIFEST_NAME);
}
File getGeneratedFilterFile() {
return new File(getGeneratedVaultDir(), Constants.FILTER_XML);
}
/**
*
* @return the first matching directory from the list given in {@link #metaInfVaultDirectory}
*/
protected File getMetaInfVaultSourceDirectory() {
return getMetaInfVaultSourceDirectory(metaInfVaultDirectory, getLog());
}
protected static File getMetaInfVaultSourceDirectory(File[] metaInfVaultDirectory, Log log) {
File metaInfDirectory = getFirstExistingDirectory(metaInfVaultDirectory);
if (metaInfDirectory != null) {
log.info("Using META-INF/vault from " + metaInfDirectory.getPath());
}
return metaInfDirectory;
}
Filters loadGeneratedFilterFile() throws IOException, ConfigurationException {
// load filters for further processing
Filters filters = new Filters();
filters.load(getGeneratedFilterFile());
return filters;
}
}