package org.codehaus.mojo.shade.resource; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import org.codehaus.plexus.util.IOUtil; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.Xpp3DomWriter; // 1. We want to process all resources that are common in all the JARs that we are processing. // 2. At the end of processing we want to hand back the transformation of the resources. // In my particular case I want to grab all the plexus components.xml files and aggregate them // and then stick them in one place in the aggregated JAR. public class ComponentsXmlResourceTransformer implements ResourceTransformer { private Map components = new LinkedHashMap(); public static final String COMPONENTS_XML_PATH = "META-INF/plexus/components.xml"; public boolean canTransformResource( String resource ) { return COMPONENTS_XML_PATH.equals( resource ); } public void processResource( InputStream is ) throws IOException { // We can't just read the stream because the plexus dom builder closes the stream File f = File.createTempFile( "maven-shade-plugin", "tmp" ); f.deleteOnExit(); String n = f.getAbsolutePath(); OutputStream os = new FileOutputStream( f ); IOUtil.copy( is, os ); os.close(); // Reader reader; Xpp3Dom newDom; try { reader = new FileReader( n ); newDom = Xpp3DomBuilder.build( reader ); } catch ( Exception e ) { throw new IOException( "Error parsing components.xml in " + is ); } Xpp3Dom[] children = newDom.getChild( "components" ).getChildren( "component" ); for ( int i = 0; i < children.length; i++ ) { Xpp3Dom component = children[i]; String role = component.getChild( "role" ).getValue(); Xpp3Dom child = component.getChild( "role-hint" ); String roleHint = child != null ? child.getValue() : ""; components.put( role + roleHint, component ); } } public void modifyOutputStream( JarOutputStream jos ) throws IOException { Reader reader = new FileReader( getTransformedResource() ); jos.putNextEntry( new JarEntry( COMPONENTS_XML_PATH ) ); IOUtil.copy( reader, jos ); reader.close(); } public boolean hasTransformedResource() { return components.size() > 0; } public File getTransformedResource() throws IOException { File f = File.createTempFile( "shade-maven-plugin-plx", "tmp" ); f.deleteOnExit(); FileWriter fileWriter = new FileWriter( f ); try { Xpp3Dom dom = new Xpp3Dom( "component-set" ); Xpp3Dom componentDom = new Xpp3Dom( "components" ); dom.addChild( componentDom ); for ( Iterator i = components.values().iterator(); i.hasNext(); ) { Xpp3Dom component = (Xpp3Dom) i.next(); componentDom.addChild( component ); } Xpp3DomWriter.write( fileWriter, dom ); } finally { IOUtil.close( fileWriter ); } return f; } }