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.servicemix.eip.patterns;
018:
019: import javax.jbi.messaging.ExchangeStatus;
020: import javax.jbi.messaging.InOnly;
021: import javax.jbi.messaging.InOut;
022: import javax.jbi.messaging.MessageExchange;
023: import javax.jbi.messaging.NormalizedMessage;
024: import javax.jbi.messaging.RobustInOnly;
025: import javax.xml.namespace.QName;
026: import javax.xml.parsers.ParserConfigurationException;
027: import javax.xml.transform.Source;
028: import javax.xml.transform.dom.DOMSource;
029:
030: import org.w3c.dom.Document;
031: import org.w3c.dom.Element;
032: import org.w3c.dom.Node;
033:
034: import org.apache.servicemix.eip.EIPEndpoint;
035: import org.apache.servicemix.eip.support.ExchangeTarget;
036: import org.apache.servicemix.jbi.jaxp.SourceTransformer;
037: import org.apache.servicemix.jbi.util.MessageUtil;
038:
039: /**
040: * Implementation of the
041: * <a href="http://www.enterpriseintegrationpatterns.com/DataEnricher.html">'Content-Enricher'</a>
042: * Pattern.
043: *
044: * @org.apache.xbean.XBean element="content-enricher"
045: * description="A Content Enricher"
046: */
047: public class ContentEnricher extends EIPEndpoint {
048:
049: /**
050: * The address of the target endpoint
051: */
052: private ExchangeTarget target;
053:
054: /**
055: * the target to enrich the request
056: */
057: private ExchangeTarget enricherTarget;
058:
059: /**
060: * the QName of the resulting root node
061: */
062: private QName enricherElementName = new QName("enricher");
063:
064: /**
065: * the QName of the element which contains the 'IN Message'
066: * within the response message
067: */
068: private QName requestElementName = new QName("request");
069:
070: /**
071: * the QName of the element which contains the message
072: * which was produced by the enricherTarget within the
073: * response message
074: */
075: private QName resultElementName = new QName("result");
076:
077: /**
078: * returns the QName of the resulting root node
079: * @return QName of the resulting root node
080: */
081: public QName getEnricherElementName() {
082: return enricherElementName;
083: }
084:
085: /**
086: * Sets the QName of the resulting root node
087: * @param enricherElementName QName of the resulting root node
088: */
089: public void setEnricherElementName(QName enricherElementName) {
090: this .enricherElementName = enricherElementName;
091: }
092:
093: /**
094: * Returns the QName of the element which contains the 'IN Message'
095: * within the response message
096: *
097: * @return QName
098: */
099: public QName getRequestElementName() {
100: return requestElementName;
101: }
102:
103: /**
104: * Sets the QName of the element which contains the 'IN Message'
105: * within the response message
106: *
107: * @param requestElementName QName
108: */
109: public void setRequestElementName(QName requestElementName) {
110: this .requestElementName = requestElementName;
111: }
112:
113: /**
114: * Returns the QName of the element which contains the message
115: * which was produced by the enricherTarget within the
116: * response message
117: *
118: * @return QName
119: */
120: public QName getResultElementName() {
121: return resultElementName;
122: }
123:
124: /**
125: * Sets the QName of the element which contains the message
126: * which was produced by the enricherTarget within the
127: * response message
128: *
129: * @param resultElementName QName
130: */
131: public void setResultElementName(QName resultElementName) {
132: this .resultElementName = resultElementName;
133: }
134:
135: protected void processAsync(MessageExchange exchange)
136: throws Exception {
137: throw new IllegalStateException();
138: }
139:
140: protected void processSync(MessageExchange exchange)
141: throws Exception {
142: throw new IllegalStateException();
143: }
144:
145: public void process(MessageExchange exchange) throws Exception {
146:
147: if (!(exchange instanceof InOnly)
148: && !(exchange instanceof RobustInOnly)) {
149: fail(exchange, new UnsupportedOperationException(
150: "Use an InOnly or RobustInOnly MEP"));
151: }
152:
153: // Skip done exchanges
154: if (exchange.getStatus() == ExchangeStatus.DONE) {
155: return;
156: // Handle error exchanges
157: } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
158: return;
159: }
160:
161: InOut enricherTargetME = getExchangeFactory()
162: .createInOutExchange();
163: enricherTarget.configureTarget(enricherTargetME, getContext());
164: MessageUtil.transferInToIn(exchange, enricherTargetME);
165:
166: sendSync(enricherTargetME);
167:
168: if (enricherTargetME.getStatus() == ExchangeStatus.ERROR) {
169: fail(exchange, enricherTargetME.getError());
170: return;
171: }
172:
173: Document document = combineToDOMDocument(exchange
174: .getMessage("in"), enricherTargetME.getMessage("out"));
175:
176: done(enricherTargetME);
177:
178: MessageExchange outExchange = getExchangeFactory()
179: .createInOnlyExchange();
180: NormalizedMessage out = outExchange.createMessage();
181: target.configureTarget(outExchange, getContext());
182: out.setContent(new DOMSource(document));
183:
184: outExchange.setMessage(out, "in");
185:
186: sendSync(outExchange);
187: done(exchange);
188:
189: }
190:
191: /**
192: * Combines two NormalizedMessages to one DOM Document. The
193: * element Names are specified via the following properties:
194: * enricherElementName, requestElementName, resultElementName
195: *
196: * Example:
197: * Content of Message1 :
198: *
199: * <hello/>
200: *
201: * Content of Message 2:
202: *
203: * <message2/>
204: *
205: * Result of this method a DOM Document containing the following:
206: *
207: * <enricher>
208: * <request>
209: * <hello/>
210: * </request>
211: * <result>
212: * <message2/>
213: * </result>
214: * </enricher>
215: *
216: */
217: private Document combineToDOMDocument(
218: NormalizedMessage requestMessage,
219: NormalizedMessage targetResultMessage) throws Exception,
220: ParserConfigurationException {
221:
222: Node originalDocumentNode = getDOMNode(requestMessage
223: .getContent());
224: Node targetResultNode = getDOMNode(targetResultMessage
225: .getContent());
226:
227: Document document = new SourceTransformer().createDocument();
228: Element enricherElement = createChildElement(
229: enricherElementName, document);
230: Element requestElement = createChildElement(requestElementName,
231: document);
232:
233: Node node = document.importNode(originalDocumentNode, true);
234: requestElement.appendChild(node);
235: enricherElement.appendChild(requestElement);
236: document.appendChild(enricherElement);
237:
238: Element resultElement = createChildElement(resultElementName,
239: document);
240:
241: Node node2 = document.importNode(targetResultNode, true);
242:
243: resultElement.appendChild(node2);
244: enricherElement.appendChild(resultElement);
245: return document;
246:
247: }
248:
249: private Element createChildElement(QName name, Document document) {
250: Element elem;
251: if ("".equals(name.getNamespaceURI())) {
252: elem = document.createElement(name.getLocalPart());
253: } else {
254: elem = document.createElementNS(name.getNamespaceURI(),
255: name.getPrefix() + ":" + name.getLocalPart());
256: }
257: return elem;
258: }
259:
260: private Node getDOMNode(Source source) throws Exception {
261: SourceTransformer sourceTransformer = new SourceTransformer();
262: Node node = sourceTransformer.toDOMNode(source);
263: if (node.getNodeType() == Node.DOCUMENT_NODE) {
264: node = ((Document) node).getDocumentElement();
265: }
266: return node;
267: }
268:
269: public void setTarget(ExchangeTarget target) {
270: this .target = target;
271: }
272:
273: public void setEnricherTarget(ExchangeTarget enricherTarget) {
274: this.enricherTarget = enricherTarget;
275: }
276:
277: }
|