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 */ 017package org.apache.camel.processor; 018 019import java.io.InputStream; 020import java.util.Iterator; 021 022import org.apache.camel.AsyncCallback; 023import org.apache.camel.AsyncProcessor; 024import org.apache.camel.CamelContext; 025import org.apache.camel.CamelContextAware; 026import org.apache.camel.Exchange; 027import org.apache.camel.Message; 028import org.apache.camel.RuntimeCamelException; 029import org.apache.camel.Traceable; 030import org.apache.camel.spi.DataFormat; 031import org.apache.camel.spi.IdAware; 032import org.apache.camel.support.ServiceSupport; 033import org.apache.camel.util.AsyncProcessorHelper; 034import org.apache.camel.util.IOHelper; 035import org.apache.camel.util.ObjectHelper; 036import org.apache.camel.util.ServiceHelper; 037 038/** 039 * Unmarshals the body of the incoming message using the given 040 * <a href="http://camel.apache.org/data-format.html">data format</a> 041 * 042 * @version 043 */ 044public class UnmarshalProcessor extends ServiceSupport implements AsyncProcessor, Traceable, CamelContextAware, IdAware { 045 private String id; 046 private CamelContext camelContext; 047 private final DataFormat dataFormat; 048 049 public UnmarshalProcessor(DataFormat dataFormat) { 050 this.dataFormat = dataFormat; 051 } 052 053 public void process(Exchange exchange) throws Exception { 054 AsyncProcessorHelper.process(this, exchange); 055 } 056 057 public boolean process(Exchange exchange, AsyncCallback callback) { 058 ObjectHelper.notNull(dataFormat, "dataFormat"); 059 060 InputStream stream = null; 061 Object result = null; 062 try { 063 stream = exchange.getIn().getMandatoryBody(InputStream.class); 064 065 // lets setup the out message before we invoke the dataFormat so that it can mutate it if necessary 066 Message out = exchange.getOut(); 067 out.copyFrom(exchange.getIn()); 068 069 result = dataFormat.unmarshal(exchange, stream); 070 if (result instanceof Exchange) { 071 if (result != exchange) { 072 // it's not allowed to return another exchange other than the one provided to dataFormat 073 throw new RuntimeCamelException("The returned exchange " + result + " is not the same as " + exchange + " provided to the DataFormat"); 074 } 075 } else if (result instanceof Message) { 076 // the dataformat has probably set headers, attachments, etc. so let's use it as the outbound payload 077 exchange.setOut((Message) result); 078 } else { 079 out.setBody(result); 080 } 081 } catch (Throwable e) { 082 // remove OUT message, as an exception occurred 083 exchange.setOut(null); 084 exchange.setException(e); 085 } finally { 086 // The Iterator will close the stream itself 087 if (!(result instanceof Iterator)) { 088 IOHelper.close(stream, "input stream"); 089 } 090 } 091 callback.done(true); 092 return true; 093 } 094 095 public String toString() { 096 return "Unmarshal[" + dataFormat + "]"; 097 } 098 099 public String getTraceLabel() { 100 return "unmarshal[" + dataFormat + "]"; 101 } 102 103 public String getId() { 104 return id; 105 } 106 107 public void setId(String id) { 108 this.id = id; 109 } 110 111 public CamelContext getCamelContext() { 112 return camelContext; 113 } 114 115 public void setCamelContext(CamelContext camelContext) { 116 this.camelContext = camelContext; 117 } 118 119 @Override 120 protected void doStart() throws Exception { 121 // inject CamelContext on data format 122 if (dataFormat instanceof CamelContextAware) { 123 ((CamelContextAware) dataFormat).setCamelContext(camelContext); 124 } 125 // add dataFormat as service which will also start the service 126 // (false => we handle the lifecycle of the dataFormat) 127 getCamelContext().addService(dataFormat, false, true); 128 } 129 130 @Override 131 protected void doStop() throws Exception { 132 ServiceHelper.stopService(dataFormat); 133 getCamelContext().removeService(dataFormat); 134 } 135 136}