/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.properties; import gw.config.CommonServices; import gw.fs.IFile; import gw.internal.gosu.util.StringUtil; import gw.lang.reflect.module.IModule; import gw.util.Pair; import gw.util.concurrent.LockingLazyVar; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeSet; /** * A property set based on an underlying {@link Properties} object. Knows how to finds Properties * files within a module and to converts them into PropertySet objects. */ public class PropertiesPropertySet implements PropertySet { /** * Knows how to find all the property files in a module and create PropertiesPropertySets * from them. */ public static class Source implements PropertySetSource { private static final String EXTENSION = ".properties"; private final IModule _module; private final LockingLazyVar<Map<String,IFile>> _filesByTypeName = new LockingLazyVar<Map<String, IFile>>() { @Override protected Map<String, IFile> init() { List<Pair<String, IFile>> propertiesFiles = _module.getFileRepository().findAllFilesByExtension(EXTENSION); final int initialCapacity = propertiesFiles.size(); Map<String,IFile> result = new HashMap<String, IFile>( initialCapacity ); for (Pair<String,IFile> pair : propertiesFiles) { String fileName = pair.getFirst(); if( !PropertiesTypeLoader.isDisplayPropertiesFile( pair.getSecond().getName() ) ) { String typeName = fileName.substring(0, fileName.length() - EXTENSION.length()).replace('/', '.'); if (isValidTypeName(typeName)) { result.put(typeName, pair.getSecond()); } } } return result; } }; @Override public PropertySet getPropertySetForFile(IFile file) { for (Map.Entry<String, IFile> entry : _filesByTypeName.get().entrySet()){ IFile value = entry.getValue(); if (value.equals(file)) { return getPropertySet(entry.getKey()); } } return null; } @Override public IFile getFile(String name) { return _filesByTypeName.get().get(name); } public Source(IModule module) { _module = module; } @Override public Set<String> getPropertySetNames() { return _filesByTypeName.get().keySet(); } @Override public PropertySet getPropertySet(String name) { IFile file = _filesByTypeName.get().get(name); if (file == null) { throw new IllegalArgumentException(name + " is not the name of a properties file property set"); } PropertySet result = new EmptyPropertySet(name); if (file.exists()) { try { InputStream propertiesStream = file.openInputStream(); Properties properties = new Properties(); try { properties.load(propertiesStream); result = new PropertiesPropertySet(name, properties); } finally { closeSafely(propertiesStream); } } catch (IOException e) { CommonServices.getEntityAccess().getLogger().error(String.format("Could not read property file %s", file), e); } } return result; } private static boolean isValidTypeName(String typeName) { List<String> nameParts = StringUtil.tokenizeToList(typeName, '.'); if (nameParts == null || nameParts.isEmpty()) { return false; } for (String namePart : nameParts) { if (!PropertyNode.isGosuIdentifier(namePart)) { return false; } } return true; } private static void closeSafely(InputStream inputStream) { try { inputStream.close(); } catch (IOException e) { // Ignore } } } private final String _name; private final Set<String> _keys; private final Properties _properties; public PropertiesPropertySet(String name, Properties properties) { _name = name; _properties = properties; _keys = getStringPropertyNames(properties); } @Override public Set<String> getKeys() { return _keys; } @Override public String getName() { return _name; } @Override public String getValue(String key) { return _properties.getProperty(key); } private Set<String> getStringPropertyNames(Properties properties) { // Can't use properties.stringPropertyNames() because it's not available in Java 1.5 Set<String> result = new TreeSet<String>(); for (Map.Entry<Object, Object> entry : properties.entrySet()) { if (entry.getKey() instanceof String && entry.getValue() instanceof String) { result.add((String) entry.getKey()); } } return Collections.unmodifiableSet(result); } }