/*******************************************************************************
* Copyright 2011 Google Inc. All Rights Reserved.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* 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 com.google.gdt.eclipse.maven;
import com.google.gdt.eclipse.core.StringUtilities;
import com.google.gdt.eclipse.core.natures.NatureUtils;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
/**
* A set of utilities for dealing with paths to Maven artifacts.
*/
public class MavenUtils {
/**
* A class to hold Maven-related information about a given artifact.
*/
public static class MavenInfo {
private static final int VERSION_INDEX_FROM_END_OF_MAVEN_PATH = 1;
private static final int ARTIFACTID_INDEX_FROM_END_OF_MAVEN_PATH = 2;
private static final int NUM_SEGMENTS_IN_ARTIFACTID = 1;
private static final int NUM_SEGMENTS_IN_VERSION = 1;
// The +1 is for the file name at the end of the Maven path
private static final int NUM_TRAILING_SEGMENTS_AFTER_GROUP_ID = NUM_SEGMENTS_IN_ARTIFACTID
+ NUM_SEGMENTS_IN_VERSION + 1;
/**
* Creates a MavenInfo instance based on the path to a Maven artifact in a local repository and
* the artifact's group id.
*
* @param artifactPath the path to the artifact in the user's local repository (e.g.,
* <code>/home/user/.m2/repository/com/google/gwt/gwt
* -user/2.1-SNAPSHOT/gwt-user-2.1-SNAPSHOT.jar</code>)
* @param groupId the group id of the artifact (e.g., <code>com.google.gwt</code>)
* @return an instance of MavenInfo, or null if one could not be found due to a mismatch between
* the group id and the artifact path
*/
public static MavenInfo create(IPath artifactPath, String groupId) {
if (artifactPath == null || artifactPath.isEmpty() || groupId == null
|| StringUtilities.isEmpty(groupId)) {
return null;
}
IPath groupPath = Path.fromPortableString(groupId.replace('.', '/'));
final int numTrailingSegmentsAfterRepositoryBase =
NUM_TRAILING_SEGMENTS_AFTER_GROUP_ID + groupPath.segmentCount();
if (artifactPath.segmentCount() <= numTrailingSegmentsAfterRepositoryBase) {
return null;
}
String artifactName = artifactPath.lastSegment();
String version =
artifactPath.segment(artifactPath.segmentCount() - VERSION_INDEX_FROM_END_OF_MAVEN_PATH
- 1);
String artifactId =
artifactPath.segment(artifactPath.segmentCount()
- ARTIFACTID_INDEX_FROM_END_OF_MAVEN_PATH - 1);
if (!artifactPath.removeLastSegments(NUM_TRAILING_SEGMENTS_AFTER_GROUP_ID)
.removeTrailingSeparator().toPortableString().endsWith(groupPath.toPortableString())) {
return null;
}
IPath repositoryPath =
artifactPath.removeLastSegments(numTrailingSegmentsAfterRepositoryBase);
return new MavenInfo(repositoryPath, groupId, artifactId, artifactName, version);
}
private final IPath repositoryPath;
private final String groupId;
private final String artifactId;
private final String artifactName;
private final String version;
protected MavenInfo(IPath repositoryPath, String groupId, String artifactId,
String artifactName, String version) {
this.repositoryPath = repositoryPath;
this.groupId = groupId;
this.artifactId = artifactId;
this.artifactName = artifactName;
this.version = version;
}
/**
* Returns anything that comes after the <code><artifact id>-<artifact version></code> prefix of
* an artifact's name, including any hyphens and file extensions. For example, for the artifact
* <code>gwt-dev-2.1-SNAPSHOT-javadoc.jar</code>, the artifactNameSuffix would be
* <code>-SNAPSHOT-javadoc.jar</code>.
*
* If there is a mismatch between the version of the artifact and the artifact's name, then the
* default suffix, <code>.jar</code> is returned.
*/
public String computeArtifactNameSuffix() {
int matchIndex = artifactName.indexOf(version);
if (matchIndex == -1 || matchIndex + version.length() >= artifactName.length()) {
return ".jar";
}
return artifactName.substring(matchIndex + version.length());
}
/**
* Returns the artifact id (e.g., <code>gwt-dev</code>).
*/
public String getArtifactId() {
return artifactId;
}
/**
* Returns the artifact's name (e.g., <code>gwt-dev-2.1-SNAPSHOT-javadoc.jar</code>).
*/
public String getArtifactName() {
return artifactName;
}
/**
* Returns the group id (e.g., <code>com.google.foo</code>).
*/
public String getGroupId() {
return groupId;
}
/**
* Returns the local repository path (e.g., <code>/home/user/.m2/repository</code>).
*/
public IPath getRepositoryPath() {
return repositoryPath;
}
/**
* Returns the version (e.g., 2.1, 2.1-SNAPSHOT).
*/
public String getVersion() {
return version;
}
}
public static final String OLD_MAVEN2_NATURE_ID = "org.maven.ide.eclipse.maven2Nature";
public static final String MAVEN2_NATURE_ID = "org.eclipse.m2e.core.maven2Nature";
/**
* Generates the absolute path to an artifact in a local Maven repository, based on the parameters
* given.
*
* @param repositoryBase the path to the local repository (e.g.,
* <code>/home/user/.m2/repository</code>)
* @param groupId the group id of the artifact (e.g., <code>com.google.foo</code>)
* @param version the version of the artifact (e.g., <code>2.1, 2.1-SNAPSHOT</code>)
* @param artifactId the artifact id (e.g., <code>gwt-dev</code>)
* @param artifactNameSuffix anything that comes after the <code><artifact id>-<artifact
* version></code> prefix of an artifact's name, including any hyphens and file
* extensions. For example, for the artifact <code>gwt-dev-2.1-SNAPSHOT-javadoc.jar</code>,
* the artifactNameSuffix would be <code>-SNAPSHOT-javadoc.jar</code>.
*/
public static IPath generateArtifactPath(IPath repositoryBase, String groupId, String version,
String artifactId, String artifactNameSuffix) {
if (repositoryBase == null || repositoryBase.isEmpty()) {
return null;
}
if (StringUtilities.isEmpty(groupId) || StringUtilities.isEmpty(version)
|| StringUtilities.isEmpty(artifactId) || StringUtilities.isEmpty(artifactNameSuffix)) {
return null;
}
return repositoryBase.append(groupId.replace('.', '/')).append(artifactId).append(version)
.append(artifactId + '-' + version + artifactNameSuffix);
}
/**
* Given the path of an artifact in a local Maven repository and its group id, and the artifact id
* of a peer artifact, return the path in the local Maven repository of the peer artifact.
*
* For example, with a base artifact path of
* <code>/home/user/.m2/com/google/gwt/gwt-user/2.1/gwt-user-2.1.jar</code>, a group id of
* <code>com.google.gwt</code>, and a peer artifact id of <code>gwt-dev.jar</code>, the returned
* path would be <code>/home/user/.m2/com/google/gwt/gwt-dev/2.1/gwt-dev-2.1.jar</code>.
*/
public static IPath getArtifactPathForPeerMavenArtifact(IPath baseArtifactPath, String groupId,
String peerArtifactId) {
if (baseArtifactPath == null || baseArtifactPath.isEmpty()) {
return null;
}
if (StringUtilities.isEmpty(groupId)) {
return null;
}
if (StringUtilities.isEmpty(peerArtifactId)) {
return null;
}
MavenInfo baseArtifactInfo = MavenInfo.create(baseArtifactPath, groupId);
if (baseArtifactInfo == null) {
return null;
}
return generateArtifactPath(baseArtifactInfo.getRepositoryPath(), groupId,
baseArtifactInfo.getVersion(), peerArtifactId, baseArtifactInfo.computeArtifactNameSuffix());
}
/**
* Returns <code>true</code> if the given project has the Maven 2 nature. This checks for the old
* maven nature (till m2Eclipse 0.12) and the new Maven nature (m2Eclipse 1.0.0 and up).
*/
public static boolean hasMavenNature(IProject project) {
try {
if (NatureUtils.hasNature(project, MavenUtils.MAVEN2_NATURE_ID)) {
return true;
}
if (NatureUtils.hasNature(project, MavenUtils.OLD_MAVEN2_NATURE_ID)) {
return true;
}
} catch (CoreException ce) {
Activator
.getDefault()
.getLog()
.log(
new Status(IStatus.ERROR, Activator.PLUGIN_ID,
"Unable to examine natures on project " + project.getName(), ce));
}
return false;
}
/**
* Returns <code>true</code> if the given project has the Spring nature.
*
* Technically, this should live in a Spring-specific plugin, but since the only Spring-specific
* functionality that we have is related to Maven, we can tuck it in here for now.
*/
public static boolean hasSpringNature(IProject project) {
try {
if (NatureUtils.hasNature(project, "org.springframework.ide.eclipse.core.springnature")) {
return true;
}
} catch (CoreException ce) {
Activator
.getDefault()
.getLog()
.log(
new Status(IStatus.ERROR, Activator.PLUGIN_ID,
"Unable to examine natures on project " + project.getName(), ce));
}
return false;
}
// Non-instantiatable utility class
private MavenUtils() {}
}