/**
* 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.systest.handlers;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPFault;
import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.LogicalMessage;
import javax.xml.ws.ProtocolException;
import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.soap.SOAPFaultException;
import javax.xml.xpath.XPathConstants;
import org.w3c.dom.Node;
import org.apache.cxf.binding.soap.Soap11;
import org.apache.cxf.binding.soap.saaj.SAAJUtils;
import org.apache.cxf.common.util.PackageUtils;
import org.apache.cxf.helpers.XPathUtils;
import org.apache.handler_test.PingException;
import org.apache.handler_test.types.Ping;
import org.apache.handler_test.types.PingResponse;
import org.apache.handler_test.types.PingWithArgs;
public class TestHandler<T extends LogicalMessageContext>
extends TestHandlerBase implements LogicalHandler<T> {
private final JAXBContext jaxbCtx;
public TestHandler() {
this(true);
}
public TestHandler(boolean serverSide) {
super(serverSide);
try {
jaxbCtx = JAXBContext.newInstance(PackageUtils.getPackageName(Ping.class));
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
public String getHandlerId() {
return "handler" + getId();
}
public boolean handleMessage(T ctx) {
methodCalled("handleMessage");
printHandlerInfo("handleMessage", isOutbound(ctx));
boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
boolean ret = getHandleMessageRet();
if (!isServerSideHandler()) {
return true;
}
try {
verifyJAXWSProperties(ctx);
} catch (PingException e) {
e.printStackTrace();
throw new ProtocolException(e);
}
Object obj = ctx.getMessage().getPayload(jaxbCtx);
if (obj instanceof Ping
|| obj instanceof PingResponse) {
ret = handlePingMessage(outbound, ctx);
} else if (obj instanceof PingWithArgs) {
ret = handlePingWithArgsMessage(outbound, ctx);
}
return ret;
}
private boolean handlePingWithArgsMessage(boolean outbound, T ctx) {
LogicalMessage msg = ctx.getMessage();
Object payload = msg.getPayload(jaxbCtx);
addHandlerId(ctx.getMessage(), ctx, outbound);
boolean ret = true;
if (payload instanceof PingWithArgs) {
String arg = ((PingWithArgs)payload).getHandlersCommand();
StringTokenizer strtok = new StringTokenizer(arg, " ");
String hid = "";
String direction = "";
String command = "";
if (strtok.countTokens() >= 3) {
hid = strtok.nextToken();
direction = strtok.nextToken();
command = strtok.nextToken();
}
if (!getHandlerId().equals(hid)) {
return true;
}
if ("stop".equals(command)) {
if (!outbound && "inbound".equals(direction)) {
PingResponse resp = new PingResponse();
resp.getHandlersInfo().addAll(getHandlerInfoList(ctx));
msg.setPayload(resp, jaxbCtx);
ret = false;
} else if (outbound && "outbound".equals(direction)) {
ret = false;
}
} else if ("throw".equals(command)) {
String exceptionType = null;
String exceptionText = "HandleMessage throws exception";
if (strtok.hasMoreTokens()) {
exceptionType = strtok.nextToken();
}
if (strtok.hasMoreTokens()) {
exceptionText = strtok.nextToken();
}
if (exceptionType != null && !outbound && "inbound".equals(direction)) {
if ("RuntimeException".equals(exceptionType)) {
throw new RuntimeException(exceptionText);
} else if ("ProtocolException".equals(exceptionType)) {
throw new ProtocolException(exceptionText);
}
} else if (exceptionType != null && outbound && "outbound".equals(direction)) {
if ("RuntimeException".equals(exceptionType)) {
throw new RuntimeException(exceptionText);
} else if ("ProtocolException".equals(exceptionType)) {
throw new ProtocolException(exceptionText);
}
}
}
}
return ret;
}
private boolean checkServerOutBindStopHandler(boolean outbound, T ctx) {
if (outbound) {
LogicalMessage msg = ctx.getMessage();
Object obj = msg.getPayload(jaxbCtx);
if (obj instanceof PingResponse) {
// only check if we need call for the server response handler false
PingResponse origResp = (PingResponse)obj;
for (String handler : origResp.getHandlersInfo()) {
if (handler.indexOf("server") == 0 && handler.indexOf(getHandlerId()) > 0
&& handler.indexOf("stop") > 0) {
return true;
}
}
}
}
return false;
}
private boolean handlePingMessage(boolean outbound, T ctx) {
LogicalMessage msg = ctx.getMessage();
addHandlerId(msg, ctx, outbound);
if (checkServerOutBindStopHandler(outbound, ctx)) {
return false;
} else {
return getHandleMessageRet();
}
}
private void addHandlerId(LogicalMessage msg, T ctx, boolean outbound) {
Object obj = msg.getPayload(jaxbCtx);
if (obj instanceof PingResponse) {
PingResponse origResp = (PingResponse)obj;
PingResponse newResp = new PingResponse();
newResp.getHandlersInfo().addAll(origResp.getHandlersInfo());
newResp.getHandlersInfo().add(getHandlerId());
msg.setPayload(newResp, jaxbCtx);
} else if (obj instanceof Ping || obj instanceof PingWithArgs) {
getHandlerInfoList(ctx).add(getHandlerId());
}
}
public boolean handleFault(T ctx) {
methodCalled("handleFault");
printHandlerInfo("handleFault", isOutbound(ctx));
if (isServerSideHandler()) {
if (!"handler2".equals(getHandlerId())) {
return true;
}
DOMSource source = (DOMSource)ctx.getMessage().getPayload();
Node node = source.getNode();
Map<String, String> ns = new HashMap<>();
ns.put("s", Soap11.SOAP_NAMESPACE);
XPathUtils xu = new XPathUtils(ns);
String exceptionText = (String)xu.getValue("//s:Fault/faultstring/text()", node,
XPathConstants.STRING);
//XMLUtils.writeTo(node, System.out);
if ("handler2HandleFaultThrowsRunException".equals(exceptionText)) {
throw new RuntimeException("handler2 HandleFault throws RuntimeException");
} else if ("handler2HandleFaultThrowsSOAPFaultException".equals(exceptionText)) {
throw createSOAPFaultException("handler2 HandleFault "
+ "throws SOAPFaultException");
}
}
return true;
}
private SOAPFaultException createSOAPFaultException(String faultString) {
try {
SOAPFault fault = SOAPFactory.newInstance().createFault();
fault.setFaultString(faultString);
SAAJUtils.setFaultCode(fault, new QName("http://cxf.apache.org/faultcode", "Server"));
return new SOAPFaultException(fault);
} catch (SOAPException e) {
// do nothing
}
return null;
}
public void close(MessageContext arg0) {
methodCalled("close");
}
public void destroy() {
methodCalled("destroy");
}
public String toString() {
return getHandlerId();
}
}