/* * Copyright (C) 2012 Google Inc. * * 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 interactivespaces.configuration; import interactivespaces.InteractiveSpacesException; import interactivespaces.SimpleInteractiveSpacesException; import interactivespaces.evaluation.ExpressionEvaluator; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; /** * A file based configuration storage manager. * * @author Keith M. Hughes */ public class SimplePropertyFileSingleConfigurationStorageManager implements SingleConfigurationStorageManager { /** * The properties object being handled. */ private Properties properties; /** * The configuration being managed. */ private Configuration configuration; /** * The file containing the configuration. */ private File configurationFile; /** * {@code true} if this configuration must exist. * * <p> * Loading non-existent configurations is legal. */ private boolean required; /** * Last time the file was modified. */ private long lastModifiedTime = 0; /** * Construct a new manager. * * <p> * The expression evaluator is supplied. * * @param required * {@code true} if this configuration must exist * @param configurationFile * the file containing the configuration */ public SimplePropertyFileSingleConfigurationStorageManager(boolean required, File configurationFile) { this(required, configurationFile, null); } /** * Construct a new manager. * * <p> * Loading non-existent configurations is legal if they are not required. * * @param required * {@code true} if this configuration must exist * @param configurationFile * the file containing the configuration * @param expressionEvaluator * the expression evaluator for the storage manager */ public SimplePropertyFileSingleConfigurationStorageManager(boolean required, File configurationFile, ExpressionEvaluator expressionEvaluator) { this.required = required; this.configurationFile = configurationFile; properties = new Properties(); this.configuration = new PropertiesConfiguration(properties, expressionEvaluator); } @Override public Configuration getConfiguration() { return configuration; } @Override public SingleConfigurationStorageManager load() { if (configurationFile.exists()) { long newLastModified = configurationFile.lastModified(); if (newLastModified > lastModifiedTime) { lastModifiedTime = newLastModified; // Configuration holds the same properties object, // so no need to clear configuration. properties.clear(); FileReader reader = null; try { reader = new FileReader(configurationFile); properties.load(reader); } catch (Exception e) { throw new InteractiveSpacesException(String.format("Cannot read configuration file %s", configurationFile.getAbsolutePath()), e); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { // Don't care } } } } } else { if (required) { throw new SimpleInteractiveSpacesException(String.format("Cannot locate required configuration file %s", configurationFile.getAbsolutePath())); } } return this; } @Override public SingleConfigurationStorageManager save() { FileOutputStream out = null; try { out = new FileOutputStream(configurationFile); properties.store(out, "Configuration updated"); out.flush(); } catch (IOException e) { throw new InteractiveSpacesException("Could not save configuration file " + configurationFile, e); } finally { if (out != null) { try { out.close(); } catch (IOException e) { // Don't care. } } } return this; } @Override public SingleConfigurationStorageManager update(Map<String, String> update) { for (Entry<String, String> entry : update.entrySet()) { properties.put(entry.getKey(), entry.getValue()); } return this; } @Override public SingleConfigurationStorageManager clear() { properties.clear(); return this; } }