Updated Branches:
  refs/heads/master 973ba6533 -> e3867e001

CAMEL-6683: camel-dozer works better with OSGi. Allow to configure dozer bean 
mapper without causing it to init itself to eagerly (due dozer doing that 
automatic) which allows us to better setup classloader for OSGi.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/e3867e00
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/e3867e00
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/e3867e00

Branch: refs/heads/master
Commit: e3867e001ca6dce834c71b1b8958b11f8cfb8079
Parents: 973ba65
Author: Claus Ibsen <davscl...@apache.org>
Authored: Fri Aug 30 10:03:46 2013 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Fri Aug 30 10:03:59 2013 +0200

----------------------------------------------------------------------
 .../dozer/CamelToDozerClassResolverAdapter.java |  46 ++++++++
 .../dozer/DozerBeanMapperConfiguration.java     |  73 +++++++++++++
 .../dozer/DozerTypeConverterLoader.java         | 109 +++++++++++++++----
 ...ringDozerTypeConverterConfigurationTest.java |  43 ++++++++
 ...pringDozerTypeConverterConfigurationTest.xml |  43 ++++++++
 5 files changed, 295 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/e3867e00/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/CamelToDozerClassResolverAdapter.java
----------------------------------------------------------------------
diff --git 
a/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/CamelToDozerClassResolverAdapter.java
 
