blob: 98218caaa8284118e39f7fe96da94d071ac52de3 [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.cxf.binding.corba;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.corba.types.CorbaHandlerUtils;
import org.apache.cxf.binding.corba.types.CorbaObjectHandler;
import org.apache.cxf.binding.corba.utils.ContextUtils;
import org.apache.cxf.binding.corba.utils.CorbaAnyHelper;
import org.apache.cxf.binding.corba.utils.CorbaBindingHelper;
import org.apache.cxf.binding.corba.utils.CorbaUtils;
import org.apache.cxf.binding.corba.utils.OrbConfig;
import org.apache.cxf.binding.corba.wsdl.AddressType;
import org.apache.cxf.binding.corba.wsdl.CorbaConstants;
import org.apache.cxf.binding.corba.wsdl.OperationType;
import org.apache.cxf.binding.corba.wsdl.RaisesType;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.transport.MessageObserver;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.omg.CORBA.Any;
import org.omg.CORBA.Context;
import org.omg.CORBA.ContextList;
import org.omg.CORBA.ExceptionList;
import org.omg.CORBA.NVList;
import org.omg.CORBA.NamedValue;
import org.omg.CORBA.ORB;
import org.omg.CORBA.Request;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.TypeCode;
import org.omg.CORBA.UnknownUserException;
public class CorbaConduit implements Conduit {
private static final Logger LOG = LogUtils.getL7dLogger(CorbaConduit.class);
private EndpointInfo endpointInfo;
private EndpointReferenceType target;
private MessageObserver incomingObserver;
private ORB orb;
private OrbConfig orbConfig;
private CorbaTypeMap typeMap;
public CorbaConduit(EndpointInfo ei, EndpointReferenceType ref, OrbConfig config) {
endpointInfo = ei;
target = getTargetReference(ref);
orbConfig = config;
typeMap = TypeMapCache.get(ei.getService());
}
public OrbConfig getOrbConfig() {
return orbConfig;
}
public synchronized void prepareOrb() {
if (orb == null) {
orb = CorbaBindingHelper.getDefaultORB(orbConfig);
}
}
public void prepare(Message message) throws IOException {
try {
prepareOrb();
String address = null;
if (target != null) {
address = target.getAddress().getValue();
}
if (address == null) {
AddressType ad = endpointInfo.getExtensor(AddressType.class);
if (ad != null) {
address = ad.getLocation();
}
}
String ref = (String)message.get(Message.ENDPOINT_ADDRESS);
if (ref != null) {
// A non-null endpoint address from the message means that we want to invoke on a particular
// object reference specified by the endpoint reference type. If the reference is null, then
// we want to invoke on the default location as specified in the WSDL.
address = ref;
}
if (address == null) {
LOG.log(Level.SEVERE, "Unable to locate a valid CORBA address");
throw new CorbaBindingException("Unable to locate a valid CORBA address");
}
org.omg.CORBA.Object targetObject;
targetObject = CorbaUtils.importObjectReference(orb, address);
message.put(CorbaConstants.ORB, orb);
message.put(CorbaConstants.CORBA_ENDPOINT_OBJECT, targetObject);
message.setContent(OutputStream.class,
new CorbaOutputStream(message));
if (message instanceof CorbaMessage) {
((CorbaMessage)message).setCorbaTypeMap(typeMap);
}
} catch (java.lang.Exception ex) {
LOG.log(Level.SEVERE, "Could not resolve target object");
throw new CorbaBindingException(ex);
}
}
public void close(Message message) throws IOException {
if (message.get(CorbaConstants.CORBA_ENDPOINT_OBJECT) != null) {
BindingOperationInfo boi = message.getExchange().getBindingOperationInfo();
OperationType opType = boi.getExtensor(OperationType.class);
try {
if (message instanceof CorbaMessage) {
buildRequest((CorbaMessage)message, opType);
}
message.getContent(OutputStream.class).close();
} catch (Exception ex) {
LOG.log(Level.SEVERE, "Could not build the corba request");
throw new CorbaBindingException(ex);
}
}
}
public EndpointReferenceType getTarget() {
return target;
}
public void close() {
}
public void setMessageObserver(MessageObserver observer) {
incomingObserver = observer;
}
public final EndpointReferenceType getTargetReference(EndpointReferenceType t) {
EndpointReferenceType ref = null;
if (null == t) {
ref = new EndpointReferenceType();
AttributedURIType address = new AttributedURIType();
address.setValue(getAddress());
ref.setAddress(address);
} else {
ref = t;
}
return ref;
}
public final String getAddress() {
return endpointInfo.getAddress();
}
public void buildRequest(CorbaMessage message, OperationType opType) throws Exception {
ServiceInfo service = message.getExchange().getEndpoint().getEndpointInfo().getService();
NVList nvlist = getArguments(message);
NamedValue ret = getReturn(message);
Map<TypeCode, RaisesType> exceptions = getOperationExceptions(opType, typeMap);
ExceptionList exList = getExceptionList(exceptions, message, opType);
Request request = getRequest(message, opType.getName(), nvlist, ret, exList);
if (request == null) {
throw new CorbaBindingException("Couldn't build the corba request");
}
Exception ex = null;
try {
request.invoke();
ex = request.env().exception();
} catch (SystemException sysex) {
ex = sysex;
}
if (ex != null) {
if (ex instanceof SystemException) {
message.setContent(Exception.class, new Fault(ex));
message.setSystemException((SystemException) ex);
return;
}
if (ex instanceof UnknownUserException) {
UnknownUserException userEx = (UnknownUserException) ex;
Any except = userEx.except;
RaisesType raises = exceptions.get(except.type());
if (raises == null) {
throw new CorbaBindingException("Couldn't find the exception type code to unmarshall");
}
QName elName = new QName("", raises.getException().getLocalPart());
CorbaObjectHandler handler =
CorbaHandlerUtils.initializeObjectHandler(orb,
elName,
raises.getException(),
typeMap,
service);
CorbaStreamable exStreamable = message.createStreamableObject(handler, elName);
exStreamable._read(except.create_input_stream());
message.setStreamableException(exStreamable);
message.setContent(Exception.class, new Fault(userEx));
} else {
message.setContent(Exception.class, new Fault(ex));
}
}
}
public NVList getArguments(CorbaMessage message) {
if (orb == null) {
prepareOrb();
}
// Build the list of DII arguments, returns, and exceptions
NVList list = null;
if (message.getStreamableArguments() != null) {
CorbaStreamable[] arguments = message.getStreamableArguments();
list = orb.create_list(arguments.length);
for (CorbaStreamable argument : arguments) {
Any value = CorbaAnyHelper.createAny(orb);
argument.getObject().setIntoAny(value, argument, true);
list.add_value(argument.getName(), value, argument.getMode());
}
} else {
list = orb.create_list(0);
}
return list;
}
public NamedValue getReturn(CorbaMessage message) {
if (orb == null) {
prepareOrb();
}
CorbaStreamable retVal = message.getStreamableReturn();
NamedValue ret = null;
if (retVal != null) {
Any returnAny = CorbaAnyHelper.createAny(orb);
retVal.getObject().setIntoAny(returnAny, retVal, false);
ret = orb.create_named_value(retVal.getName(), returnAny, org.omg.CORBA.ARG_OUT.value);
} else {
// TODO: REVISIT: for some reason,some ORBs do not like to
// have a null NamedValue return value. Create this 'empty'
// one if a void return type is used.
ret = orb.create_named_value("return", orb.create_any(), org.omg.CORBA.ARG_OUT.value);
}
return ret;
}
public ExceptionList getExceptionList(Map<TypeCode, RaisesType> exceptions,
CorbaMessage message,
OperationType opType) {
if (orb == null) {
prepareOrb();
}
// Get the typecodes for the exceptions this operation can throw.
// These are defined in the operation definition from WSDL.
ExceptionList exList = orb.create_exception_list();
if (exceptions != null) {
Object[] tcs = null;
tcs = exceptions.keySet().toArray();
for (int i = 0; i < exceptions.size(); ++i) {
exList.add((TypeCode)tcs[i]);
}
}
return exList;
}
public Request getRequest(CorbaMessage message,
String opName,
org.omg.CORBA.NVList nvlist,
org.omg.CORBA.NamedValue ret,
org.omg.CORBA.ExceptionList exList)
throws Exception {
Request request = null;
if (orb == null) {
prepareOrb();
}
ContextList ctxList = orb.create_context_list();
Context ctx = null;
try {
ctx = orb.get_default_context();
} catch (Exception ex) {
//ignore?
}
org.omg.CORBA.Object targetObj =
(org.omg.CORBA.Object)message.get(CorbaConstants.CORBA_ENDPOINT_OBJECT);
if (targetObj != null) {
request = targetObj._create_request(ctx, opName, nvlist, ret, exList, ctxList);
}
return request;
}
public Map<TypeCode, RaisesType> getOperationExceptions(
OperationType operation,
CorbaTypeMap map) {
if (orb == null) {
prepareOrb();
}
Map<TypeCode, RaisesType> exceptions = new HashMap<TypeCode, RaisesType>();
List<RaisesType> exList = operation.getRaises();
if (exList != null) {
for (int i = 0; i < exList.size(); ++i) {
RaisesType ex = exList.get(i);
TypeCode tc = CorbaUtils.getTypeCode(orb, ex.getException(), map);
exceptions.put(tc, ex);
}
}
return exceptions;
}
private class CorbaOutputStream extends CachedOutputStream {
private Message message;
private boolean isOneWay;
CorbaOutputStream(Message m) {
message = m;
}
/**
* Perform any actions required on stream flush (freeze headers, reset
* output stream ... etc.)
*/
public void doFlush() throws IOException {
// do nothing here
}
/**
* Perform any actions required on stream closure (handle response etc.)
*/
public void doClose() throws IOException {
if (ContextUtils.isRequestor(message) && ContextUtils.isOutbound(message)) {
try {
isOneWay = message.getExchange().isOneWay();
if (!isOneWay) {
handleResponse();
}
} catch (Exception ex) {
LOG.log(Level.WARNING, "Connection failed with Exception : ", ex);
throw new IOException(ex.toString());
}
}
}
public void onWrite() throws IOException {
}
public void handleResponse() throws IOException {
LOG.log(Level.FINE, "incoming observer is " + incomingObserver);
Exchange exchange = message.getExchange();
CorbaMessage corbaMsg = (CorbaMessage) message;
MessageImpl inMessage = new MessageImpl();
CorbaDestination destination = new CorbaDestination(endpointInfo, orbConfig, typeMap);
inMessage.setDestination(destination);
exchange.put(ORB.class, orb);
inMessage.setExchange(exchange);
CorbaMessage inCorbaMsg = new CorbaMessage(inMessage);
inCorbaMsg.setCorbaTypeMap(typeMap);
if (corbaMsg.getStreamableException() != null) {
exchange.setInFaultMessage(corbaMsg);
inCorbaMsg.setStreamableException(corbaMsg.getStreamableException());
} else if (corbaMsg.getSystemException() != null) {
exchange.setInFaultMessage(corbaMsg);
inCorbaMsg.setSystemException(corbaMsg.getSystemException());
}
LOG.log(Level.FINE, "incoming observer is " + incomingObserver);
incomingObserver.onMessage(inCorbaMsg);
message.setContent(Exception.class, inCorbaMsg.getContent(Exception.class));
}
}
public MessageObserver getMessageObserver() {
return this.incomingObserver;
}
}