001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.impl.converter;
018    
019    import java.util.concurrent.Future;
020    
021    import org.apache.camel.Converter;
022    import org.apache.camel.Exchange;
023    import org.apache.camel.NoTypeConversionAvailableException;
024    import org.apache.camel.StreamCache;
025    import org.apache.camel.TypeConverter;
026    import org.apache.camel.util.ExchangeHelper;
027    import org.apache.camel.util.ObjectHelper;
028    import org.apache.commons.logging.Log;
029    import org.apache.commons.logging.LogFactory;
030    
031    /**
032     * Future type converter.
033     *
034     * @version $Revision: 833413 $
035     */
036    @Converter
037    public final class FutureTypeConverter implements TypeConverter {
038    
039        private static final Log LOG = LogFactory.getLog(FutureTypeConverter.class);
040    
041        private final TypeConverter converter;
042    
043        public FutureTypeConverter(TypeConverter converter) {
044            this.converter = converter;
045        }
046    
047        @SuppressWarnings("unchecked")
048        private <T> T doConvertTo(Class<T> type, Exchange exchange, Object value) throws Exception {
049            // do not convert to stream cache
050            if (StreamCache.class.isAssignableFrom(value.getClass())) {
051                return null;
052            }
053    
054            if (Future.class.isAssignableFrom(value.getClass())) {
055    
056                Future future = (Future) value;
057    
058                if (future.isCancelled()) {
059                    // return void to indicate its not possible to convert at this time
060                    return (T) Void.TYPE;
061                }
062    
063                // do some trace logging as the get is blocking until the response is ready
064                if (LOG.isTraceEnabled()) {
065                    LOG.trace("Getting future response");
066                }
067    
068                Object body = future.get();
069                if (LOG.isTraceEnabled()) {
070                    LOG.trace("Got future response");
071                }
072    
073                if (body == null) {
074                    // return void to indicate its not possible to convert at this time
075                    return (T) Void.TYPE;
076                }
077    
078                // maybe from is already the type we want
079                if (type.isAssignableFrom(body.getClass())) {
080                    return type.cast(body);
081                } else if (body instanceof Exchange) {
082                    Exchange result = (Exchange) body;
083                    body = ExchangeHelper.extractResultBody(result, result.getPattern());
084                }
085    
086                // no then try to lookup a type converter
087                return converter.convertTo(type, exchange, body);
088            }
089    
090            return null;
091        }
092    
093        public <T> T convertTo(Class<T> type, Object value) {
094            return convertTo(type, null, value);
095        }
096    
097        public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
098            try {
099                return doConvertTo(type, exchange, value);
100            } catch (Exception e) {
101                throw ObjectHelper.wrapRuntimeCamelException(e);
102            }
103        }
104    
105        public <T> T mandatoryConvertTo(Class<T> type, Object value) throws NoTypeConversionAvailableException {
106            return mandatoryConvertTo(type, null, value);
107        }
108    
109        public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException {
110            T answer;
111            try {
112                answer = doConvertTo(type, exchange, value);
113            } catch (Exception e) {
114                throw new NoTypeConversionAvailableException(value, type, e);
115            }
116    
117            if (answer == null) {
118                throw new NoTypeConversionAvailableException(value, type);
119            }
120    
121            return answer;
122        }
123    }