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.component.cxf.converter;
018    
019    import java.io.ByteArrayOutputStream;
020    import java.io.InputStream;
021    import java.util.ArrayList;
022    import java.util.Collection;
023    import java.util.List;
024    
025    import javax.ws.rs.core.Response;
026    import javax.xml.soap.SOAPMessage;
027    
028    import org.apache.camel.Converter;
029    import org.apache.camel.Endpoint;
030    import org.apache.camel.Exchange;
031    import org.apache.camel.FallbackConverter;
032    import org.apache.camel.TypeConverter;
033    import org.apache.camel.component.cxf.CxfSpringEndpoint;
034    import org.apache.camel.component.cxf.DataFormat;
035    import org.apache.camel.component.cxf.spring.CxfEndpointBeanDefinitionParser.CxfSpringEndpointBean;
036    import org.apache.camel.spi.TypeConverterRegistry;
037    import org.apache.camel.spring.SpringCamelContext;
038    import org.apache.commons.logging.Log;
039    import org.apache.commons.logging.LogFactory;
040    import org.apache.cxf.common.classloader.ClassLoaderUtils;
041    import org.apache.cxf.message.MessageContentsList;
042    
043    /**
044     * The <a href="http://camel.apache.org/type-converter.html">Type Converters</a>
045     * for CXF related types' converting .
046     *
047     * @version $Revision: 16372 $
048     */
049    @Converter
050    public final class CxfConverter {
051        private static final Log LOG = LogFactory.getLog(CxfConverter.class);
052    
053        private CxfConverter() {
054            // Helper class
055        }
056    
057        @Converter
058        public static MessageContentsList toMessageContentsList(final Object[] array) {
059            if (array != null) {
060                return new MessageContentsList(array);
061            } else {
062                return new MessageContentsList();
063            }
064        }
065        
066        @Converter
067        public static List<Class> toClassesList(final String[] classNames) throws ClassNotFoundException {
068            List<Class> answer = new ArrayList<Class>();
069            for (String className : classNames) {
070                answer.add(ClassLoaderUtils.loadClass(className.trim(), CxfConverter.class));
071            }
072            return answer;
073        }
074        
075        @Converter
076        public static List<Class> toClassList(String classeString) throws ClassNotFoundException {
077            String[] classNames = classeString.split(",|;");
078            return toClassesList(classNames);        
079        }
080        
081        @Converter
082        public static Object[] toArray(Object object) {
083            if (object instanceof Collection) {
084                return ((Collection)object).toArray();
085            } else {
086                Object answer[];
087                if (object == null) {
088                    answer = new Object[0];
089                } else {
090                    answer = new Object[1];
091                    answer[0] = object;
092                }
093                return answer;
094            }       
095        }
096    
097        @Converter
098        public static String soapMessageToString(final SOAPMessage soapMessage) {
099            ByteArrayOutputStream baos = new ByteArrayOutputStream();
100            try {
101                soapMessage.writeTo(baos);
102            } catch (Exception e) {
103                LOG.error("Get the exception when converting the SOAPMessage into String, the exception is " + e);
104            }
105            return baos.toString();
106        }
107        
108        @Converter
109        public static Endpoint toEndpoint(final CxfSpringEndpointBean endpointBean) throws Exception {
110            if (endpointBean == null) {
111                throw new IllegalArgumentException("The CxfEndpoint instance is null");
112            }
113            // CamelContext 
114            SpringCamelContext context = SpringCamelContext.springCamelContext(endpointBean.getApplicationContext());
115            // The beanId will be set from endpointBean's property        
116            Endpoint answer = new CxfSpringEndpoint(context, endpointBean);        
117            return answer;
118        }
119    
120        @Converter
121        public static DataFormat toDataFormat(final String name) {
122            return DataFormat.valueOf(name.toUpperCase());
123        }
124        
125        @Converter
126        public static InputStream toInputStream(Response response, Exchange exchange) {
127            
128            Object obj = response.getEntity();
129            
130            if (obj == null) {
131                return null;
132            }
133            
134            if (obj instanceof InputStream) {
135                // short circuit the lookup
136                return (InputStream)obj;
137            }
138            
139            TypeConverterRegistry registry = exchange.getContext().getTypeConverterRegistry();
140            TypeConverter tc = registry.lookup(InputStream.class, obj.getClass());
141            
142            if (tc != null) {
143                return tc.convertTo(InputStream.class, exchange, obj);
144            }
145            
146            return null;
147        }
148    
149        /**
150         * Use a fallback type converter so we can convert the embedded list element 
151         * if the value is MessageContentsList.  The algorithm of this converter
152         * finds the first non-null list element from the list and applies convertion
153         * to the list element.
154         * 
155         * @param type the desired type to be converted to
156         * @param exchange optional exchange which can be null
157         * @param value the object to be converted
158         * @param registry type converter registry
159         * @return the converted value of the desired type or null if no suitable converter found
160         */
161        @SuppressWarnings("unchecked")
162        @FallbackConverter
163        public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, 
164                TypeConverterRegistry registry) {
165            
166            if (MessageContentsList.class.isAssignableFrom(value.getClass())) {
167                MessageContentsList list = (MessageContentsList)value;
168    
169                for (Object embedded : list) {
170                    if (embedded != null) {
171                        if (type.isInstance(embedded)) {
172                            return type.cast(embedded);
173                        } else {
174                            TypeConverter tc = registry.lookup(type, embedded.getClass());
175                            if (tc != null) {
176                                return tc.convertTo(type, exchange, embedded);
177                            }
178                        }
179                    }
180                }
181                // return void to indicate its not possible to convert at this time
182                return (T) Void.TYPE;
183            }
184            
185            return null;
186        }
187    }