1 50 51 package org.apache.excalibur.configuration.merged; 52 53 import java.util.HashSet ; 54 import java.util.Set ; 55 56 import org.apache.avalon.framework.configuration.Configuration; 57 import org.apache.avalon.framework.configuration.ConfigurationException; 58 import org.apache.avalon.framework.configuration.DefaultConfiguration; 59 import org.apache.excalibur.configuration.ConfigurationUtil; 60 61 82 public class ConfigurationMerger 83 { 84 94 public static Configuration merge( final Configuration layer, final Configuration base ) 95 throws ConfigurationException 96 { 97 final DefaultConfiguration merged = 98 new DefaultConfiguration( base.getName(), 99 "Merged [layer: " + layer.getLocation() 100 + ", base: " + base.getLocation() + "]" ); 101 102 copyAttributes( base, merged ); 103 copyAttributes( layer, merged ); 104 105 mergeChildren( layer, base, merged ); 106 107 merged.setValue( getValue( layer, base ) ); 108 merged.makeReadOnly(); 109 110 return merged; 111 } 112 113 private static void mergeChildren( final Configuration layer, 114 final Configuration base, 115 final DefaultConfiguration merged ) 116 throws ConfigurationException 117 { 118 final Configuration[] lc = layer.getChildren(); 119 final Configuration[] bc = base.getChildren(); 120 final Set baseUsed = new HashSet (); 121 122 for( int i = 0; i < lc.length; i++ ) 123 { 124 final Configuration mergeWith = getMergePartner( lc[ i ], layer, base ); 125 126 if( null == mergeWith ) 127 { 128 merged.addChild( lc[ i ] ); 129 } 130 else 131 { 132 merged.addChild( merge( lc[ i ], mergeWith ) ); 133 134 baseUsed.add( mergeWith ); 135 } 136 } 137 138 for( int i = 0; i < bc.length; i++ ) 139 { 140 if( !baseUsed.contains( bc[ i ] ) ) 141 { 142 merged.addChild( bc[ i ] ); 143 } 144 } 145 } 146 147 private static Configuration getMergePartner( final Configuration toMerge, 148 final Configuration layer, 149 final Configuration base ) 150 throws ConfigurationException 151 { 152 if( toMerge.getAttributeAsBoolean( Constants.MERGE_ATTR, false ) ) 153 { 154 final String keyAttribute = toMerge.getAttribute( Constants.KEY_ATTR, null ); 155 final String keyvalue = 156 keyAttribute == null ? null : toMerge.getAttribute( keyAttribute ); 157 158 final Configuration[] layerKids = ConfigurationUtil.match( layer, 159 toMerge.getName(), 160 keyAttribute, 161 keyvalue ); 162 163 final Configuration[] baseKids = ConfigurationUtil.match( base, 164 toMerge.getName(), 165 keyAttribute, 166 keyvalue ); 167 168 if( layerKids.length == 1 && baseKids.length == 1 ) 169 { 170 return baseKids[ 0 ]; 171 } 172 else 173 { 174 throw new ConfigurationException( "Unable to merge configuration item, " 175 + "multiple matches on child or base [name: " 176 + toMerge.getName() + "]" ); 177 } 178 } 179 180 return null; 181 } 182 183 private static String getValue( final Configuration layer, final Configuration base ) 184 { 185 try 186 { 187 return layer.getValue(); 188 } 189 catch( ConfigurationException e ) 190 { 191 return base.getValue( null ); 192 } 193 } 194 195 private static void copyAttributes( final Configuration source, 196 final DefaultConfiguration dest ) 197 throws ConfigurationException 198 { 199 final String [] names = source.getAttributeNames(); 200 201 for( int i = 0; i < names.length; i++ ) 202 { 203 if( !names[ i ].startsWith( Constants.MERGE_METADATA_PREFIX ) ) 204 { 205 dest.setAttribute( names[ i ], source.getAttribute( names[ i ] ) ); 206 } 207 } 208 } 209 } 210 | Popular Tags |