b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/CamelToDozerClassResolverAdapter.java
new file mode 100644
index 0000000..ad913d1
--- /dev/null
+++ 
b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/CamelToDozerClassResolverAdapter.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.converter.dozer;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultClassResolver;
+import org.apache.camel.spi.ClassResolver;
+import org.dozer.util.DozerClassLoader;
+
+public final class CamelToDozerClassResolverAdapter implements 
DozerClassLoader {
+
+    private final ClassResolver classResolver;
+
+    public CamelToDozerClassResolverAdapter() {
+        // must have a default nor-arg constructor to allow Dozer to work with 
OSGi
+        classResolver = new DefaultClassResolver();
+    }
+
+    public CamelToDozerClassResolverAdapter(CamelContext camelContext) {
+        classResolver = camelContext.getClassResolver();
+    }
+
+    public Class<?> loadClass(String name) {
+        return classResolver.resolveClass(name);
+    }
+
+    public URL loadResource(String name) {
+        return DozerTypeConverterLoader.loadMappingFile(classResolver, name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e3867e00/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerBeanMapperConfiguration.java
----------------------------------------------------------------------
diff --git 
a/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerBeanMapperConfiguration.java
 
b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerBeanMapperConfiguration.java
new file mode 100644
index 0000000..6257547
--- /dev/null
+++ 
b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerBeanMapperConfiguration.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.converter.dozer;
+
+import java.util.List;
+import java.util.Map;
+
+import org.dozer.CustomConverter;
+import org.dozer.CustomFieldMapper;
+import org.dozer.DozerEventListener;
+
+public class DozerBeanMapperConfiguration {
+
+    private List<String> mappingFiles;
+    private List<CustomConverter> customConverters;
+    private List<DozerEventListener> eventListeners;
+    private Map<String, CustomConverter> customConvertersWithId;
+    private CustomFieldMapper customFieldMapper;
+
+    public List<String> getMappingFiles() {
+        return mappingFiles;
+    }
+
+    public void setMappingFiles(List<String> mappingFiles) {
+        this.mappingFiles = mappingFiles;
+    }
+
+    public List<CustomConverter> getCustomConverters() {
+        return customConverters;
+    }
+
+    public void setCustomConverters(List<CustomConverter> customConverters) {
+        this.customConverters = customConverters;
+    }
+
+    public List<DozerEventListener> getEventListeners() {
+        return eventListeners;
+    }
+
+    public void setEventListeners(List<DozerEventListener> eventListeners) {
+        this.eventListeners = eventListeners;
+    }
+
+    public Map<String, CustomConverter> getCustomConvertersWithId() {
+        return customConvertersWithId;
+    }
+
+    public void setCustomConvertersWithId(Map<String, CustomConverter> 
customConvertersWithId) {
+        this.customConvertersWithId = customConvertersWithId;
+    }
+
+    public CustomFieldMapper getCustomFieldMapper() {
+        return customFieldMapper;
+    }
+
+    public void setCustomFieldMapper(CustomFieldMapper customFieldMapper) {
+        this.customFieldMapper = customFieldMapper;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e3867e00/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverterLoader.java
----------------------------------------------------------------------
diff --git 
a/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverterLoader.java
 
b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverterLoader.java
index bb488b0..317dfa8 100644
--- 
a/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverterLoader.java
+++ 
b/components/camel-dozer/src/main/java/org/apache/camel/converter/dozer/DozerTypeConverterLoader.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.converter.dozer;
 
+import java.lang.reflect.Field;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
@@ -29,12 +30,14 @@ import org.apache.camel.CamelContextAware;
 import org.apache.camel.TypeConverter;
 import org.apache.camel.spi.ClassResolver;
 import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.util.ReflectionHelper;
 import org.apache.camel.util.ResourceHelper;
 import org.dozer.DozerBeanMapper;
 import org.dozer.Mapper;
 import org.dozer.classmap.ClassMap;
 import org.dozer.classmap.MappingFileData;
 import org.dozer.config.BeanContainer;
+import org.dozer.config.GlobalSettings;
 import org.dozer.loader.api.BeanMappingBuilder;
 import org.dozer.loader.xml.MappingFileReader;
 import org.dozer.loader.xml.XMLParserFactory;
@@ -59,7 +62,8 @@ public class DozerTypeConverterLoader implements 
CamelContextAware {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
     private CamelContext camelContext;
-    private DozerBeanMapper mapper;
+    private DozerBeanMapperConfiguration configuration;
+    private transient DozerBeanMapper mapper;
 
     /**
      * Creates a <code>DozerTypeConverter</code> performing no
@@ -82,6 +86,35 @@ public class DozerTypeConverterLoader implements 
CamelContextAware {
     }
 
     /**
+     * Creates a <code>DozerTypeConverter</code> using the given
+     * {@link DozerBeanMapperConfiguration} configuration.
+     *
+     * @param camelContext the context to register the
+     *                     {@link DozerTypeConverter} in
+     *
+     * @param configuration dozer mapping bean configuration.
+     */
+    public DozerTypeConverterLoader(CamelContext camelContext, 
DozerBeanMapperConfiguration configuration) {
+        GlobalSettings settings = GlobalSettings.getInstance();
+        try {
+            log.info("Configuring GlobalSettings to use Camel classloader: 
{}", CamelToDozerClassResolverAdapter.class.getName());
+            Field field = 
settings.getClass().getDeclaredField("classLoaderBeanName");
+            ReflectionHelper.setField(field, settings, 
CamelToDozerClassResolverAdapter.class.getName());
+        } catch (Exception e) {
+            throw new IllegalStateException("Cannot configure Dozer 
GlobalSettings to use CamelToDozerClassResolverAdapter as classloader due " + 
e.getMessage(), e);
+        }
+
+        // must set class loader before we create bean mapper
+        CamelToDozerClassResolverAdapter adapter = new 
CamelToDozerClassResolverAdapter(camelContext);
+        BeanContainer.getInstance().setClassLoader(adapter);
+
+        log.info("Using DozerBeanMapperConfiguration: {}", configuration);
+        DozerBeanMapper mapper = createDozerBeanMapper(configuration);
+
+        init(camelContext, mapper);
+    }
+
+    /**
      * Creates a <code>DozerTypeConverter</code> that will wrap the the given
      * {@link DozerBeanMapper} as a {@link DozerTypeConverter} and register it
      * with the given context. It will also search the context for
@@ -90,6 +123,7 @@ public class DozerTypeConverterLoader implements 
CamelContextAware {
      *                     {@link DozerTypeConverter} in
      * @param mapper       the DozerMapperBean to be wrapped as a type 
converter.
      */
+    @Deprecated
     public DozerTypeConverterLoader(CamelContext camelContext, DozerBeanMapper 
mapper) {
         init(camelContext, mapper);
     }
@@ -110,12 +144,30 @@ public class DozerTypeConverterLoader implements 
CamelContextAware {
 
         CamelToDozerClassResolverAdapter adapter = new 
CamelToDozerClassResolverAdapter(camelContext);
         BeanContainer.getInstance().setClassLoader(adapter);
-        
+
         Map<String, DozerBeanMapper> mappers = lookupDozerBeanMappers();
         // only add if we do not already have it
         if (mapper != null && !mappers.containsValue(mapper)) {
             mappers.put("parameter", mapper);
         }
+
+        // add any dozer bean mapper configurations
+        Map<String, DozerBeanMapperConfiguration> configurations = 
lookupDozerBeanMapperConfigurations();
+        if (configurations != null) {
+            if (configurations.size() > 1) {
+                log.warn("Loaded " + configurations.size() + " Dozer 
configurations from Camel registry."
+                        + " Dozer is most efficient when there is a single 
mapper instance. Consider amalgamating instances.");
+            }
+            for (Map.Entry<String, DozerBeanMapperConfiguration> entry : 
configurations.entrySet()) {
+                String id = entry.getKey();
+                DozerBeanMapper beanMapper = 
createDozerBeanMapper(entry.getValue());
+                // only add if we do not already have it
+                if (!mappers.containsValue(beanMapper)) {
+                    mappers.put(id, beanMapper);
+                }
+            }
+        }
+
         if (mappers.size() > 1) {
             log.warn("Loaded " + mappers.size() + " Dozer mappers from Camel 
registry."
                     + " Dozer is most efficient when there is a single mapper 
instance. Consider amalgamating instances.");
@@ -124,6 +176,7 @@ public class DozerTypeConverterLoader implements 
CamelContextAware {
                     + DozerBeanMapper.class.getName());
         }
 
+
         TypeConverterRegistry registry = 
camelContext.getTypeConverterRegistry();
         for (Map.Entry<String, DozerBeanMapper> entry : mappers.entrySet()) {
             String mapperId = entry.getKey();
@@ -134,12 +187,47 @@ public class DozerTypeConverterLoader implements 
CamelContextAware {
     }
 
     /**
+     * Creates a {@link DozerBeanMapper} from the given configuration.
+     *
+     * @param configuration  the dozer bean mapper configuration.
+     * @return the created mapper
+     */
+    protected DozerBeanMapper 
createDozerBeanMapper(DozerBeanMapperConfiguration configuration) {
+        DozerBeanMapper mapper;
+        if (configuration.getMappingFiles() != null) {
+            mapper = new DozerBeanMapper(configuration.getMappingFiles());
+        } else {
+            mapper = new DozerBeanMapper();
+        }
+        if (configuration.getCustomConverters() != null) {
+            mapper.setCustomConverters(configuration.getCustomConverters());
+        }
+        if (configuration.getEventListeners() != null) {
+            mapper.setEventListeners(configuration.getEventListeners());
+        }
+        if (configuration.getCustomConvertersWithId() != null) {
+            
mapper.setCustomConvertersWithId(configuration.getCustomConvertersWithId());
+        }
+        if (configuration.getCustomFieldMapper() != null) {
+            mapper.setCustomFieldMapper(configuration.getCustomFieldMapper());
+        }
+        return mapper;
+    }
+
+    /**
      * Lookup the dozer {@link DozerBeanMapper} to be used.
      */
     protected Map<String, DozerBeanMapper> lookupDozerBeanMappers() {
         return new HashMap<String, 
DozerBeanMapper>(camelContext.getRegistry().findByTypeWithName(DozerBeanMapper.class));
     }
 
+    /**
+     * Lookup the dozer {@link DozerBeanMapperConfiguration} to be used.
+     */
+    protected Map<String, DozerBeanMapperConfiguration> 
lookupDozerBeanMapperConfigurations() {
+        return new HashMap<String, 
DozerBeanMapperConfiguration>(camelContext.getRegistry().findByTypeWithName(DozerBeanMapperConfiguration.class));
+    }
+
     protected void registerClassMaps(TypeConverterRegistry registry, String 
dozerId, DozerBeanMapper dozer, List<ClassMap> all) {
         DozerTypeConverter converter = new DozerTypeConverter(dozer);
         for (ClassMap map : all) {
@@ -244,21 +332,4 @@ public class DozerTypeConverterLoader implements 
CamelContextAware {
         return url;
     }
 
-    private static final class CamelToDozerClassResolverAdapter implements 
DozerClassLoader {
-
-        private final ClassResolver classResolver;
-
-        private CamelToDozerClassResolverAdapter(CamelContext camelContext) {
-            classResolver = camelContext.getClassResolver();
-        }
-
-        public Class<?> loadClass(String name) {
-            return classResolver.resolveClass(name);
-        }
-
-        public URL loadResource(String name) {
-            return loadMappingFile(classResolver, name);
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/e3867e00/components/camel-dozer/src/test/java/org/apache/camel/converter/dozer/SpringDozerTypeConverterConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-dozer/src/test/java/org/apache/camel/converter/dozer/SpringDozerTypeConverterConfigurationTest.java
 
b/components/camel-dozer/src/test/java/org/apache/camel/converter/dozer/SpringDozerTypeConverterConfigurationTest.java
new file mode 100644
index 0000000..2d51ad1
--- /dev/null
+++ 
b/components/camel-dozer/src/test/java/org/apache/camel/converter/dozer/SpringDozerTypeConverterConfigurationTest.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.converter.dozer;
+
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static 
org.apache.camel.converter.dozer.DozerTestArtifactsFactory.createServiceCustomer;
+
+public class SpringDozerTypeConverterConfigurationTest extends 
CamelSpringTestSupport {
+
+    @Override
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new 
ClassPathXmlApplicationContext("SpringDozerTypeConverterConfigurationTest.xml");
+    }
+
+    @Test
+    public void verifyCamelConversionViaDozer() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:verify-model");
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:service-in", createServiceCustomer());
+
+        assertMockEndpointsSatisfied();
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/e3867e00/components/camel-dozer/src/test/resources/SpringDozerTypeConverterConfigurationTest.xml
----------------------------------------------------------------------
diff --git 
a/components/camel-dozer/src/test/resources/SpringDozerTypeConverterConfigurationTest.xml
 
b/components/camel-dozer/src/test/resources/SpringDozerTypeConverterConfigurationTest.xml
new file mode 100644
index 0000000..8a51385
--- /dev/null
+++ 
b/components/camel-dozer/src/test/resources/SpringDozerTypeConverterConfigurationTest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF 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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+            http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+            http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd";>
+
+  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring";>
+    <route>
+      <from uri="direct:service-in"/>
+      <to uri="bean:customer-processor"/>
+      <to uri="mock:verify-model"/>
+    </route>
+  </camelContext>
+
+  <bean id="customer-processor" 
class="org.apache.camel.converter.dozer.CustomerProcessor"/>
+  <bean id="dozerConverterLoader" 
class="org.apache.camel.converter.dozer.DozerTypeConverterLoader"/>
+
+  <!-- use bean mapping configuration -->
+  <bean id="mapper" 
class="org.apache.camel.converter.dozer.DozerBeanMapperConfiguration">
+    <property name="mappingFiles">
+      <list>
+        <value>mapping.xml</value>
+      </list>
+    </property>
+  </bean>
+
+</beans>
\ No newline at end of file

Reply via email to