/** * Licensed to the Austrian Association for Software Tool Integration (AASTI) * under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. The AASTI licenses this file to you 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.openengsb.core.services.internal.deployer.connector; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.Transformer; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.MapDifference; import com.google.common.collect.Maps; public class ConnectorFile { private static final String PROPERTY = "property"; private static final String ATTRIBUTE = "attribute"; private static final String LIST_DELIMITER = ","; private String name; private String domainType; private String connectorType; private ImmutableMap<String, String> attributes; private ImmutableMap<String, Object> properties; public static class ChangeSet { private String domainType; private String connectorType; private MapDifference<String, String> changedAttributes; private MapDifference<String, Object> changedProperties; public ChangeSet(String domainType, String connectorType, MapDifference<String, String> changedAttributes, MapDifference<String, Object> changedProperties) { this.domainType = domainType; this.connectorType = connectorType; this.changedAttributes = changedAttributes; this.changedProperties = changedProperties; } public MapDifference<String, String> getChangedAttributes() { return changedAttributes; } public MapDifference<String, Object> getChangedProperties() { return changedProperties; } public String getDomainType() { return domainType; } public String getConnectorType() { return connectorType; } } public ConnectorFile(File connectorFile) { name = FilenameUtils.removeExtension(connectorFile.getName()); update(connectorFile); } private ImmutableMap<String, String> getAttributesFromMap(ImmutableMap<String, String> propertyMap) { return getFilteredEntries(propertyMap, ATTRIBUTE); } private ImmutableMap<String, Object> getPropertiesFromMap(Map<String, String> propertyMap) { ImmutableMap<String, String> serviceProperties = getFilteredEntries(propertyMap, PROPERTY); Map<String, Object> transformedProperties = Maps.transformValues(serviceProperties, new Function<String, Object>() { @Override public Object apply(String input) { if (input.contains(LIST_DELIMITER)) { return splitBySeparatorAndTrimItems(input); } if (NumberUtils.isNumber(input)) { return NumberUtils.createNumber(input); } return input; } private Object splitBySeparatorAndTrimItems(String input) { String[] split = input.split(LIST_DELIMITER); for (int i = 0; i < split.length; i++) { split[i] = StringUtils.trim(split[i]); } return split; } }); return ImmutableMap.copyOf(transformedProperties); } public ChangeSet getChanges(File file) { ImmutableMap<String, String> newPropertyMap = readProperties(file); MapDifference<String, String> changedAttributes = Maps.difference(attributes, getAttributesFromMap(newPropertyMap)); MapDifference<String, Object> changedProperties = Maps.difference(properties, getPropertiesFromMap(newPropertyMap)); return new ChangeSet(newPropertyMap.get("domainType"), newPropertyMap.get("connectorType"), changedAttributes, changedProperties); } public void update(File file) { ImmutableMap<String, String> newPropertyMap = readProperties(file); domainType = newPropertyMap.get("domainType"); connectorType = newPropertyMap.get("connectorType"); attributes = getAttributesFromMap(newPropertyMap); properties = getPropertiesFromMap(newPropertyMap); } private ImmutableMap<String, String> readProperties(File file) { FileReader reader = null; try { reader = new FileReader(file); Properties props = new Properties(); props.load(reader); Map<String, String> map = Maps.fromProperties(props); Map<String, String> transformedMap = Maps.transformValues(map, new TrimFunction<String, String>()); return ImmutableMap.copyOf(transformedMap); } catch (FileNotFoundException e) { throw new IllegalStateException(e); } catch (IOException e) { throw new IllegalStateException(e); } finally { IOUtils.closeQuietly(reader); } } private ImmutableMap<String, String> getFilteredEntries(Map<String, String> propertyMap, final String prefix) { @SuppressWarnings("unchecked") Map<String, String> transformedMap = MapUtils.transformedMap(new HashMap<String, String>(), new Transformer() { @Override public Object transform(Object input) { return ((String) input).replaceFirst(prefix + ".", ""); } }, null); Map<String, String> filterEntries = Maps.filterEntries(propertyMap, new Predicate<Map.Entry<String, String>>() { @Override public boolean apply(Entry<String, String> input) { return input.getKey().startsWith(prefix + "."); } }); transformedMap.putAll(filterEntries); return ImmutableMap.copyOf(transformedMap); } public Properties toProperties() { Properties result = new Properties(); result.put("domainType", domainType); result.put("connectorType", connectorType); for (Entry<String, String> entry : attributes.entrySet()) { result.put(ATTRIBUTE + "." + entry.getKey(), entry.getValue()); } for (Entry<String, Object> entry : properties.entrySet()) { String key = PROPERTY + "." + entry.getKey(); Object value = entry.getValue(); if (value.getClass().isArray()) { result.put(key, StringUtils.join((Object[]) value)); } else { result.put(key, value); } } return result; } public static Boolean isRootService(File connectorFile) { return isRootServiceDirectory(connectorFile.getParentFile()); } private static Boolean isRootServiceDirectory(File directory) { return directory.isDirectory() && directory.getName().equals("etc"); } public String getName() { return name; } public String getDomainType() { return domainType; } public String getConnectorType() { return connectorType; } public ImmutableMap<String, String> getAttributes() { return attributes; } public ImmutableMap<String, Object> getProperties() { return properties; } private class TrimFunction<F, T> implements Function<F, T> { @SuppressWarnings("unchecked") @Override public Object apply(Object input) { return (input == null) ? null : ((String) input).trim(); } } }