/** * 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<>(); 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; } }