luetzkendorf    2004/07/13 01:47:30

  Modified:    webdavclient/clientlib/src/java/org/apache/webdav/lib
                        WebdavResource.java
               webdavclient/clientlib/src/java/org/apache/webdav/lib/methods
                        SubscribeMethod.java UnsubscribeMethod.java
  Added:       webdavclient/clientlib/src/java/org/apache/webdav/lib
                        Subscription.java
               webdavclient/clientlib/src/java/org/apache/webdav/lib/event
                        Listener.java Notification.java
                        NotificationListener.java
                        NotificationProcessor.java
                        PrintingNotificationProcessor.java UDPListener.java
                        package.html
               webdavclient/clientlib/src/java/org/apache/webdav/lib/methods
                        PollMethod.java
  Log:
  continued to add notification support
  
  Revision  Changes    Path
  1.22      +175 -31   
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/WebdavResource.java
  
  Index: WebdavResource.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/WebdavResource.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- WebdavResource.java       6 Jul 2004 12:43:51 -0000       1.21
  +++ WebdavResource.java       13 Jul 2004 08:47:30 -0000      1.22
  @@ -40,51 +40,29 @@
   import java.util.Locale;
   import java.util.TimeZone;
   import java.util.Vector;
  +
   import org.apache.commons.httpclient.Credentials;
   import org.apache.commons.httpclient.HttpClient;
   import org.apache.commons.httpclient.HttpException;
   import org.apache.commons.httpclient.HttpMethod;
   import org.apache.commons.httpclient.HttpStatus;
  +import org.apache.commons.httpclient.HttpURL;
  +import org.apache.commons.httpclient.HttpsURL;
  +import org.apache.commons.httpclient.URIException;
   import org.apache.commons.httpclient.UsernamePasswordCredentials;
   import org.apache.commons.httpclient.methods.GetMethod;
   import org.apache.commons.httpclient.methods.HeadMethod;
   import org.apache.commons.httpclient.methods.PutMethod;
   import org.apache.commons.httpclient.util.URIUtil;
  +
   import org.apache.util.DOMUtils;
  -import org.apache.commons.httpclient.HttpURL;
  -import org.apache.commons.httpclient.HttpsURL;
  -import org.apache.commons.httpclient.URIException;
   import org.apache.util.WebdavStatus;
  -import org.apache.webdav.lib.methods.AclMethod;
  -import org.apache.webdav.lib.methods.AclReportMethod;
  -import org.apache.webdav.lib.methods.CheckinMethod;
  -import org.apache.webdav.lib.methods.CheckoutMethod;
  -import org.apache.webdav.lib.methods.CopyMethod;
  -import org.apache.webdav.lib.methods.DeleteMethod;
  -import org.apache.webdav.lib.methods.DepthSupport;
  -import org.apache.webdav.lib.methods.LabelMethod;
  -import org.apache.webdav.lib.methods.LockMethod;
  -import org.apache.webdav.lib.methods.MkWorkspaceMethod;
  -import org.apache.webdav.lib.methods.MkcolMethod;
  -import org.apache.webdav.lib.methods.MoveMethod;
  -import org.apache.webdav.lib.methods.OptionsMethod;
  -import org.apache.webdav.lib.methods.PropFindMethod;
  -import org.apache.webdav.lib.methods.PropPatchMethod;
  -import org.apache.webdav.lib.methods.ReportMethod;
  -import org.apache.webdav.lib.methods.UncheckoutMethod;
  -import org.apache.webdav.lib.methods.UnlockMethod;
  -import org.apache.webdav.lib.methods.UpdateMethod;
  -import org.apache.webdav.lib.methods.VersionControlMethod;
  -import org.apache.webdav.lib.methods.BindMethod;
  -import org.apache.webdav.lib.methods.UnbindMethod;
  -import org.apache.webdav.lib.methods.RebindMethod;
  +import org.apache.webdav.lib.methods.*;
   import org.apache.webdav.lib.properties.AclProperty;
   import org.apache.webdav.lib.properties.LockDiscoveryProperty;
   import org.apache.webdav.lib.properties.PrincipalCollectionSetProperty;
   import org.apache.webdav.lib.properties.ResourceTypeProperty;
   
  -import sun.text.Normalizer;
  -
   /**
    * The class <code>WebdavResource</code> is an abstract representation
    * for WebDAV resource.<p>
  @@ -5037,6 +5015,172 @@
           return statusCode >= 200 && statusCode < 300;
       }
   
  +    /**
  +     * Subscribes for notifications for modifications of WebDAV resources.
  +     * 
  +     * @param path URL path of the resource that is to be subscribed
  +     * @param notificationType 
  +     * @param callback the URL to be registered for notification, may be 
  +     *        <code>null</code> if no callback shall be registered.
  +     * @param notificationDelay
  +     * @param depth the depth of the subscription (for valid values see 
  +     *    [EMAIL PROTECTED] DepthSupport})
  +     * @param lifetime duration of that subscription in seconds (Note: the
  +     *    server may change this and return an other one; 
  +     *    see [EMAIL PROTECTED] Subscription#getLifetime()}.
  +     * 
  +     * @return a [EMAIL PROTECTED] Subscription} or <code>null</code> if an error 
occurs
  +     * @throws HttpException
  +     * @throws IOException
  +     */
  +    public Subscription subscribeMethod(String path, 
  +          String notificationType,
  +          String callback,
  +          long notificationDelay,
  +          int depth,
  +          long lifetime) 
  +       throws HttpException, IOException
  +    {
  +       setClient();
  +       
  +       SubscribeMethod method = new SubscribeMethod(path);
  +       method.setDebug(debug);
  +       method.setFollowRedirects(this.followRedirects);
  +
  +       method.setCallback(callback);
  +       method.setDepth(depth);
  +       method.setSubsciptionLifetime(lifetime);
  +       method.setNotificationType(notificationType);
  +       method.setNotificationDelay(notificationDelay);
  +       
  +       int statusCode = client.executeMethod(method);
  +       
  +       if (statusCode == HttpStatus.SC_OK) {
  +          return new Subscription(
  +                      path, 
  +                      method.getResponsedSubscriptionId(),
  +                      method.getCallback(),
  +                      method.getResponsedSubscriptionLifetime(),
  +                      method.getResponsedContentLocation(),
  +                      method.getNotificationType()
  +                );
  +       } else {
  +          return null;
  +       }
  +    }
  +    
  +    /**
  +     * Refreshes a subscription.
  +     * 
  +     * @return <code>true</code> on success.
  +     * @author Stefan L�tzkendorf
  +     */
  +    public boolean subscribeMethod(String path, int subscriptionId)
  +       throws HttpException, IOException
  +    {
  +       setClient();
  +       
  +       SubscribeMethod method = new SubscribeMethod(path);
  +       method.setDebug(debug);
  +       method.setFollowRedirects(this.followRedirects);
  +       
  +       method.setSubscriptionId(subscriptionId);
  +       
  +       int statusCode = client.executeMethod(method);
  +       
  +       if (statusCode == HttpStatus.SC_OK) {
  +          return true;
  +       } else {
  +          return false;
  +       } 
  +    }
  +    
  +    /**
  +     * Refreshes a subscription.
  +     * 
  +     * @param subscription The subscription to be refreshed.
  +     * @return <code>true</code> on success
  +     */
  +    public boolean subscribeMethod(Subscription subscription)
  +       throws HttpException, IOException
  +    {
  +       return subscribeMethod(subscription.getPath(), subscription.getId());
  +    }
  +    
  +    /**
  +     * Cancels a subscription.
  +     * @param path URL path for that was subscribed 
  +     * @return <code>true</code> on success
  +     */
  +    public boolean unsubscribeMethod(String path, int subscriptionId) 
  +       throws HttpException, IOException
  +    {
  +       setClient();
  +       
  +       UnsubscribeMethod method = new UnsubscribeMethod(path);
  +       method.setDebug(debug);
  +       method.setFollowRedirects(this.followRedirects);   
  +       
  +       method.addSubscriptionId(subscriptionId);
  +       
  +       int statusCode = client.executeMethod(method);
  +       
  +       if (statusCode == HttpStatus.SC_OK) {
  +          return true;
  +       } else {
  +          return false;
  +       }
  +    }
  +    /**
  +     * Cancels a subscription.
  +     * @param subscription
  +     * @return <code>true</code> on success
  +     */
  +    public boolean unsubscribeMethod(Subscription subscription) 
  +       throws HttpException, IOException
  +    {
  +       return unsubscribeMethod(subscription.getPath(),subscription.getId());
  +    }
  +    
  +    /**
  +     * Asks the server whether events for a given subscription are fired.
  +     * @param contentLocation URL path returned by the SUBSCRIBE methods
  +     *                        Content-Location header
  +     * @param subscriptionId id of the subscription
  +     * @return <code>true</code> if an event was fired
  +     */
  +    public boolean pollMethod(String contentLocation, int subscriptionId)
  +       throws HttpException, IOException
  +    {
  +       setClient();
  +       
  +       PollMethod method = new PollMethod(contentLocation);
  +       method.setDebug(debug);
  +       method.setFollowRedirects(this.followRedirects);
  +       
  +       method.addSubscriptionId(subscriptionId);
  +       
  +       int statusCode = client.executeMethod(method);
  +       
  +       if (statusCode == HttpStatus.SC_MULTI_STATUS) {
  +          return method.getSubscriptionsWithEvents().size() > 0;
  +       } else {
  +          return false;
  +       }
  +    }
  +    /**
  +     * Asks the server whether events for a given subscription are fired.
  +     * @param subscription the subscription to ask for
  +     * @return <code>true</code> if an event was fired
  +     */
  +    public boolean pollMethod(Subscription subscription)
  +       throws HttpException, IOException
  +    {
  +       return pollMethod(subscription.getContentLocation(), subscription.getId());
  +    }
  +
  +    
  +    
       private static String getName(String uri) {
           String escapedName = URIUtil.getName(
               uri.endsWith("/") ? uri.substring(0, uri.length() - 1): uri);
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/Subscription.java
  
  Index: Subscription.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.webdav.lib;
  
  /**
   * Object that holds information about a single WebDAV subscription.
   * 
   * @see org.apache.webdav.lib.WebdavResource#subscribeMethod(String, String, String, 
long, int, long)
   * @author Stefan L�tzkendorf
   */
  public class Subscription
  {
     public static final String UPDATE_NOTIFICATION = "update";
     public static final String NEW_MEMBER_NOTIFICATION = "update/newmember";
     public static final String DELETE_NOTIFICATION = "delete";
     public static final String MOVE_NOTIFICATION = "move";
     
     private int id;
     private long lifetime;
     private String callback;
     private String contentLocation;
     private String notificationType;
     private String path;
     
     public Subscription(String path, int id, String callback, long lifetime, 
           String contentLocation, String notificationType)
     {
        this.path = path;
        this.id = id;
        this.callback = callback;
        this.lifetime = lifetime;
        this.contentLocation = contentLocation;
        this.notificationType = notificationType;
     }
     
     public String getCallback()
     {
        return callback;
     }
     public String getContentLocation()
     {
        return contentLocation;
     }
     public int getId()
     {
        return id;
     }
     public long getLifetime()
     {
        return lifetime;
     }
     public String getNotificationType()
     {
        return notificationType;
     }
     public String getPath() 
     {
        return path;
     }
  }
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/event/Listener.java
  
  Index: Listener.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.webdav.lib.event;
  
  /**
   * @author Stefan L�tzkendorf
   */
  abstract class Listener extends Thread
  {
  
     /**
      * Returns the count of currenty queued notifications.
      */
     public abstract int getNotificationCount();
  
     /**
      * Removes the next notification to be processed from the queue and returns
      * it. 
      * @throws java.util.NoSuchElementException if no notification exists.
      */
     public abstract Notification popNextNotification();
     
     public abstract Exception getException();
  }
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/event/Notification.java
  
  Index: Notification.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.webdav.lib.event;
  
  import java.net.InetAddress;
  
  
  /**
   * Object that holds information about a single notification. 
   * 
   * @author Stefan L�tzkendorf
   */
  public final class Notification
  {
     /** the request uri */
     private String url;
     private long subscription;
     private InetAddress inetAddress;
     
     /**
      * Creates a notification object from an URL and a number identifying a
      * subscription.
      * @param url 
      * @param subscription
      * @param address the address of the host that send the notification
      */
     public Notification(String url, long subscription, InetAddress address) {
        this.url = url;
        this.subscription = subscription; 
        this.inetAddress = address;
     }
     
     /**
      * The request uri of the notification. That should match the call back
      * registered while subscription.
      */
     public String getURL() {
        return this.url;
     }
  
     /**
      * The ID of the subscription that is notified. 
      */
     public long getSubscriptionId() {
        return this.subscription;
     }
     
     /**
      * The String representation of the IP address of the notifier.
      * @return IP address as String, e.g. 192.168.0.1
      */
     public String getNotifiersAddress() {
        return this.inetAddress.getHostAddress();
     }
     /**
      * The name of the notifier. 
      * @see InetAddress#getHostName()
      */
     public String getNotifiersName() {
        return this.inetAddress.getHostName();
     }
     /**
      * The name of the notifier.
      * @see InetAddress#getCanonicalHostName()
      */
     public String getNotifiersCanonicalName() {
        return this.inetAddress.getCanonicalHostName();
     }
     
     public String toString() {
        return new StringBuffer(120)
           .append("url=")
           .append(this.url)
           .append(", subscription=")
           .append(this.subscription)
           .toString();
     }
     
     /**
      * Two notifications are equal if their request uri and id are equal.
      */
     public boolean equals(Object obj) {
        if (obj == this) return true;
        
        if (obj instanceof Notification) {
           Notification that = (Notification)obj;
           return (this.subscription == that.subscription && 
                   this.url.equals(that.url));
        }
        return false;
     }
     
     public int hashCode() {
        return (51 * (int)this.subscription) + this.url.hashCode();
     }
  }
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/event/NotificationListener.java
  
  Index: NotificationListener.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.webdav.lib.event;
  
  
  /**
   * Listener for WebDAV notifications.
   * 
   * <p><b>Usage:</b>
   * <p>
   * Implement the interface [EMAIL PROTECTED] NotificationProcessor} to determine how
   * do you want to process [EMAIL PROTECTED] Notification}s.
   * 
   * <p> Create your processsor 
   * <pre>
   *   NotificationProcessor myProcessor = new MyProcessor();
   * </pre>
   * 
   * <p>Determine the port to listen on (should match the port in the URL
   * you have provided while subscription, e.g. httpu://localhost:8887).
   * <pre>
   *  int myPort = 8887;
   * </pre>
   * 
   * <p>Create a NotificationListner and run it
   * <pre>
   *  NotificationListener listener = NotificationListener.createUDPListener(
   *            myPort,
   *            myProcessor);
   *  listener.start();
   * </pre>
   * 
   * @author Stefan L�tzkendorf
   */
  public class NotificationListener extends Thread
  { 
     private Listener listener;
     private NotificationProcessor processor;
     
     private NotificationListener(Listener listener, NotificationProcessor processor) {
        this.listener = listener;
        this.processor = processor;
        setName("Notification processing thread for " + listener);
     }
     
     /**
      * Creates a listener that listens on a DatagramSocket and calls 
      * [EMAIL PROTECTED] NotificationProcessor#processNotification(Notification)} for
      * each incomming notification.
      * 
      * @param port Port number to be listened
      * @param processor callback to process incomming [EMAIL PROTECTED] 
Notification}s.
      */
     public static NotificationListener createUDPListener(
           int port,  
           NotificationProcessor processor)
     {
        return new NotificationListener(
              new UDPListener(port),
              processor);
     }
     
     /**
      * Not yet implemented.
      */
     public static NotificationListener createTCPListener(
           int port,  
           NotificationProcessor processor)
     {
        throw new UnsupportedOperationException();
     }
  
     public void run()
     {
        listener.start();
        
        while (true) {
           Notification notification;
           
           synchronized(listener) {
              while (listener.getNotificationCount() < 1) {
                 try {
                    listener.wait(1000);
                 } catch (InterruptedException e) {
                    listener.interrupt();
                    return;
                 }
                 if (isInterrupted()) {
                    listener.interrupt();
                    return;
                 }
              }
              notification = listener.popNextNotification();
           }
           
           processor.processNotification(notification);
        }
     }
     
     /**
      * Runs an UDPListener that listens on port 80.
      */
     public static void main(String[] args)
     {
        NotificationListener listener = NotificationListener.createUDPListener(
              80,
              new PrintingNotificationProcessor());
        //listener.setDaemon(false);
        listener.start();
        try {
           listener.join();
        } catch (InterruptedException e) {
        }
     }
  }
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/event/NotificationProcessor.java
  
  Index: NotificationProcessor.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.webdav.lib.event;
  
  
  /**
   * Interface for classes which take responsibility for processing 
   * incomming notifications.
   * 
   * @see org.apache.webdav.lib.event.NotificationListener
   * 
   * @author Stefan L�tzkendorf
   */
  public interface NotificationProcessor
  {
     public void processNotification(Notification notification);
  }
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/event/PrintingNotificationProcessor.java
  
  Index: PrintingNotificationProcessor.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.webdav.lib.event;
  
  import java.io.PrintStream;
  
  
  /**
   * NotificationProcessor for testing purposes that simply prints all
   * notifications to a stream (by default to [EMAIL PROTECTED] System#out}).
   * 
   * @author Stefan L�tzkendorf
   */
  public class PrintingNotificationProcessor
     implements NotificationProcessor
  {
     private PrintStream out;
  
     public PrintingNotificationProcessor() {
        this.out = System.out;
     }
     
     public PrintingNotificationProcessor(PrintStream stream) {
        this.out = stream;
     }
     
     public void processNotification(Notification notification)
     {
        this.out.println(notification);
     }
  }
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/event/UDPListener.java
  
  Index: UDPListener.java
  ===================================================================
  // vi: set ts=3 sw=3:
  package org.apache.webdav.lib.event;
  
  import java.io.IOException;
  import java.io.UnsupportedEncodingException;
  import java.net.DatagramPacket;
  import java.net.DatagramSocket;
  import java.net.SocketException;
  import java.net.SocketTimeoutException;
  import java.net.URLDecoder;
  import java.util.Collections;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.StringTokenizer;
  
  
  /**
   * @author Stefan L�tzkendorf
   */
  class UDPListener extends Listener
  {
     private int port = 80;
     private DatagramSocket socket;
     private byte[] buffer = new byte[1024];
     private LinkedList notifications = new LinkedList();
     private Exception exception = null;
     
     public UDPListener() {
        this(80);
     }
     
     public UDPListener(int port) {
        this.port = port;
        setName(this.toString());
     }
     
     public void run() {
        
        try {
           this.socket = new DatagramSocket(this.port);
           this.socket.setSoTimeout(10000);
           
           DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
           while (true) {
              try {
                 this.socket.receive(packet);
                 List l = parseRequest(packet);
                 if (l.size() > 0) {
                    synchronized (this) {
                       this.notifications.addAll(l);
                       this.notify();
                    }
                 }
              }
              catch (SocketTimeoutException e) {
                 if (isInterrupted()) {
                    return;
                 }
              }
           }
        } catch (SocketException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
           this.exception = e;
        } catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
           this.exception = e;
        }
     }
     
     public Exception getException() {
        return this.exception;
     }
     
     /**
      * Returns the count of currenty queued notifications.
      */
     public int getNotificationCount() {
        return this.notifications.size();
     }
  
     /**
      * Removes the next notification to be processed from the queue and returns
      * it. 
      * @throws java.util.NoSuchElementException if no notification exists.
      */
     public Notification popNextNotification() {
        return (Notification)this.notifications.removeFirst();
     }
     
     public String toString() {
        return "UDP Notification Listener on port " + this.port;
     }
     
     /**
      * Parses the packet as NOTIFY request and returns a list of notifications
      * contained. The list may be empty if this is not a (valid) NOTIFY request.
      *  
      * @return List of [EMAIL PROTECTED] Notification}s.
      */
     private List parseRequest(DatagramPacket packet) {
        List result = new LinkedList();
        byte[] data = packet.getData();
        int pos = packet.getOffset();
        int lastPos = packet.getOffset() + packet.getLength();
        
        if (data[pos]   == 'N' && 
            data[pos+1] == 'O' &&
            data[pos+2] == 'T' &&
            data[pos+3] == 'I' &&
            data[pos+4] == 'F' &&
            data[pos+5] == 'Y' &&
            data[pos+6] == ' ') 
        {
           int secondSpacePos = indexOf((byte)' ', data, pos+7, lastPos);
           if (secondSpacePos == -1) return Collections.EMPTY_LIST;
           String url;
           try {
              url = URLDecoder.decode(new String(data, 7, secondSpacePos-7), "UTF-8");
           } catch (UnsupportedEncodingException e) {
              url = new String(data, 7, secondSpacePos);
           }
           // skip command line
           pos = 1+indexOfEOL(data, secondSpacePos + 1, lastPos);
           
           while(pos < lastPos) {
              int lineEnd = indexOfEOL(data, pos, lastPos);
              String line;
              if (lineEnd == -1) {
                 line = new String(data, pos, lastPos-pos);
                 lineEnd = lastPos;
              } else {
                 line = new String(data, pos, lineEnd-pos);
              }
              
              String headerName = line.substring(0, line.indexOf(':')).trim();
              if ("Subscription-ID".equalsIgnoreCase(headerName)) {
                 StringTokenizer tokenizer = new StringTokenizer(
                       line.substring(line.indexOf(':')+1), ", ");
                 
                 while(tokenizer.hasMoreTokens()) {
                    long id = Long.parseLong(tokenizer.nextToken());
                    Notification n = new Notification(url, id, packet.getAddress());
                    result.add(n);
                 }
              }
              pos = lineEnd+1;
           }
        }
        return result;
     }
     
     private int indexOf(byte b, byte[] data, int offset, int end) {
        for(int i = offset; i < end; i++) {
           if(data[i] == b) return i; 
        }
        return -1;
     }
     
     private int indexOfEOL(byte[] data, int offset, int end) {
        for(int i = offset; i < end; i++) {
           switch (data[i]) {
              case '\r':
                 if (i+1<end && data[i+1] == '\n') return i+1;
              case '\n':
                 return i;
           }
        }
        return -1;
     }
  }
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/event/package.html
  
  Index: package.html
  ===================================================================
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
  <HTML><HEAD> 
         <TITLE>HTML 4 Strict</TITLE></HEAD>
    <BODY> 
         <P>Package with tools for handling WebDAV events.</P>
         <P></P></BODY>
  </HTML>
  
  
  
  1.2       +53 -20    
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/methods/SubscribeMethod.java
  
  Index: SubscribeMethod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/methods/SubscribeMethod.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SubscribeMethod.java      6 Jul 2004 17:03:56 -0000       1.1
  +++ SubscribeMethod.java      13 Jul 2004 08:47:30 -0000      1.2
  @@ -46,6 +46,7 @@
      private static final String HEADER_NOTIFICATION_DELAY = "Notification-Delay";
      private static final String HEADER_DEPTH = "Depth";
      private static final String HEADER_CALL_BACK = "Call-Back";
  +   private static final String HEADER_CONTENT_LOCATION = "Content-Location";
      
      public static final String TYPE_UPDATE = "update";
      public static final String TYPE_UPDATE_NEW_MEMBER = "update/newmember";
  @@ -56,23 +57,33 @@
      private String notificationType = null;
      private int depth = -1;
      private long subsciptionLifetime = -1;
  -   private long subscriptionId = -1;
  +   private int subscriptionId = -1;
      private long notificationDelay = -1;
      
      private long responsedSubscriptionLifetime = -1;
  -   private long responsedSubscriptionId = -1;
  +   private int responsedSubscriptionId = -1;
  +   private String responsedContentLocation = null;
      
  +   public SubscribeMethod() {
  +      
  +   }
  +   
  +   public SubscribeMethod(String path) {
  +      super(path);
  +   }
   
      public String getCallback()
      {
         return callback;
      }
      /**
  -    * Sets the URI tha's to be notified if the subscribed event does occur.  
  +    * Sets the URI that's to be notified if the subscribed event does occur.  
       */
      public void setCallback(String callback)
      {
  -      this.callback = callback;
  +      if (callback != null && callback.length() > 0) {
  +         this.callback = callback;
  +      }
      }
      public String getNotificationType()
      {
  @@ -81,8 +92,10 @@
      /**
       * Sets the notification type, i.e. determines the events that are 
       * subscribed.
  -    * @see [EMAIL PROTECTED] #TYPE_DELETE}, [EMAIL PROTECTED] #TYPE_MOVE},
  -    *      [EMAIL PROTECTED] #TYPE_UPDATE}, [EMAIL PROTECTED] 
#TYPE_UPDATE_NEW_MEMBER}
  +    * @see #TYPE_DELETE 
  +    * @see #TYPE_MOVE
  +    * @see #TYPE_UPDATE
  +    * @see #TYPE_UPDATE_NEW_MEMBER
       */
      public void setNotificationType(String notificationType)
      {
  @@ -107,7 +120,7 @@
       * Sets the ID of a subscription to be refreshed.
       * @param subscriptionId
       */
  -   public void setSubscriptionId(long subscriptionId)
  +   public void setSubscriptionId(int subscriptionId)
      {
         this.subscriptionId = subscriptionId;
      }
  @@ -145,7 +158,7 @@
       * Returns the subscription ID responsed from the server.
       * @return -1 if no subscription id was in the response 
       */
  -   public long getResponsedSubscriptionId() {
  +   public int getResponsedSubscriptionId() {
         checkUsed();
         return this.responsedSubscriptionId;
      }
  @@ -157,6 +170,15 @@
         checkUsed();
         return this.responsedSubscriptionLifetime;
      }
  +   /**
  +    * Returns the value of the content-location header of the response. 
  +    * This shall be used to the request uri for a POLL method querying this
  +    * subscription.
  +    */
  +   public String getResponsedContentLocation() {
  +      checkUsed();
  +      return this.responsedContentLocation;
  +   }
      // --------------------------------------------------- WebdavMethod Methods
   
      public String getName()
  @@ -185,20 +207,22 @@
            super.setRequestHeader(HEADER_CALL_BACK, this.callback);
         }
         if (this.depth > -1) {
  -         super.setRequestHeader(HEADER_DEPTH, Integer.toString(this.depth));
  +         super.setRequestHeader(HEADER_DEPTH, 
  +               this.depth == DEPTH_INFINITY ? "infinity" 
  +                     : String.valueOf(this.depth));
         }
         if (this.notificationType != null) {
            super.setRequestHeader(HEADER_NOTIFICATION_TYPE, this.notificationType);
         }
  -      if (this.subsciptionLifetime > -1) {
  +      if (this.subsciptionLifetime > 0) {
            super.setRequestHeader(HEADER_SUBSCRIPTION_LIFETIME, 
                  Long.toString(this.subsciptionLifetime));
         }
  -      if (this.subscriptionId > -1) {
  +      if (this.subscriptionId > 0) {
            super.setRequestHeader(HEADER_SUBSCRIPTION_ID, Long.toString(
                  this.subscriptionId));
         }
  -      if (this.notificationDelay > -1) {
  +      if (this.notificationDelay > 0) {
            super.setRequestHeader(HEADER_NOTIFICATION_DELAY, Long.toString(
                  this.notificationDelay));
         }
  @@ -212,13 +236,17 @@
      {
          try {
            if (headerName.equalsIgnoreCase(HEADER_DEPTH)){
  -              setDepth(Integer.parseInt(headerValue));
  +            if ("infinity".equalsIgnoreCase(headerValue)) {
  +               setDepth(DEPTH_INFINITY);
  +            } else {
  +               setDepth(Integer.parseInt(headerValue));
  +            }
             } 
             else if(headerName.equals(HEADER_SUBSCRIPTION_ID)) {
  -             setSubscriptionId(Long.parseLong(headerValue));
  +             setSubscriptionId(Integer.parseInt(headerValue));
             }
             else if(headerName.equals(HEADER_SUBSCRIPTION_LIFETIME)) {
  -             setSubscriptionId(Long.parseLong(headerValue));
  +             setSubscriptionId(Integer.parseInt(headerValue));
             }
             else if(headerName.equals(HEADER_NOTIFICATION_DELAY)) {
                setNotificationDelay(Long.parseLong(headerValue));
  @@ -240,12 +268,17 @@
         
         header = getResponseHeader(HEADER_SUBSCRIPTION_ID);
         if (header != null) {
  -         this.responsedSubscriptionId = Long.parseLong(header.getValue());
  +         this.responsedSubscriptionId = Integer.parseInt(header.getValue());
         }
         
  -      header = getRequestHeader(HEADER_SUBSCRIPTION_LIFETIME);
  +      header = getResponseHeader(HEADER_SUBSCRIPTION_LIFETIME);
         if (header != null) {
            this.responsedSubscriptionLifetime = Long.parseLong(header.getValue());
  +      }
  +      
  +      header = getResponseHeader(HEADER_CONTENT_LOCATION);
  +      if (header != null) {
  +         this.responsedContentLocation = header.getValue();
         }
      }
   }
  
  
  
  1.2       +33 -4     
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/methods/UnsubscribeMethod.java
  
  Index: UnsubscribeMethod.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/methods/UnsubscribeMethod.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- UnsubscribeMethod.java    6 Jul 2004 17:03:56 -0000       1.1
  +++ UnsubscribeMethod.java    13 Jul 2004 08:47:30 -0000      1.2
  @@ -1,4 +1,25 @@
  -// vi: set ts=3 sw=3:
  +/*
  + * $Header$
  + * $Revision$
  + * $Date$
  + *
  + * ====================================================================
  + *
  + * Copyright 1999-2002 The Apache Software Foundation 
  + *
  + * Licensed under the Apache License, Version 2.0 (the "License");
  + * you may not use this file except in compliance with the License.
  + * You may obtain a copy of the License at
  + *
  + *     http://www.apache.org/licenses/LICENSE-2.0
  + *
  + * Unless required by applicable law or agreed to in writing, software
  + * distributed under the License is distributed on an "AS IS" BASIS,
  + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  + * See the License for the specific language governing permissions and
  + * limitations under the License.
  + *
  + */
   package org.apache.webdav.lib.methods;
   
   import java.io.IOException;
  @@ -24,11 +45,18 @@
      
      private List subscriptionIds = new ArrayList();
      
  +   public UnsubscribeMethod() {
  +   }
  +   
  +   public UnsubscribeMethod(String path) {
  +      super(path);
  +   }
  +   
      /**
       * Adds an ID for a subscription that is to be withdrawn.
       */
  -   public void addSubscriptionId(long id) {
  -      this.subscriptionIds.add(new Long(id));
  +   public void addSubscriptionId(int id) {
  +      this.subscriptionIds.add(new Integer(id));
      }
   
      // --------------------------------------------------- WebdavMethod Methods
  @@ -40,6 +68,7 @@
      
      public void recycle()
      {
  +      super.recycle();
         this.subscriptionIds.clear();
      }
      
  @@ -68,7 +97,7 @@
            StringTokenizer t = new StringTokenizer(headerValue, ", ");
            try {
               for(;t.hasMoreTokens();) {
  -               addSubscriptionId(Long.parseLong(t.nextToken()));
  +               addSubscriptionId(Integer.parseInt(t.nextToken()));
               }
            } catch (NumberFormatException e) {
               throw new IllegalArgumentException("Invalid header value '" +
  
  
  
  1.1                  
jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/methods/PollMethod.java
  
  Index: PollMethod.java
  ===================================================================
  /*
   * $Header: 
/home/cvs/jakarta-slide/webdavclient/clientlib/src/java/org/apache/webdav/lib/methods/PollMethod.java,v
 1.1 2004/07/13 08:47:30 luetzkendorf Exp $
   * $Revision: 1.1 $
   * $Date: 2004/07/13 08:47:30 $
   *
   * ====================================================================
   *
   * Copyright 1999-2002 The Apache Software Foundation 
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   */
  package org.apache.webdav.lib.methods;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.List;
  import java.util.StringTokenizer;
  
  import org.apache.commons.httpclient.HttpConnection;
  import org.apache.commons.httpclient.HttpException;
  import org.apache.commons.httpclient.HttpState;
  import org.apache.commons.httpclient.HttpStatus;
  
  import org.apache.util.DOMUtils;
  import org.w3c.dom.Element;
  import org.w3c.dom.NodeList;
  
  
  /**
   * Implements the POLL WebDAV method.
   * 
   * @author Stefan L�tzkendorf
   * @see <a 
href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_webdav_poll.asp";>Reference</a>
   */
  public class PollMethod extends XMLResponseMethodBase
  {
     private static final String HEADER_SUBSCRIPTION_ID = "Subscription-Id";
     private static final String EXCHANGE_NS = 
"http://schemas.microsoft.com/Exchange/";;
     private List subscriptionIds = new ArrayList();
     private List subscriptionsWithEvents = new ArrayList();
     private List subscriptionsWithoutEvents = new ArrayList();
     
     
     public PollMethod() {
        
     }
     
     public PollMethod(String path) {
        super(path);
     }
     
     /**
      * Adds an ID for a subscription that is to be polled. All added subscription
      * IDs should have the got same Content-Location uri from the SUBSCRIBE method. 
      */
     public void addSubscriptionId(int id) {
        checkNotUsed();
        this.subscriptionIds.add(new Integer(id));
     }
     
     /**
      * Returns a list of number objects containing the subscription IDs for
      * subscriptions for which events are reported.
      * @return Collection of [EMAIL PROTECTED] Integer}s
      */
     public Collection getSubscriptionsWithEvents() {
        checkUsed();
        return this.subscriptionsWithEvents;
     }
     /**
      * Returns a list of number objects containing the subscription IDs for
      * subscriptions for which <em>NO</em> events are reported.
      * @return Collection of [EMAIL PROTECTED] Integer}s
      */
     public Collection getSubscriptionsWithoutEvents() {
        checkUsed();
        return this.subscriptionsWithoutEvents;
     }
     
     // --------------------------------------------------- WebdavMethod Methods
  
     public String getName()
     {
        return "POLL";
     }
     
     public void recycle()
     {
        super.recycle();
        this.subscriptionIds.clear();
     }
     
     protected void addRequestHeaders(HttpState state, HttpConnection conn)
        throws IOException, HttpException
     {
        super.addRequestHeaders(state, conn);
        if (this.subscriptionIds.size() > 0) {
           StringBuffer b = new StringBuffer();
           boolean first = true;
           for (Iterator i = this.subscriptionIds.iterator(); i.hasNext();) {
              if (first) first = false; else b.append(", ");
              b.append(i.next());
           }
           super.addRequestHeader(HEADER_SUBSCRIPTION_ID, b.toString());
        }
     }
     
     /**
      * Adds special checking of header values of the POLL method to
      * the super class implementation.
      */
     public void setRequestHeader(String headerName, String headerValue) 
     {
        if (headerName.equalsIgnoreCase(HEADER_SUBSCRIPTION_ID)){
           StringTokenizer t = new StringTokenizer(headerValue, ", ");
           try {
              for(;t.hasMoreTokens();) {
                 addSubscriptionId(Integer.parseInt(t.nextToken()));
              }
           } catch (NumberFormatException e) {
              throw new IllegalArgumentException("Invalid header value '" +
                    headerValue + "' for header " + headerName + "!");
           }
        } else {
           super.setRequestHeader(headerName, headerValue);
        }
     }
     
     public void parseResponse(InputStream input, HttpState state,
           HttpConnection conn) throws IOException, HttpException
     {
        int status = getStatusLine().getStatusCode();
        
        if (status == HttpStatus.SC_MULTI_STATUS) {
           parseXMLResponse(input);
           NodeList list = getResponseDocument().getDocumentElement()
              .getElementsByTagNameNS("DAV:", "response");
           
           for(int i = 0; i < list.getLength(); i++) {
              Element e = (Element)list.item(i);
              
              NodeList s = e.getElementsByTagNameNS("DAV:", "status");
              if (s.getLength() > 0) {
                 Element response = ((Element)(s.item(0)).getParentNode());
                 String statusText = DOMUtils.getTextValue((Element)s.item(0));
                 if (statusText.indexOf(" 200 ") != -1) {
                    // polled subscriptions for which *AN* event is fired
                    NodeList p = response.getElementsByTagNameNS(EXCHANGE_NS, 
"subscriptionID");
                    if (p.getLength()>0) {
                       NodeList li = ((Element)p.item(0)).getElementsByTagName("li");
                       for(int l = 0; l < li.getLength();++l) {
                          String id = DOMUtils.getTextValue(li.item(i));
                          this.subscriptionsWithEvents.add(Integer.getInteger(id));
                       }
                    }
                 } else
                 if (statusText.indexOf(" 204 ") != -1) {
                    // polled subscriptions for which *NO* event is fired
                    NodeList p = response.getElementsByTagNameNS(EXCHANGE_NS, 
"subscriptionID");
                    if (p.getLength()>0) {
                       NodeList li = ((Element)p.item(0)).getElementsByTagName("li");
                       for(int l = 0; l < li.getLength();++l) {
                          String id = DOMUtils.getTextValue(li.item(i));
                          this.subscriptionsWithoutEvents.add(Integer.getInteger(id));
                       }
                    }
                 }
              }
           }
        }
     }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to