/*
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 * 
 * Created on Feb 26, 2004
 */
package org.jboss.net.axis.server;

import java.util.ArrayList;
import java.util.StringTokenizer;

import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.handlers.BasicHandler;

/**
 * <dl>
 * <dt><b>Title: </b><dd>Transport Authorization Handler</dd>
 * <p>
 * <dt><b>Description: </b><dd>This handler allows or denies access to a service based upon the transport the request
 * came in on. The allowed transports are configured either by the allowedTransports or 
 * deniedTransports property. <br>
 * The Transport Authorization Handler can be configured using the JBoss.Net xDoclet module:
 * <pre>
 *  * jboss-net.web-service
 *  *      urn="SomeService"
 *  *      allowed-transports="http,mail"
 * </pre><br>
 * or:
 * <pre>
 *  * jboss-net.web-service
 *  *      urn="SomeService"
 *  *      denied-transports="mail"
 * </pre><br>
 * Typically only allowed-transports or denied-transports would be defined. If both are defined, first the transport
 * is checked against the allowed-transports and if it exists there, it is checked against the list of 
 * denied-transports. A transport that is in both lists will be denied.
 * </dd>
 * </dl>
 * @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a>
 * @version $Revision: 1.2.6.1 $
 */
public class TransportAuthorizationHandler extends BasicHandler
{
   public static final String ALLOWED_TRANSPORTS = "allowedTransports";
   public static final String DENIED_TRANSPORTS = "deniedTransports";

   protected ArrayList transportsAllow;
   protected ArrayList transportsDeny;

   public void init()
   {
      String allow = (String) getOption(ALLOWED_TRANSPORTS);
      String deny = (String) getOption(DENIED_TRANSPORTS);

      if (allow != null && !"*".equals(allow))
      {
         transportsAllow = new ArrayList();
         StringTokenizer t = new StringTokenizer(allow, ",");
         while (t.hasMoreTokens())
         {
            transportsAllow.add(t.nextToken().trim());
         }
         // if any transport is * then we allow all transports
         if (transportsAllow.contains("*"))
         {
            transportsAllow = null;
         }
      }

      if (deny != null && !"*".equals(deny))
      {
         transportsDeny = new ArrayList();
         StringTokenizer t = new StringTokenizer(deny, ",");
         while (t.hasMoreTokens())
         {
            transportsDeny.add(t.nextToken().trim());
         }
      }
   }

   public void invoke(MessageContext mc) throws AxisFault
   {
      String transport = mc.getTransportName().trim();
      boolean isTransportAuthorized = false;

      if (transportsAllow != null)
      {
         if (transportsAllow.contains(transport))
         {
            isTransportAuthorized = true;
         }
      }
      else
      {
         isTransportAuthorized = true;
      }

      if (transportsDeny != null)
      {
         if (transportsDeny.contains(transport))
            isTransportAuthorized = false;
         else
            isTransportAuthorized = true;
      }

      if (!isTransportAuthorized)
      {
         // we already know what our method is, but since we are going to deny access from this transport, 
         // we will throw a fault that makes it look like the operation doesn't even exist.
         OperationDesc op = mc.getOperation();
         String method = op != null ? op.getName() : "";
         throw new AxisFault("No Such Operation " + method);
      }

   }

}
