/* * 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.axis2.maven2.repo; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import org.apache.axiom.om.OMDocument; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMNode; import org.apache.axiom.om.OMXMLBuilderFactory; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException; import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts; import org.apache.maven.shared.artifact.filter.collection.ScopeFilter; import org.apache.maven.shared.artifact.filter.collection.TypeFilter; import org.codehaus.plexus.archiver.ArchiverException; import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.util.DirectoryScanner; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.StringUtils; public abstract class AbstractCreateRepositoryMojo extends AbstractMojo { /** * @parameter expression="${project.artifacts}" * @readonly * @required */ private Set<Artifact> projectArtifacts; /** * @parameter expression="${project.collectedProjects}" * @required * @readonly */ private List<MavenProject> collectedProjects; /** * The directory (relative to the repository root) where AAR files are copied. This should be * set to the same value as the <tt>ServicesDirectory</tt> property in <tt>axis2.xml</tt>. * * @parameter default-value="services" */ private String servicesDirectory; /** * The directory (relative to the repository root) where MAR files are copied. This should be * set to the same value as the <tt>ModulesDirectory</tt> property in <tt>axis2.xml</tt>. * * @parameter default-value="modules" */ private String modulesDirectory; /** * The directory (relative to the repository root) where JAX-WS service JARs will be deployed. * * @parameter default-value="servicejars" */ private String jaxwsServicesDirectory; /** * The <tt>axis2.xml</tt> file to be copied into the repository. * * @parameter */ private File axis2xml; /** * If present, an <tt>axis2.xml</tt> file will be generated (Experimental). * * @parameter */ private GeneratedAxis2Xml generatedAxis2xml; /** * The directory (relative to the repository root) where the <tt>axis2.xml</tt> file will be * written. If this parameter is not set, then the file will be written into the repository * root. * * @parameter */ private String configurationDirectory; /** * Specifies whether the plugin should scan the project dependencies for AAR and MAR artifacts. * * @parameter default-value="true" */ private boolean useDependencies; /** * Specifies whether the plugin should scan Maven modules for AAR and MAR artifacts. This * parameter only has an effect for multimodule projects. * * @parameter default-value="true" */ private boolean useModules; /** * Specifies whether the plugin should generate <tt>services.list</tt> and <tt>modules.list</tt> * files. * * @parameter default-value="false" */ private boolean generateFileLists; /** * Specifies whether the plugin strips version numbers from AAR files. * * @parameter default-value="true" */ private boolean stripServiceVersion; /** * Specifies whether the plugin strips version numbers from MAR files. * * @parameter default-value="false" */ private boolean stripModuleVersion; /** * Specifies whether modules should be deployed to the repository. * * @parameter default-value="true" */ private boolean includeModules; /** * Comma separated list of modules (by artifactId) to include in the repository. * * @parameter */ private String modules; /** * Specifies whether services should be deployed to the repository. * * @parameter default-value="true" */ private boolean includeServices; /** * Comma separated list of services (by artifactId) to include in the repository. * * @parameter */ private String services; /** * A list of JAX-WS service JARs to be generated (by packaging class files from the current * project). * * @parameter */ private JAXWSService[] jaxwsServices; protected abstract String getScope(); protected abstract File getInputDirectory(); protected abstract File getOutputDirectory(); protected abstract File[] getClassDirectories(); private void addMessageHandlers(OMElement root, MessageHandler[] handlers, String localName) { OMElement parent = root.getFirstChildWithName(new QName(localName + "s")); for (MessageHandler handler : handlers) { OMElement element = parent.getOMFactory().createOMElement(localName, null, parent); element.addAttribute("contentType", handler.getContentType(), null); element.addAttribute("class", handler.getClassName(), null); } } public void execute() throws MojoExecutionException, MojoFailureException { Log log = getLog(); File inputDirectory = getInputDirectory(); File outputDirectory = getOutputDirectory(); if (inputDirectory.exists()) { log.info("Copying files from " + inputDirectory); DirectoryScanner ds = new DirectoryScanner(); ds.setBasedir(inputDirectory); ds.scan(); for (String relativePath : ds.getIncludedFiles()) { try { FileUtils.copyFile( new File(inputDirectory, relativePath), new File(outputDirectory, relativePath)); } catch (IOException ex) { throw new MojoExecutionException("Failed to copy " + relativePath, ex); } } } Set<Artifact> artifacts = new HashSet<Artifact>(); if (useDependencies) { artifacts.addAll(projectArtifacts); } if (useModules) { for (MavenProject project : collectedProjects) { artifacts.add(project.getArtifact()); artifacts.addAll(project.getAttachedArtifacts()); } } if (includeModules || includeServices) { FilterArtifacts filter = new FilterArtifacts(); filter.addFilter(new ScopeFilter(getScope(), null)); if (includeModules && includeServices) { filter.addFilter(new TypeFilter("aar,mar", null)); } else if (includeModules) { filter.addFilter(new TypeFilter("mar", null)); } try { artifacts = filter.filter(artifacts); } catch (ArtifactFilterException ex) { throw new MojoExecutionException(ex.getMessage(), ex); } selectArtifacts(artifacts, modules, "mar"); selectArtifacts(artifacts, services, "aar"); Map<String,ArchiveDeployer> deployers = new HashMap<String,ArchiveDeployer>(); deployers.put("aar", new ArchiveDeployer(outputDirectory, servicesDirectory, "services.list", generateFileLists, stripServiceVersion)); deployers.put("mar", new ArchiveDeployer(outputDirectory, modulesDirectory, "modules.list", generateFileLists, stripModuleVersion)); for (Artifact artifact : artifacts) { File file = artifact.getFile(); if (file == null || file.isDirectory()) { throw new MojoFailureException("Artifact " + artifact.getId() + " not available. " + "This typically means that it is part of the reactor but that the " + "package phase has not been executed."); } String type = artifact.getType(); ArchiveDeployer deployer = deployers.get(type); if (deployer == null) { throw new MojoExecutionException("No deployer found for artifact type " + type); } deployer.deploy(log, artifact); } for (ArchiveDeployer deployer : deployers.values()) { deployer.finish(log); } } if (jaxwsServices != null) { File targetDirectory = new File(outputDirectory, jaxwsServicesDirectory); for (JAXWSService service : jaxwsServices) { String jarName = service.getName() + ".jar"; try { JarArchiver archiver = new JarArchiver(); archiver.setDestFile(new File(targetDirectory, jarName)); String[] packages = service.getPackages(); String[] includes = new String[packages.length]; for (int i=0; i<packages.length; i++) { includes[i] = packages[i].replace('.', '/') + "/**/*.class"; } for (File classDirectory : getClassDirectories()) { archiver.addDirectory(classDirectory, includes, new String[0]); } archiver.createArchive(); } catch (ArchiverException ex) { throw new MojoExecutionException("Failed to build " + jarName, ex); } catch (IOException ex) { throw new MojoExecutionException("Failed to build " + jarName, ex); } } } if (generatedAxis2xml != null || axis2xml != null) { File targetDirectory = configurationDirectory == null ? outputDirectory : new File(outputDirectory, configurationDirectory); targetDirectory.mkdirs(); File axis2xmlFile = new File(targetDirectory, "axis2.xml"); if (axis2xml != null) { log.info("Copying axis2.xml"); try { FileUtils.copyFile(axis2xml, axis2xmlFile); } catch (IOException ex) { throw new MojoExecutionException("Error copying axis2.xml file: " + ex.getMessage(), ex); } } else { log.info("Generating axis2.xml"); try { FilterArtifacts filter = new FilterArtifacts(); filter.addFilter(new ScopeFilter(getScope(), null)); filter.addFilter(new TypeFilter("jar", null)); List<URL> urls = new ArrayList<URL>(); for (Artifact artifact : filter.filter(projectArtifacts)) { urls.add(artifact.getFile().toURI().toURL()); } URLClassLoader classLoader = URLClassLoader.newInstance(urls.toArray(new URL[urls.size()])); InputStream in = classLoader.getResourceAsStream("org/apache/axis2/deployment/axis2_default.xml"); if (in == null) { throw new MojoFailureException("The default axis2.xml file could not be found"); } try { OMDocument axis2xmlDoc = OMXMLBuilderFactory.createOMBuilder(in).getDocument(); OMElement root = axis2xmlDoc.getOMDocumentElement(); for (Iterator<OMNode> it = root.getDescendants(false); it.hasNext(); ) { OMNode node = it.next(); if (node instanceof OMElement) { OMElement element = (OMElement)node; String classAttr = element.getAttributeValue(new QName("class")); if (classAttr != null) { try { classLoader.loadClass(classAttr); } catch (ClassNotFoundException ex) { it.remove(); } } } } addMessageHandlers(root, generatedAxis2xml.getMessageBuilders(), "messageBuilder"); addMessageHandlers(root, generatedAxis2xml.getMessageFormatters(), "messageFormatter"); OutputStream out = new FileOutputStream(axis2xmlFile); try { axis2xmlDoc.serialize(out); } finally { out.close(); } } finally { in.close(); } } catch (ArtifactFilterException ex) { throw new MojoExecutionException(ex.getMessage(), ex); } catch (IOException ex) { throw new MojoExecutionException(ex.getMessage(), ex); } catch (XMLStreamException ex) { throw new MojoExecutionException(ex.getMessage(), ex); } } } } private void selectArtifacts(Set<Artifact> artifacts, String list, String type) throws MojoFailureException { if (list != null) { Set<String> set = new HashSet<String>(Arrays.asList(StringUtils.stripAll(StringUtils.split(list, ",")))); for (Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); ) { Artifact artifact = it.next(); if (artifact.getType().equals(type) && !set.remove(artifact.getArtifactId())) { it.remove(); } } if (!set.isEmpty()) { throw new MojoFailureException("The following " + type + " artifacts have not been found: " + set); } } } }