blob: 805a5b0ece362c6f8b1b7e4c86cde2ee6f727527 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.servicemix.cxf.transport.nmr;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import org.apache.cxf.attachment.AttachmentImpl;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.message.Attachment;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.AbstractConduit;
import org.apache.cxf.transport.AbstractDestination;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.transport.MessageObserver;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.cxf.wsdl.EndpointReferenceUtils;
import org.apache.servicemix.nmr.api.Channel;
import org.apache.servicemix.nmr.api.Endpoint;
import org.apache.servicemix.nmr.api.Exchange;
import org.apache.servicemix.nmr.api.NMR;
import org.apache.servicemix.nmr.api.Pattern;
import org.apache.servicemix.nmr.api.ServiceMixException;
import org.apache.servicemix.nmr.api.Status;
public class NMRDestination extends AbstractDestination implements Endpoint {
private static final Logger LOG = LogUtils.getL7dLogger(NMRDestination.class);
private NMR nmr;
private Channel channel;
private Map<String, Object> properties;
public NMRDestination(EndpointInfo info, NMR nmr) {
super(getTargetReference(info, null), info);
this.nmr = nmr;
this.properties = new HashMap<String, Object>();
String address = info.getAddress();
if (address != null && address.indexOf(Endpoint.RUN_AS_SUBJECT) >= 0) {
String asSubject = address.substring(address.indexOf(Endpoint.RUN_AS_SUBJECT)
+ Endpoint.RUN_AS_SUBJECT.length() + 1);
this.properties.put(Endpoint.RUN_AS_SUBJECT, asSubject);
}
if (address != null && address.startsWith("nmr:")) {
if (address.indexOf("?") > 0) {
this.properties.put(Endpoint.NAME, address.substring(4, address.indexOf("?")));
} else {
this.properties.put(Endpoint.NAME, address.substring(4));
}
} else {
this.properties.put(Endpoint.NAME, info.getName().toString());
}
this.properties.put(Endpoint.SERVICE_NAME, info.getService().getName().toString());
this.properties.put(Endpoint.INTERFACE_NAME, info.getInterface().getName().toString());
if (address.indexOf("?") > 0) {
String[] props = address.substring(address.indexOf("?") + 1).split("&");
for (String prop : props) {
if (prop.indexOf("=") > 0) {
String key = prop.substring(0, prop.indexOf("="));
String val = prop.substring(prop.indexOf("=") + 1);
if (key.equals("synchronous")) {
key = Endpoint.CHANNEL_SYNC_DELIVERY;
}
this.properties.put(key, val);
}
}
}
}
public void setChannel(Channel dc) {
this.channel = dc;
}
public Channel getChannel() {
return this.channel;
}
protected Logger getLogger() {
return LOG;
}
/**
* @param inMessage the incoming message
* @return the inbuilt backchannel
*/
protected Conduit getInbuiltBackChannel(Message inMessage) {
return new BackChannelConduit(EndpointReferenceUtils.getAnonymousEndpointReference(), inMessage);
}
public void shutdown() {
}
public void deactivate() {
nmr.getEndpointRegistry().unregister(this, properties);
}
public void activate() {
nmr.getEndpointRegistry().register(this, properties);
}
public void process(Exchange exchange) {
if (exchange == null || exchange.getStatus() != Status.Active) {
return;
}
if (exchange.getPattern() == Pattern.InOnly || exchange.getPattern() == Pattern.RobustInOnly) {
exchange.setStatus(Status.Done);
getChannel().send(exchange);
}
QName opName = exchange.getOperation();
getLogger().fine("dispatch method: " + opName);
org.apache.servicemix.nmr.api.Message nm = exchange.getIn();
try {
MessageImpl inMessage = new MessageImpl();
inMessage.put(Exchange.class, exchange);
final InputStream in = NMRMessageHelper.convertMessageToInputStream(nm.getBody(Source.class));
inMessage.setContent(InputStream.class, in);
// copy attachments
Collection<Attachment> cxfAttachmentList = new ArrayList<Attachment>();
for (Map.Entry<String, Object> ent : nm.getAttachments().entrySet()) {
cxfAttachmentList.add(new AttachmentImpl(ent.getKey(), (DataHandler)ent.getValue()));
}
inMessage.setAttachments(cxfAttachmentList);
// copy properties and setup the cxf protocol header
Map<String, List<String>> protocolHeaders = new TreeMap<String, List<String>>(
String.CASE_INSENSITIVE_ORDER);
inMessage.put(Message.PROTOCOL_HEADERS, protocolHeaders);
for (Map.Entry<String, Object> ent : nm.getHeaders().entrySet()) {
if (!ent.getKey().equals(Message.REQUESTOR_ROLE)) {
inMessage.put(ent.getKey(), ent.getValue());
}
if (ent.getValue() instanceof String) {
List<String> value = new ArrayList<String>();
value.add((String)ent.getValue());
protocolHeaders.put(ent.getKey(), value);
}
}
// copy securitySubject
inMessage.put(NMRTransportFactory.NMR_SECURITY_SUBJECT, nm.getSecuritySubject());
inMessage.setDestination(this);
getMessageObserver().onMessage(inMessage);
} catch (Exception ex) {
getLogger().log(Level.SEVERE,
new org.apache.cxf.common.i18n.Message("ERROR.PREPARE.MESSAGE", getLogger())
.toString(), ex);
throw new ServiceMixException(ex);
}
}
protected class BackChannelConduit extends AbstractConduit {
protected Message inMessage;
protected NMRDestination nmrDestination;
BackChannelConduit(EndpointReferenceType ref, Message message) {
super(ref);
inMessage = message;
}
/**
* Register a message observer for incoming messages.
*
* @param observer the observer to notify on receipt of incoming
*/
public void setMessageObserver(MessageObserver observer) {
// shouldn't be called for a back channel conduit
}
/**
* Send an outbound message, assumed to contain all the name-value mappings of the corresponding input
* message (if any).
*
* @param message the message to be sent.
*/
public void prepare(Message message) throws IOException {
// setup the message to be send back
Channel dc = channel;
message.put(Exchange.class, inMessage.get(Exchange.class));
NMRTransportFactory.removeUnusedInterceptprs(message);
message.setContent(OutputStream.class, new NMRDestinationOutputStream(inMessage, message, dc));
}
protected Logger getLogger() {
return LOG;
}
}
}