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();
+ }
+}