/* * Copyright (c) 2009-2010 Clark & Parsia, LLC. <http://www.clarkparsia.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 com.clarkparsia.empire.config.io.impl; import com.clarkparsia.empire.config.EmpireConfiguration; import com.clarkparsia.empire.config.ConfigKeys; import com.clarkparsia.empire.config.io.ConfigReader; import com.clarkparsia.empire.util.EmpireAnnotationProvider; import com.clarkparsia.empire.util.BeanReflectUtil; import com.complexible.common.util.EnhancedProperties; import com.google.common.collect.Collections2; import com.google.common.base.Predicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Properties; import java.util.Map; import java.util.HashMap; import java.io.IOException; import java.io.Reader; import java.io.InputStreamReader; import java.io.InputStream; /** * <p>Implementation of a {@link ConfigReader} for reading an Empire configuration from a standard properties file.</p> * * @author Michael Grove * @since 0.6.2 * @version 0.7 * @see EmpireConfiguration */ public class PropertiesConfigReader implements ConfigReader, ConfigKeys { /** * The logger */ private static final Logger LOGGER = LoggerFactory.getLogger(ConfigReader.class.getName()); public static final String KEY_NAME = ConfigKeys.NAME; public static final String KEY_ANNOTATION_PROVIDER = "annotation.provider"; /** * @inheritDoc */ public EmpireConfiguration read(InputStream theStream) throws IOException { return read(new InputStreamReader(theStream)); } /** * @inheritDoc */ public EmpireConfiguration read(Reader theReader) throws IOException { Properties aProps = new EnhancedProperties(); try { aProps.load(theReader); } catch (Exception e) { throw new IOException(e); } int aIndex = 0; Map<String, String> aGeneralConfig = new HashMap<String, String>(); Map<String, Map<String, String>> aUnitConfig = new HashMap<String, Map<String, String>>(); while (aProps.containsKey(aIndex+"."+KEY_NAME)) { String aPrefix = aIndex+"."; Map<String, String> aUnit = new HashMap<String, String>(); for (Object aOrigKey : Collections2.filter(aProps.keySet(), new PrefixPredicate(aPrefix))) { String aKey = aOrigKey.toString(); aKey = aKey.substring(aPrefix.length()); aUnit.put(aKey, aProps.getProperty(aOrigKey.toString())); } aUnitConfig.put(aProps.getProperty(aIndex+"."+KEY_NAME), aUnit); aIndex++; } for (Object aOrigKey : Collections2.filter(aProps.keySet(), new UnitFilterPredicate())) { aGeneralConfig.put(aOrigKey.toString(), aProps.getProperty(aOrigKey.toString())); } EmpireConfiguration aConfig = new EmpireConfiguration(aGeneralConfig, aUnitConfig); if (aGeneralConfig.containsKey(KEY_ANNOTATION_PROVIDER)) { try { @SuppressWarnings("unchecked") Class<EmpireAnnotationProvider> aClass = (Class<EmpireAnnotationProvider>) BeanReflectUtil.loadClass(aGeneralConfig.get(KEY_ANNOTATION_PROVIDER)); aConfig.setAnnotationProvider(aClass); } catch (ClassNotFoundException e) { LOGGER.warn("Annotation provider implementation '{}' cannot be found, please check your classpath.", aGeneralConfig.get(KEY_ANNOTATION_PROVIDER)); } catch (ClassCastException e) { LOGGER.warn("Specified annotation provider implementation '{}' is not a valid EmpireAnnotationProvider.", aGeneralConfig.get(KEY_ANNOTATION_PROVIDER)); } } return aConfig; } /** * Filter for returning only non-unit property keys */ private static class UnitFilterPredicate implements Predicate<Object> { /** * @inheritDoc */ public boolean apply(final Object theValue) { String aStr = theValue.toString(); // the standard format for unit properties in the file is <index>.<property_name> // all these properties have been put into the appropriate unit config map. // so we want to get rid of them and only include the properties which do not // fit this format in the general config. if they don't have a period, they are // fine, and if they do have a period, but the stuff before the period is not a // number, that's good too. otherwise, it's a unit property or something that // *looks* like a unit property, so we'll filter that out if (aStr.indexOf(".") == -1) { return true; } else { String aPrefix = aStr.substring(0, aStr.indexOf(".")); try { Integer.parseInt(aPrefix); return false; } catch (NumberFormatException e) { return true; } } } } /** * Filter for only returning values whose toString() starts with the specified prefix. Used to filter out * property keys not in the current unit. */ private static class PrefixPredicate implements Predicate<Object> { private String mPrefix; private PrefixPredicate(final String thePrefix) { mPrefix = thePrefix; } /** * @inheritDoc */ public boolean apply(final Object theValue) { return theValue.toString().startsWith(mPrefix); } } public static void main(String[] args) throws Exception { String aConfig = "annotation.provider = com.clarkparsia.empire.util.PropertiesAnnotationProvider\n" + "0.name = context1\n" + "0.factory = com.clarkparsia.empire.sesame.RepositoryDataSourceFactory\n" + "0.url = http://localhost:8080/openrdf-sesame\n" + "0.repo = mem-rdf-db\n" + "\n" + "1.name = context2\n" + "1.factory = com.clarkparsia.empire.jena.JenaTestDataSourceFactory\n"; new PropertiesConfigReader().read(new java.io.StringReader(aConfig)); } }