You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wsrf-dev@ws.apache.org by sc...@apache.org on 2005/03/01 16:43:24 UTC

svn commit: r155793 - in incubator/apollo/trunk/src: java/org/apache/ws/util/test/ java/org/apache/ws/util/test/axis/ test/org/apache/ws/util/

Author: scamp
Date: Tue Mar  1 07:43:22 2005
New Revision: 155793

URL: http://svn.apache.org/viewcvs?view=rev&rev=155793
Log: (empty)


Added:
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractAxisTestCase.java
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractMultipleAxisTestCase.java
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractNoAxisTestCase.java
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractOneAxisTestCase.java
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisServer.java
    incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisWorker.java
Removed:
    incubator/apollo/trunk/src/test/org/apache/ws/util/AbstractAxisTestCase.java
    incubator/apollo/trunk/src/test/org/apache/ws/util/AbstractMultipleAxisTestCase.java
    incubator/apollo/trunk/src/test/org/apache/ws/util/AbstractNoAxisTestCase.java
    incubator/apollo/trunk/src/test/org/apache/ws/util/AbstractOneAxisTestCase.java
    incubator/apollo/trunk/src/test/org/apache/ws/util/NotSoSimpleAxisServer.java
    incubator/apollo/trunk/src/test/org/apache/ws/util/NotSoSimpleAxisWorker.java

Added: incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractAxisTestCase.java
URL: http://svn.apache.org/viewcvs/incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractAxisTestCase.java?view=auto&rev=155793
==============================================================================
--- incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractAxisTestCase.java (added)
+++ incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractAxisTestCase.java Tue Mar  1 07:43:22 2005
@@ -0,0 +1,251 @@
+/*=============================================================================*
+ *  Copyright 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.ws.util.test.axis;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+import org.apache.ws.util.rpc.JaxRpcConstants;
+import org.apache.ws.util.soap.SaajConstants;
+import org.apache.axis.configuration.FileProvider;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.URL;
+
+/**
+ * Provides some conviencence functionality for easier testing of web services.
+ * Methods provided by this JUnit test case superclass will allow an embedded
+ * Axis server to be started and stopped.
+ *
+ * @author mazz
+ */
+public abstract class AbstractAxisTestCase
+   extends TestCase
+{
+   /**
+    * This constant is used for enabling/disabling the use of the embedded axis server.
+    */
+   public boolean RUN_AXIS_SERVER = true;  
+
+   private static final int ANY_FREE_PORT = 0;
+
+   /*
+    * Make sure JAX-RPC and SAAJ factories all are set to Axis' impls.
+    */
+   static
+   {
+      System.setProperty( JaxRpcConstants.SYSPROP_SERVICE_FACTORY, JaxRpcConstants.IMPL_SERVICE_FACTORY_AXIS );
+      System.setProperty( SaajConstants.SYSPROP_SOAP_FACTORY, SaajConstants.IMPL_SOAP_FACTORY_AXIS );
+      System.setProperty( SaajConstants.SYSPROP_MESSAGE_FACTORY, SaajConstants.IMPL_MESSAGE_FACTORY_AXIS );
+      System.setProperty( SaajConstants.SYSPROP_SOAP_CONNECTION_FACTORY,
+                          SaajConstants.IMPL_SOAP_CONNECTION_FACTORY_AXIS );
+      System.setProperty( SaajConstants.SYSPROP_SOAP_ELEMENT_FACTORY, SaajConstants.IMPL_SOAP_ELEMENT_FACTORY_AXIS );
+   }
+
+   /**
+    * the embedded Axis server
+    */
+   private NotSoSimpleAxisServer m_simpleAxisServer;
+
+   /**
+    * @see TestCase#TestCase()
+    */
+   public AbstractAxisTestCase(  )
+   {
+      super(  );
+   }
+
+   /**
+    * @see TestCase#TestCase(String)
+    */
+   public AbstractAxisTestCase( String name )
+   {
+      super( name );
+   }
+
+   /**
+    * Returns the base URL used to contact the Axis server.  To access a web service hosted inside
+    * of the embedded Axis server, append the name of the web service to this base URL.
+    * <p/>
+    * Subclasses may override this method if the default is not acceptable. The
+    * default is <code>http://127.0.0.1:####/axis/services/</code> where <code>####</code>
+    * is the {@link #getAxisServerSocketPort() Axis port number} and <code>axis</code> is
+    * the {@link #getAxisContextName() Axis context name}.
+    *
+    * @return base URL for all web services hosted in the embedded Axis server
+    */
+   protected URL getAxisBaseUrl(  )
+   {
+      try
+      {
+         return new URL( "http",
+                         "127.0.0.1",
+                         m_simpleAxisServer.getServerSocket(  ).getLocalPort(  ),
+                         "/" + getAxisContextName(  ) + "/services/" );
+      }
+      catch ( MalformedURLException murle )
+      { // should never occur - throw error so as not to force a throws clause in signature
+         throw new AssertionFailedError( murle.toString(  ) );
+      }
+   }
+
+   /**
+    * Returns the full directory path containing the WSDD configuration file(s).
+    * This is the base path that is prepended to the
+    * {@link #getAxisConfigFileName() configuration file name}.
+    * <p/>
+    * Subclasses may override this method if the default is not acceptable. The
+    * default is the current directory as defined by the system property
+    * <code>user.dir</code>.
+    *
+    * @return filename of the WSDD configuration file
+    */
+   protected String getAxisConfigBasePath(  )
+   {
+      return System.getProperty( "user.dir" );
+   }
+
+   /**
+    * Returns the filename of the actual Axis WSDD configuration file, excluding
+    * all directory paths.
+    * <p/>
+    * Subclasses may override this method if the default is not acceptable. The
+    * default is <code>server-config.wsdd</code>.
+    *
+    * @return filename of the WSDD configuration file
+    */
+   protected String getAxisConfigFileName(  )
+   {
+      return "server-config.wsdd";
+   }
+
+   /**
+    * Returns the context name of the Axis servlet for use within an endpoint URL.
+    *
+    * @return context name of the Axis servlet
+    */
+   protected String getAxisContextName(  )
+   {
+      return "axis";
+   }
+
+   /**
+    * This setter is to allow subclasses to tell us if we should use an already existing Axis server.
+    *
+    * @param server the embedded Axis server to be used by the tests
+    */
+   protected void setAxisServer( NotSoSimpleAxisServer server )
+   {
+      m_simpleAxisServer = server;
+   }
+
+   /**
+    * @return the embedded Axis server to be used by the tests
+    */
+   protected NotSoSimpleAxisServer getAxisServer(  )
+   {
+      return m_simpleAxisServer;
+   }
+
+   /**
+    * Returns the number of the port that the embedded Axis server will accept
+    * requests on.
+    * <p/>
+    * Subclasses may override this method if the default is not acceptable. The
+    * default is <code>8080</code>.
+    *
+    * @return port number that the Axis server will listen to
+    */
+   protected int getAxisServerSocketPort(  )
+   {
+      return ANY_FREE_PORT;
+   }
+
+   /**
+    * Returns a URL used to request a WSDL document for a web service with the given name.
+    * This method uses {@link #getAxisBaseUrl()} to determine the base URL.
+    *
+    * @param serviceName the name of the web service
+    *
+    * @return URL used to request a web service WSDL document
+    *
+    * @see #getAxisBaseUrl()
+    */
+   protected URL getAxisWebServiceUrl( String serviceName )
+   {
+      try
+      {
+         return new URL( getAxisBaseUrl(  ),
+                         serviceName );
+      }
+      catch ( MalformedURLException murle )
+      { // should never occur - throw error so as not to force a throws clause in signature
+         throw new AssertionFailedError( murle.toString(  ) );
+      }
+   }
+
+   /**
+    * Returns a URL used to request a WSDL document for a web service with the given name.
+    * This method uses {@link #getAxisBaseUrl()} to determine the base URL.
+    *
+    * @param serviceName the name of the web service
+    *
+    * @return URL used to request a web service WSDL document
+    *
+    * @see #getAxisBaseUrl()
+    */
+   protected URL getAxisWebServiceWsdlUrl( String serviceName )
+   {
+      try
+      {
+         return new URL( getAxisBaseUrl(  ).toString(  ) + serviceName + "?wsdl" );
+      }
+      catch ( MalformedURLException murle )
+      { // should never occur - throw error so as not to force a throws clause in signature
+         throw new AssertionFailedError( murle.toString(  ) );
+      }
+   }
+
+   /**
+    * Reads in the Axis configuration file, creates a server socket to accept
+    * requests and then starts the embedded Axis server.
+    *
+    * @throws Exception if failed to get the configuration file, failed to start
+    *                   the server socket or failed to start the server
+    */
+   protected void startAxisServer(  )
+   throws Exception
+   {
+      FileProvider config = new FileProvider( getAxisConfigBasePath(  ),
+                                              getAxisConfigFileName(  ) );
+      ServerSocket ss = new ServerSocket( getAxisServerSocketPort(  ) );
+      m_simpleAxisServer = new NotSoSimpleAxisServer(  );
+      m_simpleAxisServer.setServerSocket( ss );
+      m_simpleAxisServer.setMyConfig( config );
+      m_simpleAxisServer.start(  );
+   }
+
+   /**
+    * Stops the embedded Axis server if it is running.
+    */
+   protected void stopAxisServer(  )
+   {
+      if ( m_simpleAxisServer != null )
+      {
+         m_simpleAxisServer.stop(  );
+         m_simpleAxisServer = null;
+      }
+   }
+}
\ No newline at end of file

