You are viewing a plain text version of this content. The canonical link for it is here.
Posted to muse-dev@ws.apache.org by wi...@apache.org on 2005/08/12 22:45:46 UTC

svn commit: r232376 [8/112] - in /webservices/muse/trunk/src/examples/client: ./ bin/ bin/axis/ bin/axis/com/ bin/axis/com/xyz/ bin/org/ bin/org/apache/ bin/org/apache/ws/ bin/org/apache/ws/client/ bin/org/apache/ws/client/async/ bin/org/apache/ws/clie...

Added: webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Consumer.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Consumer.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Consumer.java (added)
+++ webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Consumer.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,273 @@
+/*=============================================================================*
+ *  Confidential Copyright (c) 2004 Hewlett-Packard Development Company, L.P.  *
+ *=============================================================================*/
+package org.apache.ws.client.util;
+
+import org.apache.ws.client.model.WsdmClient;
+import org.apache.ws.client.model.WsdmClientFactory;
+import org.apache.ws.client.model.WsdmInstance;
+import org.apache.ws.client.model.WsdmResource;
+import com.ibm.xmlns.stdwip.webServices.wsBaseNotification.NotifyDocument;
+import com.ibm.xmlns.stdwip.webServices.wsBaseNotification.TopicExpressionType;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+import javax.xml.namespace.QName;
+import java.net.URL;
+
+/**
+ * Object that represents a notification consumer.  This object will take care of
+ * creating and destroying subscriptions as well as spawning a notification consumer
+ * endpoint that can be used to accept incoming notification messages from producers.
+ * <p/>
+ * This class is meant to be subclassed.  The subclass is to use the subscriber to create
+ * subscriptions and should also override {@link #consume(NotifyDocument)} to process
+ * notifications generated from those subscriptions.
+ */
+public class Consumer
+{
+   /** the default port that will be listened to by the listener */
+   private static final int DEFAULT_LISTENER_PORT = 9090;
+
+   /** object used to manage subscriptions */
+   private Subscriber m_subscriber;
+
+   /** listens for incoming notification requests */
+   private SimpleHttpPortListener m_listener;
+
+   /** the port that will be listened to be the listener */
+   private int m_listenerPort;
+
+   /** <code>true</code> when the consumer has started its listener and is ready to consume notifications */
+   private boolean m_started;
+
+   /**
+    * Creates the consumer object but does not start it.  Call {@link #start()} to begin consuming.
+    */
+   public Consumer(  )
+   {
+      m_subscriber      = null;
+      m_listener        = null;
+      m_listenerPort    = DEFAULT_LISTENER_PORT;
+      m_started         = false;
+   }
+
+   /**
+    * FOR TESTING ONLY!!!!!!!!!!!!!!!
+    * We can delete this later.
+    * 
+    * @param args DOCUMENT_ME
+    * @throws Exception
+    */
+   public static void main( String[] args )
+   throws Exception
+   {
+      /** just a test util class to house common test code for this main method */
+      final class Util
+      {
+         /** */
+         public WsdmInstance getMyInstance(  )
+         throws Exception
+         {
+            WsdmClient     wc =
+               WsdmClientFactory.create( WsdmClientFactory.AXIS_CLIENT_TYPE, "localhost:8080", "wsdm" );
+            WsdmResource   wr = wc.getResource( "sensor" );
+            WsdmInstance[] wi = wr.getInstances(  );
+
+            return wi[0];
+         }
+
+         /** */
+         public TopicExpressionType getMyTopicExpressionType( WsdmInstance wi )
+         throws Exception
+         {
+            QName       tq =
+               new QName( "http://www.ibm.com/xmlns/stdwip/web-services/WS-BaseNotification", "Topic" );
+            XmlObject[] topics = wi.getPropertyValue( tq );
+
+            return TopicExpressionType.Factory.parse( topics[1].newInputStream(  ) );
+         }
+      }
+
+      // read the comments for this MyConsumer class - it tells you how you use the Consumer class
+
+      /**
+       * Demonstrates the usage pattern for Consumer class.
+       * We extend it and subscribe to the things we want to consume.
+       * We can then override consume() to do what we want.
+       */
+      final class MyConsumer
+         extends Consumer
+      {
+         /** we can do with the notification what we want here- for testing, just delegate to superclass */
+         protected void consume( NotifyDocument notif )
+         {
+            super.consume( notif );
+         }
+
+         /** if we want to, we can have our consumer subclass do the subscribing */
+         public void start(  )
+         {
+            super.start(  ); // make sure you start first - this creates our subscriber
+
+            try
+            {
+               // now we can subscribe to the notification producers
+               WsdmInstance        notifProducer = new Util(  ).getMyInstance(  );
+               TopicExpressionType tet = new Util(  ).getMyTopicExpressionType( notifProducer );
+
+               getSubscriber(  ).subscribe( notifProducer, tet );
+            }
+            catch ( Exception e )
+            {
+               e.printStackTrace(  );
+            }
+         }
+      }
+
+      // here our main method creates our consumer class - if we want, we can subscribe to producers here
+      // note that if our consumer already subscribed, we don't have to do this
+      // but nothing is stopping us from telling the consumer to subscribe to more things here
+      // this is helpful if, during runtime, we want the consumer to subscribe to new notifications
+      Consumer c = new MyConsumer(  );
+      c.start(  );
+
+      WsdmInstance        notifProducer = new Util(  ).getMyInstance(  );
+      TopicExpressionType tet = new Util(  ).getMyTopicExpressionType( notifProducer );
+      c.getSubscriber(  ).subscribe( notifProducer, tet );
+
+      c.stop(  );
+   }
+
+   /**
+    * Returns this consumer's endpoint URL.  If this consumer has not yet been {@link #start() started},
+    * this method will return <code>null</code>.
+    *
+    * @return this consumer's endpoint URL that producers send notifications to; <code>null</code> if not consuming yet
+    */
+   public URL getConsumerUrl(  )
+   {
+      return ( m_started ) ? m_listener.getServerUrl(  ) : null;
+   }
+
+   /**
+    * Starts the consumer.  This creates a network endpoint that begins accepting incoming notifications.
+    */
+   public void start(  )
+   {
+      if ( !m_started )
+      {
+         final int consumerPort = getListenerPort(  );
+         final int timeout = 0; // wait for an infinite time for notifications to come in
+
+         m_listener      = new SimpleHttpPortListener( consumerPort, timeout );
+         m_subscriber    = new Subscriber( m_listener.getServerUrl(  ) );
+
+         // start a thread that continually listens for new notifications and consumes them as they come in
+         new Thread( new Runnable(  )
+            {
+               public void run(  )
+               {
+                  while ( !m_listener.isStopped(  ) )
+                  {
+                     String incomingMsg = m_listener.waitForIncomingMessage(  );
+
+                     if ( incomingMsg != null )
+                     {
+                        String notifXml = m_listener.getHttpBody( incomingMsg );
+
+                        if ( notifXml != null )
+                        {
+                           try
+                           {
+                              consume( NotifyDocument.Factory.parse( notifXml ) );
+                           }
+                           catch ( XmlException e )
+                           {
+                              e.printStackTrace(  );
+                           }
+                        }
+                     }
+                  }
+
+                  return; // notification consumer thread is exiting
+               }
+            },
+                     "notification-consumer" ).start(  );
+
+         m_started = true;
+      }
+
+      return;
+   }
+
+   /**
+    * Stops the consumer.  This terminates the network endpoint which disallows all future incoming notifications.
+    * Any currently existing subscriptions are canceled.
+    */
+   public void stop(  )
+   {
+      if ( m_started )
+      {
+         try
+         {
+            m_subscriber.unsubscribe(  );
+            m_listener.stopListening(  );
+            m_started = false;
+         }
+         catch ( Exception e )
+         {
+            throw new RuntimeException( e );
+         }
+      }
+
+      return;
+   }
+
+   /**
+    * Sets the port in which this consumer's listener will listen to.
+    * Subclasses are free to call this in order to set their own port.
+    * Note that calling this method while the consumer is {@link #start() started}
+    * has no effect until the consumer is {@link #stop() stopped} and restarted.
+    *
+    * @param port port that is to be listened to for notifications
+    */
+   protected void setListenerPort( int port )
+   {
+      m_listenerPort = port;
+   }
+
+   /**
+    * Returns the port in which this consumer's listener will listen to.
+    * Subclasses may {@link #setListenerPort(int) set} the port; otherwise, the default
+    * will be {@link #DEFAULT_LISTENER_PORT}.
+    *
+    * @return port that is to be listened to for notifications
+    */
+   protected int getListenerPort(  )
+   {
+      return m_listenerPort;
+   }
+
+   /**
+    * Returns the <code>Subscriber</code> used by this object to manage subscriptions.
+    * Subclasses are free to use this Subscriber to subscribe/unsubcribe to any notification
+    * producer they choose.
+    *
+    * @return the subscriber that this object uses to manage subscriptions
+    */
+   protected Subscriber getSubscriber(  )
+   {
+      return m_subscriber;
+   }
+
+   /**
+    * The default consumption implementation that simply outputs the notification XML to stdout.
+    * Subclasses should normally override this method to perform its own custom tasks.
+    *
+    * @param notif the notification being consumed
+    */
+   protected void consume( NotifyDocument notif )
+   {
+      System.out.println( notif.xmlText(  ) );
+   }
+}
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/EnvelopeWrapper.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/EnvelopeWrapper.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/EnvelopeWrapper.java (added)
+++ webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/EnvelopeWrapper.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,79 @@
+/*=============================================================================*
+ *  Confidential Copyright (c) 2004 Hewlett-Packard Development Company, L.P.  *
+ *=============================================================================*/
+package org.apache.ws.client.util;
+
+import org.apache.commons.io.IoUtils;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+import org.xmlsoap.schemas.soap.envelope.Envelope;
+import org.xmlsoap.schemas.soap.envelope.EnvelopeDocument;
+
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Wraps an XmlBean Envelope (or a javax.xml.soap.SOAPMessage class) to provide
+ * utility methods for getting at the XmlBean objects.
+ *
+ * @author Ian Springer, Sal Campana
+ */
+public class EnvelopeWrapper
+{
+   private Envelope m_envelope;
+
+   /**
+    * Constructor.  Takes an XmlBean Envelope type.
+    *
+    * @param envelope
+    */
+   public EnvelopeWrapper( Envelope envelope )
+   {
+      m_envelope = envelope;
+   }
+
+   /**
+    * Constructor.  Takes a java.xml.soap.SOAPMessage type and converts
+    * it to an XmlObject Envelope type inside the wrapper.
+    *
+    * @param message
+    * @throws IOException
+    * @throws SOAPException
+    * @throws XmlException
+    */
+   public EnvelopeWrapper( SOAPMessage message )
+   throws IOException, 
+          SOAPException, 
+          XmlException
+   {
+      ByteArrayOutputStream byteout = new ByteArrayOutputStream(  );
+      message.writeTo( byteout );
+      ByteArrayInputStream byteinput = IoUtils.toByteArrayInputStream( byteout );
+      m_envelope = ((EnvelopeDocument) XmlObject.Factory.parse( byteinput )).getEnvelope();
+      byteout.close(  );
+      byteinput.close(  );
+   }
+
+   /**
+    * Returns the BodyWrapper class for accessing the body XmlObjects
+    *
+    * @return BodyWrapper
+    */
+   public BodyWrapper getBodyWrapper(  )
+   {
+      return new BodyWrapper( m_envelope.getBody(  ) );
+   }
+
+   /**
+    * Returns the HeaderWrapper class for accessing the header XmlObjects
+    *
+    * @return HeaderWrapper
+    */
+   public HeaderWrapper getHeaderWrapper(  )
+   {
+      return new HeaderWrapper( m_envelope.getHeader(  ) );
+   }
+}
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/HeaderWrapper.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/HeaderWrapper.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/HeaderWrapper.java (added)
+++ webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/HeaderWrapper.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,86 @@
+/*=============================================================================*
+ *  Confidential Copyright (c) 2004 Hewlett-Packard Development Company, L.P.  *
+ *=============================================================================*/
+package org.apache.ws.client.util;
+
+import org.apache.xmlbeans.XmlCursor;
+import org.apache.xmlbeans.XmlObject;
+import org.xmlsoap.schemas.soap.envelope.Header;
+import javax.xml.namespace.QName;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Wraps an XmlBean generated Header to provide
+ * utility methods for getting at the XmlBean objects.
+ *
+ * @author Ian Springer, Sal Campana
+ */
+public class HeaderWrapper
+{
+   private Header m_header;
+
+   /**
+    * Creates a new {@link HeaderWrapper} object.
+    *
+    * @param header
+    */
+   public HeaderWrapper( Header header )
+   {
+      m_header = header;
+   }
+
+   /**
+    * Returns the top-level elements from the header as an XmlBean Object[].
+    *
+    * @return XmlObject[] of header elements
+    */
+   public XmlObject[] getHeaderElements(  )
+   {
+      if ( m_header == null )
+      {
+         return new XmlObject[0];
+      }
+
+      XmlCursor xmlCursor = m_header.newCursor(  );
+      xmlCursor.toNextToken(  );
+
+      //get the first child of the body i.e. the response message, or fault
+      XmlObject xmlBeanResponseMessage = xmlCursor.getObject(  );
+      List      xmlObjects = new ArrayList(  );
+      xmlObjects.add( xmlBeanResponseMessage );
+
+      //add the rest of the top-level-elements to the list
+      while ( xmlCursor.toNextSibling(  ) )
+      {
+         xmlObjects.add( xmlCursor.getObject(  ) );
+      }
+
+      return (XmlObject[]) xmlObjects.toArray( new XmlObject[0] );
+   }
+
+   /**
+    * Returns the top-level header elements with the specified name.
+    *
+    * @return the top-level header elements with the specified name
+    */
+   public XmlObject[] getHeaderElements( QName qName )
+   {
+      if ( qName == null )
+      {
+         throw new IllegalArgumentException( "Null name is not allowed." );
+      }
+
+      XmlObject[] allHeaderElems = getHeaderElements(  );
+      List        headerElems = new ArrayList(  );
+      for ( int i = 0; i < allHeaderElems.length; i++ )
+      {
+         if ( qName.equals( allHeaderElems[i].schemaType(  ).getName(  ) ) )
+         {
+            headerElems.add( allHeaderElems[i] );
+         }
+      }
+
+      return (XmlObject[]) headerElems.toArray( new XmlObject[0] );
+   }
+}
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimpleHttpPortListener.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimpleHttpPortListener.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimpleHttpPortListener.java (added)
+++ webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimpleHttpPortListener.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,159 @@
+/*=============================================================================*
+ *  Confidential Copyright (c) 2004 Hewlett-Packard Development Company, L.P.  *
+ *=============================================================================*/
+package org.apache.ws.client.util;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HeaderGroup;
+import java.net.InetAddress;
+import java.net.URL;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+
+/**
+ * Listens for incoming HTTP messages and provides convienence methods to access
+ * HTTP headers and the HTTP body.  An HTTP response will be sent back to the client in reponse
+ * to all messages received.
+ */
+public class SimpleHttpPortListener
+   extends SimplePortListener
+{
+   /** format used to build a date for the HTTP response that is returned to the client sending us a message */
+   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" ) );
+   }
+
+   /**
+    * @see SimplePortListener#SimplePortListener(int, int)
+    */
+   public SimpleHttpPortListener( int port,
+                                  int timeout )
+   {
+      super( port, timeout );
+   }
+
+   /**
+    * Returns a URL of the form <code>http://hostname:port</code> where
+    * <code>hostname</code> and <code>port</code> is of this listener.
+    *
+    * @return the HTTP URL used to access this listener
+    */
+   public URL getServerUrl(  )
+   {
+      try
+      {
+         return new URL( "http://" + InetAddress.getLocalHost(  ).getCanonicalHostName(  ) + ":"
+                         + getServerSocket(  ).getLocalPort(  ) );
+      }
+      catch ( Exception e )
+      {
+         return null;
+      }
+   }
+
+   /**
+    * Returns the HTTP body of the <code>message</code> string.
+    * If it doesn't look like an HTTP message, <code>null</code> is returned.
+    *
+    * @param message the HTTP message (typically this is the value returned by {@link SimplePortListener#waitForIncomingMessage()})
+    *
+    * @return the HTTP body of the message (the HTTP headers will be stripped out)
+    */
+   public String getHttpBody( String message )
+   {
+      final String headersBodyDelimiter = "\r\n\r\n";
+      int          endOfHeaders = message.indexOf( headersBodyDelimiter );
+      int          startOfBody  = endOfHeaders + headersBodyDelimiter.length(  );
+
+      return ( endOfHeaders != -1 ) ? message.substring( startOfBody ) : null;
+   }
+
+   /**
+    * Returns the HTTP headers found in the given HTTP message in a map keyed on the header names.
+    * If <code>message</code> doesn't look like an HTTP message, <code>null</code> is returned.
+    *
+    * @param message the HTTP message (typically this is the value returned by {@link SimplePortListener#waitForIncomingMessage()})
+    *
+    * @return the HTTP headers found in the message (the HTTP body will be ignored)
+    */
+   public Map getHttpHeaders( String message )
+   {
+      final String headersDelimiter      = "\r\n"; // each header is separated by this
+      final String nvpDelimiter          = ":"; // delimits between a header's name and value
+      final String headersStartDelimiter = "\r\n"; // from the start of the message, this delimits the first header
+      final String headersBodyDelimiter  = "\r\n\r\n"; // delimits between the headers and the HTTP body
+      int          endOfHeaders          = message.indexOf( headersBodyDelimiter );
+      int          startOfHeaders        = message.indexOf( headersStartDelimiter );
+
+      if ( ( endOfHeaders == -1 ) || ( startOfHeaders == -1 ) )
+      {
+         return null;
+      }
+
+      startOfHeaders += headersStartDelimiter.length(  ); // skip the delimiter
+
+      String          headers   = message.substring( startOfHeaders, endOfHeaders );
+      StringTokenizer strtok    = new StringTokenizer( headers, headersDelimiter );
+      Map             headerMap = new HashMap(  );
+
+      while ( strtok.hasMoreTokens(  ) )
+      {
+         String nvp               = strtok.nextToken(  );
+         int    nvpDelimiterIndex = nvp.indexOf( nvpDelimiter );
+         String name              = nvp.substring( 0, nvpDelimiterIndex );
+         String value             = nvp.substring( nvpDelimiterIndex + 1 );
+
+         headerMap.put( name.trim(  ),
+                        value.trim(  ) );
+      }
+
+      return headerMap;
+   }
+
+   /**
+    * 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
+    */
+   protected String buildResponse(  )
+   {
+      final String httpServerName = "WS-NotificationConsumer/1.0";
+      final String httpVersion = "1.0";
+      final String httpStatus  = "202 Accepted";
+
+      Date         timeNow          = new Date(  );
+      Date         sameTimeTomorrow = new Date( timeNow.getTime(  ) + ( 24 * 60 * 60 * 1000 ) );
+      StringBuffer responseBuf      = new StringBuffer( "HTTP/" );
+
+      responseBuf.append( httpVersion );
+      responseBuf.append( " " );
+      responseBuf.append( httpStatus );
+      responseBuf.append( "\r\n" );
+      HeaderGroup headerGroup = new HeaderGroup(  );
+      headerGroup.addHeader( new Header( "Date",
+                                         HTTP_DATE_FORMAT.format( timeNow ) ) );
+      headerGroup.addHeader( new Header( "Server", httpServerName ) );
+      headerGroup.addHeader( new Header( "Cache-Control", "max-age=86400" ) );
+      headerGroup.addHeader( new Header( "Expires",
+                                         HTTP_DATE_FORMAT.format( sameTimeTomorrow ) ) );
+      Header[] headers = headerGroup.getAllHeaders(  );
+
+      for ( int i = 0; i < headers.length; i++ )
+      {
+         responseBuf.append( headers[i] );
+      }
+
+      return responseBuf.toString(  );
+   }
+}
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimplePortListener.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimplePortListener.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimplePortListener.java (added)
+++ webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/SimplePortListener.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,356 @@
+/*=============================================================================*
+ *  Confidential Copyright (c) 2004 Hewlett-Packard Development Company, L.P.  *
+ *=============================================================================*/
+package org.apache.ws.client.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Vector;
+
+/**
+ * A simple port listener that accepts multiple messages on a TCP/IP socket and returns a simple response string in reply.
+ * When this object is instantiated, it will spawn a thread
+ * and listen for messages on the specified port. Call {@link #waitForIncomingMessage()}
+ * to block, waiting for a message.  If multiple messages have been receieved, each call to
+ * {@link #waitForIncomingMessage()} will return the messages in the order than were received.
+ */
+public class SimplePortListener
+{
+   /** a value used to indicate that our listening thread has stopped */
+   public static final String STOP_LISTENING_MESSAGE = "ERROR: listening stopped";
+
+   /**
+    * the buffer to store the incoming message
+    */
+   private StringBuffer m_incomingMessage;
+
+   /**
+    * a list of all messages received but not yet picked up via {@link #waitForIncomingMessage()}
+    */
+   private Vector m_messages;
+
+   /** the thread that listens */
+   private Thread m_listenerThread;
+
+   /** will be true when this listener has been asked to stop */
+   private boolean m_stopped;
+
+   /** the server socket used to accept incoming messages */
+   private ServerSocket m_serverSocket;
+
+   /**
+    * 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 SimplePortListener( int port,
+                              int timeout )
+   {
+      m_incomingMessage    = new StringBuffer(  );
+      m_messages           = new Vector(  );
+      m_stopped            = false;
+
+      // spawn the thread (this assigns the thread to m_listenerThread and creates m_serverSocket)
+      spawnListeningThread( port, timeout );
+
+      // There is a small window of time between the listener thread getting created and the server socket getting bound.
+      // Wait for that small window of time to elapse.  This ensures that when the constructor returns, the listener thread
+      // has been created and the server socket is actually listening for messages.
+      while ( !m_serverSocket.isBound(  ) && !m_stopped && m_listenerThread.isAlive(  ) )
+      {
+         ;
+      }
+
+      return;
+   }
+
+   /**
+    * Returns <code>true</code> if there is at least one message that has been received.
+    * Use this method to determine if the next call to {@link #waitForIncomingMessage()} will block.
+    *
+    * @return <code>true</code> if a message has been received but not yet collected or <code>false</code>
+    *         if no messages are available to be collected yet.
+    *
+    * @see #waitForIncomingMessage()
+    */
+   public boolean isMessageAvailable(  )
+   {
+      return !m_messages.isEmpty(  );
+   }
+
+   /**
+    * Returns <code>true</code> if the listener has stopped listening for messages.  A stopped listener
+    * cannot be restarted.
+    *
+    * @return <code>true</code> if this object is no longer accepting new messages.
+    */
+   public boolean isStopped(  )
+   {
+      return m_stopped;
+   }
+
+   /**
+    * Tells this listener to stop listening for more messages.
+    */
+   public void stopListening(  )
+   {
+      m_stopped = true;
+
+      while ( m_listenerThread.isAlive(  ) )
+      {
+         try
+         {
+            m_serverSocket.close(  );
+         }
+         catch ( IOException e )
+         {
+         }
+
+         m_listenerThread.interrupt(  );
+      }
+
+      return;
+   }
+
+   /**
+    * Returns the next incoming message in the order it was received; waits for the incoming message if
+    * none have been received yet.  Call {@link #isMessageAvailable()} to determine if this method
+    * will block.
+    * <p/>
+    * This method will block waiting for the incoming message to come in or for
+    * an error to occur or until the listening has been {@link #stopListening() stopped}.
+    *
+    * @return the incoming message as an immutable <code>String</code>
+    *
+    * @see #isMessageAvailable()
+    */
+   public String waitForIncomingMessage(  )
+   {
+      String newMessage;
+
+      synchronized ( m_incomingMessage )
+      {
+         while ( ( m_messages.isEmpty(  ) ) && !m_stopped )
+         {
+            try
+            {
+               m_incomingMessage.wait( 1000 );
+            }
+            catch ( InterruptedException e )
+            {
+            }
+         }
+
+         synchronized ( m_messages )
+         {
+            if ( !m_messages.isEmpty(  ) )
+            {
+               newMessage = (String) m_messages.get( 0 );
+               m_messages.remove( 0 );
+            }
+            else
+            {
+               newMessage = STOP_LISTENING_MESSAGE;
+            }
+         }
+      }
+
+      return newMessage;
+   }
+
+   /**
+    * Returns the server socket used to receive incoming messages.
+    *
+    * @return the server socket that is or was used to receive incoming TCP/IP messages
+    */
+   protected ServerSocket getServerSocket(  )
+   {
+      return m_serverSocket;
+   }
+
+   /**
+    * Builds a simple response string that will be sent back to the client to acknowledge the receipt of the message.
+    * Subclasses may override this method if a more sophisticated response string should be sent back (such as a set of HTTP
+    * response headers).
+    *
+    * @return simple one-line response string.
+    */
+   protected String buildResponse(  )
+   {
+      return "Message Received";
+   }
+
+   /**
+    * Creates the thread that listens for incoming TCP/IP messages.  When an incoming message is received, it is stored in the
+    * <code>m_incomingMessage</code> string buffer and <code>notify</code> on that string buffer will
+    * be called to let the caller know that it is ready.  <code>m_messages</code> will be used to store immutable
+    * forms of all incoming messages that are received by the listening thread.
+    * <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 a simple one-line response string back to the client.
+    * <p/>
+    * The created thread will run indefinitely, or until {@link #stopListening() stopped}.
+    *
+    * @param port the port to listen to
+    * @param timeout the time (in milliseconds) the socket accept() will wait for an incoming connection
+    *
+    * @throws IllegalArgumentException if the given buffer was <code>null</code> or not empty
+    */
+   protected void spawnListeningThread( final int port,
+                                        final int timeout )
+   throws IllegalArgumentException
+   {
+      // 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(  );
+
+      m_listenerThread =
+         new Thread( new Runnable(  )
+            {
+               public void run(  )
+               {
+                  m_serverSocket = null;
+
+                  while ( !m_stopped )
+                  {
+                     try
+                     {
+                        // create our server socket if not yet created
+                        if ( m_serverSocket == null )
+                        {
+                           m_serverSocket = new ServerSocket( port );
+                           m_serverSocket.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 = m_serverSocket.accept(  );
+                        sock.setSoTimeout( 500 );
+
+                        BufferedInputStream  bufIn         = new BufferedInputStream( sock.getInputStream(  ) );
+                        BufferedOutputStream bufOut        = new BufferedOutputStream( sock.getOutputStream(  ) );
+                        byte[]               responseBytes = buildResponse(  ).toString(  ).getBytes(  );
+
+                        bufOut.write( responseBytes, 0, responseBytes.length );
+                        bufOut.flush(  );
+
+                        try
+                        {
+                           byte[] incoming = new byte[1];
+
+                           synchronized ( m_incomingMessage )
+                           {
+                              m_incomingMessage.setLength( 0 ); // clear it out
+
+                              while ( bufIn.read( incoming ) != -1 )
+                              {
+                                 m_incomingMessage.append( new String( incoming ) );
+                              }
+                           }
+                        }
+                        catch ( InterruptedIOException ignored )
+                        {
+                        }
+
+                        bufIn.close(  );
+                        bufOut.close(  );
+                     }
+                     catch ( Throwable t )
+                     {
+                        synchronized ( m_incomingMessage )
+                        {
+                           m_incomingMessage.delete( 0,
+                                                     m_incomingMessage.length(  ) );
+
+                           if ( !m_stopped )
+                           {
+                              m_incomingMessage.append( "ERROR:" );
+                              m_incomingMessage.append( t );
+                           }
+                        }
+                     }
+                     finally
+                     {
+                        synchronized ( m_incomingMessage )
+                        {
+                           // make sure something goes in the message, even if nothing was received
+                           // don't bother if we were stopped, we'll add our own stopped message
+                           if ( ( m_incomingMessage.length(  ) == 0 ) && !m_stopped )
+                           {
+                              m_incomingMessage.append( "ERROR: incoming message was empty" );
+                           }
+
+                           // add our new incoming message to the list of messages
+                           if ( m_incomingMessage.length(  ) > 0 )
+                           {
+                              m_messages.add( m_incomingMessage.toString(  ) );
+                           }
+
+                           // if we are stopped, add another message to let the client know we stopped
+                           if ( m_stopped )
+                           {
+                              m_messages.add( STOP_LISTENING_MESSAGE );
+                           }
+
+                           // wake up the wait method
+                           m_incomingMessage.notify(  );
+                        }
+
+                        if ( m_stopped && ( m_serverSocket != null ) )
+                        {
+                           try
+                           {
+                              m_serverSocket.close(  );
+                           }
+                           catch ( IOException ignored )
+                           {
+                           }
+                        }
+
+                        // do this as a fail safe
+                        synchronized ( listenerStarted )
+                        {
+                           listenerStarted.notify(  );
+                        }
+                     }
+                  }
+
+                  // this is the listener thread exiting
+                  return;
+               }
+            } );
+
+      // start listening and then return when the thread has officially gone live
+      // and the socket is ready to be accepted
+      synchronized ( listenerStarted )
+      {
+         m_listenerThread.setDaemon( true );
+         m_listenerThread.start(  );
+
+         try
+         {
+            listenerStarted.wait(  );
+         }
+         catch ( InterruptedException ignored )
+         {
+         }
+      }
+
+      return;
+   }
+}
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Subscriber.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Subscriber.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Subscriber.java (added)
+++ webservices/muse/trunk/src/examples/client/src/java/org/apache/ws/client/util/Subscriber.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,402 @@
+/*=============================================================================*
+ *  Confidential Copyright (c) 2004 Hewlett-Packard Development Company, L.P.  *
+ *=============================================================================*/
+package org.apache.ws.client.util;
+
+import org.apache.ws.client.model.WsdmClient;
+import org.apache.ws.client.model.WsdmInstance;
+import org.apache.ws.client.model.WsdmOperation;
+import com.ibm.xmlns.stdwip.webServices.wsBaseNotification.TopicExpressionType;
+import org.apache.xmlbeans.XmlObject;
+import org.xmlsoap.schemas.ws.x2003.x03.addressing.EndpointReferenceDocument;
+import org.xmlsoap.schemas.ws.x2003.x03.addressing.EndpointReferenceType;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Acts as a WS-Notification Subscriber and will subscribe a notification consumer to
+ * a set of notification producers.
+ * <p>
+ * This object groups subscriptions based on which notification producers are subscribed to with each
+ * group holding subscriptions to individual topics.
+ * <p>
+ * Subscriptions may be canceled individually (see {@link #unsubscribe(WsdmInstance, TopicExpressionType)})
+ * or en masse (see {@link #unsubscribe()} and {@link #unsubscribe(WsdmInstance)}).
+ */
+public class Subscriber
+{
+   /** the EPR of the notification consumer that is to be subscribed */
+   private final EndpointReferenceType m_notificationConsumer;
+
+   /** the set of all subscriptions, keyed on WsdmInstance objects (each value is also a Map of Subscriptions keyed on topic expression) */
+   private final Map m_subscriptions = new HashMap(  );
+
+   /**
+    * Creates the subscriber given a consumer's EPR.
+    *
+    * @param consumer the EPR of the consumer who will be subscribed
+    */
+   public Subscriber( EndpointReferenceType consumer )
+   {
+      m_notificationConsumer = consumer;
+   }
+
+   /**
+    * Creates the subscriber given a consumer's <code>WsdmInstance</code> object representation.
+    *
+    * @param consumer the EPR of the consumer who will be subscribed
+    */
+   public Subscriber( WsdmInstance consumer )
+   {
+      try
+      {
+         m_notificationConsumer = consumer.getEPR(  );
+      }
+      catch ( Exception e )
+      {
+         throw new IllegalArgumentException( e.toString(  ) );
+      }
+   }
+
+   /**
+    * Creates the subscriber given just the consumer's endpoint URL.  Since only a URL is provided,
+    * the consumer's EPR will not consist of any WS-Addressing information.
+    *
+    * @param consumer the endpoint URL of the consumer
+    */
+   public Subscriber( URL consumer )
+   {
+      m_notificationConsumer = EndpointReferenceDocument.Factory.newInstance(  ).addNewEndpointReference(  );
+
+      m_notificationConsumer.addNewAddress(  ).setStringValue( consumer.toString(  ) );
+   }
+
+   /**
+    * Returns the EPR to a subscription resource for the subscription on the given producer topic.
+    * <code>null</code> will be returned if this object is not maintaining such a subscription.
+    *
+    * @param notificationProducer the producer resource whose is subscribed to
+    * @param topic the topic that is subscribed to
+    *
+    * @return the subscription resource EPR, or <code>null</code> if there is no such subscription
+    */
+   public synchronized Subscription getSubscription( WsdmInstance        notificationProducer,
+                                                     TopicExpressionType topic )
+   {
+      Subscription retSubscription       = null;
+      Map          producerSubscriptions = (Map) m_subscriptions.get( notificationProducer );
+
+      if ( producerSubscriptions != null )
+      {
+         retSubscription = (Subscription) producerSubscriptions.get( topic );
+      }
+
+      return retSubscription;
+   }
+
+   /**
+    * Returns an array of EPRs refering to all subscription resources for all subscriptions on the given producer.
+    * An empty array will be returned if no subscriptions exist.
+    *
+    * @param notificationProducer the producer resource whose is subscribed to
+    *
+    * @return array of subscription resource EPRs
+    */
+   public synchronized Subscription[] getSubscriptions( WsdmInstance notificationProducer )
+   {
+      Subscription[] retSubscriptions;
+      Map            producerSubscriptions = (Map) m_subscriptions.get( notificationProducer );
+
+      if ( producerSubscriptions != null )
+      {
+         Collection subscriptions = producerSubscriptions.values(  );
+         retSubscriptions = (Subscription[]) subscriptions.toArray( new Subscription[subscriptions.size(  )] );
+      }
+      else
+      {
+         retSubscriptions = new Subscription[0];
+      }
+
+      return retSubscriptions;
+   }
+
+   /**
+    * Returns an array of EPRs refering to all subscription resources for all subscriptions for all producers.
+    * An empty array will be returned if no subscriptions exist.
+    *
+    * @return array of subscription resource EPRs
+    */
+   public synchronized Subscription[] getSubscriptions(  )
+   {
+      List retSubscriptions = new ArrayList(  );
+
+      for ( Iterator iter = m_subscriptions.values(  ).iterator(  ); iter.hasNext(  ); )
+      {
+         Map producerSubscriptions = (Map) iter.next(  );
+
+         retSubscriptions.addAll( producerSubscriptions.values(  ) );
+      }
+
+      return (Subscription[]) retSubscriptions.toArray( new Subscription[retSubscriptions.size(  )] );
+   }
+
+   /**
+    * Subscribes the notification consumer to the given notification producer on the given topic.
+    * If the subscription already exists, this method will <b>not</b> subscribe again.
+    *
+    * @param notificationProducer the producer of the notifications to be subscribed to
+    * @param topicExpression the topic to subscribe to
+    *
+    * @throws Exception on any error that caused the request to fail
+    */
+   public synchronized void subscribe( WsdmInstance        notificationProducer,
+                                       TopicExpressionType topicExpression )
+   throws Exception
+   {
+      EndpointReferenceType subscriptionEpr;
+      WsdmOperation         subscribeOp = notificationProducer.findOperation( "Subscribe" );
+
+      if ( subscribeOp == null )
+      {
+         throw new IllegalArgumentException( "The given WsdmInstance is not a notification producer:"
+                                             + notificationProducer.getName(  ) );
+      }
+
+      // actually perform the subscribe
+      Hashtable params = new Hashtable(  );
+      params.put( "TopicExpression", topicExpression );
+      params.put( "ConsumerReference", m_notificationConsumer );
+      params.put( "UseNotify", Boolean.TRUE );
+
+      XmlObject[] results = notificationProducer.invoke( subscribeOp, params );
+
+      // TODO get the subscription resource EPR from the invoke results
+      subscriptionEpr = null;
+
+      // add the new subscription to our set of exiting subscriptions
+      addSubscription( new Subscription( notificationProducer, topicExpression, subscriptionEpr ) );
+
+      return;
+   }
+
+   /**
+    * Unsubscribes the notification consumer from the given notification producer's topic.
+    * If the subscription does not already exist, this method will do nothing.
+    *
+    * @param notificationProducer the producer of the notifications to be unsubscribed from
+    * @param topicExpression the topic to unsubscribe from
+    *
+    * @throws Exception on any error that caused the request to fail
+    */
+   public synchronized void unsubscribe( WsdmInstance        notificationProducer,
+                                         TopicExpressionType topicExpression )
+   throws Exception
+   {
+      Subscription doomedSubscription = getSubscription( notificationProducer, topicExpression );
+
+      unsubscribe( doomedSubscription );
+
+      return;
+   }
+
+   /**
+    * Unsubscribes the notification consumer from any and all subscribed topics from the given notification producer.
+    *
+    * @param notificationProducer the producer of the notifications to be unsubscribed from
+    *
+    * @throws Exception on any error that caused the request to fail
+    */
+   public synchronized void unsubscribe( WsdmInstance notificationProducer )
+   throws Exception
+   {
+      Subscription[] doomedSubscriptions = getSubscriptions( notificationProducer );
+
+      for ( int i = 0; i < doomedSubscriptions.length; i++ )
+      {
+         unsubscribe( doomedSubscriptions[i] );
+      }
+
+      return;
+   }
+
+   /**
+    * Unsubscribes the notification consumer from any and all topics on any and all notification producers.
+    *
+    * @throws Exception on any error that caused the request to fail
+    */
+   public synchronized void unsubscribe(  )
+   throws Exception
+   {
+      Subscription[] doomedSubscriptions = getSubscriptions(  );
+
+      for ( int i = 0; i < doomedSubscriptions.length; i++ )
+      {
+         unsubscribe( doomedSubscriptions[i] );
+      }
+
+      return;
+   }
+
+   /**
+    * Adds the given subscription to our internal set of existing subscriptions.
+    * This does not actually perform any type of subscribing, this method merely adds
+    * the subscription to our internal map structure.
+    *
+    * @param newSubscription the new subscription to add
+    */
+   protected void addSubscription( Subscription newSubscription )
+   {
+      // get the map of all the subscriptions to the producer of the new subscription
+      Map producerSubscriptions = (Map) m_subscriptions.get( newSubscription.getNotificationProducer(  ) );
+
+      // if this producer has not yet been subscribed to, create the new, empty map for it
+      if ( producerSubscriptions == null )
+      {
+         producerSubscriptions = new HashMap(  );
+         m_subscriptions.put( newSubscription.getNotificationProducer(  ),
+                              producerSubscriptions );
+      }
+
+      // add the new subscription to the map of producer subscriptions, keyed on the topic that is subscribed to
+      producerSubscriptions.put( newSubscription.getTopic(  ),
+                                 newSubscription );
+
+      return;
+   }
+
+   /**
+    * Removes the given subscription from our internal set of existing subscriptions.
+    * This does not actually perform any type of unsubscribing, this method merely removes
+    * the subscription from our internal map structure.
+    *
+    * @param doomedSubscription the subscription to remove
+    */
+   protected void removeSubscription( Subscription doomedSubscription )
+   {
+      // get the map of all the subscriptions to the producer of the doomed subscription
+      Map producerSubscriptions = (Map) m_subscriptions.get( doomedSubscription.getNotificationProducer(  ) );
+
+      if ( producerSubscriptions != null )
+      {
+         // remove the subscription from the map of producer subscriptions (this map is keyed on topic)
+         producerSubscriptions.remove( doomedSubscription.getTopic(  ) );
+
+         // if that was the last subscription for this producer, remove the entire producer subscription map, too
+         if ( producerSubscriptions.isEmpty(  ) )
+         {
+            m_subscriptions.remove( doomedSubscription.getNotificationProducer(  ) );
+         }
+      }
+
+      return;
+   }
+
+   /**
+    * Unsubscribes the given subscription and removes the subscription from our internal map structure.
+    *
+    * @param doomedSubscription the subscription that is to be destroyed
+    */
+   protected void unsubscribe( Subscription doomedSubscription )
+   {
+      // perform the actual WSDM unsubscribe here by destroying the subscription resource
+      WsdmInstance subscriptionWsdmInstance = doomedSubscription.getSubscriptionWsdmInstance(  );
+
+      try
+      {
+         WsdmOperation destroyOp = subscriptionWsdmInstance.findOperation( "Destroy" );
+         subscriptionWsdmInstance.invoke( destroyOp, null );
+      }
+      catch ( Exception e )
+      {
+         throw new IllegalArgumentException( "The subscription WsdmInstance does not conform to WS-ResourceLifetime:"
+                                             + subscriptionWsdmInstance.getName(  ) );
+      }
+
+      // remove the  subscription from our set of exiting subscriptions
+      removeSubscription( doomedSubscription );
+
+      return;
+   }
+
+   /**
+    * Immutable inner class used to hold information on an existing subscription, including the WsdmInstance
+    * of the notification producer, the topic subscribed to and the subscription resource EPR.
+    */
+   public class Subscription
+   {
+      private final WsdmInstance          m_notificationProducer;
+      private final TopicExpressionType   m_topic;
+      private final EndpointReferenceType m_subscriptionEpr;
+
+      /**
+       * Creates the object.
+       *
+       * @param notificationProducer the producer who is subscribed to
+       * @param topic the topic that is subscribed to
+       * @param subscriptionEpr the EPR of the subscription resource
+       */
+      public Subscription( final WsdmInstance          notificationProducer,
+                           final TopicExpressionType   topic,
+                           final EndpointReferenceType subscriptionEpr )
+      {
+         m_notificationProducer    = notificationProducer;
+         m_topic                   = topic;
+         m_subscriptionEpr         = subscriptionEpr;
+      }
+
+      /**
+       * Returns the notification producer.
+       *
+       * @return the notification producer
+       */
+      public WsdmInstance getNotificationProducer(  )
+      {
+         return m_notificationProducer;
+      }
+
+      /**
+       * Returns the subscription resource EPR.
+       *
+       * @return the subscription EPR
+       */
+      public EndpointReferenceType getSubscriptionEpr(  )
+      {
+         return m_subscriptionEpr;
+      }
+
+      /**
+       * Returns a <code>WsdmInstance</code> that can be used to access the
+       * Subscription resource.
+       * The returned Subscription resource has the WS-Notification Subscription Manager interface.
+       *
+       * @return subscription resource instance
+       */
+      public WsdmInstance getSubscriptionWsdmInstance(  )
+      {
+         WsdmInstance retSubcriptionInstance = null;
+         WsdmClient   producerClient = m_notificationProducer.getParent(  ).getParent(  );
+
+         // note that we assume the subscription resource is located in the same SOAP engine
+         // (host/port/servlet context) as the notification producer
+         // TODO retSubcriptionInstance = producerClient.findInstance( m_subscriptionEpr );
+         
+         return retSubcriptionInstance;
+      }
+
+      /**
+       * Returns the topic that is subscribed to.
+       *
+       * @return the subscribed topic
+       */
+      public TopicExpressionType getTopic(  )
+      {
+         return m_topic;
+      }
+   }
+}
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/test/axis/com/xyz/DiskWsdmServiceWSResource.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/test/axis/com/xyz/DiskWsdmServiceWSResource.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/test/axis/com/xyz/DiskWsdmServiceWSResource.java (added)
+++ webservices/muse/trunk/src/examples/client/src/test/axis/com/xyz/DiskWsdmServiceWSResource.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,415 @@
+/*=============================================================================*
+ *  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 axis.com.xyz;
+
+
+// [mod] imports for added code
+import org.apache.ws.resource.example.Disk;
+import org.apache.ws.resource.example.ExampleConstants;
+import org.apache.ws.resource.example.StateInfo;
+import org.apache.ws.muws.Muws05Constants;
+import org.apache.ws.muws.state.StateTransitionFailedException;
+import com.xyz.ActiveTimeDocument;
+import com.xyz.BlockSizeDocument;
+import com.xyz.FileSystemDocument;
+import com.xyz.ManufacturerDocument;
+import com.xyz.NotificationSimulator;
+import com.xyz.NumberOfBlocksDocument;
+import com.xyz.StateInfoDocument;
+import org.oasisOpen.docs.wsdm.x2004.x04.muws05.schema.DurationMetric;
+import org.oasisOpen.docs.wsdm.x2004.x04.muws05.schema.IntegerMetric;
+import org.oasisOpen.docs.wsdm.x2004.x04.muws05.schema.StateInformation;
+import javax.xml.soap.SOAPException;
+import java.util.Calendar;
+
+/**
+ * WSResource class to support the service <b>DiskWsdmService</b>.
+ * This is an auto-generated class that requires developer modification.
+ * Modified for use by our unit tests - ips, 09/11/04.
+ */
+public class DiskWsdmServiceWSResource
+   extends AbstractDiskWsdmServiceWSResource
+{
+   /** object used to log messages */
+   private static final org.apache.commons.logging.Log LOG =
+      org.apache.commons.logging.LogFactory.getLog( DiskWsdmServiceWSResource.class );
+
+   // [mod] added to simulate the true backend resource
+   private Disk m_backendDiskBean;
+
+   /**
+    * Constructor creating a new WSResource instance.
+    * [mod] changed to call added constructor that takes a Disk arg
+    *
+    * @param id the resource Id
+    *
+    * @throws Exception if failed to create the WSResource instance
+    */
+   public DiskWsdmServiceWSResource( String id )
+   throws Exception
+   {
+      this( new Disk( id ) );
+   }
+
+   /**
+    * Constructor creating a new WSResource instance.
+    * [mod] changed constructor param to Disk instead of String
+    *
+    * @param backendDisk the "backend" disk that this WSResource is fronting
+    *
+    * @throws Exception if failed to create the WSResource instance
+    */
+   public DiskWsdmServiceWSResource( Disk backendDisk )
+   throws Exception
+   {
+      // [mod] call super() specifying disk serial # as the resource Id
+      super( backendDisk.getSerialNumber(  ) );
+
+      // [mod] set m_backendDiskBean to the specified Disk bean
+      m_backendDiskBean = backendDisk;
+
+      // [mod] added this to support custom notification emission
+      // Demonstrate the support for non-property change notifications
+      setupBadSectorNotifications(  );
+   }
+
+   /**
+    * Adds a resource property to the backend managed resource.
+    *
+    * @param qname the name of the resource property to add
+    * @param bean an XmlBean that contains the initial value of the new resource property
+    *
+    * @return true if property was added successfully, false otherwise
+    */
+   public boolean addBackendProperty( javax.xml.namespace.QName     qname,
+                                      org.apache.xmlbeans.XmlObject bean )
+   {
+      // [mod] added logic to if blocks
+      if ( qname.equals( PropertyQNames.STATEINFO ) )
+      {
+         final StateInfo backendStateInfo = new StateInfo(  );
+         backendStateInfo.setState( ( (StateInfoDocument) bean ).getStateInfo(  ).getState(  ) );
+         backendStateInfo.setTimeEntered( ( (StateInfoDocument) bean ).getStateInfo(  ).getTimeEntered(  ) );
+         m_backendDiskBean.addStateInfo( backendStateInfo );
+      }
+      else if ( qname.equals( PropertyQNames.BLOCKSIZE ) )
+      {
+         m_backendDiskBean.setBlockSize( ( (BlockSizeDocument) bean ).getBlockSize(  ) );
+
+         // changing BlockSize will change the Capacity, so call refreshProperty() so the Capacity metric's LastUpdated attrib will be updated
+         try
+         {
+            refreshProperty( PropertyQNames.CAPACITY );
+         }
+         catch ( Exception e )
+         {
+            throw new RuntimeException( e );
+         }
+      }
+      else if ( qname.equals( PropertyQNames.FILESYSTEM ) )
+      {
+         m_backendDiskBean.addFilesystem( ( (FileSystemDocument) bean ).getFileSystem(  ) );
+      }
+      else if ( qname.equals( PropertyQNames.MANUFACTURER ) )
+      {
+         m_backendDiskBean.setManufacturer( ( (ManufacturerDocument) bean ).getManufacturer(  ) );
+      }
+      else if ( qname.equals( PropertyQNames.NUMBEROFBLOCKS ) )
+      {
+         m_backendDiskBean.setNumberOfBlocks( ( (NumberOfBlocksDocument) bean ).getNumberOfBlocks(  ) );
+
+         // changing NumberOfBlocks will change the Capacity, so call refreshProperty() so the Capacity metric's LastUpdated attrib will be updated
+         try
+         {
+            refreshProperty( PropertyQNames.CAPACITY );
+         }
+         catch ( Exception e )
+         {
+            throw new RuntimeException( e );
+         }
+      }
+      else if ( qname.equals( PropertyQNames.ACTIVETIME ) )
+      {
+         m_backendDiskBean.setActiveTime( ( (ActiveTimeDocument) bean ).getActiveTime(  ).getGDurationValue(  ) );
+      }
+      else
+      {
+         LOG.warn( "addBackendProperty() not implemented for property " + qname );
+      }
+
+      return true;
+   }
+
+   /**
+    * Refreshes the value of the resource property with the specified name.
+    * The method of retrieving backend properties is application-specific,
+    * so the application developer must fill in this method.
+    *
+    * @param propQName the name of the resource property to refresh
+    */
+   public void refreshProperty( javax.xml.namespace.QName propQName )
+   throws Exception
+   {
+      // [mod] added logic to if blocks
+      if ( propQName.equals( PropertyQNames.STATEINFO ) )
+      {
+         if ( m_backendDiskBean.getStateInfoList(  ).length != 0 )
+         {
+            final StateInfo[]        backendStateInfos = m_backendDiskBean.getStateInfoList(  );
+            final StateInformation[] stateInfoXBeans = new StateInformation[backendStateInfos.length];
+
+            for ( int i = 0; i < backendStateInfos.length; i++ )
+            {
+               final StateInformation stateInfoXBean = StateInformation.Factory.newInstance(  );
+               stateInfoXBean.setState( backendStateInfos[i].getState(  ) );
+               stateInfoXBean.setTimeEntered( backendStateInfos[i].getTimeEntered(  ) );
+               stateInfoXBeans[i] = stateInfoXBean;
+            }
+
+            getProperties(  ).setStateInfoArray( stateInfoXBeans );
+         }
+      }
+      else if ( propQName.equals( PropertyQNames.BLOCKSIZE ) )
+      {
+         if ( m_backendDiskBean.getBlockSize(  ) != -1 )
+         {
+            getProperties(  ).setBlockSize( m_backendDiskBean.getBlockSize(  ) );
+         }
+      }
+      else if ( propQName.equals( PropertyQNames.ACTIVETIME ) )
+      {
+         DurationMetric activeTime = getProperties(  ).getActiveTime(  );
+
+         if ( activeTime == null )
+         {
+            activeTime = DurationMetric.Factory.newInstance(  );
+            activeTime.setChangeType( DurationMetric.ChangeType.COUNTER );
+            activeTime.setTimeScope( DurationMetric.TimeScope.POINT_IN_TIME );
+         }
+
+         activeTime.setGDurationValue( m_backendDiskBean.getActiveTime(  ) );
+         activeTime.setLastUpdated( Calendar.getInstance(  ) );
+         getProperties(  ).setActiveTime( activeTime );
+      }
+      else if ( propQName.equals( PropertyQNames.CAPACITY ) )
+      {
+         IntegerMetric capacity = getProperties(  ).getCapacity(  );
+
+         if ( capacity == null )
+         {
+            capacity = IntegerMetric.Factory.newInstance(  );
+            capacity.setChangeType( IntegerMetric.ChangeType.GAUGE );
+            capacity.setTimeScope( IntegerMetric.TimeScope.POINT_IN_TIME );
+         }
+
+         capacity.setBigIntegerValue( m_backendDiskBean.getCapacity(  ) );
+         capacity.setLastUpdated( Calendar.getInstance(  ) );
+         getProperties(  ).setCapacity( capacity );
+      }
+      else if ( propQName.equals( PropertyQNames.FILESYSTEM ) )
+      {
+         if ( m_backendDiskBean.getFilesystems(  ).length != 0 )
+         {
+            getProperties(  ).setFileSystemArray( m_backendDiskBean.getFilesystems(  ) );
+         }
+      }
+      else if ( propQName.equals( PropertyQNames.MANUFACTURER ) )
+      {
+         if ( m_backendDiskBean.getManufacturer(  ) != null )
+         {
+            getProperties(  ).setManufacturer( m_backendDiskBean.getManufacturer(  ) );
+         }
+      }
+      else if ( propQName.equals( PropertyQNames.NUMBEROFBLOCKS ) )
+      {
+         if ( m_backendDiskBean.getNumberOfBlocks(  ) != null )
+         {
+            getProperties(  ).setNumberOfBlocks( m_backendDiskBean.getNumberOfBlocks(  ) );
+         }
+      }
+      else if ( propQName.equals( PropertyQNames.RESOURCESTATE ) )
+      {
+         if ( m_backendDiskBean.isStarted(  ) )
+         {
+            setResourceState( Muws05Constants.RESOURCE_STATE_URI_AVAILABLE );
+         }
+         else
+         {
+            setResourceState( Muws05Constants.RESOURCE_STATE_URI_UNAVAILABLE );
+         }
+      }
+      else if ( propQName.equals( PropertyQNames.TERMINATIONTIME ) )
+      {
+         getProperties(  ).setNilTerminationTime(  );
+      }
+      else if ( propQName.equals( PropertyQNames.FIXEDTOPICSET ) )
+      {
+         getProperties(  ).setFixedTopicSet( true );
+      }
+   }
+
+   /**
+    * Removes all data associated with the given resource property name from the backend managed resource.
+    *
+    * @param qname the name of the resource property to remove
+    *
+    * @return true if property was removed successfully, false otherwise
+    */
+   public boolean removeAllBackendProperties( javax.xml.namespace.QName qname )
+   {
+      // [mod] added logic to if blocks
+      if ( qname.equals( PropertyQNames.STATEINFO ) )
+      {
+         m_backendDiskBean.removeAllStateInfos(  );
+      }
+      else if ( qname.equals( PropertyQNames.BLOCKSIZE ) )
+      {
+         m_backendDiskBean.setBlockSize( -1 );
+      }
+      else if ( qname.equals( PropertyQNames.FILESYSTEM ) )
+      {
+         m_backendDiskBean.removeAllFilesystems(  );
+      }
+      else if ( qname.equals( PropertyQNames.MANUFACTURER ) )
+      {
+         m_backendDiskBean.setManufacturer( null );
+      }
+      else if ( qname.equals( PropertyQNames.NUMBEROFBLOCKS ) )
+      {
+         m_backendDiskBean.setNumberOfBlocks( null );
+      }
+      else
+      {
+         LOG.warn( "removeAllBackendProperties() not implemented for property " + qname );
+      }
+
+      return true;
+   }
+
+   /**
+    * If the metric property with the specified QName can be reset,
+    * then reset it on the "backend" resource and return true;
+    * otherwise, return false.
+    *
+    * @param propQName the QName of a metric property
+    *
+    * @return true if the specified "backend" property was reset, or false otherwise
+    */
+   protected boolean backendResetMetric( javax.xml.namespace.QName propQName )
+   {
+      if ( propQName.equals( PropertyQNames.CAPACITY ) )
+      {
+         // [mod] capacity metric cannot be reset.
+      }
+      else if ( propQName.equals( PropertyQNames.ACTIVETIME ) )
+      {
+         // [mod] added following two lines
+         m_backendDiskBean.setActiveTime( ExampleConstants.INITIAL_PROP_VALUE__ACTIVE_TIME );
+
+         return true;
+      }
+
+      return false;
+   }
+
+   /**
+    * This method will be invoked by the Muse infrastructure whenever
+    * the muws:ResourceState Start operation is called by a client.
+    * The MUWS service developer is responsible for adding code to this
+    * method that will appropriately update the state of the "backend"
+    * managed resource.
+    */
+   protected void backendStart(  )
+   throws StateTransitionFailedException
+   {
+      // [mod] below code added
+      try
+      {
+         m_backendDiskBean.start(  );
+      }
+      catch ( Exception e )
+      {
+         throw new StateTransitionFailedException( e );
+      }
+   }
+
+   /**
+    * This method will be invoked by the Muse infrastructure whenever
+    * the muws:ResourceState Stop operation is called by a client.
+    * The MUWS service developer is responsible for adding code to this
+    * method that will appropriately update the state of the "backend"
+    * managed resource.
+    */
+   protected void backendStop(  )
+   throws StateTransitionFailedException
+   {
+      // [mod] below code added
+      try
+      {
+         m_backendDiskBean.stop(  );
+      }
+      catch ( Exception e )
+      {
+         throw new StateTransitionFailedException( e );
+      }
+   }
+
+   /**
+    * DOCUMENT_ME
+    */
+   protected void registerForPropertyChangeNotifications(  )
+   {
+      // Make calls to register all properties that participate in property change notifications.
+      // [mod] removed register calls for resource properties that should not emit property change notifications
+      registerPropertyForChangeNotification( PropertyQNames.STATEINFO );
+      registerPropertyForChangeNotification( PropertyQNames.RESOURCESTATE );
+      registerPropertyForChangeNotification( PropertyQNames.BLOCKSIZE );
+      registerPropertyForChangeNotification( PropertyQNames.MANUFACTURER );
+      registerPropertyForChangeNotification( PropertyQNames.NUMBEROFBLOCKS );
+   }
+
+   // [mod] added setupBadSectorNotifications to support a custom notification
+
+   /**
+    * Demonstrates how to support a miscellaneous notification (i.e. not a property change notification).
+    * In this example we are demonstrating support for a BadSector topic.
+    *
+    * @throws SOAPException
+    */
+   private void setupBadSectorNotifications(  )
+   throws SOAPException
+   {
+      String namespace = "http://com.xyz";
+      String localName = "BadSector";
+
+      // To indicate that a particular notification topic is supported call the base class's
+      // registerBaseNotifTopic passing the namespace and localName of the topic.
+      // The topic is returned so that it can be used in the Notification process
+      com.ibm.xmlns.stdwip.webServices.wsBaseNotification.TopicExpressionType topic =
+         registerBaseNotifTopic( namespace, localName );
+
+      // The rest of this method is about setting up the NotificationSimulator class.
+      // Create a bad sector SOAP message with sectorId 6789
+      javax.xml.soap.SOAPElement badSectorMessage =
+         javax.xml.soap.SOAPFactory.newInstance(  ).createElement( localName, "ns1", namespace );
+      javax.xml.soap.SOAPElement sectorId = badSectorMessage.addTextNode( "SectorId" );
+      sectorId.setValue( "6789" );
+
+      // Start simulation of the bad sector notification issuing one every 5 seconds.
+      new NotificationSimulator( this,
+                                 getNotificationManager(  ), topic, badSectorMessage, 5000 );
+   }
+}
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/test/client-config.wsdd
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/test/client-config.wsdd?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/test/client-config.wsdd (added)
+++ webservices/muse/trunk/src/examples/client/src/test/client-config.wsdd Fri Aug 12 13:38:04 2005
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
+   <handler name="LogHandler" type="java:org.apache.axis.handlers.LogHandler">
+      <parameter name="LogHandler.fileName" value="C:/Projects/ws-rp/src/test/client.log"/>
+   </handler>
+   <handler name="AddressingHandler" type="java:org.apache.axis.message.addressing.handler.AddressingHandler" />
+   <handler name="AxisClientSideAddressingHandler" type="java:org.apache.axis.message.addressing.handler.AxisClientSideAddressingHandler" />
+   <globalConfiguration>
+      <requestFlow>
+         <!--
+         <handler type="java:org.apache.axis.handlers.JAXRPCHandler">
+            <parameter name="className" value="org.apache.axis.message.addressing.handler.AxisClientSideAddressingHandler"/>
+            <parameter name="referencePropertyNames" value="*"/>
+         </handler>
+         -->
+      </requestFlow>
+      <responseFlow>
+         <!--
+         <handler type="java:org.apache.axis.handlers.JAXRPCHandler">
+            <parameter name="className" value="org.apache.axis.message.addressing.handler.AxisClientSideAddressingHandler"/>
+            <parameter name="referencePropertyNames" value="*"/>
+         </handler>
+         -->
+      </responseFlow>
+   </globalConfiguration>
+   <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
+   <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/>
+</deployment>

Added: webservices/muse/trunk/src/examples/client/src/test/discovery-agent-registry.xml
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/test/discovery-agent-registry.xml?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/test/discovery-agent-registry.xml (added)
+++ webservices/muse/trunk/src/examples/client/src/test/discovery-agent-registry.xml Fri Aug 12 13:38:04 2005
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<discovery-config xmlns='http://apache.org/ws/resource/discovery/xml' >
+    <agent-list> 
+	    <agent>
+	        <name>Disk Resource Discovery Agent 1</name>
+	        <class>org.apache.ws.resource.example.discovery.DiskDiscoveryAgent</class>
+	        <properties>
+	            <property id="ResourceID">1234</property>
+	            <property id="ResourceID">5678</property>
+	        </properties>
+	    </agent>
+	    <agent>
+	        <name>Disk Resource Discovery Agent 2</name>
+	        <class>org.apache.ws.resource.example.discovery.DiskDiscoveryAgent</class>
+	        <properties>
+	            <property id="ResourceID">4321</property>
+	            <property id="ResourceID">8765</property>
+	        </properties>
+	    </agent>
+	</agent-list>
+</discovery-config>
\ No newline at end of file

Added: webservices/muse/trunk/src/examples/client/src/test/org/apache/ws/client/DynamicSchemaClassBuilderTestCase.java
URL: http://svn.apache.org/viewcvs/webservices/muse/trunk/src/examples/client/src/test/org/apache/ws/client/DynamicSchemaClassBuilderTestCase.java?rev=232376&view=auto
==============================================================================
--- webservices/muse/trunk/src/examples/client/src/test/org/apache/ws/client/DynamicSchemaClassBuilderTestCase.java (added)
+++ webservices/muse/trunk/src/examples/client/src/test/org/apache/ws/client/DynamicSchemaClassBuilderTestCase.java Fri Aug 12 13:38:04 2005
@@ -0,0 +1,230 @@
+/*=============================================================================*
+ *  Confidential Copyright (c) 2004 Hewlett-Packard Development Company, L.P.  *
+ *=============================================================================*/
+package org.apache.ws.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Iterator;
+
+import javax.wsdl.WSDLException;
+import javax.xml.namespace.QName;
+import javax.xml.soap.MessageFactory;
+import javax.xml.soap.SOAPElement;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.xmlbeans.XmlObject;
+
+import org.apache.commons.io.IoUtils;
+
+/**
+ * Test case for the DynamicSchemaClassBuilder.
+ *
+ * @author wire
+ *
+ */
+public class DynamicSchemaClassBuilderTestCase extends TestCase {
+	File m_tempDir;
+	URL m_wsdl_url;
+
+	/*
+	 * @see TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+
+		// Write out a test wsdl
+		String hashAsString=this.getClass().getName()+"@"+this.hashCode();
+		m_tempDir=new File(System.getProperty("java.io.tmpdir")+"/"+hashAsString);
+		m_tempDir.mkdir();
+		Assert.assertTrue(m_tempDir.exists());
+		File tempFile= new File("./src/wsdl/muse/registry.wsdl");
+		m_wsdl_url=tempFile.getAbsoluteFile().toURL();
+		m_builder = new DynamicSchemaClassBuilder("src\\wsdl\\muse",m_wsdl_url);
+		m_builder.compile();
+	}
+
+
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+		DynamicSchemaClassBuilder.dispose();
+		IoUtils.deleteDir(m_tempDir);
+	}
+
+
+	/**
+	 * Objective: Excersize schema compiler to create empty instances of classes from the smaple schema.
+	 * @throws WSDLException
+	 * @throws IOException
+	 * @throws SecurityException
+	 * @throws IllegalArgumentException
+	 * @throws ClassNotFoundException
+	 * @throws NoSuchMethodException
+	 * @throws IllegalAccessException
+	 * @throws InvocationTargetException
+	 */
+
+	public void testCreateInstance() throws WSDLException, IOException, SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException{
+		XmlObject xmlBean=m_builder.getEmptyInstanceOfXMLBean(new QName("http://schemas.xmlsoap.org/ws/2004/03/addressing","EndpointReference"));
+		Assert.assertNotNull(xmlBean);
+		String className=xmlBean.getClass().getName();
+		Assert.assertEquals(xmlBean.getClass().getName() , "org.xmlsoap.schemas.ws.x2004.x03.addressing.impl.EndpointReferenceDocumentImpl");
+
+		XmlObject xmlBean1=m_builder.getEmptyInstanceOfXMLBean(new QName("http://registry.generated.ws.apache.org","FindResourceRequest"));
+		Assert.assertNotNull(xmlBean1);
+		String className1=xmlBean1.getClass().getName();
+		Assert.assertEquals(xmlBean1.getClass().getName(),"org.apache.ws.generated.registry.impl.FindResourceRequestDocumentImpl");
+	}
+
+
+	public void testCreateInstanceFromXML() throws WSDLException, IOException, SecurityException, IllegalArgumentException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, SOAPException{
+
+		// Build a SOAP message
+		InputStream in=new ByteArrayInputStream(m_test_envelope.getBytes());
+		SOAPMessage soapResponseMsg = MessageFactory.newInstance().createMessage(null,in);
+		Iterator propElemsIter = soapResponseMsg.getSOAPPart().getEnvelope().getBody().getChildElements();
+		Assert.assertTrue(propElemsIter.hasNext());
+
+		// Iterate into it to find FindResponse element, an array of EndpointReferences
+		SOAPElement e=(SOAPElement)propElemsIter.next();
+		Iterator children = e.getChildElements();
+		Assert.assertTrue(children.hasNext());
+		SOAPElement elementFindResponse=(SOAPElement)children.next();
+
+		// Get a document bean
+		QName findResponseQName=new QName(e.getNamespaceURI(),e.getLocalName());
+		XmlObject xmlBean=m_builder.getInstanceOfXMLBean(findResponseQName,e);
+		Assert.assertNotNull(xmlBean);
+		String className=xmlBean.getClass().getName();
+		Assert.assertEquals("org.apache.ws.generated.registry.impl.FindResponseDocumentImpl",className);
+
+		// Extract an xmlBean
+		Method getFindResponseMethod=xmlBean.getClass().getMethod("getFindResponse",null);
+		Assert.assertNotNull(getFindResponseMethod);
+		XmlObject findResponse=(XmlObject)getFindResponseMethod.invoke(xmlBean,null);
+		Method getItemArrayMethod=findResponse.getClass().getMethod("getItemArray",null);
+		Object[] array=(Object[])getItemArrayMethod.invoke(findResponse,null);
+
+		// See if the returned array has for parts
+		Assert.assertEquals(4,array.length);
+		XmlObject endpointReferenceType=(XmlObject)array[0];
+		Method[] methods=endpointReferenceType.getClass().getMethods();
+
+		// Use introspection to tests some values
+//		XmlObject portType=(XmlObject)DynamicSchemaClassBuilder.getProperty(endpointReferenceType,"PortType");
+//		String localPart=(String)DynamicSchemaClassBuilder.getProperty(portType,"StringValue");//
+//		Assert.assertEquals("ns5:DiskPortType",localPart);
+
+		// Get ResourceID
+//		XmlObject refProps=(XmlObject)DynamicSchemaClassBuilder.getProperty(endpointReferenceType,"ReferenceProperties");
+		//Method[] methods = refProps.getClass().getMethods();
+		//String[] meths = DynamicSchemaClassBuilder.getProperties(refProps);
+		//XmlObject d=(XmlObject)DynamicSchemaClassBuilder.getProperty(endpointReferenceType,"refProps");
+		//Object id=DynamicSchemaClassBuilder.getProperty(refProps,"EnumValue");
+		//Method selectPathMethod = refProps.getClass().getMethod("selectPath",new Class[]{java.lang.String.class});
+		//Object ret = selectPathMethod.invoke(refProps,new Object[]{"ResourceID"});
+
+		System.out.println();
+	}
+
+	String m_test_envelope1="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"+
+	"   <soapenv:Body>\n"+
+	"      <ns1:findResourcesByServiceNameResponse xmlns:ns1=\"http://registry.generated.ws.apache.org\" >\n"+
+	"         <ns1:FindResponse xmlns:ns1=\"http://registry.generated.ws.apache.org\">\n"+
+	"            <ns1:item>\n"+
+	"               <ns2:Address xmlns:ns2=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">http://localhost:8080/wsdm/services/disk</ns2:Address>\n"+
+	"               <ns3:ReferenceProperties xmlns:ns3=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">\n"+
+	"                  <ns4:ResourceID xmlns:ns4=\"http://www.apache.org/props\">8765</ns4:ResourceID>\n"+
+	"               </ns3:ReferenceProperties>\n"+
+	"               <ns6:PortType xmlns:ns5=\"http://xyz.com/\" xmlns:ns6=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns5:DiskPortType</ns6:PortType>\n"+
+	"               <ns8:ServiceName PortName=\"disk\" xmlns:ns7=\"http://xyz.com/\" xmlns:ns8=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns7:DiskWsdmService</ns8:ServiceName>\n"+
+	"            </ns1:item>\n"+
+	"            <ns1:item>\n"+
+	"               <ns9:Address xmlns:ns9=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">http://localhost:8080/wsdm/services/disk</ns9:Address>\n"+
+	"               <ns10:ReferenceProperties xmlns:ns10=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">\n"+
+	"                  <ns11:ResourceID xmlns:ns11=\"http://www.apache.org/props\">5678</ns11:ResourceID>\n"+
+	"               </ns10:ReferenceProperties>\n"+
+	"               <ns13:PortType xmlns:ns12=\"http://xyz.com/\" xmlns:ns13=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns12:DiskPortType</ns13:PortType>\n"+
+	"               <ns15:ServiceName PortName=\"disk\" xmlns:ns14=\"http://xyz.com/\" xmlns:ns15=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns14:DiskWsdmService</ns15:ServiceName>\n"+
+	"            </ns1:item>\n"+
+	"            <ns1:item>\n"+
+	"               <ns16:Address xmlns:ns16=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">http://localhost:8080/wsdm/services/disk</ns16:Address>\n"+
+	"               <ns17:ReferenceProperties xmlns:ns17=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">\n"+
+	"                  <ns18:ResourceID xmlns:ns18=\"http://www.apache.org/props\">4321</ns18:ResourceID>\n"+
+	"               </ns17:ReferenceProperties>\n"+
+	"               <ns20:PortType xmlns:ns19=\"http://xyz.com/\" xmlns:ns20=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns19:DiskPortType</ns20:PortType>\n"+
+	"               <ns22:ServiceName PortName=\"disk\" xmlns:ns21=\"http://xyz.com/\" xmlns:ns22=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns21:DiskWsdmService</ns22:ServiceName>\n"+
+	"            </ns1:item>\n"+
+	"            <ns1:item>\n"+
+	"               <ns23:Address xmlns:ns23=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">http://localhost:8080/wsdm/services/disk</ns23:Address>\n"+
+	"               <ns24:ReferenceProperties xmlns:ns24=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">\n"+
+	"                  <ns25:ResourceID xmlns:ns25=\"http://www.apache.org/props\">1234</ns25:ResourceID>\n"+
+	"               </ns24:ReferenceProperties>\n"+
+	"               <ns27:PortType xmlns:ns26=\"http://xyz.com/\" xmlns:ns27=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns26:DiskPortType</ns27:PortType>\n"+
+	"               <ns29:ServiceName PortName=\"disk\" xmlns:ns28=\"http://xyz.com/\" xmlns:ns29=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">ns28:DiskWsdmService</ns29:ServiceName>\n"+
+	"            </ns1:item>\n"+
+	"         </ns1:FindResponse>\n"+
+	"      </ns1:findResourcesByServiceNameResponse>\n"+
+	"   </soapenv:Body></soapenv:Envelope>";
+
+	String m_test_envelope="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">"+
+	"  <soapenv:Header>"+
+	"    <wsa:MessageID soapenv:mustUnderstand=\"0\">uuid:51B07250-0DDA-11D9-A169-845A89F5F967</wsa:MessageID>"+
+	"    <wsa:To soapenv:mustUnderstand=\"0\">http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous</wsa:To>"+
+	"    <wsa:Action soapenv:mustUnderstand=\"0\">http://127.0.0.1:9009/axis/services/registry/actionResponse</wsa:Action>"+
+	"    <wsa:From soapenv:mustUnderstand=\"0\">"+
+	"      <Address xmlns=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">http://127.0.0.1:9009/axis/services/registry</Address>"+
+	"    </wsa:From>"+
+	"  </soapenv:Header>"+
+	"  <soapenv:Body>"+
+	"    <FindResponse xmlns=\"http://apache.org/ws/generated/registry\">"+
+	"      <item xsi:type=\"wsa:EndpointReferenceType\">"+
+	"        <wsa:Address>http://localhost:8080/wsdm/services/disk</wsa:Address>"+
+	"        <wsa:ReferenceProperties>"+
+	"          <ns1:ResourceID xmlns:ns1=\"urn:proposedstandard.org/muse/addressing\">1234</ns1:ResourceID>"+
+	"        </wsa:ReferenceProperties>"+
+	"        <wsa:PortType xmlns:ns2=\"http://xyz.com/\">ns2:DiskPortType</wsa:PortType>"+
+	"        <wsa:ServiceName PortName=\"disk\" xmlns:ns3=\"http://xyz.com/\">ns3:DiskWsdmService</wsa:ServiceName>"+
+	"      </item>"+
+	"      <item xsi:type=\"wsa:EndpointReferenceType\">"+
+	"        <wsa:Address>http://localhost:8080/wsdm/services/disk</wsa:Address>"+
+	"        <wsa:ReferenceProperties>"+
+	"          <ns4:ResourceID xmlns:ns4=\"urn:proposedstandard.org/muse/addressing\">8765</ns4:ResourceID>"+
+	"        </wsa:ReferenceProperties>"+
+	"        <wsa:PortType xmlns:ns5=\"http://xyz.com/\">ns5:DiskPortType</wsa:PortType>"+
+	"        <wsa:ServiceName PortName=\"disk\" xmlns:ns6=\"http://xyz.com/\">ns6:DiskWsdmService</wsa:ServiceName>"+
+	"      </item>"+
+	"      <item xsi:type=\"wsa:EndpointReferenceType\">"+
+	"        <wsa:Address>http://localhost:8080/wsdm/services/disk</wsa:Address>"+
+	"        <wsa:ReferenceProperties>"+
+	"          <ns7:ResourceID xmlns:ns7=\"urn:proposedstandard.org/muse/addressing\">4321</ns7:ResourceID>"+
+	"        </wsa:ReferenceProperties>"+
+	"        <wsa:PortType xmlns:ns8=\"http://xyz.com/\">ns8:DiskPortType</wsa:PortType>"+
+	"        <wsa:ServiceName PortName=\"disk\" xmlns:ns9=\"http://xyz.com/\">ns9:DiskWsdmService</wsa:ServiceName>"+
+	"      </item>"+
+	"      <item xsi:type=\"wsa:EndpointReferenceType\">"+
+	"        <wsa:Address>http://localhost:8080/wsdm/services/disk</wsa:Address>"+
+	"        <wsa:ReferenceProperties>"+
+	"          <ns10:ResourceID xmlns:ns10=\"urn:proposedstandard.org/muse/addressing\">5678</ns10:ResourceID>"+
+	"        </wsa:ReferenceProperties>"+
+	"        <wsa:PortType xmlns:ns11=\"http://xyz.com/\">ns11:DiskPortType</wsa:PortType>"+
+	"        <wsa:ServiceName PortName=\"disk\" xmlns:ns12=\"http://xyz.com/\">ns12:DiskWsdmService</wsa:ServiceName>"+
+	"      </item>"+
+	"    </FindResponse>"+
+	"  </soapenv:Body>"+
+	"</soapenv:Envelope>";
+
+	private DynamicSchemaClassBuilder m_builder;
+}



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