You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pubscribe-dev@ws.apache.org by sc...@apache.org on 2005/03/31 20:56:13 UTC

svn commit: r159623 - incubator/hermes/trunk/src/java/org/apache/ws/util/test/PortListen.java

Author: scamp
Date: Thu Mar 31 10:56:13 2005
New Revision: 159623

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


Added:
    incubator/hermes/trunk/src/java/org/apache/ws/util/test/PortListen.java

Added: incubator/hermes/trunk/src/java/org/apache/ws/util/test/PortListen.java
URL: http://svn.apache.org/viewcvs/incubator/hermes/trunk/src/java/org/apache/ws/util/test/PortListen.java?view=auto&rev=159623
==============================================================================
--- incubator/hermes/trunk/src/java/org/apache/ws/util/test/PortListen.java (added)
+++ incubator/hermes/trunk/src/java/org/apache/ws/util/test/PortListen.java Thu Mar 31 10:56:13 2005
@@ -0,0 +1,288 @@
+package org.apache.ws.util.test;
+
+/*=============================================================================*
+ *  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.
+ *=============================================================================*/
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.BufferedReader;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Single-message HTTP listener.  When this object is instantiated, it will spawn a thread
+ * and listen for a message on the specified port. Call {@link #waitForIncomingMessage()}
+ * to block, waiting for the message.
+ *
+ * @author mazz
+ * @author ips
+ */
+public class PortListen
+{
+   private static DateFormat HTTP_DATE_FORMAT = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US );
+
+   static
+   {
+      HTTP_DATE_FORMAT.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
+   }
+
+   /**
+    * the buffer to store the incoming message
+    */
+   private StringBuffer m_incomingMessage;
+
+   /**
+    * Instantiates the object and immediately begins listening for a message.
+    *
+    * @param port    the port to listen to
+    * @param timeout the time (in milliseconds) the socket accept() will wait for an incoming connection
+    */
+   public PortListen( int port,
+                      int timeout )
+   {
+      m_incomingMessage = new StringBuffer(  );
+
+      // spawn the thread
+      getIncomingMessage( port, timeout, m_incomingMessage );
+
+      return;
+   }
+
+   /**
+    * Waits for the incoming message.
+    * <p/>
+    * This method will block waiting for the incoming message to come in or for
+    * an error to occur.
+    *
+    * @return the incoming message as an immutable <code>String</code>
+    */
+   public String waitForIncomingMessage(  )
+   {
+      synchronized ( m_incomingMessage )
+      {
+         while ( m_incomingMessage.length(  ) == 0 )
+         {
+            try
+            {
+               m_incomingMessage.wait( 1000 );
+            }
+            catch ( InterruptedException e )
+            {
+            }
+         }
+      }
+
+      return m_incomingMessage.toString(  );
+   }
+
+   /**
+    * Listens for an incoming TCP/IP message.  When an incoming message is received, it is stored in the
+    * <code>retIncomingMessage</code> string buffer and <code>notify</code> on that string buffer will
+    * be called to let the caller know that it is ready.
+    * <p/>
+    * The incoming message string buffer must be non-<code>null</code> and must be empty.
+    * <p/>
+    * If an error occurs, the string buffer will be filled with the string "ERROR:" followed by the exception message.
+    * Even on an error, <code>notify</code> will be called to let the caller know that something happened.
+    * <p/>
+    * Note that this method does not block - it spawns a thread to perform the listening and returns immediately.
+    * <p/>
+    * This will return an HTTP server-like response back to the client.
+    *
+    * @param port               the port to listen to
+    * @param timeout            the time (in milliseconds) the socket accept() will wait for an incoming connection
+    * @param retIncomingMessage the incoming message to be returned to the caller - this buffer will be filled in and
+    *                           <code>notify</code> will be called on it to let the caller know that it is ready
+    *
+    * @throws IllegalArgumentException if the given buffer was <code>null</code> or not empty
+    */
+   protected void getIncomingMessage( final int          port,
+                                      final int          timeout,
+                                      final StringBuffer retIncomingMessage )
+   throws IllegalArgumentException
+   {
+      if ( ( retIncomingMessage == null ) || ( retIncomingMessage.length(  ) > 0 ) )
+      {
+         throw new IllegalArgumentException( "Must provide a non-null string buffer that is empty" );
+      }
+
+      // use as a monitor lock to determine when the thread has started
+      // this must be final to allow for the inner Runnable class to access it
+      final Object listenerStarted = new Object(  );
+
+      Thread       listener =
+         new Thread( new Runnable(  )
+            {
+               private final String m_httpServerName = "WS-NotificationConsumer/1.0";
+               private final String m_httpVersion = "1.0";
+               private final String m_httpStatus  = "202 Accepted";
+
+               public void run(  )
+               {
+                  ServerSocket server = null;
+
+                  try
+                  {
+                     server = new ServerSocket( port );
+                     server.setSoTimeout( timeout );
+
+                     // let the outer method know that we have started and just about to block on the accept
+                     synchronized ( listenerStarted )
+                     {
+                        listenerStarted.notify(  );
+                     }
+
+                     Socket sock = server.accept(  );
+                     sock.setSoTimeout( 500 );
+                     BufferedReader  bufIn  = new BufferedReader( new InputStreamReader( sock.getInputStream(  ) ) );
+                     BufferedOutputStream bufOut = new BufferedOutputStream( sock.getOutputStream(  ) );
+
+                     byte[]               responseBytes = buildResponse(  ).toString(  ).getBytes(  );
+
+
+
+                     try
+                     {
+                        String line;
+                        synchronized ( retIncomingMessage )
+                        {
+                           while ( ! (line = bufIn.readLine()).equals( "" ) )
+                           {
+                           }
+                            char[] buffer = new char[10240];
+                            int length = -1;
+                           while ( ( length = bufIn.read(buffer,0, buffer.length ) ) != -1 )
+                           {
+                               retIncomingMessage.append( buffer , 0, length );
+                           }
+                        }
+                     }
+                     catch ( InterruptedIOException ignored )
+                     {
+                     }
+                     bufOut.write( responseBytes, 0, responseBytes.length );
+                     bufOut.flush(  );
+                     bufIn.close(  );
+                     bufOut.close(  );
+                  }
+                  catch ( Throwable t )
+                  {
+                     synchronized ( retIncomingMessage )
+                     {
+                        retIncomingMessage.delete( 0,
+                                                   retIncomingMessage.length(  ) );
+                        retIncomingMessage.append( "ERROR:" );
+                        retIncomingMessage.append( t );
+                     }
+                  }
+                  finally
+                  {
+                     synchronized ( retIncomingMessage )
+                     {
+                        // make sure something goes in the message, even if nothing was received
+                        if ( retIncomingMessage.length(  ) == 0 )
+                        {
+                           retIncomingMessage.append( "ERROR: incoming message was empty" );
+                        }
+
+                        retIncomingMessage.notify(  );
+                     }
+
+                     if ( server != null )
+                     {
+                        try
+                        {
+                           server.close(  );
+                        }
+                        catch ( IOException ignored )
+                        {
+                        }
+                     }
+
+                     // do this as a fail safe
+                     synchronized ( listenerStarted )
+                     {
+                        listenerStarted.notify(  );
+                     }
+                  }
+
+                  return;
+               }
+
+               /**
+                * Build a one-way HTTP response message that complies to the WS-I
+                * Basic Profile 1.0, section 5.6.10 - see
+                * http://www.ws-i.org/Profiles/BasicProfile-1.0-2004-04-16.html#refinement16651160
+                *
+                * @return a WS-I-compliant Notify response message
+                */
+               private String buildResponse(  )
+               {
+                  Date         timeNow          = new Date(  );
+                  Date         sameTimeTomorrow = new Date( timeNow.getTime(  ) + ( 24 * 60 * 60 * 1000 ) );
+                  StringBuffer responseBuf      = new StringBuffer( "HTTP/" );
+                  responseBuf.append( m_httpVersion );
+                  responseBuf.append( " " );
+                  responseBuf.append( m_httpStatus );
+                  responseBuf.append( "\r\n" );
+
+                  responseBuf.append( "Date: " );
+                  responseBuf.append( HTTP_DATE_FORMAT.format( timeNow ) );
+                  responseBuf.append( "\r\n" );
+
+                  responseBuf.append( "Server: " );
+                  responseBuf.append( m_httpServerName );
+                  responseBuf.append( "\r\n" );
+
+                  responseBuf.append( "Cache-Control: " );
+                  responseBuf.append( "max-age=86400" );
+                  responseBuf.append( "\r\n" );
+
+                  responseBuf.append( "Expires: " );
+                  responseBuf.append( HTTP_DATE_FORMAT.format( sameTimeTomorrow ) );
+                  responseBuf.append( "\r\n" );
+
+                  return responseBuf.toString(  );
+               }
+            } );
+
+      // start listening and then return when the thread has officially gone live
+      // and the socket is ready to be accepted
+      synchronized ( listenerStarted )
+      {
+         listener.start(  );
+
+         try
+         {
+            listenerStarted.wait(  );
+         }
+         catch ( InterruptedException ignored )
+         {
+         }
+      }
+
+      return;
+   }
+}
\ No newline at end of file



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