1.服务部署:
1)即时发布
编写java类,去掉包名称,将.java文件类型改成jws。
通过浏览器打开url如:http://localhost:8888/axis/EchoHeaders.jws
点击“Click to see the WSDL”,即可查看所部署服务的WSDL描述文件
2)定制发布
通过deploy.wsdd部署,如:
<service name="AxisService" provider="java:RPC">
<parameter name="allowedMethods" value="*"/>
<parameter name="className" value="com.axis.service.AxisService"/>
</service>
2.源码解读:
1)初始化AxisEngine:
<servlet> <servlet-name>AxisServlet</servlet-name> <display-name>Apache-Axis Servlet</display-name> <servlet-class> org.apache.axis.transport.http.AxisServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>*.jws</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping>
即所有以jws结尾或者services路径的的URL均由AxisServlet进行处理。
AxisServlet的init方法:
public void init() throws javax.servlet.ServletException { //super.init()即执行父类AxisServletBase的init方法,完成AxisServer初始化工作 super.init(); ServletContext context = getServletConfig().getServletContext(); isDebug = log.isDebugEnabled(); if (isDebug) { log.debug("In servlet init"); } transportName = getOption(context, INIT_PROPERTY_TRANSPORT_NAME, HTTPTransport.DEFAULT_TRANSPORT_NAME); if (JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_USE_SECURITY, null))) { securityProvider = new ServletSecurityProvider(); } enableList = JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_ENABLE_LIST, null)); jwsClassDir = getOption(context, INIT_PROPERTY_JWS_CLASS_DIR, null); disableServicesList = JavaUtils.isTrue(getOption(context, INIT_PROPERTY_DISABLE_SERVICES_LIST, "false")); servicesPath = getOption(context, INIT_PROPERTY_SERVICES_PATH, "/services/"); if (jwsClassDir != null) { if (getHomeDir() != null) { jwsClassDir = getHomeDir() + jwsClassDir; } } else { jwsClassDir = getDefaultJWSClassDir(); } //初始化查询Handler,即wsdl对应的handler,用于wsdl文件生成 initQueryStringHandlers(); // Setup the service admin try { ServiceAdmin.setEngine(this.getEngine(), context.getServerInfo()); } catch (AxisFault af) { exceptionLog.info("Exception setting AxisEngine on ServiceAdmin " + af); } }
AxisServletBase.init():
public void init() throws javax.servlet.ServletException { ServletContext context = getServletConfig().getServletContext(); webInfPath = context.getRealPath("/WEB-INF"); homeDir = context.getRealPath("/"); isDebug = log.isDebugEnabled(); if(log.isDebugEnabled()) log.debug("In AxisServletBase init"); //触发AxisServer的初始化 isDevelopment= JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_DEVELOPMENT_SYSTEM, null)); }
AxisServer初始化工作由getOption触发
protected String getOption(ServletContext context, String param, String dephault) { String value = AxisProperties.getProperty(param); if (value == null) value = getInitParameter(param); if (value == null) value = context.getInitParameter(param); try { //初始化AxisServer AxisServer engine = getEngine(this); if (value == null && engine != null) value = (String) engine.getOption(param); } catch (AxisFault axisFault) { } return (value != null) ? value : dephault; }
初始化AxisServer:
public static AxisServer getEngine(HttpServlet servlet) throws AxisFault { AxisServer engine = null; if (isDebug) log.debug("Enter: getEngine()"); ServletContext context = servlet.getServletContext(); synchronized (context) { engine = retrieveEngine(servlet); if (engine == null) { //配置Engine环境 Map environment = getEngineEnvironment(servlet); //初始化AxisServer Engine engine = AxisServer.getServer(environment); engine.setName(servlet.getServletName()); //存储AxisServer Engine至上下文 storeEngine(servlet, engine); } } if (isDebug) log.debug("Exit: getEngine()"); return engine; }
首先从当前上下文中获取AxisServer Engine,如果返回为null,则进行初始化并存储至上下文中。
protected static Map getEngineEnvironment(HttpServlet servlet) { Map environment = new HashMap(); String attdir= servlet.getInitParameter(AxisEngine.ENV_ATTACHMENT_DIR); if (attdir != null) environment.put(AxisEngine.ENV_ATTACHMENT_DIR, attdir); ServletContext context = servlet.getServletContext(); environment.put(AxisEngine.ENV_SERVLET_CONTEXT, context); String webInfPath = context.getRealPath("/WEB-INF"); if (webInfPath != null) environment.put(AxisEngine.ENV_SERVLET_REALPATH, webInfPath + File.separator + "attachments"); EngineConfiguration config = EngineConfigurationFactoryFinder.newFactory(servlet) .getServerEngineConfig(); if (config != null) { environment.put(EngineConfiguration.PROPERTY_NAME, config); } return environment; }
EngineConfigurationFactoryFinder.newFactory(servlet)返回org.apache.axis.configuration.EngineConfigurationFactoryServlet工厂实例,并通过private static EngineConfiguration getServerEngineConfig(ServletConfig cfg)新建EngineConfiguration实现类:FileProvider对象(即server-config.wsdd的文件操作类)
AxisServer类getServer方法充当工厂方法,返回自身对象。但实际新建AxisServer Engine任务是委托AxisServerFactory工厂实例完成。
public static AxisServer getServer(Map environment) throws AxisFault { if (factory == null) { String factoryClassName = AxisProperties.getProperty("axis.ServerFactory"); if (factoryClassName != null) { try { Class factoryClass = ClassUtils.forName(factoryClassName); if (AxisServerFactory.class.isAssignableFrom(factoryClass)) factory = (AxisServerFactory)factoryClass.newInstance(); } catch (Exception e) { // If something goes wrong here, should we just fall // through and use the default one? log.error(Messages.getMessage("exception00"), e); } } if (factory == null) { //通过默认工厂新建Server Engine factory = new DefaultAxisServerFactory(); } } return factory.getServer(environment); }
DefaultAxisServerFactory类getServer方法:
public AxisServer getServer(Map environment) throws AxisFault { log.debug("Enter: DefaultAxisServerFactory::getServer"); AxisServer ret = createServer(environment); if (ret != null) { if (environment != null) { ret.setOptionDefault(AxisEngine.PROP_ATTACHMENT_DIR, (String)environment.get(AxisEngine.ENV_ATTACHMENT_DIR)); ret.setOptionDefault(AxisEngine.PROP_ATTACHMENT_DIR, (String)environment.get(AxisEngine.ENV_SERVLET_REALPATH)); } String attachmentsdir = (String)ret.getOption(AxisEngine.PROP_ATTACHMENT_DIR); if (attachmentsdir != null) { File attdirFile = new File(attachmentsdir); if (!attdirFile.isDirectory()) { attdirFile.mkdirs(); } } } log.debug("Exit: DefaultAxisServerFactory::getServer"); return ret; } private static AxisServer createServer(Map environment) { //从Map环境中取出FileProvider对象 EngineConfiguration config = getEngineConfiguration(environment); //通过AxisServer(EngineConfiguration config)构造函数新建对象 return (config == null) ? new AxisServer() : new AxisServer(config); }
public AxisServer(EngineConfiguration config) { //Engine的初始化由父类AxisEngine完成 super(config); // 服务端默认是保存配置 setShouldSaveConfig(true); }
public void init() { if (log.isDebugEnabled()) { log.debug("Enter: AxisEngine::init"); } try { //通过FileProvider类配置Engine config.configureEngine(this); } catch (Exception e) { throw new InternalException(e); } setOptionDefault(PROP_ATTACHMENT_IMPLEMENTATION, AxisProperties.getProperty("axis." + PROP_ATTACHMENT_IMPLEMENTATION )); setOptionDefault(PROP_ATTACHMENT_IMPLEMENTATION, DEFAULT_ATTACHMENT_IMPL); final Object dotnet = getOption(PROP_DOTNET_SOAPENC_FIX); if (JavaUtils.isTrue(dotnet)) { TypeMappingImpl.dotnet_soapenc_bugfix = true; } if (log.isDebugEnabled()) { log.debug("Exit: AxisEngine::init"); } }
public void configureEngine(AxisEngine engine) throws ConfigurationException { try { if (getInputStream() == null) { try { setInputStream(new FileInputStream(configFile)); } catch (Exception e) { if (searchClasspath) setInputStream(ClassUtils.getResourceAsStream(engine.getClass(), filename, true)); } } if (getInputStream() == null) { throw new ConfigurationException( Messages.getMessage("noConfigFile")); } //初始化deployment WSDDDocument doc = new WSDDDocument(XMLUtils. newDocument(getInputStream())); deployment = doc.getDeployment(); //deployment持有Engine引用 deployment.configureEngine(engine); //刷新global配置选项 engine.refreshGlobalOptions(); setInputStream(null); } catch (Exception e) { throw new ConfigurationException(e); } }
configureEngine完成的任务主要是解析server-config.wsdd服务配置。将配置文件中的各种属性(handler、globalConfiguration、service、transport……)缓存至WSDDDeployment类中。刷新global配置选项即将server-config.wsdd配置文件中globalConfiguration节点中的parameter属性集合由AxisEngine持有。
以上完成了所有初始化工作。
2)通过url打开服务:
在浏览器中打开
http://localhost:8888/axis/EchoHeaders.jws
AxisServlet的doGet方法:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (isDebug) { log.debug("Enter: doGet()"); } PrintWriter writer = new FilterPrintWriter(response); try { AxisEngine engine = getEngine(); ServletContext servletContext = getServletConfig().getServletContext(); String pathInfo = request.getPathInfo(); String realpath = servletContext.getRealPath(request.getServletPath()); if (realpath == null) { realpath = request.getServletPath(); } boolean isJWSPage = request.getRequestURI().endsWith(".jws"); if (isJWSPage) { pathInfo = request.getServletPath(); } //判断是否存在查询。即server-config.wsdd的transport节点 //配置的parameter查询条件(list/method/wsdl) //如url:http://localhost:8888/axis/EchoHeaders.jws?wsdl //如url:http://localhost:8888/services/AxisService?wsdl //这样doGet直接生成wsdl描述信息至浏览器端 if (processQuery(request, response, writer) == true) { return; } boolean hasNoPath = (pathInfo == null || pathInfo.equals("")); if (!disableServicesList) { if(hasNoPath) { reportAvailableServices(response, writer, request); } else if (realpath != null) { MessageContext msgContext = createMessageContext(engine,request, response); String url = HttpUtils.getRequestURL(request).toString(); msgContext.setProperty(MessageContext.TRANS_URL, url); String serviceName; if (pathInfo.startsWith("/")) { serviceName = pathInfo.substring(1); } else { serviceName = pathInfo; } //从WSDDDeployment的services缓存中取service SOAPService s = engine.getService(serviceName); if (s == null) { if (isJWSPage) { //生成Click to see the WSDL连接的页面 reportCantGetJWSService(request, response, writer); } else { reportCantGetAxisService(request, response, writer); } } else { reportServiceInfo(response, writer, s, serviceName); } } } else { response.setContentType("text/html; charset=utf-8"); writer.println("<html><h1>Axis HTTP Servlet</h1>"); writer.println(Messages.getMessage("reachedServlet00")); writer.println("<p>" + Messages.getMessage("transportName00", "<b>" + transportName + "</b>")); writer.println("</html>"); } } catch (AxisFault fault) { reportTroubleInGet(fault, response, writer); } catch (Exception e) { reportTroubleInGet(e, response, writer); } finally { writer.close(); if (isDebug) { log.debug("Exit: doGet()"); } } }
如果是JWS服务,在返回的页面中,点击“Click to see the WSDL”,则产生服务描述XML信息。
该链接对应的url为:http://localhost:8888/axis/EchoHeaders.jws?wsdl
即带有查询条件的url。
上面代码注释中已说明此类url由processQuery(request, response, writer)处理
private boolean processQuery(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) throws AxisFault { String path = request.getServletPath(); String queryString = request.getQueryString(); String serviceName; AxisEngine engine = getEngine(); Iterator i = this.transport.getOptions().keySet().iterator(); if (queryString == null) { return false; } String servletURI = request.getContextPath() + path; String reqURI = request.getRequestURI(); // chop off '/'. if (servletURI.length() + 1 < reqURI.length()) { serviceName = reqURI.substring(servletURI.length() + 1); } else { serviceName = ""; } while (i.hasNext() == true) { String queryHandler = (String) i.next(); if (queryHandler.startsWith("qs.") == true) { String handlerName = queryHandler.substring (queryHandler.indexOf(".") + 1). toLowerCase(); int length = 0; boolean firstParamFound = false; while (firstParamFound == false && length < queryString.length()) { char ch = queryString.charAt(length++); if (ch == '&' || ch == '=') { firstParamFound = true; --length; } } if (length < queryString.length()) { queryString = queryString.substring(0, length); } if (queryString.toLowerCase().equals(handlerName) == true) { if (this.transport.getOption(queryHandler).equals("")) { return false; } try { MessageContext msgContext = createMessageContext(engine,request, response); Class plugin = Class.forName((String)this.transport.getOption(queryHandler)); Method pluginMethod = plugin.getDeclaredMethod("invoke",new Class[] {msgContext.getClass()}); String url = HttpUtils.getRequestURL(request).toString(); msgContext.setProperty(MessageContext.TRANS_URL, url); msgContext.setProperty(HTTPConstants. PLUGIN_SERVICE_NAME, serviceName); msgContext.setProperty(HTTPConstants.PLUGIN_NAME,handlerName); msgContext.setProperty(HTTPConstants. PLUGIN_IS_DEVELOPMENT, new Boolean(isDevelopment())); msgContext.setProperty(HTTPConstants.PLUGIN_ENABLE_LIST,new Boolean(enableList)); msgContext.setProperty(HTTPConstants.PLUGIN_ENGINE,engine); msgContext.setProperty(HTTPConstants.PLUGIN_WRITER,writer); msgContext.setProperty(HTTPConstants.PLUGIN_LOG, log); msgContext.setProperty(HTTPConstants. PLUGIN_EXCEPTION_LOG,exceptionLog); pluginMethod.invoke(plugin.newInstance(), new Object[] {msgContext}); writer.close(); return true; } catch (InvocationTargetException ie) { reportTroubleInGet(ie.getTargetException(), response,writer); return true; } catch (Exception e) { reportTroubleInGet(e, response, writer); return true; } } } } return false; }
以上代码主要任务是根据查询条件字符串(即wsdl),通过与server-config.wsdd中transport节点parameter属性匹配,查找对应的handler(即:org.apache.axis.transport.http.QSWSDLHandler)。并通过反射执行QSWSDLHandler的invoke方法
QSWSDLHandler:
public void invoke(MessageContext msgContext) throws AxisFault { // Obtain objects relevant to the task at hand from the provided // MessageContext's bag. configureFromContext(msgContext); AxisServer engine = (AxisServer) msgContext.getProperty (HTTPConstants.PLUGIN_ENGINE); PrintWriter writer = (PrintWriter) msgContext.getProperty (HTTPConstants.PLUGIN_WRITER); HttpServletResponse response = (HttpServletResponse) msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE); try { //生成WSDL服务描述信息 engine.generateWSDL(msgContext); Document wsdlDoc = (Document) msgContext.getProperty("WSDL"); if (wsdlDoc != null) { try { updateSoapAddressLocationURLs(wsdlDoc, msgContext); } catch (RuntimeException re) { log.warn( "Failed to update soap:address location URL(s) in WSDL.", re); } response.setContentType( "text/xml; charset=" + XMLUtils.getEncoding().toLowerCase()); //将描述信息XML通过writer输出至浏览器端 reportWSDL(wsdlDoc, writer); } else { if (log.isDebugEnabled()) { log.debug("processWsdlRequest: failed to create WSDL"); } reportNoWSDL(response, writer, "noWSDL02", null); } } catch (AxisFault axisFault) { //the no-service fault is mapped to a no-wsdl error if (axisFault.getFaultCode().equals (Constants.QNAME_NO_SERVICE_FAULT_CODE)) { //which we log processAxisFault(axisFault); //then report under a 404 error response.setStatus(HttpURLConnection.HTTP_NOT_FOUND); reportNoWSDL(response, writer, "noWSDL01", axisFault); } else { //all other faults get thrown throw axisFault; } } }
AxisEngine的generateWSDL方法:
public void generateWSDL(MessageContext msgContext) throws AxisFault { if (log.isDebugEnabled()) { log.debug("Enter: AxisServer::generateWSDL"); } if (!isRunning()) { throw new AxisFault("Server.disabled", Messages.getMessage("serverDisabled00"), null, null); } String hName = null ; Handler h = null ; // save previous context MessageContext previousContext = getCurrentMessageContext(); try { // set active context setCurrentMessageContext(msgContext); hName = msgContext.getStrProp( MessageContext.ENGINE_HANDLER ); if ( hName != null ) { if ( (h = getHandler(hName)) == null ) { ClassLoader cl = msgContext.getClassLoader(); try { log.debug( Messages.getMessage("tryingLoad00", hName) ); Class cls = ClassUtils.forName(hName, true, cl); h = (Handler) cls.newInstance(); } catch( Exception e ) { throw new AxisFault( "Server.error", Messages.getMessage("noHandler00", hName), null, null ); } } h.generateWSDL(msgContext); } else { hName = msgContext.getStrProp(MessageContext.TRANSPORT); if ( hName != null ) { if ((h = hr.find( hName )) != null ) { h.generateWSDL(msgContext); } else { log.error(Messages.getMessage("noTransport02", hName)); } } else { defaultTransport.generateWSDL(msgContext); } hName = msgContext.getTransportName(); SimpleTargetedChain transportChain = null; if ( hName != null && (h = getTransport( hName )) != null ) { if (h instanceof SimpleTargetedChain) { transportChain = (SimpleTargetedChain)h; h = transportChain.getRequestHandler(); if (h != null) { h.generateWSDL(msgContext); } } } if ((h = getGlobalRequest()) != null ) h.generateWSDL(msgContext); h = msgContext.getService(); if (h == null) { Message rm = msgContext.getRequestMessage(); if (rm != null) { rm.getSOAPEnvelope().getFirstBody(); h = msgContext.getService(); } if (h == null) { …… } } h.generateWSDL(msgContext); if ((h = getGlobalResponse()) != null ) h.generateWSDL(msgContext); if (transportChain != null) { h = transportChain.getResponseHandler(); if (h != null) { h.generateWSDL(msgContext); } } } } catch (AxisFault e) { throw e; } catch(Exception e) { throw AxisFault.makeFault(e); } finally { setCurrentMessageContext(previousContext); } }
以上代码主要将生成wsdl任务交给server-config.wsdd所配置的一系列Handler,其执行顺序为
transport【requestFlow】---->globalConfiguration【requestFlow】---->service【requestFlow】---->service【responseFlow】---->globalConfiguration【responseFlow】---->transport【responseFlow】
针对jws的服务通过JWSHandler处理
org.apache.axis.handlers.JWSHandler:
public void generateWSDL(MessageContext msgContext) throws AxisFault { try { setupService(msgContext); } catch (Exception e) { log.error( Messages.getMessage("exception00"), e ); throw AxisFault.makeFault(e); } } protected void setupService(MessageContext msgContext) throws Exception { // FORCE the targetService to be JWS if the URL is right. String realpath = msgContext.getStrProp(Constants.MC_REALPATH); String extension = (String)getOption(OPTION_JWS_FILE_EXTENSION); if (extension == null) extension = DEFAULT_JWS_FILE_EXTENSION; if ((realpath!=null) && (realpath.endsWith(extension))) { /* Grab the *.jws filename from the context - should have been */ /* placed there by another handler (ie. HTTPActionHandler) */ /***************************************************************/ String jwsFile = realpath; String rel = msgContext.getStrProp(Constants.MC_RELATIVE_PATH); // Check for file existance, report error with // relative path to avoid giving out directory info. File f2 = new File( jwsFile ); if (!f2.exists()) { throw new FileNotFoundException(rel); } if (rel.charAt(0) == '/') { rel = rel.substring(1); } int lastSlash = rel.lastIndexOf('/'); String dir = null; if (lastSlash > 0) { dir = rel.substring(0, lastSlash); } String file = rel.substring(lastSlash + 1); String outdir = msgContext.getStrProp( Constants.MC_JWS_CLASSDIR ); if ( outdir == null ) outdir = "." ; // Build matching directory structure under the output // directory. In other words, if we have: // /webroot/jws1/Foo.jws // // That will be compiled to: // .../jwsOutputDirectory/jws1/Foo.class if (dir != null) { outdir = outdir + File.separator + dir; } // Confirm output directory exists. If not, create it IF we're // allowed to. // !!! TODO: add a switch to control this. File outDirectory = new File(outdir); if (!outDirectory.exists()) { outDirectory.mkdirs(); } if (log.isDebugEnabled()) log.debug("jwsFile: " + jwsFile ); String jFile = outdir + File.separator + file.substring(0, file.length()-extension.length()+1) + "java" ; String cFile = outdir + File.separator + file.substring(0, file.length()-extension.length()+1) + "class" ; if (log.isDebugEnabled()) { log.debug("jFile: " + jFile ); log.debug("cFile: " + cFile ); log.debug("outdir: " + outdir); } File f1 = new File( cFile ); /* Get the class */ /*****************/ String clsName = null ; //clsName = msgContext.getStrProp(Constants.MC_RELATIVE_PATH); if ( clsName == null ) clsName = f2.getName(); if ( clsName != null && clsName.charAt(0) == '/' ) clsName = clsName.substring(1); clsName = clsName.substring( 0, clsName.length()-extension.length() ); clsName = clsName.replace('/', '.'); if (log.isDebugEnabled()) log.debug("ClsName: " + clsName ); /* Check to see if we need to recompile */ /****************************************/ if ( !f1.exists() || f2.lastModified() > f1.lastModified() ) { /* If the class file doesn't exist, or it's older than the */ /* java file then recompile the java file. */ /* Start by copying the *.jws file to *.java */ /***********************************************************/ log.debug(Messages.getMessage("compiling00", jwsFile) ); log.debug(Messages.getMessage("copy00", jwsFile, jFile) ); FileReader fr = new FileReader( jwsFile ); FileWriter fw = new FileWriter( jFile ); char[] buf = new char[4096]; int rc ; while ( (rc = fr.read( buf, 0, 4095)) >= 0 ) fw.write( buf, 0, rc ); fw.close(); fr.close(); /* Now run javac on the *.java file */ /************************************/ log.debug("javac " + jFile ); // Process proc = rt.exec( "javac " + jFile ); // proc.waitFor(); //获取编译器(默认:sun.tools.javac.Main,com.sun.tools.javac.main.Main) Compiler compiler = CompilerFactory.getCompiler(); compiler.setClasspath(ClasspathUtils.getDefaultClasspath(msgContext)); compiler.setDestination(outdir); compiler.addFile(jFile); boolean result = compiler.compile(); /* Delete the temporary *.java file and check return code */ /**********************************************************/ (new File(jFile)).delete(); if ( !result ) { /* Delete the *class file - sometimes it gets created even */ /* when there are errors - so erase it so it doesn't */ /* confuse us. */ /***********************************************************/ (new File(cFile)).delete(); Document doc = XMLUtils.newDocument(); Element root = doc.createElementNS("", "Errors"); StringBuffer message = new StringBuffer("Error compiling "); message.append(jFile); message.append(":\n"); List errors = compiler.getErrors(); int count = errors.size(); for (int i = 0; i < count; i++) { CompilerError error = (CompilerError) errors.get(i); if (i > 0) message.append("\n"); message.append("Line "); message.append(error.getStartLine()); message.append(", column "); message.append(error.getStartColumn()); message.append(": "); message.append(error.getMessage()); } root.appendChild( doc.createTextNode( message.toString() ) ); throw new AxisFault( "Server.compileError", Messages.getMessage("badCompile00", jFile), null, new Element[] { root } ); } ClassUtils.removeClassLoader( clsName ); // And clean out the cached service. soapServices.remove(clsName); } ClassLoader cl = ClassUtils.getClassLoader(clsName); if (cl == null) { cl = new JWSClassLoader(clsName, msgContext.getClassLoader(), cFile); } msgContext.setClassLoader(cl); /* Create a new RPCProvider - this will be the "service" */ /* that we invoke. */ /******************************************************************/ // Cache the rpc service created to handle the class. The cache // is based on class name, so only one .jws/.jwr class can be active // in the system at a time. SOAPService rpc = (SOAPService)soapServices.get(clsName); if (rpc == null) { rpc = new SOAPService(new RPCProvider()); rpc.setName(clsName); rpc.setOption(RPCProvider.OPTION_CLASSNAME, clsName ); rpc.setEngine(msgContext.getAxisEngine()); // Support specification of "allowedMethods" as a parameter. String allowed = (String)getOption(RPCProvider.OPTION_ALLOWEDMETHODS); if (allowed == null) allowed = "*"; rpc.setOption(RPCProvider.OPTION_ALLOWEDMETHODS, allowed); // Take the setting for the scope option from the handler // parameter named "scope" String scope = (String)getOption(RPCProvider.OPTION_SCOPE); if (scope == null) scope = Scope.DEFAULT.getName(); rpc.setOption(RPCProvider.OPTION_SCOPE, scope); rpc.getInitializedServiceDesc(msgContext); soapServices.put(clsName, rpc); } // Set engine, which hooks up type mappings. rpc.setEngine(msgContext.getAxisEngine()); rpc.init(); // ?? // OK, this is now the destination service! msgContext.setService( rpc ); } if (log.isDebugEnabled()) { log.debug("Exit: JWSHandler::invoke"); } }
以上代码主要完成将jws转换成java文件,并临时存放至jwsClasses目录中,再通过jdk中的编译器sun.tools.javac.Main、com.sun.tools.javac.main.Main对java文件进行编译,将编译后的class文件存放至jwsClasses目录中,删除临时java文件,并将生成的class二进制文件加载至类加载器中。
rpc = new SOAPService(new RPCProvider());
增加Handler实例RPCProvider(继承BasicProvider)到当前handler链中
BasicProvider generateWSDL:
public void generateWSDL(MessageContext msgContext) throws AxisFault { if (log.isDebugEnabled()) log.debug("Enter: BasicProvider::generateWSDL (" + this +")"); SOAPService service = msgContext.getService(); ServiceDesc serviceDesc = service.getInitializedServiceDesc(msgContext); try { // Location URL is whatever is explicitly set in the MC String locationUrl = msgContext.getStrProp(MessageContext.WSDLGEN_SERV_LOC_URL); if (locationUrl == null) { // If nothing, try what's explicitly set in the ServiceDesc locationUrl = serviceDesc.getEndpointURL(); } if (locationUrl == null) { // If nothing, use the actual transport URL locationUrl = msgContext.getStrProp(MessageContext.TRANS_URL); } // Interface namespace is whatever is explicitly set String interfaceNamespace = msgContext.getStrProp(MessageContext.WSDLGEN_INTFNAMESPACE); if (interfaceNamespace == null) { // If nothing, use the default namespace of the ServiceDesc interfaceNamespace = serviceDesc.getDefaultNamespace(); } if (interfaceNamespace == null) { // If nothing still, use the location URL determined above interfaceNamespace = locationUrl; } Emitter emitter = new Emitter(); String alias = (String) service.getOption("alias"); if (alias != null) emitter.setServiceElementName(alias); // Set style/use emitter.setStyle(serviceDesc.getStyle()); emitter.setUse(serviceDesc.getUse()); if (serviceDesc instanceof JavaServiceDesc) { emitter.setClsSmart(((JavaServiceDesc)serviceDesc).getImplClass(), locationUrl); } // If a wsdl target namespace was provided, use the targetNamespace. // Otherwise use the interfaceNamespace constructed above. String targetNamespace = (String) service.getOption(OPTION_WSDL_TARGETNAMESPACE); if (targetNamespace == null || targetNamespace.length() == 0) { targetNamespace = interfaceNamespace; } emitter.setIntfNamespace(targetNamespace); emitter.setLocationUrl(locationUrl); emitter.setServiceDesc(serviceDesc); emitter.setTypeMappingRegistry(msgContext.getTypeMappingRegistry()); String wsdlPortType = (String) service.getOption(OPTION_WSDL_PORTTYPE); String wsdlServiceElement = (String) service.getOption(OPTION_WSDL_SERVICEELEMENT); String wsdlServicePort = (String) service.getOption(OPTION_WSDL_SERVICEPORT); String wsdlInputSchema = (String) service.getOption(OPTION_WSDL_INPUTSCHEMA); String wsdlSoapActinMode = (String) service.getOption(OPTION_WSDL_SOAPACTION_MODE); String extraClasses = (String) service.getOption(OPTION_EXTRACLASSES); if (wsdlPortType != null && wsdlPortType.length() > 0) { emitter.setPortTypeName(wsdlPortType); } if (wsdlServiceElement != null && wsdlServiceElement.length() > 0) { emitter.setServiceElementName(wsdlServiceElement); } if (wsdlServicePort != null && wsdlServicePort.length() > 0) { emitter.setServicePortName(wsdlServicePort); } if (wsdlInputSchema != null && wsdlInputSchema.length() > 0) { emitter.setInputSchema(wsdlInputSchema); } if (wsdlSoapActinMode != null && wsdlSoapActinMode.length() > 0) { emitter.setSoapAction(wsdlSoapActinMode); } if (extraClasses != null && extraClasses.length() > 0) { emitter.setExtraClasses(extraClasses); } if (msgContext.isPropertyTrue(AxisEngine.PROP_EMIT_ALL_TYPES)) { emitter.setEmitAllTypes(true); } Document doc = emitter.emit(Emitter.MODE_ALL); msgContext.setProperty("WSDL", doc); } catch (NoClassDefFoundError e) { entLog.info(Messages.getMessage("toAxisFault00"), e); throw new AxisFault(e.toString(), e); } catch (Exception e) { entLog.info(Messages.getMessage("toAxisFault00"), e); throw AxisFault.makeFault(e); } if (log.isDebugEnabled()) log.debug("Exit: BasicProvider::generateWSDL (" + this +")"); }
由于RPCProvider添加至handler链中,故也需完成generateWSDL任务。该任务由父类
BasicProvider完成。实际生成WSDL的任务委托至Emitter类处理
至此,整个服务部署以及WSDL描述算是梳理完毕。