/**
* 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.yoko.bindings.corba.interceptors;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.jaxb.io.EventDataWriter;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.BindingInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.FaultInfo;
import org.apache.cxf.service.model.InterfaceInfo;
import org.apache.cxf.service.model.MessagePartInfo;
import org.apache.cxf.service.model.OperationInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.schemas.yoko.bindings.corba.OperationType;
import org.apache.schemas.yoko.bindings.corba.RaisesType;
import org.apache.schemas.yoko.bindings.corba.TypeMappingType;
import org.apache.yoko.bindings.corba.ContextUtils;
import org.apache.yoko.bindings.corba.CorbaBindingException;
import org.apache.yoko.bindings.corba.CorbaDestination;
import org.apache.yoko.bindings.corba.CorbaMessage;
import org.apache.yoko.bindings.corba.CorbaStaxObject;
import org.apache.yoko.bindings.corba.CorbaStreamable;
import org.apache.yoko.bindings.corba.CorbaTypeMap;
import org.apache.yoko.bindings.corba.CorbaUtils;
import org.apache.yoko.bindings.corba.types.CorbaObjectHandler;
import org.apache.yoko.wsdl.CorbaConstants;
public class CorbaFaultOutInterceptor extends AbstractPhaseInterceptor<Message> {
private static final Logger LOG = LogUtils.getL7dLogger(CorbaFaultOutInterceptor.class);
protected CorbaStaxObject corbaStaxObject;
public CorbaFaultOutInterceptor() {
super();
setPhase(Phase.MARSHAL);
corbaStaxObject = new CorbaStaxObject();
}
public void handleMessage(Message msg) {
try {
CorbaMessage message = (CorbaMessage)msg;
EventDataWriter writer = (EventDataWriter)ContextUtils.getDataWriter(message);
CorbaDestination destination = null;
if (message.getDestination() != null) {
destination = (CorbaDestination)message.getDestination();
} else {
destination = (CorbaDestination)message.getExchange().getDestination();
}
org.omg.CORBA.ORB orb = (org.omg.CORBA.ORB) message.get(CorbaConstants.ORB);
if (orb == null) {
orb = (org.omg.CORBA.ORB) message.getExchange().get(org.omg.CORBA.ORB.class);
}
corbaStaxObject.setOrb(orb);
List<CorbaTypeMap> typeMaps = new ArrayList<CorbaTypeMap>();
ServiceInfo service = destination.getBindingInfo().getService();
List<TypeMappingType> corbaTypes = service.getDescription().getExtensors(TypeMappingType.class);
if (corbaTypes != null) {
CorbaUtils.createCorbaTypeMap(typeMaps, corbaTypes);
corbaStaxObject.setTypeMaps(typeMaps);
corbaStaxObject.setServiceInfo(service);
}
Throwable ex = message.getContent(Exception.class);
ex = ex.getCause();
if (ex instanceof InvocationTargetException) {
ex = ex.getCause();
}
// Get information about the operation being invoked from the WSDL
// definition.
// We need this to marshal data correctly
BindingInfo bInfo = destination.getBindingInfo();
InterfaceInfo info = bInfo.getInterface();
String opName = message.getExchange().get(String.class);
Iterator iter = bInfo.getOperations().iterator();
BindingOperationInfo bopInfo = null;
OperationType opType = null;
while (iter.hasNext()) {
bopInfo = (BindingOperationInfo)iter.next();
if (bopInfo.getName().getLocalPart().equals(opName)) {
opType = bopInfo.getExtensor(OperationType.class);
break;
}
}
if (opType == null) {
throw new CorbaBindingException("Unable to find operation definition");
}
OperationInfo opInfo = bopInfo.getOperationInfo();
QName exIdlType = null;
List<RaisesType> exList = opType.getRaises();
for (Iterator<RaisesType> i = exList.iterator(); i.hasNext();) {
// REVISIT: Note that this assumes that exception names need to
// be unique. We should make
// sure that this is really the case.
RaisesType raises = i.next();
if (raises.getException().getLocalPart().equals(ex.getClass().getSimpleName())) {
exIdlType = raises.getException();
break;
}
}
if (exIdlType != null) {
setUserException(message, ex, exIdlType, opInfo, writer);
}
} catch (java.lang.Exception ex) {
LOG.log(Level.SEVERE, "CORBA marshal fault exception", ex);
throw new CorbaBindingException("Marshal fault failed", ex);
}
}
protected void setUserException(CorbaMessage message,
Throwable ex,
QName exIdlType,
OperationInfo opInfo,
EventDataWriter writer)
throws Exception {
QName elName = new QName("", exIdlType.getLocalPart());
MessagePartInfo faultPart = getFaultMessagePartInfo(opInfo, elName);
if (faultPart == null) {
throw new CorbaBindingException("Coulnd't find the message fault part : " + elName);
}
Method faultMethod = ex.getClass().getMethod("getFaultInfo");
if (faultMethod == null) {
return;
}
Object fault = faultMethod.invoke(ex);
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
XMLEventWriter evtWriter = outputFactory.createXMLEventWriter(outStream);
writer.write(fault, faultPart, evtWriter);
LOG.log(Level.INFO, "Found exception in the raises list. Marshalling.");
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
XMLEventReader evtReader = inputFactory.createXMLEventReader(inStream);
CorbaObjectHandler obj = corbaStaxObject.readObjectFromStax(evtReader, exIdlType);
CorbaStreamable streamable = new CorbaStreamable(obj, elName);
message.setStreamableException(streamable);
}
protected MessagePartInfo getFaultMessagePartInfo(OperationInfo opInfo, QName faultName) {
Iterator<FaultInfo> faults = opInfo.getFaults().iterator();
while (faults.hasNext()) {
FaultInfo fault = faults.next();
if (fault.getFaultName().getLocalPart().equals(faultName.getLocalPart())) {
return fault.getMessageParts().get(0);
}
}
return null;
}
}