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.components.util;
018
019 import javax.jbi.JBIException;
020 import javax.jbi.messaging.DeliveryChannel;
021 import javax.jbi.messaging.ExchangeStatus;
022 import javax.jbi.messaging.Fault;
023 import javax.jbi.messaging.InOnly;
024 import javax.jbi.messaging.InOut;
025 import javax.jbi.messaging.MessageExchange;
026 import javax.jbi.messaging.MessageExchangeFactory;
027 import javax.jbi.messaging.MessagingException;
028 import javax.jbi.servicedesc.ServiceEndpoint;
029 import javax.xml.namespace.QName;
030
031 import org.apache.servicemix.MessageExchangeListener;
032 import org.apache.servicemix.jbi.MissingPropertyException;
033 import org.apache.servicemix.jbi.NoServiceAvailableException;
034
035 /**
036 * This component acts as an InOnly component which pipelines a request/response (InOut) to a service
037 * then forwards the response onto an InOut component.
038 *
039 * @version $Revision: 564374 $
040 */
041 public class PipelineComponent extends ComponentSupport implements MessageExchangeListener {
042 private ServiceEndpoint requestResponseEndpoint;
043 private ServiceEndpoint outputEndpoint;
044 private QName requestResponseServiceName;
045 private QName outputEndpointServiceName;
046
047 public PipelineComponent() {
048 }
049
050 public PipelineComponent(QName service, String endpoint) {
051 super(service, endpoint);
052 }
053
054 public void start() throws JBIException {
055 super.start();
056
057 if (requestResponseEndpoint == null) {
058 if (requestResponseServiceName == null) {
059 throw new MissingPropertyException("requestResponseServiceName");
060 }
061 requestResponseEndpoint = chooseEndpoint(requestResponseServiceName);
062
063 }
064 if (outputEndpoint == null) {
065 if (outputEndpointServiceName == null) {
066 throw new MissingPropertyException("outputEndpointServiceName");
067 }
068 outputEndpoint = chooseEndpoint(outputEndpointServiceName);
069 }
070 }
071
072 public void onMessageExchange(MessageExchange exchange) throws MessagingException {
073 // Skip done exchanges
074 if (exchange.getStatus() == ExchangeStatus.DONE) {
075 return;
076 // Handle error exchanges
077 } else if (exchange.getStatus() == ExchangeStatus.ERROR) {
078 return;
079 }
080
081 // lets create an endpoint
082 DeliveryChannel deliveryChannel = getDeliveryChannel();
083 MessageExchangeFactory rpcFactory = deliveryChannel.createExchangeFactory(requestResponseEndpoint);
084 InOut rpc = rpcFactory.createInOutExchange();
085 rpc.setInMessage(exchange.getMessage("in"));
086 boolean answer = deliveryChannel.sendSync(rpc);
087
088 MessageExchangeFactory outputFactory = deliveryChannel.createExchangeFactory(outputEndpoint);
089 InOnly inOnly = outputFactory.createInOnlyExchange();
090
091 if (answer) {
092 inOnly.setInMessage(rpc.getOutMessage());
093 deliveryChannel.send(inOnly);
094 done(exchange);
095 } else if (!(exchange instanceof InOnly)) {
096 inOnly.setError(rpc.getError());
097 Fault fault = rpc.getFault();
098 fail(exchange, fault);
099 } else {
100 // terminate the exchange
101 done(exchange);
102 }
103 done(rpc);
104 }
105
106 // Properties
107 //-------------------------------------------------------------------------
108 public ServiceEndpoint getRequestResponseEndpoint() {
109 return requestResponseEndpoint;
110 }
111
112 public void setRequestResponseEndpoint(ServiceEndpoint requestResponseEndpoint) {
113 this.requestResponseEndpoint = requestResponseEndpoint;
114 }
115
116 public ServiceEndpoint getOutputEndpoint() {
117 return outputEndpoint;
118 }
119
120 public void setOutputEndpoint(ServiceEndpoint outputEndpoint) {
121 this.outputEndpoint = outputEndpoint;
122 }
123
124 public QName getRequestResponseServiceName() {
125 return requestResponseServiceName;
126 }
127
128 public void setRequestResponseServiceName(QName requestResponseServiceName) {
129 this.requestResponseServiceName = requestResponseServiceName;
130 }
131
132 public QName getOutputEndpointServiceName() {
133 return outputEndpointServiceName;
134 }
135
136 public void setOutputEndpointServiceName(QName outputEndpointServiceName) {
137 this.outputEndpointServiceName = outputEndpointServiceName;
138 }
139
140 // Implementation methods
141 //-------------------------------------------------------------------------
142
143 /**
144 * Resolves the given service endpoint reference from a serviceName
145 *
146 * @param serviceName is the name of the service
147 * @return the service endpoint
148 * @throws JBIException if the service cannot be resolved
149 */
150 protected ServiceEndpoint chooseEndpoint(QName serviceName) throws JBIException {
151 ServiceEndpoint[] endpoints = getContext().getEndpointsForService(serviceName);
152 if (endpoints == null || endpoints.length == 0) {
153 throw new NoServiceAvailableException(serviceName);
154 }
155 // TODO how should we choose?
156 return endpoints[0];
157 }
158
159 }