roller-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From snoopd...@apache.org
Subject svn commit: r375629 [1/2] - in /incubator/roller/trunk/sandbox/atomadminprotocol: ./ src/ src/org/ src/org/roller/ src/org/roller/presentation/ src/org/roller/presentation/atomadminapi/ test/
Date Tue, 07 Feb 2006 15:37:04 GMT
Author: snoopdave
Date: Tue Feb  7 07:37:00 2006
New Revision: 375629

URL: http://svn.apache.org/viewcvs?rev=375629&view=rev
Log:
Jeff Blattman's Atom Admin Publishing Protocol (AAPP)

Added:
    incubator/roller/trunk/sandbox/atomadminprotocol/
    incubator/roller/trunk/sandbox/atomadminprotocol/issues.txt
    incubator/roller/trunk/sandbox/atomadminprotocol/src/
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminService.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminServlet.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Authenticator.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/BasicAuthenticator.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Entry.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/EntrySet.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Handler.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/IntrospectionHandler.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntry.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntrySet.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerMemberHandler.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerUserHandler.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerWeblogHandler.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntry.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntrySet.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WSSEAuthenticator.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WSSEUtilities.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WeblogEntry.java
    incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WeblogEntrySet.java
    incubator/roller/trunk/sandbox/atomadminprotocol/test/
    incubator/roller/trunk/sandbox/atomadminprotocol/test/member-test1.xml
    incubator/roller/trunk/sandbox/atomadminprotocol/test/member-test2.xml
    incubator/roller/trunk/sandbox/atomadminprotocol/test/user-test1.xml
    incubator/roller/trunk/sandbox/atomadminprotocol/test/user-test2.xml
    incubator/roller/trunk/sandbox/atomadminprotocol/test/weblog-test1.xml
    incubator/roller/trunk/sandbox/atomadminprotocol/test/weblog-test2.xml

