blob: f3ec001a0d6546cfd5d95a8a18981966a1591413 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc., Oracle Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
* Oracle Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.test.provisioning.internal;
import java.io.File;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.gemini.blueprint.test.provisioning.ArtifactLocator;
import org.springframework.beans.factory.xml.DefaultDocumentLoader;
import org.springframework.beans.factory.xml.DocumentLoader;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.util.xml.DomUtils;
import org.springframework.util.xml.XmlValidationModeDetector;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/**
* Locator for artifacts found in the local maven repository. Does <strong>not</strong>
* use Maven libraries, it rather uses the maven patterns and conventions to
* identify the artifacts.
*
* @author Hal Hildebrand
* @author Costin Leau
*
*/
public class LocalFileSystemMavenRepository implements ArtifactLocator {
private static final char SLASH_CHAR = '/';
private static final String LOCAL_REPOSITORY_ELEM = "localRepository";
private static final Log log = LogFactory.getLog(LocalFileSystemMavenRepository.class);
/** local repo system property */
private static final String SYS_PROPERTY = LOCAL_REPOSITORY_ELEM;
/** user home system property */
private static final String USER_HOME_PROPERTY = "user.home";
/** m2 local user settings */
private static final String M2_DIR = ".m2";
/** maven settings xml */
private static final String M2_SETTINGS = M2_DIR.concat("/settings.xml");
/** default local repository */
private static final String DEFAULT_DIR = M2_DIR.concat("/repository");
/** discovered local m2 repository home */
private String repositoryHome;
/**
* Initialization method It determines the repository path by checking the
* existence of <code>localRepository</code> system property and falling
* back to the <code>settings.xml</code> file and then the traditional
* <code>user.home/.m2/repository</code>.
*
* <p/> This method is used to postpone initialization until an artifact is
* actually located. As the test class is instantiated on each test run, the
* init() method prevents repetitive, waste-less initialization.
*
*/
private void init() {
// already discovered a repository home, bailing out
if (repositoryHome != null) {
return;
}
boolean trace = log.isDebugEnabled();
final String[] sysProperties = new String[2];
// check system property
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
sysProperties[0] = System.getProperty(SYS_PROPERTY);
sysProperties[1] = System.getProperty(USER_HOME_PROPERTY);
return null;
}
});
String localRepository = sysProperties[0];
String userHome = sysProperties[1];
if (trace) {
log.trace("M2 system property [" + SYS_PROPERTY + "] has value=" + localRepository);
}
if (localRepository == null) {
// if it's not present then check settings.xml local repository property
Resource settingsFile = new FileSystemResource(new File(userHome, M2_SETTINGS));
localRepository = getMavenSettingsLocalRepository(settingsFile);
if (trace) {
log.trace("Falling back to M2 settings.xml [" + settingsFile + "]; found value=" + localRepository);
}
if (localRepository == null) {
// fall back to the default location
localRepository = new File(userHome, DEFAULT_DIR).getAbsolutePath();
if (trace) {
log.trace("No custom setting found; using default M2 local repository=" + localRepository);
}
}
}
repositoryHome = localRepository;
log.info("Local Maven2 repository used: [" + repositoryHome + "]");
}
/**
* Returns the <code>localRepository</code> settings as indicated by the
* <code>settings.xml</code> file.
*
* @return local repository as indicated by a Maven settings.xml file
*/
String getMavenSettingsLocalRepository(Resource m2Settings) {
// no file found, return null to continue the discovery process
if (!m2Settings.exists()) {
return null;
}
try {
DocumentLoader docLoader = new DefaultDocumentLoader();
Document document = docLoader.loadDocument(new InputSource(m2Settings.getInputStream()), null, null,
XmlValidationModeDetector.VALIDATION_NONE, false);
return (DomUtils.getChildElementValueByTagName(document.getDocumentElement(), LOCAL_REPOSITORY_ELEM));
} catch (Exception ex) {
throw new RuntimeException(new ParserConfigurationException("error parsing resource=" + m2Settings).initCause(ex));
}
}
/**
* Find a local maven artifact. First tries to find the resource as a
* packaged artifact produced by a local maven build, and if that fails will
* search the local maven repository.
*
* @param groupId - the groupId of the organization supplying the bundle
* @param artifactId - the artifact id of the bundle
* @param version - the version of the bundle
* @return the String representing the URL location of this bundle
*/
public Resource locateArtifact(String groupId, String artifactId, String version) {
return locateArtifact(groupId, artifactId, version, DEFAULT_ARTIFACT_TYPE);
}
/**
* Find a local maven artifact. First tries to find the resource as a
* packaged artifact produced by a local maven build, and if that fails will
* search the local maven repository.
*
* @param groupId - the groupId of the organization supplying the bundle
* @param artifactId - the artifact id of the bundle
* @param version - the version of the bundle
* @param type - the extension type of the artifact
* @return located artifact
*/
public Resource locateArtifact(final String groupId, final String artifactId, final String version, final String type) {
init();
return (Resource) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
try {
return localMavenBuildArtifact(groupId, artifactId, version, type);
}
catch (IllegalStateException illStateEx) {
Resource localMavenBundle = localMavenBundle(groupId, artifactId, version, type);
if (log.isDebugEnabled()) {
String buf = "[" + groupId + "|" + artifactId + "|" + version + "]";
log.debug(buf
+ " local maven build artifact detection failed, falling back to local maven bundle "
+ localMavenBundle.getDescription());
}
return localMavenBundle;
}
}
});
}
/**
* Return the resource of the indicated bundle in the local Maven repository
*
* @param groupId - the groupId of the organization supplying the bundle
* @param artifact - the artifact id of the bundle
* @param version - the version of the bundle
* @return
*/
protected Resource localMavenBundle(String groupId, String artifact, String version, String type) {
StringBuilder location = new StringBuilder(groupId.replace('.', SLASH_CHAR));
location.append(SLASH_CHAR).append(artifact).append(SLASH_CHAR).append(version).append(SLASH_CHAR)
.append(artifact).append('-').append(version).append(".").append(type);
return new FileSystemResource(new File(repositoryHome, location.toString()));
}
/**
* Find a local maven artifact in the current build tree. This searches for
* resources produced by the package phase of a maven build.
*
* @param artifactId
* @param version
* @param type
* @return
*/
protected Resource localMavenBuildArtifact(String groupId, String artifactId, String version, String type) {
try {
File found = new MavenPackagedArtifactFinder(groupId, artifactId, version, type).findPackagedArtifact(new File("."));
Resource res = new FileSystemResource(found);
if (log.isDebugEnabled()) {
log.debug("[" + artifactId + "|" + version + "] resolved to " + res.getDescription() + " as a local maven artifact");
}
return res;
}
catch (IOException ioEx) {
throw (RuntimeException) new IllegalStateException("Artifact " + artifactId + "-" + version + "." + type
+ " could not be found").initCause(ioEx);
}
}
}