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 2007/10/02 23:45:36 UTC
svn commit: r581397 - in /incubator/abdera/java/trunk: server/
server/src/main/java/org/apache/abdera/protocol/server/content/
server/src/main/java/org/apache/abdera/protocol/server/impl/
server/src/test/java/org/apache/abdera/server/ server/src/test/j...
Author: jmsnell
Date: Tue Oct 2 14:45:34 2007
New Revision: 581397
URL: http://svn.apache.org/viewvc?rev=581397&view=rev
Log:
Dan's server module updates. This is still a work in progress
Added:
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractCollectionProvider.java
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractWorkspaceProvider.java
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/CollectionProvider.java
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/SimpleWorkspaceInfo.java
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceInfo.java
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceProvider.java
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/ProviderSupport.java
incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/
incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/
incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/
incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/
incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/ContentProviderTest.java
incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/Customer.java
incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/CustomerContentProvider.java
Modified:
incubator/abdera/java/trunk/server/pom.xml
incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/AbstractProvider.java
incubator/abdera/java/trunk/spring/src/main/resources/META-INF/schemas/abdera-spring.xsd
Modified: incubator/abdera/java/trunk/server/pom.xml
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/pom.xml?rev=581397&r1=581396&r2=581397&view=diff
==============================================================================
--- incubator/abdera/java/trunk/server/pom.xml (original)
+++ incubator/abdera/java/trunk/server/pom.xml Tue Oct 2 14:45:34 2007
@@ -69,5 +69,17 @@
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty</artifactId>
+ <version>6.1.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.abdera</groupId>
+ <artifactId>abdera-client</artifactId>
+ <version>0.3.0-incubating-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Added: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractCollectionProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractCollectionProvider.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractCollectionProvider.java (added)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractCollectionProvider.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,397 @@
+package org.apache.abdera.protocol.server.content;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Date;
+
+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.Base;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.parser.ParseException;
+import org.apache.abdera.parser.Parser;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+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.MediaResponseContext;
+import org.apache.abdera.protocol.server.impl.ProviderSupport;
+import org.apache.abdera.util.EntityTag;
+import org.apache.abdera.util.MimeTypeHelper;
+
+public abstract class AbstractCollectionProvider<T> extends ProviderSupport
+ implements CollectionProvider<T> {
+
+ private String baseMediaIri = "media/";
+
+ public ResponseContext createEntry(RequestContext request) {
+ try {
+ MimeType contentType = request.getContentType();
+ if (isMediaType(contentType))
+ return createMediaEntry(request);
+ else
+ return createNonMediaEntry(request);
+ } catch (ParseException pe) {
+ return new EmptyResponseContext(415);
+ } catch (ClassCastException cce) {
+ return new EmptyResponseContext(415);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return new EmptyResponseContext(500);
+ }
+ }
+
+ protected boolean isMediaType(MimeType contentType) {
+ String ctype = (contentType != null) ? contentType.toString() : null;
+ return ctype != null && !MimeTypeHelper.isAtom(ctype) /*&& !MimeTypeHelper.isXml(ctype)*/;
+ }
+
+ public abstract T createEntry(String title, String summary, Content content);
+
+ public T createMediaEntry(MimeType mimeType, String slug, InputStream inputStream) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ResponseContext deleteEntry(RequestContext request) {
+ String id = getEntryID(request);
+ if (id != null) {
+
+ deleteEntry(id);
+
+ return new EmptyResponseContext(204);
+ } else {
+ // TODO: is this right?
+ return new EmptyResponseContext(404);
+ }
+ }
+
+ public abstract void deleteEntry(String resourceName);
+
+ public abstract String getAuthor();
+
+ public String getBaseMediaIri() {
+ return baseMediaIri;
+ }
+
+ public abstract Object getContent(T entry);
+
+ // GET, POST, PUT, DELETE
+
+ public String getContentType(T entry) {
+ throw new UnsupportedOperationException();
+ }
+
+ public abstract Iterable<T> getEntries();
+
+ public ResponseContext getEntry(RequestContext request, IRI entryBaseIri) {
+ Entry entry = getEntryFromCollectionProvider(entryBaseIri,
+ request);
+ if (entry != null) {
+ Feed feed = createDocumentsFeed(request.getAbdera());
+ entry.setSource(feed.getAsSource());
+ Document<Entry> entry_doc = entry.getDocument();
+ AbstractResponseContext rc = new BaseResponseContext<Document<Entry>>(entry_doc);
+ rc.setEntityTag(calculateEntityTag(entry));
+ return rc;
+ } else {
+ return new EmptyResponseContext(404);
+ }
+ }
+
+ public abstract T getEntry(String resourceName);
+
+ public abstract T getEntryFromId(String id);
+
+
+ public ResponseContext getFeed(RequestContext request) {
+ Abdera abdera = request.getAbdera();
+ Feed feed = createDocumentsFeed(abdera);
+
+ return getFeed(request, feed);
+ }
+
+ public ResponseContext getFeed(RequestContext request, Feed feed) {
+ feed.setUpdated(new Date());
+
+ for (T entryObj : getEntries()) {
+ Entry e = feed.addEntry();
+
+ addEntryDetails(request, e, resolveBase(request), entryObj);
+ addContent(e, entryObj);
+ }
+
+ Document<Feed> document = feed.getDocument();
+ AbstractResponseContext rc = new BaseResponseContext<Document<Feed>>(document);
+ rc.setEntityTag(calculateEntityTag(document.getRoot()));
+ return rc;
+ }
+
+ public abstract String getId();
+ /**
+ * Gets the UUID for the specified entry.
+ * @param entry
+ * @return
+ */
+ public abstract String getId(T entry);
+
+ public ResponseContext getMedia(RequestContext request) {
+ try {
+ String id = getEntryID(request);
+ T entryObj = getEntry(id);
+
+ if (entryObj == null) {
+ return new EmptyResponseContext(404);
+ }
+
+ MediaResponseContext ctx = new MediaResponseContext(getMediaStream(entryObj),
+ getUpdated(entryObj),
+ 200);
+ ctx.setContentType(getContentType(entryObj));
+
+ return ctx;
+ } catch (ParseException pe) {
+ return new EmptyResponseContext(415);
+ } catch (ClassCastException cce) {
+ return new EmptyResponseContext(415);
+ } catch (Exception e) {
+ return new EmptyResponseContext(400);
+ }
+ }
+ public String getMediaName(T entry) {
+ throw new UnsupportedOperationException();
+ }
+
+ public InputStream getMediaStream(T gdoc) {
+ throw new UnsupportedOperationException();
+ }
+
+ public abstract String getName(T entry);
+
+ public abstract String getTitle();
+
+ public abstract String getTitle(T entry);
+
+ public abstract Date getUpdated(T entry);
+
+ public boolean isMediaEntry(T entry) {
+ return false;
+ }
+
+ public void setBaseMediaIri(String baseMediaIri) {
+ this.baseMediaIri = baseMediaIri;
+ }
+
+ public ResponseContext updateEntry(RequestContext request, IRI feedUri) {
+ Abdera abdera = request.getAbdera();
+ Entry orig_entry = getEntryFromCollectionProvider(feedUri, request);
+ if (orig_entry != null) {
+ try {
+ 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 (!isValidEntry(entry))
+ return new EmptyResponseContext(400);
+
+ entry.setUpdated(new Date());
+ // TODO: is this really necessary?
+ // entry.getIdElement().setValue(factory.newUuidUri());
+ entry.addLink(feedUri.resolve(entry.getId().toString()).toString(), "edit");
+
+ // entryObjProvider.updateEntry(entry)
+
+ Feed feed = createDocumentsFeed(abdera);
+ feed.insertEntry(entry);
+ feed.setUpdated(new Date());
+ return new EmptyResponseContext(204);
+ } else {
+ return new EmptyResponseContext(400);
+ }
+ } catch (ParseException pe) {
+ return new EmptyResponseContext(415);
+ } catch (ClassCastException cce) {
+ return new EmptyResponseContext(415);
+ } catch (Exception e) {
+ return new EmptyResponseContext(400);
+ }
+ } else {
+ return new EmptyResponseContext(404);
+ }
+ }
+
+ public abstract T updateEntry(T entry, Content content);
+
+ protected void addContent(Entry e, T doc) {
+ Object content = getContent(doc);
+
+ 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) {
+ IRI entryIri = entryBaseIri.resolve(getName(entryObj));
+ e.addLink(entryIri.toString(), "edit");
+ e.setId(getId(entryObj));
+ e.setTitle(getTitle(entryObj));
+ e.setUpdated(getUpdated(entryObj));
+ }
+
+ protected void addMediaContent(IRI entryBaseIri, Entry entry, T doc) {
+ String name = getMediaName(doc);
+ IRI mediaIri = getMediaIRI(entryBaseIri, name);
+ mediaIri = entryBaseIri.resolve(mediaIri);
+
+ entry.setContent(mediaIri, getContentType(doc));
+ entry.addLink(mediaIri.toString(), "edit-media");
+ }
+
+ 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);
+ }
+ protected Feed createDocumentsFeed(Abdera abdera) {
+ Factory factory = abdera.getFactory();
+ Feed feed = factory.newFeed();
+ try {
+ feed.setId(getId());
+ feed.setTitle(getTitle());
+ feed.addLink("");
+ feed.addLink("", "self");
+ feed.addAuthor(getAuthor());
+ } catch (Exception e) {
+ }
+ return feed;
+ }
+
+ protected ResponseContext createMediaEntry(RequestContext request) {
+ try {
+ T doc = createMediaEntry(request.getContentType(), request.getSlug(), request.getInputStream());
+
+ IRI baseIri = resolveBase(request);
+ IRI entryIri = getEntryBaseFromFeedIRI(baseIri);
+
+ Entry entry = request.getAbdera().getFactory().newEntry();
+
+ addEntryDetails(request, entry, entryIri, doc);
+
+ addMediaContent(entryIri, entry, doc);
+
+ 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;
+ } catch (IOException e) {
+ return new EmptyResponseContext(500);
+ }
+ }
+
+ protected ResponseContext createNonMediaEntry(RequestContext request)
+ throws IOException {
+ Entry entry = getEntryFromRequest(request);
+ if (entry != null) {
+ if (!isValidEntry(entry))
+ return new EmptyResponseContext(400);
+
+ entry.setUpdated(new Date());
+
+ T entryObj = createEntry(entry.getTitle(), entry.getSummary(),
+ entry.getContentElement());
+ entry.getIdElement().setValue(getId(entryObj));
+
+ IRI entryBaseUri = getEntryBaseFromFeedIRI(resolveBase(request));
+
+ IRI entryIri = entryBaseUri.resolve(getName(entryObj));
+ entry.addLink(entryIri.toString(), "edit");
+
+ 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;
+ } else {
+ return new EmptyResponseContext(400);
+ }
+ }
+
+ protected IRI getEntryBaseFromFeedIRI(IRI baseIri) {
+ return new IRI(baseIri + "/");
+ }
+
+ protected Entry getEntryFromCollectionProvider(IRI feedIri, RequestContext request) {
+
+ String id = getEntryID(request);
+ T entryObj = getEntry(id);
+
+ if (entryObj == null) {
+ return null;
+ }
+
+ Abdera abdera = request.getAbdera();
+ Factory factory = abdera.getFactory();
+ Entry entry = factory.newEntry();
+
+ addEntryDetails(request, entry, feedIri, entryObj);
+
+ if (isMediaEntry(entryObj)) {
+ addMediaContent(feedIri, entry, entryObj);
+ } else {
+ addContent(entry, entryObj);
+ }
+
+ return entry;
+ }
+
+ @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.getUri().toString();
+ String[] segments = path.split("/");
+ return segments[segments.length - 1];
+ }
+
+ protected IRI getMediaIRI(IRI entryBaseIri, String name) {
+ return entryBaseIri.resolve(getBaseMediaIri()).resolve(name);
+ }
+
+ @Override
+ protected IRI resolveBase(RequestContext request) {
+ return request.getBaseUri().resolve(request.getUri());
+ }
+}
Added: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractWorkspaceProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractWorkspaceProvider.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractWorkspaceProvider.java (added)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/AbstractWorkspaceProvider.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,134 @@
+package org.apache.abdera.protocol.server.content;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Collection;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Service;
+import org.apache.abdera.model.Workspace;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.impl.AbstractProvider;
+import org.apache.abdera.protocol.server.impl.AbstractResponseContext;
+import org.apache.abdera.protocol.server.impl.BaseResponseContext;
+import org.apache.abdera.util.EntityTag;
+
+public abstract class AbstractWorkspaceProvider extends AbstractProvider {
+
+ private EntityTag service_etag = new EntityTag("simple");
+
+ protected AbstractWorkspaceProvider(int count) {
+ super(count);
+ }
+
+ public ResponseContext getService(RequestContext request) {
+ Abdera abdera = request.getAbdera();
+ Document<Service> service = getServicesDocument(abdera);
+ AbstractResponseContext rc = new BaseResponseContext<Document<Service>>(service);
+ rc.setEntityTag(service_etag);
+ return rc;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Document<Service> getServicesDocument(Abdera abdera) {
+ Factory factory = abdera.getFactory();
+ Service service = factory.newService();
+ for (WorkspaceInfo wp : getWorkspaces()) {
+ Workspace workspace = service.addWorkspace(wp.getName());
+ Set<Map.Entry<String, CollectionProvider>> entrySet =
+ (Set<Map.Entry<String, CollectionProvider>>) (wp.getCollectionProviders().entrySet());
+ for (Map.Entry<String, CollectionProvider> entry : entrySet) {
+ CollectionProvider<?> cp = entry.getValue();
+ Collection collection = workspace.addCollection(cp.getTitle(),
+ wp.getId() + "/" + entry.getKey());
+ collection.setAccept("entry");
+ // collection.addCategories().setFixed(false);
+ }
+ }
+ return service.getDocument();
+ }
+
+ public abstract java.util.Collection<WorkspaceInfo> getWorkspaces();
+
+ public ResponseContext getFeed(RequestContext request) {
+ CollectionProvider provider = getCollectionProvider(resolveBase(request), request);
+
+ return provider.getFeed(request);
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> CollectionProvider<T> getCollectionProvider(IRI resolveBase,
+ RequestContext request) {
+ String path = resolveBase.getPath();
+ String[] paths = path.split("/");
+ if (paths.length < 1) {
+ // TODO:
+ throw new RuntimeException();
+ } else if (paths.length == 1) {
+ WorkspaceInfo wp = getWorkspaceInfo("");
+ if (wp == null) {
+ // TODO: 404
+ throw new RuntimeException();
+ }
+ return wp.getCollectionProvider(paths[0]);
+ } else {
+ WorkspaceInfo wp = getWorkspaceInfo(paths[paths.length - 2]);
+ if (wp == null) {
+ // TODO: 404
+ throw new RuntimeException();
+ }
+ return wp.getCollectionProvider(paths[paths.length - 1]);
+ }
+ }
+
+ protected abstract WorkspaceInfo<?> getWorkspaceInfo(String string);
+
+ public ResponseContext createEntry(RequestContext request) {
+ CollectionProvider provider = getCollectionProvider(request.getUri(), request);
+
+ return provider.createEntry(request);
+ }
+
+ @Override
+ public ResponseContext getMedia(RequestContext request) {
+ IRI entryBaseIri = resolveBase(request).resolve("../");
+ CollectionProvider provider = getCollectionProvider(entryBaseIri, request);
+
+ return provider.getMedia(request);
+ }
+
+
+ @Override
+ public ResponseContext updateMedia(RequestContext request) {
+ // TODO Auto-generated method stub
+ return super.updateMedia(request);
+ }
+
+ public ResponseContext deleteEntry(RequestContext request) {
+ CollectionProvider<?> provider = getCollectionProvider(resolveBase(request).resolve("./"), request);
+
+ return provider.deleteEntry(request);
+ }
+
+
+ public ResponseContext getEntry(RequestContext request) {
+ IRI entryBaseIri = resolveBase(request).resolve("./");
+ CollectionProvider provider = getCollectionProvider(entryBaseIri, request);
+
+ return provider.getEntry(request, entryBaseIri);
+ }
+
+ @SuppressWarnings("unchecked")
+ public ResponseContext updateEntry(RequestContext request) {
+ IRI entryBaseIri = resolveBase(request).resolve("./");
+ CollectionProvider provider = getCollectionProvider(entryBaseIri, request);
+
+ return provider.updateEntry(request, entryBaseIri);
+ }
+
+
+}
Added: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/CollectionProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/CollectionProvider.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/CollectionProvider.java (added)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/CollectionProvider.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,32 @@
+package org.apache.abdera.protocol.server.content;
+
+import java.io.InputStream;
+import java.util.Date;
+
+import javax.activation.MimeType;
+
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+
+public interface CollectionProvider<T> {
+
+ String getTitle();
+
+ ResponseContext getFeed(RequestContext request, Feed feed);
+
+ ResponseContext createEntry(RequestContext request);
+
+ ResponseContext getMedia(RequestContext request);
+
+ ResponseContext deleteEntry(RequestContext request);
+
+ ResponseContext getEntry(RequestContext request, IRI entryBaseIri);
+
+ ResponseContext getFeed(RequestContext request);
+
+ ResponseContext updateEntry(RequestContext request, IRI entryBaseIri);
+
+}
Added: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/SimpleWorkspaceInfo.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/SimpleWorkspaceInfo.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/SimpleWorkspaceInfo.java (added)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/SimpleWorkspaceInfo.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,42 @@
+package org.apache.abdera.protocol.server.content;
+
+import java.util.Collection;
+import java.util.Map;
+
+public class SimpleWorkspaceInfo implements WorkspaceInfo {
+ private Map<String, CollectionProvider> collectionProviders;
+ private String name;
+ private String id;
+
+ /* (non-Javadoc)
+ * @see org.apache.abdera.protocol.server.content.WorkspaceInfo#getId()
+ */
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public CollectionProvider getCollectionProvider(String id) {
+ return collectionProviders.get(id);
+ }
+
+ public Map<String, CollectionProvider> getCollectionProviders() {
+ return collectionProviders;
+ }
+
+ public void setCollectionProviders(Map<String, CollectionProvider> contentProviders) {
+ this.collectionProviders = contentProviders;
+ }
+
+
+}
Added: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceInfo.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceInfo.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceInfo.java (added)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceInfo.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,15 @@
+package org.apache.abdera.protocol.server.content;
+
+import java.util.Map;
+
+public interface WorkspaceInfo<T> {
+
+ String getId();
+
+ String getName();
+
+ Map<String, CollectionProvider<T>> getCollectionProviders();
+
+ CollectionProvider<T> getCollectionProvider(String id);
+
+}
Added: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceProvider.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceProvider.java (added)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/content/WorkspaceProvider.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,30 @@
+package org.apache.abdera.protocol.server.content;
+
+import java.util.Collection;
+
+public class WorkspaceProvider extends AbstractWorkspaceProvider {
+
+ private Collection<WorkspaceInfo> workspaces;
+
+ public WorkspaceProvider() {
+ super(10);
+ }
+
+ public WorkspaceInfo<?> getWorkspaceInfo(String id) {
+ for (WorkspaceInfo wp : workspaces) {
+ if (wp.getId().equals(id)) {
+ return wp;
+ }
+ }
+ return null;
+ }
+
+ public Collection<WorkspaceInfo> getWorkspaces() {
+ return workspaces;
+ }
+
+ public void setWorkspaces(Collection<WorkspaceInfo> workspaces) {
+ this.workspaces = workspaces;
+ }
+
+}
Modified: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/AbstractProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/AbstractProvider.java?rev=581397&r1=581396&r2=581397&view=diff
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/AbstractProvider.java (original)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/AbstractProvider.java Tue Oct 2 14:45:34 2007
@@ -17,33 +17,20 @@
*/
package org.apache.abdera.protocol.server.impl;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
-import javax.xml.namespace.QName;
-import org.apache.abdera.Abdera;
-import org.apache.abdera.model.Base;
import org.apache.abdera.model.Categories;
-import org.apache.abdera.model.Content;
-import org.apache.abdera.model.Document;
-import org.apache.abdera.model.Element;
-import org.apache.abdera.model.Entry;
-import org.apache.abdera.model.ExtensibleElement;
-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.TargetType;
-import org.apache.abdera.protocol.util.EncodingUtil;
import org.apache.abdera.util.Messages;
-import org.apache.abdera.util.MimeTypeHelper;
-import org.apache.abdera.i18n.iri.IRI;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public abstract class AbstractProvider
+ extends ProviderSupport
implements Provider {
private final static Log log = LogFactory.getLog(AbstractProvider.class);
@@ -56,353 +43,6 @@
this.defaultpagesize = defaultpagesize;
}
- protected Document<Error> createErrorDocument(
- Abdera abdera,
- int code,
- String message,
- Throwable e) {
- Error error = Error.create(abdera,code,message);
- return error.getDocument();
- }
-
- /**
- * Return a server error
- */
- protected ResponseContext servererror(
- Abdera abdera,
- RequestContext request,
- String reason,
- Throwable t) {
- log.debug(Messages.get("SERVER_ERROR"));
- return returnBase(
- createErrorDocument(
- abdera, 500,
- reason, t),
- 500, null);
- }
-
- /**
- * Return an unauthorized error
- */
- protected ResponseContext unauthorized(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("UNAUTHORIZED"));
- return returnBase(
- createErrorDocument(
- abdera, 401,
- reason, null),
- 401, null);
- }
-
- /**
- * Return an unauthorized error
- */
- protected ResponseContext forbidden(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("FORBIDDEN"));
- return returnBase(
- createErrorDocument(
- abdera, 403,
- reason, null),
- 403, null);
- }
-
- /**
- * Return a 404 not found error
- */
- protected ResponseContext unknown(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("UNKNOWN"));
- return returnBase(
- createErrorDocument(
- abdera, 404,
- reason, null),
- 404, null);
- }
-
- /**
- * Return a 405 method not allowed error
- */
- protected ResponseContext notallowed(
- Abdera abdera,
- RequestContext request,
- String reason,
- String... methods) {
- log.debug(Messages.get("NOT.ALLOWED"));
- BaseResponseContext resp =
- (BaseResponseContext)returnBase(
- createErrorDocument(
- abdera, 405,
- reason, null),
- 405, null);
- resp.setAllow(methods);
- return resp;
- }
-
- /**
- * Return a 400 bad request error
- */
- protected ResponseContext badrequest(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("BAD.REQUEST"));
- return returnBase(
- createErrorDocument(
- abdera, 400,
- reason, null),
- 400, null);
- }
-
- /**
- * Return a 409 conflict error
- */
- protected ResponseContext conflict(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("CONFLICT"));
- return returnBase(
- createErrorDocument(
- abdera, 409,
- reason, null),
- 409, null);
- }
-
- /**
- * Return a service unavailable error
- */
- protected ResponseContext unavailable(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("UNAVAILABLE"));
- return returnBase(
- createErrorDocument(
- abdera, 503,
- reason, null),
- 503, null);
- }
-
- protected ResponseContext notmodified(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("NOT.MODIFIED"));
- EmptyResponseContext rc = new EmptyResponseContext(304);
- rc.setStatusText(reason);
- return rc;
- }
-
- protected ResponseContext preconditionfailed(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("PRECONDITION.FAILED"));
- return returnBase(
- createErrorDocument(
- abdera, 412,
- reason, null),
- 412, null);
- }
-
- /**
- * Return a 415 media type not-supported error
- */
- protected ResponseContext notsupported(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("NOT.SUPPORTED"));
- return returnBase(
- createErrorDocument(
- abdera, 415,
- reason, null),
- 415,null);
- }
-
- /**
- * Return a 423 locked error
- */
- protected ResponseContext locked(
- Abdera abdera,
- RequestContext request,
- String reason) {
- log.debug(Messages.get("LOCKED"));
- return returnBase(
- createErrorDocument(
- abdera, 423,
- reason, null),
- 423,null);
- }
-
- /**
- * Return a document
- */
- @SuppressWarnings("unchecked")
- protected ResponseContext returnBase(
- Base base,
- int status,
- Date lastModified) {
- log.debug(Messages.get("RETURNING.DOCUMENT"));
- BaseResponseContext response = new BaseResponseContext(base);
- response.setStatus(status);
- if (lastModified != null) response.setLastModified(lastModified);
- response.setContentType(MimeTypeHelper.getMimeType(base));
- Document doc = base instanceof Document ? (Document)base : ((Element)base).getDocument();
- if (doc.getEntityTag() != null) {
- response.setEntityTag(doc.getEntityTag());
- } else if (doc.getLastModified() != null) {
- response.setLastModified(doc.getLastModified());
- }
- return response;
- }
-
- /**
- * Sanitize the value of a Slug header. Any non alphanumeric characters in
- * the slug are replaced with an underscore
- */
- protected String sanitizeSlug(String slug) {
- if (slug == null) throw new IllegalArgumentException(Messages.get("SLUG.NOT.NULL"));
- String sanitized = EncodingUtil.sanitize(slug);
- log.debug(Messages.format("SLUG.SANITIZED", slug, sanitized));
- return sanitized;
- }
-
- protected int getDefaultPageSize() {
- log.debug(Messages.format("DEFAULT.PAGE.SIZE",defaultpagesize));
- return defaultpagesize;
- }
-
-
- protected int getPageSize(
- RequestContext request,
- String pagesizeparam) {
- int max = getDefaultPageSize();
- int size = max;
- try {
- String _ps = request.getParameter(pagesizeparam);
- size = (_ps != null) ?
- Math.min(Math.max(Integer.parseInt(_ps),0),max) : max;
- } catch (Exception e) {}
- log.debug(Messages.format("PAGE.SIZE",size));
- return size;
- }
-
- protected int getOffset(
- RequestContext request,
- String pageparam,
- int pageSize) {
- int offset = 0;
- try {
- String _page = request.getParameter(pageparam);
- int page =(_page != null) ? Integer.parseInt(_page) : 1;
- page = Math.max(page, 1) - 1;
- offset = pageSize * page;
- } catch (Exception e) {}
- log.debug(Messages.format("OFFSET",offset));
- return offset;
- }
-
- /**
- * Check to see if the entry is minimally valid according to RFC4287.
- * This is not a complete check. It just verifies that the appropriate
- * elements are present and that their values can be accessed.
- */
- protected static boolean isValidEntry(Entry entry) {
- try {
- IRI id = entry.getId();
- if (id == null ||
- id.toString().trim().length() == 0 ||
- !id.isAbsolute()) return false;
- if (entry.getTitle() == null) return false;
- if (entry.getAuthor() == null) return false;
- if (entry.getUpdated() == null) return false;
- Content content = entry.getContentElement();
- if (content == null) {
- if (entry.getAlternateLink() == null) return false;
- } else {
- if ((content.getSrc() != null ||
- content.getContentType() == Content.Type.MEDIA ||
- content.getContentType() == Content.Type.XML) &&
- entry.getSummary() == null) {
- log.debug(Messages.format("CHECKING.VALID.ENTRY",false));
- return false;
- }
- }
- } catch (Exception e) {
- log.debug(Messages.format("CHECKING.VALID.ENTRY",false));
- return false;
- }
- log.debug(Messages.format("CHECKING.VALID.ENTRY",true));
- return true;
- }
-
-
- /**
- * Implementations should override this method to add additional namespaces
- * to the ignore list.
- */
- protected void checkEntryAddAdditionalNamespaces(List ignore) {}
-
- /**
- * Checks the entry for unknown extension elements. Returns false if the
- * entry contains any extension elements that are not supported
- */
- protected boolean checkEntryNamespaces(
- RequestContext request,
- Entry entry) {
- List<String> ignore = new ArrayList<String>();
- ignore.add(org.apache.abdera.util.Constants.APP_NS);
- ignore.add(org.apache.abdera.util.Constants.XHTML_NS);
- ignore.add(org.apache.abdera.util.Constants.XML_NS);
- checkEntryAddAdditionalNamespaces(ignore);
- boolean answer = checkElement(entry,ignore);
- log.debug(Messages.format("CHECKING.ENTRY.NAMESPACES",answer));
- return answer;
- }
-
- /**
- * Return false if the element contains any extension elements that are not
- * supported
- */
- private boolean checkElement(
- Element element,
- List ignore) {
- List<QName> attrs = element.getExtensionAttributes();
- for (QName qname : attrs) {
- String ns = qname.getNamespaceURI();
- if (!ignore.contains(ns)) return false;
- }
- if (element instanceof ExtensibleElement) {
- ExtensibleElement ext = (ExtensibleElement) element;
- List<Element> extensions = ext.getExtensions();
- for (Element el : extensions) {
- QName qname = el.getQName();
- String ns = qname.getNamespaceURI();
- if (!ignore.contains(ns)) return false;
- if (!checkElement(el, ignore)) return false;
- }
- }
- return true;
- }
-
- protected static boolean beforeOrEqual(Date d1, Date d2) {
- long l1 = d1.getTime() / 1000; // drop milliseconds
- long l2 = d2.getTime() / 1000; // drop milliseconds
- return l1 <= l2;
- }
-
- protected IRI resolveBase(RequestContext request) {
- return request.getBaseUri().resolve(request.getUri());
- }
-
public ResponseContext request(RequestContext request) {
TargetType type = request.getTarget().getType();
String method = request.getMethod();
Added: incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/ProviderSupport.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/ProviderSupport.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/ProviderSupport.java (added)
+++ incubator/abdera/java/trunk/server/src/main/java/org/apache/abdera/protocol/server/impl/ProviderSupport.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,395 @@
+package org.apache.abdera.protocol.server.impl;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Base;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.ExtensibleElement;
+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.content.CollectionProvider;
+import org.apache.abdera.protocol.util.EncodingUtil;
+import org.apache.abdera.util.Messages;
+import org.apache.abdera.util.MimeTypeHelper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Provides support methods for {@link Provider} and {@link CollectionProvider}.
+ */
+public class ProviderSupport {
+ private final static Log log = LogFactory.getLog(ProviderSupport.class);
+
+ protected int defaultpagesize = 10;
+
+ protected ProviderSupport() {}
+
+ protected ProviderSupport(int defaultpagesize) {
+ this.defaultpagesize = defaultpagesize;
+ }
+
+ public int getDefaultpagesize() {
+ return defaultpagesize;
+ }
+
+ public void setDefaultpagesize(int defaultpagesize) {
+ this.defaultpagesize = defaultpagesize;
+ }
+
+ protected Document<Error> createErrorDocument(
+ Abdera abdera,
+ int code,
+ String message,
+ Throwable e) {
+ Error error = Error.create(abdera,code,message);
+ return error.getDocument();
+ }
+
+ /**
+ * Return a server error
+ */
+ protected ResponseContext servererror(
+ Abdera abdera,
+ RequestContext request,
+ String reason,
+ Throwable t) {
+ log.debug(Messages.get("SERVER_ERROR"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 500,
+ reason, t),
+ 500, null);
+ }
+
+ /**
+ * Return an unauthorized error
+ */
+ protected ResponseContext unauthorized(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("UNAUTHORIZED"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 401,
+ reason, null),
+ 401, null);
+ }
+
+ /**
+ * Return an unauthorized error
+ */
+ protected ResponseContext forbidden(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("FORBIDDEN"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 403,
+ reason, null),
+ 403, null);
+ }
+
+ /**
+ * Return a 404 not found error
+ */
+ protected ResponseContext unknown(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("UNKNOWN"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 404,
+ reason, null),
+ 404, null);
+ }
+
+ /**
+ * Return a 405 method not allowed error
+ */
+ protected ResponseContext notallowed(
+ Abdera abdera,
+ RequestContext request,
+ String reason,
+ String... methods) {
+ log.debug(Messages.get("NOT.ALLOWED"));
+ BaseResponseContext resp =
+ (BaseResponseContext)returnBase(
+ createErrorDocument(
+ abdera, 405,
+ reason, null),
+ 405, null);
+ resp.setAllow(methods);
+ return resp;
+ }
+
+ /**
+ * Return a 400 bad request error
+ */
+ protected ResponseContext badrequest(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("BAD.REQUEST"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 400,
+ reason, null),
+ 400, null);
+ }
+
+ /**
+ * Return a 409 conflict error
+ */
+ protected ResponseContext conflict(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("CONFLICT"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 409,
+ reason, null),
+ 409, null);
+ }
+
+ /**
+ * Return a service unavailable error
+ */
+ protected ResponseContext unavailable(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("UNAVAILABLE"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 503,
+ reason, null),
+ 503, null);
+ }
+
+ protected ResponseContext notmodified(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("NOT.MODIFIED"));
+ EmptyResponseContext rc = new EmptyResponseContext(304);
+ rc.setStatusText(reason);
+ return rc;
+ }
+
+ protected ResponseContext preconditionfailed(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("PRECONDITION.FAILED"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 412,
+ reason, null),
+ 412, null);
+ }
+
+ /**
+ * Return a 415 media type not-supported error
+ */
+ protected ResponseContext notsupported(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("NOT.SUPPORTED"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 415,
+ reason, null),
+ 415,null);
+ }
+
+ /**
+ * Return a 423 locked error
+ */
+ protected ResponseContext locked(
+ Abdera abdera,
+ RequestContext request,
+ String reason) {
+ log.debug(Messages.get("LOCKED"));
+ return returnBase(
+ createErrorDocument(
+ abdera, 423,
+ reason, null),
+ 423,null);
+ }
+
+ /**
+ * Return a document
+ */
+ @SuppressWarnings("unchecked")
+ protected ResponseContext returnBase(
+ Base base,
+ int status,
+ Date lastModified) {
+ log.debug(Messages.get("RETURNING.DOCUMENT"));
+ BaseResponseContext response = new BaseResponseContext(base);
+ response.setStatus(status);
+ if (lastModified != null) response.setLastModified(lastModified);
+ response.setContentType(MimeTypeHelper.getMimeType(base));
+ Document doc = base instanceof Document ? (Document)base : ((Element)base).getDocument();
+ if (doc.getEntityTag() != null) {
+ response.setEntityTag(doc.getEntityTag());
+ } else if (doc.getLastModified() != null) {
+ response.setLastModified(doc.getLastModified());
+ }
+ return response;
+ }
+
+ /**
+ * Sanitize the value of a Slug header. Any non alphanumeric characters in
+ * the slug are replaced with an underscore
+ */
+ protected String sanitizeSlug(String slug) {
+ if (slug == null) throw new IllegalArgumentException(Messages.get("SLUG.NOT.NULL"));
+ String sanitized = EncodingUtil.sanitize(slug);
+ log.debug(Messages.format("SLUG.SANITIZED", slug, sanitized));
+ return sanitized;
+ }
+
+ protected int getDefaultPageSize() {
+ log.debug(Messages.format("DEFAULT.PAGE.SIZE",defaultpagesize));
+ return defaultpagesize;
+ }
+
+ protected int getPageSize(
+ RequestContext request,
+ String pagesizeparam) {
+ int max = getDefaultPageSize();
+ int size = max;
+ try {
+ String _ps = request.getParameter(pagesizeparam);
+ size = (_ps != null) ?
+ Math.min(Math.max(Integer.parseInt(_ps),0),max) : max;
+ } catch (Exception e) {}
+ log.debug(Messages.format("PAGE.SIZE",size));
+ return size;
+ }
+
+ protected int getOffset(
+ RequestContext request,
+ String pageparam,
+ int pageSize) {
+ int offset = 0;
+ try {
+ String _page = request.getParameter(pageparam);
+ int page =(_page != null) ? Integer.parseInt(_page) : 1;
+ page = Math.max(page, 1) - 1;
+ offset = pageSize * page;
+ } catch (Exception e) {}
+ log.debug(Messages.format("OFFSET",offset));
+ return offset;
+ }
+
+ /**
+ * Check to see if the entry is minimally valid according to RFC4287.
+ * This is not a complete check. It just verifies that the appropriate
+ * elements are present and that their values can be accessed.
+ */
+ protected static boolean isValidEntry(Entry entry) {
+ try {
+ IRI id = entry.getId();
+ if (id == null ||
+ id.toString().trim().length() == 0 ||
+ !id.isAbsolute()) return false;
+ if (entry.getTitle() == null) return false;
+ if (entry.getAuthor() == null) return false;
+ if (entry.getUpdated() == null) return false;
+ Content content = entry.getContentElement();
+ if (content == null) {
+ if (entry.getAlternateLink() == null) return false;
+ } else {
+ if ((content.getSrc() != null ||
+ content.getContentType() == Content.Type.MEDIA ||
+ content.getContentType() == Content.Type.XML) &&
+ entry.getSummary() == null) {
+ log.debug(Messages.format("CHECKING.VALID.ENTRY",false));
+ return false;
+ }
+ }
+ } catch (Exception e) {
+ log.debug(Messages.format("CHECKING.VALID.ENTRY",false));
+ return false;
+ }
+ log.debug(Messages.format("CHECKING.VALID.ENTRY",true));
+ return true;
+ }
+
+ /**
+ * Implementations should override this method to add additional namespaces
+ * to the ignore list.
+ */
+ protected void checkEntryAddAdditionalNamespaces(List ignore) {}
+
+ /**
+ * Checks the entry for unknown extension elements. Returns false if the
+ * entry contains any extension elements that are not supported
+ */
+ protected boolean checkEntryNamespaces(
+ RequestContext request,
+ Entry entry) {
+ List<String> ignore = new ArrayList<String>();
+ ignore.add(org.apache.abdera.util.Constants.APP_NS);
+ ignore.add(org.apache.abdera.util.Constants.XHTML_NS);
+ ignore.add(org.apache.abdera.util.Constants.XML_NS);
+ checkEntryAddAdditionalNamespaces(ignore);
+ boolean answer = checkElement(entry,ignore);
+ log.debug(Messages.format("CHECKING.ENTRY.NAMESPACES",answer));
+ return answer;
+ }
+
+ /**
+ * Return false if the element contains any extension elements that are not
+ * supported
+ */
+ private boolean checkElement(
+ Element element,
+ List ignore) {
+ List<QName> attrs = element.getExtensionAttributes();
+ for (QName qname : attrs) {
+ String ns = qname.getNamespaceURI();
+ if (!ignore.contains(ns)) return false;
+ }
+ if (element instanceof ExtensibleElement) {
+ ExtensibleElement ext = (ExtensibleElement) element;
+ List<Element> extensions = ext.getExtensions();
+ for (Element el : extensions) {
+ QName qname = el.getQName();
+ String ns = qname.getNamespaceURI();
+ if (!ignore.contains(ns)) return false;
+ if (!checkElement(el, ignore)) return false;
+ }
+ }
+ return true;
+ }
+
+ protected static boolean beforeOrEqual(Date d1, Date d2) {
+ long l1 = d1.getTime() / 1000; // drop milliseconds
+ long l2 = d2.getTime() / 1000; // drop milliseconds
+ return l1 <= l2;
+ }
+
+ protected IRI resolveBase(RequestContext request) {
+ return request.getBaseUri().resolve(request.getUri());
+ }
+
+}
Added: incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/ContentProviderTest.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/ContentProviderTest.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/ContentProviderTest.java (added)
+++ incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/ContentProviderTest.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,143 @@
+package org.apache.abdera.server.protocol.server.content;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import junit.framework.TestCase;
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.i18n.iri.IRI;
+import org.apache.abdera.model.Base;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.Entry;
+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.ServiceContext;
+import org.apache.abdera.protocol.server.TargetType;
+import org.apache.abdera.protocol.server.content.CollectionProvider;
+import org.apache.abdera.protocol.server.content.SimpleWorkspaceInfo;
+import org.apache.abdera.protocol.server.content.WorkspaceInfo;
+import org.apache.abdera.protocol.server.content.WorkspaceProvider;
+import org.apache.abdera.protocol.server.impl.DefaultServiceContext;
+import org.apache.abdera.protocol.server.impl.RegexTargetResolver;
+import org.apache.abdera.protocol.server.impl.SingletonProviderManager;
+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 ContentProviderTest extends TestCase {
+
+ private Server server;
+ private DefaultServiceContext abderaServiceContext;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ abderaServiceContext = new DefaultServiceContext();
+
+ RegexTargetResolver resolver = new RegexTargetResolver();
+ resolver.setPattern("/acme(\\?[^#]*)?", TargetType.TYPE_SERVICE);
+ resolver.setPattern("/acme/customers(\\?[^#]*)?", TargetType.TYPE_COLLECTION);
+ resolver.setPattern("/acme/customers/([^/#?]+)(\\?[^#]*)?", TargetType.TYPE_ENTRY);
+ abderaServiceContext.setTargetResolver(resolver);
+
+ SingletonProviderManager pm = new SingletonProviderManager();
+ abderaServiceContext.setProviderManager(pm);
+
+ WorkspaceProvider wp = new WorkspaceProvider();
+
+ SimpleWorkspaceInfo wi = new SimpleWorkspaceInfo();
+ wi.setId("acme");
+ CustomerContentProvider cp = new CustomerContentProvider();
+ Map<String, CollectionProvider> contentProviders = new HashMap<String, CollectionProvider>();
+ contentProviders.put("customers", cp);
+
+ wi.setCollectionProviders(contentProviders);
+
+ List<WorkspaceInfo> workspaces = new ArrayList<WorkspaceInfo>();
+ workspaces.add(wi);
+ wp.setWorkspaces(workspaces);
+ pm.setProvider(wp);
+
+ initializeJetty();
+ }
+
+ public void testCustomerProvider() throws Exception {
+
+ Abdera abdera = new Abdera();
+ Factory factory = abdera.getFactory();
+
+ AbderaClient client = new AbderaClient(abdera);
+
+ String base = "http://localhost:9002/";
+
+ // Testing of entry creation
+ IRI colUri = new IRI(base).resolve("acme/customers"); // base +
+ // docCollection.getHref().toString();
+ Entry entry = factory.newEntry();
+ entry.setTitle("Hmmm this is ignored right now");
+ entry.setUpdated(new Date());
+ entry.addAuthor("Acme Industries");
+ entry.setId(factory.newUuidUri());
+ entry.setSummary("Customer document");
+
+ Element customerEl = factory.newElement(new QName("customer"));
+ customerEl.setAttributeValue(new QName("name"), "Dan Diephouse");
+ entry.setContent(customerEl);
+
+ RequestOptions opts = new RequestOptions();
+ opts.setContentType("application/atom+xml;type=entry");
+ ClientResponse res = client.post(colUri.toString(), entry, opts);
+ assertEquals(201, res.getStatus());
+
+ prettyPrint(abdera, res.getDocument());
+
+ IRI location = res.getLocation();
+ assertEquals(colUri + "/1001-Dan_Diephouse",
+ location.toString());
+
+ // GET the entry
+ res = client.get(location.toString());
+ assertEquals(200, res.getStatus());
+
+ prettyPrint(abdera, res.getDocument());
+ org.apache.abdera.model.Document<Entry> entry_doc = res.getDocument();
+ entry = entry_doc.getRoot();
+
+ }
+
+ private void prettyPrint(Abdera abdera, Base doc) throws IOException {
+ abdera.getWriterFactory().getWriter("prettyxml").writeTo(doc, System.out);
+ System.out.println();
+ }
+
+ private void initializeJetty() throws Exception {
+
+ server = new Server(9002);
+ Context root = new Context(server, "/", Context.NO_SESSIONS);
+ root.addServlet(new ServletHolder(new AbderaServlet() {
+
+ @Override
+ protected ServiceContext createServiceContext() {
+ abderaServiceContext.init(getAbdera(), getProperties(getServletConfig()));
+ return abderaServiceContext;
+ }
+ }), "/*");
+ server.start();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (server != null) server.stop();
+ }
+
+}
Added: incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/Customer.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/Customer.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/Customer.java (added)
+++ incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/Customer.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,22 @@
+package org.apache.abdera.server.protocol.server.content;
+
+import java.util.Date;
+
+public class Customer {
+ private int id;
+ private String name;
+
+ public int getId() {
+ return id;
+ }
+ public void setId(int id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
Added: incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/CustomerContentProvider.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/CustomerContentProvider.java?rev=581397&view=auto
==============================================================================
--- incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/CustomerContentProvider.java (added)
+++ incubator/abdera/java/trunk/server/src/test/java/org/apache/abdera/server/protocol/server/content/CustomerContentProvider.java Tue Oct 2 14:45:34 2007
@@ -0,0 +1,115 @@
+package org.apache.abdera.server.protocol.server.content;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.xml.namespace.QName;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Content;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.protocol.server.content.AbstractCollectionProvider;
+import sun.security.pkcs.ContentInfo;
+
+public class CustomerContentProvider extends AbstractCollectionProvider<Customer> {
+ private static final String ID_PREFIX = "urn:acme:customer:";
+
+ private final static AtomicInteger nextId = new AtomicInteger(1000);
+ private Map<Integer, Customer> customers = new HashMap<Integer, Customer>();
+ private Factory factory = new Abdera().getFactory();
+
+ public String getId() {
+ return "tag:example.org,2006:feed";
+ }
+
+ public Customer createEntry(String title, String summary, Content content) {
+ Customer customer = contentToCustomer(content);
+ customers.put(customer.getId(), customer);
+
+ return customer;
+ }
+
+ private Customer contentToCustomer(Content content) {
+ Customer customer = new Customer();
+
+ return contentToCustomer(content, customer);
+ }
+
+ private Customer contentToCustomer(Content content, Customer customer) {
+ Element firstChild = content.getFirstChild();
+ customer.setName(firstChild.getAttributeValue("name"));
+ customer.setId(nextId.incrementAndGet());
+ return customer;
+ }
+
+ public void deleteEntry(String resourceName) {
+ Integer id = getIdFromResourceName(resourceName);
+ customers.remove(id);
+ }
+
+ public String getAuthor() {
+ return "Acme Industries";
+ }
+
+ public Object getContent(Customer entry) {
+ Content content = factory.newContent();
+ Element customerEl = factory.newElement(new QName("customer"));
+ customerEl.setAttributeValue(new QName("name"), entry.getName());
+
+ content.setValueElement(customerEl);
+ return content;
+ }
+
+ public Iterable<Customer> getEntries() {
+ return customers.values();
+ }
+
+ public Customer getEntry(String resourceName) {
+ Integer id = getIdFromResourceName(resourceName);
+ return customers.get(id);
+ }
+
+ private Integer getIdFromResourceName(String resourceName) {
+ int idx = resourceName.indexOf("-");
+ if (idx == -1) {
+ // TODO: exception handling for 404 Not found
+ }
+ Integer id = new Integer(resourceName.substring(0, idx));
+ return id;
+ }
+
+ public Customer getEntryFromId(String id) {
+ return customers.get(new Integer(id));
+ }
+
+ public String getId(Customer entry) {
+ // TODO: is this valid?
+ return ID_PREFIX + entry.getId();
+ }
+
+ public String getName(Customer entry) {
+ return entry.getId() + "-" + entry.getName().replaceAll(" ", "_");
+ }
+
+ public String getTitle() {
+ return "Acme Customer Database";
+ }
+
+ public String getTitle(Customer entry) {
+ return entry.getName();
+ }
+
+ public Date getUpdated(Customer entry) {
+ return new Date();
+ }
+
+ public Customer updateEntry(Customer entry, Content content) {
+ contentToCustomer(content, entry);
+
+ return entry;
+ }
+
+}
Modified: incubator/abdera/java/trunk/spring/src/main/resources/META-INF/schemas/abdera-spring.xsd
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/spring/src/main/resources/META-INF/schemas/abdera-spring.xsd?rev=581397&r1=581396&r2=581397&view=diff
==============================================================================
--- incubator/abdera/java/trunk/spring/src/main/resources/META-INF/schemas/abdera-spring.xsd (original)
+++ incubator/abdera/java/trunk/spring/src/main/resources/META-INF/schemas/abdera-spring.xsd Tue Oct 2 14:45:34 2007
@@ -48,13 +48,13 @@
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
- <xsd:sequence>
+ <xsd:choice maxOccurs="unbounded">
<xsd:element name="category" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="collection" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="entry" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="media" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="service" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
+ </xsd:choice>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>