This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag slingstart-maven-plugin-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-slingstart-maven-plugin.git
commit 87744a466de8c0955934568a0860dae75a8f572b Author: Carsten Ziegeler <[email protected]> AuthorDate: Fri Sep 19 08:12:35 2014 +0000 Add slingstart maven plugin git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/tooling/maven/slingstart-maven-plugin@1626140 13f79535-47bb-0310-9956-ffa450edef68 --- .../maven/slingstart/AbstractSubsystemMojo.java | 72 ++++ .../maven/slingstart/AttachSlingSubsystem.java | 69 ++++ .../sling/maven/slingstart/BuildConstants.java | 98 +++++ .../slingstart/DependencyLifecycleParticipant.java | 194 ++++++++++ .../sling/maven/slingstart/JarArchiverHelper.java | 180 ++++++++++ .../apache/sling/maven/slingstart/PackageMojo.java | 121 +++++++ .../sling/maven/slingstart/PreparePackageMojo.java | 400 +++++++++++++++++++++ .../sling/maven/slingstart/SubsystemUtils.java | 179 +++++++++ src/main/resources/META-INF/plexus/components.xml | 95 +++++ 9 files changed, 1408 insertions(+) diff --git a/src/main/java/org/apache/sling/maven/slingstart/AbstractSubsystemMojo.java b/src/main/java/org/apache/sling/maven/slingstart/AbstractSubsystemMojo.java new file mode 100644 index 0000000..121ef2c --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/AbstractSubsystemMojo.java @@ -0,0 +1,72 @@ +/* + * 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.File; +import java.io.IOException; +import java.io.StringReader; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.MavenProjectHelper; +import org.apache.sling.slingstart.model.SSMSubsystem; +import org.apache.sling.slingstart.model.xml.XMLSSMModelReader; + +public abstract class AbstractSubsystemMojo extends AbstractMojo { + + @Parameter(defaultValue="${basedir}/src/main/systems") + protected File systemsDirectory; + + @Parameter(property = "project", readonly = true, required = true) + protected MavenProject project; + + @Component + protected MavenProjectHelper projectHelper; + + @Parameter(property = "session", readonly = true, required = true) + protected MavenSession mavenSession; + + @Parameter(defaultValue="false") + protected boolean createWebapp; + + /** + * Read the model prepared by the lifecycle plugin + */ + protected SSMSubsystem readModel() + throws MojoExecutionException { + SSMSubsystem result = (SSMSubsystem)this.project.getContextValue(SSMSubsystem.class.getName()); + if ( result == null ) { + try { + final String contents = (String)this.project.getContextValue(SSMSubsystem.class.getName() + "/text"); + result = XMLSSMModelReader.read(new StringReader(contents)); + + this.project.setContextValue(SSMSubsystem.class.getName(), result); + } catch ( final IOException ioe) { + throw new MojoExecutionException("Unable to cache model", ioe); + } + } + return result; + } + + protected File getTmpDir() { + return new File(this.project.getBuild().getDirectory(), "slingstart-tmp"); + } +} diff --git a/src/main/java/org/apache/sling/maven/slingstart/AttachSlingSubsystem.java b/src/main/java/org/apache/sling/maven/slingstart/AttachSlingSubsystem.java new file mode 100644 index 0000000..72a9687 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/AttachSlingSubsystem.java @@ -0,0 +1,69 @@ +/* + * 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.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; + +import org.apache.commons.io.IOUtils; +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; +import org.apache.sling.slingstart.model.SSMSubsystem; +import org.apache.sling.slingstart.model.xml.XMLSSMModelWriter; + +/** + * Attaches the subsystem as a project artifact. + * + */ +@Mojo( + name = "attach-slingsubsystem", + defaultPhase = LifecyclePhase.PACKAGE, + requiresDependencyResolution = ResolutionScope.TEST, + threadSafe = true + ) +public class AttachSlingSubsystem extends AbstractSubsystemMojo { + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + final SSMSubsystem model = this.readModel(); + + final File outputFile = new File(this.project.getBuild().getDirectory() + File.separatorChar + "slingstart.xml"); + outputFile.getParentFile().mkdirs(); + Writer writer = null; + try { + writer = new FileWriter(outputFile); + XMLSSMModelWriter.write(writer, model); + } catch (IOException e) { + throw new MojoExecutionException("Unable to write model to " + outputFile, e); + } finally { + IOUtils.closeQuietly(writer); + } + + // if this project is a partial bundle list, it's the main artifact + if ( project.getPackaging().equals(BuildConstants.PACKAGING_PARTIAL_SYSTEM) ) { + project.getArtifact().setFile(outputFile); + } else { + // otherwise attach it as an additional artifact + projectHelper.attachArtifact(project, BuildConstants.TYPE_XML, 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 new file mode 100644 index 0000000..169bcdc --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/BuildConstants.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.util.ArrayList; +import java.util.List; + +import org.apache.sling.slingstart.model.SSMRunMode; + +public abstract class BuildConstants { + + // CONTEXTS + public static final String CONTEXT_GLOBAL = "slingstart:global"; + public static final String CONTEXT_STANDALONE = "slingstart" + SSMRunMode.RUN_MODE_STANDALONE; + public static final String CONTEXT_WEBAPP = "slingstart" + SSMRunMode.RUN_MODE_WEBAPP; + + + // Types + + public static final String TYPE_JAR = "jar"; + + public static final String TYPE_WAR = "war"; + + public static final String TYPE_POM = "pom"; + + public static final String TYPE_XML = "xml"; + + public static final String PACKAGING_PARTIAL_SYSTEM = "slingsubsystem"; + + public static final String PACKAGING_SLINGSTART = "slingstart"; + + // Classifiers + + public static final String CLASSIFIER_PARTIAL_SYSTEM = "slingsubsystem"; + + public static final String CLASSIFIER_BASE = "base"; + + public static final String CLASSIFIER_APP = "app"; + + public static final String CLASSIFIER_WEBAPP = "webapp"; + + // Manifest attributes + + public static final String ATTR_BUILT_BY = "Built-By"; + + public static final String ATTR_CREATED_BY = "Created-By"; + + public static final String ATTR_IMPLEMENTATION_VERSION = "Implementation-Version"; + + public static final String ATTR_IMPLEMENTATION_VENDOR = "Implementation-Vendor"; + + public static final String ATTR_IMPLEMENTATION_BUILD = "Implementation-Build"; + + public static final String ATTR_IMPLEMENTATION_VENDOR_ID = "Implementation-Vendor-Id"; + + public static final String ATTR_IMPLEMENTATION_TITLE = "Implementation-Title"; + + public static final String ATTR_SPECIFICATION_TITLE = "Specification-Title"; + + public static final String ATTR_SPECIFICATION_VENDOR = "Specification-Vendor"; + + public static final String ATTR_SPECIFICATION_VERSION = "Specification-Version"; + + public static final String ATTR_MAIN_CLASS = "Main-Class"; + + public static final String ATTR_VALUE_MAIN_CLASS = "org.apache.sling.launchpad.app.Main"; + + public static final List<String> ATTRS_EXCLUDES = new ArrayList<String>(); + static { + ATTRS_EXCLUDES.add(ATTR_BUILT_BY); + ATTRS_EXCLUDES.add(ATTR_CREATED_BY); + ATTRS_EXCLUDES.add(ATTR_IMPLEMENTATION_VERSION); + ATTRS_EXCLUDES.add(ATTR_IMPLEMENTATION_VENDOR); + ATTRS_EXCLUDES.add(ATTR_IMPLEMENTATION_BUILD); + ATTRS_EXCLUDES.add(ATTR_IMPLEMENTATION_VENDOR_ID); + ATTRS_EXCLUDES.add(ATTR_IMPLEMENTATION_TITLE); + ATTRS_EXCLUDES.add(ATTR_SPECIFICATION_TITLE); + ATTRS_EXCLUDES.add(ATTR_SPECIFICATION_VENDOR); + ATTRS_EXCLUDES.add(ATTR_SPECIFICATION_VERSION); + } + + // build constants + public static final String WEBAPP_OUTDIR = "slingstart-webapp"; +} diff --git a/src/main/java/org/apache/sling/maven/slingstart/DependencyLifecycleParticipant.java b/src/main/java/org/apache/sling/maven/slingstart/DependencyLifecycleParticipant.java new file mode 100644 index 0000000..797d867 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/DependencyLifecycleParticipant.java @@ -0,0 +1,194 @@ +/* + * 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.File; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.AbstractMavenLifecycleParticipant; +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; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Plugin; +import org.apache.maven.project.MavenProject; +import org.apache.sling.slingstart.model.SSMArtifact; +import org.apache.sling.slingstart.model.SSMRunMode; +import org.apache.sling.slingstart.model.SSMStartLevel; +import org.apache.sling.slingstart.model.SSMSubsystem; +import org.apache.sling.slingstart.model.xml.XMLSSMModelWriter; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.codehaus.plexus.logging.Logger; +import org.codehaus.plexus.util.xml.Xpp3Dom; + +/** + * Maven lifecycle participant which adds the artifacts of the model to the dependencies. + */ +@Component(role = AbstractMavenLifecycleParticipant.class) +public class DependencyLifecycleParticipant extends AbstractMavenLifecycleParticipant { + + private static final String PLUGIN_ID = "slingstart-maven-plugin"; + + private static final String PROVIDED = "provided"; + + @Requirement + private Logger log; + + @Requirement + private ArtifactHandlerManager artifactHandlerManager; + + /** + * Used to look up Artifacts in the remote repository. + * + */ + @Requirement + private ArtifactResolver resolver; + + @Override + public void afterProjectsRead(final MavenSession session) throws MavenExecutionException { + log.info("Searching for slingstart projects..."); + try { + final Map<String, MavenProject> projectMap = new HashMap<String, MavenProject>(); + for (final MavenProject project : session.getProjects()) { + projectMap.put(project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion(), + project); + } + + for (final MavenProject project : session.getProjects()) { + for (Plugin plugin : project.getBuild().getPlugins()) { + if (plugin.getArtifactId().equals(PLUGIN_ID)) { + addDependencies(artifactHandlerManager, resolver, log, + session, project, plugin); + } + } + } + } catch (final Exception e) { + throw new MavenExecutionException("Unable to determine plugin-based dependencies", e); + } + } + + public static void addDependencies(final ArtifactHandlerManager artifactHandlerManager, + final ArtifactResolver resolver, + final Logger log, + final MavenSession session, final MavenProject project, final Plugin plugin) + throws Exception { + // check dependent projects first + final List<File> dependencies = new ArrayList<File>(); + for(final Dependency d : project.getDependencies() ) { + if ( d.getType().equals(BuildConstants.PACKAGING_SLINGSTART) + || d.getType().equals(BuildConstants.PACKAGING_PARTIAL_SYSTEM)) { + final File modelXML = getSlingstartArtifact(artifactHandlerManager, resolver, project, session, d); + dependencies.add(modelXML); + } + } + + final String directory = nodeValue((Xpp3Dom) plugin.getConfiguration(), + "systemsDirectory", new File(project.getBasedir(), "src/main/systems").getAbsolutePath()); + final SSMSubsystem model = SubsystemUtils.readFullModel(new File(directory), dependencies, project, session, log); + + final StringWriter w = new StringWriter(); + XMLSSMModelWriter.write(w, model); + project.setContextValue(SSMSubsystem.class.getName() + "/text", w.toString()); + + // start with base artifact + final SSMArtifact base = SubsystemUtils.getBaseArtifact(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(base.groupId); + dep.setArtifactId(base.artifactId); + dep.setVersion(model.getValue(base.version)); + dep.setType(base.type); + dep.setClassifier(c); + if ( BuildConstants.CLASSIFIER_WEBAPP.equals(c) ) { + dep.setType(BuildConstants.TYPE_WAR); + } + dep.setScope(PROVIDED); + + log.debug("- adding dependency " + dep); + project.getDependencies().add(dep); + } + + addDependencies(model, log, project); + } + + private static void addDependencies(final SSMSubsystem model, final Logger log, final MavenProject project) { + for(final SSMRunMode runMode : model.runModes) { + // skip base + if ( runMode.isRunMode(SSMRunMode.RUN_MODE_BASE) ) { + continue; + } + for(final SSMStartLevel sl : runMode.startLevels) { + for(final SSMArtifact a : sl.artifacts) { + final Dependency dep = new Dependency(); + dep.setGroupId(a.groupId); + dep.setArtifactId(a.artifactId); + dep.setVersion(model.getValue(a.version)); + dep.setType(a.type); + dep.setClassifier(a.classifier); + dep.setScope(PROVIDED); + + log.debug("- adding dependency " + dep); + project.getDependencies().add(dep); + } + } + } + } + + private static File getSlingstartArtifact(final ArtifactHandlerManager artifactHandlerManager, + final ArtifactResolver resolver, + final MavenProject project, + final MavenSession session, + final Dependency d) + throws MavenExecutionException { + final Artifact prjArtifact = new DefaultArtifact(d.getGroupId(), + d.getArtifactId(), + VersionRange.createFromVersion(d.getVersion()), + Artifact.SCOPE_PROVIDED, + d.getType(), + d.getClassifier(), + artifactHandlerManager.getArtifactHandler(d.getType())); + try { + resolver.resolve(prjArtifact, project.getRemoteArtifactRepositories(), session.getLocalRepository()); + } catch (final ArtifactResolutionException e) { + throw new MavenExecutionException("Unable to get artifact for " + d, e); + } catch (final ArtifactNotFoundException e) { + throw new MavenExecutionException("Unable to get artifact for " + d, e); + } + return prjArtifact.getFile(); + } + + private static String nodeValue(final Xpp3Dom config, final String name, final String defaultValue) { + final Xpp3Dom node = (config == null ? null : config.getChild(name)); + if (node != null) { + return node.getValue(); + } else { + return defaultValue; + } + } +} diff --git a/src/main/java/org/apache/sling/maven/slingstart/JarArchiverHelper.java b/src/main/java/org/apache/sling/maven/slingstart/JarArchiverHelper.java new file mode 100644 index 0000000..9b70652 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/JarArchiverHelper.java @@ -0,0 +1,180 @@ +/* + * 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.File; +import java.io.IOException; +import java.util.Map; + +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.jar.JarArchiver; +import org.codehaus.plexus.archiver.jar.Manifest; +import org.codehaus.plexus.archiver.jar.Manifest.Attribute; +import org.codehaus.plexus.archiver.jar.ManifestException; + +public class JarArchiverHelper { + + private final JarArchiver archiver; + + private final MavenProject project; + + public JarArchiverHelper(final JarArchiver archiver, + final MavenProject project, + final File destFile) throws MojoExecutionException { + this(archiver, project, destFile, null); + } + + public JarArchiverHelper(final JarArchiver archiver, + final MavenProject project, + final File destFile, + final java.util.jar.Manifest manifest) throws MojoExecutionException { + this.project = project; + this.archiver = archiver; + this.archiver.reset(); + this.archiver.setDestFile(destFile); + + this.createManifest(manifest); + } + + /** + * Create a manifest + */ + private void createManifest(final java.util.jar.Manifest manifest) throws MojoExecutionException { + // create a new manifest + final Manifest outManifest = new Manifest(); + + try { + boolean hasMain = false; + + // copy entries from existing manifest + if ( manifest != null ) { + final Map<Object, Object> attrs = manifest.getMainAttributes(); + for(final Map.Entry<Object, Object> entry : attrs.entrySet()) { + final String key = entry.getKey().toString(); + if ( !BuildConstants.ATTRS_EXCLUDES.contains(key)) { + final Attribute a = new Attribute(key, entry.getValue().toString()); + outManifest.addConfiguredAttribute(a); + } + if ( key.equals(BuildConstants.ATTR_MAIN_CLASS) ) { + hasMain = true; + } + } + } + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_IMPLEMENTATION_BUILD, + project.getVersion())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_IMPLEMENTATION_VENDOR, + project.getOrganization().getName())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_IMPLEMENTATION_VERSION, + project.getVersion())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_CREATED_BY, + project.getOrganization().getName())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_BUILT_BY, + project.getOrganization().getName())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_IMPLEMENTATION_VENDOR_ID, + project.getGroupId())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_IMPLEMENTATION_TITLE, + project.getName())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_SPECIFICATION_TITLE, + project.getName())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_SPECIFICATION_VENDOR, + project.getOrganization().getName())); + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_SPECIFICATION_VERSION, + project.getVersion())); + + if ( archiver.getDestFile().getName().endsWith(".jar") && !hasMain) { + outManifest.addConfiguredAttribute(new Attribute(BuildConstants.ATTR_MAIN_CLASS, + BuildConstants.ATTR_VALUE_MAIN_CLASS)); + } + + archiver.addConfiguredManifest(outManifest); + } catch (final ManifestException e) { + throw new MojoExecutionException("Unable to create manifest for " + this.archiver.getDestFile(), e); + } + } + + public void addDirectory(File directory, String prefix, String[] includes, String[] excludes) + throws MojoExecutionException { + try { + archiver.addDirectory(directory, prefix, includes, excludes); + } catch (final ArchiverException ae) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), ae); + } + } + + public void addDirectory(File directory, String prefix) throws MojoExecutionException { + try { + archiver.addDirectory(directory, prefix); + } catch (final ArchiverException ae) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), ae); + } + } + + public void addDirectory(File directory, String[] includes, String[] excludes) throws MojoExecutionException { + try { + archiver.addDirectory(directory, includes, excludes); + } catch (final ArchiverException ae) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), ae); + } + } + + public void addDirectory(File directory) throws MojoExecutionException { + try { + archiver.addDirectory(directory); + } catch (final ArchiverException ae) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), ae); + } + } + + public void addFile(File arg0, String arg1, int arg2) throws MojoExecutionException { + try { + archiver.addFile(arg0, arg1, arg2); + } catch (final ArchiverException ae) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), ae); + } + } + + public void addFile(File inputFile, String destFileName) throws MojoExecutionException { + try { + archiver.addFile(inputFile, destFileName); + } catch (final ArchiverException ae) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), ae); + } + } + + public void createArchive() throws MojoExecutionException { + try { + archiver.createArchive(); + } catch (final ArchiverException ae) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), ae); + } catch (IOException e) { + throw new MojoExecutionException("Unable to create archive for " + this.archiver.getDestFile(), e); + } + } + + public void addArtifacts(final Map<String, File> globalContentsMap, final String prefix) + throws MojoExecutionException { + for(final Map.Entry<String, File> entry : globalContentsMap.entrySet()) { + if ( entry.getValue().isFile() ) { + this.addFile(entry.getValue(), prefix + entry.getKey()); + } else { + this.addDirectory(entry.getValue(), prefix); + } + } + } +} diff --git a/src/main/java/org/apache/sling/maven/slingstart/PackageMojo.java b/src/main/java/org/apache/sling/maven/slingstart/PackageMojo.java new file mode 100644 index 0000000..0914d2a --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/PackageMojo.java @@ -0,0 +1,121 @@ +/* + * 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.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Map; +import java.util.jar.Manifest; + +import org.apache.commons.io.IOUtils; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.codehaus.plexus.archiver.jar.JarArchiver; + +/** + * Initialize a Sling application project by extracting bundles into the correct + * locations. + */ +@Mojo( + name = "package", + defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST, + requiresDependencyResolution = ResolutionScope.TEST, + threadSafe = true + ) +public class PackageMojo extends AbstractSubsystemMojo { + + private static final String[] EXCLUDES_MANIFEST = new String[] {"META-INF/MANIFEST.MF"}; + + /** + * The Jar archiver. + */ + @Component(role = org.codehaus.plexus.archiver.Archiver.class, hint = "jar") + private JarArchiver jarArchiver; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + + @SuppressWarnings("unchecked") + final Map<String, File> globalContentsMap = (Map<String, File>) this.project.getContextValue(BuildConstants.CONTEXT_GLOBAL); + + this.packageStandaloneApp(globalContentsMap); + this.packageWebapp(globalContentsMap); + } + + private void packageStandaloneApp(final Map<String, File> globalContentsMap) throws MojoExecutionException { + this.getLog().info("Packaging standalone jar..."); + + final File buildDirectory = new File(this.project.getBuild().getDirectory()); + @SuppressWarnings("unchecked") + final Map<String, File> contentsMap = (Map<String, File>) this.project.getContextValue(BuildConstants.CONTEXT_STANDALONE); + + final File buildOutputDirectory = new File(this.project.getBuild().getOutputDirectory()); + final File manifestFile = new File(buildOutputDirectory, "META-INF/MANIFEST.MF"); + FileInputStream fis = null; + try { + fis = new FileInputStream(manifestFile); + final Manifest mf = new Manifest(fis); + + final File outputFile = new File(buildDirectory, this.project.getArtifactId() + "-" + this.project.getVersion() + ".jar"); + + final JarArchiverHelper helper = new JarArchiverHelper(jarArchiver, this.project, outputFile, mf); + helper.addDirectory(buildOutputDirectory, null, EXCLUDES_MANIFEST); + + helper.addArtifacts(globalContentsMap, ""); + helper.addArtifacts(contentsMap, ""); + + helper.createArchive(); + if ( BuildConstants.PACKAGING_SLINGSTART.equals(project.getPackaging()) ) { + project.getArtifact().setFile(outputFile); + } else { + projectHelper.attachArtifact(project, BuildConstants.TYPE_JAR, BuildConstants.CLASSIFIER_APP, outputFile); + } + } catch ( final IOException ioe) { + throw new MojoExecutionException("Unable to create standalone jar", ioe); + } finally { + IOUtils.closeQuietly(fis); + } + } + + private void packageWebapp(final Map<String, File> globalContentsMap) throws MojoExecutionException { + if ( this.createWebapp ) { + this.getLog().info("Packaging webapp..."); + + final File buildDirectory = new File(this.project.getBuild().getDirectory()); + @SuppressWarnings("unchecked") + final Map<String, File> contentsMap = (Map<String, File>) this.project.getContextValue(BuildConstants.CONTEXT_WEBAPP); + + final File buildOutputDirectory = new File(buildDirectory, BuildConstants.WEBAPP_OUTDIR); + final File outputFile = new File(buildDirectory, this.project.getArtifactId() + "-" + this.project.getVersion() + ".war"); + + final JarArchiverHelper helper = new JarArchiverHelper(this.jarArchiver, this.project, outputFile); + helper.addDirectory(buildOutputDirectory, null, EXCLUDES_MANIFEST); + + helper.addArtifacts(globalContentsMap, "WEB-INF/"); + helper.addArtifacts(contentsMap, "WEB-INF/"); + + helper.createArchive(); + + projectHelper.attachArtifact(project, BuildConstants.TYPE_WAR, BuildConstants.CLASSIFIER_WEBAPP, outputFile); + } + } +} diff --git a/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java b/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java new file mode 100644 index 0000000..d595251 --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/PreparePackageMojo.java @@ -0,0 +1,400 @@ +/* + * 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.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.sling.slingstart.model.SSMArtifact; +import org.apache.sling.slingstart.model.SSMConfiguration; +import org.apache.sling.slingstart.model.SSMConstants; +import org.apache.sling.slingstart.model.SSMRunMode; +import org.apache.sling.slingstart.model.SSMStartLevel; +import org.apache.sling.slingstart.model.SSMSubsystem; +import org.codehaus.plexus.archiver.ArchiverException; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.manager.ArchiverManager; +import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; +import org.codehaus.plexus.util.FileUtils; + +/** + * Prepare the sling start applications. + */ +@Mojo( + name = "prepare-package", + defaultPhase = LifecyclePhase.PROCESS_SOURCES, + requiresDependencyResolution = ResolutionScope.TEST, + threadSafe = true + ) +public class PreparePackageMojo extends AbstractSubsystemMojo { + + private static final String BASE_DESTINATION = "resources"; + + private static final String BOOT_DIRECTORY = "bundles"; + + private static final String ARTIFACTS_DIRECTORY = "install"; + + private static final String CONFIG_DIRECTORY = "config"; + + private static final String BOOTSTRAP_FILE = "sling_bootstrap.txt"; + + private static final String PROPERTIES_FILE = "sling_install.properties"; + + /** + * To look up Archiver/UnArchiver implementations + */ + @Component + private ArchiverManager archiverManager; + + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + final SSMSubsystem model = this.readModel(); + + this.prepareGlobal(model); + this.prepareStandaloneApp(model); + this.prepareWebapp(model); + } + + /** + * Prepare the global map for the artifacts. + */ + private void prepareGlobal(final SSMSubsystem model) throws MojoExecutionException { + final Map<String, File> globalContentsMap = new HashMap<String, File>(); + this.buildContentsMap(model, (String)null, globalContentsMap); + + this.project.setContextValue(BuildConstants.CONTEXT_GLOBAL, globalContentsMap); + } + + /** + * Prepare the standalone application. + */ + private void prepareStandaloneApp(final SSMSubsystem model) throws MojoExecutionException { + final Map<String, File> contentsMap = new HashMap<String, File>(); + this.project.setContextValue(BuildConstants.CONTEXT_STANDALONE, contentsMap); + + // unpack base artifact and create settings + final File outputDir = new File(this.project.getBuild().getOutputDirectory()); + unpackBaseArtifact(model, outputDir, SSMRunMode.RUN_MODE_STANDALONE); + this.buildSettings(model, SSMRunMode.RUN_MODE_STANDALONE, outputDir); + this.buildBootstrapFile(model, SSMRunMode.RUN_MODE_STANDALONE, outputDir); + + this.buildContentsMap(model, SSMRunMode.RUN_MODE_STANDALONE, contentsMap); + } + + /** + * Prepare the web application. + */ + private void prepareWebapp(final SSMSubsystem model) throws MojoExecutionException { + if ( this.createWebapp ) { + final Map<String, File> contentsMap = new HashMap<String, File>(); + this.project.setContextValue(BuildConstants.CONTEXT_WEBAPP, contentsMap); + + // unpack base artifact and create settings + final File outputDir = new File(this.project.getBuild().getDirectory(), BuildConstants.WEBAPP_OUTDIR); + final File webappDir = new File(outputDir, "WEB-INF"); + unpackBaseArtifact(model, outputDir, SSMRunMode.RUN_MODE_WEBAPP); + + // check for web.xml + final SSMRunMode webappRM = model.getRunMode(SSMRunMode.RUN_MODE_WEBAPP); + if ( webappRM != null ) { + final SSMConfiguration webConfig = webappRM.getConfiguration(SSMConstants.CFG_WEB_XML); + if ( webConfig != null ) { + final File webXML = new File(webappDir, "web.xml"); + try { + FileUtils.fileWrite(webXML, webConfig.properties); + } catch (final IOException e) { + throw new MojoExecutionException("Unable to write configuration to " + webXML, e); + } + } + } + this.buildSettings(model, SSMRunMode.RUN_MODE_WEBAPP, webappDir); + this.buildBootstrapFile(model, SSMRunMode.RUN_MODE_WEBAPP, outputDir); + + this.buildContentsMap(model, SSMRunMode.RUN_MODE_WEBAPP, contentsMap); + } + } + + /** + * Build a list of all artifacts. + */ + private void buildContentsMap(final SSMSubsystem model, final String packageRunMode, final Map<String, File> contentsMap) + throws MojoExecutionException { + if ( packageRunMode == null ) { + // add base jar + final Artifact artifact = getBaseArtifact(model, null, BuildConstants.TYPE_JAR); + contentsMap.put(BASE_DESTINATION + "/"+ artifact.getArtifactId() + "." + artifact.getArtifactHandler().getExtension(), artifact.getFile()); + } + for(final SSMRunMode runMode : model.runModes) { + if ( packageRunMode == null ) { + if ( runMode.isSpecial() + && !runMode.isRunMode(SSMRunMode.RUN_MODE_BOOT)) { + continue; + } + this.buildContentsMap(model, runMode, contentsMap); + } else { + if ( runMode.isRunMode(packageRunMode) ) { + this.buildContentsMap(model, runMode, contentsMap); + } + } + } + } + + /** + * Build a list of all artifacts from this run mode + */ + private void buildContentsMap(final SSMSubsystem model, final SSMRunMode runMode, final Map<String, File> contentsMap) + throws MojoExecutionException{ + for(final SSMStartLevel sl : runMode.startLevels) { + for(final SSMArtifact a : sl.artifacts) { + final Artifact artifact = SubsystemUtils.getArtifact(this.project, a.groupId, a.artifactId, model.getValue(a.version), a.type, a.classifier); + final File artifactFile = artifact.getFile(); + contentsMap.put(getPathForArtifact(sl.level, artifactFile.getName(), runMode), artifactFile); + } + } + + final File rootConfDir = new File(this.getTmpDir(), "global-config"); + boolean hasConfig = false; + for(final SSMConfiguration config : runMode.configurations) { + // skip special configurations + if ( config.isSpecial() ) { + continue; + } + final String configPath = getPathForConfiguration(config, runMode); + final File configFile = new File(rootConfDir, configPath); + getLog().debug(String.format("Creating configuration at %s", configFile.getPath())); + configFile.getParentFile().mkdirs(); + try { + FileUtils.fileWrite(configFile, config.properties); + } catch (final IOException e) { + throw new MojoExecutionException("Unable to write configuration to " + configFile, e); + } + hasConfig = true; + } + if ( hasConfig ) { + contentsMap.put(BASE_DESTINATION, rootConfDir); + } + } + + /** + * Build the settings for the given packaging run mode + */ + private void buildSettings(final SSMSubsystem model, final String packageRunMode, final File outputDir) + throws MojoExecutionException { + String settings = null; + final SSMRunMode baseRM = model.getRunMode(SSMRunMode.RUN_MODE_BASE); + if ( baseRM != null && baseRM.settings != null ) { + settings = baseRM.settings.properties + "\n"; + } else { + settings = ""; + } + final SSMRunMode bootRM = model.getRunMode(SSMRunMode.RUN_MODE_BOOT); + if ( bootRM != null && bootRM.settings != null ) { + settings = settings + bootRM.settings.properties + "\n"; + } + final SSMRunMode packageRM = model.getRunMode(packageRunMode); + if ( packageRM != null && packageRM.settings != null ) { + settings = settings + packageRM.settings.properties; + } + + if ( settings != null ) { + final File settingsFile = new File(outputDir, PROPERTIES_FILE); + getLog().debug(String.format("Creating settings at %s", settingsFile.getPath())); + try { + FileUtils.fileWrite(settingsFile, settings); + } catch ( final IOException ioe ) { + throw new MojoExecutionException("Unable to write properties file.", ioe); + } + } + } + + /** + * Build the bootstrap file for the given packaging run mode + */ + private void buildBootstrapFile(final SSMSubsystem model, final String packageRunMode, final File outputDir) + throws MojoExecutionException { + String bootstrapTxt = ""; + final SSMRunMode baseRM = model.getRunMode(SSMRunMode.RUN_MODE_BASE); + if ( baseRM != null ) { + final SSMConfiguration c = baseRM.getConfiguration(SSMConstants.CFG_BOOTSTRAP); + if ( c != null ) { + bootstrapTxt = c.properties + "\n"; + } + } + final SSMRunMode bootRM = model.getRunMode(SSMRunMode.RUN_MODE_BOOT); + if ( bootRM != null ) { + final SSMConfiguration c = bootRM.getConfiguration(SSMConstants.CFG_BOOTSTRAP); + if ( c != null ) { + bootstrapTxt = bootstrapTxt + c.properties; + } + } + final SSMRunMode packageRM = model.getRunMode(packageRunMode); + if ( packageRM != null ) { + final SSMConfiguration c = packageRM.getConfiguration(SSMConstants.CFG_BOOTSTRAP); + if ( c != null ) { + bootstrapTxt = bootstrapTxt + c.properties; + } + } + + if ( bootstrapTxt != null ) { + final File file = new File(outputDir, BOOTSTRAP_FILE); + getLog().debug(String.format("Creating bootstrap file at %s", file.getPath())); + try { + FileUtils.fileWrite(file, bootstrapTxt); + } catch ( final IOException ioe ) { + throw new MojoExecutionException("Unable to write bootstrap file.", ioe); + } + } + } + + /** + * Return the base artifact + */ + private Artifact getBaseArtifact(final SSMSubsystem model, final String classifier, final String type) throws MojoExecutionException { + final SSMArtifact baseArtifact = SubsystemUtils.getBaseArtifact(model); + + final Artifact a = SubsystemUtils.getArtifact(this.project, baseArtifact.groupId, + baseArtifact.artifactId, + model.getValue(baseArtifact.version), + type, + classifier); + if (a == null) { + throw new MojoExecutionException( + String.format("Project doesn't have a base dependency of groupId %s and artifactId %s", + baseArtifact.groupId, baseArtifact.artifactId)); + } + return a; + } + + /** + * Unpack the base artifact + */ + private void unpackBaseArtifact(final SSMSubsystem model, final File outputDirectory, final String packageRunMode) + throws MojoExecutionException { + final String classifier; + final String type; + if ( SSMRunMode.RUN_MODE_STANDALONE.equals(packageRunMode) ) { + classifier = BuildConstants.CLASSIFIER_APP; + type = BuildConstants.TYPE_JAR; + } else { + classifier = BuildConstants.CLASSIFIER_WEBAPP; + type = BuildConstants.TYPE_WAR; + } + final Artifact artifact = this.getBaseArtifact(model, classifier, type); + unpack(artifact.getFile(), outputDirectory); + } + + /** + * Unpack a file + */ + private void unpack(final File source, final File destination) + throws MojoExecutionException { + getLog().debug("Unpacking " + source.getPath() + " to\n " + destination.getPath()); + try { + destination.mkdirs(); + + final UnArchiver unArchiver = archiverManager.getUnArchiver(source); + + unArchiver.setSourceFile(source); + unArchiver.setDestDirectory(destination); + + unArchiver.extract(); + } catch (final NoSuchArchiverException e) { + throw new MojoExecutionException("Unable to find archiver for " + source.getPath(), e); + } catch (final ArchiverException e) { + throw new MojoExecutionException("Unable to unpack " + source.getPath(), e); + } + } + + /** + * Get the relative path for an artifact. + */ + private String getPathForArtifact(final int startLevel, final String artifactName, final SSMRunMode rm) { + final Set<String> runModesList = new TreeSet<String>(); + if (rm.runModes != null ) { + for(final String mode : rm.runModes) { + runModesList.add(mode); + } + } + final String runModeExt; + if ( runModesList.size() == 0 || rm.isSpecial() ) { + runModeExt = ""; + } else { + final StringBuilder sb = new StringBuilder(); + for(final String n : runModesList ) { + sb.append('.'); + sb.append(n); + } + runModeExt = sb.toString(); + } + + if ( rm.isRunMode(SSMRunMode.RUN_MODE_BOOT) ) { + return String.format("%s/%s/1/%s", BASE_DESTINATION, BOOT_DIRECTORY, + artifactName); + } + return String.format("%s/%s%s/%s/%s", BASE_DESTINATION, ARTIFACTS_DIRECTORY, + runModeExt, + (startLevel == -1 ? 1 : startLevel), + artifactName); + } + + /** + * Get the relative path for a configuration + */ + private String getPathForConfiguration(final SSMConfiguration config, final SSMRunMode rm) { + final Set<String> runModesList = new TreeSet<String>(); + if (rm.runModes != null ) { + for(final String mode : rm.runModes) { + runModesList.add(mode); + } + } + final String runModeExt; + if ( runModesList.size() == 0 || rm.isSpecial() ) { + runModeExt = ""; + } else { + final StringBuilder sb = new StringBuilder(); + boolean first = true; + for(final String n : runModesList ) { + if ( first ) { + sb.append('/'); + first = false; + } else { + sb.append('.'); + } + sb.append(n); + } + runModeExt = sb.toString(); + } + + final String mainName = (config.factoryPid != null ? config.factoryPid : config.pid); + final String alias = (config.factoryPid != null ? "-" + config.pid : ""); + return String.format("%s/%s%s/%s%s.cfg", BASE_DESTINATION, CONFIG_DIRECTORY, + runModeExt, + mainName, + alias); + } +} diff --git a/src/main/java/org/apache/sling/maven/slingstart/SubsystemUtils.java b/src/main/java/org/apache/sling/maven/slingstart/SubsystemUtils.java new file mode 100644 index 0000000..d0c36ac --- /dev/null +++ b/src/main/java/org/apache/sling/maven/slingstart/SubsystemUtils.java @@ -0,0 +1,179 @@ +/* + * 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.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.commons.io.IOUtils; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.project.MavenProject; +import org.apache.sling.slingstart.model.SSMArtifact; +import org.apache.sling.slingstart.model.SSMRunMode; +import org.apache.sling.slingstart.model.SSMSubsystem; +import org.apache.sling.slingstart.model.xml.XMLSSMModelReader; +import org.codehaus.plexus.logging.Logger; + +public abstract class SubsystemUtils { + + /** + * Read all model files from the directory in alphabetical order + * @param logger + */ + private static SSMSubsystem readLocalModel(final File systemsDirectory, final MavenProject project, final MavenSession session, final Logger logger) + throws MojoExecutionException { + final SSMSubsystem result = new SSMSubsystem(); + final List<String> candidates = new ArrayList<String>(); + if ( systemsDirectory != null && systemsDirectory.exists() ) { + for(final File f : systemsDirectory.listFiles() ) { + if ( f.isFile() && f.getName().endsWith(".xml") && !f.getName().startsWith(".") ) { + candidates.add(f.getName()); + } + } + Collections.sort(candidates); + } + if ( candidates.size() == 0 ) { + throw new MojoExecutionException("No model files found in " + systemsDirectory); + } + for(final String name : candidates) { + logger.debug("Reading model " + name + " in project " + project.getId()); + try { + final FileReader reader = new FileReader(new File(systemsDirectory, name)); + try { + final SSMSubsystem current = XMLSSMModelReader.read(reader); + try { + current.validate(); + } catch ( final IllegalStateException ise) { + throw new MojoExecutionException("Invalid model at " + name, ise); + } + result.merge(current); + } finally { + IOUtils.closeQuietly(reader); + } + } catch ( final IOException io) { + throw new MojoExecutionException("Unable to read " + name, io); + } + } + + try { + result.validate(); + } catch ( final IllegalStateException ise) { + throw new MojoExecutionException("Invalid assembled model", ise); + } + + return result; + } + + /** + * Read the full model + */ + public static SSMSubsystem readFullModel(final File systemsDirectory, + final List<File> dependentModels, + final MavenProject project, + final MavenSession session, + final Logger logger) + throws MojoExecutionException { + try { + final SSMSubsystem localModel = readLocalModel(systemsDirectory, project, session, logger); + + // check dependent models + SSMSubsystem depModel = null; + for(final File file : dependentModels) { + FileReader r = null; + try { + r = new FileReader(file); + if ( depModel == null ) { + depModel = new SSMSubsystem(); + } + final SSMSubsystem readModel = XMLSSMModelReader.read(r); + try { + readModel.validate(); + } catch ( final IllegalStateException ise) { + throw new MojoExecutionException("Invalid model " + file, ise); + } + depModel.merge(readModel); + } finally { + IOUtils.closeQuietly(r); + } + } + final SSMSubsystem result; + if ( depModel != null ) { + try { + depModel.validate(); + depModel.merge(localModel); + depModel.validate(); + } catch ( final IllegalStateException ise) { + throw new MojoExecutionException("Invalid model.", ise); + } + result = depModel; + } else { + result = localModel; + } + return result; + } catch ( final IOException ioe) { + throw new MojoExecutionException("Unable to cache model", ioe); + } + } + + public static SSMArtifact getBaseArtifact(final SSMSubsystem model) throws MojoExecutionException { + // get base run mode + final SSMRunMode base = model.getRunMode(SSMRunMode.RUN_MODE_BASE); + if ( base == null ) { + throw new MojoExecutionException("No base run mode found."); + } + if ( base.startLevels.size() == 0 ) { + throw new MojoExecutionException("No base artifacts defined."); + } + if ( base.startLevels.size() > 1 ) { + throw new MojoExecutionException("Base run mode should only have a single start level."); + } + if ( base.startLevels.get(0).artifacts.size() != 1 ) { + throw new MojoExecutionException("Base run mode should contain exactly one artifact."); + } + + return base.startLevels.get(0).artifacts.get(0); + } + + /** + * Get a resolved Artifact from the coordinates provided + * + * @return the artifact, which has been resolved. + * @throws MojoExecutionException + */ + public static Artifact getArtifact(final MavenProject project, + final String groupId, final String artifactId, final String version, final String type, final String classifier) + throws MojoExecutionException { + final Set<Artifact> artifacts = project.getDependencyArtifacts(); + for(final Artifact artifact : artifacts) { + if ( artifact.getGroupId().equals(groupId) + && artifact.getArtifactId().equals(artifactId) + && artifact.getVersion().equals(version) + && artifact.getType().equals(type) + && ((classifier == null && artifact.getClassifier() == null) || (classifier != null && classifier.equals(artifact.getClassifier()))) ) { + return artifact; + } + } + return null; + } +} diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 0000000..8896896 --- /dev/null +++ b/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,95 @@ +<!-- + 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. +--> +<component-set> + <components> + <component> + <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role> + <role-hint>slingsubsystem</role-hint> + <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation> + <configuration> + <lifecycles> + <lifecycle> + <id>default</id> + <!-- START SNIPPET: bundle-lifecycle --> + <phases> + <package>org.apache.sling:slingstart-maven-plugin:attach-slingsubsystem</package> + <install>org.apache.maven.plugins:maven-install-plugin:install</install> + <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy> + </phases> + <!-- END SNIPPET: bundle-lifecycle --> + </lifecycle> + </lifecycles> + </configuration> + </component> + <component> + <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role> + <role-hint>slingstart</role-hint> + <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation> + <configuration> + <lifecycles> + <lifecycle> + <id>default</id> + <!-- START SNIPPET: bundle-lifecycle --> + <phases> + <process-sources>org.apache.sling:slingstart-maven-plugin:prepare-package</process-sources> + <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> + org.apache.maven.plugins:maven-resources-plugin:testResources, + </process-test-resources> + <test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile> + <test>org.apache.maven.plugins:maven-surefire-plugin:test</test> + <package> + org.apache.sling:slingstart-maven-plugin:attach-slingsubsystem, + org.apache.sling:slingstart-maven-plugin:package + </package> + <install>org.apache.maven.plugins:maven-install-plugin:install</install> + <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy> + </phases> + <!-- END SNIPPET: bundle-lifecycle --> + </lifecycle> + </lifecycles> + </configuration> + </component> + <component> + <role>org.apache.maven.artifact.handler.ArtifactHandler</role> + <role-hint>slingsubsystem</role-hint> + <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation> + <configuration> + <type>slingsubsystem</type> + <includesDependencies>false</includesDependencies> + <language>xml</language> + <extension>xml</extension> + <addedToClasspath>false</addedToClasspath> + </configuration> + </component> + <component> + <role>org.apache.maven.artifact.handler.ArtifactHandler</role> + <role-hint>slingstart</role-hint> + <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation> + <configuration> + <type>slingstart</type> + <includesDependencies>true</includesDependencies> + <language>java</language> + <extension>jar</extension> + <addedToClasspath>false</addedToClasspath> + </configuration> + </component> + </components> +</component-set> -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
