/*******************************************************************************
* Copyright (c) 2008 Pierre-Antoine Grégoire.
* 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
*
* Contributors:
* Pierre-Antoine Grégoire - initial API and implementation
*******************************************************************************/
package org.org.eclipse.dws.core.internal;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Comparator;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.JavaCore;
import org.org.eclipse.core.utils.platform.binding.BindingException;
import org.org.eclipse.core.utils.platform.tools.IOToolBox;
import org.org.eclipse.dws.core.internal.bridges.ProjectInteractionHelper;
import org.org.eclipse.dws.core.internal.configuration.AggregatedProperties;
import org.org.eclipse.dws.core.internal.model.DWSClasspathEntryDescriptor;
import org.org.eclipse.dws.core.internal.model.Pom;
import org.org.eclipse.dws.core.internal.model.PomCreationDescription;
import org.org.eclipse.dws.core.internal.model.PomDependency;
import org.org.eclipse.dws.core.internal.model.visitors.DependenciesHarvester;
import org.org.eclipse.dws.core.internal.model.visitors.PomDependenciesFilteringOptions;
import org.org.eclipse.dws.core.internal.model.visitors.PomDependenciesFilteringOptions.Filter;
import org.org.eclipse.dws.core.internal.model.visitors.PomDependenciesFilteringOptions.ScopeFilter;
import org.org.eclipse.dws.core.internal.xml.IXmlPomFileBinder;
import org.org.eclipse.dws.core.internal.xml.StaxPomFileBinder;
import org.org.repository.crawler.items.ICrawledRepositorySetup;
import org.org.repository.crawler.items.IHttpCrawledRepositorySetup;
import org.org.repository.crawler.maven2.model.ArtifactVersion;
/**
* The Class PomInteractionHelper.
*/
public final class PomInteractionHelper {
/**
* Instantiates a new pom interaction helper.
*/
private PomInteractionHelper() {
}
/**
* The Class PomInteractionException.
*/
public static class PomInteractionException extends RuntimeException {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -2793937229997215054L;
/**
* Instantiates a new pom interaction exception.
*/
public PomInteractionException() {
super();
}
/**
* Instantiates a new pom interaction exception.
*
* @param message
* the message
* @param cause
* the cause
*/
public PomInteractionException(String message, Throwable cause) {
super(message, cause);
}
/**
* Instantiates a new pom interaction exception.
*
* @param message
* the message
*/
public PomInteractionException(String message) {
super(message);
}
/**
* Instantiates a new pom interaction exception.
*
* @param cause
* the cause
*/
public PomInteractionException(Throwable cause) {
super(cause);
}
}
/**
* This method parses the.
*
* @param pomStream
* the pom stream
*
* @return the parsed pom description
*/
public static Pom parsePom(InputStream pomStream) {
IXmlPomFileBinder xmlPomFileBinder = new StaxPomFileBinder();
Pom pom = null;
try {
pom = xmlPomFileBinder.parsePomFile(pomStream);
} catch (BindingException e) {
throw new PomInteractionException("The inputStream for the POM could not be streamed with Stax.", e);
}
return pom;
}
/**
* Adds the pom dependencies to pom.
*
* @param pomStream
* the pom stream
* @param pomDependencies
* the pom dependencies
* @param pomEncoding
* the pom encoding
*
* @return the string
*/
public static String addPomDependenciesToPom(InputStream pomStream, Set<PomDependency> pomDependencies, String pomEncoding) {
String pomContent = null;
IXmlPomFileBinder xmlPomFileBinder = new StaxPomFileBinder();
try {
pomContent = xmlPomFileBinder.updatePom(pomStream, pomDependencies, pomEncoding);
} catch (BindingException e) {
throw new PomInteractionException("The inputStream for the POM could not be streamed with Stax.", e);
}
try {
pomStream.close();
} catch (IOException e) {
}
return pomContent;
}
/**
* Gets the pom stream.
*
* @param crawledRepositorySetup
* the repository setup
* @param pomURL
* the pom url
*
* @return the pom stream
*/
public static InputStream getPomStream(ICrawledRepositorySetup crawledRepositorySetup, URL pomURL) {
InputStream result = null;
try {
URLConnection connection = null;
if (crawledRepositorySetup instanceof IHttpCrawledRepositorySetup) {
IHttpCrawledRepositorySetup httpCrawledRepositorySetup = (IHttpCrawledRepositorySetup) crawledRepositorySetup;
if (httpCrawledRepositorySetup.getProxyHost() != null && !(httpCrawledRepositorySetup.getProxyHost().equals(""))) {
final Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(httpCrawledRepositorySetup.getProxyHost(), httpCrawledRepositorySetup.getProxyPort()));
connection = pomURL.openConnection(proxy);
} else {
connection = pomURL.openConnection(IOToolBox.determineProxy(pomURL));
}
} else {
connection = pomURL.openConnection(Proxy.NO_PROXY);
}
result = connection.getInputStream();
} catch (IOException e) {
throw new PomInteractionException("Impossible to get POM Stream.", e);
} catch (URISyntaxException e) {
throw new PomInteractionException("Impossible to get POM Stream. Bad URI.", e);
}
return result;
}
/**
* Checks if is classpath entry from same artifact.
*
* @param classpathEntry
* the classpath entry
* @param pomDependency
* the pom dependency
*
* @return true, if checks if is classpath entry from same artifact
*/
public static boolean isClasspathEntryFromSameArtifact(DWSClasspathEntryDescriptor classpathEntry, PomDependency pomDependency) {
String pathToParse = classpathEntry.getPath();
String artifactId = pomDependency.getArtifactId();
Pattern pattern = Pattern.compile(".+" + artifactId + "-(.+).jar");
Matcher matcher = pattern.matcher(pathToParse);
return matcher.matches();
}
/**
* Extract version if any.
*
* @param classpathEntry
* the classpath entry
* @param pomDependency
* the pom dependency
*
* @return the string
*/
public static String extractVersionIfAny(DWSClasspathEntryDescriptor classpathEntry, PomDependency pomDependency) {
String result = "";
String pathToParse = classpathEntry.getPath();
String artifactId = pomDependency.getArtifactId();
Pattern pattern = Pattern.compile(".+" + artifactId + "-(.+).jar");
Matcher matcher = pattern.matcher(pathToParse);
if (matcher.matches()) {
result = matcher.group(1);
result = formatToSnapshotIfNecessary(result);
} else {
result = null;
}
return result;
}
/**
* Format to snapshot if necessary.
*
* @param version
* the version
*
* @return the string
*/
public static String formatToSnapshotIfNecessary(String version) {
if (version.contains("-")) {
StringTokenizer tkz = new StringTokenizer(version, "-", false);
version = tkz.nextToken() + "-SNAPSHOT";
}
return version;
}
/**
* Format pom contents.
*
* @param pomContents
* the pom contents
*
* @return the string
*/
public static String formatPomContents(String pomContents) {
return pomContents.replace("\t", " ");
}
/**
* Gets the pom contents.
*
* @param groupId
* the group id
* @param artifactId
* the artifact id
* @param version
* the version
* @param packaging
* the packaging
*
* @return the pom contents
*/
public static String getPomContents(String groupId, String artifactId, String version, String packaging) {
StringBuilder contents = new StringBuilder();
contents.append("<?xml version=\"1.0\"?>\n");
contents.append("<project>\n");
contents.append("\t<modelVersion>4.0.0</modelVersion>\n");
contents.append("\t<groupId>" + (groupId == null ? "" : groupId) + "</groupId>\n");
contents.append("\t<artifactId>" + (artifactId == null ? "" : artifactId) + "</artifactId>\n");
contents.append("\t<version>" + (version == null ? "" : version) + "</version>\n");
contents.append("\t<packaging>" + (packaging == null ? "" : packaging) + "</packaging>\n");
contents.append("\t<dependencies>\n");
contents.append("\t\t<!-- insert your project's dependencies here-->\n");
contents.append("\t\t");
contents.append("\t</dependencies>\n");
contents.append("</project>");
return contents.toString();
}
/**
* Gets the pom contents.
*
* @param pomCreationDescription
* the pom creation description
*
* @return the pom contents
*/
public static String getPomContents(PomCreationDescription pomCreationDescription) {
StringBuilder contents = new StringBuilder();
contents.append("<?xml version=\"1.0\"?>\n");
contents.append("<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\"> \n");
contents.append("\t<modelVersion>4.0.0</modelVersion>\n");
contents.append("\t<groupId>" + (pomCreationDescription.getGroupId() == null ? "" : pomCreationDescription.getGroupId()) + "</groupId>\n");
contents.append("\t<artifactId>" + (pomCreationDescription.getArtifactId() == null ? "" : pomCreationDescription.getArtifactId()) + "</artifactId>\n");
contents.append("\t<version>" + (pomCreationDescription.getVersion() == null ? "" : pomCreationDescription.getVersion()) + "</version>\n");
contents.append("\t<packaging>" + (pomCreationDescription.getPackaging() == null ? "" : pomCreationDescription.getPackaging()) + "</packaging>\n");
contents.append("\t<dependencies>\n");
for (ArtifactVersion chosenDependency : pomCreationDescription.getChildren()) {
contents.append(PomInteractionHelper.toDependencyXML(chosenDependency));
}
contents.append("\t\t");
contents.append("\t\t<!-- insert your project's dependencies here-->\n");
contents.append("\t\t");
contents.append("\t</dependencies>\n");
contents.append("</project>");
return contents.toString();
}
/**
* Gets the exclusions.
*
* @param transitiveDependency
* the transitive dependency
* @param builder
* the builder
*
* @return the exclusions
*/
public static void getExclusions(PomDependency transitiveDependency, StringBuilder builder) {
builder.append("<dependency>\n");
builder.append("\t<groupId>" + transitiveDependency.getGroupId() + "</groupId>\n");
builder.append("\t<artifactId>" + transitiveDependency.getArtifactId() + "</artifactId>\n");
builder.append("\t<version>" + transitiveDependency.getVersion() + "</version>\n");
if (transitiveDependency.getClassifier() != null) {
builder.append("\t<classifier>" + transitiveDependency.getClassifier() + "</classifier>\n");
}
builder.append("\t<scope>compile</scope><!-- compile, test, provided,runtime or system-->\n");
if (transitiveDependency.hasChildren()) {
builder.append("\t<exclusions>\n");
DependenciesHarvester dependenciesHarvester = new DependenciesHarvester(transitiveDependency);
transitiveDependency.accept(dependenciesHarvester);
Set<PomDependency> allTransitiveDependencies = new TreeSet<PomDependency>(new Comparator<PomDependency>() {
public int compare(PomDependency o1, PomDependency o2) {
String o1Str = o1.getGroupId() + o1.getArtifactId();
String o2Str = o2.getGroupId() + o2.getArtifactId();
return o1Str.compareTo(o2Str);
}
});
allTransitiveDependencies.addAll(dependenciesHarvester.getDependencies());
for (PomDependency pomDependency : allTransitiveDependencies) {
builder.append("\t\t<exclusion>\n");
builder.append("\t\t\t<groupId>" + pomDependency.getGroupId() + "</groupId>\n");
builder.append("\t\t\t<artifactId>" + pomDependency.getArtifactId() + "</artifactId>\n");
builder.append("\t\t<exclusions>\n");
}
builder.append("\t</exclusions>\n");
} else {
builder.append("\t<!-- no transitive dependencies: no exclusions -->\n");
}
builder.append("</dependency>\n");
}
/**
* Gets the description.
*
* @param transitiveDependency
* the transitive dependency
* @param buffer
* the buffer
* @param tabs
* the tabs
*
* @return the description
*/
public static void getDescription(PomDependency transitiveDependency, StringBuilder buffer, StringBuilder tabs) {
buffer.append(tabs.toString() + getDescription(transitiveDependency) + "\n");
if (transitiveDependency.hasChildren()) {
tabs.append("----");
Set<PomDependency> orderedDependencies = new TreeSet<PomDependency>(new Comparator<PomDependency>() {
public int compare(PomDependency pomDependency1, PomDependency pomDependency2) {
int result = 0;
if (pomDependency1.getScope() != null && pomDependency2.getScope() != null) {
result = pomDependency1.getScope().compareTo(pomDependency2.getScope());
if (result == 0) {
result = pomDependency1.compareTo(pomDependency2);
}
} else {
result = pomDependency1.compareTo(pomDependency2);
}
return result;
}
});
orderedDependencies.addAll(transitiveDependency.getChildren());
for (PomDependency dependency : orderedDependencies) {
getDescription(dependency, buffer, tabs);
}
}
}
/**
* Gets the description.
*
* @param transitiveDependency
* the transitive dependency
*
* @return the description
*/
private static Object getDescription(PomDependency transitiveDependency) {
final String groupId = transitiveDependency.getGroupId();
final String artifactId = transitiveDependency.getArtifactId();
final String version = transitiveDependency.getVersion();
final String scope = transitiveDependency.getScope() == null ? "[NO SCOPE DEFINED]" : transitiveDependency.getScope().name().toLowerCase();
return groupId + ":" + artifactId + ":" + version + ":" + scope;
}
/**
* To dependency xml.
*
* @param artifactVersion
* the artifact version
*
* @return the string
*/
public static String toDependencyXML(ArtifactVersion artifactVersion) {
StringBuilder builder = new StringBuilder();
builder.append("<dependency>\n");
builder.append("\t<groupId>" + artifactVersion.getParent().getParent().getName() + "</groupId>\n");
builder.append("\t<artifactId>" + artifactVersion.getParent().getId() + "</artifactId>\n");
builder.append("\t<version>" + artifactVersion.getVersion() + "</version>\n");
if (artifactVersion.getClassifier() != null) {
builder.append("\t<classifier>" + artifactVersion.getClassifier() + "</classifier>\n");
}
builder.append("\t<scope>compile</scope><!-- compile, test, provided,runtime or system-->\n");
builder.append("</dependency>\n");
return builder.toString();
}
/**
* Gets the parsed pom description.
*
* @param selectedFile
* the selected file
*
* @return the parsed pom description
*
* @throws WizardInitException
* the wizard init exception
*/
public static Pom getParsedPomDescription(IFile selectedFile) throws PomInteractionException {
Pom pom;
try {
pom = parsePom(selectedFile.getContents());
} catch (CoreException e) {
throw new PomInteractionException(e);
}
return pom;
}
/**
* Prepare options.
*
* @param project
* the project
*
* @return the filtering options
*/
public static PomDependenciesFilteringOptions preparePomDependenciesFilteringOptions(IProject project) {
PomDependenciesFilteringOptions.Builder optionsBuilder = new PomDependenciesFilteringOptions.Builder();
optionsBuilder.projectClasspathEntries(ProjectInteractionHelper.getClasspathEntries(JavaCore.create(project)));
optionsBuilder.scopeFilter(ScopeFilter.NONE);
optionsBuilder.filter(Filter.NONE);
optionsBuilder.dealWithTransitive(AggregatedProperties.getDealWithTransitive(project));
optionsBuilder.dealWithOptional(AggregatedProperties.getDealWithOptional(project));
optionsBuilder.dealWithNarrow(AggregatedProperties.getDealWithNarrow(project));
optionsBuilder.skippedDependencies(AggregatedProperties.getSkippedDependencies(project));
optionsBuilder.artifactExtensions(AggregatedProperties.getArtifactExtensions());
PomDependenciesFilteringOptions filteringOptions = optionsBuilder.build();
return filteringOptions;
}
}