Added: incubator/roller/trunk/sandbox/atomadminprotocol/issues.txt
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/issues.txt?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/issues.txt (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/issues.txt Tue Feb  7 07:37:00 2006
@@ -0,0 +1,10 @@
+1. users are currently returned including their plain-text password. this is 
+probably not the correct thing to do.
+
+2. when users are posted, their plain text password is passed in the request.
+should the password be encrypted in the client / decrypted by the server?
+
+3. to avoid depending on another sandboxed component, auth utilities
+are copied from atomprotocol. there is opportunity to re-use that code,
+if it can be re-factored.
+

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminService.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminService.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminService.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminService.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,137 @@
+/*
+ * AtomAdminService.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.Namespace;
+import org.jdom.filter.Filter;
+
+/**
+ * This class describes an AAPP introspection document.
+ * An AtomAdminService is a set of workspaces, which is a set of
+ * collections.
+ *
+ * @author jtb
+ */
+
+class AtomAdminService extends EntrySet {
+    static class Workspace extends EntrySet {
+        public static interface Attributes {
+            public static final String TITLE = "title";
+        }
+        
+        private String title = null;
+        
+        public Workspace() {
+        }
+        
+        public String getType() {
+            return Types.WORKSPACE;
+        }
+        
+        public String getTitle() {
+            return title;
+        }
+        
+        public void setTitle(String title) {
+            this.title = title;
+        }
+        
+        
+        public Document toDocument() {
+            Document doc = new Document();
+            Element element = new Element(EntrySet.Types.WORKSPACE, NAMESPACE);
+            doc.setRootElement(element);
+            
+            element.setAttribute(Attributes.TITLE, getTitle());
+            for (int i = 0; i < getEntries().length; i++) {
+                Entry entry = getEntries()[i];
+                element.addContent(entry.toDocument().detachRootElement());
+            }
+            
+            return doc;
+        }
+    }
+    
+    public static class WorkspaceCollection extends Entry {
+        public static interface Tags {
+            public static final String MEMBER_TYPE = "member-type";
+        }
+        
+        public static interface Attributes {
+            public static final String TITLE = "title";
+        }
+        
+        private String title;
+        private String memberType;
+        
+        public WorkspaceCollection() {
+        }
+        
+        public String getType() {
+            return Types.COLLECTION;
+        }
+        
+        public String getTitle() {
+            return title;
+        }
+        
+        public void setTitle(String title) {
+            this.title = title;
+        }
+        
+        
+        public Document toDocument() {
+            Document doc = new Document();
+            Element element = new Element(Types.COLLECTION, NAMESPACE);
+            doc.setRootElement(element);
+            
+            element.setAttribute(Attributes.TITLE, getTitle());
+            element.setAttribute(Entry.Attributes.HREF, getHref());
+            
+            Element memberType = new Element(Tags.MEMBER_TYPE, NAMESPACE);
+            memberType.setText(getMemberType());
+            element.addContent(memberType);
+            
+            return doc;
+        }
+        
+        public String getMemberType() {
+            return memberType;
+        }
+        
+        public void setMemberType(String memberType) {
+            this.memberType = memberType;
+        }
+        
+    }
+    
+    public AtomAdminService(String href) {
+        setHref(href);
+    }
+    
+    public String getType() {
+        return Types.SERVICE;
+    }
+    
+    public Document toDocument() {
+        Document doc = new Document();
+        Element root = new Element(Types.SERVICE, NAMESPACE);
+        doc.setRootElement(root);
+        
+        for (int i = 0; i < getEntries().length; i++) {
+            Entry entry = getEntries()[i];
+            root.addContent(entry.toDocument().detachRootElement());
+        }
+        
+        return doc;
+    }
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminServlet.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminServlet.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/AtomAdminServlet.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2005 David M Johnson (For RSS and Atom In Action)
+ *
+ * Licensed 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.
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Writer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jdom.Document;
+import org.jdom.output.XMLOutputter;
+import org.jdom.output.Format;
+
+/**
+ * Atom Admin Servlet implements the Atom Admin endpoint.
+ * This servlet simply delegates work to a particular handler object.
+ *
+ * @web.servlet name="AtomAdminServlet"
+ * @web.servlet-mapping url-pattern="/aapp/*"
+ *
+ * @author jtb
+ */
+public class AtomAdminServlet extends HttpServlet {
+    private static Log logger = LogFactory.getFactory().getInstance(AtomAdminServlet.class);
+    
+    /**
+     * Handles an Atom GET by calling handler and writing results to response.
+     */
+    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+        try {
+            Handler handler = Handler.getHandler(req);
+            String userName = handler.getUsername();
+            if (userName == null) {
+                res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                return;
+            }
+            
+            EntrySet c = handler.processGet();
+            Document doc = c.toDocument();
+            
+            res.setContentType("application/xml; charset=utf8");
+            Writer writer = res.getWriter();
+            XMLOutputter outputter = new XMLOutputter();
+            outputter.setFormat(Format.getPrettyFormat());
+            outputter.output(doc, writer);
+            writer.close();
+            
+            res.setStatus(HttpServletResponse.SC_OK);
+        } catch (Exception e) {
+            res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            e.printStackTrace(res.getWriter());
+            logger.error(e);
+        }
+    }
+    
+    /**
+     * Handles an Atom POST by calling handler to identify URI, reading/parsing
+     * data, calling handler and writing results to response.
+     */
+    protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+        try {
+            Handler handler = Handler.getHandler(req);
+            String userName = handler.getUsername();
+            if (userName == null) {
+                res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                return;
+            }
+            
+            EntrySet c = handler.processPost(new InputStreamReader(req.getInputStream()));
+            Document doc = c.toDocument();
+            
+            
+            res.setContentType("application/xml; charset=utf8");
+            Writer writer = res.getWriter();
+            XMLOutputter outputter = new XMLOutputter();
+            outputter.setFormat(Format.getPrettyFormat());
+            outputter.output(doc, writer);
+            writer.close();
+            
+            res.setStatus(HttpServletResponse.SC_OK);
+        } catch (Exception e) {
+            res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            e.printStackTrace(res.getWriter());
+            logger.error(e);
+        }
+    }
+    
+    /**
+     * Handles an Atom PUT by calling handler to identify URI, reading/parsing
+     * data, calling handler and writing results to response.
+     */
+    protected void doPut(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+        try {
+            Handler handler = Handler.getHandler(req);
+            String userName = handler.getUsername();
+            if (userName == null) {
+                res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                return;
+            }
+            
+            EntrySet c = handler.processPut(new InputStreamReader(req.getInputStream()));
+            Document doc = c.toDocument();
+            
+            res.setContentType("application/xml; charset=utf8");
+            Writer writer = res.getWriter();
+            XMLOutputter outputter = new XMLOutputter();
+            outputter.setFormat(Format.getPrettyFormat());
+            outputter.output(doc, writer);
+            writer.close();
+            
+            res.setStatus(HttpServletResponse.SC_OK);
+        } catch (Exception e) {
+            res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            e.printStackTrace(res.getWriter());
+            logger.error(e);
+        }
+    }
+    
+    /**
+     * Handle Atom DELETE by calling appropriate handler.
+     */
+    protected void doDelete(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
+        try {
+            Handler handler = Handler.getHandler(req);
+            String userName = handler.getUsername();
+            if (userName == null) {
+                res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+                return;
+            }
+            
+            EntrySet es = handler.processDelete();
+            Document doc = es.toDocument();
+            
+            res.setContentType("application/xml; charset=utf8");
+            Writer writer = res.getWriter();
+            XMLOutputter outputter = new XMLOutputter();
+            outputter.setFormat(Format.getPrettyFormat());
+            outputter.output(doc, writer);
+            writer.close();
+            
+            res.setStatus(HttpServletResponse.SC_OK);            
+        } catch (Exception e) {
+            res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            e.printStackTrace(res.getWriter());
+            logger.error(e);
+        }
+    }
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Authenticator.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Authenticator.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Authenticator.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Authenticator.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2005 David M Johnson (For RSS and Atom In Action)
+ *
+ * Licensed 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.
+ */
+package org.roller.presentation.atomadminapi;
+
+import javax.servlet.http.HttpServletRequest;
+import org.roller.model.Roller;
+import org.roller.model.RollerFactory;
+
+/**
+ * TODO
+ *
+ * @author jtb
+ */
+abstract class Authenticator {   
+    private HttpServletRequest request;
+    private Roller             roller;
+    private String             userId;
+    
+    /** Creates a new instance of HttpBasicAuthenticator */
+    public Authenticator(HttpServletRequest req) {
+        setRequest(req);
+        setRoller(RollerFactory.getRoller());
+    }
+    
+    public abstract boolean authenticate();    
+
+    public HttpServletRequest getRequest() {
+        return request;
+    }
+
+    protected void setRequest(HttpServletRequest request) {
+        this.request = request;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    protected void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    protected Roller getRoller() {
+        return roller;
+    }
+
+    protected void setRoller(Roller roller) {
+        this.roller = roller;
+    }
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/BasicAuthenticator.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/BasicAuthenticator.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/BasicAuthenticator.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/BasicAuthenticator.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2005 David M Johnson (For RSS and Atom In Action)
+ *
+ * Licensed 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.
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.util.StringTokenizer;
+import javax.servlet.http.HttpServletRequest;
+import com.sun.syndication.io.impl.Base64;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.model.Roller;
+import org.roller.pojos.UserData;
+import org.roller.presentation.RollerContext;
+
+/**
+ * This class implements HTTP basic authentication for roller.
+ *
+ * @author jtb
+ */
+class BasicAuthenticator extends Authenticator {
+    private static Log logger = LogFactory.getFactory().getInstance(BasicAuthenticator.class);
+ 
+    /** Creates a new instance of HttpBasicAuthenticator */
+    public BasicAuthenticator(HttpServletRequest req) {
+        super(req);
+    }
+       
+    public boolean authenticate() {
+        boolean valid = false;
+        String id = null;
+        String password = null;
+        try {
+            String authHeader = getRequest().getHeader("Authorization");
+            if (authHeader != null) {
+                StringTokenizer st = new StringTokenizer(authHeader);
+                if (st.hasMoreTokens()) {
+                    String basic = st.nextToken();
+                    if (basic.equalsIgnoreCase("Basic")) {
+                        String credentials = st.nextToken();
+                        String userPass = new String(Base64.decode(credentials));
+                        int p = userPass.indexOf(":");
+                        if (p != -1) {
+                            id = userPass.substring(0, p);
+                            UserData user = getRoller().getUserManager().getUser(id);
+                            String realpassword = user.getPassword();
+                            password = userPass.substring(p+1);
+                            if (    (id.trim().equals(user.getUserName()))
+                            && (password.trim().equals(realpassword))) {
+                                valid = true;
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) { //TODO: not good to be catching "Exception"
+            logger.debug(e);
+        }        
+        if (valid) { 
+            setUserId(id);
+        } else {
+            // clear out old value, if second call
+            setUserId(null); 
+        }
+        return valid;
+    }
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Entry.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Entry.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Entry.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Entry.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,48 @@
+/*
+ * Entry.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+
+package org.roller.presentation.atomadminapi;
+
+import org.jdom.Document;
+import org.jdom.Namespace;
+
+/**
+ * This class is the abstract notion of an entry.
+ * Weblog resources are represented by sets of entries. 
+ *
+ * @author jtb
+ */
+abstract class Entry {
+    protected static final Namespace NAMESPACE = Namespace.getNamespace("http://purl.org/atom/aapp#");   
+    
+    /** Entry types. */
+    static interface Types {
+        public static final String USER = "user";
+        public static final String WEBLOG = "weblog";
+        public static final String MEMBER = "member";
+        public static final String COLLECTION = "collection";
+    }    
+       
+    /** XML attributes common to all entry types. */
+    public static interface Attributes {
+        public static final String HREF = "href";
+    }     
+        
+    private String href = null;    
+    
+    /** Get the HREF that identifies this entry. */
+    public String getHref() {
+        return href;
+    }
+
+    /** Set the HREF that identifies this entry. */
+    public void setHref(String href) {
+        this.href = href;
+    }    
+    
+    /** This entry, as a JDOM Document object. */
+    public abstract Document toDocument();    
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/EntrySet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/EntrySet.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/EntrySet.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/EntrySet.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,85 @@
+/*
+ * EntrySet.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+
+package org.roller.presentation.atomadminapi;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.jar.Attributes;
+import org.jdom.Document;
+import org.jdom.Element;
+
+/**
+ * This class is the abstract notion of a set of entries.
+ * Weblog resources are represented by sets of entries. 
+ *
+ * @author jtb
+ */
+abstract class EntrySet extends Entry {
+    /** Entry set types. */
+    static interface Types {
+        /*
+         * Set of user entries. 
+         * A user entry describes a user of the weblog server.
+         */
+        public static final String USERS = "users";
+        /** 
+         * Set of weblog entries. 
+         * Note that this is not a set of entries in a weblog, but rather,
+         * a set of entries that describe the weblog itself.
+         */
+        public static final String WEBLOGS = "weblogs";
+        /** 
+         * Set of member entries.
+         * A member entry describes a user's membership to and 
+         * permission with a particular weblog.
+         */
+        public static final String MEMBERS = "members";
+         /**
+          * Set of workspace entries.
+          * This type, along with WORKSPACE and COLLECTION, define
+          * the element that describe the introspection document
+          * for the AAPP service.
+          * <p>
+          * A service is a set of workspaces, and a workspace is a set of 
+          * collections.
+          */
+        public static final String SERVICE = "service";        
+        /** Set of collection entries. */
+        public static final String WORKSPACE = "workspace";           
+    }
+    
+    private List entries = null;
+        
+    /** Get the type of this object. */
+    public abstract String getType();
+    
+    /** Get the entries in this object. */
+    public Entry[] getEntries() {
+        return (Entry[])entries.toArray(new Entry[0]);
+    }
+    
+    /** Set the entries of this object. */
+    public void setEntries(Entry[] entryArray) {
+        entries = Arrays.asList(entryArray);
+    }
+    
+    /** This object as a JDOM Document */
+    public Document toDocument() {
+        Element e = new Element(getType(), NAMESPACE);
+        Document doc = new Document(e);
+        
+        // href
+        e.setAttribute(Attributes.HREF, getHref());
+        
+        // entries
+        for (int i = 0; i < getEntries().length; i++) {
+            e.addContent(getEntries()[i].toDocument().detachRootElement());
+        }
+        
+        return doc;
+    }    
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Handler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Handler.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Handler.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/Handler.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,185 @@
+/*
+ * Handler.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.io.Reader;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jdom.Namespace;
+import org.roller.RollerException;
+import org.roller.model.Roller;
+import org.roller.model.RollerFactory;
+import org.roller.pojos.UserData;
+import org.roller.presentation.RollerContext;
+import org.roller.util.StringUtils;
+
+/**
+ * This class is the abstract notion of an AAPP request handler.
+ * It processes HTTP requests for each of the four HTTP verbs:
+ * GET, POST, PUT, DELETE, for a given weblog resource. 
+ *
+ * @author jtb
+ */
+abstract class Handler {
+    protected static final String ENDPOINT = "/aapp";
+    
+    static class URI {
+        private String type;
+        private String[] entryIds;
+        
+        public URI(HttpServletRequest request) {
+            String pathInfo = request.getPathInfo();
+            pathInfo = (pathInfo!=null) ? pathInfo : "";
+            String[] elements = StringUtils.split(pathInfo,"/");
+            
+            if (elements.length > 0) {
+                type = elements[0];
+            }
+            if (elements.length > 1) {
+                entryIds = new String[elements.length-1];
+                System.arraycopy(elements, 1, entryIds, 0, entryIds.length);
+            }
+        }
+        
+        public String getType() {
+            return type;
+        }        
+        
+        public String[] getEntryIds() {
+            return entryIds;
+        }
+        
+        public String getEntryId() {
+            if (getEntryIds() == null) {
+                return null;
+            }
+            if (getEntryIds().length == 0) {
+                return null;
+            }
+            return getEntryIds()[0];
+        }
+        
+        public boolean isIntrospection() {
+            return getEntryId() == null && type == null;
+        }
+        
+        public boolean isCollection() {
+            return getEntryId() == null && type != null;
+        }
+        
+        public boolean isEntry() {
+            return getEntryId() != null && type != null;
+        }
+    }    
+    
+    protected static final Log logger = LogFactory.getFactory().getInstance(Handler.class);
+    
+    private HttpServletRequest request;
+    private Roller roller;
+    private RollerContext rollerContext;    
+    private String username;
+    private URI uri;
+    private String urlPrefix;
+    
+    /** Get a Handler object implementation based on the given request. */
+    public static Handler getHandler(HttpServletRequest req) throws Exception {
+         URI uri = new URI(req);
+         Handler handler;
+         
+         if (uri.isIntrospection()) {
+             handler = new IntrospectionHandler(req);
+         } else if (uri.isCollection() || uri.isEntry()) {
+             String type = uri.getType();
+             if (type.equals(EntrySet.Types.WEBLOGS)) {
+                 handler = new RollerWeblogHandler(req);
+             } else if (type.equals(EntrySet.Types.USERS)) {
+                 handler = new RollerUserHandler(req); 
+             } else if (type.equals(EntrySet.Types.MEMBERS)) {
+                 handler = new RollerMemberHandler(req);                  
+             } else {
+                 throw new Exception("ERROR: Unknown type: " + uri.getType());
+             }
+         } else {
+             throw new Exception("ERROR: Unknown URI type");
+         }
+    
+         return handler;
+    }
+    
+    public Handler(HttpServletRequest request) {
+        this.request = request;
+        this.uri = new URI(request);
+        this.rollerContext = RollerContext.getRollerContext();
+        this.roller = RollerFactory.getRoller();
+        this.urlPrefix = getRollerContext().getAbsoluteContextUrl(getRequest()) + ENDPOINT;        
+        
+        // TODO: decide what to do about authentication, is WSSE going to fly?
+        //Authenticator auth = new WSSEAuthenticator(request);
+        Authenticator auth = new BasicAuthenticator(request);
+        
+        //
+        // if this results in username not being set, then the client code
+        // should understand that means failed authentication
+        //
+        
+        if (auth.authenticate()) {
+            try {
+                UserData user = getRoller().getUserManager().getUser(auth.getUserId());
+                if (user != null && user.hasRole("admin") && user.getEnabled().booleanValue()) {
+                    // success!
+                    getRoller().setUser(user);
+                    username = auth.getUserId();
+                } else {
+                    logger.warn("WARN: Is not global admin user: " + user.getUserName());
+                }
+            } catch (RollerException re) {
+                logger.error("ERROR: Could not create RollerAtomAdminHandler", re);
+            }
+        } else {
+            logger.warn("WARN: Authentication failed");
+        }
+       
+    }
+    
+    /**
+     * Get the authenticated user name.
+     * If this method returns null, then authentication has failed.
+     */
+    public String getUsername() {
+        return username;
+    }   
+    
+    /** Process an HTTP GET request. */
+    public abstract EntrySet processGet() throws Exception;
+    /** Process an HTTP POST request. */
+    public abstract EntrySet processPost(Reader r) throws Exception;
+    /** Process an HTTP PUT request. */
+    public abstract EntrySet processPut(Reader r) throws Exception;
+    /** Process an HTTP DELETE request. */
+    public abstract EntrySet processDelete() throws Exception;
+    
+    protected URI getUri() {
+        return uri;
+    }
+
+    protected HttpServletRequest getRequest() {
+        return request;
+    }
+
+    protected RollerContext getRollerContext() {
+        return rollerContext;
+    }
+
+    protected Roller getRoller() {
+        return roller;
+    }
+
+    protected String getUrlPrefix() {
+        return urlPrefix;
+    }
+}
+

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/IntrospectionHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/IntrospectionHandler.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/IntrospectionHandler.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/IntrospectionHandler.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,78 @@
+/*
+ * IntrospectionHandler.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * This class handles requests for the AAPP introspection document.
+ * It only processes HTTP GET requests.
+ *
+ * @author jtb
+ */
+class IntrospectionHandler extends Handler {   
+    public IntrospectionHandler(HttpServletRequest request) {
+        super(request);
+    }
+    
+    public EntrySet processGet() throws Exception {
+        if (getUri().isIntrospection()) {
+            return getIntrospection(getRequest());
+        } else {
+            throw new Exception("ERROR: Unknown GET URI type");
+        }
+    }
+    
+    public EntrySet processPost(Reader r) {
+        throw new UnsupportedOperationException("ERROR: POST not supported in this handler");
+    }
+    
+    public EntrySet processPut(Reader r) {
+        throw new UnsupportedOperationException("ERROR: PUT not supported in this handler");
+    }
+    
+    public EntrySet processDelete() {
+        throw new UnsupportedOperationException("ERROR: DELETE not supported in this handler");
+    }
+    
+    private AtomAdminService getIntrospection(HttpServletRequest req) throws Exception {
+        String href = getUrlPrefix();
+        AtomAdminService service = new AtomAdminService(href);
+        
+        AtomAdminService.Workspace workspace = new AtomAdminService.Workspace();
+        workspace.setTitle("Workspace: Collections for administration");
+        workspace.setHref(service.getHref());
+        service.setEntries(new Entry[] { workspace });
+        
+        List workspaceCollections = new ArrayList();
+        
+        AtomAdminService.WorkspaceCollection weblogCol = new AtomAdminService.WorkspaceCollection();
+        weblogCol.setTitle("Collection: Weblog administration entries");
+        weblogCol.setMemberType(org.roller.presentation.atomadminapi.Entry.Types.WEBLOG);
+        weblogCol.setHref(service.getHref() + "/" + org.roller.presentation.atomadminapi.EntrySet.Types.WEBLOGS);
+        workspaceCollections.add(weblogCol);
+        
+        AtomAdminService.WorkspaceCollection userCol = new AtomAdminService.WorkspaceCollection();
+        userCol.setTitle("Collection: User administration entries");
+        userCol.setMemberType("user");
+        userCol.setHref(service.getHref() + "/" + org.roller.presentation.atomadminapi.EntrySet.Types.USERS);
+        workspaceCollections.add(userCol);
+        
+        AtomAdminService.WorkspaceCollection memberCol = new AtomAdminService.WorkspaceCollection();
+        memberCol.setTitle("Collection: Member administration entries");
+        memberCol.setMemberType("member");
+        memberCol.setHref(service.getHref() + "/" + org.roller.presentation.atomadminapi.EntrySet.Types.MEMBERS);
+        workspaceCollections.add(memberCol);
+        
+        workspace.setEntries((Entry[])workspaceCollections.toArray(new Entry[0]));
+        
+        return service;
+    }
+}
+

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntry.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntry.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntry.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntry.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,156 @@
+/*
+ * MemberEntry.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+
+package org.roller.presentation.atomadminapi;
+
+import java.util.Date;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.Text;
+import org.roller.pojos.PermissionsData;
+import org.roller.pojos.UserData;
+import org.roller.presentation.atomadminapi.Entry.Attributes;
+import org.roller.presentation.atomadminapi.Entry.Types;
+
+/**
+ *
+ * @author jtb
+ */
+class MemberEntry extends Entry {
+    static interface Tags {
+        public static final String MEMBER = "member";
+        public static final String NAME = "name";
+        public static final String HANDLE = "handle";
+        public static final String PERMISSION = "permission";
+    }     
+    
+    private String name;
+    private String handle;
+    private String permission;
+    
+    public MemberEntry(Element e, String urlPrefix) throws Exception {
+        // name
+        Element nameElement = e.getChild(Tags.NAME, NAMESPACE);
+        if (nameElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.NAME);
+        }
+        setName(nameElement.getText());
+        
+        String href = urlPrefix + "/" + EntrySet.Types.MEMBERS + "/" + getHandle() + "/" + getName();
+        setHref(href);
+        
+        // full name
+        Element handleElement = e.getChild(Tags.HANDLE, NAMESPACE);
+        if (handleElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.HANDLE);
+        }
+        setHandle(handleElement.getText());
+        
+        // password
+        Element permissionElement = e.getChild(Tags.PERMISSION, NAMESPACE);
+        if (permissionElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.PERMISSION);
+        }
+        setPermission(permissionElement.getText());                
+    }
+    
+    public MemberEntry(PermissionsData pd, String urlPrefix) {
+        String href = urlPrefix + "/" + EntrySet.Types.MEMBERS + "/" + pd.getWebsite().getHandle() + "/" + pd.getUser().getUserName();
+        
+        setHref(href);
+        setName(pd.getUser().getUserName());
+        setHandle(pd.getWebsite().getHandle());
+        setPermission(maskToString(pd.getPermissionMask()));        
+    }
+    
+    private static String maskToString(short mask) {
+        if (mask == PermissionsData.ADMIN) {
+            return "ADMIN";
+        }
+        if (mask == PermissionsData.AUTHOR) {
+            return "AUTHOR";
+        }
+        if (mask == PermissionsData.LIMITED) {
+            return "LIMITED";
+        }
+        return null;
+    }
+
+    
+    private static short stringToMask(String s) {
+        if (s.equalsIgnoreCase("ADMIN")) {
+            return PermissionsData.ADMIN;
+        }
+        if (s.equalsIgnoreCase("AUTHOR")) {
+            return PermissionsData.AUTHOR;
+        }
+        if (s.equalsIgnoreCase("LIMITED")) {
+            return PermissionsData.LIMITED;
+        }
+        return 0;
+    }
+    
+    public String getType() {
+        return Types.MEMBER;
+    }
+    
+    public Document toDocument() {
+        Element member = new Element(Tags.MEMBER, NAMESPACE);
+        Document doc = new Document(member);
+        
+        // href
+        member.setAttribute(Attributes.HREF, getHref());
+               
+        // name
+        Element name = new Element(Tags.NAME, AtomAdminService.NAMESPACE);
+        Text nameText = new Text(getName());
+        name.addContent(nameText);
+        member.addContent(name);
+       
+        // handle
+        Element handle = new Element(Tags.HANDLE, NAMESPACE);
+        Text handleText = new Text(getHandle());
+        handle.addContent(handleText);
+        member.addContent(handle);
+        
+        // permission
+        Element permission = new Element(Tags.PERMISSION, NAMESPACE);
+        Text permissionText = new Text(getPermission());
+        permission.addContent(permissionText);
+        member.addContent(permission);
+                
+        return doc;
+    }
+            
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getHandle() {
+        return handle;
+    }
+
+    public void setHandle(String handle) {
+        this.handle = handle;
+    }
+
+    public String getPermission() {
+        return permission;
+    }
+    
+    public short getPermissionMask() {
+        return stringToMask(getPermission());
+    }
+
+    public void setPermission(String permission) {
+        this.permission = permission;
+    }
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntrySet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntrySet.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntrySet.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/MemberEntrySet.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,66 @@
+/*
+ * WeblogEntrySet.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+
+package org.roller.presentation.atomadminapi;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.roller.pojos.PermissionsData;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.atomadminapi.EntrySet.Types;
+
+/**
+ * This class describes a set of member entries. 
+ *
+ * @author jtb
+ */
+class MemberEntrySet extends EntrySet {
+    static interface Tags {
+        public static final String MEMBERS = "members";
+    }       
+        
+    public MemberEntrySet(PermissionsData[] members, String urlPrefix) {
+        if (members == null) {
+            throw new NullPointerException("ERROR: Null members not allowed");
+        }
+        
+        List entries = new ArrayList();        
+        for (int i = 0; i < members.length; i++) {
+            PermissionsData pd = members[i];
+            Entry entry = new MemberEntry(pd, urlPrefix);
+            entries.add(entry);            
+        }
+        setEntries((Entry[])entries.toArray(new Entry[0]));
+        setHref(urlPrefix + "/" + Types.MEMBERS);
+    }
+    
+    public MemberEntrySet(Document d, String urlPrefix) throws Exception {
+        Element root = d.getRootElement();
+        String rootName = root.getName();
+        if (!rootName.equals(Tags.MEMBERS)) {
+            throw new Exception("ERROR: Expected root name: " + Tags.MEMBERS + ", root name was: " + rootName);
+        }
+        List members = root.getChildren(MemberEntry.Tags.MEMBER, NAMESPACE);
+        if (members != null) {
+            List entries = new ArrayList();
+            for (Iterator i = members.iterator(); i.hasNext(); ) {
+                Element member = (Element)i.next();
+                MemberEntry entry = new MemberEntry(member, urlPrefix);
+                entries.add(entry);
+            }
+            setEntries((Entry[])entries.toArray(new Entry[0]));
+        }
+        setHref(urlPrefix + "/" + Types.MEMBERS);
+    }
+        
+    public String getType() {
+        return Types.MEMBERS;
+    }    
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerMemberHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerMemberHandler.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerMemberHandler.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerMemberHandler.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,319 @@
+/*
+ * RollerMemberHandler.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import org.jdom.Document;
+import org.jdom.input.SAXBuilder;
+import org.roller.RollerException;
+import org.roller.model.UserManager;
+import org.roller.pojos.PermissionsData;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WebsiteData;
+
+/**
+ * This class handles requests concerning Roller weblog membership (groups).
+ *
+ * @author jtb
+ */
+class RollerMemberHandler extends Handler {
+    static class MemberURI extends URI {
+        private String username;
+        private String handle;
+        
+        public MemberURI(HttpServletRequest req) {
+            super(req);           
+            setHandle(getEntryId());
+            if (getEntryIds() != null && getEntryIds().length > 1) {
+                setUsername(getEntryIds()[1]);
+            }
+        }
+               
+        public boolean hasUsername() {
+            return getUsername() != null;
+        }
+
+        public String getUsername() {
+            return username;
+        }
+
+        private void setUsername(String username) {
+            this.username = username;
+        }
+
+        public String getHandle() {
+            return handle;
+        }
+
+        private void setHandle(String handle) {
+            this.handle = handle;
+        }
+    }    
+    
+    private URI memberUri;
+    
+    public RollerMemberHandler(HttpServletRequest request) {
+        super(request);
+        memberUri = new MemberURI(request);
+    }
+    
+    protected URI getUri() {
+        return memberUri;
+    }
+    
+    public EntrySet processGet() throws Exception {
+        if (getUri().isCollection()) {
+            return getCollection();
+        } else if (getUri().isEntry()) {
+            return getEntry();
+        } else {
+            throw new Exception("ERROR: Unknown GET URI type");
+        }
+    }
+    
+    public EntrySet processPost(Reader r) throws Exception {
+        if (getUri().isCollection()) {
+            return postCollection(r);
+        } else {
+            throw new Exception("ERROR: Unknown POST URI type");
+        }
+    }
+    
+    public EntrySet processPut(Reader r) throws Exception {
+        if (getUri().isCollection()) {
+            return putCollection(r);
+        } else if (getUri().isEntry()) {
+            return putEntry(r);
+        } else {
+            throw new Exception("ERROR: Unknown PUT URI type");
+        }
+    }
+    
+    public EntrySet processDelete() throws Exception {
+        if (getUri().isEntry()) {
+            return deleteEntry();
+        } else {
+            throw new Exception("ERROR: Unknown DELETE URI type");
+        }
+    }
+    
+    private EntrySet getCollection() throws Exception {
+        // get all permissions: for all users, for all websites
+        List users = getRoller().getUserManager().getUsers();
+        List perms = new ArrayList();
+        for (Iterator i = users.iterator(); i.hasNext(); ) {
+            UserData user = (UserData)i.next();
+            List permissions = getRoller().getUserManager().getAllPermissions(user);
+            for (Iterator j = permissions.iterator(); j.hasNext(); ) {
+                PermissionsData pd = (PermissionsData)j.next();
+                perms.add(pd);
+            }
+        }
+        EntrySet es = new MemberEntrySet((PermissionsData[])perms.toArray(new PermissionsData[0]), getUrlPrefix());
+        return es;
+    }
+    
+    private EntrySet getEntry() throws Exception {
+        MemberURI muri = (MemberURI)getUri();
+        String handle = muri.getHandle();
+        String username = muri.getUsername();
+               
+        List perms;
+        if (username == null) {
+            //get all entries for the given website handle
+            WebsiteData wd = getRoller().getUserManager().getWebsiteByHandle(handle);
+            if (wd == null) {
+                throw new Exception("ERROR: Unknown weblog handle: " + handle);
+            }
+            perms = getRoller().getUserManager().getAllPermissions(wd);
+        } else {
+            //get all entries for the given website handle & username
+            WebsiteData wd = getRoller().getUserManager().getWebsiteByHandle(handle);
+            if (wd == null) {
+                throw new Exception("ERROR: Unknown weblog handle: " + handle);
+            }
+            UserData ud = getRoller().getUserManager().getUser(username);
+            if (ud == null) {
+                throw new Exception("ERROR: Unknown user name: " + username);
+            }
+            perms = Collections.singletonList(getRoller().getUserManager().getPermissions(wd, ud));
+        }
+        
+        EntrySet es = new MemberEntrySet((PermissionsData[])perms.toArray(new PermissionsData[0]), getUrlPrefix());
+        return es;
+    }
+    
+    private EntrySet postCollection(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new MemberEntrySet(collectionDoc, getUrlPrefix());
+        createMembers((MemberEntrySet)c);
+        
+        return c;
+    }
+    
+    private EntrySet putCollection(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new MemberEntrySet(collectionDoc, getUrlPrefix());
+        updateMembers((MemberEntrySet)c);
+        
+        return c;
+    }
+    
+    private EntrySet putEntry(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new MemberEntrySet(collectionDoc, getUrlPrefix());
+        
+        if (c.getEntries().length > 1) {
+            throw new Exception("ERROR: Cannot put >1 entries per request");
+        }
+        if (c.getEntries().length > 0) {
+            // only one entry
+            // if there's zero entries, this is a nop
+            MemberEntry entry = (MemberEntry)c.getEntries()[0];
+            
+            MemberURI muri = (MemberURI)getUri();            
+            
+            // get handle
+            // if there's no handle in the entry, set it
+            // if the entry and URI handles do not match, exception
+            String handle = muri.getHandle();
+            if (entry.getHandle() == null) {
+                entry.setHandle(handle);
+            } else if (!entry.getHandle().equals(handle)) {
+                throw new Exception("ERROR: URI and entry handle do not match");
+            }
+            
+            // get username
+            // if there's no name in the entry or the URI, exception
+            // if there's no name in the entry, set it
+            // if the names in the entry and URI do not match, exception
+            String username = muri.getUsername();
+            if (entry.getName() == null) {
+                if (username == null) {
+                    throw new Exception("ERROR: No user name in URI or entry");
+                }
+                entry.setName(username);
+            } else if (username != null && !entry.getName().equals(username)) {
+                throw new Exception("ERROR: URI and entry user name do not match");
+            }
+                                    
+            updateMembers((MemberEntrySet)c);
+        }
+        
+        return c;
+    }
+    
+    private void createMembers(MemberEntrySet c) throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            
+            // Need system user to create website
+            getRoller().setUser(UserData.SYSTEM_USER);
+            
+            for (int i = 0; i < c.getEntries().length; i++) {
+                MemberEntry entry = (MemberEntry)c.getEntries()[i];
+                PermissionsData pd = toPermissionsData(entry);
+                pd.save();                
+            }
+            getRoller().commit();
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+    
+    private PermissionsData toPermissionsData(MemberEntry entry) throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            UserData ud = mgr.getUser(entry.getName());
+            WebsiteData wd = mgr.getWebsiteByHandle(entry.getHandle());
+            PermissionsData pd = new PermissionsData();
+            pd.setUser(ud);
+            pd.setWebsite(wd);
+            pd.setPermissionMask(entry.getPermissionMask());
+            pd.setPending(false);
+            
+            return pd;
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+    
+    private PermissionsData getPermissionsData(MemberEntry entry) throws Exception {
+        return getPermissionsData(entry.getHandle(), entry.getName());
+    }
+    
+    private PermissionsData getPermissionsData(String handle, String username) throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            UserData ud = mgr.getUser(username);
+            WebsiteData wd = mgr.getWebsiteByHandle(handle);
+            PermissionsData pd = mgr.getPermissions(wd, ud);
+            
+            return pd;
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }        
+    }    
+    private void updateMembers(MemberEntrySet c) throws Exception {
+        try {
+            getRoller().setUser(UserData.SYSTEM_USER);
+            for (int i = 0; i < c.getEntries().length; i++) {
+                MemberEntry entry = (MemberEntry)c.getEntries()[i];
+                PermissionsData pd = getPermissionsData(entry);
+                if (pd == null) {
+                    throw new Exception("ERROR: Permissions do not exist for weblog handle: " + entry.getHandle() + ", user name: " + entry.getName());
+                }
+                updatePermissionsData(pd, entry);
+                pd.save();
+            }
+            getRoller().commit();
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+    
+    private void updatePermissionsData(PermissionsData pd, MemberEntry entry) {
+        // only permission can be updated
+        
+        if (entry.getPermission() != null) {
+            pd.setPermissionMask(entry.getPermissionMask());
+        }
+    }
+    
+    private EntrySet deleteEntry() throws Exception {
+        MemberURI muri = (MemberURI)getUri();
+        
+        String handle = muri.getHandle();
+        String username = muri.getUsername();
+       
+        if (username == null) {
+            throw new Exception("ERROR: No user name supplied in URI");
+        }
+        
+        try {
+            getRoller().setUser(UserData.SYSTEM_USER);
+            PermissionsData pd = getPermissionsData(handle, username);
+            PermissionsData[] pds = new PermissionsData[] { pd };               
+            EntrySet es = new MemberEntrySet(pds, getUrlPrefix());
+        
+            pd.remove();
+            getRoller().commit();
+
+            return es;            
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+}
+

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerUserHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerUserHandler.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerUserHandler.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerUserHandler.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,197 @@
+/*
+ * RollerUserHandler.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import org.jdom.Document;
+import org.jdom.input.SAXBuilder;
+import org.roller.RollerException;
+import org.roller.model.UserManager;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.atomadminapi.EntrySet.Types;
+
+/**
+ * This class handles request concerning Roller users.
+ *
+ * @author jtb
+ */
+class RollerUserHandler extends Handler {
+    public RollerUserHandler(HttpServletRequest request) {
+        super(request);
+    }
+    
+    public EntrySet processGet() throws Exception {
+        if (getUri().isCollection()) {
+            return getCollection();
+        } else if (getUri().isEntry()) {
+            return getEntry();
+        } else {
+            throw new Exception("ERROR: Unknown GET URI type");
+        }
+    }
+    
+    public EntrySet processPost(Reader r) throws Exception {
+        if (getUri().isCollection()) {
+            return postCollection(r);
+        } else {
+            throw new Exception("ERROR: Unknown POST URI type");
+        }
+    }
+    
+    public EntrySet processPut(Reader r) throws Exception {
+        if (getUri().isCollection()) {
+            return putCollection(r);
+        } else if (getUri().isEntry()) {
+            return putEntry(r);
+        } else {
+            throw new Exception("ERROR: Unknown PUT URI type");
+        }
+    }
+    
+    public EntrySet processDelete() throws Exception {
+        if (getUri().isEntry()) {
+            return deleteEntry();
+        } else {
+            throw new Exception("ERROR: Unknown DELETE URI type");
+        }
+    }
+    
+    private EntrySet getCollection() throws Exception {
+        List users = getRoller().getUserManager().getUsers();
+        EntrySet es = new UserEntrySet((UserData[])users.toArray(new UserData[0]), getUrlPrefix());
+        
+        return es;
+    }
+    
+    private EntrySet getEntry() throws Exception {
+        UserData ud = getRoller().getUserManager().getUser(getUri().getEntryId());
+        if (ud == null) {
+            throw new Exception("ERROR: Unknown user name: " + getUri().getEntryId());
+        }
+        UserData[] uds = new UserData[] { ud };
+        EntrySet c = new UserEntrySet(uds, getUrlPrefix());
+        
+        return c;
+    }
+    
+    private EntrySet postCollection(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new UserEntrySet(collectionDoc, getUrlPrefix());
+        createUsers((UserEntrySet)c);
+        
+        return c;
+    }
+    
+    private EntrySet putCollection(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new UserEntrySet(collectionDoc, getUrlPrefix());
+        updateUsers((UserEntrySet)c);
+        
+        return c;
+    }
+    
+    private EntrySet putEntry(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new UserEntrySet(collectionDoc, getUrlPrefix());
+        
+        if (c.getEntries().length > 1) {
+            throw new Exception("ERROR: Cannot put >1 entries per request");
+        }
+        if (c.getEntries().length > 0) {
+            UserEntry entry = (UserEntry)c.getEntries()[0];
+            if (entry.getName() != null && !entry.getName().equals(getUri().getEntryId())) {
+                throw new Exception("ERROR: Content name does not match URI name");
+            }
+            entry.setName(getUri().getEntryId());
+            updateUsers((UserEntrySet)c);
+        }
+        
+        return c;
+    }
+    
+    private void createUsers(UserEntrySet c) throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            
+            // Need system user to create website
+            getRoller().setUser(UserData.SYSTEM_USER);
+            
+            for (int i = 0; i < c.getEntries().length; i++) {
+                UserEntry entry = (UserEntry)c.getEntries()[i];
+                UserData user = entry.toUserData();
+                mgr.addUser(user);
+            }
+            getRoller().commit();
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+    
+    private void updateUsers(UserEntrySet c) throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            
+            // Need system user to create user
+            getRoller().setUser(UserData.SYSTEM_USER);
+            
+            for (int i = 0; i < c.getEntries().length; i++) {
+                UserEntry entry = (UserEntry)c.getEntries()[i];
+                UserData ud = mgr.getUser(entry.getName());
+                updateUserData(ud, entry);
+                ud.save();
+            }
+            getRoller().commit();
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+    
+    private void updateUserData(UserData ud, UserEntry entry) {
+        // user name cannot be updated
+        
+        if (entry.getFullName() != null) {
+            ud.setFullName(entry.getFullName());
+        }
+        if (entry.getPassword() != null) {
+            ud.setPassword(entry.getPassword());
+        }
+        if (entry.getLocale() != null) {
+            ud.setLocale(entry.getLocale());
+        }
+        if (entry.getTimezone() != null) {
+            ud.setTimeZone(entry.getTimezone());
+        }
+        if (entry.getEmailAddress() != null) {
+            ud.setEmailAddress(entry.getEmailAddress());
+        }
+    }
+    
+    private EntrySet deleteEntry() throws Exception {
+        try {
+            getRoller().setUser(UserData.SYSTEM_USER);
+            UserManager mgr = getRoller().getUserManager();
+            UserData ud = mgr.getUser(getUri().getEntryId());
+            
+            UserData[] uds = new UserData[] { ud };
+            EntrySet es = new UserEntrySet(uds, getUrlPrefix());
+            
+            ud.remove();
+            getRoller().commit();
+            
+            return es;
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+}
+

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerWeblogHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerWeblogHandler.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerWeblogHandler.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/RollerWeblogHandler.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,211 @@
+/*
+ * RollerWeblogHandler.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import org.jdom.Document;
+import org.jdom.input.SAXBuilder;
+import org.roller.RollerException;
+import org.roller.model.UserManager;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.atomadminapi.EntrySet.Types;
+
+/**
+ * This class handles requests concernning Roller weblog resources.
+ *
+ * @author jtb
+ */
+class RollerWeblogHandler extends Handler {
+    /** Theme name used when creating weblogs */
+    private static final String DEFAULT_THEME = "basic";
+    
+    public RollerWeblogHandler(HttpServletRequest request) {
+        super(request);
+    }
+    
+    public EntrySet processGet() throws Exception {
+        if (getUri().isCollection()) {
+            return getCollection();
+        } else if (getUri().isEntry()) {
+            return getEntry();
+        } else {
+            throw new Exception("ERROR: Unknown GET URI type");
+        }
+    }
+    
+    public EntrySet processPost(Reader r) throws Exception {
+        if (getUri().isCollection()) {
+            return postCollection(r);
+        } else {
+            throw new Exception("ERROR: Unknown POST URI type");
+        }        
+    }
+    
+    public EntrySet processPut(Reader r) throws Exception {
+        if (getUri().isCollection()) {
+            return putCollection(r);
+        } else if (getUri().isEntry()) {
+            return putEntry(r);
+        } else {
+            throw new Exception("ERROR: Unknown PUT URI type");
+        }
+    }
+    
+    public EntrySet processDelete() throws Exception {
+        if (getUri().isEntry()) {
+            return deleteEntry();
+        } else {
+            throw new Exception("ERROR: Unknown DELETE URI type");
+        }
+    }    
+    
+    private EntrySet getCollection() throws Exception {
+        List users = getRoller().getUserManager().getUsers();
+        EntrySet c = new WeblogEntrySet((UserData[])users.toArray(new UserData[0]), getUrlPrefix());
+        
+        return c;
+    }
+    
+    private EntrySet getEntry() throws Exception {
+        WebsiteData wd = getRoller().getUserManager().getWebsiteByHandle(getUri().getEntryId());
+        if (wd == null) {
+            throw new Exception("ERROR: Unknown weblog handle: " + getUri().getEntryId());
+        }
+        WebsiteData[] wds = new WebsiteData[] { wd };
+        EntrySet c = new WeblogEntrySet(wds, getUrlPrefix());
+        
+        return c;
+    }
+    
+    private EntrySet postCollection(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new WeblogEntrySet(collectionDoc, getUrlPrefix());
+        createWeblogs((WeblogEntrySet)c);
+        
+        return c;
+    }
+    
+    private EntrySet putCollection(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new WeblogEntrySet(collectionDoc, getUrlPrefix());
+        updateWeblogs((WeblogEntrySet)c);
+        
+        return c;
+    }
+    
+    private EntrySet putEntry(Reader r) throws Exception {
+        SAXBuilder builder = new SAXBuilder();
+        Document collectionDoc = builder.build(r);
+        EntrySet c = new WeblogEntrySet(collectionDoc, getUrlPrefix());
+        
+        if (c.getEntries().length > 1) {
+            throw new Exception("ERROR: Cannot put >1 entries per request");
+        }
+        if (c.getEntries().length > 0) {
+            WeblogEntry entry = (WeblogEntry)c.getEntries()[0];
+            if (entry.getHandle() != null && !entry.getHandle().equals(getUri().getEntryId())) {
+                throw new Exception("ERROR: Content handle does not match URI handle");
+            }
+            entry.setHandle(getUri().getEntryId());
+            updateWeblogs((WeblogEntrySet)c);
+        }
+        
+        return c;
+    }
+    
+    private void createWeblogs(WeblogEntrySet c) throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            
+            //TODO: group blogging check?
+            
+            // Need system user to create website
+            getRoller().setUser(UserData.SYSTEM_USER);
+            HashMap pages = null; //getRollerContext().readThemeMacros(form.getTheme());
+            
+            for (int i = 0; i < c.getEntries().length; i++) {
+                WeblogEntry entry = (WeblogEntry)c.getEntries()[i];
+                UserData user = mgr.getUser(entry.getCreatingUser());
+                WebsiteData wd = mgr.createWebsite(user, pages, entry.getHandle(), entry.getName(), entry.getDescription(), entry.getEmailAddress(), DEFAULT_THEME, entry.getLocale(), entry.getTimezone());
+                wd.save();                
+            }
+            getRoller().commit();
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+    
+    private void updateWeblogs(WeblogEntrySet c) throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            
+            //TODO: group blogging check?
+            
+            // Need system user to create website
+            getRoller().setUser(UserData.SYSTEM_USER);
+            HashMap pages = null;
+            
+            for (int i = 0; i < c.getEntries().length; i++) {
+                WeblogEntry entry = (WeblogEntry)c.getEntries()[i];
+                WebsiteData wd = mgr.getWebsiteByHandle(entry.getHandle());
+                updateWebsiteData(wd, entry);
+                wd.save();
+            }
+            getRoller().commit();
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+    
+    private void updateWebsiteData(WebsiteData wd, WeblogEntry entry) {
+        if (entry.getName() != null) {
+            wd.setName(entry.getName());
+        }
+        if (entry.getDescription() != null) {
+            wd.setDescription(entry.getDescription());
+        }
+        if (entry.getLocale() != null) {
+            wd.setLocale(entry.getLocale());
+        }
+        if (entry.getTimezone() != null) {
+            wd.setTimeZone(entry.getTimezone());
+        }
+        if (entry.getEmailAddress() != null) {
+            wd.setEmailAddress(entry.getEmailAddress());
+        }
+    }
+    
+    private EntrySet deleteEntry() throws Exception {
+        try {
+            UserManager mgr = getRoller().getUserManager();
+            
+            // Need system user to create website
+            getRoller().setUser(UserData.SYSTEM_USER);
+            
+            WebsiteData wd = mgr.getWebsiteByHandle(getUri().getEntryId());
+            if (wd == null) {
+                throw new Exception("ERROR: Uknown weblog handle: " + getUri().getEntryId());
+            }
+            
+            WebsiteData[] wds = new WebsiteData[] { wd };            
+            EntrySet es = new WeblogEntrySet(wds, getUrlPrefix());            
+            
+            wd.remove();
+            getRoller().commit();
+            
+            return es;
+        } catch (RollerException re) {
+            throw new Exception(re);
+        }
+    }
+}
+

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntry.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntry.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntry.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntry.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,250 @@
+/*
+ * UserEntry.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+
+package org.roller.presentation.atomadminapi;
+
+import java.util.Date;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.Text;
+import org.roller.pojos.UserData;
+import org.roller.presentation.atomadminapi.Entry.Types;
+
+/**
+ * This class describes a user entry; a user weblog resource.
+ * @author jtb
+ */
+class UserEntry extends Entry {
+    /** XML tags that define a user entry. */
+    static interface Tags {
+        public static final String USER = "user";
+        public static final String NAME = "name";
+        public static final String FULL_NAME = "full-name";
+        public static final String PASSWORD = "password";
+        public static final String EMAIL_ADDRESS = "email-address";
+        public static final String LOCALE = "locale";
+        public static final String TIMEZONE = "timezone";
+        public static final String DATE_CREATED = "date-created";
+    }     
+    
+    private String name;
+    private String fullName;
+    private String password;
+    private String locale;
+    private String timezone;
+    private Date dateCreated;
+    private String emailAddress;
+    
+    /** Construct a user entry from a JDOM element. */
+    public UserEntry(Element e, String urlPrefix) throws Exception {
+        // name
+        Element nameElement = e.getChild(Tags.NAME, NAMESPACE);
+        if (nameElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.NAME);
+        }
+        setName(nameElement.getText());
+        String href = urlPrefix + "/" + EntrySet.Types.USERS + "/" + getName();
+        setHref(href);
+        
+        // full name
+        Element fullNameElement = e.getChild(Tags.FULL_NAME, NAMESPACE);
+        if (fullNameElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.FULL_NAME);
+        }
+        setFullName(fullNameElement.getText());
+        
+        // password
+        Element passwordElement = e.getChild(Tags.PASSWORD, NAMESPACE);
+        if (passwordElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.PASSWORD);
+        }
+        setPassword(passwordElement.getText());
+        
+        // locale
+        Element localeElement = e.getChild(Tags.LOCALE, AtomAdminService.NAMESPACE);
+        if (localeElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.LOCALE);
+        }
+        setLocale(localeElement.getText());
+        
+        // timezone
+        Element tzElement = e.getChild(Tags.TIMEZONE, AtomAdminService.NAMESPACE);
+        if (tzElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.TIMEZONE);
+        }
+        setTimezone(tzElement.getText());
+        
+        // email address
+        Element emailElement = e.getChild(Tags.EMAIL_ADDRESS, AtomAdminService.NAMESPACE);
+        if (emailElement == null) {
+            throw new Exception("ERROR: Missing element: " + Tags.EMAIL_ADDRESS);
+        }
+        setEmailAddress(emailElement.getText());
+        
+        // created (optional)
+        Element createdElement = e.getChild(Tags.DATE_CREATED, AtomAdminService.NAMESPACE);
+        if (createdElement != null) {
+            setDateCreated(new Date(Long.valueOf(createdElement.getText()).longValue()));
+        }
+    }
+    
+    /** Construct a user entry from a Roller UserData object. */
+    public UserEntry(UserData ud, String urlPrefix) {
+        String href = urlPrefix + "/" + EntrySet.Types.USERS + "/" + ud.getUserName();
+        
+        setHref(href);
+        setName(ud.getUserName());
+        setFullName(ud.getFullName());
+        setPassword(ud.getPassword());
+        setLocale(ud.getLocale());
+        setTimezone(ud.getTimeZone());
+        setEmailAddress(ud.getEmailAddress());
+        setDateCreated(ud.getDateCreated());
+    }
+        
+    public String getType() {
+        return Types.USER;
+    }
+    
+    public Document toDocument() {
+        Element user = new Element(Tags.USER, NAMESPACE);
+        Document doc = new Document(user);
+        
+        // href
+        user.setAttribute(Attributes.HREF, getHref());
+               
+        // name
+        Element name = new Element(Tags.NAME, AtomAdminService.NAMESPACE);
+        Text nameText = new Text(getName());
+        name.addContent(nameText);
+        user.addContent(name);
+       
+        // full name
+        Element fullName = new Element(Tags.FULL_NAME, NAMESPACE);
+        Text fullNameText = new Text(getFullName());
+        fullName.addContent(fullNameText);
+        user.addContent(fullName);
+        
+        // password
+        Element password = new Element(Tags.PASSWORD, NAMESPACE);
+        Text passwordText = new Text(getPassword());
+        password.addContent(passwordText);
+        user.addContent(password);
+        
+        // locale
+        Element locale = new Element(Tags.LOCALE, AtomAdminService.NAMESPACE);
+        Text localeText = new Text(getLocale());
+        locale.addContent(localeText);
+        user.addContent(locale);
+        
+        // timezone
+        Element tz = new Element(Tags.TIMEZONE, AtomAdminService.NAMESPACE);
+        Text tzText = new Text(getTimezone());
+        tz.addContent(tzText);
+        user.addContent(tz);
+                
+        // email address
+        Element email = new Element(Tags.EMAIL_ADDRESS, AtomAdminService.NAMESPACE);
+        Text emailText = new Text(String.valueOf(getEmailAddress()));
+        email.addContent(emailText);
+        user.addContent(email);
+        
+        // creation date (optional)
+        Element created = new Element(Tags.DATE_CREATED, AtomAdminService.NAMESPACE);
+        Date datedCreated = getDateCreated();
+        if (getDateCreated() != null) {
+            Text createdText = new Text(String.valueOf(getDateCreated().getTime()));
+            created.addContent(createdText);
+            user.addContent(created);
+        }
+        
+        return doc;
+    }
+    
+    /** Get the user name of this user entry. */
+    public String getName() {
+        return name;
+    }
+    
+    /** Set of the user name of this user entry. */
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    /** Get the full name of this user entry. */
+    public String getFullName() {
+        return fullName;
+    }
+    
+    /** Set the full name of this user entry. */
+    public void setFullName(String fullName) {
+        this.fullName = fullName;
+    }
+    
+    /** Get the password of this user entry. */
+    public String getPassword() {
+        return password;
+    }
+    
+    /** Set the password of this user entry. */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+    
+    /** Get the locale string of this user entry. */
+    public String getLocale() {
+        return locale;
+    }
+    
+    /** Set the locale string of this user entry. */
+    public void setLocale(String locale) {
+        this.locale = locale;
+    }
+    
+    /** Get the timezone string of this user entry. */
+    public String getTimezone() {
+        return timezone;
+    }
+    
+    /** Set the timezone string of this user entry. */
+    public void setTimezone(String timezone) {
+        this.timezone = timezone;
+    }
+    
+    /** Get the date created of this user entry. */
+    public Date getDateCreated() {
+        return dateCreated;
+    }
+    
+    /** Set the date created of this user entry. */
+    public void setDateCreated(Date dateCreated) {
+        this.dateCreated = dateCreated;
+    }
+    
+    /** Get the email address of this user entry. */
+    public String getEmailAddress() {
+        return emailAddress;
+    }
+    
+    /** Set the email address of this user entry. */
+    public void setEmailAddress(String emailAddress) {
+        this.emailAddress = emailAddress;
+    }      
+    
+    /** This object, as a Roller UserData object. */
+    public UserData toUserData() {
+        UserData ud = new UserData();
+        ud.setUserName(getName());
+        ud.setFullName(getFullName());
+        ud.setPassword(getPassword());
+        ud.setEmailAddress(getEmailAddress());
+        ud.setLocale(getLocale());
+        ud.setTimeZone(getTimezone());
+        ud.setDateCreated(getDateCreated());
+        
+        return ud;
+    }
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntrySet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntrySet.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntrySet.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/UserEntrySet.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,68 @@
+/*
+ * UserEntrySet.java
+ *
+ * Created on January 17, 2006, 12:44 PM
+ */
+
+package org.roller.presentation.atomadminapi;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.roller.pojos.PermissionsData;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.atomadminapi.EntrySet.Types;
+
+/**
+ * This class describes a set of user entries. 
+ * @author jtb
+ */
+class UserEntrySet extends EntrySet {
+    /** XML tags that describe a set of user entries. */
+    static interface Tags {
+        public static final String USERS = "users";
+    }       
+        
+    /** Construct based on an array of Roller UserData objects. */
+    public UserEntrySet(UserData[] users, String urlPrefix) {
+        if (users == null) {
+            throw new NullPointerException("ERROR: Null users not allowed");
+        }
+        
+        List entries = new ArrayList();        
+        for (int i = 0; i < users.length; i++) {
+            UserData ud = users[i];
+            Entry entry = new UserEntry(ud, urlPrefix);
+            entries.add(entry);            
+        }
+        setEntries((Entry[])entries.toArray(new Entry[0]));
+        setHref(urlPrefix + "/" + Types.USERS);
+    }
+    
+    /** Construct based on a JDOM Document object. */
+    public UserEntrySet(Document d, String urlPrefix) throws Exception {
+        Element root = d.getRootElement();
+        String rootName = root.getName();
+        if (!rootName.equals(Tags.USERS)) {
+            throw new Exception("ERROR: Expected root name: " + Tags.USERS + ", root name was: " + rootName);
+        }
+        List users = root.getChildren(UserEntry.Tags.USER, NAMESPACE);
+        if (users != null) {
+            List entries = new ArrayList();
+            for (Iterator i = users.iterator(); i.hasNext(); ) {
+                Element user = (Element)i.next();
+                UserEntry entry = new UserEntry(user, urlPrefix);
+                entries.add(entry);
+            }
+            setEntries((Entry[])entries.toArray(new Entry[0]));
+        }
+        setHref(urlPrefix + "/" + Types.USERS);
+    }
+        
+    public String getType() {
+        return Types.USERS;
+    }    
+}

Added: incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WSSEAuthenticator.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WSSEAuthenticator.java?rev=375629&view=auto
==============================================================================
--- incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WSSEAuthenticator.java (added)
+++ incubator/roller/trunk/sandbox/atomadminprotocol/src/org/roller/presentation/atomadminapi/WSSEAuthenticator.java Tue Feb  7 07:37:00 2006
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2005 David M Johnson (For RSS and Atom In Action)
+ *
+ * Licensed 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.
+ */
+package org.roller.presentation.atomadminapi;
+
+import java.util.StringTokenizer;
+import javax.servlet.http.HttpServletRequest;
+import com.sun.syndication.io.impl.Base64;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.model.Roller;
+import org.roller.pojos.UserData;
+import org.roller.presentation.RollerContext;
+
+/**
+ * This class implements HTTP basic authentication for roller.
+ *
+ * @author jtb
+ */
+class WSSEAuthenticator extends Authenticator {
+    private static Log logger = LogFactory.getFactory().getInstance(WSSEAuthenticator.class);
+ 
+    /** Creates a new instance of HttpBasicAuthenticator */
+    public WSSEAuthenticator(HttpServletRequest req) {
+        super(req);
+    }
+       
+    public boolean authenticate() {
+        String wsseHeader = getRequest().getHeader("X-WSSE");
+        if (wsseHeader == null) return false;
+        
+        String id = null;
+        String userName = null;
+        String created = null;
+        String nonce = null;
+        String passwordDigest = null;
+        String[] tokens = wsseHeader.split(",");
+        for (int i = 0; i < tokens.length; i++) {
+            int index = tokens[i].indexOf('=');
+            if (index != -1) {
+                String key = tokens[i].substring(0, index).trim();
+                String value = tokens[i].substring(index + 1).trim();
+                value = value.replaceAll("\"", "");
+                if (key.startsWith("UsernameToken")) {
+                    userName = value;
+                } else if (key.equalsIgnoreCase("nonce")) {
+                    nonce = value;
+                } else if (key.equalsIgnoreCase("passworddigest")) {
+                    passwordDigest = value;
+                } else if (key.equalsIgnoreCase("created")) {
+                    created = value;
+                }
+            }
+        }
+        String digest = null;
+        try {
+            UserData user = getRoller().getUserManager().getUser(userName);
+            digest = WSSEUtilities.generateDigest(
+                    WSSEUtilities.base64Decode(nonce),
+                    created.getBytes("UTF-8"),
+                    user.getPassword().getBytes("UTF-8"));
+            if (digest.equals(passwordDigest)) {
+                id = userName;
+            }
+        } catch (Exception e) {
+            logger.error("ERROR in wsseAuthenticataion: " + e.getMessage(), e);
+        }
+        
+        if (id != null) {
+            setUserId(id);
+            return true;
+        } else {
+            setUserId(null);
+            return false;
+        }
+    }
+}



Mime
View raw message