diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d2f1eda --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +target +.idea +*.iml +*.ipr +*.iws \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9e186b5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2014 YANDEX + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..29b6bc2 --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +CLAY (Common LAYer module) +============= + +## Clay Maven Settings Builder + +Fluent-api builders for maven settings. + +```java +Settings settings = newSettings() + .withActiveProfile(newProfile() + .withId("profile") + .withRepository(newRepository() + .withUrl("http://repo1.maven.org/maven2"))).build(); +``` + +## Clay Aether + +Fluent-api for Eclipse Aether. Easy to resolve/collect/install/deploy artifacts. + +```java +//resolve with transitives +List results = aether(localRepositoryFile, settings) + .resolve("ru.yandex.qatools.allure:allure-model:jar:1.3.9").get(); +} + +//resolve without transitives +List results = aether(localRepositoryFile, settings) + .resolve("ru.yandex.qatools.allure:allure-model:jar:1.3.9", false); + +//resolve all given artifacts +List results = aether(localRepo, MAVEN_SETTINGS) + .resolveAll("ru.yandex.qatools.allure:allure-model:jar:1.3.9", + "ru.yandex.qatools.allure:allure-java-annotations:jar:1.3.9").get(); + +//collect +List artifacts = aether(localRepositoryFile, settings) + .collect("ru.yandex.qatools.allure:allure-model:jar:1.3.9"); + +//install +aether(localRepositoryFile, settings) + .install(archiveToDeploy, "testGroupId", "testArtifactId", "testVersion"); + +//deploy +aether(localRepositoryFile, settings) + .deploy(distributionManagement, archiveToDeploy, "testGroupId", "testArtifactId", "testVersion"); + + +``` + +Also you have few ways to get resolve results: + +```java +//as list of artifact results: +List results = aether(localRepositoryFile, settings) + .resolve("ru.yandex.qatools.allure:allure-model:jar:1.3.9").get(); + +//as array of urls: +URL[] urls = aether(localRepositoryFile, settings) + .resolve("ru.yandex.qatools.allure:allure-model:jar:1.3.9").getAsUrls(); + +//as class path: +String[] cp = aether(localRepositoryFile, settings) + .resolve("ru.yandex.qatools.allure:allure-model:jar:1.3.9").getAsClassPath(); + +//as ClassLoader: +ClassLoader cl = aether(localRepositoryFile, settings) + .resolve("ru.yandex.qatools.allure:allure-model:jar:1.3.9").getAsClassLoader(); +``` + +## Clay Utils + +Some useful tools, such as **ArchiveUtil** (configurable unpack jar's), **DateUtil** and **MapUtil**. diff --git a/clay-aether/pom.xml b/clay-aether/pom.xml new file mode 100644 index 0000000..460ad3e --- /dev/null +++ b/clay-aether/pom.xml @@ -0,0 +1,115 @@ + + + + clay + ru.yandex.qatools.clay + 2.0-SNAPSHOT + + 4.0.0 + + clay-aether + + Clay Aether + + + 1.0.0.v20140518 + 2.6 + 2.4 + + + + + + org.eclipse.aether + aether-api + ${aether.version} + + + org.eclipse.aether + aether-util + ${aether.version} + + + org.eclipse.aether + aether-impl + ${aether.version} + + + org.eclipse.aether + aether-connector-basic + ${aether.version} + + + org.eclipse.aether + aether-transport-file + ${aether.version} + + + org.eclipse.aether + aether-transport-http + ${aether.version} + + + org.eclipse.aether + aether-transport-wagon + ${aether.version} + + + + + org.apache.maven + maven-aether-provider + ${maven.version} + + + + + org.apache.maven.wagon + wagon-ssh + ${wagon.version} + + + org.apache.maven.wagon + wagon-file + ${wagon.version} + + + org.apache.maven.wagon + wagon-http + ${wagon.version} + + + org.apache.maven.wagon + wagon-http-lightweight + ${wagon.version} + + + + + ru.yandex.qatools.clay + clay-maven-settings-builder + + + + + commons-io + commons-io + ${commons-io.version} + + + + + junit + junit + 4.11 + test + + + org.apache.commons + commons-compress + 1.8.1 + test + + + + \ No newline at end of file diff --git a/clay-aether/src/main/java/ru/yandex/qatools/clay/Aether.java b/clay-aether/src/main/java/ru/yandex/qatools/clay/Aether.java new file mode 100644 index 0000000..0604ed5 --- /dev/null +++ b/clay-aether/src/main/java/ru/yandex/qatools/clay/Aether.java @@ -0,0 +1,402 @@ +package ru.yandex.qatools.clay; + +import org.apache.commons.io.FileUtils; +import org.apache.maven.model.DistributionManagement; +import org.apache.maven.settings.Settings; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.CollectResult; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.deployment.DeployRequest; +import org.eclipse.aether.deployment.DeploymentException; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.installation.InstallRequest; +import org.eclipse.aether.installation.InstallationException; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.resolution.DependencyResolutionException; +import org.eclipse.aether.util.artifact.JavaScopes; +import org.eclipse.aether.util.artifact.SubArtifact; +import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator; +import ru.yandex.qatools.clay.maven.settings.FluentModelBuilder; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static ru.yandex.qatools.clay.internal.AetherUtils.getRepositoriesAsList; +import static ru.yandex.qatools.clay.internal.AetherUtils.newRepositorySystem; +import static ru.yandex.qatools.clay.internal.AetherUtils.newSession; +import static ru.yandex.qatools.clay.internal.AetherUtils.toRemoteRepository; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 24.07.14 + */ +public class Aether { + + public static final String MAVEN_CENTRAL_URL = "http://repo1.maven.org/maven2"; + public static final String POM_EXTENSION = "pom"; + public static final String MODEL_VERSION = "4.0.0"; + public static final String JAR = "jar"; + + private RepositorySystemSession session; + private RepositorySystem system; + private List repositories; + + private String scope = JavaScopes.RUNTIME; + + Aether(File localRepoDir, Settings settings) { + this.system = newRepositorySystem(); + this.session = newSession(system, settings, localRepoDir); + this.repositories = getRepositoriesAsList(session, settings); + } + + Aether(RepositorySystem system, RepositorySystemSession session, List repositories) { + this.session = session; + this.system = system; + this.repositories = repositories; + } + + public static Aether aether(File localRepoDir) { + return aether(localRepoDir, null); + } + + public static Aether aether(File localRepoDir, Settings settings) { + return new Aether(localRepoDir, settings); + } + + public static Aether aether(RepositorySystem system, RepositorySystemSession session, List repositories) { + return new Aether(system, session, repositories); + } + + /** + * Using this method you can specify resolve scope, RUNTIME by default + * + * @param scope specified scope to resolving artifacts + */ + public Aether scope(String scope) { + this.scope = scope; + return this; + } + + /** + * Other way to run {@link #resolve(org.eclipse.aether.artifact.Artifact)} + * + * @param artifactCoordinates The artifact coordinates in the format + * {@code :[:[:]]:}, must not be {@code null}. + */ + public AetherResult resolve(String artifactCoordinates) throws AetherException { + return resolve(new DefaultArtifact(artifactCoordinates)); + } + + /** + * Shortcut for {@link #resolve(org.eclipse.aether.artifact.Artifact, boolean)} + */ + public AetherResult resolve(Artifact artifact) throws AetherException { + return resolve(artifact, true); + } + + /** + * Other way to run {@link #resolve(org.eclipse.aether.artifact.Artifact, boolean)} + * + * @param artifactCoordinates The artifact coordinates in the format + * {@code :[:[:]]:}, must not be {@code null}. + */ + public AetherResult resolve(String artifactCoordinates, boolean withTransitives) throws AetherException { + return resolve(new DefaultArtifact(artifactCoordinates), withTransitives); + } + + /** + * Resolve given artifact with or without transitives + * {@link #resolveWithTransitives(org.eclipse.aether.artifact.Artifact)} + * {@link #resolveWithoutTransitives(org.eclipse.aether.artifact.Artifact...)} + * + * @param artifact the given artifacts to resolve + * @param withTransitives true if you need to resolve artifact with transitives, false otherwise + */ + public AetherResult resolve(Artifact artifact, boolean withTransitives) throws AetherException { + return withTransitives ? resolveWithTransitives(artifact) : resolveWithoutTransitives(artifact); + } + + /** + * Other way to run {@link #resolveAll(org.eclipse.aether.artifact.Artifact...)} + * + * @param artifactsCoordinates The array of artifact coordinates in the format + * {@code :[:[:]]:}, must not be {@code null}. + */ + public AetherResult resolveAll(String... artifactsCoordinates) throws AetherException { + List artifacts = new ArrayList<>(); + for (String coordinate : artifactsCoordinates) { + artifacts.add(new DefaultArtifact(coordinate)); + } + return resolveAll(artifacts.toArray(new Artifact[artifacts.size()])); + } + + /** + * Resolve all given artifacts {@link #resolveWithoutTransitives(org.eclipse.aether.artifact.Artifact...)} + * without transitives + * + * @param artifacts the given artifacts to resolve + * @return The resolution result, never {@code null}. + * @throws AetherException if can't resolve given artifacts + */ + public AetherResult resolveAll(Artifact... artifacts) throws AetherException { + return resolveWithoutTransitives(artifacts); + } + + /** + * Collects and resolves the transitive dependencies of an artifact. This operation is essentially a combination of + * {@link org.eclipse.aether.RepositorySystem#collectDependencies(RepositorySystemSession, CollectRequest)} and + * {@link org.eclipse.aether.RepositorySystem#resolveArtifacts(RepositorySystemSession, java.util.Collection)}. + * + * @param artifact The artifact to resolve, may be {@code null}. + * @return The resolution result {@link ru.yandex.qatools.clay.AetherResult}, never {@code null}. + * @throws AetherException if can't resolve given artifact + */ + protected AetherResult resolveWithTransitives(Artifact artifact) throws AetherException { + try { + CollectRequest collectRequest = new CollectRequest( + new Dependency(artifact, scope), + repositories() + ); + + DependencyRequest request = new DependencyRequest(collectRequest, null); + return new AetherResult(system.resolveDependencies(session, request).getArtifactResults()); + } catch (DependencyResolutionException e) { + throw new AetherException("Can't resolve given artifact " + artifact, e); + } + } + + /** + * Resolves the paths for a collection of artifacts. Artifacts will be downloaded to the local repository if + * necessary. Artifacts that are already resolved will be skipped and are not re-resolved. In general, callers must + * not assume any relationship between an artifact's filename and its coordinates. Note that this method assumes + * that any relocations have already been processed. + * + * @param artifacts Collection of artifacts to resolve, never {@code null}. + * @return The resolution result {@link ru.yandex.qatools.clay.AetherResult}, never {@code null}. + * @throws AetherException if can't resolve given artifact + */ + protected AetherResult resolveWithoutTransitives(Artifact... artifacts) throws AetherException { + try { + return new AetherResult(system.resolveArtifacts(session, buildArtifactRequests(artifacts))); + } catch (ArtifactResolutionException e) { + throw new AetherException("Can't resolve one or more given artifacts " + Arrays.toString(artifacts), e); + } + } + + /** + * Build {@link org.eclipse.aether.resolution.ArtifactRequest} for each given + * {@link org.eclipse.aether.artifact.Artifact} + * + * @param artifacts the given artifacts + * @return list of artifact requests + */ + protected List buildArtifactRequests(Artifact... artifacts) { + List requests = new ArrayList<>(); + for (Artifact artifact : artifacts) { + requests.add(new ArtifactRequest(artifact, repositories(), null)); + } + return requests; + } + + /** + * Other way to run {@link #collect(org.eclipse.aether.artifact.Artifact)} + * + * @param artifactCoordinates The artifact coordinates in the format + * {@code :[:[:]]:}, must not be {@code null}. + */ + public List collect(String artifactCoordinates) throws AetherException { + return collect(new DefaultArtifact(artifactCoordinates)); + } + + /** + * Collects the transitive dependencies of an artifact and builds a dependency graph. Note that this operation is + * only concerned about determining the coordinates of the transitive dependencies. To also resolve the actual + * artifact files, use {@link #resolve(org.eclipse.aether.artifact.Artifact)}. + * + * @param artifact the given artifacts to collect + * @throws AetherException if can't collect transitive dependencies for given artifact + */ + public List collect(Artifact artifact) throws AetherException { + try { + if (session.isOffline()) { + throw new AetherException("Can't collect dependencies in offline mode"); + } + CollectRequest collectRequest = new CollectRequest( + new Dependency(artifact, scope), + repositories() + ); + CollectResult result = system.collectDependencies(session, collectRequest); + PreorderNodeListGenerator visitor = new PreorderNodeListGenerator(); + result.getRoot().accept(visitor); + return visitor.getArtifacts(true); + } catch (DependencyCollectionException e) { + throw new AetherException("Can't collect given artifact " + artifact, e); + } + } + + /** + * Shortcut for {@link #install(java.io.File, String, String, String, String)} + */ + public void install(File jar, String groupId, String artifactId, String version) throws AetherException { + install(jar, groupId, artifactId, JAR, version); + } + + /** + * Shortcut for {@link #install(java.io.File, String, String, String, String, String)} + */ + public void install(File jar, String groupId, String artifactId, String extension, String version) + throws AetherException { + install(jar, groupId, artifactId, "", extension, version); + } + + /** + * Shortcut for {@link #install(java.io.File, java.io.File, String, String, String, String, String)} + */ + public void install(File jar, String groupId, String artifactId, String classifier, String extension, String version) + throws AetherException { + File pom = null; + try { + pom = File.createTempFile("install", "pom.xml"); + FluentModelBuilder.newPom() + .withGroupId(groupId) + .withArtifactId(artifactId) + .withVersion(version) + .withModelVersion(MODEL_VERSION) + .marshalTo(pom); + install(jar, pom, groupId, artifactId, classifier, extension, version); + } catch (IOException e) { + throw new AetherException("Can't create temp file for pom.xml", e); + } finally { + FileUtils.deleteQuietly(pom); + } + } + + /** + * Install given jars to local repository using specified artifact coordinates. + * + * @param jar archive with given artifact to install + * @param pom archive with pom.xml + * @throws AetherException If any artifact/metadata from the request could not be installed. + */ + public void install(File jar, File pom, String groupId, String artifactId, String classifier, String extension, String version) + throws AetherException { + Artifact jarArtifact = new DefaultArtifact(groupId, artifactId, classifier, extension, version, null, jar); + Artifact pomArtifact = new SubArtifact(jarArtifact, null, POM_EXTENSION, pom); + install(jarArtifact, pomArtifact); + } + + /** + * Installs a collection of artifacts and their accompanying metadata to the local repository. + * + * @param artifacts the given artifacts to install + * @throws AetherException If any artifact/metadata from the request could not be installed. + */ + public void install(Artifact... artifacts) throws AetherException { + try { + InstallRequest installRequest = new InstallRequest(); + for (Artifact artifact : artifacts) { + installRequest.addArtifact(artifact); + } + system.install(session, installRequest); + } catch (InstallationException e) { + throw new AetherException("Can't install one or more given artifacts " + Arrays.toString(artifacts), e); + } + } + + /** + * Shortcut for {@link #deploy(DistributionManagement distribution, java.io.File, String, String, String, String)} + */ + public void deploy(DistributionManagement distribution, File jar, String groupId, String artifactId, String version) + throws AetherException { + deploy(distribution, jar, groupId, artifactId, JAR, version); + } + + /** + * Shortcut for {@link #deploy(DistributionManagement distribution, java.io.File, String, String, String, String, String)} + */ + public void deploy(DistributionManagement distribution, File jar, String groupId, String artifactId, + String extension, String version) + throws AetherException { + deploy(distribution, jar, groupId, artifactId, "", extension, version); + } + + /** + * Other way to run {@link #deploy(org.apache.maven.model.DistributionManagement, java.io.File, java.io.File, String, String, String, String, String)} + */ + public void deploy(DistributionManagement distribution, File jar, String groupId, String artifactId, + String classifier, String extension, String version) throws AetherException { + File pom = null; + try { + pom = File.createTempFile("install", "pom.xml"); + FluentModelBuilder.newPom() + .withGroupId(groupId) + .withArtifactId(artifactId) + .withVersion(version) + .withModelVersion(MODEL_VERSION) + .marshalTo(pom); + deploy(distribution, jar, pom, groupId, artifactId, classifier, extension, version); + } catch (IOException e) { + throw new AetherException("Can't create temp file for pom.xml", e); + } finally { + FileUtils.deleteQuietly(pom); + } + } + + /** + * Other way to run {@link #deploy(org.apache.maven.model.DistributionManagement, org.eclipse.aether.artifact.Artifact...)} + */ + public void deploy(DistributionManagement distribution, File jar, File pom, String groupId, String artifactId, + String classifier, String extension, String version) throws AetherException { + Artifact jarArtifact = new DefaultArtifact(groupId, artifactId, classifier, extension, version, null, jar); + Artifact pomArtifact = new SubArtifact(jarArtifact, null, POM_EXTENSION, pom); + deploy(distribution, jarArtifact, pomArtifact); + } + + /** + * Uploads a collection of artifacts and their accompanying metadata to a remote repository. + * + * @param distribution {@link org.apache.maven.model.DistributionManagement} which contains information + * about remotes + * @param artifacts the given artifacts to deploy + * @throws AetherException If any artifact/metadata from the request could not be deployd. + */ + public void deploy(DistributionManagement distribution, Artifact... artifacts) throws AetherException { + try { + if (artifacts.length == 0) { + return; + } + DeployRequest deployRequest = new DeployRequest(); + for (Artifact artifact : artifacts) { + deployRequest.addArtifact(artifact); + } + deployRequest.setRepository(toRemoteRepository( + artifacts[0].isSnapshot() ? + distribution.getSnapshotRepository() : + distribution.getRepository(), + session + )); + system.deploy(session, deployRequest); + } catch (DeploymentException e) { + throw new AetherException("Can't deploy one or more given artifacts" + Arrays.toString(artifacts), e); + } + } + + /** + * Get remote repositories if online mode, null otherwise + * + * @return list of remotes or null + */ + protected List repositories() { + return session.isOffline() ? null : repositories; + } +} diff --git a/clay-aether/src/main/java/ru/yandex/qatools/clay/AetherException.java b/clay-aether/src/main/java/ru/yandex/qatools/clay/AetherException.java new file mode 100644 index 0000000..edd60a4 --- /dev/null +++ b/clay-aether/src/main/java/ru/yandex/qatools/clay/AetherException.java @@ -0,0 +1,25 @@ +package ru.yandex.qatools.clay; + +import org.eclipse.aether.RepositoryException; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 24.07.14 + *

