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 2008/01/21 06:33:58 UTC

svn commit: r613765 [3/4] - in /incubator/abdera/java/branches/server_refactor/src: main/java/org/ main/java/org/apache/ main/java/org/apache/abdera/ main/java/org/apache/abdera/protocol/ main/java/org/apache/abdera/protocol/server/ main/java/org/apach...

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractEntityCollectionAdapter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractEntityCollectionAdapter.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractEntityCollectionAdapter.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractEntityCollectionAdapter.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,506 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.provider.ext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.List;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.model.Person;
+import org.apache.abdera.model.Text;
+import org.apache.abdera.parser.ParseException;
+import org.apache.abdera.protocol.server.MediaCollectionAdapter;
+import org.apache.abdera.protocol.server.ProviderHelper;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.impl.EmptyResponseContext;
+import org.apache.abdera.protocol.server.impl.MediaResponseContext;
+import org.apache.abdera.protocol.server.impl.ResponseContextException;
+import org.apache.abdera.util.MimeTypeHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public abstract class AbstractEntityCollectionAdapter<T> 
+  extends AbstractNamedCollectionAdapter
+  implements MediaCollectionAdapter {
+
+  private final static Log log = LogFactory.getLog(AbstractEntityCollectionAdapter.class);
+  
+  public abstract void deleteEntry(
+    String resourceName, 
+    RequestContext request)
+      throws ResponseContextException;
+  
+  public void deleteMedia(
+    String resourceName, 
+    RequestContext request)
+      throws ResponseContextException {
+    throw new UnsupportedOperationException();
+  }
+ 
+  public ResponseContext deleteEntry(RequestContext request) {
+    String id = getEntryID(request);
+    if (id != null) {
+      try {
+        deleteEntry(id, request);
+      } catch (ResponseContextException e) {
+        return createErrorResponse(e);
+      }
+      return ProviderHelper.nocontent("No Content");
+    } else {
+      return ProviderHelper.notfound(request,"Not Found");
+    }
+  }
+
+  public ResponseContext deleteMedia(
+    RequestContext request) {
+    String id = getEntryID(request);
+    if (id != null) {
+      try {
+        deleteMedia(id, request);
+      } catch (ResponseContextException e) {
+        return createErrorResponse(e);
+      }
+      return ProviderHelper.nocontent("No Content");
+    } else {
+      return ProviderHelper.notfound(request,"Not Found");
+    }
+  }
+  
+  public List<Person> getAuthors(
+    T entry, 
+    RequestContext request) 
+      throws ResponseContextException {
+    return null;
+  }
+
+  public abstract Object getContent(
+    T entry, 
+    RequestContext request) 
+      throws ResponseContextException;
+  
+  public String getContentType(T entry) {
+    throw new UnsupportedOperationException();
+  }
+  
+  public abstract Iterable<T> getEntries(
+    RequestContext request) 
+      throws ResponseContextException;
+
+  
+  public ResponseContext getEntry(
+    RequestContext request) {
+    try {
+      IRI entryBaseIri = ProviderHelper.resolveBase(request).resolve("./");
+      Entry entry = 
+        getEntryFromCollectionProvider(
+          entryBaseIri,
+          request);
+      if (entry != null) {
+        return buildGetEntryResponse(request, entry);
+      } else {
+        return new EmptyResponseContext(404);
+      }
+    } catch (ResponseContextException e) {
+      return createErrorResponse(e);
+    }
+  }
+
+  public abstract T getEntry(
+    String resourceName, 
+    RequestContext request) 
+      throws ResponseContextException;
+
+  public ResponseContext getFeed(
+    RequestContext request) {
+      Feed feed = createFeedBase(request);    
+      return getFeed(feed, request);
+  }
+  
+  public ResponseContext getFeed(
+    Feed feed, 
+    RequestContext request) {
+      try {
+        addFeedDetails(feed, request);
+        return buildGetFeedResponse(feed);
+      } catch (ResponseContextException e) {
+        return createErrorResponse(e);
+      }
+  }
+
+  protected void addFeedDetails(
+    Feed feed, 
+    RequestContext request) 
+      throws ResponseContextException {
+    feed.setUpdated(new Date());
+    IRI baseIri = ProviderHelper.resolveBase(request);
+    IRI entryIri = getEntryBaseFromFeedIRI(baseIri);    
+    Iterable<T> entries = getEntries(request);
+    if (entries != null) {
+      for (T entryObj : entries) {
+        Entry e = feed.addEntry();  
+        addEntryDetails(request, e, entryIri, entryObj);
+        if (isMediaEntry(entryObj)) {
+          addMediaContent(entryIri, e, entryObj);
+        } else {
+          addContent(e, entryObj, request);
+        }
+      }
+    }
+  }
+  
+  /**
+   * Gets the UUID for the specified entry.
+   * @param entry
+   * @return
+   */
+  public abstract String getId(
+    T entry) 
+      throws ResponseContextException;
+
+  public ResponseContext getMedia(
+    RequestContext request) {
+      try {
+        String id = getEntryID(request);
+        T entryObj = getEntry(id, request);
+        if (entryObj == null) {
+          return new EmptyResponseContext(404);
+        }  
+        return buildGetMediaResponse(entryObj);
+      } catch (ParseException pe) {
+        return new EmptyResponseContext(415);
+      } catch (ClassCastException cce) {
+        return new EmptyResponseContext(415);
+      } catch (ResponseContextException e) {
+        return e.getResponseContext();
+      } catch (Exception e) {
+        log.warn(e.getMessage(), e);
+        return new EmptyResponseContext(400);
+      }
+  }
+
+  protected ResponseContext buildGetMediaResponse(
+    T entryObj) 
+      throws ResponseContextException {
+    MediaResponseContext ctx = 
+      new MediaResponseContext(
+        getMediaStream(entryObj), 
+        getUpdated(entryObj), 200);
+    ctx.setContentType(getContentType(entryObj));
+    return ctx;
+  }
+  public String getMediaName(
+    T entry) 
+      throws ResponseContextException {
+    throw new UnsupportedOperationException();
+  }
+
+  public InputStream getMediaStream(
+    T entry) 
+      throws ResponseContextException {
+    throw new UnsupportedOperationException();
+  }
+  
+  public abstract String getName(
+    T entry) 
+      throws ResponseContextException;
+
+  public abstract String getTitle(
+    T entry) 
+      throws ResponseContextException;
+
+  public abstract Date getUpdated(
+    T entry) 
+      throws ResponseContextException;
+
+  public boolean isMediaEntry(
+    T entry) 
+      throws ResponseContextException {
+    return false;
+  }
+  
+  public T updateMedia(
+      String resourceName,
+      MimeType mimeType, 
+      String slug, 
+      InputStream inputStream, 
+      RequestContext request) 
+        throws ResponseContextException {
+      throw new UnsupportedOperationException();
+  }
+  
+  public ResponseContext putMedia(
+    RequestContext request) {
+      try {
+        String id = getEntryID(request);
+        if (id != null) {
+          try {
+            updateMedia(
+              id,
+              request.getContentType(),
+              request.getSlug(),
+              request.getInputStream(),
+              request);
+          } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+          }
+          return ProviderHelper.nocontent("No Content");
+        } else {
+          return ProviderHelper.notfound(request,"Not Found");
+        }
+      } catch (IOException e) {
+        return ProviderHelper.servererror(request, "Server Error", e);
+      }
+  }
+  
+  public ResponseContext putEntry(
+    RequestContext request) {
+      try {
+        IRI feedIri = ProviderHelper.resolveBase(request).resolve("./");
+        String id = getEntryID(request);
+        T entryObj = getEntry(id, request);        
+        if (entryObj == null)
+          return new EmptyResponseContext(404);      
+        Entry orig_entry = 
+          getEntryFromCollectionProvider(
+            entryObj, feedIri, request);
+        if (orig_entry != null) {
+          MimeType contentType = request.getContentType();
+          if (contentType != null && 
+              !MimeTypeHelper.isAtom(contentType.toString()))
+            return new EmptyResponseContext(415);
+          Entry entry = getEntryFromRequest(request);
+          if (entry != null) {
+            if (!entry.getId().equals(orig_entry.getId()))
+              return new EmptyResponseContext(409);
+            if (!ProviderHelper.isValidEntry(entry))
+              return new EmptyResponseContext(400);
+            updateEntry(
+              entryObj, 
+              entry.getTitle(), 
+              new Date(), 
+              entry.getAuthors(), 
+              entry.getSummary(), 
+              entry.getContentElement(), 
+              request);
+            return ProviderHelper.nocontent("No Content");
+          } else {
+            return ProviderHelper.badrequest(request, "Bad Request");
+          }
+        } else {
+          return ProviderHelper.notfound(request, "Not Found");
+        }
+      } catch (ResponseContextException e) {
+        return createErrorResponse(e);
+      } catch (ParseException pe) {
+        return ProviderHelper.notsupported(request, "Media Type Not Supported");
+      } catch (ClassCastException cce) {
+        return ProviderHelper.notsupported(request, "Not Supported");
+    } catch (Exception e) {
+      log.warn(e.getMessage(), e);
+      return ProviderHelper.badrequest(request, "Bad Request");
+    }    
+  }
+
+  public abstract void updateEntry(
+    T entry, 
+    String title, 
+    Date updated, 
+    List<Person> authors, 
+    String summary, 
+    Content content, 
+    RequestContext request) 
+      throws ResponseContextException;
+
+  protected void addContent(
+    Entry e, 
+    T doc, 
+    RequestContext request) 
+      throws ResponseContextException {
+    Object content = getContent(doc, request);
+    if (content instanceof Content)
+      e.setContentElement((Content)content);
+    else if (content instanceof String)
+      e.setContent((String)content);
+  }
+
+  protected void addEntryDetails(
+    RequestContext request, 
+    Entry e, 
+    IRI entryBaseIri, 
+    T entryObj) 
+      throws ResponseContextException {
+    IRI entryIri = entryBaseIri.resolve(getName(entryObj));
+    e.addLink(entryIri.toString(), "edit");
+    e.setId(getId(entryObj));
+    e.setTitle(getTitle(entryObj));
+    e.setUpdated(getUpdated(entryObj));
+    List<Person> authors = getAuthors(entryObj, request);
+    if (authors != null) {
+      for (Person a : authors)
+        e.addAuthor(a);
+    }    
+    Text t = getSummary(entryObj, request);
+    if (t != null)
+      e.setSummaryElement(t);
+  }
+
+  public Text getSummary(
+    T entry, 
+    RequestContext request) 
+      throws ResponseContextException {
+    return null;
+  }
+
+  protected void addMediaContent(
+    IRI entryBaseIri, 
+    Entry entry, 
+    T doc) 
+      throws ResponseContextException {
+    String name = getMediaName(doc);
+    IRI mediaIri = getMediaIRI(entryBaseIri, name);
+    mediaIri = entryBaseIri.resolve(mediaIri);
+    entry.setContent(mediaIri, getContentType(doc));
+    entry.addLink(mediaIri.toString(), "edit-media");
+  }
+
+  public abstract T createEntry(
+    String title, 
+    IRI id, 
+    String summary, 
+    Date updated, 
+    List<Person> authors, 
+    Content content, 
+    RequestContext request) 
+      throws ResponseContextException;
+  
+  public T createMediaEntry(
+    MimeType mimeType, 
+    String slug, 
+    InputStream inputStream, 
+    RequestContext request) 
+      throws ResponseContextException {
+    throw new UnsupportedOperationException();
+  }
+
+  public ResponseContext postMedia(RequestContext request) {
+    try {
+      T doc = createMediaEntry(
+        request.getContentType(), 
+        request.getSlug(), 
+        request.getInputStream(), 
+        request);
+      IRI baseIri = ProviderHelper.resolveBase(request);
+      IRI entryIri = getEntryBaseFromFeedIRI(baseIri);
+      Entry entry = request.getAbdera().getFactory().newEntry();
+      addEntryDetails(request, entry, entryIri, doc);
+      addMediaContent(entryIri, entry, doc);
+      return buildCreateMediaEntryResponse(entryIri, entry);
+    } catch (IOException e) {
+      return ProviderHelper.servererror(request, "Server Error", e);
+    } catch (ResponseContextException e) {
+      return createErrorResponse(e);
+    }
+  }
+  
+  public ResponseContext postEntry(
+    RequestContext request) {
+      try {
+        Entry entry = getEntryFromRequest(request);
+        if (entry != null) {
+          if (!ProviderHelper.isValidEntry(entry))
+            return ProviderHelper.badrequest(request, "Bad Request");
+          entry.setUpdated(new Date());    
+          try {
+            T entryObj = 
+              createEntry(
+                entry.getTitle(),
+                entry.getId(),
+                entry.getSummary(),
+                entry.getUpdated(),
+                entry.getAuthors(),
+                entry.getContentElement(), 
+                request);
+            entry.getIdElement().setValue(getId(entryObj));
+            IRI entryBaseUri = 
+              getEntryBaseFromFeedIRI(
+                ProviderHelper.resolveBase(request));
+            IRI entryIri = entryBaseUri.resolve(getName(entryObj));
+            entry.addLink(entryIri.toString(), "edit");
+            return buildCreateEntryResponse(entryIri, entry);
+          } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+          }
+        } else {
+          return ProviderHelper.badrequest(request, "Bad Request");
+        }
+      } catch (IOException e) {
+        return ProviderHelper.servererror(request, "Server Error", e);
+      }
+  }
+
+  protected IRI getEntryBaseFromFeedIRI(
+    IRI baseIri) {
+      return new IRI(baseIri.toString() + "/");
+  }
+
+  protected Entry getEntryFromCollectionProvider(
+    IRI feedIri, 
+    RequestContext request) 
+      throws ResponseContextException {
+    String id = getEntryID(request);
+    T entryObj = getEntry(id, request);
+    if (entryObj == null) return null;
+    return getEntryFromCollectionProvider(entryObj, feedIri, request);
+  }
+
+  Entry getEntryFromCollectionProvider(
+    T entryObj, 
+    IRI feedIri, 
+    RequestContext request)
+      throws ResponseContextException {
+    Abdera abdera = request.getAbdera();
+    Factory factory = abdera.getFactory();
+    Entry entry = factory.newEntry();
+    return buildEntry(entryObj, entry, feedIri, request);
+  }
+
+  private Entry buildEntry(
+    T entryObj, 
+    Entry entry, 
+    IRI feedIri, 
+    RequestContext request)
+      throws ResponseContextException {
+    addEntryDetails(request, entry, feedIri, entryObj);
+    if (isMediaEntry(entryObj))
+      addMediaContent(feedIri, entry, entryObj);
+    else
+      addContent(entry, entryObj, request);
+    return entry;
+  }
+  
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractNamedCollectionAdapter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractNamedCollectionAdapter.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractNamedCollectionAdapter.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/AbstractNamedCollectionAdapter.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,210 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.provider.ext;
+
+import java.io.IOException;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.i18n.text.UrlEncoding;
+import org.apache.abdera.model.Base;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.parser.Parser;
+import org.apache.abdera.protocol.server.ProviderHelper;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.Transactional;
+import org.apache.abdera.protocol.server.impl.AbstractResponseContext;
+import org.apache.abdera.protocol.server.impl.BaseResponseContext;
+import org.apache.abdera.protocol.server.impl.EmptyResponseContext;
+import org.apache.abdera.protocol.server.impl.ResponseContextException;
+import org.apache.abdera.util.EntityTag;
+import org.apache.abdera.util.MimeTypeHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public abstract class AbstractNamedCollectionAdapter 
+  implements NamedCollectionAdapter, 
+             Transactional {
+  
+  private final static Log log = LogFactory.getLog(AbstractNamedCollectionAdapter.class);
+  
+  private static final int DEFAULT_PAGE_SIZE = 10;
+  private final int defaultpagesize;
+  private String baseMediaIri = "media/";
+  
+  protected AbstractNamedCollectionAdapter() {
+    this(DEFAULT_PAGE_SIZE);
+  }
+  
+  protected AbstractNamedCollectionAdapter(
+    int defaultpagesize) {
+      this.defaultpagesize = defaultpagesize;
+  }
+  
+  protected int getDefaultPageSize() {
+    return defaultpagesize;
+  }
+  
+  public abstract String getAuthor();
+  
+  public String getBaseMediaIri() {
+    return baseMediaIri;
+  }
+  
+  public abstract String getId(RequestContext request);
+  
+  public abstract String getTitle(RequestContext request);
+
+  public void setBaseMediaIri(String baseMediaIri) {
+    this.baseMediaIri = baseMediaIri;
+  }
+
+  protected ResponseContext buildCreateEntryResponse(
+    IRI entryIri, 
+    Entry entry) {
+      BaseResponseContext<Entry> rc = new BaseResponseContext<Entry>(entry);
+      rc.setLocation(entryIri.resolve(entry.getEditLinkResolvedHref()).toString());
+      rc.setContentLocation(rc.getLocation().toString());
+      rc.setEntityTag(calculateEntityTag(entry));
+      rc.setStatus(201);
+      return rc;
+  }
+
+  protected ResponseContext buildCreateMediaEntryResponse(
+    IRI entryIri, 
+    Entry entry) {
+      return buildCreateEntryResponse(entryIri, entry);
+  }
+
+  protected ResponseContext buildGetEntryResponse(
+    RequestContext request, 
+    Entry entry) {
+      Feed feed = createFeedBase(request);
+      entry.setSource(feed.getAsSource());
+      Document<Entry> entry_doc = entry.getDocument();
+      AbstractResponseContext rc = new BaseResponseContext<Document<Entry>>(entry_doc);
+      rc.setEntityTag(calculateEntityTag(entry));
+      return rc;
+  }
+
+  protected ResponseContext buildGetFeedResponse(
+    Feed feed) {
+      Document<Feed> document = feed.getDocument();
+      AbstractResponseContext rc = new BaseResponseContext<Document<Feed>>(document);
+      rc.setEntityTag(calculateEntityTag(document.getRoot()));
+      return rc;
+  }
+  
+  protected EntityTag calculateEntityTag(
+    Base base) {
+      String id = null;
+      String modified = null;
+      if (base instanceof Entry) {
+        id = ((Entry)base).getId().toString();
+        modified = ((Entry)base).getUpdatedElement().getText();
+      } else if (base instanceof Feed) {
+        id = ((Feed)base).getId().toString();
+        modified = ((Feed)base).getUpdatedElement().getText();
+      }
+      return EntityTag.generate(id, modified);
+  }
+
+  /**
+   * Create a ResponseContext (or take it from the Exception) for an
+   * exception that occurred in the application.
+   * @param e
+   * @return
+   */
+  protected ResponseContext createErrorResponse(ResponseContextException e) {
+    if (log.isInfoEnabled()) {
+      log.info("A ResponseException was thrown.", e);
+    } else if (e.getResponseContext() instanceof EmptyResponseContext 
+      && ((EmptyResponseContext) e.getResponseContext()).getStatus() >= 500) {
+      log.warn("A ResponseException was thrown.", e);
+    }
+    
+    return e.getResponseContext();
+  }
+  
+  protected Feed createFeedBase(RequestContext request) {
+    Factory factory = request.getAbdera().getFactory();
+    Feed feed = factory.newFeed();
+    try {
+      feed.setId(getId(request));
+      feed.setTitle(getTitle(request));
+      feed.addLink("");
+      feed.addLink("", "self");
+      feed.addAuthor(getAuthor());
+    } catch (Exception e) {
+    }
+    return feed;
+  }
+
+  @SuppressWarnings("unchecked")
+  protected Entry getEntryFromRequest(RequestContext request) throws IOException {
+    Abdera abdera = request.getAbdera();
+    Parser parser = abdera.getParser();
+
+    Document<Entry> entry_doc = (Document<Entry>)request.getDocument(parser).clone();
+    if (entry_doc == null) {
+      return null;
+    }
+    return entry_doc.getRoot();
+  }
+
+  protected String getEntryID(RequestContext request) {
+    String path = request.getTargetPath();
+    int q = path.indexOf("?");
+    if (q != -1) {
+      path = path.substring(0, q);
+    }
+    String[] segments = path.split("/");
+    String id = segments[segments.length - 1];
+    return UrlEncoding.decode(id);
+  }
+
+
+  protected IRI getMediaIRI(IRI entryBaseIri, String name) {
+    return entryBaseIri.resolve(getBaseMediaIri()).resolve(name);
+  }
+
+  protected boolean isMediaType(MimeType contentType) {
+    String ctype = (contentType != null) ? contentType.toString() : null;
+    return ctype != null && !MimeTypeHelper.isAtom(ctype) /*&& !MimeTypeHelper.isXml(ctype)*/;
+  }
+  
+  public ResponseContext extensionRequest(RequestContext request) {
+    return ProviderHelper.notallowed(
+      request, 
+      "Method Not Allowed", 
+      ProviderHelper.getDefaultMethods(request));
+  }
+  
+  public void compensate(Throwable t) {}
+
+  public void end() {}
+
+  public void start() {}
+  
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedProvider.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedProvider.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedProvider.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,122 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.provider.ext;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.i18n.text.UrlEncoding;
+import org.apache.abdera.i18n.text.CharUtils.Profile;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.WorkspaceManager;
+import org.apache.abdera.protocol.server.impl.AbstractProvider;
+import org.apache.abdera.protocol.server.impl.AbstractResponseContext;
+import org.apache.abdera.protocol.server.impl.StreamWriterResponseContext;
+import org.apache.abdera.util.Constants;
+import org.apache.abdera.writer.StreamWriter;
+
+/**
+ * Represents an Atom service which is backed by various workspaces and CollectionProviders.
+ * This class can be extended to provide a dynamic list of workspaces or ServiceProvider can
+ * be used to use a static list.
+ * 
+ */
+public abstract class ExtendedProvider 
+  extends AbstractProvider {
+
+    public static final String COLLECTION_ADAPTER_ATTRIBUTE = "collectionAdapter";
+    public static final String URI_PARAMETER_ATTRIBUTE_PREFIX = "uriParameter";
+    
+    private final ExtendedWorkspaceManager ewm;
+    
+    protected ExtendedProvider() {
+      this.ewm = initWorkspaceManager();
+    }
+    
+    protected abstract ExtendedWorkspaceManager initWorkspaceManager();
+
+    public ResponseContext getServiceDocument(RequestContext request) {
+      Abdera abdera = request.getAbdera();
+      AbstractResponseContext rc = getServicesDocument(abdera, request);
+      rc.setStatus(200);
+      return rc;
+    }
+
+    private String getEncoding(RequestContext request) {
+      return "utf-8";
+    }
+
+    private AbstractResponseContext getServicesDocument(
+      final Abdera abdera, 
+      final RequestContext request) {
+      
+      final String enc = getEncoding(request);
+      
+      StreamWriterResponseContext rc = 
+        new StreamWriterResponseContext(abdera) {
+
+        protected void writeTo(StreamWriter sw) throws IOException {
+          sw.startDocument().startService();
+  
+          for (WorkspaceInfo wi : ewm.getWorkspaceInfo()) {
+            sw.startWorkspace().writeTitle(wi.getName());
+            Set<Map.Entry<String, NamedCollectionAdapter>> entrySet = 
+              (Set<Map.Entry<String, NamedCollectionAdapter>>)
+                (wi.getCollectionAdapters().entrySet());
+  
+            for (Map.Entry<String, NamedCollectionAdapter> entry : entrySet) {
+              NamedCollectionAdapter cp = entry.getValue();
+  
+              String href;
+              try {
+                href = UrlEncoding.encode(entry.getKey(), enc, Profile.PATH.filter());
+              } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+              }
+  
+              try {
+                sw.startCollection(href)
+                  .writeTitle(cp.getName())
+                  .writeAcceptsEntry()
+                  .endCollection();
+              } catch (RuntimeException e) {
+              }
+            }
+  
+            sw.endWorkspace();
+          }
+  
+          sw.endService().endDocument();
+  
+        }
+      };
+      rc.setStatus(200);
+      rc.setContentType(Constants.APP_MEDIA_TYPE);
+      return rc;
+    }
+    
+    protected WorkspaceManager getWorkspaceManager(
+      RequestContext request) {
+        return ewm;
+    }
+
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedWorkspaceManager.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedWorkspaceManager.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedWorkspaceManager.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/ExtendedWorkspaceManager.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,54 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.provider.ext;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.abdera.protocol.server.CollectionAdapter;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.WorkspaceManager;
+import org.apache.abdera.protocol.server.impl.AbstractWorkspaceManager;
+
+public class ExtendedWorkspaceManager
+  extends AbstractWorkspaceManager
+  implements WorkspaceManager {
+
+  private List<WorkspaceInfo> workspaces;
+
+  public CollectionAdapter getCollectionAdapter(RequestContext request) {
+    for (WorkspaceInfo wi : workspaces) {
+      CollectionAdapter ca = wi.getCollectionAdapter(request);
+      if (ca != null) return ca;
+    }
+    return null;
+  }
+
+  public WorkspaceInfo[] getWorkspaceInfo() {
+    return workspaces.toArray(new WorkspaceInfo[workspaces.size()]);
+  }
+
+  public void setWorkspaceInfo(List<WorkspaceInfo> workspaces) {
+    this.workspaces = workspaces;
+  }
+  
+  public void setWorkspaceInfo(WorkspaceInfo... workspaces) {
+    setWorkspaceInfo(Arrays.asList(workspaces));
+  }
+
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/NamedCollectionAdapter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/NamedCollectionAdapter.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/NamedCollectionAdapter.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/NamedCollectionAdapter.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,27 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.provider.ext;
+
+import org.apache.abdera.protocol.server.CollectionAdapter;
+
+public interface NamedCollectionAdapter 
+  extends CollectionAdapter {
+  
+  String getName();
+  
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/SimpleWorkspaceInfo.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/SimpleWorkspaceInfo.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/SimpleWorkspaceInfo.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/SimpleWorkspaceInfo.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,60 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.provider.ext;
+
+import java.util.Map;
+
+import org.apache.abdera.protocol.server.CollectionAdapter;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.Target;
+import org.apache.abdera.protocol.server.impl.AbstractWorkspaceManager;
+
+public class SimpleWorkspaceInfo
+  extends AbstractWorkspaceManager
+  implements WorkspaceInfo {
+
+  private Map<String, NamedCollectionAdapter> collectionAdapters;
+  private String name;
+
+  public String getName() {
+      return name;
+  }
+
+  public void setName(String name) {
+      this.name = name;
+  }
+  
+  public CollectionAdapter getCollectionAdapter(RequestContext request) {
+    Target target = request.getTarget();
+    String name = target.getIdentity();
+    for (Map.Entry<String, NamedCollectionAdapter> entry : collectionAdapters.entrySet()) {
+      if (name.startsWith(entry.getKey()))
+        return entry.getValue();
+    }
+    return null;
+  }
+
+  public Map<String, NamedCollectionAdapter> getCollectionAdapters() {
+    return collectionAdapters;
+  }
+
+  public void setCollectionAdapters(Map<String, NamedCollectionAdapter> contentAdapters) {
+    this.collectionAdapters = contentAdapters;
+  }
+  
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/WorkspaceInfo.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/WorkspaceInfo.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/WorkspaceInfo.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/provider/ext/WorkspaceInfo.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,35 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.provider.ext;
+
+import java.util.Map;
+
+import org.apache.abdera.protocol.server.WorkspaceManager;
+
+public interface WorkspaceInfo 
+  extends WorkspaceManager {
+
+  String getName();
+  
+  void setName(String name);
+  
+  Map<String,NamedCollectionAdapter> getCollectionAdapters();
+  
+  void setCollectionAdapters(Map<String,NamedCollectionAdapter> adapters);
+  
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaFilter.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaFilter.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaFilter.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,61 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.servlet;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.parser.Parser;
+import org.apache.abdera.protocol.server.ServiceManager;
+
+public abstract class AbderaFilter 
+  extends AbstractFilter {
+
+  protected final Abdera abdera;
+  
+  protected AbderaFilter() {
+    this.abdera = ServiceManager.getAbdera();
+  }
+  
+  protected Abdera getAbdera() {
+    return abdera;
+  }
+  
+  protected Document<Element> getDocument(
+    BufferingResponseWrapper wrapper) 
+      throws IOException {
+    Reader rdr = wrapper.getReader();
+    Parser parser = abdera.getParser();
+    try {
+      if (rdr != null) return parser.parse(rdr);
+    } catch (Exception e) {}
+    return null;
+  }
+
+  protected Document<Element> getDocument(
+    BufferedRequestWrapper wrapper)
+      throws IOException {
+    try {
+      return abdera.getParser().parse(wrapper.getReader());
+    } catch (Exception e) {}
+    return null;
+  }
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaServlet.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaServlet.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaServlet.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbderaServlet.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,179 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.servlet;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.activation.MimeType;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.protocol.ItemManager;
+import org.apache.abdera.protocol.error.Error;
+import org.apache.abdera.protocol.server.Provider;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.ServiceContext;
+import org.apache.abdera.protocol.server.ServiceManager;
+import org.apache.abdera.writer.StreamWriter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Simple Atompub servlet.
+ */
+@SuppressWarnings("unchecked") 
+public class AbderaServlet 
+  extends HttpServlet {
+
+  private static final long serialVersionUID = 2393643907128535158L;
+  
+  private final static Log log = LogFactory.getLog(AbderaServlet.class);
+  
+  protected ServiceManager manager;
+  protected ServiceContext context;
+  
+  public void init() throws ServletException {
+    log.debug("Initialing Abdera Servlet");
+    manager = createServiceManager();
+    context = createServiceContext();
+    if (context == null) {
+      log.debug("Cannot create service context");
+      throw new ServletException("Cannot create service context");
+    }
+  }
+
+  public Abdera getAbdera() {
+     return ServiceManager.getAbdera();
+  }
+  
+  public ServiceContext getServiceContext() {
+    return context;
+  }
+
+  public ServiceManager getServiceManager() {
+    return manager;
+  }
+
+  protected ServiceContext createServiceContext() {
+    return manager.newServiceContext(
+        getProperties(
+          getServletConfig()));
+  }
+
+  protected ServiceManager createServiceManager() {
+    return ServiceManager.getInstance();
+  }
+  
+  @Override
+  protected void service(
+    HttpServletRequest request, 
+    HttpServletResponse response) 
+      throws ServletException, IOException {
+    RequestContext reqcontext = new ServletRequestContext(context, request);
+    ItemManager<Provider> manager = context.getProviderManager();
+    Provider provider = manager.get(reqcontext);
+    log.debug("Provider - " + provider);
+    try {
+      output(
+        request,
+        response,
+        provider.process(
+          reqcontext));
+    } catch (Throwable t) {
+      error("Error servicing request", t, response);
+      return;
+    } finally {
+      log.debug("Releasing provider - " + provider);
+      manager.release(provider);
+    }
+    log.debug("Request complete");
+  }
+  
+  private void output(
+    HttpServletRequest request, 
+    HttpServletResponse response, 
+    ResponseContext context)
+      throws IOException {
+    if (context != null) {
+      response.setStatus(context.getStatus());
+      long cl = context.getContentLength();
+      String cc = context.getCacheControl();
+      if (cl > -1) response.setHeader("Content-Length", Long.toString(cl));
+      if (cc != null && cc.length() > 0) response.setHeader("Cache-Control",cc);
+      try {
+        MimeType ct = context.getContentType();
+        if (ct != null) response.setContentType(ct.toString());
+      } catch (Exception e) {}
+      String[] names = context.getHeaderNames();
+      for (String name : names) {
+        Object[] headers = context.getHeaders(name);
+        for (Object value : headers) {          
+          if (value instanceof Date)
+            response.setDateHeader(name, ((Date)value).getTime());
+          else
+            response.setHeader(name, value.toString());
+        }
+      }
+      
+      if (!request.getMethod().equals("HEAD") && context.hasEntity()) {
+        context.writeTo(response.getOutputStream());
+      }  
+    } else {
+      error("Internal Server Error", null, response);
+    }
+  }
+  
+  private void error(
+    String message, 
+    Throwable t, 
+    HttpServletResponse response) 
+      throws IOException {
+    if (response.isCommitted()) response.reset();
+    if (t != null) log.error(message, t);
+    else log.error(message);
+    response.setStatus(500);
+    StreamWriter sw = 
+      getAbdera().newStreamWriter()
+                 .setOutputStream(
+                   response.getOutputStream(),
+                   "UTF-8");
+    Error.create(sw, 500, message,t);
+    sw.close();
+  }
+  
+  protected Map<String,String> getProperties(ServletConfig config) {
+    Map<String,String> properties = new HashMap<String,String>();
+    Enumeration<String> e = config.getInitParameterNames();
+    while(e.hasMoreElements()) {
+      String key = (String) e.nextElement();
+      String val = config.getInitParameter(key);
+      properties.put(key, val);
+    }
+    return properties;
+  }
+  
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbstractFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbstractFilter.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbstractFilter.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/AbstractFilter.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,302 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.servlet;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.zip.DeflaterOutputStream;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+import org.apache.abdera.i18n.text.io.RewindableInputStream;
+import org.apache.abdera.util.CompressionUtil;
+import org.apache.abdera.util.CompressionUtil.CompressionCodec;
+
+/**
+ * Utility class that serves as the basis for a variety of Filter implementations
+ */
+public abstract class AbstractFilter 
+  implements Filter {
+
+  private FilterConfig config;
+  
+  public void destroy() {
+  }
+
+  public void init(FilterConfig config) throws ServletException {
+    this.config = config;
+  }
+
+  protected FilterConfig getConfig() {
+    return config;
+  }
+   
+  /**
+   * A HttpServletResponseWrapper implementation that applies GZip or Deflate
+   * compression to response output.
+   */
+  public static class CompressingResponseWrapper 
+    extends HttpServletResponseWrapper {
+
+    ServletOutputStream out = null;
+    PrintWriter output = null;
+    
+    public CompressingResponseWrapper(
+      HttpServletResponse response, 
+      CompressionCodec codec) 
+        throws IOException {
+      super(response);
+      out = new CompressingServletOutputStream(
+        codec, response.getOutputStream());
+    }
+    
+    @Override
+    public PrintWriter getWriter() throws IOException {
+      if (output == null)
+        output = new PrintWriter(
+          new OutputStreamWriter(
+            getOutputStream(), 
+            this.getCharacterEncoding()));
+      return output;
+    }
+  
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+      return out;
+    }
+    
+    public void finish() throws IOException {
+      out.flush();
+    }
+    
+    public static boolean canHandle(String enc) {
+      return enc.equalsIgnoreCase("gzip") ||
+             enc.equalsIgnoreCase("compress");
+    }
+    
+  }
+  
+  /**
+   * A ServletOutputStream implementation that handles the GZip and Deflate
+   * compression for the CompressingResponseWrapper
+   */
+  public static class CompressingServletOutputStream 
+    extends ServletOutputStream {
+
+    private OutputStream dout;
+    
+    public CompressingServletOutputStream(CompressionCodec codec, ServletOutputStream out) {
+      try {
+        dout = CompressionUtil.getEncodedOutputStream(out,codec);        
+      } catch (IOException e) {}
+    }
+    
+    public CompressingServletOutputStream(DeflaterOutputStream dout) {
+      this.dout = dout;
+    }
+    
+    @Override
+    public void write(int b) throws IOException {
+      dout.write(b);
+    }
+
+    @Override
+    public void write(byte[] b, int off, int len) throws IOException {
+      dout.write(b,off,len);
+    }
+
+    @Override
+    public void write(byte[] b) throws IOException {
+      dout.write(b);
+    }
+
+  }
+  
+  /**
+   * A HttpServletResponseWrapper implementation that buffers the response 
+   * content in memory so that a filter can perform operations on the full
+   * response content (e.g. digitally sign it, encrypt it, etc)
+   */
+  public static class BufferingResponseWrapper 
+    extends HttpServletResponseWrapper {
+  
+    PrintWriter output = null;
+    ServletOutputStream outStream = null;
+  
+    public BufferingResponseWrapper(HttpServletResponse response) {
+      super(response);
+    }
+  
+    @Override
+    public PrintWriter getWriter() throws IOException {
+      if (output == null)
+        output = new PrintWriter(
+          new OutputStreamWriter(
+            getOutputStream(), 
+            this.getCharacterEncoding()));
+      return output;
+    }
+  
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+      if (outStream == null)
+        outStream = new BufferingServletOutputStream();
+      return outStream;
+    }
+  
+    public Reader getReader() throws IOException {
+      return new InputStreamReader(
+        getInputStream(), 
+        this.getCharacterEncoding());
+    }
+  
+    public InputStream getInputStream() throws IOException {
+      BufferingServletOutputStream out = 
+        (BufferingServletOutputStream)getOutputStream();
+      return new ByteArrayInputStream(
+        out.getBuffer().toByteArray());
+    }
+  }
+
+  /**
+   * Implementation of ServletOutputStream that handles the in-memory 
+   * buffering of the response content
+   */
+  public static class BufferingServletOutputStream 
+    extends ServletOutputStream {
+
+    ByteArrayOutputStream out = null;
+  
+    public BufferingServletOutputStream() {
+      this.out = new ByteArrayOutputStream();
+    }
+    
+    public ByteArrayOutputStream getBuffer() {
+      return out;
+    }
+  
+    public void write(int b) throws IOException {
+      out.write(b);
+    }
+  
+    public void write(byte[] b) throws IOException {
+      out.write(b);
+    }
+  
+    public void write(byte[] b, int off, int len) throws IOException {
+      out.write(b, off, len);
+    }
+
+    @Override
+    public void close() throws IOException {
+      out.close();
+      super.close();
+    }
+
+    @Override
+    public void flush() throws IOException {
+      out.flush();
+      super.flush();
+    }
+    
+  }
+
+  /**
+   * Implementation of HttpServletRequestWrapper that allows a Filter 
+   * to perform operations on the full content of a request while still
+   * allowing downstream operations to be performed on the content.
+   * (e.g. decrypting requests, verifying digital signatures, etc) 
+   */
+  public static class BufferedRequestWrapper 
+    extends HttpServletRequestWrapper {
+
+    private BufferedServletInputStream bin;
+    private RewindableInputStream rin;
+    private BufferedReader rdr;
+
+    public BufferedRequestWrapper(HttpServletRequest request) {
+      super(request);
+    }
+
+    public void setInputStream(InputStream in) {
+      bin = new BufferedServletInputStream(in);
+    }
+    
+    @Override
+    public ServletInputStream getInputStream() throws IOException {
+      if (rdr != null) throw new IllegalStateException();
+      if (bin == null) {
+        rin = new RewindableInputStream(super.getInputStream());
+        bin = new BufferedServletInputStream(rin);
+      }
+      return bin;
+    }
+
+    @Override
+    public BufferedReader getReader() throws IOException {
+      if (rdr == null) {
+        String charset = this.getCharacterEncoding();
+        rdr = (charset == null) ?
+          new BufferedReader(new InputStreamReader(getInputStream())) :
+          new BufferedReader(new InputStreamReader(getInputStream(),charset));
+      }
+      return rdr;
+    }
+    
+    public void reset() throws IOException {
+      if (bin != null) rin.rewind();
+      rdr = null;
+    }
+    }
+    
+    public static class BufferedServletInputStream 
+    extends ServletInputStream {
+    
+    private InputStream in;
+    
+    public BufferedServletInputStream(InputStream in) {
+      this.in = in;
+      try {
+        in.mark(in.available());
+      } catch (Exception e) {}
+    }
+    
+    @Override
+    public int read() throws IOException {
+      return in.read();
+    }
+
+  }
+
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/CompressionFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/CompressionFilter.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/CompressionFilter.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/CompressionFilter.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,70 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.abdera.protocol.server.ProviderHelper;
+import org.apache.abdera.util.CompressionUtil;
+import org.apache.abdera.util.CompressionUtil.CompressionCodec;
+
+/**
+ * A filter that applies either GZip or Compress encoding on a response
+ * depending on the value of the Accept-Encoding request header.
+ * 
+ * Note: This is currently untested
+ */
+public class CompressionFilter
+  extends AbstractFilter
+  implements Filter {
+
+  public void doFilter(
+    ServletRequest request, 
+    ServletResponse response,
+    FilterChain chain) 
+      throws IOException, ServletException {
+    
+    HttpServletRequest req = (HttpServletRequest) request;
+    String encoding = req.getHeader("Accept-Encoding");
+    String[] encodings = 
+      encoding != null ? 
+        ProviderHelper.orderByQ(encoding) : 
+        new String[0];
+    for (String enc : encodings) {
+      if (CompressingResponseWrapper.canHandle(enc)) {
+        CompressionCodec codec = CompressionUtil.getCodec(enc);
+        CompressingResponseWrapper resp = 
+          new CompressingResponseWrapper(
+            (HttpServletResponse) response, codec);
+        chain.doFilter(request, response);
+        resp.finish();
+        return;
+      }
+    }
+    chain.doFilter(request, response);
+  }
+
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/MethodOverrideFilter.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/MethodOverrideFilter.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/MethodOverrideFilter.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/MethodOverrideFilter.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,96 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.servlet;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ * HTTP Servlet Filter that implements support for Google's X-HTTP-Method-Override
+ * header to perform "POST Tunneling" of various HTTP operations 
+ */
+public class MethodOverrideFilter 
+  extends AbstractFilter
+  implements Filter {
+
+  public static final String METHODS = "org.apache.abdera.protocol.server.servlet.Overrides";
+  
+  private String[] METHODS_TO_OVERRIDE;
+  
+  public void doFilter(
+    ServletRequest request, 
+    ServletResponse response,
+    FilterChain chain) 
+      throws IOException, 
+             ServletException {
+    chain.doFilter(
+      new MethodOverrideRequestWrapper(
+        (HttpServletRequest) request), 
+        response);
+    
+    HttpServletResponse hresponse = (HttpServletResponse) response;
+    hresponse.setHeader("Cache-Control", "no-cache");
+  }
+
+  @Override
+  public void init(FilterConfig config) throws ServletException {
+    String param = config.getInitParameter(METHODS);
+    if (param != null) {
+      String[] methods = param.split("\\s*,\\s*");
+      Arrays.sort(methods);
+      this.METHODS_TO_OVERRIDE = methods;
+    }
+  }
+
+  private class MethodOverrideRequestWrapper 
+    extends HttpServletRequestWrapper {
+
+    private final String method;
+    
+    public MethodOverrideRequestWrapper(HttpServletRequest request) {
+      super(request);
+      String method = super.getMethod();
+      String xheader = getHeader("X-HTTP-Method-Override");
+      if (xheader == null) xheader = getHeader("X-Method-Override");
+      if (xheader != null) xheader = xheader.toUpperCase().trim();
+      if (method.equals("POST") && 
+        xheader != null && 
+        Arrays.binarySearch(METHODS_TO_OVERRIDE,xheader) > -1) {
+          method = xheader;
+      }
+      this.method = method;
+    }
+
+    @Override
+    public String getMethod() {
+      return method;
+    }
+    
+  }
+}

Added: incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/ServletRequestContext.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/ServletRequestContext.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/ServletRequestContext.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/main/java/org/apache/abdera/protocol/server/servlet/ServletRequestContext.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,257 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+
+import javax.security.auth.Subject;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.i18n.text.Localizer;
+import org.apache.abdera.protocol.Resolver;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ServiceContext;
+import org.apache.abdera.protocol.server.Target;
+import org.apache.abdera.protocol.server.impl.AbstractRequestContext;
+
+public class ServletRequestContext 
+  extends AbstractRequestContext
+  implements RequestContext {
+
+  private final HttpServletRequest request;
+  private HttpSession session;
+  
+  public ServletRequestContext(
+    ServiceContext context,
+    HttpServletRequest request) {
+      super(
+        context, 
+        request.getMethod(), 
+        initRequestUri(request),
+        initBaseUri(context,request));
+      this.request = request;
+      this.session = request.getSession(false);
+      
+      Resolver<Subject> subjectResolver = context.getSubjectResolver();
+      principal = request.getUserPrincipal();
+      subject = (subjectResolver != null)? 
+        subjectResolver.resolve(this) : null;
+      
+      Resolver<Target> targetResolver = 
+        context.getTargetResolver(
+          request.getContextPath());
+      target = (targetResolver != null) ? 
+        targetResolver.resolve(this) : null;
+  }
+  
+  public Object getProperty(Property property) {
+    switch (property) {
+      case SESSIONID:         return (session != null) ? session.getId() : null;
+      case SESSIONCREATED:    return (session != null) ? new Date(session.getCreationTime()) : null;
+      case SESSIONACCESSED:   return (session != null) ? new Date(session.getLastAccessedTime()) : null;
+      case SESSIONTIMEOUT:    return (session != null) ? session.getMaxInactiveInterval() : -1;
+      case CHARACTERENCODING: return request.getCharacterEncoding();
+      case LOCALES:           return request.getLocales();
+      case PROTOCOL:          return request.getProtocol();
+      case REMOTEADDRESS:     return request.getRemoteAddr();
+      case REMOTEHOST:        return request.getRemoteHost();
+      case REMOTEUSER:        return request.getRemoteUser();
+      case SCHEME:            return request.getScheme();
+      case PRINCIPAL:         return request.getUserPrincipal();
+      case AUTHTYPE:          return request.getAuthType();
+      case CONTENTLENGTH:     return request.getContentLength();
+      case CONTENTTYPE:       return request.getContentType();
+      case CONTEXTPATH:       return request.getContextPath();
+      case LOCALADDR:         return request.getLocalAddr();
+      case LOCALNAME:         return request.getLocalName();
+      case SERVERNAME:        return request.getServerName();
+      case SERVERPORT:        return request.getServerPort();
+      default:
+        throw new UnsupportedOperationException(Localizer.get("PROPERTY.NOT.SUPPORTED")); 
+    }
+  }
+  
+  public Reader getReader() throws IOException {
+    return request.getReader();
+  }
+  
+  public InputStream getInputStream() throws IOException {
+    return request.getInputStream();
+  }
+  
+  public HttpServletRequest getRequest() {
+    return request;
+  }
+  
+  public synchronized HttpSession getSession() {
+    return getSession(false);
+  }
+  
+  public synchronized HttpSession getSession(boolean create) {
+    if (session == null) session = request.getSession(create);
+    return session;
+  }
+  
+  public RequestContext setAttribute(Scope scope, String name, Object value) {
+    switch(scope) {
+      case REQUEST: request.setAttribute(name, value); break;
+      case SESSION: getSession(true).setAttribute(name, value); break;
+    }
+    return this;
+  }
+  
+  public Object getAttribute(Scope scope, String name) {
+    switch(scope) {
+      case REQUEST: return request.getAttribute(name);
+      case SESSION: return (session != null) ? session.getAttribute(name) : null;
+    }
+    return null;
+  }
+  
+  @SuppressWarnings("unchecked")
+  public String[] getAttributeNames(Scope scope) {
+    switch(scope) {
+      case REQUEST: return enum2array(request.getAttributeNames());
+      case SESSION: return (session != null) ? enum2array(session.getAttributeNames()) : null;
+    }
+    return null;
+  }
+  
+  public String getParameter(String name) {
+    return request.getParameter(name);
+  }
+  
+  @SuppressWarnings("unchecked")
+  public String[] getParameterNames() {
+    return enum2array(request.getParameterNames());
+  }
+  
+  public List<String> getParameters(String name) {
+    String[] values = request.getParameterValues(name);
+    return values != null ? java.util.Arrays.asList(values) : null;
+  }
+  
+  public Date getDateHeader(String name) {
+    long value = request.getDateHeader(name);
+    return value != -1 ? new Date(value) : null;
+  }
+
+  public String getHeader(String name) {
+    return request.getHeader(name);
+  }
+
+  @SuppressWarnings("unchecked")
+  public String[] getHeaderNames() {
+    return enum2array(request.getHeaderNames());
+  }
+
+  @SuppressWarnings("unchecked")
+  public Object[] getHeaders(String name) {
+    Enumeration<Object> e = request.getHeaders(name);
+    List<Object> list = java.util.Collections.list(e);
+    return list.toArray(new String[list.size()]);
+  }
+
+  @SuppressWarnings("unchecked")
+  private static String[] enum2array (Enumeration<String> e) {
+    List<String> list = java.util.Collections.list(e);
+    return list.toArray(new String[list.size()]);
+  }
+  
+  private static String getHost(
+    ServiceContext context, 
+    HttpServletRequest request) {
+      Abdera abdera = context.getAbdera();
+      String host = abdera.getConfiguration().getConfigurationOption(
+        "org.apache.abdera.protocol.server.Host");
+      return (host != null) ? 
+        host : 
+        request.getServerName();
+  }
+  
+  private static int getPort(
+    ServiceContext context, 
+    HttpServletRequest request) {
+    Abdera abdera = context.getAbdera();
+      String port = abdera.getConfiguration().getConfigurationOption(
+        "org.apache.abdera.protocol.server.Port");
+      return (port != null) ? 
+        Integer.parseInt(port) : 
+        request.getServerPort();
+  }
+  
+  private static IRI initBaseUri(
+    ServiceContext context, 
+    HttpServletRequest request) {
+      StringBuilder buffer = 
+        new StringBuilder(
+          (request.isSecure())?
+            "https":"http");
+      buffer.append("://");
+      buffer.append(getHost(context,request));
+      int port = getPort(context,request);
+      if (port != 80) {
+        buffer.append(":");
+        buffer.append(port);
+      }
+      buffer.append(request.getContextPath());
+      // So that .resolve() works appropriately.
+      buffer.append("/");
+      return new IRI(buffer.toString());
+  }
+  
+  private static IRI initRequestUri(HttpServletRequest request) {
+    IRI uri = null;
+    StringBuilder buf = 
+      new StringBuilder(
+        request.getRequestURI());
+    String qs = request.getQueryString();
+    if (qs != null && qs.length() != 0)
+      buf.append("?" + request.getQueryString());
+    uri = new IRI(buf.toString());
+    return uri;
+  }
+
+  public boolean isUserInRole(String role) {
+    return request.isUserInRole(role);
+  }
+
+  public String getContextPath() {
+    return request.getContextPath();
+  }
+  
+  public Locale getPreferredLocale() {
+    return request.getLocale();
+  }
+  
+  @SuppressWarnings("unchecked") 
+  public Locale[] getPreferredLocales() {
+    List<Locale> locales = Collections.list(request.getLocales());
+    return locales.toArray(new Locale[locales.size()]);
+  }
+}

Added: incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/JettyServer.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/JettyServer.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/JettyServer.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/JettyServer.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,61 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.test;
+
+import org.apache.abdera.protocol.server.ServiceContext;
+import org.apache.abdera.protocol.server.ServiceManager;
+import org.apache.abdera.protocol.server.provider.basic.BasicServiceContext;
+import org.apache.abdera.protocol.server.servlet.AbderaServlet;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+
+public class JettyServer {
+  
+  public static final int DEFAULT_PORT = 8080;
+  
+  private final int port;
+  private Server server;
+  
+  public JettyServer() {
+    this(DEFAULT_PORT);
+  }
+  
+  public JettyServer(int port) {
+    this.port = port;
+  }
+  
+  public void start(Class<? extends ServiceContext> _class) throws Exception {
+    server = new Server(port);
+    Context context = new Context(server, "/", Context.SESSIONS);
+    ServletHolder servletHolder = new ServletHolder(new AbderaServlet());
+    servletHolder.setInitParameter(ServiceManager.SERVICE_CONTEXT, _class.getName());
+    context.addServlet(servletHolder, "/*");
+    server.start();
+  }
+  
+  public void stop() throws Exception {
+    server.stop();
+  }
+  
+  public static void main(String... args) throws Exception {
+    JettyServer js = new JettyServer();
+    js.start(BasicServiceContext.class);
+    js.stop();
+  }
+}

Added: incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/basic/BasicTest.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/basic/BasicTest.java?rev=613765&view=auto
==============================================================================
--- incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/basic/BasicTest.java (added)
+++ incubator/abdera/java/branches/server_refactor/src/test/java/org/apache/abdera/protocol/server/test/basic/BasicTest.java Sun Jan 20 21:33:46 2008
@@ -0,0 +1,136 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  The ASF licenses this file to You
+* 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.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+package org.apache.abdera.protocol.server.test.basic;
+
+import java.io.ByteArrayInputStream;
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.protocol.Response.ResponseType;
+import org.apache.abdera.protocol.client.AbderaClient;
+import org.apache.abdera.protocol.client.ClientResponse;
+import org.apache.abdera.protocol.client.RequestOptions;
+import org.apache.abdera.protocol.server.provider.basic.BasicServiceContext;
+import org.apache.abdera.protocol.server.test.JettyServer;
+import org.apache.abdera.util.Constants;
+import org.apache.abdera.util.MimeTypeHelper;
+
+public class BasicTest 
+  extends TestCase {
+
+  private static JettyServer server;
+  private static Abdera abdera = Abdera.getInstance();
+  private static AbderaClient client = new AbderaClient();
+
+  public BasicTest() {
+    try {
+      if (server == null) {
+        server = new JettyServer();
+        server.start(BasicServiceContext.class);
+      }
+    } catch (Exception e) {}
+  }
+  
+  private int count = 5;
+  
+  @Override protected void tearDown() throws Exception {
+    if (--count == 0) server.stop();
+  }
+  
+  public void testGetFeed() {
+    ClientResponse resp = client.get("http://localhost:8080/sample");
+    assertNotNull(resp);
+    assertEquals(resp.getType(),ResponseType.SUCCESS);
+    assertTrue(MimeTypeHelper.isMatch(resp.getContentType().toString(), Constants.ATOM_MEDIA_TYPE));
+    Document<Feed> doc = resp.getDocument();
+    Feed feed = doc.getRoot();
+    assertEquals(feed.getId().toString(), "http://localhost:8080/sample");
+    assertEquals(feed.getTitle(), "title for any sample feed");
+    assertEquals(feed.getAuthor().getName(), "rayc");
+    assertEquals(feed.getEntries().size(), 0);
+    resp.release();
+  }
+  
+  public void testPostEntry() {
+    Entry entry = abdera.newEntry();
+    entry.setId("http://localhost:8080/sample/foo");
+    entry.setTitle("test entry");
+    entry.setContent("Test Content");
+    entry.addLink("http://example.org");
+    entry.setUpdated(new Date());
+    entry.addAuthor("James");
+    ClientResponse resp = client.post("http://localhost:8080/sample", entry);
+    assertNotNull(resp);
+    assertEquals(resp.getType(),ResponseType.SUCCESS);
+    assertEquals(resp.getStatus(), 201);
+    assertEquals(resp.getLocation().toString(), "http://localhost:8080/sample/foo");
+    resp = client.get("http://localhost:8080/sample");
+    Document<Feed> feed_doc = resp.getDocument();
+    Feed feed = feed_doc.getRoot();
+    assertEquals(feed.getEntries().size(),1);
+    resp.release();
+  }
+  
+  public void testPostMedia() {
+    ByteArrayInputStream in = new ByteArrayInputStream(new byte[] {0x01,0x02,0x03,0x04});
+    RequestOptions options = client.getDefaultRequestOptions();
+    options.setContentType("application/octet-stream");
+    ClientResponse resp = client.post("http://localhost:8080/sample", in, options);
+    assertEquals(resp.getType(),ResponseType.CLIENT_ERROR);
+    assertEquals(resp.getStatus(), 415);
+    resp.release();
+  }
+  
+  public void testPutEntry() {
+    ClientResponse resp = client.get("http://localhost:8080/sample/foo");
+    Document<Entry> doc = resp.getDocument();
+    Entry entry = doc.getRoot();
+    entry.setTitle("This is the modified title");
+    resp.release();
+    resp = client.put("http://localhost:8080/sample/foo", entry);
+    assertEquals(resp.getType(), ResponseType.SUCCESS);
+    assertEquals(resp.getStatus(), 200);
+    resp.release();
+    resp = client.get("http://localhost:8080/sample/foo");
+    doc = resp.getDocument();
+    entry = doc.getRoot();
+    assertEquals(entry.getTitle(), "This is the modified title");
+    resp.release();
+    resp = client.get("http://localhost:8080/sample");
+    Document<Feed> feed_doc = resp.getDocument();
+    Feed feed = feed_doc.getRoot();
+    assertEquals(feed.getEntries().size(),1);
+    resp.release();
+  }
+  
+  public void testDeleteEntry() {
+    ClientResponse resp = client.delete("http://localhost:8080/sample/foo");    
+    assertEquals(resp.getType(),ResponseType.SUCCESS);
+    resp.release();
+    resp = client.get("http://localhost:8080/sample");
+    Document<Feed> feed_doc = resp.getDocument();
+    Feed feed = feed_doc.getRoot();
+    assertEquals(feed.getEntries().size(),0);
+    resp.release();
+  }
+}