/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */
package org.jboss.webservice.server;

// $Id: ContextServlet.java,v 1.1.2.2 2005/03/02 14:32:32 tdiesler Exp $

import org.jboss.axis.AxisEngine;
import org.jboss.axis.AxisFault;
import org.jboss.axis.MessageContext;
import org.jboss.axis.handlers.soap.SOAPService;
import org.jboss.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * The servlet that that is associated with context /ws4ee
 *
 * It manages the service list and the 'Version' service
 *
 * @author Thomas.Diesler@jboss.org
 * @since 09-Feb-2005
 */
public class ContextServlet extends AbstractServlet
{
   // provide logging
   protected final Logger log = Logger.getLogger(ContextServlet.class);

   /** Denies access to the generic Axis way of accessing services
    *
    *    /context-root/services/ServiceName
    *
    * J2EE web services are deployed within their own context-root that may have authentication
    * requirements.
    */
   private boolean assertServiceAccess(HttpServletRequest req, HttpServletResponse res)
           throws IOException
   {
      String contextPath = req.getContextPath();
      String requestURI = req.getRequestURI();
      String pathInfo = req.getPathInfo();

      if (requestURI.startsWith(contextPath + "/services/") && "/Version".equals(pathInfo) == false)
      {
         reportTrouble(new IllegalAccessException(requestURI), res, res.getWriter());
         return false;
      }

      return true;
   }

   /**
    * Reject POST requests to '/ws4ee/services/someService'
    */
   public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
   {
      if (assertServiceAccess(req, res) == false)
         return;

      super.doPost(req, res);
   }

   /**
    * Process GET requests.
    */
   public void doGet(HttpServletRequest req, HttpServletResponse res)
           throws ServletException, IOException
   {
      if (assertServiceAccess(req, res) == false)
         return;

      String url = req.getRequestURL().toString();
      String queryString = req.getQueryString();
      log.debug("doGet: " + url + (queryString != null ? "?" + queryString : ""));

      PrintWriter writer = res.getWriter();
      try
      {
         AxisEngine engine = getEngine();

         // Get the SOAP servie
         String serviceName = getServiceName(req);
         SOAPService service = (serviceName != null ? engine.getService(serviceName) : null);

         boolean wsdlRequested = req.getParameter("wsdl") != null || req.getParameter("WSDL") != null;

         if (!wsdlRequested)
         {
            log.debug("Report available services");

            // If the user requested the servlet (i.e. /ws4ee/services)
            // with no service name, present the user with a list of deployed services to be helpful
            // Don't do this if we are doing WSDL or list.
            reportAvailableServices(res, writer, req);
            return;
         }

         if (service == null)
         {
            log.error("Cannot get axis service: " + serviceName);
            reportCantGetAxisService(req, res, writer);
            return;
         }

         // get message context w/ various properties set
         MessageContext msgContext = createMessageContext(engine, req, res);

         // we found the service, so we can set it in the msg context
         // whoever comes after, won't have to retry finding it
         if (service != null)
            msgContext.setTargetService(serviceName);

         String transportURL = getTransportURL(req, serviceName);
         if (transportURL != null)
         {
            msgContext.setProperty(MessageContext.TRANS_URL, transportURL);
            log.debug("Set transport.url=" + transportURL);
         }

         if (wsdlRequested)
         {
            String wsdlResource = req.getParameter("resource");
            if (wsdlResource != null)
            {
               log.debug("Process wsdl import request: " + wsdlResource);
               msgContext.setProperty(MessageContext.WSDLGEN_RESOURCE, wsdlResource);
            }
            else
            {
               log.debug("Process wsdl request");
            }

            processWsdlRequest(msgContext, res, writer);
            return;
         }

         // If nothing else was done previously
         log.debug("Report service info");
         reportServiceInfo(res, writer, service, serviceName);
      }
      catch (AxisFault fault)
      {
         reportTrouble(fault, res, writer);
      }
      catch (Exception e)
      {
         reportTrouble(e, res, writer);
      }
      finally
      {
         // Make sure the MessageContext is removed from the calling ThreadLocal
         AxisEngine.setCurrentMessageContext(null);
         writer.close();
      }
   }

   /**
    * Get the service name as it is known to Axis
    * <p/>
    * For JSE service endpoints it is obtained from the generated init parameter in web.xml
    */
   protected String getServiceName(HttpServletRequest req)
   {
      String serviceName = null;
      if (req.getRequestURI().equals(req.getContextPath() + "/services/Version"))
         serviceName = "Version";

      return serviceName;
   }
}