You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@abdera.apache.org by jm...@apache.org on 2011/10/22 01:47:53 UTC

svn commit: r1187599 [2/4] - in /abdera/abdera2: activities/src/main/java/org/apache/abdera2/activities/client/ activities/src/main/java/org/apache/abdera2/activities/protocol/ activities/src/main/java/org/apache/abdera2/activities/protocol/basic/ acti...

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseProvider.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseProvider.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseProvider.java Fri Oct 21 23:47:50 2011
@@ -25,10 +25,15 @@ import java.util.Map;
 import java.util.Set;
 
 import javax.security.auth.Subject;
+
+import org.apache.abdera2.common.misc.Chain;
 import org.apache.abdera2.common.misc.Resolver;
+import org.apache.abdera2.common.misc.Task;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import com.google.common.base.Function;
+
 /**
  * Base Provider implementation that provides the core implementation details for all Providers. This class provides the
  * basic request routing logic.
@@ -39,10 +44,10 @@ public abstract class BaseProvider
 
     private final static Log log = LogFactory.getLog(BaseProvider.class);
     protected Map<String, String> properties;
-    protected Set<Filter> filters = 
-      new LinkedHashSet<Filter>();
-    protected Map<TargetType, RequestProcessor> requestProcessors = 
-      new HashMap<TargetType, RequestProcessor>();
+    protected Set<Task<RequestContext,ResponseContext>> filters = 
+      new LinkedHashSet<Task<RequestContext,ResponseContext>>();
+    protected Map<TargetType, Function<CollectionAdapter,? extends RequestProcessor>> requestProcessors = 
+      new HashMap<TargetType, Function<CollectionAdapter,? extends RequestProcessor>>();
 
     public void init(Map<String,String> properties) {
       this.properties = properties != null ? properties : new HashMap<String,String>();
@@ -80,51 +85,40 @@ public abstract class BaseProvider
     protected abstract Resolver<Target, RequestContext> getTargetResolver(RequestContext request);
 
     public ResponseContext apply(RequestContext request) {
-      return process(request);
-    }
-    
-    public <S extends ResponseContext>S process(RequestContext request) {
-        Target target = request.getTarget();
-        if (target == null || target.getType() == TargetType.TYPE_NOT_FOUND) {
-            return (S)ProviderHelper.notfound(request);
-        }
-
-        TargetType type = target.getType();
-        log.debug(String.format("Processing [%s] request for Target [%s] of Type [%s]",request.getMethod(),target.getIdentity(),type.toString()));
-        RequestProcessor processor = 
-          (RequestProcessor) this.requestProcessors.get(type);
-        if (processor == null) {
-            return (S)ProviderHelper.notfound(request);
-        }
-
-        WorkspaceManager wm = getWorkspaceManager(request);
-        CollectionAdapter adapter = wm.getCollectionAdapter(request);
-        Transactional transaction = 
-          adapter instanceof Transactional ? (Transactional)adapter : null;
-        S response = null;
-        try {
-            transactionStart(transaction, request);
-            response = (S)processor.process(request, wm, adapter);
-            response = (S)(response != null ? response : processExtensionRequest(request, adapter));
-        } catch (Throwable e) {
-            if (e instanceof ResponseContextException) {
-                ResponseContextException rce = (ResponseContextException)e;
-                if (rce.getStatusCode() >= 400 && rce.getStatusCode() < 500) {
-                    // don't report routine 4xx HTTP errors
-                    log.info(e);
-                } else {
-                    log.error(e);
-                }
-            } else {
-                log.error(e);
-            }
-            transactionCompensate(transaction, request, e);
-            response = (S)createErrorResponse(request, e);
-            return response;
-        } finally {
-            transactionEnd(transaction, request, response);
-        }
-        return (S)(response != null ? response : ProviderHelper.badrequest(request));
+      Target target = request.getTarget();
+      if (Target.NOT_FOUND.apply(target))
+          return ProviderHelper.notfound(request);
+      TargetType type = target.getType();
+      log.debug(String.format(
+        "Processing [%s] request for Target [%s] of Type [%s]",
+        request.getMethod(),
+        target.getIdentity(),
+        type.toString()));
+      CollectionAdapter adapter = 
+        getWorkspaceManager()
+          .getCollectionAdapter(request);
+      if (adapter == null)
+        return ProviderHelper.servererror(request, null);
+      RequestProcessor processor = 
+        (RequestProcessor) this.requestProcessors
+          .get(type)
+          .apply(adapter);
+      if (processor == null)
+          return ProviderHelper.notfound(request);
+      Chain<RequestContext,ResponseContext> chain = 
+        Chain.<RequestContext,ResponseContext>make()
+        .to(processor)
+        .via(getFilters(request))
+        .get();
+      ResponseContext response = null;
+      try {
+        response = chain.apply(request);
+      } catch (Throwable t) {
+        response = createErrorResponse(request, t);
+      }
+      return response != null ? 
+        response : 
+        ProviderHelper.badrequest(request);
     }
 
     /**
@@ -134,55 +128,32 @@ public abstract class BaseProvider
         return ProviderHelper.servererror(request, e);
     }
 
-    protected void transactionCompensate(Transactional transactional, RequestContext request, Throwable e) {
-        if (transactional != null) {
-            transactional.compensate(request, e);
-        }
-    }
-
-    protected void transactionEnd(Transactional transactional, RequestContext request, ResponseContext response) {
-        if (transactional != null) {
-            transactional.end(request, response);
-        }
-    }
-
-    protected void transactionStart(Transactional transactional, RequestContext request)
-        throws ResponseContextException {
-        if (transactional != null) {
-            transactional.start(request);
-        }
-    }
-
-    protected ResponseContext processExtensionRequest(RequestContext context, CollectionAdapter adapter) {
-        return adapter.extensionRequest(context);
-    }
-
-    protected abstract WorkspaceManager getWorkspaceManager(RequestContext request);
+    protected abstract WorkspaceManager getWorkspaceManager();
 
-    public void setFilters(Collection<Filter> filters) {
-        this.filters = new LinkedHashSet<Filter>(filters);
+    public void setFilters(Collection<Task<RequestContext,ResponseContext>> filters) {
+        this.filters = new LinkedHashSet<Task<RequestContext,ResponseContext>>(filters);
     }
 
-    public Iterable<Filter> getFilters(RequestContext request) {
+    public Iterable<Task<RequestContext,ResponseContext>> getFilters(RequestContext request) {
         return filters;
     }
 
-    public void addFilter(Filter... filters) {
-        for (Filter filter : filters) {
+    public void addFilter(Task<RequestContext,ResponseContext>... filters) {
+        for (Task<RequestContext,ResponseContext> filter : filters) {
             this.filters.add(filter);
         }
     }
 
-    public void setRequestProcessors(Map<TargetType, RequestProcessor> requestProcessors) {
+    public void setRequestProcessors(Map<TargetType, Function<CollectionAdapter,? extends RequestProcessor>> requestProcessors) {
         this.requestProcessors.clear();
         this.requestProcessors.putAll(requestProcessors);
     }
 
-    public void addRequestProcessors(Map<TargetType, RequestProcessor> requestProcessors) {
+    public void addRequestProcessors(Map<TargetType, Function<CollectionAdapter,? extends RequestProcessor>> requestProcessors) {
         this.requestProcessors.putAll(requestProcessors);
     }
 
-    public Map<TargetType, RequestProcessor> getRequestProcessors() {
+    public Map<TargetType, Function<CollectionAdapter,? extends RequestProcessor>> getRequestProcessors() {
         return Collections.unmodifiableMap(this.requestProcessors);
     }
     

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseRequestContextWrapper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseRequestContextWrapper.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseRequestContextWrapper.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseRequestContextWrapper.java Fri Oct 21 23:47:50 2011
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.Reader;
 import java.security.Principal;
-import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
@@ -35,6 +34,7 @@ import org.apache.abdera2.common.http.Ca
 import org.apache.abdera2.common.http.EntityTag;
 import org.apache.abdera2.common.http.Preference;
 import org.apache.abdera2.common.http.WebLink;
+import org.joda.time.DateTime;
 
 @SuppressWarnings("unchecked")
 public class BaseRequestContextWrapper
@@ -164,7 +164,7 @@ public class BaseRequestContextWrapper
         return request.getIfMatch();
     }
 
-    public Date getIfModifiedSince() {
+    public DateTime getIfModifiedSince() {
         return request.getIfModifiedSince();
     }
 
@@ -172,7 +172,7 @@ public class BaseRequestContextWrapper
         return request.getIfNoneMatch();
     }
 
-    public Date getIfUnmodifiedSince() {
+    public DateTime getIfUnmodifiedSince() {
         return request.getIfUnmodifiedSince();
     }
 
@@ -192,7 +192,7 @@ public class BaseRequestContextWrapper
         return request.getContentType();
     }
 
-    public Date getDateHeader(String name) {
+    public DateTime getDateHeader(String name) {
         return request.getDateHeader(name);
     }
 

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseResponseContextWrapper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseResponseContextWrapper.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseResponseContextWrapper.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BaseResponseContextWrapper.java Fri Oct 21 23:47:50 2011
@@ -20,7 +20,6 @@ package org.apache.abdera2.common.protoc
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Date;
 
 import javax.activation.MimeType;
 
@@ -32,6 +31,7 @@ import org.apache.abdera2.common.http.En
 import org.apache.abdera2.common.http.Preference;
 import org.apache.abdera2.common.http.ResponseType;
 import org.apache.abdera2.common.http.WebLink;
+import org.joda.time.DateTime;
 
 @SuppressWarnings("unchecked")
 public class BaseResponseContextWrapper implements ResponseContext {
@@ -136,7 +136,7 @@ public class BaseResponseContextWrapper 
         return (T)this;
     }
 
-    public <T extends ResponseContext>T setExpires(Date date) {
+    public <T extends ResponseContext>T setExpires(DateTime date) {
         response.setExpires(date);
         return (T)this;
     }
@@ -151,7 +151,7 @@ public class BaseResponseContextWrapper 
         return (T)this;
     }
 
-    public <T extends ResponseContext>T setLastModified(Date date) {
+    public <T extends ResponseContext>T setLastModified(DateTime date) {
         response.setLastModified(date);
         return (T)this;
     }
@@ -200,11 +200,11 @@ public class BaseResponseContextWrapper 
         return response.getEntityTag();
     }
 
-    public Date getExpires() {
+    public DateTime getExpires() {
         return response.getExpires();
     }
 
-    public Date getLastModified() {
+    public DateTime getLastModified() {
         return response.getLastModified();
     }
 
@@ -240,7 +240,7 @@ public class BaseResponseContextWrapper 
         return response.getContentType();
     }
 
-    public Date getDateHeader(String name) {
+    public DateTime getDateHeader(String name) {
         return response.getDateHeader(name);
     }
 

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicCollectionInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicCollectionInfo.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicCollectionInfo.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicCollectionInfo.java Fri Oct 21 23:47:50 2011
@@ -18,26 +18,54 @@
 package org.apache.abdera2.common.protocol;
 
 import java.io.Serializable;
-import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Set;
 
+import com.google.common.base.Supplier;
 
 public class BasicCollectionInfo 
   implements CollectionInfo, 
              Serializable {
 
+    public static Generator make() {
+      return new Generator();
+    }
+  
+    public static class Generator implements Supplier<CollectionInfo> {
+      private String title;
+      private String href;
+      private final Set<String> accepts = 
+        new LinkedHashSet<String>();
+      public Generator title(String title) {
+        this.title = title;
+        return this;
+      }
+      public Generator href(String href) {
+        this.href = href;
+        return this;
+      }
+      public Generator accept(String type) {
+        this.accepts.add(type);
+        return this;
+      }
+      public CollectionInfo get() {
+        return new BasicCollectionInfo(this);
+      }
+    }
+  
     private static final long serialVersionUID = 8026455829158149510L;
 
     private final String title;
     private final String href;
-    private final String[] accepts;
+    private final Set<String> accepts = new LinkedHashSet<String>();
 
-    public BasicCollectionInfo(String title, String href, String... accepts) {
-        this.title = title;
-        this.accepts = accepts;
-        this.href = href;
+    protected BasicCollectionInfo(Generator gen) {
+        this.title = gen.title;
+        this.accepts.addAll(gen.accepts);
+        this.href = gen.href;
     }
 
-    public String[] getAccepts(RequestContext request) {
+    public Iterable<String> getAccepts(RequestContext request) {
         return accepts;
     }
 
@@ -49,36 +77,40 @@ public class BasicCollectionInfo 
         return title;
     }
 
+    @Override
     public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + Arrays.hashCode(accepts);
-        result = prime * result + ((href == null) ? 0 : href.hashCode());
-        result = prime * result + ((title == null) ? 0 : title.hashCode());
-        return result;
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((accepts == null) ? 0 : accepts.hashCode());
+      result = prime * result + ((href == null) ? 0 : href.hashCode());
+      result = prime * result + ((title == null) ? 0 : title.hashCode());
+      return result;
     }
 
+    @Override
     public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        final BasicCollectionInfo other = (BasicCollectionInfo)obj;
-        if (!Arrays.equals(accepts, other.accepts))
-            return false;
-        if (href == null) {
-            if (other.href != null)
-                return false;
-        } else if (!href.equals(other.href))
-            return false;
-        if (title == null) {
-            if (other.title != null)
-                return false;
-        } else if (!title.equals(other.title))
-            return false;
+      if (this == obj)
         return true;
+      if (obj == null)
+        return false;
+      if (getClass() != obj.getClass())
+        return false;
+      BasicCollectionInfo other = (BasicCollectionInfo) obj;
+      if (accepts == null) {
+        if (other.accepts != null)
+          return false;
+      } else if (!accepts.equals(other.accepts))
+        return false;
+      if (href == null) {
+        if (other.href != null)
+          return false;
+      } else if (!href.equals(other.href))
+        return false;
+      if (title == null) {
+        if (other.title != null)
+          return false;
+      } else if (!title.equals(other.title))
+        return false;
+      return true;
     }
-
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicWorkspaceInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicWorkspaceInfo.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicWorkspaceInfo.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/BasicWorkspaceInfo.java Fri Oct 21 23:47:50 2011
@@ -18,21 +18,48 @@
 package org.apache.abdera2.common.protocol;
 
 import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+
 
 public class BasicWorkspaceInfo
   implements WorkspaceInfo, 
              Serializable {
 
     private static final long serialVersionUID = -8459688584319762878L;
+    
+    public static class Generator implements Supplier<WorkspaceInfo> {
 
-    protected String title;
-    protected Set<CollectionInfo> collections;
-
-    public BasicWorkspaceInfo() {
+      private String title;
+      private final Set<CollectionInfo> collections = 
+        new LinkedHashSet<CollectionInfo>();
+      
+      public Generator title(String title) {
+        this.title = title;
+        return this;
+      }
+      
+      public Generator collection(CollectionInfo info) {
+        this.collections.add(info);
+        return this;
+      }
+      
+      public WorkspaceInfo get() {
+        return new BasicWorkspaceInfo(this);
+      }
+      
+    }
+    
+    protected final String title;
+    protected final Set<CollectionInfo> collections =
+      new LinkedHashSet<CollectionInfo>();
+
+    protected BasicWorkspaceInfo(Generator generator) {
+      this.title = generator.title;
+      this.collections.addAll(generator.collections);
     }
 
     public BasicWorkspaceInfo(String title) {
@@ -43,32 +70,12 @@ public class BasicWorkspaceInfo
         return title;
     }
 
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
     public String getTitle(RequestContext request) {
         return title;
     }
 
-    public void addCollection(CollectionInfo ci) {
-        getCollections().add(ci);
-    }
-
-    public Collection<CollectionInfo> getCollections(RequestContext request) {
-        return collections;
-    }
-
-    public Set<CollectionInfo> getCollections() {
-        if (collections == null) {
-            collections = new HashSet<CollectionInfo>();
-        }
-
-        return collections;
-    }
-
-    public void setCollections(Set<CollectionInfo> collections) {
-        this.collections = collections;
+    public Iterable<CollectionInfo> getCollections(RequestContext request) {
+        return Iterables.unmodifiableIterable(collections);
     }
 
     public int hashCode() {

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionAdapter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionAdapter.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionAdapter.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionAdapter.java Fri Oct 21 23:47:50 2011
@@ -17,48 +17,13 @@
  */
 package org.apache.abdera2.common.protocol;
 
