You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2007/07/01 05:30:02 UTC

svn commit: r552239 - in /roller/branches/roller_3.1: src/org/apache/roller/business/hibernate/ src/org/apache/roller/webservices/atomprotocol/ web/WEB-INF/classes/

Author: snoopdave
Date: Sat Jun 30 20:30:00 2007
New Revision: 552239

URL: http://svn.apache.org/viewvc?view=rev&rev=552239
Log:
Updating APP imlementation for ROL-1464

Added:
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModule.java
      - copied, changed from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModule.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleGenerator.java
      - copied, changed from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleGenerator.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleImpl.java
      - copied, changed from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleImpl.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleParser.java
      - copied, changed from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleParser.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Categories.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Collection.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Workspace.java
Removed:
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModule.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleGenerator.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleImpl.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleParser.java
Modified:
    roller/branches/roller_3.1/src/org/apache/roller/business/hibernate/HibernateWeblogManagerImpl.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomService.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomServlet.java
    roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/RollerAtomHandler.java
    roller/branches/roller_3.1/web/WEB-INF/classes/rome.properties

Modified: roller/branches/roller_3.1/src/org/apache/roller/business/hibernate/HibernateWeblogManagerImpl.java
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/business/hibernate/HibernateWeblogManagerImpl.java?view=diff&rev=552239&r1=552238&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/business/hibernate/HibernateWeblogManagerImpl.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/business/hibernate/HibernateWeblogManagerImpl.java Sat Jun 30 20:30:00 2007
@@ -204,6 +204,8 @@
             updateTagCount(name, entry.getWebsite(), -1);
         }  
         
+        entry.setUpdateTime(new Timestamp(new Date().getTime()));
+        
         this.strategy.store(entry);        
         
         // update weblog last modified date.  date updated by saveWebsite()

Copied: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModule.java (from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModule.java)
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModule.java?view=diff&rev=552239&p1=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModule.java&r1=552026&p2=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModule.java&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModule.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModule.java Sat Jun 30 20:30:00 2007
@@ -18,9 +18,13 @@
 package org.apache.roller.webservices.atomprotocol;
 
 import com.sun.syndication.feed.module.Module;
+import java.util.Date;
 
