package org.codehaus.plexus.configuration; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import org.codehaus.plexus.component.repository.ComponentDescriptor; import org.codehaus.plexus.component.repository.ComponentRequirement; import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; /** * * @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a> * */ public class PlexusComponentDescriptorMerger { /** * Merges override and target, where target is updated with override. */ public static void merge( ComponentDescriptor<?> override, ComponentDescriptor<?> target ) { if ( override.getImplementation() != null ) { target.setImplementation( override.getImplementation() ); } mergeRequirements( override, target ); mergeConfiguration( override, target ); // TODO: other getters/setters. } private static void mergeConfiguration( ComponentDescriptor<?> override, ComponentDescriptor<?> target ) { // try to parse the override dom. If this fails, do not update anything and keep // the original target configuration. Xpp3Dom overrideDom; try { overrideDom = Xpp3DomBuilder.build( new StringReader( override.getConfiguration().toString() ) ); } catch ( XmlPullParserException e1 ) { return; } catch ( IOException e1 ) { return; } // try to parse the target dom. if this fails, replace it with the override configuration, // dom, otherwise merge it. Xpp3Dom targetDom = null; if ( target.getConfiguration() != null ) { try { targetDom = Xpp3DomBuilder.build( new StringReader( target.getConfiguration().toString() ) ); } catch ( XmlPullParserException e1 ) { } catch ( IOException e1 ) { } } if ( targetDom != null ) { Xpp3Dom.mergeXpp3Dom( overrideDom, targetDom ); } else { targetDom = overrideDom; } target.setConfiguration( new XmlPlexusConfiguration( targetDom ) ); } private static void mergeRequirements( ComponentDescriptor<?> override, ComponentDescriptor<?> target ) { List<ComponentRequirement> toAdd = new ArrayList<ComponentRequirement>(); List<ComponentRequirement> toRemove = new ArrayList<ComponentRequirement>(); for ( ComponentRequirement sourceReq : override.getRequirements() ) { for ( ComponentRequirement targetReq : target.getRequirements() ) { // if a fieldName is specified, only override target requirements // that also have a fieldname. if ( sourceReq.getFieldName() != null ) { if ( sourceReq.getFieldName().equals( targetReq.getFieldName() ) ) { toRemove.add( targetReq ); toAdd.add( sourceReq ); break; } } else if ( targetReq.getFieldName() == null ) { // no fieldnames specified - just check for the role; hints may be // overriden too. if ( sourceReq.getRole().equals( targetReq.getRole() ) ) { toRemove.add( targetReq ); toAdd.add( sourceReq ); } } } } target.removeRequirements( toRemove ); target.addRequirements( toAdd ); } }