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 2006/08/31 00:53:14 UTC

svn commit: r438696 - in /incubator/abdera/java/trunk/examples: ./ src/main/java/org/apache/abdera/examples/appserver/ src/main/resources/org/ src/main/resources/org/apache/ src/main/resources/org/apache/abdera/ src/main/resources/org/apache/abdera/exa...

Author: jmsnell
Date: Wed Aug 30 15:53:13 2006
New Revision: 438696

URL: http://svn.apache.org/viewvc?rev=438696&view=rev
Log:
Initial simple APP Server implementation example.  This is not complete, but its 
generally functional.

Added:
    incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/
    incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandler.java
    incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandlerFactory.java
    incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleTargetResolver.java
    incubator/abdera/java/trunk/examples/src/main/resources/org/
    incubator/abdera/java/trunk/examples/src/main/resources/org/apache/
    incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/
    incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/
    incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/
    incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/README
    incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml
Modified:
    incubator/abdera/java/trunk/examples/pom.xml

Modified: incubator/abdera/java/trunk/examples/pom.xml
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/examples/pom.xml?rev=438696&r1=438695&r2=438696&view=diff
==============================================================================
--- incubator/abdera/java/trunk/examples/pom.xml (original)
+++ incubator/abdera/java/trunk/examples/pom.xml Wed Aug 30 15:53:13 2006
@@ -61,6 +61,12 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.abdera</groupId>
+      <artifactId>abdera-server</artifactId>
+      <version>0.2.0-incubating-SNAPSHOT</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
       <groupId>commons-httpclient</groupId>
       <artifactId>commons-httpclient</artifactId>
     </dependency>

