/* * Copyright (C) 2012 John Casey. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.redhat.rcm.version.mgr.session; import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.MapBasedValueSource; import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.redhat.rcm.version.VManException; public class PropertyMappings { private final Logger logger = LoggerFactory.getLogger( getClass() ); private static final String EXPRESSION_PATTERN = "@([^@]+)@"; private final Map<String, String> mappings = new HashMap<String, String>(); private final Map<String, String> expressions = new HashMap<String, String>(); public PropertyMappings( final Map<String, String> newMappings ) { addMappings( null, newMappings ); } PropertyMappings addBomPropertyMappings( final File bom, final Properties properties ) { return addBomPropertyMappings( bom, properties, mappings ); } PropertyMappings addBomPropertyMappings( final File bom, final Properties properties, final Map<String, String> newMappings ) { addMappings( properties, newMappings ); final Map<String, String> fromProps = new HashMap<String, String>(); for ( final String key : properties.stringPropertyNames() ) { fromProps.put( key, properties.getProperty( key ) ); } // Add the BOM's own properties into the mappings... addMappings( properties, fromProps ); return this; } public String getMappedValue( final String key, final VersionManagerSession session ) { final String raw = mappings.get( key ); if ( raw == null ) { return null; } final StringSearchInterpolator interpolator = new StringSearchInterpolator( "@", "@" ); interpolator.addValueSource( new MapBasedValueSource( mappings ) ); try { return interpolator.interpolate( raw ); } catch ( final InterpolationException e ) { logger.error( "Invalid expression: '%s'. Reason: %s", e, raw, e.getMessage() ); session.addError( new VManException( "Invalid expression: '%s'. Reason: %s", e, raw, e.getMessage() ) ); } return null; } private void addMappings( final Properties properties, final Map<String, String> newMappings ) { final Pattern pattern = Pattern.compile( EXPRESSION_PATTERN ); if ( newMappings != null ) { for ( final Map.Entry<String, String> entry : newMappings.entrySet() ) { final String val = entry.getValue(); final Matcher matcher = pattern.matcher( val ); if ( matcher.matches() ) { final String k = matcher.group( 1 ); if ( ( !mappings.containsKey( k ) && !newMappings.containsKey( k ) ) || // Its also an expression if the property exists in the global properties map. ( properties != null && properties.containsKey( k ) ) ) { expressions.put( entry.getKey(), matcher.group( 1 ) ); } else { mappings.put( entry.getKey(), val ); } } // Only add the mapping if a previous BOM has not already added it. else if ( !mappings.containsKey( entry.getKey() )) { mappings.put( entry.getKey(), val ); } } } } public Set<String> getKeys() { return mappings.keySet(); } /* * This method should take a properties from a BOM and look through that to update the mappings value with the real * value. */ void updateProjectMap( final Properties properties ) { final Set<Map.Entry<String, String>> contents = expressions.entrySet(); for ( final Iterator<Map.Entry<String, String>> i = contents.iterator(); i.hasNext(); ) { final Map.Entry<String, String> v = i.next(); final String value = properties.getProperty( v.getValue() ); if ( value == null ) { continue; } mappings.put( v.getKey(), value ); logger.info( "Replacing " + v.getKey() + " with value from " + v.getValue() + '(' + mappings.get( v.getKey() ) + ')' ); i.remove(); } } }