Author: davsclaus Date: Sat May 1 08:41:00 2010 New Revision: 939945 URL: http://svn.apache.org/viewvc?rev=939945&view=rev Log: CAMEL-2690: FallbackTypeConverter less aggresive to be promoted. Now you explict have to define it on the @FallbackConverter if allowed to be promoted.
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/FallbackPromoteTest.java (with props) camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyCoolBean.java (with props) camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyFallbackPromoteConverter.java (with props) Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/FallbackConverter.java camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java camel/trunk/camel-core/src/test/java/org/apache/camel/converter/InstanceFallbackConverterTest.java camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java camel/trunk/components/camel-osgi/src/test/java/org/apache/camel/osgi/test/MockTypeConverterRegistry.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/FallbackConverter.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/FallbackConverter.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/FallbackConverter.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/FallbackConverter.java Sat May 1 08:41:00 2010 @@ -30,7 +30,7 @@ import java.lang.annotation.Target; * <p/> * The difference between a regular <tt>@Converter</tt> and a <tt>@FallbackConverter</tt> * is that the fallback is resolved at last if no regular converter could be found. - * Also the method signautre is scoped to be generic to allow handling a broader range + * Also the method signature is scoped to be generic to allow handling a broader range * of types trying to be converted. The fallback converter can just return <tt>null</tt> * if it can not handle the types to convert from/to. * @@ -42,4 +42,9 @@ import java.lang.annotation.Target; @Documented @Target({ElementType.TYPE, ElementType.METHOD }) public @interface FallbackConverter { + + /** + * Whether or not this fallback converter can be promoted to a first class type converter. + */ + boolean canPromote() default false; } \ No newline at end of file Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/AnnotationTypeConverterLoader.java Sat May 1 08:41:00 2010 @@ -213,12 +213,12 @@ public class AnnotationTypeConverterLoad + method + " as a fallback converter method returns a void method"); } else { if (isStatic(modifiers)) { - registerFallbackTypeConverter(registry, new StaticMethodFallbackTypeConverter(method, registry)); + registerFallbackTypeConverter(registry, new StaticMethodFallbackTypeConverter(method, registry), method); } else { if (injector == null) { injector = new CachingInjector<Object>(registry, CastUtils.cast(type, Object.class)); } - registerFallbackTypeConverter(registry, new InstanceMethodFallbackTypeConverter(injector, method, registry)); + registerFallbackTypeConverter(registry, new InstanceMethodFallbackTypeConverter(injector, method, registry), method); } } } @@ -240,8 +240,13 @@ public class AnnotationTypeConverterLoad || (parameterTypes.length == 2 && Exchange.class.isAssignableFrom(parameterTypes[1]))); } - protected void registerFallbackTypeConverter(TypeConverterRegistry registry, TypeConverter typeConverter) { - registry.addFallbackTypeConverter(typeConverter); + protected void registerFallbackTypeConverter(TypeConverterRegistry registry, TypeConverter typeConverter, Method method) { + boolean canPromote = false; + // check whether the annotation may indicate it can promote + if (method.getAnnotation(FallbackConverter.class) != null) { + canPromote = method.getAnnotation(FallbackConverter.class).canPromote(); + } + registry.addFallbackTypeConverter(typeConverter, canPromote); } protected boolean isValidFallbackConverterMethod(Method method) { Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/DefaultTypeConverter.java Sat May 1 08:41:00 2010 @@ -53,7 +53,7 @@ public class DefaultTypeConverter extend private final Map<TypeMapping, TypeConverter> typeMappings = new ConcurrentHashMap<TypeMapping, TypeConverter>(); private final Map<TypeMapping, TypeMapping> misses = new ConcurrentHashMap<TypeMapping, TypeMapping>(); private final List<TypeConverterLoader> typeConverterLoaders = new ArrayList<TypeConverterLoader>(); - private final List<TypeConverter> fallbackConverters = new ArrayList<TypeConverter>(); + private final List<FallbackTypeConverter> fallbackConverters = new ArrayList<FallbackTypeConverter>(); private Injector injector; private final FactoryFinder factoryFinder; @@ -64,11 +64,11 @@ public class DefaultTypeConverter extend // add to string first as it will then be last in the last as to string can nearly // always convert something to a string so we want it only as the last resort - addFallbackTypeConverter(new ToStringTypeConverter()); - addFallbackTypeConverter(new EnumTypeConverter()); - addFallbackTypeConverter(new ArrayTypeConverter()); - addFallbackTypeConverter(new PropertyEditorTypeConverter()); - addFallbackTypeConverter(new FutureTypeConverter(this)); + addFallbackTypeConverter(new ToStringTypeConverter(), false); + addFallbackTypeConverter(new EnumTypeConverter(), true); + addFallbackTypeConverter(new ArrayTypeConverter(), true); + addFallbackTypeConverter(new PropertyEditorTypeConverter(), true); + addFallbackTypeConverter(new FutureTypeConverter(this), false); } public List<TypeConverterLoader> getTypeConverterLoaders() { @@ -131,7 +131,7 @@ public class DefaultTypeConverter extend public Object doConvertTo(final Class type, final Exchange exchange, final Object value) { if (LOG.isTraceEnabled()) { LOG.trace("Converting " + (value == null ? "null" : value.getClass().getCanonicalName()) - + " -> " + type.getCanonicalName() + " with value: " + value); + + " -> " + type.getCanonicalName() + " with value: " + value); } if (value == null) { @@ -164,8 +164,8 @@ public class DefaultTypeConverter extend } // fallback converters - for (TypeConverter fallback : fallbackConverters) { - Object rc = fallback.convertTo(type, exchange, value); + for (FallbackTypeConverter fallback : fallbackConverters) { + Object rc = fallback.getFallbackTypeConverter().convertTo(type, exchange, value); if (Void.TYPE.equals(rc)) { // it cannot be converted so give up @@ -173,16 +173,29 @@ public class DefaultTypeConverter extend } if (rc != null) { - // add it as a known type converter since we found a fallback that could do it - if (LOG.isDebugEnabled()) { - LOG.debug("Adding fallback type converter as a known type converter to convert from: " - + type.getCanonicalName() + " to: " + value.getClass().getCanonicalName()); + // if fallback can promote then let it be promoted to a first class type converter + if (fallback.isCanPromote()) { + // add it as a known type converter since we found a fallback that could do it + if (LOG.isDebugEnabled()) { + LOG.debug("Promoting fallback type converter as a known type converter to convert from: " + + type.getCanonicalName() + " to: " + value.getClass().getCanonicalName() + + " for the fallback converter: " + fallback.getFallbackTypeConverter()); + } + addTypeConverter(type, value.getClass(), fallback.getFallbackTypeConverter()); + } + + if (LOG.isTraceEnabled()) { + LOG.trace("Fallback type converter " + fallback.getFallbackTypeConverter() + " converted type from: " + + type.getCanonicalName() + " to: " + value.getClass().getCanonicalName()); } - addTypeConverter(type, value.getClass(), fallback); + + // return converted value return rc; } } + // TODO: check before if its type/value is primitive/wrapper combo which we can convert asap then + // primitives if (type.isPrimitive()) { Class primitiveType = ObjectHelper.convertPrimitiveTypeToWrapperType(type); @@ -218,15 +231,15 @@ public class DefaultTypeConverter extend } } - public void addFallbackTypeConverter(TypeConverter typeConverter) { + public void addFallbackTypeConverter(TypeConverter typeConverter, boolean canPromote) { if (LOG.isTraceEnabled()) { - LOG.trace("Adding fallback type converter: " + typeConverter); + LOG.trace("Adding fallback type converter: " + typeConverter + " which can promote: " + canPromote); } // add in top of fallback as the toString() fallback will nearly always be able to convert - fallbackConverters.add(0, typeConverter); + fallbackConverters.add(0, new FallbackTypeConverter(typeConverter, canPromote)); if (typeConverter instanceof TypeConverterAware) { - TypeConverterAware typeConverterAware = (TypeConverterAware)typeConverter; + TypeConverterAware typeConverterAware = (TypeConverterAware) typeConverter; typeConverterAware.setTypeConverter(this); } } @@ -377,7 +390,7 @@ public class DefaultTypeConverter extend protected void loadFallbackTypeConverters() throws IOException, ClassNotFoundException { List<TypeConverter> converters = factoryFinder.newInstances("FallbackTypeConverter", getInjector(), TypeConverter.class); for (TypeConverter converter : converters) { - addFallbackTypeConverter(converter); + addFallbackTypeConverter(converter, false); } } @@ -415,9 +428,9 @@ public class DefaultTypeConverter extend @Override public boolean equals(Object object) { if (object instanceof TypeMapping) { - TypeMapping that = (TypeMapping)object; + TypeMapping that = (TypeMapping) object; return ObjectHelper.equal(this.fromType, that.fromType) - && ObjectHelper.equal(this.toType, that.toType); + && ObjectHelper.equal(this.toType, that.toType); } return false; } @@ -440,4 +453,26 @@ public class DefaultTypeConverter extend return fromType.isAssignableFrom(fromClass); } } + + /** + * Represents a fallback type converter + */ + protected static class FallbackTypeConverter { + private boolean canPromote; + private TypeConverter fallbackTypeConverter; + + FallbackTypeConverter(TypeConverter fallbackTypeConverter, boolean canPromote) { + this.canPromote = canPromote; + this.fallbackTypeConverter = fallbackTypeConverter; + } + + public boolean isCanPromote() { + return canPromote; + } + + public TypeConverter getFallbackTypeConverter() { + return fallbackTypeConverter; + } + } + } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/MulticastProcessor.java Sat May 1 08:41:00 2010 @@ -181,7 +181,7 @@ public class MulticastProcessor extends completion = new SubmitOrderedCompletionService<Exchange>(executorService); } - final AtomicInteger total = new AtomicInteger(0); + final AtomicInteger total = new AtomicInteger(0); for (ProcessorExchangePair pair : pairs) { final Processor processor = pair.getProcessor(); Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java Sat May 1 08:41:00 2010 @@ -38,8 +38,9 @@ public interface TypeConverterRegistry { * Registers a new fallback type converter * * @param typeConverter the type converter to use + * @param canPromote whether or not the fallback type converter can be promoted to a first class type converter */ - void addFallbackTypeConverter(TypeConverter typeConverter); + void addFallbackTypeConverter(TypeConverter typeConverter, boolean canPromote); /** * Performs a lookup for a given type converter. @@ -52,11 +53,15 @@ public interface TypeConverterRegistry { /** * Sets the injector to be used for creating new instances during type convertions. + * + * @param injector the injector */ void setInjector(Injector injector); /** * Gets the injector + * + * @return the injector */ Injector getInjector(); } Added: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/FallbackPromoteTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/converter/FallbackPromoteTest.java?rev=939945&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/converter/FallbackPromoteTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/converter/FallbackPromoteTest.java Sat May 1 08:41:00 2010 @@ -0,0 +1,45 @@ +/** + * 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; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.TypeConverter; + +/** + * @version $Revision$ + */ +public class FallbackPromoteTest extends ContextTestSupport { + + public void testFallbackPromote() throws Exception { + MyCoolBean cool = new MyCoolBean(); + cool.setCool("Camel rocks"); + + TypeConverter tc = context.getTypeConverterRegistry().lookup(String.class, MyCoolBean.class); + assertNull("No regular type converters", tc); + + String s = context.getTypeConverter().convertTo(String.class, cool); + assertEquals("This is cool: Camel rocks", s); + + cool.setCool("It works"); + s = context.getTypeConverter().convertTo(String.class, cool); + assertEquals("This is cool: It works", s); + + tc = context.getTypeConverterRegistry().lookup(String.class, MyCoolBean.class); + assertNotNull("Should have been promoted", tc); + } + +} Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/FallbackPromoteTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/FallbackPromoteTest.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/InstanceFallbackConverterTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/converter/InstanceFallbackConverterTest.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/converter/InstanceFallbackConverterTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/converter/InstanceFallbackConverterTest.java Sat May 1 08:41:00 2010 @@ -31,7 +31,7 @@ import org.apache.camel.impl.DefaultExch */ public class InstanceFallbackConverterTest extends ContextTestSupport { - public void testIntanceFallbackConverter() throws Exception { + public void testInstanceFallbackConverter() throws Exception { Exchange exchange = new DefaultExchange(context); Currency cur = Currency.getInstance(Locale.US); @@ -39,7 +39,7 @@ public class InstanceFallbackConverterTe assertEquals("Money talks", money); } - public void testIntanceFallbackMandatoryConverter() throws Exception { + public void testInstanceFallbackMandatoryConverter() throws Exception { Exchange exchange = new DefaultExchange(context); Currency cur = Currency.getInstance(Locale.US); @@ -47,7 +47,7 @@ public class InstanceFallbackConverterTe assertEquals("Money talks", money); } - public void testIntanceFallbackMandatoryFailed() throws Exception { + public void testInstanceFallbackMandatoryFailed() throws Exception { Exchange exchange = new DefaultExchange(context); try { @@ -58,7 +58,7 @@ public class InstanceFallbackConverterTe } } - public void testIntanceFallbackFailed() throws Exception { + public void testInstanceFallbackFailed() throws Exception { Exchange exchange = new DefaultExchange(context); Date out = context.getTypeConverter().convertTo(Date.class, exchange, new Timestamp(0)); Added: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyCoolBean.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyCoolBean.java?rev=939945&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyCoolBean.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyCoolBean.java Sat May 1 08:41:00 2010 @@ -0,0 +1,38 @@ +/** + * 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; + +/** + * @version $Revision$ + */ +public class MyCoolBean { + + private String cool; + + public String getCool() { + return cool; + } + + public void setCool(String cool) { + this.cool = cool; + } + + @Override + public String toString() { + return cool; + } +} Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyCoolBean.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyCoolBean.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Added: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyFallbackPromoteConverter.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyFallbackPromoteConverter.java?rev=939945&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyFallbackPromoteConverter.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyFallbackPromoteConverter.java Sat May 1 08:41:00 2010 @@ -0,0 +1,37 @@ +/** + * 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; + +import org.apache.camel.Converter; +import org.apache.camel.Exchange; +import org.apache.camel.FallbackConverter; +import org.apache.camel.spi.TypeConverterRegistry; + +/** + * @version $Revision$ + */ +...@converter +public class MyFallbackPromoteConverter { + + @FallbackConverter(canPromote = true) + public Object convertTo(Class<?> type, Exchange exchange, Object value, TypeConverterRegistry registry) { + if (MyCoolBean.class.isAssignableFrom(value.getClass())) { + return "This is cool: " + value.toString(); + } + return null; + } +} Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyFallbackPromoteConverter.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/converter/MyFallbackPromoteConverter.java ------------------------------------------------------------------------------ svn:keywords = Rev Date Modified: camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java (original) +++ camel/trunk/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecResultConverter.java Sat May 1 08:41:00 2010 @@ -76,18 +76,13 @@ public final class ExecResultConverter { * @param type Class instance of the type to which to convert * @param exchange a Camel exchange. If exchange is <code>null</code>, no * conversion will be made - * @param result + * @param result the exec result * @return the converted {...@link ExecResult} - * @throws FileNotFoundException if theres is a file in the execResult, and + * @throws FileNotFoundException if there is a file in the execResult, and * the file can not be found */ public static <T> T convertTo(Class<T> type, Exchange exchange, ExecResult result) throws FileNotFoundException { - if (exchange != null) { - return (T)exchange.getContext().getTypeConverter().convertTo(type, exchange, toInputStream(result)); - } else { - // should revert to fallback converter if we don't have an exchange - return null; - } + return exchange.getContext().getTypeConverter().convertTo(type, exchange, toInputStream(result)); } /** Modified: camel/trunk/components/camel-osgi/src/test/java/org/apache/camel/osgi/test/MockTypeConverterRegistry.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-osgi/src/test/java/org/apache/camel/osgi/test/MockTypeConverterRegistry.java?rev=939945&r1=939944&r2=939945&view=diff ============================================================================== --- camel/trunk/components/camel-osgi/src/test/java/org/apache/camel/osgi/test/MockTypeConverterRegistry.java (original) +++ camel/trunk/components/camel-osgi/src/test/java/org/apache/camel/osgi/test/MockTypeConverterRegistry.java Sat May 1 08:41:00 2010 @@ -39,7 +39,7 @@ public class MockTypeConverterRegistry i typeConverters.add(typeConverter); } - public void addFallbackTypeConverter(TypeConverter typeConverter) { + public void addFallbackTypeConverter(TypeConverter typeConverter, boolean canPromote) { fallbackTypeConverters.add(typeConverter); }