This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag slingstart-maven-plugin-1.1.0 in repository https://gitbox.apache.org/repos/asf/sling-slingstart-maven-plugin.git
commit e2fb05194d2e41419efa49fbdcf8da1b3cc37478 Author: Carsten Ziegeler <[email protected]> AuthorDate: Sun Apr 12 16:34:40 2015 +0000 Refactor slingstart maven plugin: resolve slingstart/slingfeature projects during setup of maven (reactor) project git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/tooling/maven/slingstart-maven-plugin@1673028 13f79535-47bb-0310-9956-ffa450edef68 --- .../maven/slingstart/AbstractSlingStartMojo.java | 3 + .../maven/slingstart/AttachSlingStartModel.java | 13 +- .../sling/maven/slingstart/BuildConstants.java | 2 + .../slingstart/DependencyLifecycleParticipant.java | 346 ++++++++++++++++----- .../apache/sling/maven/slingstart/ModelUtils.java | 335 ++------------------ .../sling/maven/slingstart/PreparePackageMojo.java | 37 +-- .../maven/slingstart/PrepareSlingStartMojo.java | 68 ---- .../sling/maven/slingstart/ProjectHelper.java | 98 ++++++ src/main/resources/META-INF/plexus/components.xml | 2 - 9 files changed, 426 insertions(+), 478 deletions(-) diff --git a/src/main/java/org/apache/sling/maven/slingstart/AbstractSlingStartMojo.java b/src/main/java/org/apache/sling/maven/slingstart/AbstractSlingStartMojo.java index 4aa4aab..f2024f8 100644 --- a/src/main/java/org/apache/sling/maven/slingstart/AbstractSlingStartMojo.java +++ b/src/main/java/org/apache/sling/maven/slingstart/AbstractSlingStartMojo.java @@ -25,6 +25,9 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; +/** + * Base class for all slingstart mojos. + */ public abstract class AbstractSlingStartMojo extends AbstractMojo { @Parameter(defaultValue="${basedir}/src/main/provisioning") diff --git a/src/main/java/org/apache/sling/maven/slingstart/AttachSlingStartModel.java b/src/main/java/org/apache/sling/maven/slingstart/AttachSlingStartModel.java index 77ef6ce..acfc7ed 100644 --- a/src/main/java/org/apache/sling/maven/slingstart/AttachSlingStartModel.java +++ b/src/main/java/org/apache/sling/maven/slingstart/AttachSlingStartModel.java @@ -31,8 +31,7 @@ import org.apache.sling.provisioning.model.Model; import org.apache.sling.provisioning.model.io.ModelWriter; /** - * Attaches the subsystem as a project artifact. - * + * Attaches the model as a project artifact. */ @Mojo( name = "attach-slingfeature", @@ -44,13 +43,16 @@ public class AttachSlingStartModel extends AbstractSlingStartMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { - final Model model = ModelUtils.getRawModel(this.project); + final Model model = ProjectHelper.getRawModel(this.project); - final File outputFile = new File(this.project.getBuild().getDirectory() + File.separatorChar + "slingstart.txt"); + // write the model + final File outputFile = new File(this.project.getBuild().getDirectory() + File.separatorChar + BuildConstants.MODEL_ARTIFACT_NAME); outputFile.getParentFile().mkdirs(); + Writer writer = null; try { + writer = new FileWriter(outputFile); ModelWriter.write(writer, model); } catch (IOException e) { @@ -64,7 +66,8 @@ public class AttachSlingStartModel extends AbstractSlingStartMojo { project.getArtifact().setFile(outputFile); } else { // otherwise attach it as an additional artifact - projectHelper.attachArtifact(project, BuildConstants.PACKAGING_PARTIAL_SYSTEM, BuildConstants.CLASSIFIER_PARTIAL_SYSTEM, outputFile); + projectHelper.attachArtifact(project, BuildConstants.PACKAGING_PARTIAL_SYSTEM, + BuildConstants.CLASSIFIER_PARTIAL_SYSTEM, outputFile); } } } diff --git a/src/main/java/org/apache/sling/maven/slingstart/BuildConstants.java b/src/main/java/org/apache/sling/maven/slingstart/BuildConstants.java index cc6b3af..07885fd 100644 --- a/src/main/java/org/apache/sling/maven/slingstart/BuildConstants.java +++ b/src/main/java/org/apache/sling/maven/slingstart/BuildConstants.java @@ -28,6 +28,8 @@ public abstract class BuildConstants { public static final String CONTEXT_STANDALONE = "slingstart" + ModelConstants.RUN_MODE_STANDALONE; public static final String CONTEXT_WEBAPP = "slingstart" + ModelConstants.RUN_MODE_WEBAPP; + // Model artifact name + public static final String MODEL_ARTIFACT_NAME = "slingstart.txt"; // Types diff --git a/src/main/java/org/apache/sling/maven/slingstart/DependencyLifecycleParticipant.java b/src/main/java/org/apache/sling/maven/slingstart/DependencyLifecycleParticipant.java index c65f427..895248a 100644 --- a/src/main/java/org/apache/sling/maven/slingstart/DependencyLifecycleParticipant.java +++ b/src/main/java/org/apache/sling/maven/slingstart/DependencyLifecycleParticipant.java @@ -17,11 +17,15 @@ package org.apache.sling.maven.slingstart; import java.io.File; +import java.io.FileReader; +import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.io.IOUtils; import org.apache.maven.AbstractMavenLifecycleParticipant; import org.apache.maven.MavenExecutionException; import org.apache.maven.artifact.Artifact; @@ -41,6 +45,8 @@ import org.apache.sling.provisioning.model.Model; import org.apache.sling.provisioning.model.ModelConstants; import org.apache.sling.provisioning.model.ModelUtility; import org.apache.sling.provisioning.model.RunMode; +import org.apache.sling.provisioning.model.Traceable; +import org.apache.sling.provisioning.model.io.ModelReader; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.Logger; @@ -55,7 +61,7 @@ public class DependencyLifecycleParticipant extends AbstractMavenLifecyclePartic private static final String PLUGIN_ID = "slingstart-maven-plugin"; @Requirement - private Logger log; + private Logger logger; @Requirement private ArtifactHandlerManager artifactHandlerManager; @@ -67,90 +73,102 @@ public class DependencyLifecycleParticipant extends AbstractMavenLifecyclePartic @Requirement private ArtifactResolver resolver; + public static final class ProjectInfo { + public MavenProject project; + public Plugin plugin; + public Model localModel; + public boolean done = false; + public Model model; + } + + public static final class Environment { + public ArtifactHandlerManager artifactHandlerManager; + public ArtifactResolver resolver; + public MavenSession session; + public Logger logger; + public final Map<String, ProjectInfo> modelProjects = new HashMap<String, ProjectInfo>(); + } + @Override public void afterProjectsRead(final MavenSession session) throws MavenExecutionException { - log.debug("Searching for slingstart projects..."); + final Environment env = new Environment(); + env.artifactHandlerManager = artifactHandlerManager; + env.resolver = resolver; + env.logger = logger; + env.session = session; + + logger.debug("Searching for " + BuildConstants.PACKAGING_SLINGSTART + "/" + BuildConstants.PACKAGING_PARTIAL_SYSTEM + " projects..."); + for (final MavenProject project : session.getProjects()) { - for (Plugin plugin : project.getBuild().getPlugins()) { - if (plugin.getArtifactId().equals(PLUGIN_ID)) { - log.debug("Found potential slingstart project: " + project); - try { - addDependencies(artifactHandlerManager, resolver, log, - session, project, plugin); - } catch (final Exception e) { - throw new MavenExecutionException("Unable to determine plugin-based dependencies for project " + project, e); + if ( project.getPackaging().equals(BuildConstants.PACKAGING_SLINGSTART) + || project.getPackaging().equals(BuildConstants.PACKAGING_PARTIAL_SYSTEM)) { + logger.debug("Found " + project.getPackaging() + " project: " + project); + // search plugin configuration (optional) + final ProjectInfo info = new ProjectInfo(); + for (Plugin plugin : project.getBuild().getPlugins()) { + if (plugin.getArtifactId().equals(PLUGIN_ID)) { + info.plugin = plugin; + break; } } + info.project = project; + env.modelProjects.put(project.getGroupId() + ":" + project.getArtifactId(), info); } } + + addDependencies(env); } - public static void addDependencies(final ArtifactHandlerManager artifactHandlerManager, - final ArtifactResolver resolver, - final Logger log, - final MavenSession session, - final MavenProject project, - final Plugin plugin) - throws Exception { - // get all projects of the current build - final Map<String, MavenProject> projectMap = new HashMap<String, MavenProject>(); - for (final MavenProject p : session.getProjects()) { - projectMap.put(p.getGroupId() + ":" + p.getArtifactId() + ":" + p.getVersion(), p); - } - - // check dependent projects first: slingstart or partial system - final List<Object> allDependencies = new ArrayList<Object>(); - final List<File> resolvedModelDependencies = new ArrayList<File>(); - for(final Dependency d : project.getDependencies() ) { - if ( d.getType().equals(BuildConstants.PACKAGING_SLINGSTART) - || d.getType().equals(BuildConstants.PACKAGING_PARTIAL_SYSTEM)) { - // if it's a project from the current reactor build, we can't resolve it right now - final String key = d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion(); - if ( projectMap.containsKey(key) ) { - allDependencies.add(key + ":" + (d.getClassifier() != null ? d.getClassifier() : "") - + ":" + (d.getType() != null ? d.getType() : "")); - } else { - // "external" dependency, we can already resolve it - final File modelFile = getSlingstartArtifact(artifactHandlerManager, resolver, project, session, d); - resolvedModelDependencies.add(modelFile); - allDependencies.add(modelFile); - } - } + public static void addDependencies(final Environment env) throws MavenExecutionException { + for(final ProjectInfo info : env.modelProjects.values()) { + addDependencies(env, info); } + } - // read local model - final String directory = nodeValue((Xpp3Dom) plugin.getConfiguration(), - "modelDirectory", new File(project.getBasedir(), "src/main/provisioning").getAbsolutePath()); - final Model model = ModelUtils.readFullModel(new File(directory), resolvedModelDependencies, project, session, log); + private static Model addDependencies(final Environment env, final ProjectInfo info) + throws MavenExecutionException { + if ( info.done == true ) { + env.logger.debug("Return prepared model for " + info.project); + return info.model; + } + // prevent recursion and multiple processing + info.done = true; + env.logger.debug("Processing project " + info.project); - ModelUtils.storeModelInfo(project, model, allDependencies); + // read local model + final String directory = nodeValue(info.plugin, + "modelDirectory", + new File(info.project.getBasedir(), "src/main/provisioning").getAbsolutePath()); + try { + info.localModel = readLocalModel(info.project, new File(directory), env.logger); + } catch ( final IOException ioe) { + throw new MavenExecutionException(ioe.getMessage(), ioe); + } // we have to create an effective model to add the dependencies - final Model effectiveModel = ModelUtility.getEffectiveModel(model, null); - - if ( project.getPackaging().equals(BuildConstants.PACKAGING_SLINGSTART ) ) { - // start with base artifact - final ModelUtils.SearchResult result = ModelUtils.findBaseArtifact(effectiveModel); - if ( result.artifact != null ) { - final String[] classifiers = new String[] {null, BuildConstants.CLASSIFIER_APP, BuildConstants.CLASSIFIER_WEBAPP}; - for(final String c : classifiers) { - final Dependency dep = new Dependency(); - dep.setGroupId(result.artifact.getGroupId()); - dep.setArtifactId(result.artifact.getArtifactId()); - dep.setVersion(result.artifact.getVersion()); - dep.setType(result.artifact.getType()); - dep.setClassifier(c); - if ( BuildConstants.CLASSIFIER_WEBAPP.equals(c) ) { - dep.setType(BuildConstants.TYPE_WAR); - } - dep.setScope(Artifact.SCOPE_PROVIDED); + final Model effectiveModel = ModelUtility.getEffectiveModel(info.localModel, null); - log.debug("- adding dependency " + dep); - project.getDependencies().add(dep); - } - } + final List<Model> dependencies = searchSlingstartDependencies(env, info, effectiveModel); + info.model = new Model(); + for(final Model d : dependencies) { + ModelUtility.merge(info.model, d); } - addDependenciesFromModel(project, effectiveModel, log); + ModelUtility.merge(info.model, effectiveModel); + info.model = ModelUtility.getEffectiveModel(info.model, null); + + final Map<Traceable, String> errors = ModelUtility.validate(info.model); + if ( errors != null ) { + throw new MavenExecutionException("Unable to create model file for " + info.project + " : " + errors, (File)null); + } + + addDependenciesFromModel(env, info); + + try { + ProjectHelper.storeProjectInfo(info); + } catch ( final IOException ioe) { + throw new MavenExecutionException(ioe.getMessage(), ioe); + } + return info.model; } /** @@ -158,10 +176,36 @@ public class DependencyLifecycleParticipant extends AbstractMavenLifecyclePartic * @param project The project * @param model The model * @param log The logger + * @throws MavenExecutionException */ - private static void addDependenciesFromModel(final MavenProject project, final Model model, final Logger log) { - for(final Feature feature : model.getFeatures()) { - // skip base + private static void addDependenciesFromModel( + final Environment env, + final ProjectInfo info) + throws MavenExecutionException { + if ( info.project.getPackaging().equals(BuildConstants.PACKAGING_SLINGSTART ) ) { + // add base artifact if defined in current model + final org.apache.sling.provisioning.model.Artifact baseArtifact = ModelUtils.findBaseArtifact(info.model); + + final String[] classifiers = new String[] {null, BuildConstants.CLASSIFIER_APP, BuildConstants.CLASSIFIER_WEBAPP}; + for(final String c : classifiers) { + final Dependency dep = new Dependency(); + dep.setGroupId(baseArtifact.getGroupId()); + dep.setArtifactId(baseArtifact.getArtifactId()); + dep.setVersion(baseArtifact.getVersion()); + dep.setType(baseArtifact.getType()); + dep.setClassifier(c); + if ( BuildConstants.CLASSIFIER_WEBAPP.equals(c) ) { + dep.setType(BuildConstants.TYPE_WAR); + } + dep.setScope(Artifact.SCOPE_PROVIDED); + + info.project.getDependencies().add(dep); + env.logger.debug("- adding base dependency " + ModelUtils.toString(dep)); + } + } + + for(final Feature feature : info.model.getFeatures()) { + // skip launchpad feature if ( feature.getName().equals(ModelConstants.FEATURE_LAUNCHPAD) ) { continue; } @@ -174,17 +218,105 @@ public class DependencyLifecycleParticipant extends AbstractMavenLifecyclePartic dep.setVersion(a.getVersion()); dep.setType(a.getType()); dep.setClassifier(a.getClassifier()); + dep.setScope(Artifact.SCOPE_PROVIDED); - log.debug("- adding dependency " + dep); - project.getDependencies().add(dep); + env.logger.debug("- adding dependency " + ModelUtils.toString(dep)); + info.project.getDependencies().add(dep); + } + } + } + } + } + + /** + * Search for dependent slingstart/slingfeature artifacts and remove them from the effective model. + * @throws MavenExecutionException + */ + private static List<Model> searchSlingstartDependencies( + final Environment env, + final ProjectInfo info, + final Model effectiveModel) + throws MavenExecutionException { + // slingstart or slingfeature + final List<Model> dependencies = new ArrayList<Model>(); + + for(final Feature feature : effectiveModel.getFeatures()) { + for(final RunMode runMode : feature.getRunModes()) { + for(final ArtifactGroup group : runMode.getArtifactGroups()) { + final List<org.apache.sling.provisioning.model.Artifact> removeList = new ArrayList<org.apache.sling.provisioning.model.Artifact>(); + for(final org.apache.sling.provisioning.model.Artifact a : group) { + if ( a.getType().equals(BuildConstants.PACKAGING_SLINGSTART) + || a.getType().equals(BuildConstants.PACKAGING_PARTIAL_SYSTEM)) { + + final Dependency dep = new Dependency(); + dep.setGroupId(a.getGroupId()); + dep.setArtifactId(a.getArtifactId()); + dep.setVersion(a.getVersion()); + dep.setType(BuildConstants.PACKAGING_PARTIAL_SYSTEM); + if ( a.getType().equals(BuildConstants.PACKAGING_SLINGSTART) ) { + dep.setClassifier(BuildConstants.PACKAGING_PARTIAL_SYSTEM); + } else { + dep.setClassifier(a.getClassifier()); + } + dep.setScope(Artifact.SCOPE_PROVIDED); + + env.logger.debug("- adding dependency " + ModelUtils.toString(dep)); + info.project.getDependencies().add(dep); + + // if it's a project from the current reactor build, we can't resolve it right now + final String key = a.getGroupId() + ":" + a.getArtifactId(); + if ( env.modelProjects.containsKey(key) ) { + env.logger.debug("Found reactor " + a.getType() + " dependency : " + a); + final Model model = addDependencies(env, env.modelProjects.get(key)); + if ( model == null ) { + throw new MavenExecutionException("Recursive model dependency list including project " + info.project, (File)null); + } + dependencies.add(model); + } else { + env.logger.debug("Found external " + a.getType() + " dependency: " + a); + // "external" dependency, we can already resolve it + final File modelFile = resolveSlingstartArtifact(env, info.project, dep); + FileReader r = null; + try { + r = new FileReader(modelFile); + final Model m = ModelReader.read(r, modelFile.getAbsolutePath()); + + final Map<Traceable, String> errors = ModelUtility.validate(m); + if ( errors != null ) { + throw new MavenExecutionException("Unable to read model file from " + modelFile + " : " + errors, modelFile); + } + dependencies.add(m); + } catch ( final IOException ioe) { + throw new MavenExecutionException("Unable to read model file from " + modelFile, ioe); + } finally { + try { + if ( r != null ) { + r.close(); + } + } catch ( final IOException io) { + // ignore + } + } + } + env.logger.debug("- adding dependency " + ModelUtils.toString(dep)); + info.project.getDependencies().add(dep); + + removeList.add(a); + } + } + for(final org.apache.sling.provisioning.model.Artifact r : removeList) { + group.remove(r); } } } } + + return dependencies; } - private static String nodeValue(final Xpp3Dom config, final String name, final String defaultValue) { + private static String nodeValue(final Plugin plugin, final String name, final String defaultValue) { + final Xpp3Dom config = plugin == null ? null : (Xpp3Dom)plugin.getConfiguration(); final Xpp3Dom node = (config == null ? null : config.getChild(name)); if (node != null) { return node.getValue(); @@ -193,10 +325,8 @@ public class DependencyLifecycleParticipant extends AbstractMavenLifecyclePartic } } - private static File getSlingstartArtifact(final ArtifactHandlerManager artifactHandlerManager, - final ArtifactResolver resolver, + private static File resolveSlingstartArtifact(final Environment env, final MavenProject project, - final MavenSession session, final Dependency d) throws MavenExecutionException { final Artifact prjArtifact = new DefaultArtifact(d.getGroupId(), @@ -205,9 +335,9 @@ public class DependencyLifecycleParticipant extends AbstractMavenLifecyclePartic Artifact.SCOPE_PROVIDED, d.getType(), d.getClassifier(), - artifactHandlerManager.getArtifactHandler(d.getType())); + env.artifactHandlerManager.getArtifactHandler(d.getType())); try { - resolver.resolve(prjArtifact, project.getRemoteArtifactRepositories(), session.getLocalRepository()); + env.resolver.resolve(prjArtifact, project.getRemoteArtifactRepositories(), env.session.getLocalRepository()); } catch (final ArtifactResolutionException e) { throw new MavenExecutionException("Unable to get artifact for " + d, e); } catch (final ArtifactNotFoundException e) { @@ -215,4 +345,60 @@ public class DependencyLifecycleParticipant extends AbstractMavenLifecyclePartic } return prjArtifact.getFile(); } + + /** + * Read all model files from the directory in alphabetical order. + * Only files ending with .txt or .model are read. + * + * @param project The current maven project + * @param modelDirectory The directory to scan for models + * @param logger The logger + */ + private static Model readLocalModel( + final MavenProject project, + final File modelDirectory, + final Logger logger) + throws MavenExecutionException, IOException { + final List<String> candidates = new ArrayList<String>(); + if ( modelDirectory != null && modelDirectory.exists() ) { + for(final File f : modelDirectory.listFiles() ) { + if ( f.isFile() && !f.getName().startsWith(".") ) { + if ( f.getName().endsWith(".txt") || f.getName().endsWith(".model") ) { + candidates.add(f.getName()); + } + } + } + Collections.sort(candidates); + } + if ( candidates.size() == 0 ) { + throw new MavenExecutionException("No model files found in " + modelDirectory, (File)null); + } + final Model result = new Model(); + for(final String name : candidates) { + logger.debug("Reading model " + name + " in project " + project.getId()); + try { + final File f = new File(modelDirectory, name); + final FileReader reader = new FileReader(f); + try { + final Model current = ModelReader.read(reader, f.getAbsolutePath()); + final Map<Traceable, String> errors = ModelUtility.validate(current); + if (errors != null ) { + throw new MavenExecutionException("Invalid model at " + name + " : " + errors, (File)null); + } + ModelUtility.merge(result, current); + } finally { + IOUtils.closeQuietly(reader); + } + } catch ( final IOException io) { + throw new MavenExecutionException("Unable to read model at " + name, io); + } + } + + final Map<Traceable, String> errors = ModelUtility.validate(result); + if (errors != null ) { + throw new MavenExecutionException("Invalid assembled model : " + errors, (File)null); + } + + return result; + } } diff --git a/src/main/java/org/apache/sling/maven/slingstart/ModelUtils.java b/src/main/java/org/apache/sling/maven/slingstart/ModelUtils.java index 098d1ca..ccde9e4 100644 --- a/src/main/java/org/apache/sling/maven/slingstart/ModelUtils.java +++ b/src/main/java/org/apache/sling/maven/slingstart/ModelUtils.java @@ -17,17 +17,9 @@ package org.apache.sling.maven.slingstart; import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; import java.util.Set; -import org.apache.commons.io.IOUtils; +import org.apache.maven.MavenExecutionException; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; @@ -42,164 +34,10 @@ import org.apache.maven.project.MavenProject; import org.apache.sling.provisioning.model.Feature; import org.apache.sling.provisioning.model.Model; import org.apache.sling.provisioning.model.ModelConstants; -import org.apache.sling.provisioning.model.ModelUtility; import org.apache.sling.provisioning.model.RunMode; -import org.apache.sling.provisioning.model.Traceable; -import org.apache.sling.provisioning.model.io.ModelReader; -import org.apache.sling.provisioning.model.io.ModelWriter; -import org.codehaus.plexus.logging.Logger; public abstract class ModelUtils { - private static final String EXT_TXT = ".txt"; - private static final String EXT_MODEL = ".model"; - - /** - * Read all model files from the directory in alphabetical order. - * Only files ending with .txt or .model are read. - * - * @param startingModel The model into which the read models are merged or {@code null} - * @param modelDirectory The directory to scan for models - * @param project The current maven project - * @param session The current maven session - * @param logger The logger - */ - private static Model readLocalModel(final Model startingModel, - final File modelDirectory, - final MavenProject project, - final MavenSession session, - final Logger logger) - throws MojoExecutionException { - final Model result = (startingModel != null ? startingModel : new Model()); - final List<String> candidates = new ArrayList<String>(); - if ( modelDirectory != null && modelDirectory.exists() ) { - for(final File f : modelDirectory.listFiles() ) { - if ( f.isFile() && !f.getName().startsWith(".") ) { - if ( f.getName().endsWith(EXT_TXT) || f.getName().endsWith(EXT_MODEL) ) { - candidates.add(f.getName()); - } - } - } - Collections.sort(candidates); - } - if ( candidates.size() == 0 ) { - throw new MojoExecutionException("No model files found in " + modelDirectory); - } - for(final String name : candidates) { - logger.debug("Reading model " + name + " in project " + project.getId()); - try { - final File f = new File(modelDirectory, name); - final FileReader reader = new FileReader(f); - try { - final Model current = ModelReader.read(reader, f.getAbsolutePath()); - final Map<Traceable, String> errors = ModelUtility.validate(current); - if (errors != null ) { - throw new MojoExecutionException("Invalid model at " + name + " : " + errors); - } - ModelUtility.merge(result, current); - } finally { - IOUtils.closeQuietly(reader); - } - } catch ( final IOException io) { - throw new MojoExecutionException("Unable to read model at " + name, io); - } - } - - final Map<Traceable, String> errors = ModelUtility.validate(result); - if (errors != null ) { - throw new MojoExecutionException("Invalid assembled model : " + errors); - } - - return result; - } - - /** - * Read the full model - */ - public static Model readFullModel(final File modelDirectory, - final List<File> dependentModels, - final MavenProject project, - final MavenSession session, - final Logger logger) - throws MojoExecutionException { - try { - // read dependent models - Model depModel = null; - if ( dependentModels != null ) { - for(final File file : dependentModels) { - FileReader r = null; - try { - r = new FileReader(file); - if ( depModel == null ) { - depModel = new Model(); - } - final Model readModel = ModelReader.read(r, file.getAbsolutePath()); - final Map<Traceable, String> errors = ModelUtility.validate(readModel); - if (errors != null ) { - throw new MojoExecutionException("Invalid model at " + file + " : " + errors); - } - ModelUtility.merge(depModel, readModel); - } finally { - IOUtils.closeQuietly(r); - } - } - } - if ( depModel != null ) { - final Map<Traceable, String> errors = ModelUtility.validate(depModel); - if (errors != null ) { - throw new MojoExecutionException("Invalid model : " + errors); - } - } - - final Model result = readLocalModel(depModel, modelDirectory, project, session, logger); - - return result; - } catch ( final IOException ioe) { - throw new MojoExecutionException("Unable to cache model", ioe); - } - } - - public static final class SearchResult { - public org.apache.sling.provisioning.model.Artifact artifact; - public String errorMessage; - } - - public static SearchResult findBaseArtifact(final Model model) throws MojoExecutionException { - final SearchResult result = new SearchResult(); - final Feature base = model.getFeature(ModelConstants.FEATURE_LAUNCHPAD); - if ( base == null ) { - result.errorMessage = "No launchpad feature found."; - } else { - // get global run mode - final RunMode runMode = base.getRunMode(); - if ( runMode == null ) { - result.errorMessage = "No global run mode found in launchpad feature."; - } else { - if ( runMode.getArtifactGroups().isEmpty() ) { - result.errorMessage = "No base artifacts defined."; - } else if ( runMode.getArtifactGroups().size() > 1 ) { - result.errorMessage = "Base run mode should only have a single start level."; - } else { - org.apache.sling.provisioning.model.Artifact firstArtifact = null; - for(final org.apache.sling.provisioning.model.Artifact a : runMode.getArtifactGroups().get(0)) { - if ( firstArtifact == null ) { - firstArtifact = a; - } else { - result.errorMessage = "Base run mode should contain exactly one artifact."; - break; - } - } - if ( firstArtifact == null ) { - result.errorMessage = "No base artifacts defined."; - } - if ( result.errorMessage == null ) { - result.artifact = firstArtifact; - } - } - } - } - return result; - } /** * Get a resolved Artifact from the coordinates provided @@ -240,155 +78,42 @@ public abstract class ModelUtils { return prjArtifact; } - private static final String RAW_MODEL_TXT = Model.class.getName() + "/raw.txt"; - private static final String RAW_MODEL_DEPS = Model.class.getName() + "/raw.deps"; - - private static final String EFFECTIVE_MODEL = Model.class.getName() + "/effective"; - private static final String RAW_MODEL = Model.class.getName() + "/raw"; - - /** - * Store the model info from the dependency lifecycle participant - * @param project The maven project - * @param model The local model - * @param dependencies The dependencies (either String or File objects) - * @throws IOException If writing fails - */ - public static void storeModelInfo(final MavenProject project, final Model model, final List<Object> dependencies) - throws IOException { - // we have to serialize as the dependency lifecycle participant uses a different class loader (!) - final StringWriter w = new StringWriter(); - ModelWriter.write(w, model); - project.setContextValue(RAW_MODEL_TXT, w.toString()); - project.setContextValue(RAW_MODEL_DEPS, dependencies); - } - - public static void prepareModel(final MavenProject project, - final MavenSession session) - throws MojoExecutionException { - final String contents = (String)project.getContextValue(RAW_MODEL_TXT); - final Model localModel; - try { - localModel = ModelReader.read(new StringReader(contents), null); - } catch ( final IOException ioe) { - throw new MojoExecutionException("Unable to read cached model.", ioe); - } - final List<File> modelDependencies = new ArrayList<File>(); - @SuppressWarnings("unchecked") - final List<Object> localDeps = (List<Object>)project.getContextValue(RAW_MODEL_DEPS); - for(final Object o : localDeps) { - if ( o instanceof String ) { - final String[] info = ((String)o).split(":"); - - final Dependency dep = new Dependency(); - dep.setGroupId(info[0]); - dep.setArtifactId(info[1]); - dep.setVersion(info[2]); - if ( info[3] != null && info[3].length() > 0 ) { - dep.setClassifier(info[3]); - } - if ( info[4] != null && info[4].length() > 0 ) { - dep.setType(info[4]); - } - modelDependencies.add(getSlingstartArtifact(project, session, dep)); - } else { - modelDependencies.add((File)o); - } - } - // read dependent models - Model depModel = null; - for(final File file : modelDependencies) { - FileReader r = null; - try { - r = new FileReader(file); - if ( depModel == null ) { - depModel = new Model(); - } - final Model readModel = ModelReader.read(r, file.getAbsolutePath()); - final Map<Traceable, String> errors = ModelUtility.validate(readModel); - if (errors != null ) { - throw new MojoExecutionException("Invalid model at " + file + " : " + errors); - } - ModelUtility.merge(depModel, readModel); - } catch ( final IOException ioe) { - throw new MojoExecutionException("Unable to read model from " + file, ioe); - } finally { - IOUtils.closeQuietly(r); - } - } - - final Model rawModel; - if ( depModel != null ) { - ModelUtility.merge(depModel, localModel); - final Map<Traceable, String> errors = ModelUtility.validate(depModel); - if (errors != null ) { - throw new MojoExecutionException("Invalid model : " + errors); - } - rawModel = depModel; + public static org.apache.sling.provisioning.model.Artifact findBaseArtifact(final Model model) + throws MavenExecutionException { + final Feature base = model.getFeature(ModelConstants.FEATURE_LAUNCHPAD); + if ( base == null ) { + throw new MavenExecutionException("No launchpad feature found.", (File)null); } else { - rawModel = localModel; - } - - // store raw model - project.setContextValue(RAW_MODEL, rawModel); - // create and store effective model - final Model effectiveModel = ModelUtility.getEffectiveModel(rawModel, null); - project.setContextValue(EFFECTIVE_MODEL, effectiveModel); - } - - private static File getSlingstartArtifact(final MavenProject project, - final MavenSession session, - final Dependency dep) - throws MojoExecutionException { - for (final MavenProject p : session.getProjects()) { - // we only need to find the group id / artifact id, version is correct anyway - if ( p.getGroupId().equals(dep.getGroupId()) - && p.getArtifactId().equals(dep.getArtifactId()) ) { - - // check main artifact first - if ( dep.getClassifier() == null && p.getPackaging().equals(dep.getType()) ) { - if ( p.getArtifact() != null && p.getArtifact().getFile() != null ) { - return p.getArtifact().getFile(); - } - } - // followed by attached artifacts - for(final Artifact a : p.getAttachedArtifacts()) { - if ( equals(a.getType(), dep.getType() ) && equals(a.getClassifier(), dep.getClassifier())) { - if ( a.getFile() != null ) { - return a.getFile(); + // get global run mode + final RunMode runMode = base.getRunMode(); + if ( runMode == null ) { + throw new MavenExecutionException("No global run mode found in launchpad feature.", (File)null); + } else { + if ( runMode.getArtifactGroups().isEmpty() ) { + throw new MavenExecutionException("No base artifacts defined.", (File)null); + } else if ( runMode.getArtifactGroups().size() > 1 ) { + throw new MavenExecutionException("Base run mode should only have a single start level.", (File)null); + } else { + org.apache.sling.provisioning.model.Artifact firstArtifact = null; + for(final org.apache.sling.provisioning.model.Artifact a : runMode.getArtifactGroups().get(0)) { + if ( firstArtifact == null ) { + firstArtifact = a; + } else { + throw new MavenExecutionException("Base run mode should contain exactly one artifact.", (File)null); } } + if ( firstArtifact == null ) { + throw new MavenExecutionException("No base artifacts defined.", (File)null); + } + return firstArtifact; } - break; } } - throw new MojoExecutionException("Unable to find dependency build artifact " + dep); - } - - private final static boolean equals(final String a, final String b) { - if ( a == null && b == null ) { - return true; - } - if ( a == null ) { - return false; - } - return a.equals(b); } - /** - * Get the effective model from the project - * @param project The maven projet - * @return The effective model - */ - public static Model getEffectiveModel(final MavenProject project) { - return (Model)project.getContextValue(EFFECTIVE_MODEL); - } - - /** - * Get the raw model from the project - * @param project The maven projet - * @return The raw model - */ - public static Model getRawModel(final MavenProject project) { - return (Model)project.getContextValue(RAW_MODEL); + public static String toString(final Dependency d) { + return "Dependency {groupId=" + d.getGroupId() + ", artifactId=" + d.getArtifactId() + ", version=" + d.getVersion() + + (d.getClassifier() != null ? ", classifier=" + d.getClassifier() : "") + + ", type=" + d.getType() + "}"; } } diff --git a/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java b/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java index 90eb778..28c14d2 100644 --- a/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java +++ b/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java @@ -28,6 +28,7 @@ import java.util.TreeSet; import org.apache.commons.io.IOUtils; import org.apache.felix.cm.file.ConfigurationHandler; +import org.apache.maven.MavenExecutionException; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.artifact.resolver.ArtifactResolver; @@ -90,7 +91,7 @@ public class PreparePackageMojo extends AbstractSlingStartMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { - final Model model = ModelUtils.getEffectiveModel(this.project); + final Model model = ProjectHelper.getEffectiveModel(this.project); this.prepareGlobal(model); this.prepareStandaloneApp(model); @@ -323,24 +324,24 @@ public class PreparePackageMojo extends AbstractSlingStartMojo { * Return the base artifact */ private Artifact getBaseArtifact(final Model model, final String classifier, final String type) throws MojoExecutionException { - final ModelUtils.SearchResult result = ModelUtils.findBaseArtifact(model); - if ( result.errorMessage != null ) { - throw new MojoExecutionException(result.errorMessage); - } - final org.apache.sling.provisioning.model.Artifact baseArtifact = result.artifact; - - final Artifact a = ModelUtils.getArtifact(this.project, this.mavenSession, this.artifactHandlerManager, this.resolver, - baseArtifact.getGroupId(), - baseArtifact.getArtifactId(), - baseArtifact.getVersion(), - type, - classifier); - if (a == null) { - throw new MojoExecutionException( - String.format("Project doesn't have a base dependency of groupId %s and artifactId %s", - baseArtifact.getGroupId(), baseArtifact.getArtifactId())); + try { + final org.apache.sling.provisioning.model.Artifact baseArtifact = ModelUtils.findBaseArtifact(model); + + final Artifact a = ModelUtils.getArtifact(this.project, this.mavenSession, this.artifactHandlerManager, this.resolver, + baseArtifact.getGroupId(), + baseArtifact.getArtifactId(), + baseArtifact.getVersion(), + type, + classifier); + if (a == null) { + throw new MojoExecutionException( + String.format("Project doesn't have a base dependency of groupId %s and artifactId %s", + baseArtifact.getGroupId(), baseArtifact.getArtifactId())); + } + return a; + } catch ( final MavenExecutionException mee) { + throw new MojoExecutionException(mee.getMessage(), mee.getCause()); } - return a; } /** diff --git a/src/main/java/org/apache/sling/maven/slingstart/PrepareSlingStartMojo.java b/src/main/java/org/apache/sling/maven/slingstart/PrepareSlingStartMojo.java deleted file mode 100644 index d7a1184..0000000 --- a/src/main/java/org/apache/sling/maven/slingstart/PrepareSlingStartMojo.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ -package org.apache.sling.maven.slingstart; - -import org.apache.maven.artifact.Artifact; -import org.apache.maven.model.Dependency; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.ResolutionScope; - -/** - * Prepares the project - * - */ -@Mojo( - name = "prepare", - defaultPhase = LifecyclePhase.VALIDATE, - requiresDependencyResolution = ResolutionScope.TEST, - threadSafe = true - ) -public class PrepareSlingStartMojo extends AbstractSlingStartMojo { - - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - ModelUtils.prepareModel(this.project, this.mavenSession); - - if ( project.getPackaging().equals(BuildConstants.PACKAGING_SLINGSTART ) ) { - // add dependencies for base artifact - final ModelUtils.SearchResult result = ModelUtils.findBaseArtifact(ModelUtils.getEffectiveModel(project)); - if ( result.artifact != null ) { - final String[] classifiers = new String[] {null, BuildConstants.CLASSIFIER_APP, BuildConstants.CLASSIFIER_WEBAPP}; - for(final String c : classifiers) { - final Dependency dep = new Dependency(); - dep.setGroupId(result.artifact.getGroupId()); - dep.setArtifactId(result.artifact.getArtifactId()); - dep.setVersion(result.artifact.getVersion()); - dep.setType(result.artifact.getType()); - dep.setClassifier(c); - if ( BuildConstants.CLASSIFIER_WEBAPP.equals(c) ) { - dep.setType(BuildConstants.TYPE_WAR); - } - dep.setScope(Artifact.SCOPE_PROVIDED); - - getLog().debug("Adding base dependency " + dep); - project.getDependencies().add(dep); - } - } else { - throw new MojoExecutionException(result.errorMessage); - } - } - } -} diff --git a/src/main/java/org/apache/sling/maven/slingstart/ProjectHelper.java b/src/main/java/org/apache/sling/maven/slingstart/ProjectHelper.java new file mode 100644 index 0000000..bf13b00 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/ProjectHelper.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.sling.maven.slingstart; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.sling.provisioning.model.Model; +import org.apache.sling.provisioning.model.ModelUtility; +import org.apache.sling.provisioning.model.io.ModelReader; +import org.apache.sling.provisioning.model.io.ModelWriter; + +public abstract class ProjectHelper { + + /** The raw local model. */ + private static final String RAW_MODEL_TXT = Model.class.getName() + "/raw.txt"; + private static final String RAW_MODEL_CACHE = Model.class.getName() + "/raw.cache"; + + private static final String EFFECTIVE_MODEL_TXT = Model.class.getName() + "/effective.txt"; + private static final String EFFECTIVE_MODEL_CACHE = Model.class.getName() + "/effective.cache"; + + /** + * + * @param info The project info + * @throws IOException If writing fails + */ + public static void storeProjectInfo(final DependencyLifecycleParticipant.ProjectInfo info) + throws IOException { + // we have to serialize as the dependency lifecycle participant uses a different class loader (!) + final StringWriter w1 = new StringWriter(); + ModelWriter.write(w1, info.localModel); + info.project.setContextValue(RAW_MODEL_TXT, w1.toString()); + + final StringWriter w2 = new StringWriter(); + ModelWriter.write(w2, info.model); + info.project.setContextValue(EFFECTIVE_MODEL_TXT, w2.toString()); + } + + /** + * Get the effective model from the project + * @param project The maven projet + * @return The effective model + * @throws MojoExecutionException If reading fails + */ + public static Model getEffectiveModel(final MavenProject project) + throws MojoExecutionException { + Model result = (Model) project.getContextValue(EFFECTIVE_MODEL_CACHE); + if ( result == null ) { + try { + final StringReader r = new StringReader((String)project.getContextValue(EFFECTIVE_MODEL_TXT)); + result = ModelReader.read(r, project.getId()); + result = ModelUtility.getEffectiveModel(result, null); + project.setContextValue(EFFECTIVE_MODEL_CACHE, result); + } catch ( final IOException ioe) { + throw new MojoExecutionException(ioe.getMessage(), ioe); + } + } + return result; + } + + /** + * Get the raw model from the project + * @param project The maven projet + * @return The raw local model + * @throws MojoExecutionException If reading fails + */ + public static Model getRawModel(final MavenProject project) + throws MojoExecutionException { + Model result = (Model) project.getContextValue(RAW_MODEL_CACHE); + if ( result == null ) { + try { + final StringReader r = new StringReader((String)project.getContextValue(RAW_MODEL_TXT)); + result = ModelReader.read(r, project.getId()); + project.setContextValue(RAW_MODEL_CACHE, result); + } catch ( final IOException ioe) { + throw new MojoExecutionException(ioe.getMessage(), ioe); + } + } + return result; + } +} diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml index 323d663..21f4ced 100644 --- a/src/main/resources/META-INF/plexus/components.xml +++ b/src/main/resources/META-INF/plexus/components.xml @@ -27,7 +27,6 @@ <lifecycle> <id>default</id> <phases> - <validate>org.apache.sling:slingstart-maven-plugin:prepare</validate> <package>org.apache.sling:slingstart-maven-plugin:attach-slingfeature</package> <install>org.apache.maven.plugins:maven-install-plugin:install</install> <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy> @@ -45,7 +44,6 @@ <lifecycle> <id>default</id> <phases> - <validate>org.apache.sling:slingstart-maven-plugin:prepare</validate> <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources> <compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile> <process-test-resources> -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