+import com.google.common.base.Function;
 
-public interface CollectionAdapter {
-
-    /**
-     * Post a new entry to the collection
-     */
-    <S extends ResponseContext>S postItem(RequestContext request);
-
-    /**
-     * Delete an entry from the collection
-     */
-    <S extends ResponseContext>S deleteItem(RequestContext request);
-
-    /**
-     * Get an entry from the collection
-     */
-    <S extends ResponseContext>S getItem(RequestContext request);
-
-    /**
-     * Get metadata for an entry from the collection
-     */
-    <S extends ResponseContext>S headItem(RequestContext request);
 
-    /**
-     * Get options for an entry from the collection
-     */
-    <S extends ResponseContext>S optionsItem(RequestContext request);
-
-    /**
-     * Update an existing entry
-     */
-    <S extends ResponseContext>S putItem(RequestContext request);
-
-    /**
-     * Get the collections Atom feed document
-     */
-    <S extends ResponseContext>S getItemList(RequestContext request);
-
-    /**
-     * Any request that is not covered by the postEntry, deleteEntry, etc methods will be passed on to the
-     * extensionRequest method. This provides an Adapter with the ability to support Atompub protocol extensions.
-     */
-    <S extends ResponseContext>S extensionRequest(RequestContext request);
+public interface CollectionAdapter {
 
+    Function<RequestContext,ResponseContext> handlerFor(
+      Target target, 
+      String method);
+    
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionInfo.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionInfo.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionInfo.java Fri Oct 21 23:47:50 2011
@@ -39,6 +39,6 @@ public interface CollectionInfo {
      * Returns an array of MIME media types for the app:collection element's app:accept elements. These tell a client
      * which media types the collection will accept on a POST
      */
-    String[] getAccepts(RequestContext request);
+    Iterable<String> getAccepts(RequestContext request);
 
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionRequestProcessor.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionRequestProcessor.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionRequestProcessor.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CollectionRequestProcessor.java Fri Oct 21 23:47:50 2011
@@ -17,40 +17,27 @@
  */
 package org.apache.abdera2.common.protocol;
 
+import com.google.common.base.Predicate;
+
 
 /**
  * {@link org.apache.AtompubRequestProcessor.protocol.server.RequestProcessor} implementation which processes requests for collection
  * documents.
  */
-@SuppressWarnings("unchecked")
 public abstract class CollectionRequestProcessor
-  implements RequestProcessor {
-
-    protected abstract boolean isAcceptableItemType(RequestContext context);
-  
-    public <S extends ResponseContext>S process(
-        RequestContext context,
-        WorkspaceManager workspaceManager,
-        CollectionAdapter collectionAdapter) {
-        if (collectionAdapter == null) {
-            return (S)ProviderHelper.notfound(context);
-        } else {
-            return (S)this.processCollection(context, collectionAdapter);
-        }
-    }
+  extends TransactionalRequestProcessor {
 
-    private <S extends ResponseContext>S processCollection(
-        RequestContext context, 
-        CollectionAdapter adapter) {
-        String method = context.getMethod();
-        if (method.equalsIgnoreCase("GET")) {
-            return (S)adapter.getItemList(context);
-        } else if (method.equalsIgnoreCase("POST")) {
-            return (S)(isAcceptableItemType(context) ? adapter.postItem(context)
-                : adapter instanceof MediaCollectionAdapter ? ((MediaCollectionAdapter)adapter).postMedia(context)
-                    : ProviderHelper.notallowed(context));
-        } else {
-            return null;
-        }
+  public CollectionRequestProcessor(
+      WorkspaceManager workspaceManager,
+      CollectionAdapter adapter) {
+      super(workspaceManager,adapter);
     }
+  
+  public CollectionRequestProcessor(
+    WorkspaceManager workspaceManager,
+    CollectionAdapter adapter,
+    Predicate<RequestContext> predicate) {
+    super(workspaceManager,adapter,predicate);
+  }
+  
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CompressionFilter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CompressionFilter.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CompressionFilter.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/CompressionFilter.java Fri Oct 21 23:47:50 2011
@@ -27,21 +27,21 @@ import org.apache.abdera2.common.http.Qu
 import org.apache.abdera2.common.io.Compression;
 import org.apache.abdera2.common.io.Compression.CompressionCodec;
 import org.apache.abdera2.common.misc.Chain;
+import org.apache.abdera2.common.misc.Task;
 
 /**
  * Abdera Filter implementation that selectively applies compression to the response payload
  */
-public class CompressionFilter implements Filter {
+public class CompressionFilter implements Task<RequestContext,ResponseContext> {
 
     public ResponseContext apply(RequestContext request, Chain<RequestContext,ResponseContext> chain) {
         String encoding = request.getHeader("Accept-Encoding");
         QToken[] encodings = encoding != null ? QualityHelper.orderByQ(encoding) : new QToken[0];
         for (QToken enc : encodings) {
-            try {
-                CompressionCodec codec = CompressionCodec.valueOf(enc.token().toUpperCase());
-                return new CompressingResponseContextWrapper(chain.next(request), codec);
-            } catch (Exception e) {
-            }
+          try {
+              CompressionCodec codec = CompressionCodec.valueOf(enc.token().toUpperCase());
+              return new CompressingResponseContextWrapper(chain.next(request), codec);
+          } catch (Exception e) {}
         }
         return chain.next(request);
     }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/DefaultWorkspaceManager.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/DefaultWorkspaceManager.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/DefaultWorkspaceManager.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/DefaultWorkspaceManager.java Fri Oct 21 23:47:50 2011
@@ -19,6 +19,9 @@ package org.apache.abdera2.common.protoc
 
 import org.apache.abdera2.common.protocol.RequestContext.Scope;
 
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
 
 /**
  * The DefaultWorkspaceManager is used by the DefaultProvider
@@ -28,26 +31,37 @@ public class DefaultWorkspaceManager 
     // URI reserved delimiter characters (gen-delims) from RFC 3986 section 2.2
     private static final String URI_GEN_DELIMS = ":/?#[]@";
     public CollectionAdapter getCollectionAdapter(RequestContext request) {
-        String path = request.getContextPath() + request.getTargetPath();
-
-        // Typically this happens when a Resolver wants to override the CollectionAdapter being used
-        CollectionAdapter ca = 
-          (CollectionAdapter)request.getAttribute(
-            Scope.REQUEST, AbstractWorkspaceManager.COLLECTION_ADAPTER_ATTRIBUTE);
-        if (ca != null) {
-            return ca;
-        }
-        for (WorkspaceInfo wi : workspaces) {
-            for (CollectionInfo ci : wi.getCollections(request)) {
-                String href = ci.getHref(request);
-                if (path.equals(href) || (href != null && path.startsWith(href) && URI_GEN_DELIMS.contains(path
-                    .substring(href.length(), href.length() + 1)))) {
-                    return (CollectionAdapter)ci;
-                }
-            }
+      String path = request.getContextPath() + request.getTargetPath();
+      CollectionAdapter ca = 
+        (CollectionAdapter)request.getAttribute(
+          Scope.REQUEST, 
+          AbstractWorkspaceManager.COLLECTION_ADAPTER_ATTRIBUTE);
+      if (ca != null)
+          return ca;
+      for (WorkspaceInfo wi : workspaces) {
+        CollectionInfo ci = 
+          Iterables.<CollectionInfo>find(
+            wi.getCollections(request), 
+            CI(request,path),null);
+        if (ci != null)
+          return (CollectionAdapter)ci;
+      }
+      return null;
+    }
+    
+    private static final Predicate<CollectionInfo> CI(
+      final RequestContext rc, 
+      final String path) { 
+      return new Predicate<CollectionInfo>() {
+        public boolean apply(CollectionInfo input) {
+          String href = input.getHref(rc);
+          return (
+            path.equals(href) || 
+            (href != null && 
+             path.startsWith(href) && 
+             URI_GEN_DELIMS.contains(
+              path.substring(href.length(), href.length() + 1))));
         }
-
-        return null;
+      }; 
     }
-
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/EntryRequestProcessor.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/EntryRequestProcessor.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/EntryRequestProcessor.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/EntryRequestProcessor.java Fri Oct 21 23:47:50 2011
@@ -17,46 +17,27 @@
  */
 package org.apache.abdera2.common.protocol;
 
+import com.google.common.base.Predicate;
+
 
 /**
  * {@link org.apache.AtompubRequestProcessor.protocol.server.RequestProcessor} implementation which processes requests for entry
  * documents.
  */
 public class EntryRequestProcessor
-    implements RequestProcessor {
+    extends TransactionalRequestProcessor {
   
-    @SuppressWarnings("unchecked")
-    public <S extends ResponseContext>S process(RequestContext context,
-                     WorkspaceManager workspaceManager,
-                     CollectionAdapter collectionAdapter) {
-        if (collectionAdapter == null) {
-            return (S)ProviderHelper.notfound(context);
-        } else {
-            return (S)this.processEntry(context, collectionAdapter);
-        }
+    public EntryRequestProcessor(
+      WorkspaceManager workspaceManager, 
+      CollectionAdapter adapter) {
+        super(workspaceManager,adapter);
     }
 
-    @SuppressWarnings("unchecked")
-    public <S extends ResponseContext>S processEntry(
-        RequestContext context, 
-        CollectionAdapter adapter) {
-        String method = context.getMethod();
-        if (method.equalsIgnoreCase("GET")) {
-            return (S)adapter.getItem(context);
-        } else if (method.equalsIgnoreCase("POST")) {
-            return (S)adapter.postItem(context);
-        } else if (method.equalsIgnoreCase("PUT")) {
-            return (S)adapter.putItem(context);
-        } else if (method.equalsIgnoreCase("DELETE")) {
-            return (S)adapter.deleteItem(context);
-        } else if (method.equalsIgnoreCase("HEAD")) {
-            return (S)adapter.headItem(context);
-        } else if (method.equalsIgnoreCase("OPTIONS")) {
-            return (S)adapter.optionsItem(context);
-        } else if (method.equalsIgnoreCase("PATCH") && adapter instanceof PatchAdapter) {
-            return (S)((PatchAdapter)adapter).patchItem(context);
-        } else {
-            return null;
-        }
-    }
+    public EntryRequestProcessor(
+        WorkspaceManager workspaceManager, 
+        CollectionAdapter adapter,
+        Predicate<RequestContext> predicate) {
+          super(workspaceManager,adapter,predicate);
+      }
+    
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaRequestProcessor.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaRequestProcessor.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaRequestProcessor.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaRequestProcessor.java Fri Oct 21 23:47:50 2011
@@ -17,51 +17,26 @@
  */
 package org.apache.abdera2.common.protocol;
 
+import com.google.common.base.Predicate;
+
 
 /**
  * {@link org.apache.AtompubRequestProcessor.protocol.server.RequestProcessor} implementation which processes requests for media
  * documents.
  */
-@SuppressWarnings("unchecked")
 public class MediaRequestProcessor
-    implements RequestProcessor {
+    extends TransactionalRequestProcessor {
 
-    public <S extends ResponseContext>S process(
-        RequestContext context,
-        WorkspaceManager workspaceManager,
-        CollectionAdapter collectionAdapter) {
-        if (collectionAdapter == null) {
-            return (S)ProviderHelper.notfound(context);
-        } else {
-            return (S)this.processMedia(context, collectionAdapter);
-        }
+    public MediaRequestProcessor(
+      WorkspaceManager workspaceManager, 
+      CollectionAdapter adapter) {
+      super(workspaceManager, adapter);
     }
-
-    public <S extends ResponseContext>S processMedia(
-        RequestContext context, 
-        CollectionAdapter adapter) {
-        String method = context.getMethod();
-        if (adapter instanceof MediaCollectionAdapter) {
-            MediaCollectionAdapter mcadapter = (MediaCollectionAdapter)adapter;
-            if (method.equalsIgnoreCase("GET")) {
-                return (S)mcadapter.getMedia(context);
-            } else if (method.equalsIgnoreCase("POST")) {
-                return (S)mcadapter.postMedia(context);
-            } else if (method.equalsIgnoreCase("PUT")) {
-                return (S)mcadapter.putMedia(context);
-            } else if (method.equalsIgnoreCase("DELETE")) {
-                return (S)mcadapter.deleteMedia(context);
-            } else if (method.equalsIgnoreCase("HEAD")) {
-                return (S)mcadapter.headMedia(context);
-            } else if (method.equalsIgnoreCase("OPTIONS")) {
-                return (S)mcadapter.optionsMedia(context);
-            } else if (method.equalsIgnoreCase("PATCH") && mcadapter instanceof PatchMediaAdapter) {
-                return (S)((PatchMediaAdapter)mcadapter).patchMedia(context);
-            } else {
-                return null;
-            }
-        } else {
-            return (S)ProviderHelper.notallowed(context);
-        }
+    
+    public MediaRequestProcessor(
+      WorkspaceManager workspaceManager, 
+      CollectionAdapter adapter,
+      Predicate<RequestContext> predicate) {
+      super(workspaceManager, adapter,predicate);
     }
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaResponseContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaResponseContext.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaResponseContext.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MediaResponseContext.java Fri Oct 21 23:47:50 2011
@@ -25,9 +25,9 @@ import java.io.OutputStream;
 import java.io.Writer;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
-import java.util.Date;
 
 import org.apache.abdera2.common.http.EntityTag;
+import org.joda.time.DateTime;
 
 /**
  * ResponseContext implementation for arbitrary media resources
@@ -59,14 +59,14 @@ public class MediaResponseContext extend
         this(in,status,true);
     }
 
-    public MediaResponseContext(InputStream in, Date lastmodified, int status, boolean autoclose) {
+    public MediaResponseContext(InputStream in, DateTime lastmodified, int status, boolean autoclose) {
       this.in = in;
       this.status = status;
       this.autoclose = autoclose;
       setLastModified(lastmodified);
     }
     
-    public MediaResponseContext(InputStream in, Date lastmodified, int status) {
+    public MediaResponseContext(InputStream in, DateTime lastmodified, int status) {
         this(in,lastmodified,status,true);
     }
 
@@ -74,7 +74,7 @@ public class MediaResponseContext extend
         this(new ByteArrayInputStream(bytes), status);
     }
 
-    public MediaResponseContext(byte[] bytes, Date lastmodified, int status) {
+    public MediaResponseContext(byte[] bytes, DateTime lastmodified, int status) {
         this(new ByteArrayInputStream(bytes), lastmodified, status);
     }
 
@@ -90,11 +90,11 @@ public class MediaResponseContext extend
         this(channel,status,true);
     }
 
-    public MediaResponseContext(ReadableByteChannel channel, Date lastmodified, int status, boolean autoclose) {
+    public MediaResponseContext(ReadableByteChannel channel, DateTime lastmodified, int status, boolean autoclose) {
       this(Channels.newInputStream(channel), lastmodified,status,autoclose);
     }
     
-    public MediaResponseContext(ReadableByteChannel channel, Date lastmodified, int status) {
+    public MediaResponseContext(ReadableByteChannel channel, DateTime lastmodified, int status) {
         this(channel, lastmodified, status, true);
     }
 

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Message.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Message.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Message.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Message.java Fri Oct 21 23:47:50 2011
@@ -17,8 +17,6 @@
  */
 package org.apache.abdera2.common.protocol;
 
-import java.util.Date;
-
 import javax.activation.MimeType;
 
 import org.apache.abdera2.common.http.Authentication;
@@ -26,6 +24,7 @@ import org.apache.abdera2.common.http.Ca
 import org.apache.abdera2.common.http.Preference;
 import org.apache.abdera2.common.http.WebLink;
 import org.apache.abdera2.common.iri.IRI;
+import org.joda.time.DateTime;
 
 /**
  * A protocol message. This is used as the basis for both request and response objects in order to provide a consistent
@@ -81,7 +80,7 @@ public interface Message {
     /**
      * Return the value of a Date header
      */
-    Date getDateHeader(String name);
+    DateTime getDateHeader(String name);
 
     /**
      * Return the Cache Control Data

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MethodOverrideFilter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MethodOverrideFilter.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MethodOverrideFilter.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/MethodOverrideFilter.java Fri Oct 21 23:47:50 2011
@@ -21,11 +21,12 @@ import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.abdera2.common.misc.Chain;
+import org.apache.abdera2.common.misc.Task;
 
 /**
  * Abdera Filter implementation that supports the use of the X-HTTP-Method-Override header used by GData.
  */
-public class MethodOverrideFilter implements Filter {
+public class MethodOverrideFilter implements Task<RequestContext,ResponseContext> {
 
     private Set<String> methods = new HashSet<String>();
 

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Provider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Provider.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Provider.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Provider.java Fri Oct 21 23:47:50 2011
@@ -21,6 +21,8 @@ import java.util.Map;
 
 import javax.security.auth.Subject;
 
+import org.apache.abdera2.common.misc.Task;
+
 import com.google.common.base.Function;
 
 /**
@@ -58,29 +60,24 @@ public interface Provider
     Target resolveTarget(RequestContext request);
 
     /**
-     * Process the request
-     */
-    <S extends ResponseContext>S process(RequestContext request);
-
-    /**
      * Return the listing of filters for this request
      */
-    Iterable<Filter> getFilters(RequestContext request);
+    Iterable<Task<RequestContext,ResponseContext>> getFilters(RequestContext request);
 
-    <S extends ResponseContext>S createErrorResponse(int code, String message, Throwable t);
+    ResponseContext createErrorResponse(int code, String message, Throwable t);
     
     /**
      * Set a map of {@link AtompubRequestProcessor}s to register on this provider, overriding already registered ones.
      */
-    void setRequestProcessors(Map<TargetType, RequestProcessor> requestProcessors);
+    void setRequestProcessors(Map<TargetType, Function<CollectionAdapter,? extends RequestProcessor>> requestProcessors);
 
     /**
      * Add a map of {@link AtompubRequestProcessor}s to register on this provider, without overriding already registered ones.
      */
-    void addRequestProcessors(Map<TargetType, RequestProcessor> requestProcessors);
+    void addRequestProcessors(Map<TargetType, Function<CollectionAdapter,? extends RequestProcessor>> requestProcessors);
 
     /**
      * Return a map of registered {@link AtompubRequestProcessor}s with related {@link TargetType}.
      */
-    Map<TargetType, RequestProcessor> getRequestProcessors();
+    Map<TargetType, Function<CollectionAdapter,? extends RequestProcessor>> getRequestProcessors();
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ProviderHelper.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ProviderHelper.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ProviderHelper.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ProviderHelper.java Fri Oct 21 23:47:50 2011
@@ -30,6 +30,8 @@ import org.apache.abdera2.common.mediaty
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import com.google.common.base.Predicate;
+
 public class ProviderHelper {
     public final static Log log = LogFactory.getLog(ProviderHelper.class);
 
@@ -287,6 +289,14 @@ public class ProviderHelper {
         return (java.util.Arrays.binarySearch(methods, request.getMethod()) >= 0);
     }
     
+    public static Predicate<RequestContext> isAtom() {
+      return new Predicate<RequestContext>() {
+        public boolean apply(RequestContext input) {
+          return isAtom(input);
+        }
+      };
+    }
+    
     public static boolean isAtom(RequestContext request) {
         MimeType mt = request.getContentType();
         String ctype = (mt != null) ? mt.toString() : null;

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Request.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Request.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Request.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Request.java Fri Oct 21 23:47:50 2011
@@ -17,9 +17,8 @@
  */
 package org.apache.abdera2.common.protocol;
 
-import java.util.Date;
-
 import org.apache.abdera2.common.http.EntityTag;
+import org.joda.time.DateTime;
 
 /**
  * A protocol request. This is used as a base for both server and client requests
@@ -54,7 +53,7 @@ public interface Request extends Message
     /**
      * Get the value of the If-Modified-Since header
      */
-    Date getIfModifiedSince();
+    DateTime getIfModifiedSince();
 
     /**
      * Get a listing of ETags from the If-None-Match header
@@ -64,6 +63,6 @@ public interface Request extends Message
     /**
      * Get the value of the If-Unmodified-Since header
      */
-    Date getIfUnmodifiedSince();
+    DateTime getIfUnmodifiedSince();
 
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/RequestProcessor.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/RequestProcessor.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/RequestProcessor.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/RequestProcessor.java Fri Oct 21 23:47:50 2011
@@ -17,22 +17,108 @@
  */
 package org.apache.abdera2.common.protocol;
 
+import java.lang.reflect.Constructor;
+
+import org.apache.abdera2.common.misc.ExceptionHelper;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+
 /**
  * Request processors implement the actual business logic for handling requests to the Atompub server and producing the
  * related response.
  */
-public interface RequestProcessor {
+public abstract class RequestProcessor 
+  implements Function<RequestContext,ResponseContext> {
  
-    /**
-     * Provide the actual request processing logic.
-     * 
-     * @param requestContext The {@link AtompubRequestContext} object, holding information about the request to process.
-     * @param workspaceManager The {@link AtompubWorkspaceManager} object, holding information useful for request processing.
-     * @param collectionAdapter The {@link AtompubCollectionAdapter} object, holding information useful for request processing;
-     *            may be null if not needed.
-     * @return A {@link AtompubResponseContext} object, as resulted from the request processing.
-     */
-  <S extends ResponseContext>S process(RequestContext requestContext,
-            WorkspaceManager workspaceManager,
-            CollectionAdapter collectionAdapter);
+  protected final WorkspaceManager workspaceManager;
+  protected final CollectionAdapter adapter;
+  protected final Predicate<RequestContext> predicate;
+  
+  protected RequestProcessor(
+    WorkspaceManager workspaceManager, 
+    CollectionAdapter adapter) {
+    this.workspaceManager = workspaceManager;
+    this.adapter = adapter;
+    this.predicate = null;
+  }
+  
+  protected RequestProcessor(
+      WorkspaceManager workspaceManager, 
+      CollectionAdapter adapter,
+      Predicate<RequestContext> predicate) {
+      this.workspaceManager = workspaceManager;
+      this.adapter = adapter;
+      this.predicate = predicate;
+    }
+  
+  protected ResponseContext actuallyApply(RequestContext request) {
+    if (predicate != null && !predicate.apply(request))
+      return ProviderHelper.notallowed(request);
+    Function<RequestContext,ResponseContext> handler = 
+      adapter.handlerFor(
+        request.getTarget(),
+        request.getMethod());
+    return handler != null ?
+      handler.apply(request) :
+      ProviderHelper.notfound(request);
+  }
+  
+  public ResponseContext apply(RequestContext request) {
+    return actuallyApply(request);
+  }
+
+  public static abstract class RequestProcessorSupplier<T extends RequestProcessor> 
+    implements Function<CollectionAdapter,T> {
+    protected final WorkspaceManager workspaceManager;
+    protected RequestProcessorSupplier(
+      WorkspaceManager workspaceManager) {
+      this.workspaceManager = workspaceManager;
+    }
+  }
+  
+  public static <T extends RequestProcessor>Function<CollectionAdapter,T> forClass(
+      final Class<T> _class, 
+      final WorkspaceManager workspaceManager,
+      final Predicate<RequestContext> predicate) {
+      try {
+        final Constructor<T> c = 
+          _class.getConstructor(
+            WorkspaceManager.class,
+            CollectionAdapter.class);
+        return new RequestProcessorSupplier<T>(workspaceManager) {
+          public T apply(CollectionAdapter adapter) {
+            try {
+              return c.newInstance(workspaceManager,adapter);
+            } catch (Throwable t) {
+              throw ExceptionHelper.propogate(t);
+            }
+          }
+        };
+      } catch (Throwable t) {
+        throw ExceptionHelper.propogate(t);
+      }
+    }
+  
+  public static <T extends RequestProcessor>Function<CollectionAdapter,T> forClass(
+    final Class<T> _class, 
+    final WorkspaceManager workspaceManager) {
+    try {
+      final Constructor<T> c = 
+        _class.getConstructor(
+          WorkspaceManager.class,
+          CollectionAdapter.class);
+      return new RequestProcessorSupplier<T>(workspaceManager) {
+        public T apply(CollectionAdapter adapter) {
+          try {
+            return c.newInstance(workspaceManager,adapter);
+          } catch (Throwable t) {
+            throw ExceptionHelper.propogate(t);
+          }
+        }
+      };
+    } catch (Throwable t) {
+      throw ExceptionHelper.propogate(t);
+    }
+  }
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Response.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Response.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Response.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Response.java Fri Oct 21 23:47:50 2011
@@ -17,11 +17,10 @@
  */
 package org.apache.abdera2.common.protocol;
 
-import java.util.Date;
-
 import org.apache.abdera2.common.iri.IRI;
 import org.apache.abdera2.common.http.EntityTag;
 import org.apache.abdera2.common.http.ResponseType;
+import org.joda.time.DateTime;
 
 /**
  * Base interface for an Atompub protocol response message
@@ -51,7 +50,7 @@ public interface Response extends Messag
     /**
      * Get the value of the Last-Modified response header
      */
-    Date getLastModified();
+    DateTime getLastModified();
 
     /**
      * Get the value of the Content-Length response header
@@ -76,6 +75,6 @@ public interface Response extends Messag
     /**
      * Get the date/time this response expires
      */
-    Date getExpires();
+    DateTime getExpires();
 
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContext.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContext.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContext.java Fri Oct 21 23:47:50 2011
@@ -19,13 +19,13 @@ package org.apache.abdera2.common.protoc
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Date;
 
 import org.apache.abdera2.common.text.CharUtils.Profile;
 import org.apache.abdera2.common.http.CacheControl;
 import org.apache.abdera2.common.http.EntityTag;
 import org.apache.abdera2.common.http.Preference;
 import org.apache.abdera2.common.http.WebLink;
+import org.joda.time.DateTime;
 
 /**
  * The ResponseContext encapsulates a server response
@@ -159,12 +159,12 @@ public interface ResponseContext extends
     /**
      * Set the value of the Expires header
      */
-    <B extends ResponseContext>B setExpires(Date date);
+    <B extends ResponseContext>B setExpires(DateTime date);
 
     /**
      * Set the value of the Last-Modified header
      */
-    <B extends ResponseContext>B setLastModified(Date date);
+    <B extends ResponseContext>B setLastModified(DateTime date);
 
     /**
      * Set the value of the Location header

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContextException.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContextException.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContextException.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/ResponseContextException.java Fri Oct 21 23:47:50 2011
@@ -17,6 +17,8 @@
  */
 package org.apache.abdera2.common.protocol;
 
+import org.apache.abdera2.common.http.ResponseType;
+
 
 public class ResponseContextException extends RuntimeException {
 
@@ -60,4 +62,8 @@ public class ResponseContextException ex
     public int getStatusCode() {
         return responseContext.getStatus();
     }
+    
+    public ResponseType getResponseType() {
+      return ResponseType.select(getStatusCode());
+    }
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Target.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Target.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Target.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/Target.java Fri Oct 21 23:47:50 2011
@@ -17,6 +17,7 @@
  */
 package org.apache.abdera2.common.protocol;
 
+import com.google.common.base.Predicate;
 
 /**
  * Identifies the target of the request.
@@ -50,4 +51,11 @@ public interface Target extends Iterable
      */
     public <T> T getMatcher();
 
+    public static final Predicate<Target> NOT_FOUND = 
+      new Predicate<Target>() {
+        public boolean apply(Target input) {
+          return input == null || 
+                 input.getType() == TargetType.TYPE_NOT_FOUND;
+        }
+    };
 }

Added: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TargetFunctionResolver.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TargetFunctionResolver.java?rev=1187599&view=auto
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TargetFunctionResolver.java (added)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TargetFunctionResolver.java Fri Oct 21 23:47:50 2011
@@ -0,0 +1,229 @@
+package org.apache.abdera2.common.protocol;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.abdera2.common.iri.IRI;
+import org.apache.abdera2.common.misc.AbstractResolver;
+import org.apache.abdera2.common.misc.ExceptionHelper;
+import org.apache.abdera2.common.misc.Resolver;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+
+/**
+ * A TargetResolver based on a Set of Function objects. Each 
+ * Function is attempted in the order it is added to the 
+ * resolver. If the Function returns a Target, execution 
+ * stops and the target is returned, otherwise the next 
+ * function in the list is tried
+ */
+public class TargetFunctionResolver<R extends RequestContext>
+  extends AbstractResolver<Target,R>
+  implements Resolver<Target,R> {
+
+  public static <R extends RequestContext>TargetFunctionResolver<R> create(
+    TargetFunction<R>... functions) {
+      return create(Arrays.asList(functions));
+  }
+  
+  public static <R extends RequestContext>TargetFunctionResolver<R> create( 
+    Iterable<TargetFunction<R>> functions) {
+      return new TargetFunctionResolver<R>(functions);
+  }
+  
+  protected final Set<TargetFunction<R>> functions = 
+    new LinkedHashSet<TargetFunction<R>>();
+
+  private TargetFunctionResolver(
+    Iterable<TargetFunction<R>> functions) {
+      Iterables.addAll(this.functions, functions);
+  }
+
+  public TargetFunctionResolver<R> addFunction(
+    TargetFunction<R> function) {
+      this.functions.add(function);
+      return this;
+  }
+
+  public Target resolve(R request) {
+    for (TargetFunction<R> f : functions) {
+      Target target = f.apply(request);
+      if (target != null)
+        return target;
+    }
+    return null;
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((functions == null) ? 0 : functions.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    TargetFunctionResolver<?> other = 
+      (TargetFunctionResolver<?>) obj;
+    if (functions == null) {
+      if (other.functions != null)
+        return false;
+    } else if (!functions.equals(other.functions))
+      return false;
+    return true;
+  }
+
+  /**
+   * A Function that Resolves a Target from a RequestContext
+   */
+  public static abstract class TargetFunction<R extends RequestContext>
+    implements Function<R,Target> {
+        
+  }
+ 
+  /**
+   * Returns a Generator used to build PredicateTargetfunction instances
+   */
+  public static <R extends RequestContext>PredicateTargetFunction.Generator<R> make() {
+    return new PredicateTargetFunction.Generator<R>();
+  }
+  
+  /**
+   * A TargetFunction that is based on a map of Predicates and Functions.
+   * The RequestContext is tested against each Predicate in the order the
+   * Predicate was added. If apply() returns true, the associated Function
+   * is used to return the appropriate Target instance.
+   */
+  public static class PredicateTargetFunction<R extends RequestContext>
+    extends TargetFunction<R> {    
+    public static class Generator<R extends RequestContext> implements Supplier<TargetFunction<R>> {
+      private final Map<Predicate<R>,Function<R,Target>> map =
+        new LinkedHashMap<Predicate<R>,Function<R,Target>>();
+      public Generator<R> set(Predicate<R> test, Function<R,Target> function) {
+        map.put(test,function);
+        return this;
+      }
+      public TargetFunction<R> get() {
+        return new PredicateTargetFunction<R>(map);
+      }
+    }
+    
+    private final Map<Predicate<R>,Function<R,Target>> map =
+      new HashMap<Predicate<R>,Function<R,Target>>();
+    
+    protected PredicateTargetFunction(
+      Map<Predicate<R>,Function<R,Target>> map) {
+        this.map.putAll(map);
+    }
+    
+    public Target apply(R input) { 
+      try {
+        for (Predicate<R> test : map.keySet())
+          if (test.apply(input))
+            return map.get(test).apply(input);
+        return null;
+      } catch (Throwable t) {
+        throw ExceptionHelper.propogate(t);
+      }
+    }
+  }
+  
+  /**
+   * A TargetFunction that resolves Targets based primarily off the 
+   * Request URI
+   */
+  public static abstract class RequestUriFunction<R extends RequestContext>
+    extends TargetFunction<R>
+    implements Function<R,Target> {
+    public Target apply(R input) {
+      return apply(input,input.getResolvedUri());
+    }
+    protected abstract Target apply(R context,IRI uri);
+  }
+  
+  /**
+   * A Predicate that tests the Request URI
+   */
+  public static abstract class RequestUriPredicate<R extends RequestContext> 
+    implements Predicate<R> {
+    public boolean apply(R input) {
+      return apply(input.getResolvedUri());
+    }
+    protected abstract boolean apply(IRI uri);
+  }
+  
+  /**
+   * A TargetFunction that performs a Regex Pattern match on the 
+   * Request URI. If the Pattern matches, a RegexTarget instance
+   * is returned. This Function can be used either directly by 
+   * the TargetFunctionResolver or as part of the PredicateTargetFunction
+   */
+  public static class RegexUriFunction<R extends RequestContext>
+    extends RequestUriFunction<R> {
+    private final Pattern pattern;
+    private final TargetType type;
+    private final Iterable<String> fields;
+    public RegexUriFunction(TargetType type, Pattern pattern, String... fields) {
+      this.type = type;
+      this.pattern = pattern;
+      this.fields = Arrays.<String>asList(fields);
+    }
+    public RegexUriFunction(TargetType type, String pattern, String... fields) {
+      this(type,Pattern.compile(pattern),fields);
+    }
+    protected Target apply(R context,IRI uri) {
+      Matcher matcher = pattern.matcher(uri.toString());
+      return matcher.matches() ?
+        new RegexTargetResolver.RegexTarget(type,context,matcher,fields) : 
+        null;
+    }  
+  }
+  
+  /**
+   * Predicate that tests the Request URI against a Regex Pattern
+   */
+  public static class RegexUriPredicate<R extends RequestContext> 
+    extends RequestUriPredicate<R> {
+    private final Pattern pattern;
+    public RegexUriPredicate(Pattern pattern) {
+      this.pattern = pattern;
+    }
+    public RegexUriPredicate(String pattern) {
+      this(Pattern.compile(pattern));
+    }
+    protected boolean apply(IRI uri) {
+      return pattern.matcher(uri.toString()).matches();
+    }
+  }
+  
+  public static <R extends RequestContext>Function<R,Target> functionForRegex(Pattern pattern, TargetType type, String... fields) {
+    return new RegexUriFunction<R>(type,pattern,fields);
+  }
+  
+  public static <R extends RequestContext>Function<R,Target> functionForRegex(String pattern, TargetType type, String... fields) {
+    return new RegexUriFunction<R>(type,pattern,fields);
+  }
+  
+  public static <R extends RequestContext>Predicate<R> predicateForRegex(Pattern pattern) {
+    return new RegexUriPredicate<R>(pattern);
+  }
+  
+  public static <R extends RequestContext>Predicate<R> predicateForRegex(String pattern) {
+    return new RegexUriPredicate<R>(pattern);
+  }
+}

Propchange: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TargetFunctionResolver.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TransactionalRequestProcessor.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TransactionalRequestProcessor.java?rev=1187599&view=auto
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TransactionalRequestProcessor.java (added)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TransactionalRequestProcessor.java Fri Oct 21 23:47:50 2011
@@ -0,0 +1,57 @@
+package org.apache.abdera2.common.protocol;
+
+import org.apache.abdera2.common.misc.ExceptionHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.base.Predicate;
+
+public abstract class TransactionalRequestProcessor 
+  extends RequestProcessor
+  implements Transactional {
+
+  private final static Log log = 
+    LogFactory.getLog(
+      TransactionalRequestProcessor.class);
+  
+  protected TransactionalRequestProcessor(
+    WorkspaceManager workspaceManager,
+    CollectionAdapter adapter) {
+      super(workspaceManager, adapter);
+  }
+  
+  protected TransactionalRequestProcessor(
+    WorkspaceManager workspaceManager,
+    CollectionAdapter adapter,
+    Predicate<RequestContext> predicate) {
+      super(workspaceManager,adapter,predicate);
+  }
+
+  public void start(RequestContext request) {
+    // the default is to do nothing here
+  }
+
+  public void end(RequestContext request, ResponseContext response) {
+    // the default is to do nothing here
+  }
+
+  public void compensate(RequestContext request, Throwable t) {
+    // the default is to do nothing here
+  }
+
+  public ResponseContext apply(RequestContext input) {
+    ResponseContext response = null;
+    try {
+      start(input);
+      response = actuallyApply(input);
+      return response;
+    } catch (Throwable e) {
+      ExceptionHelper.log(log,e);
+      compensate(input,e);
+      throw ExceptionHelper.propogate(e);
+    } finally {
+      end(input, response);
+    }
+  }
+
+}

Propchange: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/TransactionalRequestProcessor.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceInfo.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceInfo.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceInfo.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceInfo.java Fri Oct 21 23:47:50 2011
@@ -17,8 +17,6 @@
  */
 package org.apache.abdera2.common.protocol;
 
-import java.util.Collection;
-
 
 /**
  * Metadata interface used by WorkspaceManager and Provider implementations to construct Atompub Service Documents. The
@@ -35,6 +33,6 @@ public interface WorkspaceInfo {
     /**
      * Return the listing of collections available as part of the workspace
      */
-    Collection<CollectionInfo> getCollections(RequestContext request);
+    Iterable<CollectionInfo> getCollections(RequestContext request);
 
 }

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceManager.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceManager.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/WorkspaceManager.java Fri Oct 21 23:47:50 2011
@@ -18,9 +18,9 @@
 package org.apache.abdera2.common.protocol;
 
 import java.util.Collection;
-import java.util.Date;
 
 import org.apache.abdera2.common.http.EntityTag;
+import org.joda.time.DateTime;
 
 /**
  * The Workspace Manager is used by a Provider to access metadata used to construct Atompub service documents and to
@@ -38,7 +38,7 @@ public interface WorkspaceManager {
      */
     Collection<WorkspaceInfo> getWorkspaces(RequestContext request);
 
-    Date getLastModified();
+    DateTime getLastModified();
     
     EntityTag getEntityTag();
     

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/AbstractAbderaServlet.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/AbstractAbderaServlet.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/AbstractAbderaServlet.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/AbstractAbderaServlet.java Fri Oct 21 23:47:50 2011
@@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.abdera2.common.http.CacheControl;
-import org.apache.abdera2.common.misc.Chain;
 import org.apache.abdera2.common.protocol.RequestContext;
 import org.apache.abdera2.common.protocol.ResponseContext;
 import org.apache.abdera2.common.protocol.Provider;
@@ -80,13 +79,8 @@ public abstract class AbstractAbderaServ
       HttpServletResponse response,
       ServletContext context) {
       RequestContext reqcontext = new ServletRequestContext(provider, request, context);
-      Chain<RequestContext,ResponseContext> chain = 
-        Chain.<RequestContext,ResponseContext>make()
-        .to(provider)
-        .via(provider.getFilters(reqcontext))
-        .get();
       try {
-          output(request, response, chain.next(reqcontext));
+          output(request, response, provider.apply(reqcontext));
       } catch (Throwable t) {
           error("Error servicing request", t, response);
           return;

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/ServletRequestContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/ServletRequestContext.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/ServletRequestContext.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/ServletRequestContext.java Fri Oct 21 23:47:50 2011
@@ -36,6 +36,7 @@ import org.apache.abdera2.common.Localiz
 import org.apache.abdera2.common.iri.IRI;
 import org.apache.abdera2.common.protocol.AbstractBaseRequestContext;
 import org.apache.abdera2.common.protocol.Provider;
+import org.joda.time.DateTime;
 
 @SuppressWarnings({ "unchecked" })
 public class ServletRequestContext 
@@ -139,9 +140,9 @@ public class ServletRequestContext 
         return values != null ? java.util.Arrays.asList(values) : null;
     }
 
-    public Date getDateHeader(String name) {
+    public DateTime getDateHeader(String name) {
         long value = request.getDateHeader(name);
-        return value != -1 ? new Date(value) : null;
+        return value != -1 ? new DateTime(value) : null;
     }
 
     public String getHeader(String name) {

Modified: abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/async/AbderaTask.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/async/AbderaTask.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/async/AbderaTask.java (original)
+++ abdera/abdera2/common/src/main/java/org/apache/abdera2/common/protocol/servlet/async/AbderaTask.java Fri Oct 21 23:47:50 2011
@@ -27,7 +27,6 @@ import javax.servlet.http.HttpServletReq
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.abdera2.common.http.CacheControl;
-import org.apache.abdera2.common.misc.Chain;
 import org.apache.abdera2.common.protocol.RequestContext;
 import org.apache.abdera2.common.protocol.ResponseContext;
 import org.apache.abdera2.common.protocol.Provider;
@@ -95,14 +94,9 @@ public class AbderaTask {
     Provider provider,
     HttpServletRequest request,
     HttpServletResponse response) {
-    Chain<RequestContext,ResponseContext> chain =
-      Chain.<RequestContext,ResponseContext>make()
-      .to(provider)
-      .via(provider.getFilters(requestContext))
-      .get();
     try {
         log.debug(String.format("Using RequestContext: %s",requestContext.getClass().getName()));
-        output(request, response, chain.next(requestContext), provider);
+        output(request, response, provider.apply(requestContext), provider);
     } catch (Throwable t) {
         error("Error servicing request", t, response, provider);
         return;

Modified: abdera/abdera2/core/src/main/java/org/apache/abdera2/model/Collection.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/core/src/main/java/org/apache/abdera2/model/Collection.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/core/src/main/java/org/apache/abdera2/model/Collection.java (original)
+++ abdera/abdera2/core/src/main/java/org/apache/abdera2/model/Collection.java Fri Oct 21 23:47:50 2011
@@ -131,6 +131,8 @@ public interface Collection extends Exte
      */
     Collection setAccept(String... mediaRanges);
 
+    Collection setAccept(Iterable<String> mediaRanges);
+    
     /**
      * Returns true if the collection accepts the given media-type
      * 

Modified: abdera/abdera2/core/src/main/java/org/apache/abdera2/parser/axiom/FOMCollection.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/core/src/main/java/org/apache/abdera2/parser/axiom/FOMCollection.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/core/src/main/java/org/apache/abdera2/parser/axiom/FOMCollection.java (original)
+++ abdera/abdera2/core/src/main/java/org/apache/abdera2/parser/axiom/FOMCollection.java Fri Oct 21 23:47:50 2011
@@ -40,6 +40,8 @@ import org.apache.axiom.om.OMFactory;
 import org.apache.axiom.om.OMNamespace;
 import org.apache.axiom.om.OMXMLParserWrapper;
 
+import com.google.common.collect.Iterables;
+
 @SuppressWarnings({"deprecation","rawtypes"})
 public class FOMCollection extends FOMExtensibleElement implements Collection {
 
@@ -147,6 +149,10 @@ public class FOMCollection extends FOMEx
         return setAccept(new String[] {mediaRange});
     }
 
+    public Collection setAccept(Iterable<String> mediaRanges) {
+      return setAccept(Iterables.toArray(mediaRanges, String.class));
+    }
+    
     public Collection setAccept(String... mediaRanges) {
         complete();
         if (mediaRanges != null && mediaRanges.length > 0) {

Modified: abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/AbstractEntityProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/AbstractEntityProvider.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/AbstractEntityProvider.java (original)
+++ abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/AbstractEntityProvider.java Fri Oct 21 23:47:50 2011
@@ -17,9 +17,8 @@
  */
 package org.apache.abdera2.protocol;
 
-import java.util.Date;
-
 import org.apache.abdera2.common.http.EntityTag;
+import org.joda.time.DateTime;
 
 public abstract class AbstractEntityProvider implements EntityProvider {
 
@@ -31,7 +30,7 @@ public abstract class AbstractEntityProv
         return null;
     }
 
-    public Date getLastModified() {
+    public DateTime getLastModified() {
         return null;
     }
 

Modified: abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/EntityProvider.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/EntityProvider.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/EntityProvider.java (original)
+++ abdera/abdera2/core/src/main/java/org/apache/abdera2/protocol/EntityProvider.java Fri Oct 21 23:47:50 2011
@@ -17,10 +17,9 @@
  */
 package org.apache.abdera2.protocol;
 
-import java.util.Date;
-
 import org.apache.abdera2.common.http.EntityTag;
 import org.apache.abdera2.writer.StreamWriter;
+import org.joda.time.DateTime;
 
 /**
  * An EntityProvider is used to serialize entities using the StreamWriter interface. The EntityProvider interface can be
@@ -51,6 +50,6 @@ public interface EntityProvider {
     /**
      * Return the Last-Modified date of the entity
      */
-    Date getLastModified();
+    DateTime getLastModified();
 
 }

Modified: abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/AbstractStreamWriter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/AbstractStreamWriter.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/AbstractStreamWriter.java (original)
+++ abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/AbstractStreamWriter.java Fri Oct 21 23:47:50 2011
@@ -458,6 +458,13 @@ public abstract class AbstractStreamWrit
         return this;
     }
 
+    public StreamWriter writeAccepts(Iterable<String> accepts) {
+      for (String accept : accepts) {
+        startElement(Constants.ACCEPT).writeElementText(accept).endElement();
+      }
+      return this;
+    }
+    
     public StreamWriter writeAccepts(String... accepts) {
         for (String accept : accepts) {
             startElement(Constants.ACCEPT).writeElementText(accept).endElement();

Modified: abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/StreamWriter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/StreamWriter.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/StreamWriter.java (original)
+++ abdera/abdera2/core/src/main/java/org/apache/abdera2/writer/StreamWriter.java Fri Oct 21 23:47:50 2011
@@ -1079,6 +1079,8 @@ public interface StreamWriter extends Ap
      * @param accepts accept element values
      */
     StreamWriter writeAccepts(String... accepts);
+    
+    StreamWriter writeAccepts(Iterable<String> accepts);
 
     /**
      * Writes an app:accept element indicating that entries are accepted

Modified: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/AppServer.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/AppServer.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/AppServer.java (original)
+++ abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/AppServer.java Fri Oct 21 23:47:50 2011
@@ -51,15 +51,16 @@ public class AppServer {
         private static final long serialVersionUID = -549428240693531463L;
 
         protected Provider createProvider() {
-            EmployeeCollectionAdapter ca = new EmployeeCollectionAdapter();
-            ca.setHref("employee");
-
-            SimpleWorkspaceInfo wi = new SimpleWorkspaceInfo();
-            wi.setTitle("Employee Directory Workspace");
-            wi.addCollection(ca);
-
-            DefaultAtompubProvider provider = new DefaultAtompubProvider("/");
-            provider.addWorkspace(wi);
+            EmployeeCollectionAdapter ca = new EmployeeCollectionAdapter("employee");
+            DefaultAtompubProvider provider = 
+              new DefaultAtompubProvider("/");
+            provider
+              .addWorkspace(
+                SimpleWorkspaceInfo
+                  .make()
+                  .title("Employee Directory Workspace")
+                  .collection(ca)
+                  .get());
 
             provider.init(Abdera.getInstance(), null);
             return provider;

Modified: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/EmployeeCollectionAdapter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/EmployeeCollectionAdapter.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/EmployeeCollectionAdapter.java (original)
+++ abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/appserver/employee/EmployeeCollectionAdapter.java Fri Oct 21 23:47:50 2011
@@ -34,6 +34,10 @@ import org.apache.abdera2.protocol.serve
 import org.joda.time.DateTime;
 
 public class EmployeeCollectionAdapter extends AbstractEntityCollectionAdapter<Employee> {
+    public EmployeeCollectionAdapter(String href) {
+    super(href);
+  }
+
     private static final String ID_PREFIX = "tag:acme.com,2007:employee:entry:";
 
     private AtomicInteger nextId = new AtomicInteger(1000);

Modified: abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/simple/EntityProviderExample.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/simple/EntityProviderExample.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/simple/EntityProviderExample.java (original)
+++ abdera/abdera2/examples/src/main/java/org/apache/abdera2/examples/simple/EntityProviderExample.java Fri Oct 21 23:47:50 2011
@@ -17,12 +17,11 @@
  */
 package org.apache.abdera2.examples.simple;
 
-import java.util.Date;
-
 import org.apache.abdera2.Abdera;
 import org.apache.abdera2.protocol.EntityProvider;
 import org.apache.abdera2.common.http.EntityTag;
 import org.apache.abdera2.writer.StreamWriter;
+import org.joda.time.DateTime;
 
 /**
  * The EntityProvider interface allows developers to provide custom Object-to-Java serialization based on the
@@ -55,7 +54,7 @@ public class EntityProviderExample {
             return EntityTag.generate(foo, bar, baz);
         }
 
-        public Date getLastModified() {
+        public DateTime getLastModified() {
             return null;
         }
 

Modified: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java (original)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/json/JSONFilter.java Fri Oct 21 23:47:50 2011
@@ -24,9 +24,9 @@ import java.io.OutputStream;
 
 import org.apache.abdera2.Abdera;
 import org.apache.abdera2.common.misc.Chain;
+import org.apache.abdera2.common.misc.Task;
 import org.apache.abdera2.common.protocol.RequestContext;
 import org.apache.abdera2.common.protocol.ResponseContext;
-import org.apache.abdera2.common.protocol.Filter;
 import org.apache.abdera2.common.protocol.ProviderHelper;
 import org.apache.abdera2.model.Document;
 import org.apache.abdera2.model.Element;
@@ -39,7 +39,7 @@ import org.apache.abdera2.writer.Writer;
  * specifies a higher preference value for JSON or explicitly requests JSON by including a format=json querystring
  * parameter
  */
-public class JSONFilter implements Filter {
+public class JSONFilter implements Task<RequestContext,ResponseContext> {
 
     public ResponseContext apply(RequestContext request, Chain<RequestContext,ResponseContext> chain) {
         AtompubResponseContext resp = (AtompubResponseContext) chain.next(request);

Modified: abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/serializer/ObjectResponseContext.java
URL: http://svn.apache.org/viewvc/abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/serializer/ObjectResponseContext.java?rev=1187599&r1=1187598&r2=1187599&view=diff
==============================================================================
--- abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/serializer/ObjectResponseContext.java (original)
+++ abdera/abdera2/ext/src/main/java/org/apache/abdera2/ext/serializer/ObjectResponseContext.java Fri Oct 21 23:47:50 2011
@@ -19,16 +19,13 @@ package org.apache.abdera2.ext.serialize
 
 import java.io.IOException;
 import java.lang.reflect.AccessibleObject;
-import java.util.Calendar;
-import java.util.Date;
-
 import org.apache.abdera2.Abdera;
-import org.apache.abdera2.common.date.DateTimes;
 import org.apache.abdera2.ext.serializer.annotation.EntityTag;
 import org.apache.abdera2.ext.serializer.annotation.LastModified;
 import org.apache.abdera2.ext.serializer.annotation.MediaType;
 import org.apache.abdera2.protocol.server.context.StreamWriterResponseContext;
 import org.apache.abdera2.writer.StreamWriter;
+import org.joda.time.DateTime;
 
 public class ObjectResponseContext extends StreamWriterResponseContext {
 
@@ -84,8 +81,8 @@ public class ObjectResponseContext exten
         setLastModified(getObjectLastModified());
     }
 
-    private Date getObjectLastModified() {
-        Date date = null;
+    private DateTime getObjectLastModified() {
+        DateTime date = null;
         AccessibleObject accessor = objectContext.getAccessor(LastModified.class, conventions);
         if (accessor != null) {
             Object value = BaseSerializer.eval(accessor, object);
@@ -94,22 +91,8 @@ public class ObjectResponseContext exten
         return date;
     }
 
-    private Date getDate(Object value) {
-        Date date = null;
-        if (value == null)
-            return null;
-        if (value instanceof Date) {
-            date = (Date)value;
-        } else if (value instanceof Calendar) {
-            date = ((Calendar)value).getTime();
-        } else if (value instanceof Long) {
-            date = new Date(((Long)value).longValue());
-        } else if (value instanceof String) {
-            date = DateTimes.parse((String)value);
-        } else {
-            date = DateTimes.parse(value.toString());
-        }
-        return date;
+    private DateTime getDate(Object value) {
+        return new DateTime(value);
     }
 
     private String getObjectEntityTag() {