Added: incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractMultipleAxisTestCase.java
URL: http://svn.apache.org/viewcvs/incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractMultipleAxisTestCase.java?view=auto&rev=155793
==============================================================================
--- incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractMultipleAxisTestCase.java (added)
+++ incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractMultipleAxisTestCase.java Tue Mar  1 07:43:22 2005
@@ -0,0 +1,73 @@
+/*=============================================================================*
+ *  Copyright 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.ws.util.test.axis;
+
+import junit.framework.TestCase;
+
+/**
+ * A JUnit test case superclass that will setup each individual test with its own
+ * Axis server.  Multiple Axis servers will be started/stopped - one per test method.
+ *
+ * @author mazz
+ */
+public abstract class AbstractMultipleAxisTestCase
+   extends AbstractAxisTestCase
+{
+   /**
+    * @see AbstractAxisTestCase#AbstractAxisTestCase()
+    */
+   public AbstractMultipleAxisTestCase(  )
+   {
+   }
+
+   /**
+    * @see AbstractAxisTestCase#AbstractAxisTestCase(String)
+    */
+   public AbstractMultipleAxisTestCase( String name )
+   {
+      super( name );
+   }
+
+   /**
+    * Starts the embedded Axis server.
+    *
+    * @see TestCase#setUp()
+    */
+   protected void setUp(  )
+   throws Exception
+   {
+      super.setUp(  );
+       //see if server should be run
+       if (RUN_AXIS_SERVER) {
+           startAxisServer(  );
+       }
+   }
+
+   /**
+    * Stops the embedded Axis server.
+    *
+    * @see TestCase#tearDown()
+    */
+   protected void tearDown(  )
+   throws Exception
+   {
+      super.tearDown(  );
+       //see if server was running before teardown
+       if (RUN_AXIS_SERVER) {
+           stopAxisServer(  );
+       }
+   }
+}
\ No newline at end of file

Added: incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractNoAxisTestCase.java
URL: http://svn.apache.org/viewcvs/incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractNoAxisTestCase.java?view=auto&rev=155793
==============================================================================
--- incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractNoAxisTestCase.java (added)
+++ incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractNoAxisTestCase.java Tue Mar  1 07:43:22 2005
@@ -0,0 +1,36 @@
+/*=============================================================================*
+ *  Copyright 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.ws.util.test.axis;
+
+
+/**
+ * For running tests against an Axis instance running in another JVM (i.e. under Tomcat).
+ *
+ * @author Ian P. Springer
+ */
+public abstract class AbstractNoAxisTestCase
+   extends AbstractAxisTestCase
+{
+   /**
+    * Context is wsrf when not running under a {@link org.apache.axis.transport.http.SimpleAxisServer}.
+    *
+    * @return "wsrf"
+    */
+   protected String getAxisContextName(  )
+   {
+      return "wsrf";
+   }
+}
\ No newline at end of file

Added: incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractOneAxisTestCase.java
URL: http://svn.apache.org/viewcvs/incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractOneAxisTestCase.java?view=auto&rev=155793
==============================================================================
--- incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractOneAxisTestCase.java (added)
+++ incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/AbstractOneAxisTestCase.java Tue Mar  1 07:43:22 2005
@@ -0,0 +1,184 @@
+/*=============================================================================*
+ *  Copyright 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.ws.util.test.axis;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Vector;
+
+/**
+ * A JUnit test case superclass that will setup one global Axis server for use across all
+ * individual test methods.  An embedded Axis server is started before the
+ * first test is run and that one Axis server remains running until the last test completes
+ * its run at which time the Axis server is stopped.
+ *
+ * @author Ian P. Springer
+ */
+public abstract class AbstractOneAxisTestCase
+   extends AbstractAxisTestCase
+{
+   /** number of test methods that have been run (static since JUnit creates one instance of this class per test method) */
+   private static int s_testsRun = 0;
+
+   /** total number of test methods found in the test case (static since JUnit creates one instance of this class per test method) */
+   private static int s_testCount = 0;
+
+   /** axis server for use across all tests in the test case (static since JUnit creates one instance of this class per test method) */
+   private static NotSoSimpleAxisServer s_simpleAxisServer;
+
+   /**
+    * @see AbstractAxisTestCase#AbstractAxisTestCase()
+    */
+   public AbstractOneAxisTestCase(  )
+   {
+      super(  );
+   }
+
+   /**
+    * @see AbstractAxisTestCase#AbstractAxisTestCase(String)
+    */
+   public AbstractOneAxisTestCase( String name )
+   {
+      super( name );
+   }
+
+   /**
+    * Starts the embedded Axis server iff this is the first test being run within this test case.
+    *
+    * @see TestCase#setUp()
+    */
+   protected void setUp(  )
+   throws Exception
+   {
+      super.setUp(  );
+
+      //this check determines if the Axis server should be started.
+      if(RUN_AXIS_SERVER)
+      {
+      if ( s_testsRun++ == 0 )
+      {
+         startAxisServer(  );
+         s_simpleAxisServer = getAxisServer(  );
+      }
+      else
+      {
+         // a prior test method was run so the Axis server is already started, reuse it
+         setAxisServer( s_simpleAxisServer );
+      }
+      }
+   }
+
+   /**
+    * Stops the embedded Axis server after the last test within this test case has finished running.
+    *
+    * @see TestCase#tearDown()
+    */
+   protected void tearDown(  )
+   throws Exception
+   {
+      super.tearDown(  );
+      if ( s_testsRun == getTestCount(  ) )
+      {
+         //this check determines if the Axis server WAS started.
+        if(RUN_AXIS_SERVER)
+        {
+         stopAxisServer(  );
+         s_simpleAxisServer    = null;
+        }
+         // reset the counters to prepare for the next test case
+         s_testsRun     = 0;
+         s_testCount    = 0;
+      }
+   }
+
+   /**
+    * Returns the number of tests in this TestCase.
+    *
+    * @return the number of tests in this TestCase
+    */
+   private int getTestCount(  )
+   {
+      if ( s_testCount == 0 )
+      {
+         s_testCount = countTests( this.getClass(  ) );
+      }
+
+      return s_testCount;
+   }
+
+   /**
+    * Examines the given <code>Method</code> and returns <code>true</code> if it is a JUnit test method.
+    *
+    * A method is considered a test method if all of the following are <code>true</code>:
+    * <ol>
+    *    <li>The method's name starts with "test"</li>
+    *    <li>The method takes 0 parameters</li>
+    *    <li>The method returns "void"</li>
+    *    <li>The method is public</li>
+    * </ol>
+    *
+    * @param m the method to check
+    *
+    * @return <code>true</code> if the given method is a JUnit test method; <code>false</code> otherwise
+    */
+   private boolean isTestMethod( Method m )
+   {
+      String  name       = m.getName(  );
+      Class[] parameters = m.getParameterTypes(  );
+      Class   returnType = m.getReturnType(  );
+      boolean is_public  = Modifier.isPublic( m.getModifiers(  ) );
+
+      return ( parameters.length == 0 ) && name.startsWith( "test" ) && returnType.equals( Void.TYPE )
+             && is_public;
+   }
+
+   /**
+    * Counts the test methods in the specified JUnit TestCase class.
+    *
+    * @param testCaseClass a JUnit TestCase class
+    *
+    * @return the number of test methods in the specified TestCase class
+    *
+    * @see #isTestMethod(Method)
+    */
+   private int countTests( final Class testCaseClass )
+   {
+      Class  superClass = testCaseClass;
+      Vector tests = new Vector(  );
+
+      while ( Test.class.isAssignableFrom( superClass ) )
+      {
+         Method[] methods = superClass.getDeclaredMethods(  );
+
+         for ( int i = 0; i < methods.length; i++ )
+         {
+            if ( !tests.contains( methods[i].getName(  ) ) )
+            {
+               if ( isTestMethod( methods[i] ) )
+               {
+                  tests.add( methods[i].getName(  ) );
+               }
+            }
+         }
+
+         superClass = superClass.getSuperclass(  );
+      }
+
+      return tests.size(  );
+   }
+}
\ No newline at end of file

