package org.apache.beehive.wsm.axis.handlers;
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
*
* Licensed 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.
*
*/
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import org.apache.axis.AxisFault;
import org.apache.axis.Constants;
import org.apache.axis.MessageContext;
import org.apache.axis.client.Call;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.constants.Use;
import org.apache.axis.description.ServiceDesc;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.handlers.HandlerInfoChainFactory;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.providers.java.RPCProvider;
import org.apache.axis.utils.ClassUtils;
import org.apache.beehive.wsm.axis.AxisHook;
import org.apache.beehive.wsm.axis.ControlProvider;
import org.apache.beehive.wsm.model.BeehiveWsSOAPMessageHandlerInfo;
import org.apache.beehive.wsm.model.BeehiveWsTypeMetadata;
import org.apache.beehive.wsm.model.jsr181.Jsr181ObjectModelStore;
import org.w3c.dom.Element;
import org.apache.log4j.Logger;
/**
* ****************************************************************************
* A few annotation specific things added and lots of code copied from the
* JWSHandler class by
*
* @author Jonathan Colwell (jcolwell@bea.com) but most of the original code was
* written by:
* @author Glen Daniels (gdaniels@allaire.com)
* @author Doug Davis (dug@us.ibm.com)
* @author Sam Ruby (rubys@us.ibm.com) todo: fix directory
* structure/classloaders for output files
*/
public class AnnotatedWebServiceDeploymentHandler extends BasicHandler {
protected static Logger logger = Logger.getLogger(AnnotatedWebServiceDeploymentHandler.class);
protected Map<String, SOAPService> soapServices = new HashMap<String, SOAPService>();
/**
* @param mc
* @throws AxisFault
*/
public void invoke(MessageContext mc) throws AxisFault {
try {
SOAPService ss = getSOAPService(getWebServiceClass(mc));
if (null != ss) {
ss.setEngine(mc.getAxisEngine());
mc.setService(ss);
/*
* NOTE jcolwell@bea.com 2004-Oct-22 -- not sure why, but xsi
* types were still being sent even with literal Use. Forcing it
* to not send the types unless encoded.
*/
mc.setProperty(Call.SEND_TYPE_ATTR, new Boolean(Use.ENCODED
.equals(ss.getUse())));
// blow away the real path to bypass the regular JWSHandler
mc.removeProperty(Constants.MC_REALPATH);
}
} catch (Exception e) {
throw AxisFault.makeFault(e);
}
}
/**
* @param mc
* @throws AxisFault
*/
public void generateWSDL(MessageContext mc) throws AxisFault {
invoke(mc);
}
/**
* @param clazz
* @return SOAPService
* @throws Exception
*/
protected SOAPService getSOAPService(Class clazz) throws Exception {
SOAPService ss = null;
if (null != clazz) {
ss = soapServices.get(clazz.getName());
if (null == ss) {
ss = createSOAPService(Jsr181ObjectModelStore.load(clazz),
clazz);
}
}
return ss;
}
/**
* @param wsm
* @param cls
* @return SOAPService
* @throws Exception
*/
protected SOAPService createSOAPService(BeehiveWsTypeMetadata wsm, Class cls)
throws Exception {
SOAPService ss = null;
if (null != wsm) {
// HandlerHandler hh = new HandlerHandler(wsm);
// hh.init();
// // NOTE jcolwell@bea.com 2004-Nov-01 --
// // not calling ss.init() since ControlProvider won't do anything
// // with it and I don't want the HandlerHandler initialized twice.
// ss = new SOAPService(hh, new ControlProvider(), hh);
// create soap service without any handlers.
ss = new SOAPService(null, new ControlProvider(), null);
// Add jaxrpc handlers if there are any.
HandlerInfoChainFactory jaxrpcChain;
if (null != (jaxrpcChain = getJaxRPCHandlerChainFactory(wsm))) {
ss.setOption(Constants.ATTR_HANDLERINFOCHAIN, jaxrpcChain);
}
ss.setName(wsm.getWsName());
ss.setOption(RPCProvider.OPTION_CLASSNAME, cls.getName());
// Take the setting for the scope option from the handler
// parameter named "scope"
String scope = (String) getOption(RPCProvider.OPTION_SCOPE);
if (null == scope) {
scope = "Request";
}
ss.setOption(RPCProvider.OPTION_SCOPE, scope);
ServiceDesc sd = AxisHook.createServiceDesc(wsm, cls.getClassLoader());
ss.setServiceDescription(sd);
List allowedMethodNames = sd.getAllowedMethods();
Iterator allowIt = allowedMethodNames.iterator();
StringBuffer sb = new StringBuffer();
boolean firstPass = true;
while (allowIt.hasNext()) {
if (firstPass) {
sb.append(' ');
firstPass = false;
}
sb.append(((String) allowIt.next()));
}
ss.setOption(RPCProvider.OPTION_ALLOWEDMETHODS, sb.toString());
ss.setOption(RPCProvider.OPTION_WSDL_PORTTYPE, wsm.getWsName());
ss.setOption(RPCProvider.OPTION_WSDL_SERVICEPORT, wsm.getWsName());
ss.setOption(RPCProvider.OPTION_WSDL_SERVICEELEMENT, wsm
.getWsServiceName());
ss.setOption(RPCProvider.OPTION_WSDL_TARGETNAMESPACE, wsm
.getWsTargetNamespace());
ss.setStyle(sd.getStyle());
ss.setUse(sd.getUse());
soapServices.put(cls.getName(), ss);
}
return ss;
}
protected HandlerInfoChainFactory getJaxRPCHandlerChainFactory(
BeehiveWsTypeMetadata wsm) throws ClassNotFoundException {
HandlerInfoChainFactory res = null;
List< ? extends BeehiveWsSOAPMessageHandlerInfo> handlers = wsm
.getSoapHandlers();
if (handlers.size() > 0) { // there are handlers to install
ArrayList<HandlerInfo> infoList = new ArrayList<HandlerInfo>();
HashSet<String> roles = new HashSet<String>();
for (BeehiveWsSOAPMessageHandlerInfo handler : handlers) {
Class handlerClass = ClassUtils.forName(handler.getClassName());
QName[] handlerHeaders = handler.getHeaders().toArray(
new QName[0]);
infoList.add(new HandlerInfo(handlerClass, (Map) handler
.getParameterMap(), handlerHeaders));
roles.addAll(handler.getRoles());
}
res = new HandlerInfoChainFactory(infoList);
String[] roleArray = roles.toArray(new String[0]);
res.setRoles(roleArray);
}
return res;
}
/**
* @param mc
* @return web service Class
* @throws Exception
*/
protected Class getWebServiceClass(MessageContext mc) throws Exception {
// check message context
if (null == mc) {
throw new IllegalArgumentException("message context not set");
}
// retrieve & check relative path
String relativePath = mc.getStrProp(Constants.MC_RELATIVE_PATH);
if (null == relativePath) {
throw new Exception(
"relative path not set properly in message context");
}
// turn relative path into fq class name
final String JWS_EXTENSION = ".jws";
/*
if ((! relativePath.startsWith("/")) || (! relativePath.endsWith(JWS_EXTENSION))) {
throw new Exception ("invalid relative path: " + relativePath);
}
String className = relativePath.substring(1,
relativePath.length() - JWS_EXTENSION.length()).replaceAll("/",
".");
*/
if (! relativePath.startsWith("/")) {
throw new Exception ("invalid relative path: " + relativePath);
}
String className = null;
if (relativePath.endsWith(JWS_EXTENSION)) {
className = relativePath.substring(1, relativePath.length() - JWS_EXTENSION.length()).replaceAll("/", ".");
}
else {
className = relativePath.substring(1, relativePath.length()).replaceAll("/", ".");
}
// load class
if (logger.isDebugEnabled()) {
logger.debug("trying to load web service class: " + className);
}
Class clazz = Jsr181ObjectModelStore.loadWebServiceClass(className);
if (null == clazz) {
if (logger.isDebugEnabled()) {
logger.debug("failed to load web service class: " + className);
}
}
return clazz;
}
}