-public interface PubControlModule extends Module {
-    public static final String URI = "http://purl.org/atom/app#";
+public interface AppModule extends Module {
+    public static final String URI = "http://www.w3.org/2007/app";
     public boolean getDraft();
     public void setDraft(boolean draft);
+    public Date getEdited();
+    public void setEdited(Date edited);
 }
+

Copied: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleGenerator.java (from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleGenerator.java)
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleGenerator.java?view=diff&rev=552239&p1=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleGenerator.java&r1=552026&p2=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleGenerator.java&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleGenerator.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleGenerator.java Sat Jun 30 20:30:00 2007
@@ -26,20 +26,21 @@
 
 import com.sun.syndication.feed.module.Module;
 import com.sun.syndication.io.ModuleGenerator;
+import org.apache.roller.util.DateUtil;
 
-public class PubControlModuleGenerator implements ModuleGenerator {
-    private static final Namespace PUBCONTROL_NS  = 
-        Namespace.getNamespace("app", PubControlModule.URI);
+public class AppModuleGenerator implements ModuleGenerator {
+    private static final Namespace APP_NS  = 
+        Namespace.getNamespace("app", AppModule.URI);
 
     public String getNamespaceUri() {
-        return PubControlModule.URI;
+        return AppModule.URI;
     }
 
     private static final Set NAMESPACES;
 
     static {
         Set nss = new HashSet();
-        nss.add(PUBCONTROL_NS);
+        nss.add(APP_NS);
         NAMESPACES = Collections.unmodifiableSet(nss);
     }
 
@@ -48,17 +49,24 @@
     }
 
     public void generate(Module module, Element element) {
-        PubControlModule m = (PubControlModule)module;
+        AppModule m = (AppModule)module;
+        
         String draft = m.getDraft() ? "yes" : "no";
-        Element control = new Element("control", PUBCONTROL_NS);
+        Element control = new Element("control", APP_NS);
         control.addContent(generateSimpleElement("draft", draft));
         element.addContent(control);
+        
+        if (m.getEdited() != null) {
+            Element edited = new Element("edited", APP_NS);
+            edited.addContent(DateUtil.formatIso8601(m.getEdited()));
+            element.addContent(edited);
+        }
     }
 
     protected Element generateSimpleElement(String name, String value)  {
-        Element element = new Element(name, PUBCONTROL_NS);
+        Element element = new Element(name, APP_NS);
         element.addContent(value);
         return element;
     }
-
 }
+

Copied: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleImpl.java (from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleImpl.java)
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleImpl.java?view=diff&rev=552239&p1=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleImpl.java&r1=552026&p2=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleImpl.java&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleImpl.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleImpl.java Sat Jun 30 20:30:00 2007
@@ -18,24 +18,39 @@
 package org.apache.roller.webservices.atomprotocol;
 
 import com.sun.syndication.feed.module.ModuleImpl;
+import java.util.Date;
 
-public class PubControlModuleImpl extends ModuleImpl implements PubControlModule {
-    private boolean _draft = false;
-
-    public PubControlModuleImpl() {
-        super(PubControlModule.class,PubControlModule.URI);
+public class AppModuleImpl extends ModuleImpl implements AppModule {
+    private boolean draft = false;
+    private Date edited = null;
+    
+    public AppModuleImpl() {
+        super(AppModule.class, AppModule.URI);
     }
+    
     public boolean getDraft() {
-        return _draft;
+        return draft;
     }
+    
     public void setDraft(boolean draft) {
-        _draft = draft;
+        this.draft = draft;
+    }
+    
+    public Date getEdited() {
+        return edited;
     }
+
+    public void setEdited(Date edited) {
+        this.edited = edited;
+    }
+    
     public Class getInterface() {
-        return PubControlModule.class;
+        return AppModule.class;
     }
+    
     public void copyFrom(Object obj) {
-        PubControlModule m = (PubControlModule)obj;
+        AppModule m = (AppModule)obj;
         setDraft(m.getDraft());
     }
 }
+

Copied: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleParser.java (from r552026, roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleParser.java)
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleParser.java?view=diff&rev=552239&p1=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleParser.java&r1=552026&p2=roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleParser.java&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/PubControlModuleParser.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AppModuleParser.java Sat Jun 30 20:30:00 2007
@@ -22,26 +22,34 @@
 
 import com.sun.syndication.feed.module.Module;
 import com.sun.syndication.io.ModuleParser;
+import org.apache.roller.util.DateUtil;
 
-public class PubControlModuleParser implements ModuleParser {
+public class AppModuleParser implements ModuleParser {
 
     public String getNamespaceUri() {
-        return PubControlModule.URI;
+        return AppModule.URI;
     }
 
     public Namespace getContentNamespace() {
-        return Namespace.getNamespace(PubControlModule.URI);
+        return Namespace.getNamespace(AppModule.URI);
     }
+    
     public Module parse(Element elem) {
         boolean foundSomething = false;
-        PubControlModule m = new PubControlModuleImpl();
-        Element e = elem.getChild("control", getContentNamespace());
-        if (e != null) {
-            Element draftElem = e.getChild("draft", getContentNamespace());
+        AppModule m = new AppModuleImpl();
+        Element control = elem.getChild("control", getContentNamespace());
+        if (control != null) {
+            Element draftElem = control.getChild("draft", getContentNamespace());
             if (draftElem != null) {
                 if ("yes".equals(draftElem.getText())) m.setDraft(true); 
                 if ("no".equals(draftElem.getText())) m.setDraft(false);                
             }
+        }
+        Element edited = elem.getChild("editied", getContentNamespace());
+        if (edited != null) {
+            try {
+                m.setEdited(DateUtil.parseIso8601(edited.getTextTrim()));
+            } catch (Exception ignored) {}
         }
         return m;
     }

Modified: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomService.java
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomService.java?view=diff&rev=552239&r1=552238&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomService.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomService.java Sat Jun 30 20:30:00 2007
@@ -28,72 +28,26 @@
 import org.jdom.Namespace;
 
 /**
- * This class models an Atom Ublishing Protocol Service Document.
- * <p />
- * Based on: draft-ietf-atompub-protocol-10.txt
- * <p />
+ * This class models an Atom Publishing Protocol AtomService Document.
+ * Based on: draft-ietf-atompub-protocol-15.txt.
  * Designed to be Roller independent.
- *//* 
-
-	namespace app = "http://purl.org/atom/app#"
-	start = appService
-	             
-	appService =
-	   element app:service {
-	      appCommonAttributes,
-	      ( appWorkspace+
-	        & extensionElement* )
-	   }
-	   
-	For example:
-	 
-	<?xml version="1.0" encoding='utf-8'?>
-	<service xmlns="http://purl.org/atom/app#"
-	         xmlns:atom="http://www.w3.org/2005/Atom">
-	  <workspace>
-	    <atom:title>Main Site</atom:title>
-	    <collection
-	        href="http://example.org/reilly/main" >
-	      <atom:title>My Blog Entries</atom:title>
-	      <categories
-	         href="http://example.com/cats/forMain.cats" />
-	    </collection>
-	    <collection
-	        href="http://example.org/reilly/pic" >
-	      <atom:title>Pictures</atom:title>
-	      <accept>image/*</accept>
-	    </collection>
-	  </workspace>
-	  <workspace>
-	    <atom:title>Side Bar Blog</atom:title>
-	    <collection
-	        href="http://example.org/reilly/list" >
-	      <atom:title>Remaindered Links</atom:title>
-	      <accept>entry</accept>
-	      <categories fixed="yes">
-	        <atom:category
-	          scheme="http://example.org/extra-cats/"
-	          term="joke" />
-	        <atom:category
-	          scheme="http://example.org/extra-cats/"
-	          term="serious" />
-	      </categories>
-	    </collection>
-	  </workspace>
-	</service>
  */
 public class AtomService {
-    public static final Namespace ns =
-            Namespace.getNamespace("app","http://purl.org/atom/app#");
-    public static final Namespace atomns =
-            Namespace.getNamespace("atom","http://www.w3.org/2005/atom");
 
     private List workspaces = new ArrayList();
     
+    /** Namespace for Atom Syndication Format */
+    public static Namespace ATOM_FORMAT = 
+        Namespace.getNamespace("atom","http://www.w3.org/2005/Atom");
+    
+    /** Namespace for Atom Publishing Protocol */
+    public static Namespace ATOM_PROTOCOL = 
+        Namespace.getNamespace("app","http://www.w3.org/2007/app");  
+        
     public AtomService() {
     }
     
-    public void addWorkspace(AtomService.Workspace workspace) {
+    public void addWorkspace(Workspace workspace) {
         workspaces.add(workspace);
     }
     
@@ -105,362 +59,43 @@
         this.workspaces = workspaces;
     }
     
-    /**
-     * This class models an Atom workspace.
-     * @author Dave Johnson
-     *//*
-	appWorkspace =
-	   element app:workspace {
-	      appCommonAttributes,
-	      ( appCollection*
-	        & extensionElement* )
-	   }
-	atomTitle = element atom:title { atomTextConstruct }
-     */
-    public static class Workspace {
-        private String title       = null;
-        private String titleType   = null; // may be TEXT, HTML, XHTML
-        private Set    collections = new LinkedHashSet();
-        
-        public Workspace() {
-        }
-        
-        /** Iterate over collections in workspace */
-        public Iterator getCollections() {
-            return collections.iterator();
-        }
-        
-        /** Add new collection to workspace */
-        public void addCollection(AtomService.Collection col) {
-            collections.add(col);
-        }
-        
-        /** Workspace must have a human readable title */
-        public String getTitle() {
-            return title;
-        }
-        
-        public void setTitle(String title) {
-            this.title = title;
-        }
-
-        public String getTitleType() {
-            return titleType;
-        }
-
-        public void setTitleType(String titleType) {
-            this.titleType = titleType;
-        }
-    }
-    
-    /**
-     * This class models an Atom workspace collection.    
-     *//* 
-	appCollection =
-	   element app:collection {
-	      appCommonAttributes,
-	      attribute href { atomURI  },
-	      ( appAccept?	
-	        & appCategories*
-	        & extensionElement* )
-	   }
-     */
-    public static class Collection {
-        private String title = null;
-        private String titleType =null; // may be TEXT, HTML, XHTML
-        private String accept = "entry";
-        private String listTemplate = null;
-        private String href = null;
-        private Set categories = new LinkedHashSet(); // of Categories objects
-        
-        public Collection() {
-        }
-        
-        /**
-         * Comma separated list of media-ranges accepted by collection
-         * or "entry" to indicate Atom entries only. Leaving null will 
-         * default to entries only.
-         */
-        public String getAccept() {
-            return accept;
-        }
-        
-        public void setAccept(String accept) {
-            this.accept = accept;
-        }
-        
-        /** The URI of the collection */
-        public String getHref() {
-            return href;
-        }
-        
-        public void setHref(String href) {
-            this.href = href;
-        }
-        
-        /** Must have human readable title */
-        public String getTitle() {
-            return title;
-        }
-        
-        public void setTitle(String title) {
-            this.title = title;
-        }
-
-        public String getTitleType() {
-            return titleType;
-        }
-
-        public void setTitleType(String titleType) {
-            this.titleType = titleType;
-        }
-
-        /** Workspace can have multiple Categories objects */
-        public void addCategories(Categories cats) {
-            categories.add(cats);
-        }
-        
-        /** Iterate over Categories objects in Collection */
-        public Iterator getCategories() {
-            return categories.iterator();
-        }
-    }
-    
-    /** 
-     * Categories object contains Category objects 
-     *//*
-	 appInlineCategories =
-	    element app:categories {
-	        attribute fixed { "yes" | "no" }?,
-	        attribute scheme { atomURI }?,
-	        (atomCategory*)
-	    }
-     */
-    public static class Categories {
-        private Set categories = new LinkedHashSet(); // of Category objects
-        private String scheme = null;
-        private boolean fixed = false;
-        
-        /** Add category list of those specified*/
-        public void addCategory(Category cat) {
-            categories.add(cat);
-        }
-        
-        /** Iterate over Category objects */
-        public Iterator getCategories() {
-            return categories.iterator();
-        }
-
-        /** True if clients MUST use one of the categories specified */
-        public boolean isFixed() {
-            return fixed;
-        }
-
-        /** True if clients MUST use one of the categories specified */
-        public void setFixed(boolean fixed) {
-            this.fixed = fixed;
-        }
-
-        /** Category URI scheme to use for Categories without a scheme */
-        public String getScheme() {
-            return scheme;
+    public Workspace findWorkspace(String title) {
+        for (Iterator it = workspaces.iterator(); it.hasNext();) {
+            Workspace ws = (Workspace) it.next();
+            if (title.equals(ws.getTitle())) {
+                return ws;
+            }
         }
-
-        /** Category URI scheme to use for Categories without a scheme */
-        public void setScheme(String scheme) {
-            this.scheme = scheme;
-        }        
+        return null;
     }
-    
-      
-    /** 
-     * Represents an <atom:category> object 
-     *//*
-	    atomCategory =
-	    element atom:category {
-	       atomCommonAttributes,
-	       attribute term { text },
-	       attribute scheme { atomURI }?,
-	       attribute label { text }?,
-	       undefinedContent
-	    }
-     */
-    public static class Category {
-        private String term;
-        private String scheme;
-        private String label;                
-
-        public String getTerm() {
-            return term;
-        }
 
-        public void setTerm(String term) {
-            this.term = term;
-        }
-
-        public String getScheme() {
-            return scheme;
-        }
-
-        public void setScheme(String scheme) {
-            this.scheme = scheme;
-        }
-
-        public String getLabel() {
-            return label;
-        }
-
-        public void setLabel(String label) {
-            this.label = label;
-        }
-    }
-    
     /** Deserialize an Atom service XML document into an object */
     public static AtomService documentToService(Document document) {
         AtomService service = new AtomService();
         Element root = document.getRootElement();
-        List spaces = root.getChildren("workspace", ns);
+        List spaces = root.getChildren("workspace", ATOM_PROTOCOL);
         Iterator iter = spaces.iterator();
         while (iter.hasNext()) {
             Element e = (Element) iter.next();
-            service.addWorkspace(AtomService.elementToWorkspace(e));
+            service.addWorkspace(Workspace.elementToWorkspace(e));
         }
         return service;
     }
     
-    /** Serialize an AtomService object into an XML document */
+    /**
+     * Serialize an AtomService object into an XML document
+     */
     public static Document serviceToDocument(AtomService service) {
         Document doc = new Document();
-        Element root = new Element("service", ns);
+        Element root = new Element("service", ATOM_PROTOCOL);
         doc.setRootElement(root);
         Iterator iter = service.getWorkspaces().iterator();
         while (iter.hasNext()) {
-            AtomService.Workspace space = (AtomService.Workspace) iter.next();
-            root.addContent(AtomService.workspaceToElement(space));
+            Workspace space = (Workspace) iter.next();
+            root.addContent(Workspace.workspaceToElement(space));
         }
         return doc;
     }
-    
-    /** Deserialize a Atom workspace XML element into an object */
-    public static AtomService.Workspace elementToWorkspace(Element element) {
-        AtomService.Workspace space = new AtomService.Workspace();
-        
-        Element titleElem = element.getChild("title", atomns);
-        space.setTitle(titleElem.getText());
-        if (titleElem.getAttribute("type", atomns) != null) {
-            space.setTitleType(titleElem.getAttribute("type", atomns).getValue());
-        }
-        
-        List collections = element.getChildren("collection", ns);
-        Iterator iter = collections.iterator();
-        while (iter.hasNext()) {
-            Element e = (Element) iter.next();
-            space.addCollection(AtomService.elementToCollection(e));
-        }
-        return space;
-    }
-    
-    /** Serialize an AtomService.Workspace object into an XML element */
-    public static Element workspaceToElement(Workspace space) {
-        Element element = new Element("workspace", ns);
-        
-        Element title = new Element("title", atomns);
-        title.setText(space.getTitle());
-        element.addContent(title);
-        if (space.getTitleType() != null && !space.getTitleType().equals("TEXT")) {
-            element.setAttribute("type", space.getTitleType(), atomns);
-        }
-        
-        Iterator iter = space.getCollections();
-        while (iter.hasNext()) {
-            AtomService.Collection col = (AtomService.Collection) iter.next();
-            element.addContent(collectionToElement(col));
-        }
-        return element;
-    }
-    
-    /** Deserialize an Atom service collection XML element into an object */
-    public static AtomService.Collection elementToCollection(Element element) {
-        AtomService.Collection collection = new AtomService.Collection();
-        collection.setHref(element.getAttribute("href").getValue());
-        
-        Element titleElem = element.getChild("title", atomns);
-        if (titleElem != null) {
-            collection.setTitle(titleElem.getText());
-            if (titleElem.getAttribute("type", atomns) != null) {
-                collection.setTitleType(titleElem.getAttribute("type", atomns).getValue());
-            }
-        }
-                
-        Element memberType = element.getChild("accept",  ns);
-        if (memberType != null) {
-            collection.setAccept(memberType.getText());
-        }
-        
-        // Loop to parse <app:categories> element to Categories objects
-        List catsElems = element.getChildren("categories", ns);
-        for (Iterator catsIter = catsElems.iterator(); catsIter.hasNext();) {
-            Element catsElem = (Element) catsIter.next();  
-            Categories cats = new Categories();
-            if ("yes".equals(catsElem.getAttribute("fixed", ns))) {
-                cats.setFixed(true);
-            }
-            // Loop to parse <atom:category> elemenents to Category objects
-            List catElems = catsElem.getChildren("category", atomns);
-            for (Iterator catIter = catElems.iterator(); catIter.hasNext();) {                
-                Element catElem = (Element) catIter.next();
-                Category cat = new Category();
-                cat.setTerm(catElem.getAttributeValue("term", atomns));                
-                cat.setLabel(catElem.getAttributeValue("label", atomns)); 
-                cat.setScheme(catElem.getAttributeValue("scheme", atomns));
-                cats.addCategory(cat);
-            }
-            collection.addCategories(cats);
-        }
-        return collection;
-    }
-    
-    /** Serialize an AtomService.Collection object into an XML element */
-    public static Element collectionToElement(AtomService.Collection collection) {
-        Element element = new Element("collection", ns);
-        element.setAttribute("href", collection.getHref());
-                       
-        Element title = new Element("title", atomns);
-        title.setText(collection.getTitle());
-        element.addContent(title);
-        if (collection.getTitleType() != null && !collection.getTitleType().equals("TEXT")) {
-            element.setAttribute("type", collection.getTitleType(), atomns);
-        }
-                    
-        // Loop to create <app:categories> elements            
-        for (Iterator it = collection.getCategories(); it.hasNext();) {
-            Categories cats = (Categories)it.next();
-            Element catsElem = new Element("categories", ns);
-            catsElem.setAttribute("fixed", cats.isFixed() ? "yes" : "no", ns);
-            if (cats.getScheme() != null) {
-                catsElem.setAttribute("scheme", cats.getScheme(), ns);
-            }
-            // Loop to create <atom:category> elements
-            for (Iterator catIter = cats.getCategories(); catIter.hasNext();) {
-                Category cat = (Category) catIter.next();
-                Element catElem = new Element("category", atomns);
-                catElem.setAttribute("term", cat.getTerm(), atomns);
-                if (cat.getScheme() != null) { // optional
-                    catElem.setAttribute("scheme", cat.getScheme(), atomns);
-                }
-                if (cat.getLabel() != null) { // optional
-                    catElem.setAttribute("label", cat.getLabel(), atomns);
-                }
-                catsElem.addContent(catElem);
-            }
-            element.addContent(catsElem);
-        }
-        
-        Element memberType = new Element("accept", ns);
-        memberType.setText(collection.getAccept());
-        element.addContent(memberType);
-        
-        return element;
-    }
+
 }
 

Modified: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomServlet.java
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomServlet.java?view=diff&rev=552239&r1=552238&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomServlet.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/AtomServlet.java Sat Jun 30 20:30:00 2007
@@ -60,7 +60,7 @@
 public class AtomServlet extends HttpServlet {
     public static final String FEED_TYPE = "atom_1.0";
     
-    private static Log mLogger =
+    private static Log log =
             LogFactory.getFactory().getInstance(AtomServlet.class);
     
     //-----------------------------------------------------------------------------
@@ -70,6 +70,7 @@
      */
     private AtomHandler createAtomRequestHandler(HttpServletRequest request) 
     throws ServletException {
+        log.debug("Creating Atom handler");
         boolean enabled = RollerConfig.getBooleanProperty(
             "webservices.atomprotocol.enabled");
         if (!enabled) {
@@ -84,6 +85,7 @@
      */
     protected void doGet(HttpServletRequest req, HttpServletResponse res)
     throws ServletException, IOException { 
+        log.debug("Entering");
         AtomHandler handler = createAtomRequestHandler(req);
         String userName = handler.getAuthenticatedUsername();
         if (userName != null) {
@@ -93,7 +95,7 @@
                     // return an Atom Service document
                     AtomService service = handler.getIntrospection();
                     Document doc = AtomService.serviceToDocument(service);
-                    res.setContentType("application/atomserv+xml; charset=utf-8");
+                    res.setContentType("application/atomsvc+xml; charset=utf-8");
                     Writer writer = res.getWriter();
                     XMLOutputter outputter = new XMLOutputter();
                     outputter.setFormat(Format.getPrettyFormat());
@@ -130,16 +132,16 @@
                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                 }
             } catch (AtomException ae) {
-                res.setStatus(ae.getStatus());
-                mLogger.debug(ae);
-            } catch (Exception ae) {
-                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-                mLogger.debug(ae);
+                res.sendError(ae.getStatus(), ae.getMessage());
+            } catch (Exception e) {
+                res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+                log.debug(e);
             }
         } else {
             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
         }
+        log.debug("Exiting");
     }
     
     //-----------------------------------------------------------------------------
@@ -149,6 +151,7 @@
      */
     protected void doPost(HttpServletRequest req, HttpServletResponse res)
     throws ServletException, IOException {
+        log.debug("Entering");
         AtomHandler handler = createAtomRequestHandler(req);
         String userName = handler.getAuthenticatedUsername();
         if (userName != null) {
@@ -166,7 +169,7 @@
                         // call handler to post it
                         Entry savedEntry = handler.postEntry(pathInfo, unsavedEntry);
                         
-                        // return alternate link as Location header
+                        // return member entry URI as location header
                         Iterator links = savedEntry.getOtherLinks().iterator();
                         while (links.hasNext()) {
                             Link link = (Link) links.next();
@@ -187,7 +190,7 @@
                         String title = req.getHeader("Title");
                         String slug = req.getHeader("Slug");
 
-                        // hand input stream of to hander to post file
+                        // hand input stream off to hander to post file
                         Entry resource = handler.postMedia(
                             pathInfo, title, slug, req.getContentType(), req.getInputStream());
                         
@@ -195,7 +198,7 @@
                         com.sun.syndication.feed.atom.Content content = 
                             (com.sun.syndication.feed.atom.Content)resource.getContents().get(0);
 
-                        // return alternate link as Location header
+                        // return member entry URI as location header
                         Iterator links = resource.getOtherLinks().iterator();
                         while (links.hasNext()) {
                             Link link = (Link) links.next();
@@ -208,23 +211,25 @@
                         serializeEntry(resource, writer);
                         writer.close(); 
                     } else {
-                        res.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
+                        res.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE,
+                                "No content-type specified in request");
                     }
                     
                 } else {
-                    res.setStatus(HttpServletResponse.SC_NOT_FOUND);
+                    res.sendError(HttpServletResponse.SC_NOT_FOUND,
+                            "Invalid collection specified in request");
                 }
             } catch (AtomException ae) {
-                res.setStatus(ae.getStatus());
-                mLogger.debug(ae);
-            } catch (Exception ae) {
-                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-                mLogger.debug(ae);
+                res.sendError(ae.getStatus(), ae.getMessage());
+            } catch (Exception e) {
+                res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+                log.debug(e);
             }
         } else {
             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
         }
+        log.debug("Exiting");
     }
     
     //-----------------------------------------------------------------------------
@@ -234,6 +239,7 @@
      */
     protected void doPut(HttpServletRequest req, HttpServletResponse res)
     throws ServletException, IOException {
+        log.debug("Entering");
         AtomHandler handler = createAtomRequestHandler(req);
         String userName = handler.getAuthenticatedUsername();
         if (userName != null) {
@@ -273,16 +279,16 @@
                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                 }
             } catch (AtomException ae) {
-                res.setStatus(ae.getStatus());
-                mLogger.debug(ae);
-            } catch (Exception ae) {
-                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-                mLogger.debug(ae);
+                res.sendError(ae.getStatus(), ae.getMessage());
+            } catch (Exception e) {
+                res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+                log.debug(e);
             }
         } else {
             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
         }
+        log.debug("Exiting");
     }
     
     //-----------------------------------------------------------------------------
@@ -291,6 +297,7 @@
      */
     protected void doDelete(HttpServletRequest req, HttpServletResponse res)
     throws ServletException, IOException {
+        log.debug("Entering");
         AtomHandler handler = createAtomRequestHandler(req);
         String userName = handler.getAuthenticatedUsername();
         if (userName != null) {
@@ -304,16 +311,16 @@
                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                 }
             } catch (AtomException ae) {
-                res.setStatus(ae.getStatus());
-                mLogger.debug(ae);
-            } catch (Exception ae) {
-                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-                mLogger.debug(ae);
+                res.sendError(ae.getStatus(), ae.getMessage());
+            } catch (Exception e) {
+                res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+                log.debug(e);
             }
         } else {
             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
         }
+        log.debug("Exiting");
     }
     
     //-----------------------------------------------------------------------------
@@ -345,24 +352,22 @@
         // Grab entry element from feed and get JDOM to serialize it
         Element entryElement= (Element)feedDoc.getRootElement().getChildren().get(0);
         
-        // Add our own namespaced element, so we can determine if we can 
-        // count on client to preserve foreign markup as it should.
         Element rollerElement = new Element("atom-draft", 
-            "http://rollerweblogger.org/namespaces/app");
-        rollerElement.setText("9");
+            "http://roller.apache.org/namespaces/app");
+        rollerElement.setText("14");
         entryElement.addContent(rollerElement);
         
         XMLOutputter outputter = new XMLOutputter();
         outputter.setFormat(Format.getPrettyFormat());
         
-        if (mLogger.isDebugEnabled()) {
+        if (log.isDebugEnabled()) {
             StringWriter sw = new StringWriter();
             outputter.output(entryElement, sw); 
-            mLogger.debug(sw.toString());
+            log.debug(sw.toString());
             writer.write(sw.toString()); 
         } else {
             outputter.output(entryElement, writer);
-        }        
+        } 
     }
     
     /**
@@ -383,15 +388,13 @@
         Document feedDoc = wireFeedOutput.outputJDom(feed);
         feedDoc.getRootElement().addContent(fetchedEntryElement);
         
-        // Check for our special namespaced element. If it's there, then we 
-        // know that client is not preserving foreign markup.
         Namespace ns = Namespace.getNamespace(
-            "http://rollerweblogger.org/namespaces/app");
+            "http://roller.apache.org/namespaces/app");
         Element rollerElement = fetchedEntryElement.getChild("atom-draft", ns);
         if (rollerElement == null) {
-            mLogger.debug("Client is NOT preserving foreign markup");
+            log.debug("Client is NOT preserving foreign markup");
         }
-        
+                
         WireFeedInput input = new WireFeedInput();
         Feed parsedFeed = (Feed)input.build(feedDoc);
         return (Entry)parsedFeed.getEntries().get(0);

Added: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Categories.java
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Categories.java?view=auto&rev=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Categories.java (added)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Categories.java Sat Jun 30 20:30:00 2007
@@ -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.roller.webservices.atomprotocol;
+
+import com.sun.syndication.feed.atom.Category;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/** 
+ * Categories object may contain Category objects 
+ *//*
+	 appInlineCategories =
+ element app:categories {
+     attribute fixed { "yes" | "no" }?,
+     attribute scheme { atomURI }?,
+     (atomCategory*)
+ }
+ */
+public class Categories {
+    private List categories = new ArrayList(); // of Category objects
+    private String scheme = null;
+    private boolean fixed = false;
+    
+    /** Add category list of those specified*/
+    public void addCategory(Category cat) {
+        categories.add(cat);
+    }
+    
+    /** Iterate over Category objects */
+    public List getCategories() {
+        return categories;
+    }
+
+    /** True if clients MUST use one of the categories specified */
+    public boolean isFixed() {
+        return fixed;
+    }
+
+    /** True if clients MUST use one of the categories specified */
+    public void setFixed(boolean fixed) {
+        this.fixed = fixed;
+    }
+
+    /** Category URI scheme to use for Categories without a scheme */
+    public String getScheme() {
+        return scheme;
+    }
+
+    /** Category URI scheme to use for Categories without a scheme */
+    public void setScheme(String scheme) {
+        this.scheme = scheme;
+    }
+
+}

Added: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Collection.java
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Collection.java?view=auto&rev=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Collection.java (added)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Collection.java Sat Jun 30 20:30:00 2007
@@ -0,0 +1,217 @@
+/*
+* 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.roller.webservices.atomprotocol;
+
+import com.sun.syndication.feed.atom.Category;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jdom.Element;
+
+
+/**
+ * This class models an Atom workspace collection.    
+ *//* 
+	appCollection =
+	   element app:collection {
+   appCommonAttributes,
+   attribute href { atomURI  },
+   ( appAccept?	
+     & appCategories*
+     & extensionElement* )
+	   }
+ */
+public class Collection {
+    private String title = null;
+    private String titleType = null; // may be TEXT, HTML, XHTML
+    private String accept = "entry";
+    private String listTemplate = null;
+    private String href = null;
+    private List categories = new ArrayList(); // of Categories objects    
+    
+    /**
+     * Collection MUST have title and href.
+     * @param title    Title for collection
+     * @param typeType Content type of title (null for plain text)
+     * @param href     Collection URI.
+     */
+    public Collection(String title, String titleType, String href) {
+        this.title = title;
+        this.titleType = titleType;
+        this.href = href;
+    }
+    
+    /**
+     * Comma separated list of media-ranges accepted by collection.
+     */
+    public String getAccept() {
+        return accept;
+    }
+    
+    public void setAccept(String accept) {
+        this.accept = accept;
+    }
+    
+    /** The URI of the collection */
+    public String getHref() {
+        return href;
+    }
+    
+    public void setHref(String href) {
+        this.href = href;
+    }
+    
+    /** Must have human readable title */
+    public String getTitle() {
+        return title;
+    }
+    
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getTitleType() {
+        return titleType;
+    }
+
+    public void setTitleType(String titleType) {
+        this.titleType = titleType;
+    }
+
+    /** Workspace can have multiple Categories objects */
+    public void addCategories(Categories cats) {
+        categories.add(cats);
+    }
+    
+    public List getCategories() {
+        return categories;
+    }
+    
+    /**
+     * Returns true if contentType is accepted by collection.
+     */
+    public boolean accepts(String ct) {
+        if (accept != null && accept.trim().equals("*/*")) return true;
+        String entryType = "application/atom+xml";
+        boolean entry = entryType.equals(ct);
+        if (entry && null == accept) {
+            return true;
+        } else if (entry && "entry".equals(accept)) {
+            return true;
+        } else if (entry && entryType.equals(accept)) {
+            return true;
+        } else {
+            String[] rules = accept.split(",");
+            for (int i=0; i<rules.length; i++) {
+                String rule = rules[i].trim();
+                if (rule.equals(ct)) return true;
+                int slashstar = rule.indexOf("/*");
+                if (slashstar > 0) {
+                    rule = rule.substring(0, slashstar + 1);
+                    if (ct.startsWith(rule)) return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Serialize an AtomService.Collection into an XML element
+     */
+    public static Element collectionToElement(Collection collection) {
+        Element element = new Element("collection", AtomService.ATOM_PROTOCOL);
+        element.setAttribute("href", collection.getHref());
+                       
+        Element title = new Element("title", AtomService.ATOM_FORMAT);
+        title.setText(collection.getTitle());
+        element.addContent(title);
+        if (collection.getTitleType() != null && !collection.getTitleType().equals("TEXT")) {
+            element.setAttribute("type", collection.getTitleType()); //, AtomService.ATOM_FORMAT);
+        }
+                    
+        // Loop to create <app:categories> elements            
+        for (Iterator it = collection.getCategories().iterator(); it.hasNext();) {
+            Categories cats = (Categories)it.next();
+            Element catsElem = new Element("categories", AtomService.ATOM_PROTOCOL);
+            catsElem.setAttribute("fixed", cats.isFixed() ? "yes" : "no"); //, AtomService.ATOM_PROTOCOL);
+            if (cats.getScheme() != null) {
+                catsElem.setAttribute("scheme", cats.getScheme()); //, AtomService.ATOM_PROTOCOL);
+            }
+            // Loop to create <atom:category> elements
+            for (Iterator catIter = cats.getCategories().iterator(); catIter.hasNext();) {
+                Category cat = (Category) catIter.next();
+                Element catElem = new Element("category", AtomService.ATOM_FORMAT);
+                catElem.setAttribute("term", cat.getTerm()); //, AtomService.ATOM_FORMAT);
+                if (cat.getScheme() != null) { // optional
+                    catElem.setAttribute("scheme", cat.getScheme()); //, AtomService.ATOM_FORMAT);
+                }
+                if (cat.getLabel() != null) { // optional
+                    catElem.setAttribute("label", cat.getLabel()); //, AtomService.ATOM_FORMAT);
+                }
+                catsElem.addContent(catElem);
+            }
+            element.addContent(catsElem);
+        }
+        
+        Element memberType = new Element("accept", AtomService.ATOM_PROTOCOL);
+        memberType.setText(collection.getAccept());
+        element.addContent(memberType);
+        
+        return element;
+    }
+    
+    /** Deserialize an Atom service collection XML element into an object */
+    public static Collection elementToCollection(Element element) {
+        String newHref = element.getAttribute("href").getValue();
+        Element titleElem = element.getChild("title", AtomService.ATOM_FORMAT);
+        String newTitle = titleElem.getText();
+        String newType = null;
+        if (titleElem.getAttribute("type", AtomService.ATOM_FORMAT) != null) {
+            newType = titleElem.getAttribute("type", AtomService.ATOM_FORMAT).getValue();
+        }
+        Collection collection = new Collection(newTitle, newType, newHref);
+                
+        Element memberType = element.getChild("accept",  AtomService.ATOM_PROTOCOL);
+        if (memberType != null) {
+            collection.setAccept(memberType.getText());
+        }
+        
+        // Loop to parse <app:categories> element to Categories objects
+        List catsElems = element.getChildren("categories", AtomService.ATOM_PROTOCOL);
+        for (Iterator catsIter = catsElems.iterator(); catsIter.hasNext();) {
+            Element catsElem = (Element) catsIter.next();  
+            Categories cats = new Categories();
+            if ("yes".equals(catsElem.getAttribute("fixed", AtomService.ATOM_PROTOCOL))) {
+                cats.setFixed(true);
+            }
+            // Loop to parse <atom:category> elemenents to Category objects
+            List catElems = catsElem.getChildren("category", AtomService.ATOM_FORMAT);
+            for (Iterator catIter = catElems.iterator(); catIter.hasNext();) {                
+                Element catElem = (Element) catIter.next();
+                Category cat = new Category();
+                cat.setTerm(catElem.getAttributeValue("term"));                
+                cat.setLabel(catElem.getAttributeValue("label")); 
+                cat.setScheme(catElem.getAttributeValue("scheme"));
+                cats.addCategory(cat);
+            }
+            collection.addCategories(cats);
+        }
+        return collection;
+    }
+
+}

Modified: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/RollerAtomHandler.java
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/RollerAtomHandler.java?view=diff&rev=552239&r1=552238&r2=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/RollerAtomHandler.java (original)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/RollerAtomHandler.java Sat Jun 30 20:30:00 2007
@@ -66,6 +66,7 @@
 import org.apache.roller.config.RollerRuntimeConfig;
 import org.apache.roller.business.WeblogManager;
 import org.apache.roller.pojos.RollerPropertyData;
+import org.apache.roller.pojos.WeblogEntryTagData;
 import org.apache.roller.pojos.WeblogResource;
 import org.apache.roller.util.URLUtilities;
 import org.apache.roller.util.cache.CacheManager;
@@ -180,34 +181,43 @@
             for (Iterator iter=perms.iterator(); iter.hasNext();) {
                 PermissionsData perm = (PermissionsData)iter.next();
                 String handle = perm.getWebsite().getHandle();
-                AtomService.Workspace workspace = new AtomService.Workspace();
-                workspace.setTitle(Utilities.removeHTML(perm.getWebsite().getName()));
+                Workspace workspace = new Workspace(
+                    Utilities.removeHTML(perm.getWebsite().getName()), "text");
                 service.addWorkspace(workspace);
                 
-                AtomService.Collection entryCol = new AtomService.Collection();
-                entryCol.setTitle("Weblog Entries");
+                Collection entryCol = new Collection("Weblog Entries", "text", 
+                    URLUtilities.getAtomProtocolURL(true)+"/"+handle+"/entries");
                 entryCol.setAccept("entry");
                 entryCol.setHref(URLUtilities.getAtomProtocolURL(true)+"/"+handle+"/entries");
                 try {                    
-                    AtomService.Categories cats = new AtomService.Categories();
+                    // Add fixed categories using scheme that points to 
+                    // weblog because categories are weblog specific
+                    Categories cats = new Categories();
                     cats.setFixed(true);
-                    cats.setScheme(URLUtilities.getWeblogURL(perm.getWebsite(), null, true));
+                    cats.setScheme(getWeblogCategoryScheme(perm.getWebsite()));
                     List rollerCats = mRoller.getWeblogManager().getWeblogCategories(perm.getWebsite(), false);
                     for (Iterator it = rollerCats.iterator(); it.hasNext();) {
                         WeblogCategoryData rollerCat = (WeblogCategoryData)it.next();
-                        AtomService.Category cat = new AtomService.Category();
-                        cat.setTerm(rollerCat.getPath());
+                        Category cat = new Category();
+                        cat.setTerm(rollerCat.getPath().substring(1));
                         cat.setLabel(rollerCat.getName());
                         cats.addCategory(cat);
                     } 
                     entryCol.addCategories(cats);
+                    
+                    // Add tags as free-form categories using scheme that points
+                    // to site because tags can be considered site-wide
+                    Categories tags = new Categories();
+                    tags.setFixed(false);
+                    entryCol.addCategories(tags);
+                    
                 } catch (Exception e) {
                     throw new AtomException("ERROR fetching weblog categories");
                 }                               
                 workspace.addCollection(entryCol);
                                 
-                AtomService.Collection uploadCol = new AtomService.Collection();
-                uploadCol.setTitle("Media Files");
+                Collection uploadCol = new Collection("Media Files", "text", 
+                    URLUtilities.getAtomProtocolURL(true)+"/"+handle+"/resources/");
                 uploadCol.setAccept(accept);
                 uploadCol.setHref(URLUtilities.getAtomProtocolURL(true)+"/"+handle+"/resources");
                 workspace.addCollection(uploadCol);
@@ -454,15 +464,21 @@
             if (canEdit(website)) {
                 // Save it and commit it
                 WeblogManager mgr = mRoller.getWeblogManager();
-                WeblogEntryData rollerEntry = createRollerEntry(website, entry);
+                WeblogEntryData rollerEntry = new WeblogEntryData();
+                rollerEntry.setWebsite(website);
                 rollerEntry.setCreator(this.user);
+                copyToRollerEntry(entry, rollerEntry);
                 mgr.saveWeblogEntry(rollerEntry);
                 mRoller.flush();
 
-                // Throttle one entry per second
-                // (MySQL timestamp has 1 sec resolution, damnit)
-                try { Thread.sleep(1000); } catch (Exception ignored) {}
-
+                // Throttle one entry per second per weblog because time-
+                // stamp in MySQL and other DBs has only 1 sec resolution
+                try { 
+                    synchronized (getClass()) { 
+                        Thread.sleep(1000); 
+                    }  
+                } catch (Exception ignored) {}  
+ 
                 CacheManager.invalidate(website);
                 if (rollerEntry.isPublished()) {
                     mRoller.getIndexManager().addEntryReIndexOperation(rollerEntry);
@@ -481,43 +497,37 @@
      * Retrieve entry, URI like this /blog-name/entry/id
      */
     public Entry getEntry(String[] pathInfo) throws AtomException {
+        mLogger.debug("Entering");
         try {
-            if (pathInfo.length == 3) // URI is /blogname/entries/entryid
+            if (pathInfo.length > 2) // URI is /blogname/entries/entryid
             {
                 if (pathInfo[1].equals("entry")) {
                     WeblogEntryData entry = 
                         mRoller.getWeblogManager().getWeblogEntry(pathInfo[2]);
                     if (entry == null) {
-                        throw new AtomNotFoundException(
-                            "ERROR: cannot find specified entry/resource");
+                        throw new AtomNotFoundException("Cannot find specified entry/resource");
                     }
                     if (!canView(entry)) {
-                        throw new AtomNotAuthorizedException(
-                            "ERROR: not authorized to view entry");
+                        throw new AtomNotAuthorizedException("Not authorized to view entry");
                     } else {
                         return createAtomEntry(entry);
                     }
-                } else if (pathInfo[1].equals("resource") && pathInfo[2].endsWith(".media-link")) {
-                    String fileName = 
-                        pathInfo[2].substring(0, pathInfo[2].length() - ".media-link".length());
+                } else if (pathInfo[1].equals("resource") && pathInfo[pathInfo.length - 1].endsWith(".media-link")) {
+                    String path = filePathFromPathInfo(pathInfo);                    
+                    String fileName = path.substring(0, path.length() - ".media-link".length());
                     String handle = pathInfo[0];
                     WebsiteData website = 
-                        mRoller.getUserManager().getWebsiteByHandle(handle);
+                        mRoller.getUserManager().getWebsiteByHandle(handle);                    
+                    WeblogResource resource = 
+                        mRoller.getFileManager().getFile(website, fileName);
                     
-                    // TODO: this must have broken with 3.0, but i don't know
-                    // how it's supposed to work so i can't really fix it
-                    // it's unlikely this was working properly before because
-                    // it was using an invalid path
-//                    File resource = 
-//                        new File("/resources" + File.separator + fileName);
-//                    return createAtomResourceEntry(website, resource);
-                    return null;
+                    mLogger.debug("Exiting");
+                    if (resource != null) return createAtomResourceEntry(website, resource);
                 }
             }
-            throw new AtomNotFoundException(
-                "ERROR: cannot find specified entry/resource");
+            throw new AtomNotFoundException("Cannot find specified entry/resource");
         } catch (RollerException re) {
-            throw new AtomException("ERROR: getting entry");
+            throw new AtomException("Getting entry");
         }
     }
     
@@ -536,18 +546,18 @@
                 }
                 if (canEdit(rollerEntry)) {
                     WeblogManager mgr = mRoller.getWeblogManager();
-
-                    WeblogEntryData rawUpdate = createRollerEntry(rollerEntry.getWebsite(), entry);
-                    rollerEntry.setPubTime(rawUpdate.getPubTime());
-                    rollerEntry.setUpdateTime(rawUpdate.getUpdateTime());
-                    rollerEntry.setText(rawUpdate.getText());
-                    rollerEntry.setStatus(rawUpdate.getStatus());
-                    rollerEntry.setCategory(rawUpdate.getCategory());
-                    rollerEntry.setTitle(rawUpdate.getTitle());
-
+                    copyToRollerEntry(entry, rollerEntry);
                     mgr.saveWeblogEntry(rollerEntry);
                     mRoller.flush();
 
+                    // Throttle one entry per second per weblog because time-
+                    // stamp in MySQL and other DBs has only 1 sec resolution
+                    try { 
+                        synchronized (getClass()) { 
+                            Thread.sleep(1000); 
+                        }  
+                    } catch (Exception ignored) {} 
+                    
                     CacheManager.invalidate(rollerEntry.getWebsite());
                     if (rollerEntry.isPublished()) {
                         mRoller.getIndexManager().addEntryReIndexOperation(rollerEntry);
@@ -591,12 +601,11 @@
                     }
                     if (canEdit(website) && pathInfo.length > 1) {
                         try {                            
-                            String fileName = pathInfo[2];
-                            if (pathInfo[2].endsWith(".media-link")) {
-                                fileName = fileName.substring(0, pathInfo[2].length() - ".media-link".length());
-                            }
+                            String path = filePathFromPathInfo(pathInfo);
+                            String fileName = path.substring(0, path.length() - ".media-link".length());
                             FileManager fmgr = mRoller.getFileManager();
                             fmgr.deleteFile(website, fileName);
+                            mLogger.debug("Deleted resource: " + fileName);
                         } catch (Exception e) {
                             String msg = "ERROR in atom.deleteResource";
                             mLogger.error(msg,e);
@@ -630,24 +639,30 @@
             File tempFile = null;
             RollerMessages msgs = new RollerMessages();
             String handle = pathInfo[0];
+            FileManager fmgr = mRoller.getFileManager();
             WebsiteData website =
                 mRoller.getUserManager().getWebsiteByHandle(handle);
             if (canEdit(website) && pathInfo.length > 1) {
-                // save to temp file
-                String fileName = createFileName(website, (slug != null) ? slug : title, contentType);
+                // Save to temp file
+                String fileName = createFileName(website, 
+                    (slug != null) ? slug : Utilities.replaceNonAlphanumeric(title,' '), contentType);
                 try {
-                    FileManager fmgr = mRoller.getFileManager();
                     tempFile = File.createTempFile(fileName, "tmp");
                     FileOutputStream fos = new FileOutputStream(tempFile);
                     Utilities.copyInputToOutput(is, fos);
                     fos.close();
-
-                    // Try saving file
-                    FileInputStream fis = new FileInputStream(tempFile);
-                    fmgr.saveFile(website, fileName, contentType, tempFile.length(), fis);
+                                        
+                    // Parse pathinfo to determine file path
+                    String path = filePathFromPathInfo(pathInfo);
+                    
+                    if (path.length() > 0) path = path + File.separator;
+                    FileInputStream fis = new FileInputStream(tempFile);  
+                    fmgr.saveFile(website, path + fileName, contentType, tempFile.length(), fis);
                     fis.close();
                     
-                    WeblogResource resource = fmgr.getFile(website, fileName);
+                    WeblogResource resource = 
+                        mRoller.getFileManager().getFile(website, fileName);                    
+                    
                     return createAtomResourceEntry(website, resource);
 
                 } catch (IOException e) {
@@ -695,7 +710,7 @@
      *    content-type  = "image/jpg"
      * Might result in daveblog-200608201034.jpg
      */
-    private String createFileName(WebsiteData weblog, String title, String contentType) {
+    private String createFileName(WebsiteData weblog, String slug, String contentType) {
         
         if (weblog == null) throw new IllegalArgumentException("weblog cannot be null");
         if (contentType == null) throw new IllegalArgumentException("contentType cannot be null");
@@ -709,10 +724,9 @@
         String[] typeTokens = contentType.split("/");
         String ext = typeTokens[1];
         
-        if (title != null && !title.trim().equals("")) {              
+        if (slug != null && !slug.trim().equals("")) {              
             // We've got a title, so use it to build file name
-            String base = Utilities.replaceNonAlphanumeric(title, ' ');
-            StringTokenizer toker = new StringTokenizer(base);
+            StringTokenizer toker = new StringTokenizer(slug);
             String tmp = null;
             int count = 0;
             while (toker.hasMoreTokens() && count < 5) {
@@ -936,19 +950,28 @@
      */
     private Entry createAtomEntry(WeblogEntryData entry) {
         Entry atomEntry = new Entry();
-        Content content = new Content();
-        content.setType(Content.HTML);
-        content.setValue(entry.getText());
-        List contents = new ArrayList();
-        contents.add(content);
         
         String absUrl = RollerRuntimeConfig.getAbsoluteContextURL();
         atomEntry.setId(        absUrl + entry.getPermaLink());
         atomEntry.setTitle(     entry.getTitle());
-        atomEntry.setContents(  contents);
         atomEntry.setPublished( entry.getPubTime());
         atomEntry.setUpdated(   entry.getUpdateTime());
         
+        Content content = new Content();
+        content.setType(Content.HTML);
+        content.setValue(entry.getText());
+        List contents = new ArrayList();
+        contents.add(content);
+        
+        atomEntry.setContents(contents);
+        
+        if (StringUtils.isNotEmpty(entry.getSummary())) {
+            Content summary = new Content();
+            summary.setType(Content.HTML);
+            summary.setValue(entry.getSummary());
+            atomEntry.setSummary(summary);
+        }
+        
         UserData creator = entry.getCreator();
         Person author = new Person();
         author.setName(         creator.getUserName());
@@ -958,7 +981,16 @@
         List categories = new ArrayList();
         Category atomCat = new Category();
         atomCat.setTerm(entry.getCategory().getPath());
+        atomCat.setScheme(getWeblogCategoryScheme(entry.getWebsite()));
         categories.add(atomCat);
+        
+        // Add Atom categories for each Weblogger tag with null scheme
+        for (Iterator tagit = entry.getTags().iterator(); tagit.hasNext();) {
+            WeblogEntryTagData tag = (WeblogEntryTagData) tagit.next(); 
+            Category newcat = new Category();
+            newcat.setTerm(tag.getName());
+            categories.add(newcat);
+        }        
         atomEntry.setCategories(categories);
         
         Link altlink = new Link();
@@ -978,10 +1010,10 @@
         atomEntry.setOtherLinks(otherlinks);
         
         List modules = new ArrayList();
-        PubControlModule pubControl = new PubControlModuleImpl();
-        pubControl.setDraft(
-                !WeblogEntryData.PUBLISHED.equals(entry.getStatus()));
-        modules.add(pubControl);
+        AppModule app = new AppModuleImpl();
+        app.setDraft(!WeblogEntryData.PUBLISHED.equals(entry.getStatus()));
+        app.setEdited(entry.getUpdateTime());
+        modules.add(app);
         atomEntry.setModules(modules);
         
         return atomEntry;
@@ -1031,14 +1063,20 @@
         contents.add(content);
         entry.setContents(contents);
         
+        List modules = new ArrayList();
+        AppModule app = new AppModuleImpl();
+        app.setDraft(false);
+        app.setEdited(entry.getUpdated());
+        modules.add(app);
+        entry.setModules(modules);
+        
         return entry;
     }
     
     /**
-     * Create a Roller weblog entry based on a Rome Atom entry object
+     * Copy fields from ROME entry to Weblogger entry.
      */
-    private WeblogEntryData createRollerEntry(WebsiteData website, Entry entry)
-    throws RollerException {
+    private void copyToRollerEntry(Entry entry, WeblogEntryData rollerEntry) throws RollerException {
         
         Timestamp current = new Timestamp(System.currentTimeMillis());
         Timestamp pubTime = current;
@@ -1047,51 +1085,84 @@
             pubTime = new Timestamp( entry.getPublished().getTime() );
         }
         if (entry.getUpdated() != null) {
-            updateTime = new Timestamp( entry.getUpdated().getTime() );
+            updateTime = new Timestamp(entry.getUpdated().getTime());
         }
-        WeblogEntryData rollerEntry = new WeblogEntryData();
         rollerEntry.setTitle(entry.getTitle());
         if (entry.getContents() != null && entry.getContents().size() > 0) {
             Content content = (Content)entry.getContents().get(0);
             rollerEntry.setText(content.getValue());
         }
+        if (entry.getSummary() != null) {
+            rollerEntry.setSummary(entry.getSummary().getValue());
+        }
         rollerEntry.setPubTime(pubTime);
         rollerEntry.setUpdateTime(updateTime);
-        rollerEntry.setWebsite(website);
         
-        PubControlModule control =
-                (PubControlModule)entry.getModule("http://purl.org/atom/app#");
+        AppModule control =
+                (AppModule)entry.getModule(AppModule.URI);
         if (control!=null && control.getDraft()) {
             rollerEntry.setStatus(WeblogEntryData.DRAFT);
         } else {
             rollerEntry.setStatus(WeblogEntryData.PUBLISHED);
         }
-        
-        // Atom supports multiple cats, Roller supports one/entry
-        // so here we take accept the first category that exists
+                
+        // Process incoming categories:
+        // Atom categories with weblog-level scheme are Weblogger categories.
+        // Atom supports multiple cats, but Weblogger supports one/entry
+        // so here we take accept the first category that exists.
         List categories = entry.getCategories();
         if (categories != null && categories.size() > 0) {
             for (int i=0; i<categories.size(); i++) {
                 Category cat = (Category)categories.get(i);
-                // Caller has no way of knowing our categories, so be lenient here
-                String catString = cat.getTerm() != null ? cat.getTerm() : cat.getLabel();
-                if (catString != null) {
-                    WeblogCategoryData rollerCat =
+                
+                if (cat.getScheme() != null && cat.getScheme().equals(getWeblogCategoryScheme(rollerEntry.getWebsite()))) {                
+                    String catString = cat.getTerm();
+                    if (catString != null) {
+                        WeblogCategoryData rollerCat =
                             mRoller.getWeblogManager().getWeblogCategoryByPath(
-                            website, catString);
-                    if (rollerCat != null) {
-                        // Found a valid category, so break out
-                        rollerEntry.setCategory(rollerCat);
-                        break;
+                                rollerEntry.getWebsite(), catString);
+                        if (rollerCat != null) {
+                            // Found a valid category, so break out
+                            rollerEntry.setCategory(rollerCat);
+                            break;
+                        }
                     }
                 }
             }
         }
         if (rollerEntry.getCategory() == null) {
-            // no category? fall back to the default Blogger API category
-            rollerEntry.setCategory(website.getBloggerCategory());
+            // Didn't find a category? Fall back to the default Blogger API category.
+            rollerEntry.setCategory(rollerEntry.getWebsite().getBloggerCategory());
         }
-        return rollerEntry;
+        
+        // Now process incoming categories that are tags:
+        // Atom categories with no scheme are considered tags.
+        String tags = "";
+        if (categories != null && categories.size() > 0) {
+            for (int i=0; i<categories.size(); i++) {
+                Category cat = (Category)categories.get(i);            
+                if (cat.getScheme() == null) {
+                    tags = tags + " " + cat.getTerm();
+                }                
+            }
+        }
+        rollerEntry.setTagsAsString(tags);        
     }
     
+    private String getWeblogCategoryScheme(WebsiteData website) {
+        return URLUtilities.getWeblogURL(website, null, true);
+    }
+    
+    private String filePathFromPathInfo(String[] pathInfo) {
+        String path = "";
+        if (pathInfo.length > 2) {
+            for (int i = 2; i < pathInfo.length; i++) {
+                if (path.length() > 0)
+                    path = path + File.separator + pathInfo[i];
+                else
+                    path = pathInfo[i];
+            }
+        }
+        return path;
+    }
 }

Added: roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Workspace.java
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Workspace.java?view=auto&rev=552239
==============================================================================
--- roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Workspace.java (added)
+++ roller/branches/roller_3.1/src/org/apache/roller/webservices/atomprotocol/Workspace.java Sat Jun 30 20:30:00 2007
@@ -0,0 +1,133 @@
+/*
+* 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.roller.webservices.atomprotocol;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jdom.Element;
+
+
+/**
+ * This class models an Atom workspace.
+ * @author Dave Johnson
+ *//*
+	appWorkspace =
+	   element app:workspace {
+   appCommonAttributes,
+   ( appCollection*
+     & extensionElement* )
+	   }
+	atomTitle = element atom:title { atomTextConstruct }
+ */
+public class Workspace {
+    private String title = null;
+    private String titleType = null; // may be TEXT, HTML, XHTML
+    private List collections = new ArrayList(); 
+    
+    /**
+     * Collection MUST have title.
+     * @param title    Title for collection
+     * @param typeType Content type of title (null for plain text)
+     */
+    public Workspace(String title, String titleType) {
+        this.title = title;
+        this.titleType = titleType;
+    }
+    
+    /** Iterate over collections in workspace */
+    public List getCollections() {
+        return collections;
+    }
+    
+    /** Add new collection to workspace */
+    public void addCollection(Collection col) {
+        collections.add(col);
+    }
+    
+    /**
+     * DefaultWorkspace must have a human readable title
+     */
+    public String getTitle() {
+        return title;
+    }
+    
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getTitleType() {
+        return titleType;
+    }
+
+    public void setTitleType(String titleType) {
+        this.titleType = titleType;
+    }
+    
+    public Collection findCollection(String title, String contentType) {
+        for (Iterator it = collections.iterator(); it.hasNext();) {
+            Collection col = (Collection) it.next();
+            if (title != null && col.accepts(contentType)) {
+                return col;
+            } else if (col.accepts(contentType)) {
+                return col;
+            }
+        }
+        return null;
+    }
+        
+    /** Deserialize a Atom workspace XML element into an object */
+    public static Workspace elementToWorkspace(Element element) {  
+        Element titleElem = element.getChild("title", AtomService.ATOM_FORMAT);        
+        String newTitle = titleElem.getText();
+        String newType = null;        
+        if (titleElem.getAttribute("type", AtomService.ATOM_FORMAT) != null) {
+            newType = titleElem.getAttribute("type", AtomService.ATOM_FORMAT).getValue();
+        }
+        Workspace space = new Workspace(newTitle, newType);
+        List collections = element.getChildren("collection", AtomService.ATOM_PROTOCOL);
+        Iterator iter = collections.iterator();
+        while (iter.hasNext()) {
+            Element e = (Element) iter.next();
+            space.addCollection(Collection.elementToCollection(e));
+        }
+        return space;
+    }
+    
+    /**
+     * Serialize an AtomService.DefaultWorkspace object into an XML element
+     */
+    public static Element workspaceToElement(Workspace space) {
+        Element element = new Element("workspace", AtomService.ATOM_PROTOCOL);
+        
+        Element title = new Element("title", AtomService.ATOM_FORMAT);
+        title.setText(space.getTitle());
+        element.addContent(title);
+        if (space.getTitleType() != null && !space.getTitleType().equals("TEXT")) {
+            title.setAttribute("type", space.getTitleType()); //, AtomService.ATOM_FORMAT);
+        }
+        
+        Iterator iter = space.getCollections().iterator();
+        while (iter.hasNext()) {
+            Collection col = (Collection) iter.next();
+            element.addContent(Collection.collectionToElement(col));
+        }
+        return element;
+    }
+
+}

Modified: roller/branches/roller_3.1/web/WEB-INF/classes/rome.properties
URL: http://svn.apache.org/viewvc/roller/branches/roller_3.1/web/WEB-INF/classes/rome.properties?view=diff&rev=552239&r1=552238&r2=552239
==============================================================================
--- roller/branches/roller_3.1/web/WEB-INF/classes/rome.properties (original)
+++ roller/branches/roller_3.1/web/WEB-INF/classes/rome.properties Sat Jun 30 20:30:00 2007
@@ -54,9 +54,9 @@
                                   
 # Handle Atom Pub Protocol pubcontrol extension
                                       
-atom_1.0.item.ModuleParser.classes   =org.apache.roller.webservices.atomprotocol.PubControlModuleParser
+atom_1.0.item.ModuleParser.classes   =org.apache.roller.webservices.atomprotocol.AppModuleParser
 
-atom_1.0.item.ModuleGenerator.classes =org.apache.roller.webservices.atomprotocol.PubControlModuleGenerator
+atom_1.0.item.ModuleGenerator.classes =org.apache.roller.webservices.atomprotocol.AppModuleGenerator