Added: incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisServer.java
URL: http://svn.apache.org/viewcvs/incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisServer.java?view=auto&rev=155793
==============================================================================
--- incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisServer.java (added)
+++ incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisServer.java Tue Mar  1 07:43:22 2005
@@ -0,0 +1,468 @@
+/*
+ * 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.ws.util.test.axis;
+
+import org.apache.axis.EngineConfiguration;
+import org.apache.axis.collections.LRUMap;
+import org.apache.axis.components.logger.LogFactory;
+import org.apache.axis.components.threadpool.ThreadPool;
+import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
+import org.apache.axis.management.ServiceAdmin;
+import org.apache.axis.server.AxisServer;
+import org.apache.axis.session.Session;
+import org.apache.axis.session.SimpleSession;
+import org.apache.axis.transport.http.SimpleAxisWorker;
+import org.apache.axis.transport.http.SimpleAxisServer;
+import org.apache.axis.utils.Messages;
+import org.apache.axis.utils.NetworkUtils;
+import org.apache.axis.utils.Options;
+import org.apache.commons.logging.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Map;
+
+/**
+ * This is a simple implementation of an HTTP server for processing SOAP requests via Apache's xml-axis.  This is not
+ * intended for production use.  Its intended uses are for demos, debugging, and performance profiling.
+ * <p/>
+ * Note this classes uses static objects to provide a thread pool, so you should not use multiple instances of this
+ * class in the same JVM/classloader unless you want bad things to happen at shutdown.
+ *
+ * TODO: delete any methods that can be safely inherited from superclass
+ *
+ * @author Ian Springer
+ */
+public class NotSoSimpleAxisServer extends SimpleAxisServer implements Runnable
+{
+
+    public static final File DEFAULT_DOC_ROOT_DIR = new File( "./src/wsdl" );
+    public static final int DEFAULT_MAX_THREADS = 200;
+    public static final int DEFAULT_MAX_SESSIONS = 100;
+
+    protected static final Log LOG = LogFactory.getLog( NotSoSimpleAxisServer.class.getName() );
+
+    // session state.
+    // This table maps session keys (random numbers) to SimpleAxisSession objects.
+    //
+    // There is a simple LRU based session cleanup mechanism, but if clients are not
+    // passing cookies, then a new session will be created for *every* request.
+    private Map m_sessions;
+    //Maximum capacity of the LRU Map used for session cleanup
+    private int m_maxSessions;
+
+    private File m_docRootDir;
+
+    /**
+     * get the thread pool
+     *
+     * @return
+     */
+    public static ThreadPool getPool()
+    {
+        return m_pool;
+    }
+
+    /*
+     * pool of threads
+     */
+    private static ThreadPool m_pool;
+
+    /*
+     * Are we doing threads?
+     */
+    private static boolean s_doThreads = true;
+
+    /*
+     * Are we doing sessions? Set this to false if you don't want any session overhead.
+     */
+    private static boolean s_doSessions = true;
+
+    /**
+     * Create a server with default options.
+     */
+    public NotSoSimpleAxisServer()
+    {
+        this( DEFAULT_DOC_ROOT_DIR );
+    }
+
+    /**
+     * Create a server with the specified docRoot.
+     */
+    public NotSoSimpleAxisServer( File docRootDir )
+    {
+        this( docRootDir, DEFAULT_MAX_THREADS );
+    }
+
+    /**
+     * Create a server with the specified docRoot and max threads.
+     */
+    public NotSoSimpleAxisServer( File docRootDir, int maxPoolSize )
+    {
+        this( docRootDir, maxPoolSize, DEFAULT_MAX_SESSIONS );
+    }
+
+    /**
+     * Create a server with the specified docRoot, max threads, and max sessions.
+     */
+    public NotSoSimpleAxisServer( File docRootDir, int maxPoolSize, int maxSessions )
+    {
+        m_docRootDir = docRootDir;
+        m_pool = new ThreadPool( maxPoolSize );
+        m_sessions = new LRUMap( maxSessions );
+    }
+
+    /**
+     * stop the server if not already told to.
+     *
+     * @throws Throwable
+     */
+    protected void finalize() throws Throwable
+    {
+        stop();
+        super.finalize();
+    }
+
+    /**
+     * get max session count
+     *
+     * @return
+     */
+    public int getMaxSessions()
+    {
+        return m_maxSessions;
+    }
+
+    /**
+     * Resize the session map
+     *
+     * @param maxSessions maximum sessions
+     */
+    public void setMaxSessions( int maxSessions )
+    {
+        this.m_maxSessions = maxSessions;
+        ( (LRUMap) m_sessions ).setMaximumSize( maxSessions );
+    }
+    //---------------------------------------------------
+
+    protected boolean isSessionUsed()
+    {
+        return s_doSessions;
+    }
+
+    /**
+     * turn threading on or off. This sets a static value
+     *
+     * @param value
+     */
+    public void setDoThreads( boolean value )
+    {
+        s_doThreads = value;
+    }
+
+    public boolean getDoThreads()
+    {
+        return s_doThreads;
+    }
+
+    public EngineConfiguration getMyConfig()
+    {
+        return m_myConfig;
+    }
+
+    public void setMyConfig( EngineConfiguration myConfig )
+    {
+        m_myConfig = myConfig;
+    }
+
+    /**
+     * demand create a session if there is not already one for the string
+     *
+     * @param cooky
+     *
+     * @return a session.
+     */
+    protected Session createSession( String cooky )
+    {
+
+        // is there a session already?
+        Session session = null;
+        if ( m_sessions.containsKey( cooky ) )
+        {
+            session = (Session) m_sessions.get( cooky );
+        }
+        else
+        {
+            // no session for this cooky, bummer
+            session = new SimpleSession();
+
+            // ADD CLEANUP LOGIC HERE if needed
+            m_sessions.put( cooky, session );
+        }
+        return session;
+    }
+
+    // What is our current session index?
+    // This is a monotonically increasing, non-thread-safe integer
+    // (thread safety not considered crucial here)
+    public static int sessionIndex = 0;
+
+    // Axis server (shared between instances)
+    private static AxisServer myAxisServer = null;
+
+    private EngineConfiguration m_myConfig = null;
+
+    /**
+     * demand create an axis server; return an existing one if one exists. The configuration for the axis server is
+     * derived from #myConfig if not null, the default config otherwise.
+     *
+     * @return
+     */
+    public synchronized AxisServer getAxisServer()
+    {
+        if ( myAxisServer == null )
+        {
+            if ( m_myConfig == null )
+            {
+                m_myConfig = EngineConfigurationFactoryFinder.newFactory().getServerEngineConfig();
+            }
+            myAxisServer = new AxisServer( m_myConfig );
+            ServiceAdmin.setEngine( myAxisServer, NetworkUtils.getLocalHostname() + "@" + m_serverSocket.getLocalPort() );
+        }
+        return myAxisServer;
+    }
+
+    /**
+     * are we stopped? latch to true if stop() is called
+     */
+    private boolean stopped = false;
+
+    /**
+     * Accept requests from a given TCP port and send them through the Axis engine for processing.
+     */
+    public void run()
+    {
+        LOG.info( Messages.getMessage( "start01", "SimpleAxisServer",
+                new Integer( getServerSocket().getLocalPort() ).toString(), getCurrentDirectory() ) );
+
+        // Accept and process requests from the socket
+        while ( !stopped )
+        {
+            Socket socket = null;
+            try
+            {
+                socket = m_serverSocket.accept();
+            }
+            catch ( java.io.InterruptedIOException iie )
+            {
+            }
+            catch ( Exception e )
+            {
+                LOG.debug( Messages.getMessage( "exception00" ), e );
+                break;
+            }
+            if ( socket != null )
+            {
+                SimpleAxisWorker worker = new NotSoSimpleAxisWorker( this, socket, m_docRootDir );
+                if ( s_doThreads )
+                {
+                    m_pool.addWorker( worker );
+                }
+                else
+                {
+                    worker.run();
+                }
+            }
+        }
+        LOG.info( Messages.getMessage( "quit00", "SimpleAxisServer" ) );
+    }
+
+    /**
+     * Gets the current directory
+     *
+     * @return current directory
+     */
+    private String getCurrentDirectory()
+    {
+        return System.getProperty( "user.dir" );
+    }
+
+    // per thread socket information
+    private ServerSocket m_serverSocket;
+
+    /**
+     * Obtain the serverSocket that that SimpleAxisServer is listening on.
+     */
+    public ServerSocket getServerSocket()
+    {
+        return m_serverSocket;
+    }
+
+    /**
+     * Set the serverSocket this server should listen on. (note : changing this will not affect a running server, but if
+     * you stop() and then start() the server, the new socket will be used).
+     */
+    public void setServerSocket( ServerSocket serverSocket )
+    {
+        m_serverSocket = serverSocket;
+    }
+
+    /**
+     * Start this server.
+     * <p/>
+     * Spawns a worker thread to listen for HTTP requests.
+     *
+     * @param daemon a boolean indicating if the thread should be a daemon.
+     */
+    public void start( boolean daemon ) throws Exception
+    {
+        stopped = false;
+        if ( s_doThreads )
+        {
+            Thread thread = new Thread( this );
+            thread.setDaemon( daemon );
+            thread.start();
+        }
+        else
+        {
+            run();
+        }
+    }
+
+    /**
+     * Start this server as a NON-daemon.
+     */
+    public void start() throws Exception
+    {
+        start( false );
+    }
+
+    /**
+     * Stop this server. Can be called safely if the system is already stopped, or if it was never started.
+     * <p/>
+     * This will interrupt any pending accept().
+     */
+    public void stop()
+    {
+        //recognise use before we are live
+        if ( stopped )
+        {
+            return;
+        }
+        /*
+         * Close the server socket cleanly, but avoid fresh accepts while
+         * the socket is closing.
+         */
+        stopped = true;
+
+        try
+        {
+            if ( m_serverSocket != null )
+            {
+                m_serverSocket.close();
+            }
+        }
+        catch ( IOException e )
+        {
+            LOG.info( Messages.getMessage( "exception00" ), e );
+        }
+        finally
+        {
+            m_serverSocket = null;
+        }
+
+        LOG.info( Messages.getMessage( "quit00", "SimpleAxisServer" ) );
+
+        //shut down the pool
+        m_pool.shutdown();
+    }
+
+    /**
+     * Server process.
+     */
+    public static void main( String args[] )
+    {
+
+        Options opts = null;
+        try
+        {
+            opts = new Options( args );
+        }
+        catch ( MalformedURLException e )
+        {
+            LOG.error( Messages.getMessage( "malformedURLException00" ), e );
+            return;
+        }
+
+        String maxPoolSize = opts.isValueSet( 't' );
+        if ( maxPoolSize == null )
+        {
+            maxPoolSize = ThreadPool.DEFAULT_MAX_THREADS + "";
+        }
+
+        String maxSessions = opts.isValueSet( 'm' );
+        if ( maxSessions == null )
+        {
+            maxSessions = DEFAULT_MAX_SESSIONS + "";
+        }
+
+        String[] nonOptionArgs = opts.getRemainingArgs();
+        NotSoSimpleAxisServer server = new NotSoSimpleAxisServer( new File( nonOptionArgs[0] ), Integer.parseInt( maxPoolSize ),
+                Integer.parseInt( maxSessions ) );
+
+        try
+        {
+            s_doThreads = ( opts.isFlagSet( 't' ) > 0 );
+
+            int port = opts.getPort();
+            ServerSocket ss = null;
+            // Try five times
+            final int retries = 5;
+            for ( int i = 0; i < retries; i++ )
+            {
+                try
+                {
+                    ss = new ServerSocket( port );
+                    break;
+                }
+                catch ( java.net.BindException be )
+                {
+                    LOG.debug( Messages.getMessage( "exception00" ), be );
+                    if ( i < ( retries - 1 ) )
+                    {
+                        // At 3 second intervals.
+                        Thread.sleep( 3000 );
+                    }
+                    else
+                    {
+                        throw new Exception( Messages.getMessage( "unableToStartServer00",
+                                Integer.toString( port ) ) );
+                    }
+                }
+            }
+            server.setServerSocket( ss );
+            server.start();
+        }
+        catch ( Exception e )
+        {
+            LOG.error( Messages.getMessage( "exception00" ), e );
+            return;
+        }
+    }
+}

