/*
* Copyright (c) 2009-2015
* IT-Consulting Stephan Schloepke (http://www.schloepke.de/)
* klemm software consulting Mirko Klemm (http://www.klemm-scs.com/)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jbasics.versionmanager;
import org.jbasics.checker.ContractCheck;
import org.jbasics.configuration.properties.SystemProperty;
import org.jbasics.enviroment.JVMEnviroment;
import org.jbasics.pattern.resolver.Resolver;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MavenVersionResolver implements Resolver<VersionInformation, VersionIdentifier> {
public static final String MAVEN_POM_PROPERTY_FORMAT = "META-INF/maven/%1$s/%2$s/pom.properties"; //$NON-NLS-1$
public static final String MAVEN_GROUP_PROPERTY = "groupId"; //$NON-NLS-1$
public static final String MAVEN_ARTIFACT_PROPERTY = "artifactId"; //$NON-NLS-1$
public static final String MAVEN_VERSION_PROPERTY = "version"; //$NON-NLS-1$
public static final SystemProperty<Boolean> MAVEN_STRICT_MODE = SystemProperty.booleanProperty(MavenVersionResolver.class.getName()
+ ".strictMode", Boolean.FALSE); //$NON-NLS-1$
private static final Logger LOGGER = Logger.getLogger(MavenVersionResolver.class.getName());
private static final String WEB_INF_CLASES_RESOURCE = "WEB-INF/classes"; //$NON-NLS-1$
@Override
public VersionInformation resolve(final VersionIdentifier request, final VersionInformation defaultResult) {
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINE)) {
MavenVersionResolver.LOGGER.log(Level.FINE, "Trying to resolve version information for {0}", request); //$NON-NLS-1$
}
final Properties props = loadProperties(request);
if (props == null) {
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINE)) {
MavenVersionResolver.LOGGER.log(Level.FINE, "Could not resolve any version information for {0}", request); //$NON-NLS-1$
}
return defaultResult;
}
if (MavenVersionResolver.MAVEN_STRICT_MODE.value().booleanValue()) {
final String tempGroup = props.getProperty(MavenVersionResolver.MAVEN_GROUP_PROPERTY, request.getGroup()).trim();
final String tempArtifact = props.getProperty(MavenVersionResolver.MAVEN_ARTIFACT_PROPERTY, request.getArtifact()).trim();
if (!request.getGroup().equals(tempGroup) || !request.getArtifact().equals(tempArtifact)) {
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINE)) {
MavenVersionResolver.LOGGER.log(Level.FINE,
"The found version information for {0} does not match with its stored location (strict mode is on)", request); //$NON-NLS-1$
}
return defaultResult;
}
}
final String version = props.getProperty(MavenVersionResolver.MAVEN_VERSION_PROPERTY);
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINE)) {
MavenVersionResolver.LOGGER.log(Level.FINE, "Found version information for {0} with version", new Object[]{request, version}); //$NON-NLS-1$
}
return new VersionInformation(request, version);
}
private Properties loadProperties(final VersionIdentifier request) {
final String resourceName = String.format(MavenVersionResolver.MAVEN_POM_PROPERTY_FORMAT, request.getGroup(), request.getArtifact());
Properties result = tryToLoadProperties(JVMEnviroment.getResource(resourceName));
if (result == null) {
for (final URL jarUrl : JVMEnviroment.getClassPathList()) {
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINEST)) {
MavenVersionResolver.LOGGER.log(Level.FINEST, "Checking classpath element {0}", jarUrl); //$NON-NLS-1$
}
String temp = jarUrl.toExternalForm();
if (temp.matches(".*\\.(jar|war|ear|ejb|par|zip)$")) {
temp = "jar:" + temp + "!/";
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINEST)) {
MavenVersionResolver.LOGGER.log(Level.FINEST, "Found a jar/zip type changing url to {0}", temp); //$NON-NLS-1$
}
} else if (temp.endsWith(MavenVersionResolver.WEB_INF_CLASES_RESOURCE)) {
temp = temp.substring(0, temp.length() - MavenVersionResolver.WEB_INF_CLASES_RESOURCE.length());
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINEST)) {
MavenVersionResolver.LOGGER.log(Level.FINEST, "Found a war classes location changing to {0}", temp); //$NON-NLS-1$
}
}
temp = temp + resourceName;
try {
result = tryToLoadProperties(new URL(temp));
if (result != null) {
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINEST)) {
MavenVersionResolver.LOGGER.log(Level.FINEST, "We found and loaded the properties from {0}", temp); //$NON-NLS-1$
}
break;
}
} catch (final Exception e) {
// we ignore this
}
}
}
return result;
}
private Properties tryToLoadProperties(final URL resourceURL) {
if (MavenVersionResolver.LOGGER.isLoggable(Level.FINEST)) {
MavenVersionResolver.LOGGER.log(Level.FINEST, "Trying to load properties from url {0}", resourceURL); //$NON-NLS-1$
}
if (resourceURL == null) {
return null;
}
final Properties props = new Properties();
InputStream inp = null;
try {
inp = ContractCheck.mustNotBeNull(resourceURL, "resourceURL").openStream(); //$NON-NLS-1$
if (inp != null) {
props.load(inp);
return props;
}
return null;
} catch (final Exception e) {
return null;
} finally {
if (inp != null) {
try {
inp.close();
} catch (final IOException e) {
// silently ignore close problems
// we want to log here what happened
}
}
}
}
}