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