+ * Thrown in case of a unresolvable artifacts. + * Thrown in case of bad artifact descriptors, version ranges or other issues + * encountered during calculation of the dependency graph. + * Combination of {@link org.eclipse.aether.resolution.ArtifactResolutionException} + * {@link org.eclipse.aether.resolution.DependencyResolutionException} and + * {@link org.eclipse.aether.collection.DependencyCollectionException} + */ +@SuppressWarnings("unused") +public class AetherException extends RepositoryException { + public AetherException(String message) { + super(message); + } + + public AetherException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/clay-aether/src/main/java/ru/yandex/qatools/clay/AetherResult.java b/clay-aether/src/main/java/ru/yandex/qatools/clay/AetherResult.java new file mode 100644 index 0000000..897cbcc --- /dev/null +++ b/clay-aether/src/main/java/ru/yandex/qatools/clay/AetherResult.java @@ -0,0 +1,171 @@ +package ru.yandex.qatools.clay; + +import org.eclipse.aether.resolution.ArtifactResult; + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 28.07.14 + */ +public class AetherResult { + + private List results; + + AetherResult(List results) { + this.results = results; + } + + /** + * Return {@link #results} + * + * @return {@link #results} + */ + public List get() { + return results; + } + + /** + * Shortcut for {@link #getAsClassLoader(boolean)} + */ + public URLClassLoader getAsClassLoader() throws AetherException { + return getAsClassLoader(false); + } + + /** + * Shortcut for {@link #getAsClassLoader(ClassLoader, boolean)} + */ + public URLClassLoader getAsClassLoader(boolean failOnError) throws AetherException { + return getAsClassLoader(null, failOnError); + } + + /** + * Shortcut for {@link #getAsClassLoader(ClassLoader, boolean)} + */ + public URLClassLoader getAsClassLoader(ClassLoader parent) throws AetherException { + return getAsClassLoader(parent, false); + } + + /** + * Get results as {@link java.net.URLClassLoader} + * + * @param parent the parent ClassLoader, may be {@code null} + * @return created {@link java.net.URLClassLoader} + * @throws AetherException if can't get artifact URL + */ + public URLClassLoader getAsClassLoader(ClassLoader parent, boolean failOnError) throws AetherException { + return new URLClassLoader(getAsUrls(failOnError), parent); + } + + /** + * Shortcut for {@link #getAsUrls(boolean)} + */ + public URL[] getAsUrls() throws AetherException { + return getAsUrls(false); + } + + /** + * Get results as array of {@link java.net.URL} + * + * @return array of {@link java.net.URL} + * @throws AetherException if can't get artifact URL + */ + public URL[] getAsUrls(boolean failOnError) throws AetherException { + List urls = getAs(new Converter() { + @Override + public boolean check(ArtifactResult result) { + return result != null && result.getArtifact() != null && result.getArtifact().getFile() != null; + } + + @Override + public URL convert(ArtifactResult result) throws Exception { + return result.getArtifact().getFile().toURI().toURL(); + } + }, failOnError); + return urls.toArray(new URL[urls.size()]); + } + + /** + * Shortcut for {@link #getAsClassPath(boolean)} + */ + public String[] getAsClassPath() throws AetherException { + return getAsClassPath(false); + } + + /** + * Get results as array of {@link java.lang.String} + * + * @return array of {@link java.lang.String} + * @throws AetherException if can't get artifact URL + */ + public String[] getAsClassPath(boolean failOnError) throws AetherException { + List strings = getAs(new Converter() { + @Override + public boolean check(ArtifactResult result) { + return result != null && result.getArtifact() != null && result.getArtifact().getFile() != null; + } + + @Override + public String convert(ArtifactResult result) throws Exception { + return result.getArtifact().getFile().toURI().toURL().toString(); + + } + }, failOnError); + return strings.toArray(new String[strings.size()]); + } + + /** + * Convert results to list using given {@link ru.yandex.qatools.clay.AetherResult.Converter} + * + * @param converter the converter + * @param failOnError true if you need to get {@link ru.yandex.qatools.clay.AetherException} on failure, + * false otherwise + * @return list of converted results + * @throws AetherException if can't convert some result and {@code failOnError} is true + */ + public List getAs(Converter converter, boolean failOnError) throws AetherException { + List converted = new ArrayList<>(); + for (ArtifactResult result : results) { + if (converter.check(result)) { + try { + converted.add(converter.convert(result)); + } catch (Exception e) { + if (failOnError) { + throw new AetherException("Can't convert artifact result", e); + } + } + } else if (failOnError) { + throw new AetherException("Artifact result " + result + " doesn't contains file"); + } + } + return converted; + } + + /** + * Converter for {@link org.eclipse.aether.resolution.ArtifactResult} + * + * @param type in which results will be converted + */ + public interface Converter { + + /** + * Use this method to check {@link org.eclipse.aether.resolution.ArtifactResult} + * + * @param result to check + * @return true if you need to convert this {@link org.eclipse.aether.resolution.ArtifactResult} + */ + boolean check(ArtifactResult result); + + /** + * Use this method to convert {@link org.eclipse.aether.resolution.ArtifactResult} + * + * @param result to convert + * @return converted result + * @throws Exception if something went wrong + */ + T convert(ArtifactResult result) throws Exception; + } +} diff --git a/clay-aether/src/main/java/ru/yandex/qatools/clay/internal/AetherUtils.java b/clay-aether/src/main/java/ru/yandex/qatools/clay/internal/AetherUtils.java new file mode 100644 index 0000000..9045e97 --- /dev/null +++ b/clay-aether/src/main/java/ru/yandex/qatools/clay/internal/AetherUtils.java @@ -0,0 +1,264 @@ +package ru.yandex.qatools.clay.internal; + +import org.apache.maven.repository.internal.DefaultArtifactDescriptorReader; +import org.apache.maven.repository.internal.DefaultVersionRangeResolver; +import org.apache.maven.repository.internal.DefaultVersionResolver; +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Profile; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Repository; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.eclipse.aether.DefaultRepositoryCache; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; +import org.eclipse.aether.impl.ArtifactDescriptorReader; +import org.eclipse.aether.impl.ArtifactResolver; +import org.eclipse.aether.impl.DefaultServiceLocator; +import org.eclipse.aether.impl.DependencyCollector; +import org.eclipse.aether.impl.Deployer; +import org.eclipse.aether.impl.Installer; +import org.eclipse.aether.impl.LocalRepositoryProvider; +import org.eclipse.aether.impl.MetadataResolver; +import org.eclipse.aether.impl.SyncContextFactory; +import org.eclipse.aether.impl.VersionRangeResolver; +import org.eclipse.aether.impl.VersionResolver; +import org.eclipse.aether.internal.impl.DefaultArtifactResolver; +import org.eclipse.aether.internal.impl.DefaultDependencyCollector; +import org.eclipse.aether.internal.impl.DefaultDeployer; +import org.eclipse.aether.internal.impl.DefaultInstaller; +import org.eclipse.aether.internal.impl.DefaultLocalRepositoryProvider; +import org.eclipse.aether.internal.impl.DefaultMetadataResolver; +import org.eclipse.aether.internal.impl.DefaultRepositorySystem; +import org.eclipse.aether.internal.impl.DefaultSyncContextFactory; +import org.eclipse.aether.repository.Authentication; +import org.eclipse.aether.repository.AuthenticationSelector; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.MirrorSelector; +import org.eclipse.aether.repository.ProxySelector; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.repository.RepositoryPolicy; +import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.transport.TransporterFactory; +import org.eclipse.aether.spi.log.LoggerFactory; +import org.eclipse.aether.spi.log.NullLoggerFactory; +import org.eclipse.aether.transport.file.FileTransporterFactory; +import org.eclipse.aether.transport.http.HttpTransporterFactory; +import org.eclipse.aether.util.repository.AuthenticationBuilder; +import org.eclipse.aether.util.repository.ConservativeAuthenticationSelector; +import org.eclipse.aether.util.repository.DefaultAuthenticationSelector; +import org.eclipse.aether.util.repository.DefaultMirrorSelector; +import org.eclipse.aether.util.repository.DefaultProxySelector; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 24.07.14 + *

+ * Warning, it's not a part of public API. + */ +public final class AetherUtils { + + AetherUtils() { + } + + /** + * Create a new {@link org.eclipse.aether.RepositorySystem} + */ + public static RepositorySystem newRepositorySystem() { + DefaultRepositorySystem repositorySystem = new DefaultRepositorySystem(); + DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); + + locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); + locator.addService(TransporterFactory.class, FileTransporterFactory.class); + locator.addService(TransporterFactory.class, HttpTransporterFactory.class); + locator.setService(LoggerFactory.class, NullLoggerFactory.class); + locator.setService(VersionResolver.class, DefaultVersionResolver.class); + locator.setService(VersionRangeResolver.class, DefaultVersionRangeResolver.class); + locator.setService(ArtifactResolver.class, DefaultArtifactResolver.class); + locator.setService(MetadataResolver.class, DefaultMetadataResolver.class); + locator.setService(ArtifactDescriptorReader.class, DefaultArtifactDescriptorReader.class); + locator.setService(DependencyCollector.class, DefaultDependencyCollector.class); + locator.setService(Installer.class, DefaultInstaller.class); + locator.setService(Deployer.class, DefaultDeployer.class); + locator.setService(LocalRepositoryProvider.class, DefaultLocalRepositoryProvider.class); + locator.setService(SyncContextFactory.class, DefaultSyncContextFactory.class); + + repositorySystem.initService(locator); + return repositorySystem; + } + + /** + * Create a new {@link org.eclipse.aether.RepositorySystemSession} from given + * {@link org.eclipse.aether.RepositorySystem}, {@link org.apache.maven.settings.Settings} and + * local repository file + */ + public static RepositorySystemSession newSession(RepositorySystem system, Settings settings, File localRepoDir) { + DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); + LocalRepository localRepo = new LocalRepository(localRepoDir.getAbsolutePath()); + session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo)); + session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS); + if (settings != null) { + session.setOffline(settings.isOffline()); + session.setMirrorSelector(newMirrorSelector(settings.getMirrors())); + session.setAuthenticationSelector(newAuthSelector(settings.getServers())); + session.setCache(new DefaultRepositoryCache()); + session.setProxySelector(newProxySelector(settings.getProxies())); + } + return session; + } + + /** + * Create a new {@link org.eclipse.aether.repository.ProxySelector} from given list of + * {@link org.apache.maven.settings.Proxy} + */ + public static ProxySelector newProxySelector(List proxies) { + DefaultProxySelector proxySelector = new DefaultProxySelector(); + for (Proxy proxy : proxies) { + Authentication auth = new AuthenticationBuilder() + .addUsername(proxy.getUsername()) + .addPassword(proxy.getPassword()) + .build(); + proxySelector.add(new org.eclipse.aether.repository.Proxy( + proxy.getProtocol(), + proxy.getHost(), + proxy.getPort(), + auth), + proxy.getNonProxyHosts() + ); + } + return proxySelector; + } + + /** + * Create a new {@link org.eclipse.aether.repository.MirrorSelector} from given + * {@link org.apache.maven.settings.Mirror} + */ + public static MirrorSelector newMirrorSelector(List mirrors) { + DefaultMirrorSelector selector = new DefaultMirrorSelector(); + for (Mirror mirror : mirrors) { + selector.add(mirror.getId(), mirror.getUrl(), mirror.getLayout(), + false, mirror.getMirrorOf(), mirror.getMirrorOfLayouts() + ); + } + return selector; + } + + /** + * Create a new {@link org.eclipse.aether.repository.AuthenticationSelector} from given + * list of {@link org.apache.maven.settings.Server} + */ + public static AuthenticationSelector newAuthSelector(List servers) { + DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector(); + for (Server server : servers) { + AuthenticationBuilder auth = new AuthenticationBuilder(); + auth.addUsername(server.getUsername()).addPassword(server.getPassword()); + auth.addPrivateKey(server.getPrivateKey(), server.getPassphrase()); + selector.add(server.getId(), auth.build()); + } + return new ConservativeAuthenticationSelector(selector); + } + + /** + * Create a new list of {@link org.eclipse.aether.repository.RemoteRepository} from given + * {@link org.eclipse.aether.RepositorySystemSession} and {@link org.apache.maven.settings.Settings} + */ + public static List getRepositoriesAsList(RepositorySystemSession session, Settings settings) { + if (settings == null) { + return Collections.emptyList(); + } + + List repositories = new ArrayList<>(); + for (String profileName : settings.getActiveProfiles()) { + Profile profile = settings.getProfilesAsMap().get(profileName); + + for (Repository repository : profile.getRepositories()) { + repositories.add(toRemoteRepository(repository, session)); + } + } + return repositories; + } + + + /** + * Create a new {@link org.eclipse.aether.repository.RemoteRepository} from given + * {@link org.apache.maven.settings.Repository} and {@link org.eclipse.aether.RepositorySystemSession} + */ + public static RemoteRepository toRemoteRepository(Repository repo, RepositorySystemSession session) { + RemoteRepository.Builder prototypeBuilder = + new RemoteRepository.Builder(repo.getId(), repo.getLayout(), repo.getUrl()); + prototypeBuilder.setSnapshotPolicy(transformPolicy(repo.getSnapshots())); + prototypeBuilder.setReleasePolicy(transformPolicy(repo.getReleases())); + RemoteRepository prototype = prototypeBuilder.build(); + RemoteRepository.Builder builder = new RemoteRepository.Builder(prototype); + builder.setAuthentication(session.getAuthenticationSelector().getAuthentication(prototype)); + builder.setProxy(session.getProxySelector().getProxy(prototype)); + builder.setMirroredRepositories(Arrays.asList(session.getMirrorSelector().getMirror(prototype))); + return prototypeBuilder.build(); + } + + /** + * Create a new {@link org.eclipse.aether.repository.RemoteRepository} from given + * {@link org.apache.maven.model.Repository} and {@link org.eclipse.aether.RepositorySystemSession} + */ + public static RemoteRepository toRemoteRepository(org.apache.maven.model.Repository repo, RepositorySystemSession session) { + RemoteRepository.Builder prototypeBuilder = + new RemoteRepository.Builder(repo.getId(), repo.getLayout(), repo.getUrl()); + prototypeBuilder.setSnapshotPolicy(transformPolicy(repo.getSnapshots())); + prototypeBuilder.setReleasePolicy(transformPolicy(repo.getReleases())); + RemoteRepository prototype = prototypeBuilder.build(); + RemoteRepository.Builder builder = new RemoteRepository.Builder(prototype); + builder.setAuthentication(session.getAuthenticationSelector().getAuthentication(prototype)); + builder.setProxy(session.getProxySelector().getProxy(prototype)); + builder.setMirroredRepositories(Arrays.asList(session.getMirrorSelector().getMirror(prototype))); + return prototypeBuilder.build(); + } + + /** + * Convert {@link org.apache.maven.model.RepositoryPolicy} to + * {@link org.eclipse.aether.repository.RepositoryPolicy} + * + * @param policy the policy to convert, may be {@code null} + */ + public static RepositoryPolicy transformPolicy(org.apache.maven.model.RepositoryPolicy policy) { + return policy == null ? null : newRepositoryPolicy( + policy.isEnabled(), + policy.getUpdatePolicy(), + policy.getChecksumPolicy() + ); + } + + /** + * Convert {@link org.apache.maven.settings.RepositoryPolicy} to + * {@link org.eclipse.aether.repository.RepositoryPolicy} + * + * @param policy the policy to convert, may be {@code null} + */ + public static RepositoryPolicy transformPolicy(org.apache.maven.settings.RepositoryPolicy policy) { + return policy == null ? null : newRepositoryPolicy( + policy.isEnabled(), + policy.getUpdatePolicy(), + policy.getChecksumPolicy() + ); + } + + /** + * Creates a new policy with the specified settings. + * + * @param enabled A flag whether the associated repository should be accessed or not. + * @param updatePolicy The update interval after which locally cached data from the repository is considered stale + * and should be refetched, may be {@code null}. + * @param checksumPolicy The way checksum verification should be handled, may be {@code null}. + */ + public static RepositoryPolicy newRepositoryPolicy(boolean enabled, String updatePolicy, String checksumPolicy) { + return new RepositoryPolicy(enabled, updatePolicy, checksumPolicy); + } +} diff --git a/clay-aether/src/test/java/ru/yandex/qatools/clay/AetherTest.java b/clay-aether/src/test/java/ru/yandex/qatools/clay/AetherTest.java new file mode 100644 index 0000000..802067f --- /dev/null +++ b/clay-aether/src/test/java/ru/yandex/qatools/clay/AetherTest.java @@ -0,0 +1,177 @@ +package ru.yandex.qatools.clay; + +import org.apache.maven.model.DistributionManagement; +import org.apache.maven.settings.Settings; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.resolution.ArtifactResult; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.List; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static ru.yandex.qatools.clay.Aether.MAVEN_CENTRAL_URL; +import static ru.yandex.qatools.clay.Aether.aether; +import static ru.yandex.qatools.clay.DirectoryMatcher.contains; +import static ru.yandex.qatools.clay.maven.settings.FluentDeploymentRepositoryBuilder.newDeploymentRepository; +import static ru.yandex.qatools.clay.maven.settings.FluentDistributionManagementBuilder.newDistributionManagement; +import static ru.yandex.qatools.clay.maven.settings.FluentProfileBuilder.newProfile; +import static ru.yandex.qatools.clay.maven.settings.FluentRepositoryBuilder.newRepository; +import static ru.yandex.qatools.clay.maven.settings.FluentSettingsBuilder.newSettings; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 24.07.14 + */ +public class AetherTest { + + public static final Settings MAVEN_SETTINGS = newSettings() + .withActiveProfile(newProfile() + .withId("profile") + .withRepository(newRepository() + .withUrl(MAVEN_CENTRAL_URL))).build(); + + public static final String ALLURE_MODEL = "ru.yandex.qatools.allure:allure-model:jar:1.3.9"; + + public static final String ALLURE_ANNOTATIONS = "ru.yandex.qatools.allure:allure-java-annotations:jar:1.3.9"; + + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + + public File localRepo; + + @Before + public void setUp() throws Exception { + localRepo = folder.newFolder(); + } + + @Test + public void resolveWithoutTransitivesTest() throws Exception { + List results = aether(localRepo, MAVEN_SETTINGS) + .resolve(ALLURE_MODEL, false).get(); + + assertThat(results.size(), is(1)); + } + + @Test + public void resolveWithoutTransitivesAsClassLoaderTest() throws Exception { + ClassLoader classLoader = aether(localRepo, MAVEN_SETTINGS) + .resolve(ALLURE_MODEL, false).getAsClassLoader(); + + assertNotNull(classLoader.getResourceAsStream("allure.xsd")); + } + + @Test + public void resolveWithoutTransitivesAsUrlsTest() throws Exception { + URL[] urls = aether(localRepo, MAVEN_SETTINGS) + .resolve(ALLURE_MODEL, false).getAsUrls(); + + assertThat(urls.length, is(1)); + } + + @Test + public void resolveAllTest() throws Exception { + List results = aether(localRepo, MAVEN_SETTINGS) + .resolveAll(ALLURE_MODEL, ALLURE_ANNOTATIONS).get(); + + assertThat(results.size(), is(2)); + } + + @Test + public void resolveAllGetAsClassLoaderTest() throws Exception { + ClassLoader classLoader = aether(localRepo, MAVEN_SETTINGS) + .resolveAll(ALLURE_MODEL, ALLURE_ANNOTATIONS) + .getAsClassLoader(Thread.currentThread().getContextClassLoader()); + + assertNotNull(classLoader.getResourceAsStream("allure.xsd")); + assertEquals(classLoader.getParent(), Thread.currentThread().getContextClassLoader()); + } + + @Test + public void resolveWithTransitivesTest() throws Exception { + List results = aether(localRepo, MAVEN_SETTINGS) + .resolve(ALLURE_MODEL).get(); + + assertThat(results.size(), is(5)); + } + + @Test + public void resolveWithTransitivesGetAsClassPathTest() throws Exception { + String[] strings = aether(localRepo, MAVEN_SETTINGS) + .resolve(ALLURE_MODEL).getAsClassPath(); + + assertThat(strings.length, is(5)); + } + + @Test(expected = AetherException.class) + public void collectInOfflineTest() throws Exception { + Settings settings = newSettings() + .withOffline(true).build(); + aether(localRepo, settings).collect(ALLURE_MODEL); + } + + @Test + public void collectTest() throws Exception { + List artifacts = aether(localRepo, MAVEN_SETTINGS).collect(ALLURE_MODEL); + assertThat(artifacts.size(), is(5)); + } + + @Test + public void installTest() throws Exception { + File jar = createJar(); + aether(localRepo, MAVEN_SETTINGS).install(jar, "testGroupId", "testArtifactId", "testVersion"); + + File artifactDirectory = directoryContains(localRepo, "testGroupId", "testArtifactId", "testVersion"); + assertThat(artifactDirectory, contains("testArtifactId-testVersion.jar", "testArtifactId-testVersion.pom")); + } + + @Test + public void deployTest() throws Exception { + File jar = createJar(); + DistributionManagement distributionManagement = newDistributionManagement() + .withRepository(newDeploymentRepository() + .withId("server") + .withUrl(localRepo.toURI().toURL().toString())).build(); + + aether(localRepo, MAVEN_SETTINGS).deploy(distributionManagement, jar, "testGroupId", "testArtifactId", "testVersion"); + File artifactDirectory = directoryContains(localRepo, "testGroupId", "testArtifactId", "testVersion"); + assertThat(artifactDirectory, contains("testArtifactId-testVersion.jar", "testArtifactId-testVersion.pom")); + } + + private File createJar() throws IOException { + File jar = folder.newFile("test.jar"); + + try (JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(jar), createManifest())) { + jarOut.flush(); + } + return jar; + } + + private static Manifest createManifest() { + Manifest manifest = new Manifest(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + return manifest; + } + + private static File directoryContains(File directory, String... path) { + File current = directory; + for (String name : path) { + current = new File(current, name); + assertTrue(current.exists()); + } + return current; + } +} diff --git a/clay-aether/src/test/java/ru/yandex/qatools/clay/DirectoryMatcher.java b/clay-aether/src/test/java/ru/yandex/qatools/clay/DirectoryMatcher.java new file mode 100644 index 0000000..cd30ea7 --- /dev/null +++ b/clay-aether/src/test/java/ru/yandex/qatools/clay/DirectoryMatcher.java @@ -0,0 +1,53 @@ +package ru.yandex.qatools.clay; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.filefilter.NameFileFilter; +import org.apache.commons.io.filefilter.TrueFileFilter; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; + +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.core.IsNot.not; + +public class DirectoryMatcher { + public static class Contains extends TypeSafeMatcher { + + private String fileName; + + public Contains(String fileName) { + this.fileName = fileName; + } + + @Override + protected boolean matchesSafely(File directory) { + return directory.isDirectory() && !FileUtils.listFiles( + directory, + new NameFileFilter(fileName), + TrueFileFilter.INSTANCE + ).isEmpty(); + } + + @Override + public void describeTo(Description description) { + description.appendText("contains file ").appendValue(fileName); + } + } + + public static Matcher contains(String first, String... more) { + Collection result = new ArrayList<>(); + result.add(new Contains(first)); + for (String oneMore : more) { + result.add(new Contains(oneMore)); + } + return allOf(result.toArray(new Contains[result.size()])); + } + + public static Matcher notContains(String first, String... more) { + return not(contains(first, more)); + } +} \ No newline at end of file diff --git a/clay-maven-settings-builder/pom.xml b/clay-maven-settings-builder/pom.xml new file mode 100644 index 0000000..8ebd447 --- /dev/null +++ b/clay-maven-settings-builder/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + + ru.yandex.qatools.clay + clay + 2.0-SNAPSHOT + + + clay-maven-settings-builder + + Clay Maven Settings Builder + + + + org.apache.maven + maven-settings-builder + ${maven.version} + + + org.apache.maven + maven-model + ${maven.version} + + + + diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentActivationBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentActivationBuilder.java new file mode 100644 index 0000000..af91611 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentActivationBuilder.java @@ -0,0 +1,114 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.Activation; +import org.apache.maven.settings.ActivationFile; +import org.apache.maven.settings.ActivationOS; +import org.apache.maven.settings.ActivationProperty; + +/** + * The conditions within the build runtime environment + * which will trigger + * the automatic inclusion of the parent build profile. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentActivationBuilder { + + private final Activation activation; + + private FluentActivationBuilder(Activation activation) { + this.activation = activation; + } + + public Activation build() { + return activation; + } + + /* DELEGATED METHODS */ + + /** + * The conditions within the build runtime environment + * which will trigger + * the automatic inclusion of the parent build profile. + */ + public static FluentActivationBuilder newActivation() { + return new FluentActivationBuilder(new Activation()); + } + + /** + * Make this profile active as by default. + */ + public FluentActivationBuilder activeByDefault() { + activation.setActiveByDefault(true); + return this; + } + + /** + * Specifies that this profile will be activated based on + * existence of a file. + * + * @param file + */ + public FluentActivationBuilder withFile(ActivationFile file) { + activation.setFile(file); + return this; + } + + /** + * Specifies that this profile will be activated when a + * matching JDK is detected. + * + * @param jdk + */ + public FluentActivationBuilder withJdk(String jdk) { + activation.setJdk(jdk); + return this; + } + + /** + * Specifies that this profile will be activated when + * matching OS attributes are detected. + * + * @param os + */ + public FluentActivationBuilder withOs(FluentActivationOSBuilder os) { + return withOs(os.build()); + } + + /** + * Specifies that this profile will be activated when + * matching OS attributes are detected. + * + * @param os + */ + public FluentActivationBuilder withOs(ActivationOS os) { + activation.setOs(os); + return this; + } + + /** + * Specifies that this profile will be activated when this + * System property is specified. + * + * @param name + * @param value + */ + public FluentActivationBuilder withProperty(String name, String value) { + ActivationProperty property = new ActivationProperty(); + property.setName(name); + property.setValue(value); + return withProperty(property); + } + + /** + * Specifies that this profile will be activated when this + * System property is specified. + * + * @param property + */ + public FluentActivationBuilder withProperty(ActivationProperty property) { + activation.setProperty(property); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentActivationOSBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentActivationOSBuilder.java new file mode 100644 index 0000000..1b204d3 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentActivationOSBuilder.java @@ -0,0 +1,77 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.ActivationOS; + +/** + * This is an activator which will detect an operating + * system's attributes in order to activate + * its profile. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentActivationOSBuilder { + + private final ActivationOS activationOS; + + private FluentActivationOSBuilder(ActivationOS activationOS) { + this.activationOS = activationOS; + } + + /** + * This is an activator which will detect an operating + * system's attributes in order to activate + * its profile. + */ + public static FluentActivationOSBuilder newActivationOS() { + return new FluentActivationOSBuilder(new ActivationOS()); + } + + public ActivationOS build() { + return activationOS; + } + + /* DELEGATED METHODS */ + + /** + * Set the architecture of the OS to be used to activate a + * profile. + * + * @param arch + */ + public FluentActivationOSBuilder withArch(String arch) { + activationOS.setArch(arch); + return this; + } + + /** + * Set the general family of the OS to be used to activate a + * profile (e.g. 'windows'). + * + * @param family + */ + public FluentActivationOSBuilder withFamily(String family) { + activationOS.setFamily(family); + return this; + } + + /** + * Set the name of the OS to be used to activate a profile. + * + * @param name + */ + public FluentActivationOSBuilder withName(String name) { + activationOS.setName(name); + return this; + } + + /** + * Set the version of the OS to be used to activate a profile. + * + * @param version + */ + public FluentActivationOSBuilder withVersion(String version) { + activationOS.setVersion(version); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentDeploymentRepositoryBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentDeploymentRepositoryBuilder.java new file mode 100644 index 0000000..041cf74 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentDeploymentRepositoryBuilder.java @@ -0,0 +1,123 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.model.DeploymentRepository; +import org.apache.maven.model.InputLocation; +import org.apache.maven.model.RepositoryPolicy; + +/** + * Repository contains the information needed for deploying to the + * remote repository. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentDeploymentRepositoryBuilder { + + private final DeploymentRepository repository; + + private FluentDeploymentRepositoryBuilder(DeploymentRepository repository) { + this.repository = repository; + } + + /** + * Repository contains the information needed for deploying to the + * remote repository. + */ + public static FluentDeploymentRepositoryBuilder newDeploymentRepository() { + return new FluentDeploymentRepositoryBuilder(new DeploymentRepository()); + } + + public DeploymentRepository build() { + return repository; + } + + /* DELEGATED METHODS */ + + /** + * Set a unique identifier for a repository. This is used to + * match the repository to configuration in the + * settings.xml file, for example. Furthermore, + * the identifier is used during POM inheritance and profile + * injection to detect repositories that should be merged. + * + * @param id + */ + public FluentDeploymentRepositoryBuilder withId(String id) { + repository.setId(id); + return this; + } + + /** + * Set human readable name of the repository. + * + * @param name + */ + public FluentDeploymentRepositoryBuilder withName(String name) { + repository.setName(name); + return this; + } + + /** + * Set the url of the repository, in the form + * protocol://hostname/path. + * + * @param url + */ + public FluentDeploymentRepositoryBuilder withUrl(String url) { + repository.setUrl(url); + return this; + } + + /** + * Set not to use the same version each time instead of + * assigning snapshots a unique version comprised of the + * timestamp and build number (which is the default behaviour). + */ + public FluentDeploymentRepositoryBuilder withNotUniqueVersion() { + repository.setUniqueVersion(false); + return this; + } + + /** + * Set how to handle downloading of releases from this + * repository. + * + * @param releases + */ + public FluentDeploymentRepositoryBuilder withReleases(RepositoryPolicy releases) { + repository.setReleases(releases); + return this; + } + + /** + * Set how to handle downloading of snapshots from this + * repository. + * + * @param snapshots + */ + public FluentDeploymentRepositoryBuilder withSnapshots(RepositoryPolicy snapshots) { + repository.setSnapshots(snapshots); + return this; + } + + /** + * Set the type of layout this repository uses for locating and + * storing artifacts - can be legacy or + * default. + * + * @param layout + */ + public FluentDeploymentRepositoryBuilder withLayout(String layout) { + repository.setLayout(layout); + return this; + } + + /** + * @param key + * @param location + */ + public FluentDeploymentRepositoryBuilder withLocation(Object key, InputLocation location) { + repository.setLocation(key, location); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentDistributionManagementBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentDistributionManagementBuilder.java new file mode 100644 index 0000000..7d23905 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentDistributionManagementBuilder.java @@ -0,0 +1,160 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.model.*; + +/** + * This elements describes all that pertains to distribution for a + * project. It is primarily used for deployment of artifacts + * and the site produced by the build. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentDistributionManagementBuilder { + + private final DistributionManagement management; + + private FluentDistributionManagementBuilder(DistributionManagement management) { + this.management = management; + } + + /** + * This elements describes all that pertains to distribution for a + * project. It is primarily used for deployment of artifacts + * and the site produced by the build. + */ + public static FluentDistributionManagementBuilder newDistributionManagement() { + return new FluentDistributionManagementBuilder(new DistributionManagement()); + } + + public DistributionManagement build() { + return management; + } + + /* DELEGATED METHODS */ + + /** + * Set the URL of the project's download page. If not given + * users will be referred to the homepage given by + * url. This is given to assist in + * locating artifacts that are not in the repository + * due to licensing restrictions. + * + * @param downloadUrl + */ + public FluentDistributionManagementBuilder withDownloadUrl(String downloadUrl) { + management.setDownloadUrl(downloadUrl); + return this; + } + + public FluentDistributionManagementBuilder withLocation(Object key, FluentInputLocationBuilder location) { + return withLocation(key, location.build()); + } + + public FluentDistributionManagementBuilder withLocation(Object key, InputLocation location) { + management.setLocation(key, location); + return this; + } + + /** + * Set relocation information of the artifact if it has been + * moved to a new group ID and/or artifact ID. + * + * @param relocation + */ + public FluentDistributionManagementBuilder withRelocation(FluentRelocationBuilder relocation) { + return withRelocation(relocation.build()); + } + + /** + * Set relocation information of the artifact if it has been + * moved to a new group ID and/or artifact ID. + * + * @param relocation + */ + public FluentDistributionManagementBuilder withRelocation(Relocation relocation) { + management.setRelocation(relocation); + return this; + } + + /** + * Set information needed for deploying the web site of the + * project. + * + * @param site + */ + public FluentDistributionManagementBuilder withSite(FluentSiteBuilder site) { + return withSite(site.build()); + } + + /** + * Set information needed for deploying the web site of the + * project. + * + * @param site + */ + public FluentDistributionManagementBuilder withSite(Site site) { + management.setSite(site); + return this; + } + + /** + * Set information needed to deploy the artifacts generated by + * the project to a remote repository. + * + * @param repository + */ + public FluentDistributionManagementBuilder withRepository(FluentDeploymentRepositoryBuilder repository) { + return withRepository(repository.build()); + } + + /** + * Set information needed to deploy the artifacts generated by + * the project to a remote repository. + * + * @param repository + */ + public FluentDistributionManagementBuilder withRepository(DeploymentRepository repository) { + management.setRepository(repository); + return this; + } + + /** + * Set where to deploy snapshots of artifacts to. If not given, + * it defaults to the repository element. + * + * @param repository + */ + public FluentDistributionManagementBuilder withSnapshotRepository(FluentDeploymentRepositoryBuilder repository) { + return withSnapshotRepository(repository.build()); + } + + /** + * Set where to deploy snapshots of artifacts to. If not given, + * it defaults to the repository element. + * + * @param repository + */ + public FluentDistributionManagementBuilder withSnapshotRepository(DeploymentRepository repository) { + management.setSnapshotRepository(repository); + return this; + } + + /** + * Set gives the status of this artifact in the remote + * repository. This must not be set in your local project, as + * it is updated by tools placing it in the repository. + * Valid values are: none (default), + * converted (repository manager converted this + * from an Maven 1 POM), partner (directly synced + * from a partner Maven 2 repository), deployed + * (was deployed from a Maven 2 instance), verified + * (has been hand verified as correct and final). + * + * @param status + */ + public FluentDistributionManagementBuilder withStatus(String status) { + management.setStatus(status); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentInputLocationBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentInputLocationBuilder.java new file mode 100644 index 0000000..760196a --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentInputLocationBuilder.java @@ -0,0 +1,42 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.model.InputLocation; +import org.apache.maven.model.InputSource; + +import java.util.Map; + +/** + * @author innokenty + */ +public class FluentInputLocationBuilder { + + private final InputLocation location; + + private FluentInputLocationBuilder(InputLocation location) { + this.location = location; + } + + public static FluentInputLocationBuilder newInputLocation(int lineNumber, int columnNumber) { + return new FluentInputLocationBuilder(new InputLocation(lineNumber, columnNumber)); + } + + public static FluentInputLocationBuilder newInputLocation(int lineNumber, int columnNumber, InputSource source) { + return new FluentInputLocationBuilder(new InputLocation(lineNumber, columnNumber, source)); + } + + public InputLocation build() { + return location; + } + + /* DELEGATED METHODS */ + + public FluentInputLocationBuilder withLocation(Object key, InputLocation location) { + this.location.setLocation(key, location); + return this; + } + + public FluentInputLocationBuilder setLocations(Map locations) { + location.setLocations(locations); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentMirrorBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentMirrorBuilder.java new file mode 100644 index 0000000..c2bc608 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentMirrorBuilder.java @@ -0,0 +1,88 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.Mirror; + +/** + * Build a download mirror for a given repository. + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentMirrorBuilder { + + private final Mirror mirror; + + private FluentMirrorBuilder(Mirror mirror) { + this.mirror = mirror; + } + + /** + * Build a download mirror for a given repository. + */ + public static FluentMirrorBuilder newMirror() { + return new FluentMirrorBuilder(new Mirror()); + } + + public Mirror build() { + return mirror; + } + + /* DELEGATED METHODS */ + + /** + * Set the id field. + * @param id + */ + public FluentMirrorBuilder withId(String id) { + mirror.setId(id); + return this; + } + + /** + * Set the URL of the mirror repository. + * @param url + */ + public FluentMirrorBuilder withUrl(String url) { + mirror.setUrl(url); + return this; + } + + /** + * Set the optional name that describes the mirror. + * @param name + */ + public FluentMirrorBuilder withName(String name) { + mirror.setName(name); + return this; + } + + /** + * Set the server ID of the repository being mirrored, eg + * "central". This MUST NOT match the mirror id. + * @param mirrorOf + */ + public FluentMirrorBuilder withMirrorOf(String mirrorOf) { + mirror.setMirrorOf(mirrorOf); + return this; + } + + /** + * Set the layout of the mirror repository. Since Maven 3. + * @param layout + */ + public FluentMirrorBuilder withLayout(String layout) { + mirror.setLayout(layout); + return this; + } + + /** + * Set the layouts of repositories being mirrored. This value + * can be used to restrict the usage + * of the mirror to repositories with a matching + * layout (apart from a matching id). Since Maven 3. + * @param mirrorOfLayouts + */ + public FluentMirrorBuilder withMirrorOfLayouts(String mirrorOfLayouts) { + mirror.setMirrorOfLayouts(mirrorOfLayouts); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentModelBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentModelBuilder.java new file mode 100644 index 0000000..6fca9c2 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentModelBuilder.java @@ -0,0 +1,587 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.model.*; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.apache.maven.model.io.xpp3.MavenXpp3Writer; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +import java.io.*; +import java.util.List; +import java.util.Properties; + +/** + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentModelBuilder { + + private final Model model; + + private FluentModelBuilder(Model model) { + this.model = model; + } + + public static FluentModelBuilder newModel() { + return newPom(); + } + + public static FluentModelBuilder newPom() { + return new FluentModelBuilder(new Model()); + } + + public static FluentModelBuilder newModel(FileInputStream inputStream) + throws IOException, XmlPullParserException { + return newPom(inputStream); + } + + protected static FluentModelBuilder newPom(FileInputStream inputStream) + throws IOException, XmlPullParserException { + return new FluentModelBuilder(new MavenXpp3Reader().read(inputStream)); + } + + public FluentModelBuilder marshalTo(File file) throws IOException { + marshalTo(new FileOutputStream(file)); + return this; + } + + public FluentModelBuilder marshalTo(FileOutputStream outputStream) throws IOException { + new MavenXpp3Writer().write(outputStream, model); + return this; + } + + public FluentModelBuilder marshalTo(Writer writer) throws IOException { + new MavenXpp3Writer().write(writer, model); + return this; + } + + public Model build() { + return model; + } + + /* DELEGATED METHODS */ + + /** + * Method addContributor. + * + * @param contributor + */ + public FluentModelBuilder withContributor(Contributor contributor) { + model.addContributor(contributor); + return this; + } + + /** + * Method addDeveloper. + * + * @param developer + */ + public FluentModelBuilder withDeveloper(Developer developer) { + model.addDeveloper(developer); + return this; + } + + /** + * Method addLicense. + * + * @param license + */ + public FluentModelBuilder withLicense(License license) { + model.addLicense(license); + return this; + } + + /** + * Method addMailingList. + * + * @param mailingList + */ + public FluentModelBuilder withMailingList(MailingList mailingList) { + model.addMailingList(mailingList); + return this; + } + + /** + * Method addProfile. + * + * @param profile + */ + public FluentModelBuilder withProfile(Profile profile) { + model.addProfile(profile); + return this; + } + + /** + * Set the identifier for this artifact that is unique within + * the group given by the + * group ID. An artifact is something that is + * either produced or used by a project. + * Examples of artifacts produced by Maven for a + * project include: JARs, source and binary + * distributions, and WARs. + * + * @param artifactId + */ + public FluentModelBuilder withArtifactId(String artifactId) { + model.setArtifactId(artifactId); + return this; + } + + /** + * Set information required to build the project. + * + * @param build + */ + public FluentModelBuilder withBuild(Build build) { + model.setBuild(build); + return this; + } + + /** + * Set the project's continuous integration information. + * + * @param ciManagement + */ + public FluentModelBuilder withCiManagement(CiManagement ciManagement) { + model.setCiManagement(ciManagement); + return this; + } + + /** + * Set describes the contributors to a project that are not yet + * committers. + * + * @param contributors + */ + public FluentModelBuilder withContributors(List contributors) { + model.setContributors(contributors); + return this; + } + + /** + * Set a detailed description of the project, used by Maven + * whenever it needs to + * describe the project, such as on the web site. + * While this element can be specified as + * CDATA to enable the use of HTML tags within the + * description, it is discouraged to allow + * plain text representation. If you need to modify + * the index page of the generated web + * site, you are able to specify your own instead + * of adjusting this text. + * + * @param description + */ + public FluentModelBuilder withDescription(String description) { + model.setDescription(description); + return this; + } + + /** + * Set describes the committers of a project. + * + * @param developers + */ + public FluentModelBuilder withDevelopers(List developers) { + model.setDevelopers(developers); + return this; + } + + /** + * Set a universally unique identifier for a project. It is + * normal to + * use a fully-qualified package name to + * distinguish it from other + * projects with a similar name (eg. + * org.apache.maven). + * + * @param groupId + */ + public FluentModelBuilder withGroupId(String groupId) { + model.setGroupId(groupId); + return this; + } + + /** + * Set the year of the project's inception, specified with 4 + * digits. This value is + * used when generating copyright notices as well + * as being informational. + * + * @param inceptionYear + */ + public FluentModelBuilder withInceptionYear(String inceptionYear) { + model.setInceptionYear(inceptionYear); + return this; + } + + /** + * Set the project's issue management system information. + * + * @param issueManagement + */ + public FluentModelBuilder withIssueManagement(IssueManagement issueManagement) { + model.setIssueManagement(issueManagement); + return this; + } + + /** + * Set this element describes all of the licenses for this + * project. + * Each license is described by a + * license element, which + * is then described by additional elements. + * Projects should only list the license(s) that + * applies to the project + * and not the licenses that apply to dependencies. + * If multiple licenses are listed, it is assumed + * that the user can select + * any of them, not that they must accept all. + * + * @param licenses + */ + public FluentModelBuilder withLicenses(List licenses) { + model.setLicenses(licenses); + return this; + } + + /** + * Set contains information about a project's mailing lists. + * + * @param mailingLists + */ + public FluentModelBuilder withMailingLists(List mailingLists) { + model.setMailingLists(mailingLists); + return this; + } + + /** + * Set the modelEncoding field. + * + * @param modelEncoding + */ + public FluentModelBuilder withModelEncoding(String modelEncoding) { + model.setModelEncoding(modelEncoding); + return this; + } + + /** + * Set declares to which version of project descriptor this POM + * conforms. + * + * @param modelVersion + */ + public FluentModelBuilder withModelVersion(String modelVersion) { + model.setModelVersion(modelVersion); + return this; + } + + /** + * Set the full name of the project. + * + * @param name + */ + public FluentModelBuilder withName(String name) { + model.setName(name); + return this; + } + + /** + * Set this element describes various attributes of the + * organization to which the + * project belongs. These attributes are utilized + * when documentation is created (for + * copyright notices and links). + * + * @param organization + */ + public FluentModelBuilder withOrganization(Organization organization) { + model.setOrganization(organization); + return this; + } + + /** + * Set the type of artifact this project produces, for example + * jar + * war + * ear + * pom. + * Plugins can create their own packaging, and + * therefore their own packaging types, + * so this list does not contain all possible + * types. + * + * @param packaging + */ + public FluentModelBuilder withPackaging(String packaging) { + model.setPackaging(packaging); + return this; + } + + /** + * Set the location of the parent project, if one exists. + * Values from the parent + * project will be the default for this project if + * they are left unspecified. The location + * is given as a group ID, artifact ID and version. + * + * @param parent + */ + public FluentModelBuilder withParent(Parent parent) { + model.setParent(parent); + return this; + } + + /** + * Set describes the prerequisites in the build environment for + * this project. + * + * @param prerequisites + */ + public FluentModelBuilder withPrerequisites(Prerequisites prerequisites) { + model.setPrerequisites(prerequisites); + return this; + } + + /** + * Set a listing of project-local build profiles which will + * modify the build process + * when activated. + * + * @param profiles + */ + public FluentModelBuilder withProfiles(List profiles) { + model.setProfiles(profiles); + return this; + } + + /** + * Set specification for the SCM used by the project, such as + * CVS, Subversion, etc. + * + * @param scm + */ + public FluentModelBuilder withScm(Scm scm) { + model.setScm(scm); + return this; + } + + /** + * Set the URL to the project's homepage. + *
Default value is: parent value [+ + * path adjustment] + artifactId. + * + * @param url + */ + public FluentModelBuilder withUrl(String url) { + model.setUrl(url); + return this; + } + + /** + * Set the current version of the artifact produced by this + * project. + * + * @param version + */ + public FluentModelBuilder withVersion(String version) { + model.setVersion(version); + return this; + } + + public FluentModelBuilder withPomFile(File pomFile) { + model.setPomFile(pomFile); + return this; + } + + /** + * Method addDependency. + * + * @param dependency + */ + public FluentModelBuilder withDependency(Dependency dependency) { + model.addDependency(dependency); + return this; + } + + /** + * Method addModule. + * + * @param string + */ + public FluentModelBuilder withModule(String string) { + model.addModule(string); + return this; + } + + /** + * Method addPluginRepository. + * + * @param repository + */ + public FluentModelBuilder withPluginRepository(Repository repository) { + model.addPluginRepository(repository); + return this; + } + + /** + * Method addProperty. + * @param key + * @param value + */ + public FluentModelBuilder withProperty(String key, String value) { + model.addProperty(key, value); + return this; + } + + /** + * Method addRepository. + * + * @param repository + */ + public FluentModelBuilder withRepository(Repository repository) { + model.addRepository(repository); + return this; + } + + /** + * Set this element describes all of the dependencies + * associated with a + * project. + * These dependencies are used to construct a + * classpath for your + * project during the build process. They are + * automatically downloaded from the + * repositories defined in this project. + * See the + * dependency mechanism for more information. + * + * @param dependencies + */ + public FluentModelBuilder withDependencies(List dependencies) { + model.setDependencies(dependencies); + return this; + } + + /** + * Set default dependency information for projects that inherit + * from this one. The + * dependencies in this section are not immediately + * resolved. Instead, when a POM derived + * from this one declares a dependency described by + * a matching groupId and artifactId, the + * version and other values from this section are + * used for that dependency if they were not + * already specified. + * + * @param dependencyManagement + */ + public FluentModelBuilder withDependencyManagement(DependencyManagement dependencyManagement) { + model.setDependencyManagement(dependencyManagement); + return this; + } + + /** + * Set distribution information for a project that enables + * deployment of the site + * and artifacts to remote web servers and + * repositories respectively. + * + * @param distributionManagement + */ + public FluentModelBuilder withDistributionManagement(DistributionManagement distributionManagement) { + model.setDistributionManagement(distributionManagement); + return this; + } + + /** + * + * @param key + * @param location + */ + public FluentModelBuilder withLocation(Object key, InputLocation location) { + model.setLocation(key, location); + return this; + } + + /** + * Set the modules (sometimes called subprojects) to build as a + * part of this + * project. Each module listed is a relative path + * to the directory containing the module. + * To be consistent with the way default urls are + * calculated from parent, it is recommended + * to have module names match artifact ids. + * + * @param modules + */ + public FluentModelBuilder withModules(List modules) { + model.setModules(modules); + return this; + } + + /** + * Set the lists of the remote repositories for discovering + * plugins for builds and + * reports. + * + * @param pluginRepositories + */ + public FluentModelBuilder withPluginRepositories(List pluginRepositories) { + model.setPluginRepositories(pluginRepositories); + return this; + } + + /** + * Set properties that can be used throughout the POM as a + * substitution, and + * are used as filters in resources if enabled. + * The format is + * <name>value</name>. + * + * @param properties + */ + public FluentModelBuilder withProperties(Properties properties) { + model.setProperties(properties); + return this; + } + + /** + * Set this element includes the specification of report + * plugins to use + * to generate the reports on the Maven-generated + * site. + * These reports will be run when a user executes + * mvn site. + * All of the reports will be included in the + * navigation bar for browsing. + * + * @param reporting + */ + public FluentModelBuilder withReporting(Reporting reporting) { + model.setReporting(reporting); + return this; + } + + /** + * Set Deprecated. Now ignored by Maven. + * + * @param reports + */ + public FluentModelBuilder withReports(Object reports) { + model.setReports(reports); + return this; + } + + /** + * Set the lists of the remote repositories for discovering + * dependencies and + * extensions. + * + * @param repositories + */ + public FluentModelBuilder withRepositories(List repositories) { + model.setRepositories(repositories); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentProfileBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentProfileBuilder.java new file mode 100644 index 0000000..fe189e6 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentProfileBuilder.java @@ -0,0 +1,118 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.Activation; +import org.apache.maven.settings.Profile; +import org.apache.maven.settings.Repository; + +import static ru.yandex.qatools.clay.maven.settings.FluentActivationBuilder.newActivation; + +/** + * Modifications to the build process which is keyed on + * some sort of environmental parameter. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentProfileBuilder { + + private final Profile profile; + + private FluentProfileBuilder(Profile profile) { + this.profile = profile; + } + + /** + * Modifications to the build process which is keyed on + * some sort of environmental parameter. + */ + public static FluentProfileBuilder newProfile() { + return new FluentProfileBuilder(new Profile()); + } + + public Profile build() { + return profile; + } + + /* DELEGATED METHODS */ + + /** + * Set the id field. + * @param id + */ + public FluentProfileBuilder withId(String id) { + profile.setId(id); + return this; + } + + /** + * Set this profile to be active + */ + public FluentProfileBuilder activeByDefault() { + return withActivation(newActivation().activeByDefault()); + } + + /** + * Set the conditional logic which will automatically + * trigger the inclusion of this profile. + * @param activation + */ + public FluentProfileBuilder withActivation(FluentActivationBuilder activation) { + return withActivation(activation.build()); + } + + /** + * Set the conditional logic which will automatically + * trigger the inclusion of this profile. + * @param activation + */ + public FluentProfileBuilder withActivation(Activation activation) { + profile.setActivation(activation); + return this; + } + + /** + * Add extended configuration specific to this profile goes + * here. Contents take the form of + * <key>value</key> + * @param key + * @param value + */ + public FluentProfileBuilder withProperty(String key, String value) { + profile.addProperty(key, value); + return this; + } + + /** + * Add a remote repository. + * @param repository + */ + public FluentProfileBuilder withRepository(FluentRepositoryBuilder repository) { + return withRepository(repository.build()); + } + + /** + * Add a remote repository. + * @param repository + */ + public FluentProfileBuilder withRepository(Repository repository) { + profile.addRepository(repository); + return this; + } + + /** + * add a remote repository for discovering plugins. + * @param repository + */ + public FluentProfileBuilder withPluginRepository(FluentRepositoryBuilder repository) { + return withRepository(repository.build()); + } + + /** + * add a remote repository for discovering plugins. + * @param repository + */ + public FluentProfileBuilder withPluginRepository(Repository repository) { + profile.addPluginRepository(repository); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentProxyBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentProxyBuilder.java new file mode 100644 index 0000000..a8b91d1 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentProxyBuilder.java @@ -0,0 +1,105 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.Proxy; + +/** + * The <proxy> element contains + * information required to a proxy settings. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentProxyBuilder { + + private final Proxy proxy; + + private FluentProxyBuilder(Proxy proxy) { + this.proxy = proxy; + } + + /** + * The <proxy> element contains + * informations required to a proxy settings. + */ + public static FluentProxyBuilder newProxy() { + return new FluentProxyBuilder(new Proxy()); + } + + public Proxy build() { + return proxy; + } + + /* DELEGATED METHODS */ + + /** + * Set the id field. + * @param id + */ + public FluentProxyBuilder withId(String id) { + proxy.setId(id); + return this; + } + + /** + * Set the proxy user. + * @param username + */ + public FluentProxyBuilder withUsername(String username) { + proxy.setUsername(username); + return this; + } + + /** + * Set the proxy password. + * @param password + */ + public FluentProxyBuilder withPassword(String password) { + proxy.setPassword(password); + return this; + } + + /** + * Make this proxy configuration not active. + * All proxies are active by default. + */ + public FluentProxyBuilder notActive() { + proxy.setActive(false); + return this; + } + + /** + * Set the proxy host. + * @param host + */ + public FluentProxyBuilder withHost(String host) { + proxy.setHost(host); + return this; + } + + /** + * Set the list of non-proxied hosts (delimited by |). + * @param nonProxyHosts + */ + public FluentProxyBuilder withNonProxyHosts(String nonProxyHosts) { + proxy.setNonProxyHosts(nonProxyHosts); + return this; + } + + /** + * Set the proxy protocol. + * @param protocol + */ + public FluentProxyBuilder withProtocol(String protocol) { + proxy.setProtocol(protocol); + return this; + } + + /** + * Set the proxy port. + * @param port + */ + public FluentProxyBuilder withPort(int port) { + proxy.setPort(port); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRelocationBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRelocationBuilder.java new file mode 100644 index 0000000..68b67e4 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRelocationBuilder.java @@ -0,0 +1,77 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.model.InputLocation; +import org.apache.maven.model.Relocation; + +/** + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentRelocationBuilder { + + private final Relocation relocation; + + private FluentRelocationBuilder(Relocation relocation) { + this.relocation = relocation; + } + + public static FluentRelocationBuilder newRelocation() { + return new FluentRelocationBuilder(new Relocation()); + } + + public Relocation build() { + return relocation; + } + + /* DELEGATED METHODS */ + + /** + * Set the new artifact ID of the artifact. + * + * @param artifactId + */ + public FluentRelocationBuilder withArtifactId(String artifactId) { + relocation.setArtifactId(artifactId); + return this; + } + + /** + * Set the group ID the artifact has moved to. + * + * @param groupId + */ + public FluentRelocationBuilder withGroupId(String groupId) { + relocation.setGroupId(groupId); + return this; + } + + /** + * @param key + * @param location + */ + public FluentRelocationBuilder withLocation(Object key, InputLocation location) { + relocation.setLocation(key, location); + return this; + } + + /** + * Set an additional message to show the user about the move, + * such as the reason. + * + * @param message + */ + public FluentRelocationBuilder withMessage(String message) { + relocation.setMessage(message); + return this; + } + + /** + * Set the new version of the artifact. + * + * @param version + */ + public FluentRelocationBuilder withVersion(String version) { + relocation.setVersion(version); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRepositoryBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRepositoryBuilder.java new file mode 100644 index 0000000..b30cf6d --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRepositoryBuilder.java @@ -0,0 +1,118 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.Repository; +import org.apache.maven.settings.RepositoryPolicy; + +/** + * Repository contains the information needed for + * establishing connections with remote repository. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentRepositoryBuilder { + + private final Repository repository; + + private FluentRepositoryBuilder(Repository repository) { + this.repository = repository; + } + + /** + * Repository contains the information needed for + * establishing connections with remote repository. + */ + public static FluentRepositoryBuilder newRepository() { + return new FluentRepositoryBuilder(new Repository()); + } + + public Repository build() { + return repository; + } + + /* DELEGATED METHODS */ + + /** + * Set a unique identifier for a repository. + * + * @param id + */ + public FluentRepositoryBuilder withId(String id) { + repository.setId(id); + return this; + } + + /** + * Set human readable name of the repository. + * + * @param name + */ + public FluentRepositoryBuilder withName(String name) { + repository.setName(name); + return this; + } + + /** + * Set the url of the repository. + * + * @param url + */ + public FluentRepositoryBuilder withUrl(String url) { + repository.setUrl(url); + return this; + } + + /** + * Set the type of layout this repository uses for locating and + * storing artifacts - can be "legacy" or + * "default". + * + * @param layout + */ + public FluentRepositoryBuilder withLayout(String layout) { + repository.setLayout(layout); + return this; + } + + /** + * Set how to handle downloading of releases from this + * repository. + * + * @param releases + */ + public FluentRepositoryBuilder withReleases(FluentRepositoryPolicyBuilder releases) { + return withReleases(releases.build()); + } + + /** + * Set how to handle downloading of releases from this + * repository. + * + * @param releases + */ + public FluentRepositoryBuilder withReleases(RepositoryPolicy releases) { + repository.setReleases(releases); + return this; + } + + /** + * Set how to handle downloading of snapshots from this + * repository. + * + * @param snapshots + */ + public FluentRepositoryBuilder withSnapshots(FluentRepositoryPolicyBuilder snapshots) { + return withSnapshots(snapshots.build()); + } + + /** + * Set how to handle downloading of snapshots from this + * repository. + * + * @param snapshots + */ + public FluentRepositoryBuilder withSnapshots(RepositoryPolicy snapshots) { + repository.setSnapshots(snapshots); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRepositoryPolicyBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRepositoryPolicyBuilder.java new file mode 100644 index 0000000..986d57c --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentRepositoryPolicyBuilder.java @@ -0,0 +1,40 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.RepositoryPolicy; + +/** + * @author innokenty + */ +public class FluentRepositoryPolicyBuilder { + + private final RepositoryPolicy policy; + + private FluentRepositoryPolicyBuilder(RepositoryPolicy policy) { + this.policy = policy; + } + + public static FluentRepositoryPolicyBuilder newRepositoryPolicy() { + return new FluentRepositoryPolicyBuilder(new RepositoryPolicy()); + } + + public RepositoryPolicy build() { + return policy; + } + + /* DELEGATED METHODS */ + + public FluentRepositoryPolicyBuilder disabled() { + policy.setEnabled(false); + return this; + } + + public FluentRepositoryPolicyBuilder withChecksumPolicy(String checksumPolicy) { + policy.setChecksumPolicy(checksumPolicy); + return this; + } + + public FluentRepositoryPolicyBuilder withUpdatePolicy(String updatePolicy) { + policy.setUpdatePolicy(updatePolicy); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentServerBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentServerBuilder.java new file mode 100644 index 0000000..5517a59 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentServerBuilder.java @@ -0,0 +1,106 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.Server; + +/** + * The <server> element contains + * informations required to a server settings. + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentServerBuilder { + + private final Server server; + + private FluentServerBuilder(Server server) { + this.server = server; + } + + /** + * The <server> element contains + * information required to a server settings. + */ + public static FluentServerBuilder newServer() { + return new FluentServerBuilder(new Server()); + } + + public Server build() { + return server; + } + + /* DELEGATED METHODS */ + + /** + * Set the id field. + * @param id + */ + public FluentServerBuilder withId(String id) { + server.setId(id); + return this; + } + + /** + * Set the username used to authenticate. + * @param username + */ + public FluentServerBuilder withUsername(String username) { + server.setUsername(username); + return this; + } + + /** + * Set the password used in conjunction with the username to + * authenticate. + * @param password + */ + public FluentServerBuilder withPassword(String password) { + server.setPassword(password); + return this; + } + + /** + * Set the passphrase used in conjunction with the privateKey + * to authenticate. + * @param passphrase + */ + public FluentServerBuilder withPassphrase(String passphrase) { + server.setPassphrase(passphrase); + return this; + } + + /** + * Set the private key location used to authenticate. + * @param privateKey + */ + public FluentServerBuilder withPrivateKey(String privateKey) { + server.setPrivateKey(privateKey); + return this; + } + + /** + * Set extra configuration for the transport layer. + * @param configuration + */ + public FluentServerBuilder withConfiguration(Object configuration) { + server.setConfiguration(configuration); + return this; + } + + /** + * Set the permissions for directories when they are created. + * @param directoryPermissions + */ + public FluentServerBuilder withDirectoryPermissions(String directoryPermissions) { + server.setDirectoryPermissions(directoryPermissions); + return this; + } + + /** + * Set the permissions for files when they are created. + * @param filePermissions + */ + public FluentServerBuilder withFilePermissions(String filePermissions) { + server.setFilePermissions(filePermissions); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentSettingsBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentSettingsBuilder.java new file mode 100644 index 0000000..a3e4976 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentSettingsBuilder.java @@ -0,0 +1,138 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Profile; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; +import org.apache.maven.settings.building.DefaultSettingsBuilderFactory; +import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; +import org.apache.maven.settings.building.SettingsBuildingException; + +import java.io.File; + +/** + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentSettingsBuilder { + + private final Settings settings; + + private FluentSettingsBuilder(Settings settings) { + this.settings = settings; + } + + public static FluentSettingsBuilder newSettings() { + return new FluentSettingsBuilder(new Settings()); + } + + public static FluentSettingsBuilder newSettings(String settingsFilePath) + throws SettingsBuildingException { + DefaultSettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); + request.setGlobalSettingsFile(new File(settingsFilePath)); + Settings settings = new DefaultSettingsBuilderFactory() + .newInstance() + .build(request) + .getEffectiveSettings(); + return new FluentSettingsBuilder(settings); + } + + /** + * Looks for settings.xml at '${user.home}/.m2/settings.xml' and '$M2_HOME/conf/settings.xml'. + * {@see http://maven.apache.org/settings.html} + * + * @throws SettingsBuildingException {@link org.apache.maven.settings.building.DefaultSettingsBuilder#build(org.apache.maven.settings.building.SettingsBuildingRequest)} + * @throws MavenNotFoundException if can't find Maven distribution + */ + public static FluentSettingsBuilder newSystemSettings() throws SettingsBuildingException, MavenNotFoundException { + String userHome = System.getProperty("user.home"); + String m2home = System.getProperty("M2_HOME"); + String path = null; + if (userHome != null) { + return newSettings(String.format("%s/.m2/settings.xml", userHome)); + } else if (m2home != null) { + return newSettings(String.format("%s/conf/settings.xml", m2home)); + } else { + throw new MavenNotFoundException("There are no Maven distribution"); + } + } + + public Settings build() { + return settings; + } + + /* DELEGATED METHODS */ + + /** + * Set the local repository.
Default value is: + * ${user.home}/.m2/repository + * + * @param localRepository + */ + public FluentSettingsBuilder withLocalRepository(String localRepository) { + settings.setLocalRepository(localRepository); + return this; + } + + public FluentSettingsBuilder withMirror(FluentMirrorBuilder mirror) { + return withMirror(mirror.build()); + } + + public FluentSettingsBuilder withMirror(Mirror mirror) { + settings.addMirror(mirror); + return this; + } + + public FluentSettingsBuilder withPluginGroup(String string) { + settings.addPluginGroup(string); + return this; + } + + public FluentSettingsBuilder withProfile(FluentProfileBuilder profile) { + return withProfile(profile.build()); + } + + public FluentSettingsBuilder withProfile(Profile profile) { + settings.addProfile(profile); + return this; + } + + public FluentSettingsBuilder withActiveProfile(FluentProfileBuilder profile) { + return withActiveProfile(profile.build()); + } + + protected FluentSettingsBuilder withActiveProfile(Profile profile) { + settings.addProfile(profile); + settings.addActiveProfile(profile.getId()); + return this; + } + + public FluentSettingsBuilder withActiveProfile(String string) { + settings.addActiveProfile(string); + return this; + } + + public FluentSettingsBuilder withProxy(FluentProxyBuilder proxy) { + return withProxy(proxy.build()); + } + + public FluentSettingsBuilder withProxy(Proxy proxy) { + settings.addProxy(proxy); + return this; + } + + public FluentSettingsBuilder withServer(FluentServerBuilder server) { + return withServer(server.build()); + } + + public FluentSettingsBuilder withServer(Server server) { + settings.addServer(server); + return this; + } + + public FluentSettingsBuilder withOffline(boolean offline) { + settings.setOffline(offline); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentSiteBuilder.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentSiteBuilder.java new file mode 100644 index 0000000..32c9130 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/FluentSiteBuilder.java @@ -0,0 +1,76 @@ +package ru.yandex.qatools.clay.maven.settings; + +import org.apache.maven.model.InputLocation; +import org.apache.maven.model.Site; + +/** + * Contains the information needed for deploying websites. + * + * @author innokenty + */ +@SuppressWarnings("JavaDoc") +public class FluentSiteBuilder { + + private final Site site; + + private FluentSiteBuilder(Site site) { + this.site = site; + } + + /** + * Contains the information needed for deploying websites. + */ + public static FluentSiteBuilder newSite() { + return new FluentSiteBuilder(new Site()); + } + + public Site build() { + return site; + } + + /* DELEGATED METHODS */ + + /** + * Set a unique identifier for a deployment location. This is + * used to match the site to configuration in the + * settings.xml file, for example. + * + * @param id + */ + public FluentSiteBuilder withId(String id) { + site.setId(id); + return this; + } + + /** + * @param key + * @param location + */ + public FluentSiteBuilder withLocation(Object key, InputLocation location) { + site.setLocation(key, location); + return this; + } + + /** + * Set human readable name of the deployment location. + * + * @param name + */ + public FluentSiteBuilder withName(String name) { + site.setName(name); + return this; + } + + /** + * Set the url of the location where website is deployed, in + * the form protocol://hostname/path. + *
Default value is: parent value [+ + * path adjustment] + artifactId. + * + * @param url + */ + public FluentSiteBuilder withUrl(String url) { + site.setUrl(url); + return this; + } +} diff --git a/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/MavenNotFoundException.java b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/MavenNotFoundException.java new file mode 100644 index 0000000..1790c91 --- /dev/null +++ b/clay-maven-settings-builder/src/main/java/ru/yandex/qatools/clay/maven/settings/MavenNotFoundException.java @@ -0,0 +1,11 @@ +package ru.yandex.qatools.clay.maven.settings; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 28.07.14 + */ +public class MavenNotFoundException extends Exception { + public MavenNotFoundException(String message) { + super(message); + } +} diff --git a/clay-utils/pom.xml b/clay-utils/pom.xml new file mode 100644 index 0000000..f187fe3 --- /dev/null +++ b/clay-utils/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + + + ru.yandex.qatools.clay + clay + 2.0-SNAPSHOT + + + clay-utils + + Clay Utils + + + 2.4 + 3.3.2 + + + + + org.apache.commons + commons-lang3 + ${commons.lang.version} + + + commons-io + commons-io + ${commons.io.version} + + + diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/DateUtil.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/DateUtil.java new file mode 100644 index 0000000..b70df52 --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/DateUtil.java @@ -0,0 +1,76 @@ +package ru.yandex.qatools.clay.utils; + +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +/** + * Date util class + * User: isadykov + * Date: 18.01.12 + * Time: 19:49 + */ +@SuppressWarnings("unused") +public final class DateUtil { + + DateUtil() { + } + + /** + * Get timestamp for a date + * + * @param date date + * @return timestamp + */ + public static Long timestamp(Date date) { + return date.getTime(); + } + + /** + * Get current timestamp + * + * @return timestamp + */ + public static Long timestamp() { + return timestamp(now()); + } + + /** + * Get date for calendar difference from current date + * + * @param field difference field (Calendar.DATE, Calendar.MINUTE ... etc) + * @param amount how much? + * @return date for the difference + */ + public static Date forCalendarDiff(int field, int amount) { + GregorianCalendar gCal = new GregorianCalendar(); + gCal.add(field, amount); + return new Date(gCal.getTimeInMillis()); + } + + /** + * Get date for now + * + * @return date + */ + public static Date now() { + return forCalendarDiff(Calendar.SECOND, 0); + } + + /** + * Checks if the difference between current moment and timestamp is greater than diff + */ + public static boolean isTimePassedSince(long diff, long timestamp) { + return now().getTime() - timestamp >= diff; + } + + /** + * Returns calendar for time + */ + public static Calendar calThen(long time) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(time); + return cal; + } + +} diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/MapUtil.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/MapUtil.java new file mode 100644 index 0000000..d85571d --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/MapUtil.java @@ -0,0 +1,36 @@ +package ru.yandex.qatools.clay.utils; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Ilya Sadykov + * @version $Date$ $Revision$ + */ +public class MapUtil { + /** + * Creates the HashMap of Integers + * + * @param key first key of the map + * @param value first value of the map + * @param keysValues pairs of key value + * Example: sMap(1, 2, 2, 4) will create {1 -> 2, 2 -> 4} + * @return new HashMap of String -> String + */ + @SuppressWarnings("unchecked") + public static Map map(K key, V value, Object... keysValues) { + Map res = new HashMap(); + res.put(key, value); + if (keysValues.length > 0) { + if (keysValues.length % 2 > 0) { + throw new IllegalArgumentException("Arguments count must be even!"); + } + for (int i = 0; i < keysValues.length; i += 2) { + K k = (K) keysValues[i]; + V v = (V) keysValues[i + 1]; + res.put(k, v); + } + } + return res; + } +} diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/ArchiveUtil.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/ArchiveUtil.java new file mode 100644 index 0000000..98f1d47 --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/ArchiveUtil.java @@ -0,0 +1,76 @@ +package ru.yandex.qatools.clay.utils.archive; + +import org.apache.commons.io.FileUtils; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +/** + * @author Artem Eroshenko eroshenkoam@yandex-team.ru + * Date: 29.05.14 + *

+ * Unpack JAR archive utilities. + */ +public final class ArchiveUtil { + + ArchiveUtil() { + } + + public static void unpackJar(File source, File destination) throws IOException { + unpackJar(source, destination, new DefaultJarEntryFilter()); + } + + /** + * Unpack jar archive to specified directory. Uses {@link JarEntryFilter} to filter some + * entries uses {@link #unpackJar(java.util.jar.JarFile, java.io.File, JarEntryFilter)} + * + * @param source a jar file to unpack. + * @param destination a directory to unpack jar archive. Shouldn't be null. + * @param filter a JarEntryFilter + * @throws SecurityException if access to the file is denied by the SecurityManager + * @throws java.io.IOException if an I/O error has occurred + * if the destination directory cannot be created or + * the file already exists but is not a directory + * if destination cannot be written + * if an IO error occurs during copying + */ + public static void unpackJar(File source, File destination, JarEntryFilter filter) throws IOException { + unpackJar(new JarFile(source), destination, filter); + } + + /** + * Unpack {@link java.util.jar.JarFile} to specified directory. Uses {@link JarEntryFilter} to filter some + * entries. + * + * @param source a {@link java.util.jar.JarFile} to unpack. Shouldn't be null. + * @param destination a directory to unpack jar archive. Shouldn't be null. + * @param filter a JarEntryFilter + * @throws java.io.IOException if the destination directory cannot be created or the file already exists + * but is not a directory + * if destination cannot be written + * if an IO error occurs during copying + */ + public static void unpackJar(JarFile source, File destination, JarEntryFilter filter) throws IOException { + Enumeration entries = source.entries(); + while (entries.hasMoreElements()) { + JarEntry entryToCopy = entries.nextElement(); + if (filter.accept(entryToCopy)) { + File outputFile = new File(destination, filter.getOutputFilePath(entryToCopy)); + if (entryToCopy.isDirectory()) { + FileUtils.forceMkdir(outputFile); + } else { + FileUtils.copyInputStreamToFile(source.getInputStream(entryToCopy), outputFile); + } + } + } + } +} diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/DefaultJarEntryFilter.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/DefaultJarEntryFilter.java new file mode 100644 index 0000000..7cc2106 --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/DefaultJarEntryFilter.java @@ -0,0 +1,19 @@ +package ru.yandex.qatools.clay.utils.archive; + +import java.util.jar.JarEntry; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 09.07.14 + */ +public class DefaultJarEntryFilter implements JarEntryFilter { + @Override + public boolean accept(JarEntry entry) { + return true; + } + + @Override + public String getOutputFilePath(JarEntry entry) { + return entry.getName(); + } +} diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/JarEntryFilter.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/JarEntryFilter.java new file mode 100644 index 0000000..b326a50 --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/JarEntryFilter.java @@ -0,0 +1,29 @@ +package ru.yandex.qatools.clay.utils.archive; + +import java.util.jar.JarEntry; + +/** + * @author Artem Eroshenko eroshenkoam@yandex-team.ru + * Date: 29.05.14 + *

+ * Uses to filter some enties in {@link java.util.jar.JarFile}. Also map each entry + * to location. + */ +public interface JarEntryFilter { + + /** + * Tests if a specified JarEntry should be unpacked. + * + * @param entry a entry to test + * @return true if entry should be included, false otherwise + */ + boolean accept(JarEntry entry); + + /** + * Map entry to location. + * + * @param entry a entry to map. + * @return relative file path for specified entry + */ + String getOutputFilePath(JarEntry entry); +} \ No newline at end of file diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/PathJarEntryFilter.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/PathJarEntryFilter.java new file mode 100644 index 0000000..605e319 --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/archive/PathJarEntryFilter.java @@ -0,0 +1,27 @@ +package ru.yandex.qatools.clay.utils.archive; + +import java.util.jar.JarEntry; + +/** + * @author Dmitry Baev charlie@yandex-team.ru + * Date: 14.07.14 + */ +@SuppressWarnings("unused") +public class PathJarEntryFilter implements JarEntryFilter { + + private final String path; + + public PathJarEntryFilter(String path) { + this.path = path; + } + + @Override + public boolean accept(JarEntry entry) { + return entry.getName().equals(path); + } + + @Override + public String getOutputFilePath(JarEntry entry) { + return entry.getName(); + } +} diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/lang3/HierarchicalStyle.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/lang3/HierarchicalStyle.java new file mode 100644 index 0000000..d948596 --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/lang3/HierarchicalStyle.java @@ -0,0 +1,57 @@ +package ru.yandex.qatools.clay.utils.lang3; + +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + + +/** + * @author aandryashin + * @author innokenty + */ +@SuppressWarnings("unused") +public class HierarchicalStyle extends ToStringStyle { + + { + setArrayContentDetail(true); + setUseShortClassName(true); + setUseIdentityHashCode(false); + setUseFieldNames(true); + } + + private final List leafPackageNames = new ArrayList() {{ + add("java.lang"); + }}; + + public HierarchicalStyle(String... leafPackageNames) { + this.leafPackageNames.addAll(Arrays.asList(leafPackageNames)); + } + + private boolean isLeaf(Object value) { + String className = value.getClass().getName(); + for (String packageName : leafPackageNames) { + if (className.startsWith(packageName)) { + return true; + } + } + return false; + } + + @Override + public void appendDetail(StringBuffer buffer, String fieldName, Object value) { + if (isLeaf(value)) { + buffer.append(value); + } else { + buffer.append(ReflectionToStringBuilder.toString(value, this)); + } + } + + @Override + public void appendDetail(StringBuffer buffer, String fieldName, Collection value) { + appendDetail(buffer, fieldName, value.toArray()); + } +} diff --git a/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/lang3/NoClassNameStyle.java b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/lang3/NoClassNameStyle.java new file mode 100644 index 0000000..20b5664 --- /dev/null +++ b/clay-utils/src/main/java/ru/yandex/qatools/clay/utils/lang3/NoClassNameStyle.java @@ -0,0 +1,15 @@ +package ru.yandex.qatools.clay.utils.lang3; + +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * @author innokenty + */ +@SuppressWarnings("unused") +public class NoClassNameStyle extends ToStringStyle { + + { + this.setUseClassName(false); + this.setUseIdentityHashCode(false); + } +} diff --git a/pom.xml b/pom.xml new file mode 100755 index 0000000..2ef9322 --- /dev/null +++ b/pom.xml @@ -0,0 +1,138 @@ + + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + ru.yandex.qatools.clay + clay + 2.0-SNAPSHOT + pom + + + clay-maven-settings-builder + clay-aether + clay-utils + + + Clay + + + scm:git:git@github.com:camelot-framework/clay.git + scm:git:git@github.com:camelot-framework/clay.git + https://github.com/camelot-framework/clay + + + https://github.com/camelot-framework/clay + + + UTF-8 + 3.1.0 + + + + Yandex + http://company.yandex.com + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + GitHub Issues + https://github.com/camelot-framework/clay/issues + + + + TeamCity + http://teamcity.qatools.ru/ + + + + + charlie + Baev Dmitry + charlie@yandex-team.ru + Yandex + + + innokenty + Innokentii Shuvalov + innokenty@yandex-team.ru + Yandex + + + + + + Camelot Mailing List + camelot@yandex-team.ru + + + + + 3.0.4 + + + + + + ru.yandex.qatools.clay + clay-maven + ${project.version} + + + ru.yandex.qatools.clay + clay-maven-settings-builder + ${project.version} + + + ru.yandex.qatools.clay + clay-utils + ${project.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + + jar + + + + + + org.apache.maven.plugins + maven-release-plugin + + true + + + + +