/*******************************************************************************
*
* Pentaho Big Data
*
* Copyright (C) 2002-2015 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed 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.pentaho.hadoop.shim.api;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.commons.lang.SystemUtils;
/**
* Subclass of java.util.Properties with support for overriding properties with different config values (e.g. mr1 vs mr2
* config differences)
*/
public class ShimProperties extends Properties {
public static interface WindowsChecker {
boolean isWindows();
}
private static final long serialVersionUID = 2033564331119378266L;
public static final String SHIM_CP_CONFIG = "shim.current.config";
private final WindowsChecker windowsChecker;
public static enum ListOverrideType {
REPLACE, APPEND, PREPEND
}
public static enum SetOverrideType {
REPLACE, OVERLAY
}
public ShimProperties() {
this( new WindowsChecker() {
@Override
public boolean isWindows() {
return SystemUtils.IS_OS_WINDOWS;
}
} );
}
protected ShimProperties( WindowsChecker windowsChecker ) {
this.windowsChecker = windowsChecker;
}
private List<String> getShimConfigs() {
List<String> shimConfigs = new ArrayList<String>();
String shimCurrentConfig = super.getProperty( SHIM_CP_CONFIG );
String os = "linux";
if ( windowsChecker.isWindows() ) {
os = "windows";
}
shimConfigs.add( os );
if ( shimCurrentConfig != null ) {
for ( String config : shimCurrentConfig.trim().split( "," ) ) {
shimConfigs.add( config.trim() );
shimConfigs.add( os + "." + config.trim() );
}
}
return shimConfigs;
}
private List<String> getShimConfigProperties( String property ) {
List<String> shimConfigProperties = new ArrayList<String>();
for ( String config : getShimConfigs() ) {
shimConfigProperties.add( super.getProperty( config + "." + property ) );
}
return shimConfigProperties;
}
/**
* Gets a list from a comma separated property with support for overrides, defaulting to Append behavior
*
* @param property the property
* @return the list
*/
public List<String> getConfigList( String property ) {
return getConfigList( property, ListOverrideType.APPEND );
}
/**
* Gets a list from a comma separated property with support for overrides
*
* @param property the property
* @param listOverrideType the override type
* @return the list
*/
public List<String> getConfigList( String property, ListOverrideType listOverrideType ) {
List<String> shimConfigValues = getShimConfigProperties( property );
List<String> shimProperties = new ArrayList<String>();
String globalValues = super.getProperty( property );
if ( globalValues != null && globalValues.trim().length() > 0 ) {
shimProperties.addAll( Arrays.asList( globalValues.split( "," ) ) );
}
for ( String shimConfigValue : shimConfigValues ) {
if ( shimConfigValue != null ) {
List<String> shimProperty = new ArrayList<String>();
if ( shimConfigValue.trim().length() > 0 ) {
for ( String prop : shimConfigValue.trim().split( "," ) ) {
shimProperty.add( prop.trim() );
}
}
switch ( listOverrideType ) {
case APPEND:
shimProperties.addAll( shimProperty );
break;
case PREPEND:
shimProperty.addAll( shimProperties );
shimProperties = shimProperty;
break;
case REPLACE:
shimProperties = shimProperty;
break;
}
}
}
return shimProperties;
}
/**
* Gets a list from a comma separated property with support for overrides, defaulting to Overlay behavior
*
* @param property the property
* @return the list
*/
public Set<String> getConfigSet( String property ) {
return getConfigSet( property, SetOverrideType.OVERLAY );
}
/**
* Gets a list from a comma separated property with support for overrides
*
* @param property the property
* @param overrideType the override type
* @return the list
*/
public Set<String> getConfigSet( String property, SetOverrideType overrideType ) {
List<String> shimConfigValues = getShimConfigProperties( property );
Set<String> shimProperties = new HashSet<String>();
String globalValues = super.getProperty( property );
if ( globalValues != null && globalValues.trim().length() > 0 ) {
shimProperties.addAll( Arrays.asList( globalValues.split( "," ) ) );
}
for ( String shimConfigValue : shimConfigValues ) {
if ( shimConfigValue != null ) {
Set<String> shimProperty = new HashSet<String>();
if ( shimConfigValue.trim().length() > 0 ) {
for ( String prop : shimConfigValue.trim().split( "," ) ) {
shimProperty.add( prop.trim() );
}
}
switch ( overrideType ) {
case OVERLAY:
shimProperties.addAll( shimProperty );
break;
case REPLACE:
shimProperties = shimProperty;
break;
}
}
}
return shimProperties;
}
@Override
public String getProperty( String key ) {
List<String> configProperties = getShimConfigProperties( key );
for ( int i = configProperties.size() - 1; i >= 0; i-- ) {
String property = configProperties.get( i );
if ( property != null ) {
property = property.trim();
if ( property.length() > 0 ) {
return property;
}
}
}
return super.getProperty( key );
}
/**
* Returns a map of key -> value of all shim properties with the given prefix (the prefix is removed)
*
* @param prefix the prefix to look for
* @return a map of key -> value of all shim properties with the given prefix (the prefix is removed)
*/
public Map<String, String> getPrefixedProperties( String prefix ) {
List<String> propertyPrefixes = new ArrayList<String>();
propertyPrefixes.add( prefix + "." );
for ( String shimConfig : getShimConfigs() ) {
propertyPrefixes.add( shimConfig + "." + prefix.trim() + "." );
}
Map<String, String> prefixedProperties = new HashMap<String, String>();
for ( String currentPrefix : propertyPrefixes ) {
for ( String propertyName : stringPropertyNames() ) {
if ( propertyName.startsWith( currentPrefix ) ) {
prefixedProperties.put( propertyName.substring( currentPrefix.length() ), super.getProperty( propertyName ) );
}
}
}
return prefixedProperties;
}
}