Added: incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisWorker.java
URL: http://svn.apache.org/viewcvs/incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisWorker.java?view=auto&rev=155793
==============================================================================
--- incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisWorker.java (added)
+++ incubator/apollo/trunk/src/java/org/apache/ws/util/test/axis/NotSoSimpleAxisWorker.java Tue Mar  1 07:43:22 2005
@@ -0,0 +1,964 @@
+/*=============================================================================*
+ *  Copyright 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.ws.util.test.axis;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.Constants;
+import org.apache.axis.Message;
+import org.apache.axis.MessageContext;
+import org.apache.axis.description.OperationDesc;
+import org.apache.axis.description.ServiceDesc;
+import org.apache.axis.encoding.Base64;
+import org.apache.axis.message.SOAPEnvelope;
+import org.apache.axis.message.SOAPFault;
+import org.apache.axis.server.AxisServer;
+import org.apache.axis.transport.http.HTTPConstants;
+import org.apache.axis.transport.http.NonBlockingBufferedInputStream;
+import org.apache.axis.transport.http.SimpleAxisServer;
+import org.apache.axis.transport.http.SimpleAxisWorker;
+import org.apache.axis.utils.Messages;
+import org.apache.axis.utils.XMLUtils;
+import org.w3c.dom.Document;
+import javax.xml.namespace.QName;
+import javax.xml.soap.MimeHeader;
+import javax.xml.soap.MimeHeaders;
+import javax.xml.soap.SOAPMessage;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Web server that supports SOAP POST requests and arbitrary GET requests.
+ *
+ * @author Ian P. Springer
+ */
+public class NotSoSimpleAxisWorker
+   extends SimpleAxisWorker
+{
+   private static final byte[] TO_LOWER = new byte[256];
+
+   static
+   {
+      for ( int i = 0; i < 256; i++ )
+      {
+         TO_LOWER[i] = (byte) i;
+      }
+
+      for ( int lc = 'a'; lc <= 'z'; lc++ )
+      {
+         TO_LOWER[( lc + 'A' ) - 'a'] = (byte) lc;
+      }
+   }
+
+   // buffer for IO
+   private static final int BUFSIZ = 4096;
+
+   // Axis specific constants
+   private static String TRANSPORT_NAME = "SimpleHTTP";
+
+   // header ender
+   //private static final byte[] HEADER_ENDER = ": ".getBytes(  );
+
+   // HTTP status codes
+   private static byte[] OK        = ( "200 " + Messages.getMessage( "ok00" ) ).getBytes(  );
+   private static byte[] NOCONTENT = ( "202 " + Messages.getMessage( "ok00" ) + "\n\n" ).getBytes(  );
+   private static byte[] UNAUTH    = ( "401 " + Messages.getMessage( "unauth00" ) ).getBytes(  );
+   private static byte[] SENDER    = "400".getBytes(  );
+   private static byte[] ISE       = ( "500 " + Messages.getMessage( "internalError01" ) ).getBytes(  );
+
+   // HTTP prefix
+   private static byte[] HTTP = "HTTP/1.0 ".getBytes(  );
+
+   // Standard MIME headers for XML payload
+   private static byte[] XML_MIME_STUFF =
+      ( "\r\nContent-Type: text/xml; charset=utf-8\r\n" + "Content-Length: " ).getBytes(  );
+
+   // Standard MIME headers for HTML payload
+   private static byte[] HTML_MIME_STUFF =
+      ( "\r\nContent-Type: text/html; charset=utf-8\r\n" + "Content-Length: " ).getBytes(  );
+
+   // Mime/Content separator
+   private static byte[] SEPARATOR = "\r\n\r\n".getBytes(  );
+
+   // mime header for content length
+   private static final byte[] lenHeader = "content-length: ".getBytes(  );
+   private static final int    lenLen = lenHeader.length;
+
+   // mime header for content type
+   private static final byte[] typeHeader =
+      ( HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase(  ) + ": " ).getBytes(  );
+   private static final int    typeLen = typeHeader.length;
+
+   // mime header for content location
+   private static final byte[] locationHeader =
+      ( HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase(  ) + ": " ).getBytes(  );
+   private static final int    locationLen = locationHeader.length;
+
+   // mime header for soap action
+   private static final byte[] actionHeader = "soapaction: ".getBytes(  );
+   private static final int    actionLen = actionHeader.length;
+
+   // mime header for cookie
+   private static final byte[] cookieHeader = "cookie: ".getBytes(  );
+   private static final int    cookieLen = cookieHeader.length;
+
+   // mime header for cookie2
+   private static final byte[] cookie2Header = "cookie2: ".getBytes(  );
+   private static final int    cookie2Len = cookie2Header.length;
+
+   // HTTP header for authentication
+   private static final byte[] authHeader = "authorization: ".getBytes(  );
+   private static final int    authLen = authHeader.length;
+
+   // mime header for GET
+   private static final byte[] getHeader = "GET".getBytes(  );
+
+   // mime header for POST
+   private static final byte[] postHeader = "POST".getBytes(  );
+
+   // header ender
+   private static final byte[] headerEnder = ": ".getBytes(  );
+
+   // "Basic" auth string
+   private static final byte[]   basicAuth    = "basic ".getBytes(  );
+   private File                  m_docRootDir;
+   private NotSoSimpleAxisServer m_server;
+   private Socket                m_socket;
+
+   /**
+    * Creates a new {@link NotSoSimpleAxisWorker} object.
+    *
+    * @param server     DOCUMENT_ME
+    * @param socket     DOCUMENT_ME
+    * @param docRootDir DOCUMENT_ME
+    */
+   public NotSoSimpleAxisWorker( NotSoSimpleAxisServer server,
+                                 Socket                socket,
+                                 File                  docRootDir )
+   {
+      super( server, socket );
+      m_server        = server;
+      m_socket        = socket;
+      m_docRootDir    = docRootDir;
+   }
+
+   /**
+    * The main workhorse method.
+    */
+   public void execute(  )
+   {
+      byte[] buf = new byte[BUFSIZ];
+
+      // create an Axis server
+      AxisServer engine = m_server.getAxisServer(  );
+
+      // create and initialize a message context
+      MessageContext msgContext = new MessageContext( engine );
+      Message        requestMsg = null;
+
+      // Reusuable, buffered, content length controlled, InputStream
+      NonBlockingBufferedInputStream is = new NonBlockingBufferedInputStream(  );
+
+      // buffers for the headers we care about
+      StringBuffer soapAction      = new StringBuffer(  );
+      StringBuffer httpRequest     = new StringBuffer(  );
+      StringBuffer fileName        = new StringBuffer(  );
+      StringBuffer cookie          = new StringBuffer(  );
+      StringBuffer cookie2         = new StringBuffer(  );
+      StringBuffer authInfo        = new StringBuffer(  );
+      StringBuffer contentType     = new StringBuffer(  );
+      StringBuffer contentLocation = new StringBuffer(  );
+
+      Message      responseMsg = null;
+
+      // prepare request (do as much as possible while waiting for the
+      // next connection).  Note the next two statements are commented
+      // out.  Uncomment them if you experience any problems with not
+      // resetting state between requests:
+      //   msgContext = new MessageContext();
+      //   requestMsg = new Message("", "String");
+      //msgContext.setProperty("transport", "HTTPTransport");
+      msgContext.setTransportName( TRANSPORT_NAME );
+
+      responseMsg = null;
+
+      try
+      {
+         // assume the best
+         byte[] status = OK;
+
+         // assume we're not getting WSDL
+         boolean doWsdl = false;
+
+         // cookie for this session, if any
+         String cooky = null;
+
+         String methodName = null;
+
+         try
+         {
+            // wipe cookies if we're doing sessions
+            if ( m_server.isSessionUsed(  ) )
+            {
+               cookie.delete( 0,
+                              cookie.length(  ) );
+               cookie2.delete( 0,
+                               cookie2.length(  ) );
+            }
+
+            authInfo.delete( 0,
+                             authInfo.length(  ) );
+
+            // read headers
+            is.setInputStream( m_socket.getInputStream(  ) );
+
+            // parse all headers into hashtable
+            MimeHeaders requestHeaders = new MimeHeaders(  );
+            int         contentLength =
+               parseHeaders( is, buf, contentType, contentLocation, soapAction, httpRequest, fileName, cookie,
+                             cookie2, authInfo, requestHeaders );
+            is.setContentLength( contentLength );
+
+            int paramIdx = fileName.toString(  ).indexOf( '?' );
+            if ( paramIdx != -1 )
+            {
+               // Got params
+               String params = fileName.substring( paramIdx + 1 );
+               fileName.setLength( paramIdx );
+
+               log.debug( Messages.getMessage( "filename00",
+                                               fileName.toString(  ) ) );
+               log.debug( Messages.getMessage( "params00", params ) );
+
+               if ( "wsdl".equalsIgnoreCase( params ) )
+               {
+                  doWsdl = true;
+               }
+
+               if ( params.startsWith( "method=" ) )
+               {
+                  methodName = params.substring( 7 );
+               }
+            }
+
+            // Real and relative paths are the same for the
+            // SimpleAxisServer
+            msgContext.setProperty( Constants.MC_REALPATH,
+                                    fileName.toString(  ) );
+            msgContext.setProperty( Constants.MC_RELATIVE_PATH,
+                                    fileName.toString(  ) );
+            msgContext.setProperty( Constants.MC_JWS_CLASSDIR, "jwsClasses" );
+            msgContext.setProperty( Constants.MC_HOME_DIR, "." );
+
+            // !!! Fix string concatenation
+            String url =
+               "http://" + getLocalHost(  ) + ":" + m_server.getServerSocket(  ).getLocalPort(  ) + "/"
+               + fileName.toString(  );
+            msgContext.setProperty( MessageContext.TRANS_URL, url );
+
+            String filePart = fileName.toString(  );
+            if ( filePart.startsWith( "axis/services/" ) )
+            {
+               String servicePart = filePart.substring( 14 );
+               int    separator = servicePart.indexOf( '/' );
+               if ( separator > -1 )
+               {
+                  msgContext.setProperty( "objectID",
+                                          servicePart.substring( separator + 1 ) );
+                  servicePart = servicePart.substring( 0, separator );
+               }
+
+               msgContext.setTargetService( servicePart );
+            }
+
+            if ( authInfo.length(  ) > 0 )
+            {
+               // Process authentication info
+               //authInfo = new StringBuffer("dXNlcjE6cGFzczE=");
+               byte[]       decoded = Base64.decode( authInfo.toString(  ) );
+               StringBuffer userBuf = new StringBuffer(  );
+               StringBuffer pwBuf   = new StringBuffer(  );
+               StringBuffer authBuf = userBuf;
+               for ( int i = 0; i < decoded.length; i++ )
+               {
+                  if ( (char) ( decoded[i] & 0x7f ) == ':' )
+                  {
+                     authBuf = pwBuf;
+                     continue;
+                  }
+
+                  authBuf.append( (char) ( decoded[i] & 0x7f ) );
+               }
+
+               if ( log.isDebugEnabled(  ) )
+               {
+                  log.debug( Messages.getMessage( "user00",
+                                                  userBuf.toString(  ) ) );
+               }
+
+               msgContext.setUsername( userBuf.toString(  ) );
+               msgContext.setPassword( pwBuf.toString(  ) );
+            }
+
+            // if get, then return simpleton document as response
+            if ( httpRequest.toString(  ).equals( "GET" ) )
+            {
+               OutputStream out = m_socket.getOutputStream(  );
+               out.write( HTTP );
+               if ( fileName.length(  ) == 0 )
+               {
+                  out.write( "301 Redirect\nLocation: /axis/\n\n".getBytes(  ) );
+                  out.flush(  );
+                  return;
+               }
+
+               out.write( status );
+
+               if ( methodName != null )
+               {
+                  String body = "<" + methodName + ">" + 
+                     //                               args +
+                     "</" + methodName + ">";
+                  String msgtxt =
+                     "<SOAP-ENV:Envelope" + " xmlns:SOAP-ENV=\"" + Constants.URI_SOAP12_ENV + "\">"
+                     + "<SOAP-ENV:Body>" + body + "</SOAP-ENV:Body>" + "</SOAP-ENV:Envelope>";
+
+                  ByteArrayInputStream istream = new ByteArrayInputStream( msgtxt.getBytes(  ) );
+                  requestMsg = new Message( istream );
+               }
+               else if ( doWsdl )
+               {
+                  engine.generateWSDL( msgContext );
+
+                  Document doc = (Document) msgContext.getProperty( "WSDL" );
+                  if ( doc != null )
+                  {
+                     XMLUtils.normalize( doc.getDocumentElement(  ) );
+                     String response  = XMLUtils.PrettyDocumentToString( doc );
+                     byte[] respBytes = response.getBytes(  );
+
+                     out.write( XML_MIME_STUFF );
+                     putInt( buf, out, respBytes.length );
+                     out.write( SEPARATOR );
+                     out.write( respBytes );
+                     out.flush(  );
+                     return;
+                  }
+               }
+               else if ( fileName.equals( "/" ) )
+               {
+                  StringBuffer sb = new StringBuffer(  );
+                  sb.append( "<h2>And now... Some Services</h2>\n" );
+                  Iterator i = engine.getConfig(  ).getDeployedServices(  );
+                  sb.append( "<ul>\n" );
+                  while ( i.hasNext(  ) )
+                  {
+                     ServiceDesc sd = (ServiceDesc) i.next(  );
+                     sb.append( "<li>\n" );
+                     sb.append( sd.getName(  ) );
+                     sb.append( " <a href=\"services/" );
+                     sb.append( sd.getName(  ) );
+                     sb.append( "?wsdl\"><i>(wsdl)</i></a></li>\n" );
+                     ArrayList operations = sd.getOperations(  );
+                     if ( !operations.isEmpty(  ) )
+                     {
+                        sb.append( "<ul>\n" );
+                        for ( Iterator it = operations.iterator(  ); it.hasNext(  ); )
+                        {
+                           OperationDesc desc = (OperationDesc) it.next(  );
+                           sb.append( "<li>" + desc.getName(  ) );
+                        }
+
+                        sb.append( "</ul>\n" );
+                     }
+                  }
+
+                  sb.append( "</ul>\n" );
+
+                  byte[] bytes = sb.toString(  ).getBytes(  );
+
+                  out.write( HTML_MIME_STUFF );
+                  putInt( buf, out, bytes.length );
+                  out.write( SEPARATOR );
+                  out.write( bytes );
+                  out.flush(  );
+                  return;
+               }
+               else
+               {
+                  String filePath = fileName.toString(  );
+                  if ( filePath.startsWith( "/" ) )
+                  {
+                     filePath = filePath.substring( 1 );
+                  }
+
+                  File        realPath = new File( m_docRootDir, filePath );
+                  InputStream in = new BufferedInputStream( new FileInputStream( realPath ) );
+
+                  //System.out.println( "Serving up " + realPath + " on a silver platter..." );
+                  IoUtils.copy( in, out );
+                  in.close(  );
+                  out.flush(  );
+                  return;
+               }
+            }
+            else
+            {
+               // this may be "" if either SOAPAction: "" or if no SOAPAction at all.
+               // for now, do not complain if no SOAPAction at all
+               String soapActionString = soapAction.toString(  );
+               if ( soapActionString != null )
+               {
+                  msgContext.setUseSOAPAction( true );
+                  msgContext.setSOAPActionURI( soapActionString );
+               }
+
+               requestMsg = new Message( is,
+                                         false,
+                                         contentType.toString(  ),
+                                         contentLocation.toString(  ) );
+            }
+
+            // Transfer HTTP headers to MIME headers for request message.
+            MimeHeaders requestMimeHeaders = requestMsg.getMimeHeaders(  );
+            for ( Iterator i = requestHeaders.getAllHeaders(  ); i.hasNext(  ); )
+            {
+               MimeHeader requestHeader = (MimeHeader) i.next(  );
+               requestMimeHeaders.addHeader( requestHeader.getName(  ),
+                                             requestHeader.getValue(  ) );
+            }
+
+            msgContext.setRequestMessage( requestMsg );
+
+            // put character encoding of request to message context
+            // in order to reuse it during the whole process.
+            String requestEncoding = (String) requestMsg.getProperty( SOAPMessage.CHARACTER_SET_ENCODING );
+            if ( requestEncoding != null )
+            {
+               msgContext.setProperty( SOAPMessage.CHARACTER_SET_ENCODING, requestEncoding );
+            }
+
+            // set up session, if any
+            if ( m_server.isSessionUsed(  ) )
+            {
+               // did we get a cookie?
+               if ( cookie.length(  ) > 0 )
+               {
+                  cooky = cookie.toString(  ).trim(  );
+               }
+               else if ( cookie2.length(  ) > 0 )
+               {
+                  cooky = cookie2.toString(  ).trim(  );
+               }
+
+               // if cooky is null, cook up a cooky
+               if ( cooky == null )
+               {
+                  // fake one up!
+                  // make it be an arbitrarily increasing number
+                  // (no this is not thread safe because ++ isn't atomic)
+                  int i = SimpleAxisServer.sessionIndex++;
+                  cooky = "" + i;
+               }
+
+               msgContext.setSession( m_server.createSession( cooky ) );
+            }
+
+            // invoke the Axis engine
+            engine.invoke( msgContext );
+
+            // Retrieve the response from Axis
+            responseMsg = msgContext.getResponseMessage(  );
+
+            if ( responseMsg == null )
+            {
+               status = NOCONTENT;
+            }
+         }
+         catch ( Exception e )
+         {
+            AxisFault af;
+            if ( e instanceof AxisFault )
+            {
+               af = (AxisFault) e;
+               log.debug( Messages.getMessage( "serverFault00" ),
+                          af );
+               QName faultCode = af.getFaultCode(  );
+               if ( Constants.FAULT_SOAP12_SENDER.equals( faultCode ) )
+               {
+                  status = SENDER;
+               }
+               else if ( "Server.Unauthorized".equals( af.getFaultCode(  ).getLocalPart(  ) ) )
+               {
+                  status = UNAUTH; // SC_UNAUTHORIZED
+               }
+               else
+               {
+                  status = ISE; // SC_INTERNAL_SERVER_ERROR
+               }
+            }
+            else
+            {
+               status    = ISE; // SC_INTERNAL_SERVER_ERROR
+               af        = AxisFault.makeFault( e );
+            }
+
+            // There may be headers we want to preserve in the
+            // response message - so if it's there, just add the
+            // FaultElement to it.  Otherwise, make a new one.
+            responseMsg = msgContext.getResponseMessage(  );
+            if ( responseMsg == null )
+            {
+               responseMsg = new Message( af );
+               responseMsg.setMessageContext( msgContext );
+            }
+            else
+            {
+               try
+               {
+                  SOAPEnvelope env = responseMsg.getSOAPEnvelope(  );
+                  env.clearBody(  );
+                  env.addBodyElement( new SOAPFault( (AxisFault) e ) );
+               }
+               catch ( AxisFault fault )
+               {
+                  // Should never reach here!
+               }
+            }
+         }
+
+         // synchronize the character encoding of request and response
+         String responseEncoding = (String) msgContext.getProperty( SOAPMessage.CHARACTER_SET_ENCODING );
+         if ( ( responseEncoding != null ) && ( responseMsg != null ) )
+         {
+            responseMsg.setProperty( SOAPMessage.CHARACTER_SET_ENCODING, responseEncoding );
+         }
+
+         // Send it on its way...
+         OutputStream out = m_socket.getOutputStream(  );
+         out.write( HTTP );
+         out.write( status );
+
+         if ( responseMsg != null )
+         {
+            if ( m_server.isSessionUsed(  ) && ( null != cooky ) && ( 0 != cooky.trim(  ).length(  ) ) )
+            {
+               // write cookie headers, if any
+               // don't sweat efficiency *too* badly
+               // optimize at will
+               StringBuffer cookieOut = new StringBuffer(  );
+               cookieOut.append( "\r\nSet-Cookie: " ).append( cooky ).append( "\r\nSet-Cookie2: " ).append( cooky );
+
+               // OH, THE HUMILITY!  yes this is inefficient.
+               out.write( cookieOut.toString(  ).getBytes(  ) );
+            }
+
+            //out.write(XML_MIME_STUFF);
+            out.write( ( "\r\n" + HTTPConstants.HEADER_CONTENT_TYPE + ": "
+                       + responseMsg.getContentType( msgContext.getSOAPConstants(  ) ) ).getBytes(  ) );
+
+            // Writing the length causes the entire message to be decoded twice.
+            //out.write(("\r\n" + HTTPConstants.HEADER_CONTENT_LENGTH + ": " + responseMsg.getContentLength()).getBytes());
+            // putInt(out, response.length);
+            // Transfer MIME headers to HTTP headers for response message.
+            for ( Iterator i = responseMsg.getMimeHeaders(  ).getAllHeaders(  ); i.hasNext(  ); )
+            {
+               MimeHeader responseHeader = (MimeHeader) i.next(  );
+               out.write( '\r' );
+               out.write( '\n' );
+               out.write( responseHeader.getName(  ).getBytes(  ) );
+               out.write( headerEnder );
+               out.write( responseHeader.getValue(  ).getBytes(  ) );
+            }
+
+            out.write( SEPARATOR );
+            responseMsg.writeTo( out );
+         }
+
+         // out.write(response);
+         out.flush(  );
+      }
+      catch ( Exception e )
+      {
+         log.info( Messages.getMessage( "exception00" ),
+                   e );
+      }
+      finally
+      {
+         try
+         {
+            if ( m_socket != null )
+            {
+               m_socket.close(  );
+            }
+         }
+         catch ( Exception e )
+         {
+         }
+      }
+
+      if ( msgContext.getProperty( MessageContext.QUIT_REQUESTED ) != null )
+      {
+         // why then, quit!
+         try
+         {
+            m_server.stop(  );
+         }
+         catch ( Exception e )
+         {
+         }
+      }
+   }
+
+   /**
+    * Read all mime headers, returning the value of Content-Length and SOAPAction.
+    *
+    * @param is              InputStream to read from
+    * @param contentType     The content type.
+    * @param contentLocation The content location
+    * @param soapAction      StringBuffer to return the soapAction into
+    * @param httpRequest     StringBuffer for GET / POST
+    * @param cookie          first cookie header (if doSessions)
+    * @param cookie2         second cookie header (if doSessions)
+    * @param headers         HTTP headers to transfer to MIME headers
+    *
+    * @return Content-Length
+    */
+   private int parseHeaders( NonBlockingBufferedInputStream is,
+                             byte[]                         buf,
+                             StringBuffer                   contentType,
+                             StringBuffer                   contentLocation,
+                             StringBuffer                   soapAction,
+                             StringBuffer                   httpRequest,
+                             StringBuffer                   fileName,
+                             StringBuffer                   cookie,
+                             StringBuffer                   cookie2,
+                             StringBuffer                   authInfo,
+                             MimeHeaders                    headers )
+   throws java.io.IOException
+   {
+      int n;
+      int len = 0;
+
+      // parse first line as GET or POST
+      n = this.readLine( is, buf, 0, buf.length );
+
+      if ( n < 0 )
+      {
+         // nothing!
+         throw new java.io.IOException( Messages.getMessage( "unexpectedEOS00" ) );
+      }
+
+      // which does it begin with?
+      httpRequest.delete( 0,
+                          httpRequest.length(  ) );
+      fileName.delete( 0,
+                       fileName.length(  ) );
+      contentType.delete( 0,
+                          contentType.length(  ) );
+      contentLocation.delete( 0,
+                              contentLocation.length(  ) );
+
+      if ( buf[0] == getHeader[0] )
+      {
+         httpRequest.append( "GET" );
+
+         for ( int i = 0; i < ( n - 5 ); i++ )
+         {
+            char c = (char) ( buf[i + 5] & 0x7f );
+
+            if ( c == ' ' )
+            {
+               break;
+            }
+
+            fileName.append( c );
+         }
+
+         log.debug( Messages.getMessage( "filename01",
+                                         "SimpleAxisServer",
+                                         fileName.toString(  ) ) );
+
+         return 0;
+      }
+      else if ( buf[0] == postHeader[0] )
+      {
+         httpRequest.append( "POST" );
+
+         for ( int i = 0; i < ( n - 6 ); i++ )
+         {
+            char c = (char) ( buf[i + 6] & 0x7f );
+
+            if ( c == ' ' )
+            {
+               break;
+            }
+
+            fileName.append( c );
+         }
+
+         log.debug( Messages.getMessage( "filename01",
+                                         "SimpleAxisServer",
+                                         fileName.toString(  ) ) );
+      }
+      else
+      {
+         throw new java.io.IOException( Messages.getMessage( "badRequest00" ) );
+      }
+
+      while ( ( n = readLine( is, buf, 0, buf.length ) ) > 0 )
+      {
+         if ( ( n <= 2 ) && ( ( buf[0] == '\n' ) || ( buf[0] == '\r' ) ) && ( len > 0 ) )
+         {
+            break;
+         }
+
+         // RobJ gutted the previous logic; it was too hard to extend for more headers.
+         // Now, all it does is search forwards for ": " in the buf,
+         // then do a length / byte compare.
+         // Hopefully this is still somewhat efficient (Sam is watching!).
+         // First, search forwards for ": "
+         int endHeaderIndex = 0;
+
+         while ( ( endHeaderIndex < n ) && ( TO_LOWER[buf[endHeaderIndex]] != headerEnder[0] ) )
+         {
+            endHeaderIndex++;
+         }
+
+         endHeaderIndex += 2;
+
+         // endHeaderIndex now points _just past_ the ": ", and is
+         // comparable to the various lenLen, actionLen, etc. values
+         // convenience; i gets pre-incremented, so initialize it to one less
+         int i = endHeaderIndex - 1;
+
+         // which header did we find?
+         if ( ( endHeaderIndex == lenLen ) && matches( buf, lenHeader ) )
+         {
+            // parse content length
+            while ( ( ++i < n ) && ( buf[i] >= '0' ) && ( buf[i] <= '9' ) )
+            {
+               len = ( len * 10 ) + ( buf[i] - '0' );
+            }
+
+            headers.addHeader( HTTPConstants.HEADER_CONTENT_LENGTH,
+                               String.valueOf( len ) );
+         }
+         else if ( ( endHeaderIndex == actionLen ) && matches( buf, actionHeader ) )
+         {
+            soapAction.delete( 0,
+                               soapAction.length(  ) );
+
+            // skip initial '"'
+            i++;
+
+            while ( ( ++i < n ) && ( buf[i] != '"' ) )
+            {
+               soapAction.append( (char) ( buf[i] & 0x7f ) );
+            }
+
+            headers.addHeader( HTTPConstants.HEADER_SOAP_ACTION, "\"" + soapAction.toString(  ) + "\"" );
+         }
+         else if ( m_server.isSessionUsed(  ) && ( endHeaderIndex == cookieLen ) && matches( buf, cookieHeader ) )
+         {
+            // keep everything up to first ;
+            while ( ( ++i < n ) && ( buf[i] != ';' ) && ( buf[i] != '\r' ) && ( buf[i] != '\n' ) )
+            {
+               cookie.append( (char) ( buf[i] & 0x7f ) );
+            }
+
+            headers.addHeader( "Set-Cookie",
+                               cookie.toString(  ) );
+         }
+         else if ( m_server.isSessionUsed(  ) && ( endHeaderIndex == cookie2Len ) && matches( buf, cookie2Header ) )
+         {
+            // keep everything up to first ;
+            while ( ( ++i < n ) && ( buf[i] != ';' ) && ( buf[i] != '\r' ) && ( buf[i] != '\n' ) )
+            {
+               cookie2.append( (char) ( buf[i] & 0x7f ) );
+            }
+
+            headers.addHeader( "Set-Cookie2",
+                               cookie.toString(  ) );
+         }
+         else if ( ( endHeaderIndex == authLen ) && matches( buf, authHeader ) )
+         {
+            if ( matches( buf, endHeaderIndex, basicAuth ) )
+            {
+               i += basicAuth.length;
+
+               while ( ( ++i < n ) && ( buf[i] != '\r' ) && ( buf[i] != '\n' ) )
+               {
+                  if ( buf[i] == ' ' )
+                  {
+                     continue;
+                  }
+
+                  authInfo.append( (char) ( buf[i] & 0x7f ) );
+               }
+
+               headers.addHeader( HTTPConstants.HEADER_AUTHORIZATION,
+                                  new String( basicAuth ) + authInfo.toString(  ) );
+            }
+            else
+            {
+               throw new java.io.IOException( Messages.getMessage( "badAuth00" ) );
+            }
+         }
+         else if ( ( endHeaderIndex == locationLen ) && matches( buf, locationHeader ) )
+         {
+            while ( ( ++i < n ) && ( buf[i] != '\r' ) && ( buf[i] != '\n' ) )
+            {
+               if ( buf[i] == ' ' )
+               {
+                  continue;
+               }
+
+               contentLocation.append( (char) ( buf[i] & 0x7f ) );
+            }
+
+            headers.addHeader( HTTPConstants.HEADER_CONTENT_LOCATION,
+                               contentLocation.toString(  ) );
+         }
+         else if ( ( endHeaderIndex == typeLen ) && matches( buf, typeHeader ) )
+         {
+            while ( ( ++i < n ) && ( buf[i] != '\r' ) && ( buf[i] != '\n' ) )
+            {
+               if ( buf[i] == ' ' )
+               {
+                  continue;
+               }
+
+               contentType.append( (char) ( buf[i] & 0x7f ) );
+            }
+
+            headers.addHeader( HTTPConstants.HEADER_CONTENT_TYPE,
+                               contentLocation.toString(  ) );
+         }
+         else
+         {
+            String       customHeaderName  = new String( buf, 0, endHeaderIndex - 2 );
+            StringBuffer customHeaderValue = new StringBuffer(  );
+
+            while ( ( ++i < n ) && ( buf[i] != '\r' ) && ( buf[i] != '\n' ) )
+            {
+               if ( buf[i] == ' ' )
+               {
+                  continue;
+               }
+
+               customHeaderValue.append( (char) ( buf[i] & 0x7f ) );
+            }
+
+            headers.addHeader( customHeaderName,
+                               customHeaderValue.toString(  ) );
+         }
+      }
+
+      return len;
+   }
+
+   /**
+    * output an integer into the output stream
+    *
+    * @param out   OutputStream to be written to
+    * @param value Integer value to be written.
+    */
+   private void putInt( byte[]       buf,
+                        OutputStream out,
+                        int          value )
+   throws java.io.IOException
+   {
+      int len    = 0;
+      int offset = buf.length;
+
+      // negative numbers
+      if ( value < 0 )
+      {
+         buf[--offset]    = (byte) '-';
+         value            = -value;
+         len++;
+      }
+
+      // zero
+      if ( value == 0 )
+      {
+         buf[--offset] = (byte) '0';
+         len++;
+      }
+
+      // positive numbers
+      while ( value > 0 )
+      {
+         buf[--offset]    = (byte) ( ( value % 10 ) + '0' );
+         value            = value / 10;
+         len++;
+      }
+
+      // write the result
+      out.write( buf, offset, len );
+   }
+
+   /**
+    * Read a single line from the input stream
+    *
+    * @param is  inputstream to read from
+    * @param b   byte array to read into
+    * @param off starting offset into the byte array
+    * @param len maximum number of bytes to read
+    */
+   private int readLine( NonBlockingBufferedInputStream is,
+                         byte[]                         b,
+                         int                            off,
+                         int                            len )
+   throws java.io.IOException
+   {
+      int count = 0;
+      int c;
+
+      while ( ( c = is.read(  ) ) != -1 )
+      {
+         if ( ( c != '\n' ) && ( c != '\r' ) )
+         {
+            b[off++] = (byte) c;
+            count++;
+         }
+
+         if ( count == len )
+         {
+            break;
+         }
+
+         if ( '\n' == c )
+         {
+            int peek = is.peek(  ); //If the next line begins with tab or space then this is a continuation.
+
+            if ( ( peek != ' ' ) && ( peek != '\t' ) )
+            {
+               break;
+            }
+         }
+      }
+
+      return ( count > 0 ) ? count : ( -1 );
+   }
+}
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: apollo-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: apollo-dev-help@ws.apache.org