blob: 1e9680ae331591f77fb217cac0ad7791bb565459 [file] [log] [blame]
/*
* Portions Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.xml.internal.ws.handler;
import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil;
import com.sun.xml.internal.ws.util.HandlerAnnotationInfo;
import com.sun.xml.internal.ws.util.JAXWSUtils;
import com.sun.xml.internal.ws.util.UtilException;
import javax.annotation.PostConstruct;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.http.HTTPBinding;
import javax.xml.ws.soap.SOAPBinding;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Logger;
public class HandlerChainsModel {
private static final Logger logger = Logger.getLogger(
com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".util");
protected Class annotatedClass;
protected List<HandlerChainType> handlerChains;
protected String id;
/** Creates a new instance of HandlerChains */
public HandlerChainsModel(Class annotatedClass) {
this.annotatedClass = annotatedClass;
}
public List<HandlerChainType> getHandlerChain() {
if (handlerChains == null) {
handlerChains = new ArrayList<HandlerChainType>();
}
return handlerChains;
}
public java.lang.String getId() {
return id;
}
public void setId(java.lang.String value) {
this.id = value;
}
/**
* reader should be on <handler-chains> element
*/
public static HandlerChainsModel parseHandlerConfigFile(Class annotatedClass, XMLStreamReader reader) {
ensureProperName(reader,QNAME_HANDLER_CHAINS);
HandlerChainsModel handlerModel = new HandlerChainsModel(annotatedClass);
List<HandlerChainType> hChains = handlerModel.getHandlerChain();
XMLStreamReaderUtil.nextElementContent(reader);
while (reader.getName().equals(QNAME_HANDLER_CHAIN)) {
HandlerChainType hChain = new HandlerChainType();
XMLStreamReaderUtil.nextElementContent(reader);
if (reader.getName().equals(QNAME_CHAIN_PORT_PATTERN)) {
QName portNamePattern = XMLStreamReaderUtil.getElementQName(reader);
hChain.setPortNamePattern(portNamePattern);
XMLStreamReaderUtil.nextElementContent(reader);
} else if (reader.getName().equals(QNAME_CHAIN_PROTOCOL_BINDING)) {
String bindingList = XMLStreamReaderUtil.getElementText(reader);
StringTokenizer stk = new StringTokenizer(bindingList);
while(stk.hasMoreTokens()) {
String token = stk.nextToken();
// This will convert tokens into Binding URI
hChain.addProtocolBinding(token);
}
XMLStreamReaderUtil.nextElementContent(reader);
} else if (reader.getName().equals(QNAME_CHAIN_SERVICE_PATTERN)) {
QName serviceNamepattern = XMLStreamReaderUtil.getElementQName(reader);
hChain.setServiceNamePattern(serviceNamepattern);
XMLStreamReaderUtil.nextElementContent(reader);
}
List<HandlerType> handlers = hChain.getHandlers();
// process all <handler> elements
while (reader.getName().equals(QNAME_HANDLER)) {
HandlerType handler = new HandlerType();
XMLStreamReaderUtil.nextContent(reader);
if (reader.getName().equals(QNAME_HANDLER_NAME)) {
String handlerName =
XMLStreamReaderUtil.getElementText(reader);
handler.setHandlerName(handlerName);
XMLStreamReaderUtil.nextContent(reader);
}
// handler class
ensureProperName(reader, QNAME_HANDLER_CLASS);
String handlerClass =
XMLStreamReaderUtil.getElementText(reader);
handler.setHandlerClass(handlerClass);
XMLStreamReaderUtil.nextContent(reader);
// init params (ignored)
while (reader.getName().equals(QNAME_HANDLER_PARAM)) {
skipInitParamElement(reader);
}
// headers (ignored)
while (reader.getName().equals(QNAME_HANDLER_HEADER)) {
skipTextElement(reader);
}
// roles (not stored per handler)
while (reader.getName().equals(QNAME_HANDLER_ROLE)) {
List<String> soapRoles = handler.getSoapRoles();
soapRoles.add(XMLStreamReaderUtil.getElementText(reader));
XMLStreamReaderUtil.nextContent(reader);
}
handlers.add(handler);
// move past </handler>
ensureProperName(reader, QNAME_HANDLER);
XMLStreamReaderUtil.nextContent(reader);
}
// move past </handler-chain>
ensureProperName(reader, QNAME_HANDLER_CHAIN);
hChains.add(hChain);
XMLStreamReaderUtil.nextContent(reader);
}
return handlerModel;
}
/**
* <p>This method is called internally by HandlerAnnotationProcessor,
* and by
* {@link com.sun.xml.internal.ws.transport.http.servlet.RuntimeEndpointInfoParser}
* directly when it reaches the handler chains element in the
* descriptor file it is parsing.
*
* @return A HandlerAnnotationInfo object that stores the
* handlers and roles.
*/
public static HandlerAnnotationInfo parseHandlerFile(XMLStreamReader reader,
ClassLoader classLoader, QName serviceName, QName portName,
String bindingId) {
ensureProperName(reader,QNAME_HANDLER_CHAINS);
HandlerAnnotationInfo info = new HandlerAnnotationInfo();
XMLStreamReaderUtil.nextElementContent(reader);
List<Handler> handlerChain = new ArrayList<Handler>();
Set<String> roles = new HashSet<String>();
while (reader.getName().equals(QNAME_HANDLER_CHAIN)) {
XMLStreamReaderUtil.nextElementContent(reader);
if (reader.getName().equals(QNAME_CHAIN_PORT_PATTERN)) {
if (portName == null) {
logger.warning("handler chain sepcified for port " +
"but port QName passed to parser is null");
}
boolean parseChain = JAXWSUtils.matchQNames(portName,
XMLStreamReaderUtil.getElementQName(reader));
if (!parseChain) {
skipChain(reader);
continue;
}
XMLStreamReaderUtil.nextElementContent(reader);
} else if (reader.getName().equals(QNAME_CHAIN_PROTOCOL_BINDING)) {
if (bindingId == null) {
logger.warning("handler chain sepcified for bindingId " +
"but bindingId passed to parser is null");
}
String bindingConstraint = XMLStreamReaderUtil.getElementText(reader);
boolean skipThisChain = true;
StringTokenizer stk = new StringTokenizer(bindingConstraint);
List<String> bindingList = new ArrayList<String>();
while(stk.hasMoreTokens()) {
String tokenOrURI = stk.nextToken();
String binding = tokenBindingMap.get(tokenOrURI);
if(binding == null) {
//Unknown binding or Unknown token, Put it as it is
binding = tokenOrURI;
}
bindingList.add(binding);
}
if(bindingList.contains(bindingId)){
skipThisChain = false;
}
if (skipThisChain) {
skipChain(reader);
continue;
}
XMLStreamReaderUtil.nextElementContent(reader);
} else if (reader.getName().equals(QNAME_CHAIN_SERVICE_PATTERN)) {
if (serviceName == null) {
logger.warning("handler chain sepcified for service " +
"but service QName passed to parser is null");
}
boolean parseChain = JAXWSUtils.matchQNames(
serviceName,
XMLStreamReaderUtil.getElementQName(reader));
if (!parseChain) {
skipChain(reader);
continue;
}
XMLStreamReaderUtil.nextElementContent(reader);
}
// process all <handler> elements
while (reader.getName().equals(QNAME_HANDLER)) {
Handler handler = null;
XMLStreamReaderUtil.nextContent(reader);
if (reader.getName().equals(QNAME_HANDLER_NAME)) {
skipTextElement(reader);
}
// handler class
ensureProperName(reader, QNAME_HANDLER_CLASS);
try {
handler = (Handler) loadClass(classLoader,
XMLStreamReaderUtil.getElementText(reader)).newInstance();
} catch (InstantiationException ie){
throw new RuntimeException(ie);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
XMLStreamReaderUtil.nextContent(reader);
// init params (ignored)
while (reader.getName().equals(QNAME_HANDLER_PARAM)) {
skipInitParamElement(reader);
}
// headers (ignored)
while (reader.getName().equals(QNAME_HANDLER_HEADER)) {
skipTextElement(reader);
}
// roles (not stored per handler)
while (reader.getName().equals(QNAME_HANDLER_ROLE)) {
roles.add(XMLStreamReaderUtil.getElementText(reader));
XMLStreamReaderUtil.nextContent(reader);
}
// call @PostConstruct method on handler if present
for (Method method : handler.getClass().getMethods()) {
if (method.getAnnotation(PostConstruct.class) == null) {
continue;
}
try {
method.invoke(handler, new Object [0]);
break;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
handlerChain.add(handler);
// move past </handler>
ensureProperName(reader, QNAME_HANDLER);
XMLStreamReaderUtil.nextContent(reader);
}
// move past </handler-chain>
ensureProperName(reader, QNAME_HANDLER_CHAIN);
XMLStreamReaderUtil.nextContent(reader);
}
info.setHandlers(handlerChain);
info.setRoles(roles);
return info;
}
public HandlerAnnotationInfo getHandlersForPortInfo(PortInfo info){
HandlerAnnotationInfo handlerInfo = new HandlerAnnotationInfo();
List<Handler> handlerClassList = new ArrayList<Handler>();
Set<String> roles = new HashSet<String>();
for(HandlerChainType hchain : handlerChains) {
boolean hchainMatched = false;
if((!hchain.isConstraintSet()) ||
JAXWSUtils.matchQNames(info.getServiceName(), hchain.getServiceNamePattern()) ||
JAXWSUtils.matchQNames(info.getPortName(), hchain.getPortNamePattern()) ||
hchain.getProtocolBindings().contains(info.getBindingID()) ){
hchainMatched = true;
}
if(hchainMatched) {
for(HandlerType handler : hchain.getHandlers()) {
try {
Handler handlerClass = (Handler) loadClass(annotatedClass.getClassLoader(),
handler.getHandlerClass()).newInstance();
callHandlerPostConstruct(handlerClass);
handlerClassList.add(handlerClass);
} catch (InstantiationException ie){
throw new RuntimeException(ie);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
roles.addAll(handler.getSoapRoles());
}
}
}
handlerInfo.setHandlers(handlerClassList);
handlerInfo.setRoles(roles);
return handlerInfo;
}
static Class loadClass(ClassLoader loader, String name) {
try {
return Class.forName(name, true, loader);
} catch (ClassNotFoundException e) {
throw new UtilException(
"util.handler.class.not.found",
name);
}
}
static void callHandlerPostConstruct(Object handlerClass) {
// call @PostConstruct method on handler if present
for (Method method : handlerClass.getClass().getMethods()) {
if (method.getAnnotation(PostConstruct.class) == null) {
continue;
}
try {
method.invoke(handlerClass, new Object [0]);
break;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
static void skipChain(XMLStreamReader reader) {
while (XMLStreamReaderUtil.nextContent(reader) !=
XMLStreamConstants.END_ELEMENT ||
!reader.getName().equals(QNAME_HANDLER_CHAIN)) {}
XMLStreamReaderUtil.nextElementContent(reader);
}
static void skipTextElement(XMLStreamReader reader) {
XMLStreamReaderUtil.nextContent(reader);
XMLStreamReaderUtil.nextElementContent(reader);
XMLStreamReaderUtil.nextElementContent(reader);
}
static void skipInitParamElement(XMLStreamReader reader) {
int state;
do {
state = XMLStreamReaderUtil.nextContent(reader);
} while (state != XMLStreamReader.END_ELEMENT ||
!reader.getName().equals(QNAME_HANDLER_PARAM));
XMLStreamReaderUtil.nextElementContent(reader);
}
static void ensureProperName(XMLStreamReader reader,
QName expectedName) {
if (!reader.getName().equals(expectedName)) {
failWithLocalName("util.parser.wrong.element", reader,
expectedName.getLocalPart());
}
}
static void ensureProperName(XMLStreamReader reader, String expectedName) {
if (!reader.getLocalName().equals(expectedName)) {
failWithLocalName("util.parser.wrong.element", reader,
expectedName);
}
}
static void failWithLocalName(String key,
XMLStreamReader reader, String arg) {
throw new UtilException(key,
new Object[] {
Integer.toString(reader.getLocation().getLineNumber()),
reader.getLocalName(),
arg });
}
public static final String PROTOCOL_SOAP11_TOKEN = "##SOAP11_HTTP";
public static final String PROTOCOL_SOAP12_TOKEN = "##SOAP12_HTTP";
public static final String PROTOCOL_XML_TOKEN = "##XML_HTTP";
public static final String NS_109 =
"http://java.sun.com/xml/ns/javaee";
public static final QName QNAME_CHAIN_PORT_PATTERN =
new QName(NS_109, "port-name-pattern");
public static final QName QNAME_CHAIN_PROTOCOL_BINDING =
new QName(NS_109, "protocol-bindings");
public static final QName QNAME_CHAIN_SERVICE_PATTERN =
new QName(NS_109, "service-name-pattern");
public static final QName QNAME_HANDLER_CHAIN =
new QName(NS_109, "handler-chain");
public static final QName QNAME_HANDLER_CHAINS =
new QName(NS_109, "handler-chains");
public static final QName QNAME_HANDLER =
new QName(NS_109, "handler");
public static final QName QNAME_HANDLER_NAME =
new QName(NS_109, "handler-name");
public static final QName QNAME_HANDLER_CLASS =
new QName(NS_109, "handler-class");
public static final QName QNAME_HANDLER_PARAM =
new QName(NS_109, "init-param");
public static final QName QNAME_HANDLER_PARAM_NAME =
new QName(NS_109, "param-name");
public static final QName QNAME_HANDLER_PARAM_VALUE =
new QName(NS_109, "param-value");
public static final QName QNAME_HANDLER_HEADER =
new QName(NS_109, "soap-header");
public static final QName QNAME_HANDLER_ROLE =
new QName(NS_109, "soap-role");
protected static final Map<String,String> tokenBindingMap;
//Populate the token map
static {
tokenBindingMap = new HashMap<String,String>();
tokenBindingMap.put("##SOAP11_HTTP",SOAPBinding.SOAP11HTTP_BINDING);
tokenBindingMap.put("##SOAP11_HTTP_MTOM",SOAPBinding.SOAP11HTTP_MTOM_BINDING);
tokenBindingMap.put("##SOAP12_HTTP",SOAPBinding.SOAP12HTTP_BINDING);
tokenBindingMap.put("##SOAP12_HTTP_MTOM",SOAPBinding.SOAP12HTTP_MTOM_BINDING);
tokenBindingMap.put("##XML_HTTP",HTTPBinding.HTTP_BINDING);
}
static class HandlerChainType {
//constraints
protected QName serviceNamePattern;
protected QName portNamePattern;
protected List<String> protocolBindings;
// This flag is set if one of the above constraint is set on handler chain
protected boolean constraintSet = false;
protected List<HandlerType> handlers;
protected String id;
/** Creates a new instance of HandlerChain */
public HandlerChainType() {
protocolBindings = new ArrayList<String>();
}
public void setServiceNamePattern(QName value) {
this.serviceNamePattern = value;
constraintSet = true;
}
public QName getServiceNamePattern() {
return serviceNamePattern;
}
public void setPortNamePattern(QName value) {
this.portNamePattern = value;
constraintSet = true;
}
public QName getPortNamePattern() {
return portNamePattern;
}
public List<java.lang.String> getProtocolBindings() {
return this.protocolBindings;
}
public void addProtocolBinding(String tokenorURI){
String binding = tokenBindingMap.get(tokenorURI);
if(binding == null) {
//Unknown binding or Unknown token, Put it as it is
binding = tokenorURI;
}
protocolBindings.add(binding);
constraintSet = true;
}
public boolean isConstraintSet() {
return constraintSet || !protocolBindings.isEmpty();
}
public java.lang.String getId() {
return id;
}
public void setId(java.lang.String value) {
this.id = value;
}
public List<HandlerType> getHandlers() {
if (handlers == null) {
handlers = new ArrayList<HandlerType>();
}
return this.handlers;
}
}
static class HandlerType {
protected String handlerName;
protected String handlerClass;
protected List<String> soapRoles;
protected java.lang.String id;
/** Creates a new instance of HandlerComponent */
public HandlerType() {
}
public String getHandlerName() {
return handlerName;
}
public void setHandlerName(String value) {
this.handlerName = value;
}
public String getHandlerClass() {
return handlerClass;
}
public void setHandlerClass(String value) {
this.handlerClass = value;
}
public java.lang.String getId() {
return id;
}
public void setId(java.lang.String value) {
this.id = value;
}
public List<String> getSoapRoles() {
if (soapRoles == null) {
soapRoles = new ArrayList<String>();
}
return this.soapRoles;
}
}
}