/* * #%L * Talend :: ESB :: Job :: Controller * %% * Copyright (C) 2011 - 2012 Talend 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. * #L% */ package org.talend.esb.job.controller.internal; import java.util.ArrayList; import java.util.Arrays; import java.util.Dictionary; import java.util.Enumeration; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; import org.jasypt.properties.PropertyValueEncryptionUtils; import org.osgi.service.cm.ConfigurationException; /** * A <code>Configuration</code> represents parameter settings for a Talend job that is provided by * the OSGi Configuration Admin Service. The parameters may be retrieved as an array of option * arguments the way they are expected by the Talend job. */ public final class Configuration { private static final Logger LOG = Logger.getLogger(Configuration.class.getName()); private static final String TIME_OUT_PROPERTY = "org.talend.esb.job.controller.configuration.timeout"; private static final String CONTEXT_PROP = "context"; private static final String CONTEXT_OPT = "--context="; private static final String CONTEXT_PARAM_OPT = "--context_param="; private static final String[] EMPTY_ARGUMENTS = new String[0]; private static final long DEFAULT_TIMEOUT = 3000; private static final String[] DEFAULT_FILTER = new String[0]; private long timeout; private List<String> argumentList; private final CountDownLatch configAvailable = new CountDownLatch(1); private final List<String> filter; private static final String ALGORITHM = "PBEWITHSHA256AND128BITAES-CBC-BC"; private static final String PASSWORD_ENV_NAME = "TESB_ENV_PASSWORD"; private static final String PROVIDER_NAME = "BC"; /** * A <code>Configuration</code> object with no properties set. */ public Configuration() { this(DEFAULT_FILTER); } /** * A <code>Configuration</code> object backed by the given properties from ConfigurationAdmin. * * @param properties the properties from ConfigurationAdmin, may be <code>null</code>. * @throws ConfigurationException thrown if the property values are not of type String */ public Configuration(Dictionary<?, ?> properties) throws ConfigurationException { this(properties, DEFAULT_FILTER); } /** * A <code>Configuration</code> object backed by the given properties from ConfigurationAdmin. * * @param properties the properties from ConfigurationAdmin, may be <code>null</code>. * @param filter list of property keys that are filtered out * @throws ConfigurationException thrown if the property values are not of type String */ public Configuration(Dictionary<?, ?> properties, String[] filter) throws ConfigurationException { this(filter); setProperties(properties); } /** * A <code>Configuration</code> object backed by the given properties from ConfigurationAdmin. * * @param filter list of property keys that are filtered out */ public Configuration(String[] filter) { this.filter = Arrays.asList(filter); initTimeout(); } /** * Set the time to wait in the {@link #awaitArguments()} method for the properties to be set. * * @param timeout time to wait in milliseconds. */ public void setTimeout(long timeout) { this.timeout = timeout; } /** * Back this <code>Configuration</code> by the given properties from ConfigurationAdmin. * * @param properties the properties from ConfigurationAdmin, may be <code>null</code>. * @throws ConfigurationException thrown if the property values are not of type String */ public void setProperties(Dictionary<?, ?> properties) throws ConfigurationException { List<String> newArgumentList = new ArrayList<String>(); if (properties != null) { for (Enumeration<?> keysEnum = properties.keys(); keysEnum.hasMoreElements();) { String key = (String) keysEnum.nextElement(); Object val = properties.get(key); if (val instanceof String) { String value = (String) val; if(PropertyValueEncryptionUtils.isEncryptedValue(value)) { StandardPBEStringEncryptor enc = new StandardPBEStringEncryptor(); EnvironmentStringPBEConfig env = new EnvironmentStringPBEConfig(); env.setProvider(new BouncyCastleProvider()); env.setProviderName(PROVIDER_NAME); env.setAlgorithm(ALGORITHM); env.setPasswordEnvName(PASSWORD_ENV_NAME); enc.setConfig(env); val = PropertyValueEncryptionUtils.decrypt(value, enc); } String strval = convertArgument(key, (String)val); if (strval != null) { newArgumentList.add(strval); } } else { throw new ConfigurationException(key, "Value is not of type String."); } } } argumentList = newArgumentList; configAvailable.countDown(); } /** * Get the configuration properties as argument list as expected by the Talend job. If the properties * were not yet set, wait the time specified by the {@link #setTimeout(long) timeout property} and return * empty argument list if properties still not specified. If <code>timeout <= 0</code> the method * immediately returns. * * @return the argument list, never <code>null</code> */ public String[] awaitArguments() throws InterruptedException { if (configAvailable.await(timeout, TimeUnit.MILLISECONDS)) { return argumentList.toArray(new String[argumentList.size()]); } else { LOG.warning("ConfigAdmin did not pass any properties yet, returning an empty argument list."); return EMPTY_ARGUMENTS; } } private void initTimeout() { timeout = Long.getLong(TIME_OUT_PROPERTY, DEFAULT_TIMEOUT); } private String convertArgument(String key, String value) { if (key.equals(CONTEXT_PROP)) { LOG.fine("Context " + value + " added to the argument list."); return CONTEXT_OPT + value; } else { if (!filter.contains(key)) { LOG.fine("Parameter " + key + " with value " + value + " added to the argument list."); return CONTEXT_PARAM_OPT + key + "=" + value; } else { LOG.fine("Propertey " + key + " filltered out."); return null; } } } }