Java tutorial
/* * Copyright 2002-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.transport.http; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.axis.AxisEngine; import org.apache.axis.AxisFault; import org.apache.axis.AxisProperties; import org.apache.axis.EngineConfiguration; import org.apache.axis.components.logger.LogFactory; import org.apache.axis.configuration.EngineConfigurationFactoryFinder; import org.apache.axis.server.AxisServer; import org.apache.axis.utils.JavaUtils; import org.apache.commons.logging.Log; /** * Base class for servlets used in axis, has common methods * to get and save the engine to a common location, currently the * webapp's context, though some alternate persistence mechanism is always * possible. Also has a load counter shared by all servlets; tracks the * # of active http requests open to any of the subclasses. * @author Steve Loughran */ public class AxisServletBase extends HttpServlet { /** * per-instance cache of the axis server */ protected AxisServer axisServer = null; private static Log log = LogFactory.getLog(AxisServlet.class.getName()); private static boolean isDebug = false; /** * count number of service requests in progress */ private static int loadCounter = 0; /** * and a lock */ private static Object loadCounterLock = new Object(); /** * name of the axis engine to use in the servlet context */ protected static final String ATTR_AXIS_ENGINE = "AxisEngine"; /** * Cached path to our WEB-INF directory */ private String webInfPath = null; /** * Cached path to our "root" dir */ private String homeDir = null; /** * flag set to true for a 'production' server */ private boolean isDevelopment; /** * property name for a production server */ private static final String INIT_PROPERTY_DEVELOPMENT_SYSTEM = "axis.development.system"; /** * our initialize routine; subclasses should call this if they override it */ 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"); isDevelopment = JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_DEVELOPMENT_SYSTEM, null)); } /** * Destroy method is called when the servlet is going away. Pass this * down to the AxisEngine to let it clean up... But don't create the * engine if it hasn't already been created. * @todo Fixme for multiple servlets. * This has always been slightly broken * (the context's copy stayed around), but now we have extracted it into * a superclass it is blatantly broken. */ public void destroy() { super.destroy(); //if we have had anything to do with creating an axis server if (axisServer != null) { //then we lock it synchronized (axisServer) { if (axisServer != null) { //clean it up axisServer.cleanup(); //and erase our history of it axisServer = null; storeEngine(this, null); } } } } /** * get the engine for this servlet from cache or context * @return * @throws AxisFault */ public AxisServer getEngine() throws AxisFault { if (axisServer == null) axisServer = getEngine(this); return axisServer; } /** * This is a uniform method of initializing AxisServer in a servlet * context. * @todo add catch for not being able to cast the context attr to an * engine and reinit the engine if so. */ 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) { Map environment = getEngineEnvironment(servlet); // Obtain an AxisServer by using whatever AxisServerFactory is // registered. The default one will just use the provider we // passed in, and presumably JNDI ones will use the ServletContext // to figure out a JNDI name to look up. // // The point of doing this rather than just creating the server // manually with the provider above is that we will then support // configurations where the server instance is managed by the // container, and pre-registered in JNDI at deployment time. It // also means we put the standard configuration pattern in one // place. engine = AxisServer.getServer(environment); // attach the AxisServer with the current Servlet engine.setName(servlet.getServletName()); storeEngine(servlet, engine); } } if (isDebug) log.debug("Exit: getEngine()"); return engine; } /** * put the engine back in to the context. * @param context servlet context to use * @param engine reference to the engine. If null, the engine is removed */ private static void storeEngine(HttpServlet servlet, AxisServer engine) { ServletContext context = servlet.getServletContext(); String axisServletName = servlet.getServletName(); if (engine == null) { context.removeAttribute(axisServletName + ATTR_AXIS_ENGINE); // find if there is other AxisEngine in Context AxisServer server = (AxisServer) context.getAttribute(ATTR_AXIS_ENGINE); // no other AxisEngine in ServletContext if (server != null && servlet.getServletName().equals(server.getName())) { context.removeAttribute(ATTR_AXIS_ENGINE); } } else { if (context.getAttribute(ATTR_AXIS_ENGINE) == null) { // first Axis servlet to store its AxisEngine // use default name context.setAttribute(ATTR_AXIS_ENGINE, engine); } context.setAttribute(axisServletName + ATTR_AXIS_ENGINE, engine); } } /** * Get an engine from the servlet context; robust againt serialization * issues of hot-updated webapps. Remember than if a webapp is marked * as distributed, there is more than 1 servlet context, hence more than * one AxisEngine instance * @param servlet * @return the engine or null if either the engine couldnt be found or * the attribute wasnt of the right type */ private static AxisServer retrieveEngine(HttpServlet servlet) { Object contextObject = servlet.getServletContext() .getAttribute(servlet.getServletName() + ATTR_AXIS_ENGINE); if (contextObject == null) { // if AxisServer not found : // fall back to the "default" AxisEngine contextObject = servlet.getServletContext().getAttribute(ATTR_AXIS_ENGINE); } if (contextObject instanceof AxisServer) { AxisServer server = (AxisServer) contextObject; // if this is "our" Engine if (server != null && servlet.getServletName().equals(server.getName())) { return server; } return null; } else { return null; } } /** * extract information from the servlet configuration files * @param servlet * @return */ 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; } /** * get a count of the # of services running. This is only * ever an approximate number in a busy system * * @return The TotalServiceCount value */ public static int getLoadCounter() { return loadCounter; } /** * thread safe lock counter increment */ protected static void incLockCounter() { synchronized (loadCounterLock) { loadCounter++; } } /** * thread safe lock counter decrement */ protected static void decLockCounter() { synchronized (loadCounterLock) { loadCounter--; } } /** * subclass of service method that tracks entry count; calls the * parent's implementation to have the http method cracked and delegated * to the doGet, doPost method. * @param req request * @param resp response * @throws ServletException something went wrong * @throws IOException something different went wrong */ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { incLockCounter(); try { super.service(req, resp); } finally { decLockCounter(); } } /** * extract the base of our webapp from an inbound request * * @param request request containing http://foobar/axis/services/something * @return some URL like http://foobar:8080/axis/ */ protected String getWebappBase(HttpServletRequest request) { StringBuffer baseURL = new StringBuffer(128); baseURL.append(request.getScheme()); baseURL.append("://"); baseURL.append(request.getServerName()); if (request.getServerPort() != 80) { baseURL.append(":"); baseURL.append(request.getServerPort()); } baseURL.append(request.getContextPath()); return baseURL.toString(); } /** * what is the servlet context * @return get the context from the servlet config */ public ServletContext getServletContext() { return getServletConfig().getServletContext(); } /** * accessor to webinf * @return path to WEB-INF/ in the local filesystem */ protected String getWebInfPath() { return webInfPath; } /** * what is the root dir of the applet? * @return path of root dir */ protected String getHomeDir() { return homeDir; } /** * Retrieve option, in order of precedence: * (Managed) System property (see discovery.ManagedProperty), * servlet init param, context init param. * Use of system properties is discouraged in production environments, * as it overrides everything else. */ 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 engine = getEngine(this); if (value == null && engine != null) value = (String) engine.getOption(param); } catch (AxisFault axisFault) { } return (value != null) ? value : dephault; } /** * probe for the system being 'production' * @return true for a dev system. */ public boolean isDevelopment() { return isDevelopment; } }