/****************************************************************************** | |
* 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); | |
} | |
} | |
} |