package org.camunda.bpm.extension.osgi.configadmin.impl;

import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.ProcessEngineConfiguration;
import org.camunda.bpm.extension.osgi.blueprint.BundleDelegatingClassLoader;
import org.camunda.bpm.extension.osgi.blueprint.ClassLoaderWrapper;
import org.camunda.bpm.extension.osgi.configadmin.ManagedProcessEngineFactory;
import org.camunda.bpm.extension.osgi.engine.ProcessEngineFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;

@SuppressWarnings("rawtypes")
public class ManagedProcessEngineFactoryImpl implements ManagedProcessEngineFactory {

  private Map<String, ProcessEngine> existingEngines = new ConcurrentHashMap<String, ProcessEngine>();
  private Map<String, ServiceRegistration> existingRegisteredEngines = new ConcurrentHashMap<String, ServiceRegistration>();
  private BundleContext ctx;

  public ManagedProcessEngineFactoryImpl(BundleContext bundleContext) {
    this.ctx = bundleContext;
  }

  @Override
  public String getName() {
    return SERVICE_PID;
  }

  @Override
  public void updated(String pid, Dictionary properties) throws ConfigurationException {
    if (existingEngines.containsKey(pid)) {
      existingEngines.get(pid).close();
      existingRegisteredEngines.get(pid).unregister();
    }
    ClassLoader previous = Thread.currentThread().getContextClassLoader();
    Bundle bundle = FrameworkUtil.getBundle(ProcessEngine.class);
    ProcessEngine engine;
    try {
      ClassLoader cl = new BundleDelegatingClassLoader(bundle);
      Thread.currentThread().setContextClassLoader(
          new ClassLoaderWrapper(cl, ProcessEngineFactory.class.getClassLoader(), ProcessEngineConfiguration.class.getClassLoader(), previous));
      ProcessEngineConfiguration processEngineConfiguration = createProcessEngineConfiguration(properties);
      processEngineConfiguration.setClassLoader(cl);
      engine = processEngineConfiguration.buildProcessEngine();
    } finally {
      Thread.currentThread().setContextClassLoader(previous);
    }
    existingEngines.put(pid, engine);
    Hashtable<String, Object> props = new Hashtable<String, Object>();
    props.put("process-engine-name", engine.getName());
    ServiceRegistration serviceRegistration = ctx.registerService(ProcessEngine.class.getName(), engine, props);
    existingRegisteredEngines.put(pid, serviceRegistration);
  }

  @SuppressWarnings("unchecked")
  private ProcessEngineConfiguration createProcessEngineConfiguration(Dictionary properties) throws ConfigurationException {
    ProcessEngineConfigurationFromProperties processEngineConfiguration = new ProcessEngineConfigurationFromProperties();
    processEngineConfiguration.configure(properties);
//    for (Object key : Collections.list(properties.keys())) {
//      char[] keyStringArray = String.valueOf(key).toCharArray();
//      keyStringArray[0] = Character.toUpperCase(keyStringArray[0]);
//      String keyString = String.valueOf(keyStringArray);
//      if (String.valueOf(key).equals("service.pid") || String.valueOf(key).equals("service.factoryPid")) {
//        continue;
//      }
//      try {
//        // because there are non-void setters we cannot use PropertyUtils
//        MethodUtils.invokeMethod(processEngineConfiguration, "set" + keyString, properties.get(key));
//      } catch (Exception e) {
//        throw new ConfigurationException(String.valueOf(key), "Property does not exist", e);
//      }
//    }
    return processEngineConfiguration;
  }

  @Override
  public void deleted(String pid) {
    ProcessEngine engine = existingEngines.get(pid);
    engine.close();
    existingEngines.remove(pid);
    existingRegisteredEngines.get(pid).unregister();
  }

}

@@ -68,26 +68,82 @@
 va.util.
-Dictionary
+Collections;%0Aimport java.util.Dictionary;%0Aimport java.util.HashMap
 ;%0Aimport
@@ -1636,24 +1636,93 @@
 er();%0A    %7D%0A
+    if(!hasPropertiesConfiguration(properties))%7B%0A      return;%0A    %7D%0A
     ClassLoa
@@ -2806,273 +2806,315 @@
 %0A%0A  
-@SuppressWarnings(%22unchecked%22)%0A  private ProcessEngineConfiguration createProcessEngineConfiguration(Dictionary properties) throws ConfigurationException %7B%0A    ProcessEngineConfigurationFromProperties processEngineConfiguration = new ProcessEngineConfigurationFromP
+/**%0A   * It happends that the factory get called with properties that only contain%0A   * service.pid and service.factoryPid. If that happens we don't want to create an engine.%0A   * @param properties%0A   * @return%0A   */%0A  @SuppressWarnings(%22unchecked%22)%0A  private boolean hasPropertiesConfiguration(Dictionary p
 rope
@@ -3122,52 +3122,83 @@
 ties
-();
+) %7B
 %0A    
-processEngineConfiguration.configure
+HashMap%3CObject, Object%3E mapProperties = new HashMap%3CObject, Object%3E
 (pro
@@ -3208,21 +3208,25 @@
 ties
+.size()
 );%0A
-//
     for
- 
 (Obj
@@ -3234,17 +3234,16 @@
 ct key :
- 
 Collecti
@@ -3274,684 +3274,531 @@
 ()))
- 
 %7B%0A
-//
       
-char%5B%5D keyStringArray = String.valueOf(key).toCharArray();%0A//      keyStringArray%5B0%5D = Character.toUpperCase(keyStringArray%5B0%5D
+mapProperties.put(key, properties.get(key)
 );%0A
-//
     
-  String keyString = String.valueOf(keyStringArray);%0A//      if (String.valueOf(key).equals(%22service.pid%22) %7C%7C String.valueOf(key).equals(%22service.factoryPid%22)) %7B%0A//        continue;%0A//      %7D%0A//      try %7B%0A//        // because there are non-void setters we cannot use PropertyUtils%0A//        MethodUtils.invokeMethod(processEngineConfiguration, %22set%22 + keyString, properties.get(key));%0A//      %7D catch (Exception e) %7B%0A//        throw new ConfigurationException(String.valueOf(key), %22Property does not exist%22, e);%0A//      %7D%0A//    %7D
+%7D%0A    mapProperties.remove(%22service.pid%22);%0A    mapProperties.remove(%22service.factoryPid%22);%0A    return !mapProperties.isEmpty();%0A  %7D%0A%0A  @SuppressWarnings(%22unchecked%22)%0A  private ProcessEngineConfiguration createProcessEngineConfiguration(Dictionary properties) throws ConfigurationException %7B%0A    ProcessEngineConfigurationFromProperties processEngineConfiguration = new ProcessEngineConfigurationFromProperties();%0A    processEngineConfiguration.configure(properties);
 %0A   

add check method for nearly empty config