Java tutorial
/* * 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. */ package org.apache.axis.handlers; import org.apache.axis.AxisFault; import org.apache.axis.Constants; import org.apache.axis.MessageContext; import org.apache.axis.components.compiler.Compiler; import org.apache.axis.components.compiler.CompilerError; import org.apache.axis.components.compiler.CompilerFactory; import org.apache.axis.components.logger.LogFactory; import org.apache.axis.constants.Scope; import org.apache.axis.handlers.soap.SOAPService; import org.apache.axis.providers.java.RPCProvider; import org.apache.axis.utils.ClassUtils; import org.apache.axis.utils.ClasspathUtils; import org.apache.axis.utils.JWSClassLoader; import org.apache.axis.utils.Messages; import org.apache.axis.utils.XMLUtils; import org.apache.commons.logging.Log; import org.w3c.dom.Document; import org.w3c.dom.Element; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.util.HashMap; import java.util.List; /** A <code>JWSHandler</code> sets the target service and JWS filename * in the context depending on the JWS configuration and the target URL. * * @author Glen Daniels (gdaniels@allaire.com) * @author Doug Davis (dug@us.ibm.com) * @author Sam Ruby (rubys@us.ibm.com) */ public class JWSHandler extends BasicHandler { protected static Log log = LogFactory.getLog(JWSHandler.class.getName()); public final String OPTION_JWS_FILE_EXTENSION = "extension"; public final String DEFAULT_JWS_FILE_EXTENSION = Constants.JWS_DEFAULT_FILE_EXTENSION; protected static HashMap soapServices = new HashMap(); /** * Just set up the service, the inner service will do the rest... */ public void invoke(MessageContext msgContext) throws AxisFault { if (log.isDebugEnabled()) { log.debug("Enter: JWSHandler::invoke"); } try { setupService(msgContext); } catch (Exception e) { log.error(Messages.getMessage("exception00"), e); throw AxisFault.makeFault(e); } } /** * If our path ends in the right file extension (*.jws), handle all the * work necessary to compile the source file if it needs it, and set * up the "proxy" RPC service surrounding it as the MessageContext's * active service. * */ 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(); 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"); } } public void generateWSDL(MessageContext msgContext) throws AxisFault { try { setupService(msgContext); } catch (Exception e) { log.error(Messages.getMessage("exception00"), e); throw AxisFault.makeFault(e); } } }