/**
* 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.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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 javax.xml.stream.XMLStreamConstants;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.databinding.DataWriter;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.jaxb.io.EventDataWriter;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.MessageInfo;
import org.apache.cxf.service.model.MessagePartInfo;
import org.apache.cxf.service.model.OperationInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.service.model.ServiceModelUtil;
import org.apache.schemas.yoko.bindings.corba.ArgType;
import org.apache.schemas.yoko.bindings.corba.ModeType;
import org.apache.schemas.yoko.bindings.corba.OperationType;
import org.apache.schemas.yoko.bindings.corba.ParamType;
import org.apache.schemas.yoko.bindings.corba.TypeMappingType;
import org.apache.yoko.bindings.corba.ContextUtils;
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.CorbaHandlerUtils;
import org.apache.yoko.bindings.corba.types.CorbaObjectHandler;
import org.apache.yoko.wsdl.CorbaConstants;
import org.omg.CORBA.ORB;
public class CorbaOutInterceptor extends AbstractPhaseInterceptor<Message> {
private static final Logger LOG = LogUtils.getL7dLogger(CorbaOutInterceptor.class);
private static final String XSI_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
private static final String XSI_PREFIX = "xsi";
private static final String XMLSCHEMA_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema";
private static final String XMLSCHEMA_PREFIX = "xs";
protected CorbaStaxObject corbaStaxObject;
private ServiceInfo service;
private List<CorbaTypeMap> typeMaps;
private ORB orb;
private XMLOutputFactory xof;
private XMLInputFactory xif;
public CorbaOutInterceptor() {
super();
setPhase(Phase.MARSHAL);
}
public void handleMessage(Message msg) {
try {
CorbaMessage message = (CorbaMessage) msg;
orb = (org.omg.CORBA.ORB) message.get(CorbaConstants.ORB);
corbaStaxObject = new CorbaStaxObject(orb);
Exchange exchange = message.getExchange();
typeMaps = new ArrayList<CorbaTypeMap>();
service = exchange.get(ServiceInfo.class);
List<TypeMappingType> corbaTypes = service.getDescription().getExtensors(TypeMappingType.class);
if (corbaTypes != null) {
CorbaUtils.createCorbaTypeMap(typeMaps, corbaTypes);
corbaStaxObject.setTypeMaps(typeMaps);
corbaStaxObject.setServiceInfo(service);
}
getXMLOutputFactory().setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
// TODO: where does encoding constant go?
//String encoding = (String)message.get("Encoding");
BindingOperationInfo boi = exchange.get(BindingOperationInfo.class);
if (ContextUtils.isRequestor(message)) {
handleOutBoundMessage(message, boi);
} else {
handleInBoundMessage(message, boi);
}
} catch (Exception ex) {
throw new Fault(ex);
}
}
protected void handleOutBoundMessage(CorbaMessage message, BindingOperationInfo boi)
throws Exception {
OperationType opType = boi.getExtensor(OperationType.class);
EventDataWriter writer = (EventDataWriter)getDataWriter(message);
List<ParamType> paramTypes = opType.getParam();
List<Object> args = message.getContent(List.class);
MessageInfo msgInfo = message.get(MessageInfo.class);
addMarshalRequestParams(message,
args,
boi,
paramTypes,
getXMLInputFactory(),
getXMLOutputFactory(),
writer);
ArgType returnParam = opType.getReturn();
if (returnParam != null) {
QName retIdlType = returnParam.getIdltype();
QName retName = new QName("", returnParam.getName());
CorbaObjectHandler obj = CorbaHandlerUtils
.initializeObjectHandler(orb, retName, retIdlType, typeMaps, service);
CorbaStreamable streamable = new CorbaStreamable(obj, retName);
message.setStreamableReturn(streamable);
}
}
protected void handleInBoundMessage(CorbaMessage message, BindingOperationInfo boi)
throws Exception {
OperationType opType = boi.getExtensor(OperationType.class);
EventDataWriter writer = (EventDataWriter)getDataWriter(message);
ArgType returnParam = opType.getReturn();
List<Object> args = message.getContent(List.class);
addMarshalResponseParams(message,
args,
boi,
opType,
getXMLInputFactory(),
getXMLOutputFactory(),
writer);
}
protected void addMarshalRequestParams(CorbaMessage message, List<Object> arguments,
BindingOperationInfo boi,
List<ParamType> params,
XMLInputFactory inputFactory,
XMLOutputFactory outputFactory,
EventDataWriter writer)
throws Exception {
if (writer != null) {
OperationInfo opInfo = boi.getOperationInfo();
List<Object> args = arguments;
OperationType opType = boi.getExtensor(OperationType.class);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
XMLEventWriter evtWriter = outputFactory.createXMLEventWriter(outStream);
for (int i = 0; i < args.size(); i++) {
MessagePartInfo part = getInputMessagePartInfo(opInfo, i);
Object partValue = args.get(i);
writer.write(partValue, part, evtWriter);
}
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
XMLEventReader evtReader = inputFactory.createXMLEventReader(inStream);
if (boi.isUnwrappedCapable()) {
//read the wrapper element from the reader
while (evtReader.peek().getEventType() != XMLStreamConstants.START_ELEMENT) {
evtReader.nextEvent();
}
evtReader.nextEvent();
}
for (Iterator<ParamType> iter = params.iterator(); iter.hasNext();) {
ParamType param = iter.next();
QName idlType = param.getIdltype();
QName elName = new QName("", param.getName());
CorbaObjectHandler obj = null;
if (param.getMode().equals(ModeType.OUT)) {
obj = CorbaHandlerUtils.initializeObjectHandler(orb, elName, idlType, typeMaps, service);
} else {
obj = corbaStaxObject.readObjectFromStax(evtReader, idlType);
}
CorbaStreamable streamable = new CorbaStreamable(obj, elName);
ModeType paramMode = param.getMode();
if (paramMode.value().equals("in")) {
streamable.setMode(org.omg.CORBA.ARG_IN.value);
} else if (paramMode.value().equals("inout")) {
streamable.setMode(org.omg.CORBA.ARG_INOUT.value);
} else if (paramMode.value().equals("out")) {
streamable.setMode(org.omg.CORBA.ARG_OUT.value);
}
message.addStreamableArgument(streamable);
}
}
}
protected void addMarshalResponseParams(CorbaMessage message, List<Object> arguments,
BindingOperationInfo boi,
OperationType opType,
XMLInputFactory inputFactory,
XMLOutputFactory outputFactory,
EventDataWriter writer)
throws Exception {
List<ParamType> params = opType.getParam();
if (writer != null) {
OperationInfo opInfo = boi.getOperationInfo();
List<Object> args = arguments;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
XMLEventWriter evtWriter = outputFactory.createXMLEventWriter(outStream);
for (int i = 0; i < args.size(); i++) {
MessagePartInfo part = getOutputMessagePartInfo(opInfo, i);
Object partValue = args.get(i);
writer.write(partValue, part, evtWriter);
}
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
XMLEventReader evtReader = inputFactory.createXMLEventReader(inStream);
if (boi.isUnwrappedCapable()) {
//read the wrapper element from the reader
while (evtReader.peek().getEventType() != XMLStreamConstants.START_ELEMENT) {
evtReader.nextEvent();
}
evtReader.nextEvent();
}
ArgType returnParam = opType.getReturn();
if (returnParam != null) {
QName retIdlType = returnParam.getIdltype();
QName retName = new QName("", returnParam.getName());
CorbaObjectHandler obj = corbaStaxObject.readObjectFromStax(evtReader, retIdlType);
CorbaStreamable streamable = new CorbaStreamable(obj, retName);
message.setStreamableReturn(streamable);
}
for (Iterator<ParamType> iter = params.iterator(); iter.hasNext();) {
ParamType param = iter.next();
QName idlType = param.getIdltype();
QName elName = new QName("", param.getName());
CorbaObjectHandler obj = null;
if (param.getMode().equals(ModeType.IN)) {
obj = CorbaHandlerUtils.initializeObjectHandler(orb, elName, idlType, typeMaps, service);
} else {
obj = corbaStaxObject.readObjectFromStax(evtReader, idlType);
}
CorbaStreamable streamable = new CorbaStreamable(obj, elName);
ModeType paramMode = param.getMode();
if (paramMode.value().equals("in")) {
streamable.setMode(org.omg.CORBA.ARG_IN.value);
} else if (paramMode.value().equals("inout")) {
streamable.setMode(org.omg.CORBA.ARG_INOUT.value);
} else if (paramMode.value().equals("out")) {
streamable.setMode(org.omg.CORBA.ARG_OUT.value);
}
message.addStreamableArgument(streamable);
}
}
}
protected XMLOutputFactory getXMLOutputFactory() {
if (xof == null) {
xof = XMLOutputFactory.newInstance();
xof.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
}
return xof;
}
protected XMLInputFactory getXMLInputFactory() {
if (xif == null) {
xif = XMLInputFactory.newInstance();
}
return xif;
}
protected MessagePartInfo getInputMessagePartInfo(OperationInfo opInfo, int index) {
MessageInfo msgInfo = opInfo.getInput();
List<MessagePartInfo> parts = msgInfo.getMessageParts();
MessagePartInfo part = parts.get(index);
return part;
}
protected MessagePartInfo getOutputMessagePartInfo(OperationInfo opInfo, int index) {
MessageInfo msgInfo = opInfo.getOutput();
List<MessagePartInfo> parts = msgInfo.getMessageParts();
MessagePartInfo part = parts.get(index);
return part;
}
protected DataWriter<XMLEventWriter> getDataWriter(CorbaMessage message) {
Service serviceModel = ServiceModelUtil.getService(message.getExchange());
DataWriter<XMLEventWriter> dataWriter =
serviceModel.getDataBinding().createWriter(XMLEventWriter.class);
if (dataWriter == null) {
//throw a fault
//throw new Fault(new org.apache.cxf.common.i18n.Message("NO_DATAWRITER", BUNDLE, service
// .getName()));
}
return dataWriter;
}
}