blob: afa68ef637b1fbda6aab8bf059e5f9734e5763f9 [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
*
* https://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.ivy.plugins.resolver.packager;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.ivy.core.module.descriptor.Artifact;
import org.apache.ivy.core.module.descriptor.DefaultArtifact;
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.plugins.resolver.URLResolver;
import org.apache.ivy.plugins.resolver.util.ResolvedResource;
import org.apache.ivy.util.FileUtil;
import org.apache.ivy.util.Message;
/**
* Resolver that performs a "build" operation to resolve artifacts.
*
* <p>
* The resolver is configured with a base URL, from which the "ivy.xml" and "packager.xml" files are
* resolved. The latter file contains instructions describing how to build the actual artifacts.
* </p>
*/
public class PackagerResolver extends URLResolver {
private static final String PACKAGER_ARTIFACT_NAME = "packager";
private static final String PACKAGER_ARTIFACT_TYPE = "packager";
private static final String PACKAGER_ARTIFACT_EXT = "xml";
private final Map<ModuleRevisionId, PackagerCacheEntry> packagerCache = new HashMap<>();
private File buildRoot;
private File resourceCache;
private String resourceURL;
private final Map<String, String> properties = new LinkedHashMap<>();
private boolean validate = true;
private boolean preserve;
private boolean restricted = true;
private boolean verbose;
private boolean quiet;
public PackagerResolver() {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
clearCache();
}
});
}
protected synchronized void clearCache() {
if (this.preserve) {
return;
}
for (PackagerCacheEntry entry : packagerCache.values()) {
entry.cleanup();
}
packagerCache.clear();
if (this.buildRoot != null) {
FileUtil.forceDelete(this.buildRoot);
}
}
/**
* Set root directory under which builds take place.
*
* @param buildRoot File
*/
public void setBuildRoot(File buildRoot) {
this.buildRoot = buildRoot;
}
/**
* Returns root directory under which builds take place.
*
* @return File
*/
public File getBuildRoot() {
return buildRoot;
}
/**
* Set resource cache directory.
*
* @param resourceCache File
*/
public void setResourceCache(File resourceCache) {
this.resourceCache = resourceCache;
}
/**
* Get resource cache directory.
*
* @return File
*/
public File getResourceCache() {
return resourceCache;
}
/**
* Set base resource override URL pattern.
*
* @param resourceURL String
*/
public void setResourceURL(String resourceURL) {
this.resourceURL = resourceURL;
}
/**
* Set pattern for locating "packager.xml" files.
*
* @param pattern String
*/
public void setPackagerPattern(String pattern) {
List<String> list = new ArrayList<>();
list.add(pattern);
setArtifactPatterns(list);
}
/**
* Set whether to preserve build directories. Default is false.
*
* @param preserve boolean
*/
public void setPreserveBuildDirectories(boolean preserve) {
this.preserve = preserve;
}
/**
* Set whether to enable restricted mode. Default is true.
*
* @param restricted boolean
*/
public void setRestricted(boolean restricted) {
this.restricted = restricted;
}
/**
* Set whether to run ant with the -verbose flag. Default is false.
*
* @param verbose boolean
*/
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
/**
* Set whether to run ant with the -quiet flag. Default is false.
*
* @param quiet boolean
*/
public void setQuiet(boolean quiet) {
this.quiet = quiet;
}
/**
* Set whether to validate downloaded packager.xml files. Default is true.
*
* @param validate boolean
*/
public void setValidate(boolean validate) {
this.validate = validate;
}
public void setAllownomd(boolean b) {
Message.error("allownomd not supported by resolver " + this);
}
public void setDescriptor(String rule) {
if (DESCRIPTOR_OPTIONAL.equals(rule)) {
Message.error("descriptor=\"" + DESCRIPTOR_OPTIONAL + "\" not supported by resolver "
+ this);
return;
}
super.setDescriptor(rule);
}
/**
* Sets a property to be passed to the child Ant build responsible for packaging the dependency.
*
* @param propertyKey
* the property to pass
* @param propertyValue
* the value of the property to pass
*/
public void setProperty(String propertyKey, String propertyValue) {
properties.put(propertyKey, propertyValue);
}
// @Override
public void validate() {
super.validate();
if (this.buildRoot == null) {
throw new IllegalStateException("no buildRoot specified");
}
if (getArtifactPatterns().size() == 0) {
throw new IllegalStateException("no packager pattern specified");
}
}
// @Override
public synchronized ResolvedResource findArtifactRef(Artifact artifact, Date date) {
// For our special packager.xml file, defer to superclass
if (PACKAGER_ARTIFACT_NAME.equals(artifact.getName())
&& PACKAGER_ARTIFACT_TYPE.equals(artifact.getType())
&& PACKAGER_ARTIFACT_EXT.equals(artifact.getExt())) {
return super.findArtifactRef(artifact, date);
}
// Check the cache
ModuleRevisionId mr = artifact.getModuleRevisionId();
PackagerCacheEntry entry = packagerCache.get(mr);
// Ignore invalid entries
if (entry != null && !entry.isBuilt()) {
packagerCache.remove(mr);
entry.cleanup();
entry = null;
}
// Build the artifacts (if not done already)
if (entry == null) {
ResolvedResource packager = findArtifactRef(new DefaultArtifact(mr, null,
PACKAGER_ARTIFACT_NAME, PACKAGER_ARTIFACT_TYPE, PACKAGER_ARTIFACT_EXT), date);
if (packager == null) {
return null;
}
entry = new PackagerCacheEntry(mr, this.buildRoot, this.resourceCache,
this.resourceURL, this.validate, this.preserve, this.restricted, this.verbose,
this.quiet);
try {
entry.build(packager.getResource(), properties);
} catch (IOException e) {
throw new RuntimeException("can't build artifact " + artifact, e);
}
packagerCache.put(mr, entry);
}
// Return reference to desired artifact
return entry.getBuiltArtifact(artifact);
}
public String getTypeName() {
return "packager";
}
}