Added: incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandler.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandler.java?rev=438696&view=auto
==============================================================================
--- incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandler.java (added)
+++ incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandler.java Wed Aug 30 15:53:13 2006
@@ -0,0 +1,307 @@
+/*
+* 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.examples.appserver;
+
+import java.io.IOException;
+import java.util.Date;
+
+import javax.activation.MimeTypeParseException;
+
+import org.apache.abdera.Abdera;
+import org.apache.abdera.factory.Factory;
+import org.apache.abdera.model.Collection;
+import org.apache.abdera.model.Document;
+import org.apache.abdera.model.Element;
+import org.apache.abdera.model.Entry;
+import org.apache.abdera.model.Feed;
+import org.apache.abdera.model.Link;
+import org.apache.abdera.model.Service;
+import org.apache.abdera.model.Workspace;
+import org.apache.abdera.parser.Parser;
+import org.apache.abdera.parser.stax.util.FOMHelper;
+import org.apache.abdera.protocol.server.AbderaServer;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.ResponseContext;
+import org.apache.abdera.protocol.server.exceptions.AbderaServerException;
+import org.apache.abdera.protocol.server.target.Target;
+import org.apache.abdera.protocol.server.util.AbstractRequestHandler;
+import org.apache.abdera.protocol.server.util.BaseResponseContext;
+import org.apache.abdera.protocol.server.util.EmptyResponseContext;
+import org.apache.abdera.protocol.server.util.ResourceType;
+import org.apache.abdera.util.Constants;
+import org.apache.abdera.util.MimeTypeHelper;
+
+public class SimpleRequestHandler 
+  extends AbstractRequestHandler {
+
+  private AbderaServer abderaServer = null;
+  
+  public SimpleRequestHandler(AbderaServer abderaServer) {
+    this.abderaServer = abderaServer;
+  }
+  
+  @Override
+  protected ResourceType getResourceType(RequestContext requestContext) {
+    Target target = requestContext.getTarget();
+    return (target != null && target.getResourceType() != null) ? 
+      target.getResourceType() : ResourceType.UNKNOWN;
+  }
+
+  @Override
+  protected ResponseContext createResponseContext() {
+    return null;
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Override
+  protected ResponseContext internalInvoke(
+    RequestContext requestContext,
+    ResponseContext responseContext) 
+      throws AbderaServerException {
+    Target target = requestContext.getTarget();
+    String method = requestContext.getMethod();
+    if (target != null) {
+      switch(target.getResourceType()) {
+        case SERVICE: {
+          try {
+            if (requestContext.getIfNoneMatch().equals("\"service\"")) 
+              throw new AbderaServerException(
+                AbderaServerException.Code.NOTMODIFIED, 
+                "Not Modified", "");
+          } catch (NullPointerException npe) {}
+          return getServiceDocument();
+        }
+        case COLLECTION: {
+          if (method.equals("GET")) {
+            if (!target.getValue(1).equals("foo")) 
+              throw new AbderaServerException(
+                AbderaServerException.Code.NOTFOUND, 
+                "Not Found", "");
+            return getFeedDocument();
+          } else if (method.equals("POST")) {
+            try {
+              Document<Entry> entry_doc = 
+                getEntryFromRequestContext(requestContext);
+              if (entry_doc != null) {
+                Entry entry = (Entry) entry_doc.getRoot().clone();
+                if (!isValidEntry(entry))
+                  throw new AbderaServerException(
+                    AbderaServerException.Code.BADREQUEST, "Invalid Entry", "");
+                entry.setUpdated(new Date());
+                entry.setModified(entry.getUpdated());
+                entry.getIdElement().setValue(FOMHelper.generateUuid());
+                entry.addLink("foo/" + entry.getId().toString(), "edit");
+                getFeed().getRoot().insertEntry((Entry) entry.clone());
+                BaseResponseContext rc = getEntryDocument(entry);
+                rc.setStatus(201);
+                String elink = entry.getEditLink().getHref().toString();
+                rc.setLocation(elink);
+                rc.setContentLocation(elink);
+                return rc;
+              } else {
+                throw new AbderaServerException(
+                  AbderaServerException.Code.UNSUPPORTEDMEDIATYPE, 
+                  "Unsupported Media Type", "");
+              }
+            } catch (AbderaServerException e) {
+              throw e;
+            } catch (Exception e) {
+              throw new AbderaServerException(e);
+            }
+          }
+        }
+        case ENTRY_EDIT: {
+          Entry entry = getEntryFromFeed(requestContext);
+          if (entry == null)
+            throw new AbderaServerException(
+              AbderaServerException.Code.NOTFOUND, "Not Found", "");
+          if (method.equals("GET")) {
+            Entry e = (Entry) entry.clone();
+            return new BaseResponseContext(e.getDocument());
+          } else if (method.equals("PUT")) {
+            try {
+              Document<Entry> entry_doc = getEntryFromRequestContext(requestContext);
+              if (entry_doc == null) 
+                throw new AbderaServerException(
+                  AbderaServerException.Code.UNSUPPORTEDMEDIATYPE, 
+                  "Unsupported Media Type", "");
+              Document<Feed> feed_doc = getFeed();
+              Entry e = (Entry) entry_doc.getRoot().clone();
+              // check to see if it's a valid atom entry
+              if (!isValidEntry(entry))
+                throw new AbderaServerException(
+                  AbderaServerException.Code.BADREQUEST, "Invalid Entry", "");
+              // check to see if the atom:id matches
+              if (!e.getId().equals(entry.getId()))
+                throw new AbderaServerException(
+                  AbderaServerException.Code.CONFLICT, "Conflict. Cannot change atom:id", "");
+              // override atom:updated 
+              e.setUpdated(new Date());
+              // set the app:modified date
+              e.setModified(e.getUpdated());
+              // make sure the edit link stays the same
+              Link editLink = e.getEditLink();
+              if (editLink == null) 
+                e.addLink("foo/" + e.getId().toString(), "edit");
+              else editLink.setHref("foo/" + e.getId().toString());
+              // discard the original
+              entry.discard();
+              // insert the new
+              feed_doc.getRoot().insertEntry((Entry) e.clone());
+              return new EmptyResponseContext(204);
+            } catch (Exception e) {
+              throw new AbderaServerException(e);
+            }
+          } else if (method.equals("DELETE")) {
+            entry.discard();
+            return new EmptyResponseContext(204);
+          }
+        }
+      }
+      return null;
+    } else {
+      throw new AbderaServerException(
+        AbderaServerException.Code.NOTFOUND, 
+        "Not Found", "");
+    }
+  }
+  
+  private Entry getEntryFromFeed(RequestContext context) {
+    try {
+      Target target = context.getTarget();
+      Document<Feed> doc_feed = getFeed();
+      String id = target.getValue(2);
+      return doc_feed.getRoot().getEntry(id);
+    } catch (Exception e) {
+      return null;
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private Document<Entry> getEntryFromRequestContext(
+    RequestContext context) 
+      throws IOException, 
+             MimeTypeParseException {
+    String ctype = context.getContentType().toString();
+    if (ctype != null && ctype.length() != 0 &&
+        (!MimeTypeHelper.isMatch(ctype, "application/atom+xml") &&
+         !MimeTypeHelper.isMatch(ctype, "application/xml"))) {
+      return null;
+    }
+    // might still be an atom entry, let's try it
+    try {
+      Parser parser = getParser();
+      Document doc = parser.parse(context.getInputStream());
+      Element root = doc.getRoot();
+      if (root != null && root.getQName().equals(Constants.ENTRY)) {
+        return doc;
+      }
+    } catch (Exception e) {}
+    return null;
+  }
+  
+  private boolean isValidEntry(Entry entry) {
+    try {
+      if (entry.getId() == null || entry.getId().toString().length() == 0) return false;
+      if (entry.getTitle() == null) return false;
+      if (entry.getAuthor() == null) return false;
+      if (entry.getUpdated() == null) return false;
+      if (entry.getContent() == null) {
+        if (entry.getAlternateLink() == null) return false;
+        if (entry.getSummary() == null) return false;
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return true;
+  }
+  
+  // The service doc, collection, etc
+  
+  private static Document<Service> service_doc = null;
+  private static Document<Feed> feed_doc = null;
+  
+  private BaseResponseContext<Document<Entry>> getEntryDocument(Entry entry) {
+    Document<Entry> entry_doc = entry.getDocument();
+    BaseResponseContext<Document<Entry>> rc =
+      new BaseResponseContext<Document<Entry>>(entry_doc);
+    return rc;
+  }
+  
+  private BaseResponseContext<Document<Service>> getServiceDocument() {
+    BaseResponseContext<Document<Service>> rc = 
+      new BaseResponseContext<Document<Service>>(getService());
+    rc.setEntityTag("\"service\"");
+    rc.setLastModified(new Date());
+    return rc;
+  }
+  
+  private BaseResponseContext<Document<Feed>> getFeedDocument() {
+    BaseResponseContext<Document<Feed>> rc =
+      new BaseResponseContext<Document<Feed>>(getFeed());
+    return rc;
+  }
+  
+  private synchronized Document<Service> getService() {
+    if (service_doc == null) {
+      try {
+        Factory factory = getFactory();
+        service_doc = factory.newDocument();
+        Service service = factory.newService(service_doc);
+        Workspace workspace = service.addWorkspace("Simple");
+        Collection entries = workspace.addCollection("foo", "atom/foo");
+        entries.setAccept("entry");
+      } catch (Exception e) {}
+    }
+    return service_doc;
+  }
+  
+  private synchronized Document<Feed> getFeed() {
+    if (feed_doc == null) {
+      try {
+        Factory factory = getFactory();
+        feed_doc = factory.newDocument();
+        Feed feed = factory.newFeed(feed_doc);
+        feed.setId(FOMHelper.generateUuid());
+        feed.setTitle("Foo");
+        feed.setUpdated(new Date());
+        feed.addLink("http://example.org");
+        feed.addLink("", "self");
+        feed.addAuthor("Simple Service");
+      } catch (Exception e) {}
+    }
+    return feed_doc;
+  }
+  
+  private AbderaServer getAbderaServer() {
+    return abderaServer;
+  }
+  
+  private Abdera getAbdera() {
+    return getAbderaServer().getAbdera();
+  }
+  
+  private Factory getFactory() {
+    return getAbdera().getFactory();
+  }
+  
+  private Parser getParser() {
+    return getAbdera().getParser();
+  }
+
+}

Added: incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandlerFactory.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandlerFactory.java?rev=438696&view=auto
==============================================================================
--- incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandlerFactory.java (added)
+++ incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleRequestHandlerFactory.java Wed Aug 30 15:53:13 2006
@@ -0,0 +1,36 @@
+/*
+* 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.examples.appserver;
+
+import org.apache.abdera.protocol.server.AbderaServer;
+import org.apache.abdera.protocol.server.RequestContext;
+import org.apache.abdera.protocol.server.RequestHandler;
+import org.apache.abdera.protocol.server.RequestHandlerFactory;
+import org.apache.abdera.protocol.server.exceptions.AbderaServerException;
+
+public class SimpleRequestHandlerFactory 
+  implements RequestHandlerFactory {
+
+  public RequestHandler newRequestHandler(
+    AbderaServer abderaServer,
+    RequestContext requestContext)
+      throws AbderaServerException {
+    return new SimpleRequestHandler(abderaServer);
+  }
+
+}

Added: incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleTargetResolver.java
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleTargetResolver.java?rev=438696&view=auto
==============================================================================
--- incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleTargetResolver.java (added)
+++ incubator/abdera/java/trunk/examples/src/main/java/org/apache/abdera/examples/appserver/SimpleTargetResolver.java Wed Aug 30 15:53:13 2006
@@ -0,0 +1,32 @@
+/*
+* 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.examples.appserver;
+
+import org.apache.abdera.protocol.server.util.RegexTargetResolver;
+import org.apache.abdera.protocol.server.util.ResourceType;
+
+public class SimpleTargetResolver 
+  extends RegexTargetResolver {
+
+  public SimpleTargetResolver() {
+    addPattern(ResourceType.SERVICE, "/appserver/atom(\\?[^#]*)?");
+    addPattern(ResourceType.COLLECTION, "/appserver/atom/([^/#?]+)(\\?[^#]*)?");
+    addPattern(ResourceType.ENTRY_EDIT, "/appserver/atom/([^/#?]+)/([^/#?]+)(\\?[^#]*)?");
+  }
+  
+}

Added: incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/README
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/README?rev=438696&view=auto
==============================================================================
--- incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/README (added)
+++ incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/README Wed Aug 30 15:53:13 2006
@@ -0,0 +1,2 @@
+A simple, generally compliant, minimal APP Server implementation that 
+demonstrates the use of the server module for building APP servers.
\ No newline at end of file

Added: incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml
URL: http://svn.apache.org/viewvc/incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml?rev=438696&view=auto
==============================================================================
--- incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml (added)
+++ incubator/abdera/java/trunk/examples/src/main/resources/org/apache/abdera/examples/appserver/web.xml Wed Aug 30 15:53:13 2006
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app id="WebApp_ID" version="2.4" 
+  xmlns="http://java.sun.com/xml/ns/j2ee" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+	<display-name>Abdera Simple APP Server</display-name>
+  <servlet id="abdera">
+    <servlet-name>Abdera</servlet-name>  
+    <servlet-class>org.apache.abdera.protocol.server.servlet.AbderaServlet</servlet-class>
+    <init-param>
+      <param-name>org.apache.abdera.protocol.server.RequestHandlerFactory</param-name>
+      <param-value>org.apache.abdera.examples.appserver.SimpleRequestHandlerFactory</param-value>
+    </init-param>
+    <init-param>
+      <param-name>org.apache.abdera.protocol.server.target.TargetResolver</param-name>
+      <param-value>org.apache.abdera.examples.appserver.SimpleTargetResolver</param-value>
+    </init-param>
+  </servlet>
+  <servlet-mapping id="abdera-mapping">
+    <servlet-name>Abdera</servlet-name>
+    <url-pattern>/atom/*</url-pattern>
+  </servlet-mapping>
+	<welcome-file-list>
+		<welcome-file>index.jsp</welcome-file>
+	</welcome-file-list>
+</web-app>