You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2011/04/18 11:29:46 UTC

svn commit: r1094397 [1/3] - in /chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings: ./ src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/ src/main/java/org/apache/chemistry/opencmis/server/impl/browser/...

Author: fmui
Date: Mon Apr 18 09:29:45 2011
New Revision: 1094397

URL: http://svn.apache.org/viewvc?rev=1094397&view=rev
Log:
CMIS-358: Moved browser binding code to server framework

Added:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/BrowserBindingUtils.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ControlParser.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/DiscoveryService.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/NavigationService.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ObjectService.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/RepositoryService.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/TypeCache.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/VersioningService.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/json/
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/json/JSONConstants.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/json/JSONConverter.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/css/
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/css/opencmis.css   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/images/
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/images/asf_logo.png   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/images/chemistry_logo_small.png   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/index.html   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/createdocument.html   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/createfolder.html   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/demo.html   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/index.html   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/web/opencmis.js   (with props)
Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/pom.xml
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/shared/ExceptionHelper.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/webapp/WEB-INF/web.xml

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/pom.xml
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/pom.xml?rev=1094397&r1=1094396&r2=1094397&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/pom.xml (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/pom.xml Mon Apr 18 09:29:45 2011
@@ -78,6 +78,26 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.0.1</version>
+        </dependency>     
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+        </dependency>        
+        <dependency>
+             <groupId>com.googlecode.json-simple</groupId>
+             <artifactId>json-simple</artifactId>
+             <version>1.1</version>
+        </dependency>
+        <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>servlet-api</artifactId>
             <version>2.4</version>

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java?rev=1094397&r1=1094396&r2=1094397&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/atompub/CmisAtomPubServlet.java Mon Apr 18 09:29:45 2011
@@ -49,6 +49,7 @@ import org.apache.chemistry.opencmis.ser
 import org.apache.chemistry.opencmis.server.shared.Dispatcher;
 import org.apache.chemistry.opencmis.server.shared.ExceptionHelper;
 import org.apache.chemistry.opencmis.server.shared.HttpUtils;
+import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -281,17 +282,20 @@ public class CmisAtomPubServlet extends 
             PrintWriter pw = response.getWriter();
             response.setStatus(statusCode);
             response.setContentType("text/html");
-            
-            pw.print("<html><head><title>Apache Chemistry OpenCMIS - " + exceptionName + " error</title>"
+
+            pw.print("<html><head><title>Apache Chemistry OpenCMIS - "
+                    + exceptionName
+                    + " error</title>"
                     + "<style><!--H1 {font-size:24px;line-height:normal;font-weight:bold;background-color:#f0f0f0;color:#003366;border-bottom:1px solid #3c78b5;padding:2px;} "
                     + "BODY {font-family:Verdana,arial,sans-serif;color:black;font-size:14px;} "
                     + "HR {color:#3c78b5;height:1px;}--></style></head><body>");
             pw.print("<h1>HTTP Status " + statusCode + " - <!--exception-->" + exceptionName + "<!--/exception--></h1>");
-            pw.print("<p><!--message-->" + ex.getMessage() + "<!--/message--></p>");
+            pw.print("<p><!--message-->" + StringEscapeUtils.escapeHtml(ex.getMessage()) + "<!--/message--></p>");
 
             String st = ExceptionHelper.getStacktraceAsString(ex);
             if (st != null) {
-                pw.print("<hr noshade='noshade'/><!--stacktrace--><pre>\n" + st + "\n</pre><!--/stacktrace--><hr noshade='noshade'/>");
+                pw.print("<hr noshade='noshade'/><!--stacktrace--><pre>\n" + st
+                        + "\n</pre><!--/stacktrace--><hr noshade='noshade'/>");
             }
 
             pw.print("</body></html>");

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/BrowserBindingUtils.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/BrowserBindingUtils.java?rev=1094397&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/BrowserBindingUtils.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/BrowserBindingUtils.java Mon Apr 18 09:29:45 2011
@@ -0,0 +1,492 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.chemistry.opencmis.server.impl.browser;
+
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.chemistry.opencmis.commons.PropertyIds;
+import org.apache.chemistry.opencmis.commons.data.Ace;
+import org.apache.chemistry.opencmis.commons.data.Acl;
+import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.data.ObjectData;
+import org.apache.chemistry.opencmis.commons.data.Properties;
+import org.apache.chemistry.opencmis.commons.data.PropertyData;
+import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
+import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.chemistry.opencmis.commons.impl.Base64;
+import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlEntryImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlPrincipalDataImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDecimalImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyHtmlImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriImpl;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
+import org.apache.chemistry.opencmis.server.shared.HttpUtils;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONStreamAware;
+
+public class BrowserBindingUtils {
+
+    public static final String JSON_MIME_TYPE = "application/json";
+
+    public static final String ROOT_PATH_FRAGMENT = "root";
+
+    public static final String SELECTOR_LAST_RESULT = "lastResult";
+
+    public static final String SELECTOR_TYPE_CHILDREN = "typeChildren";
+    public static final String SELECTOR_TYPE_DESCENDANTS = "typeDescendants";
+    public static final String SELECTOR_TYPE_DEFINITION = "typeDefintion";
+
+    public static final String SELECTOR_CONTENT = "content";
+    public static final String SELECTOR_OBJECT = "object";
+    public static final String SELECTOR_CHILDREN = "children";
+    public static final String SELECTOR_DESCENDANTS = "descendants";
+    public static final String SELECTOR_PARENTS = "parents";
+    public static final String SELECTOR_FOLDER_TREE = "folder";
+    public static final String SELECTOR_QUERY = "query";
+    public static final String SELECTOR_VERSIONS = "versions";
+
+    public static final String CMISACTION_CREATEDOCUMENT = "createDocument";
+    public static final String CMISACTION_CREATEFOLDER = "createFolder";
+    public static final String CMISACTION_QUERY = "query";
+
+    public static final String PARAM_SELECTOR = "selector";
+    public static final String PARAM_TRANSACTION = "transaction";
+    public static final String PARAM_CLIENTTOKEN = "clientToken";
+
+    public static final String CONTROL_CMISACTION = "cmisaction";
+    public static final String CONTROL_TRANSACTION = "transaction";
+    public static final String CONTROL_OBJECT_ID = "objectid";
+    public static final String CONTROL_PROP_ID = "propertyid";
+    public static final String CONTROL_PROP_VALUE = "propertyvalue";
+    public static final String CONTROL_POLICY = "policy";
+    public static final String CONTROL_ADD_ACE_PRINCIPAL = "addACEPrincipal";
+    public static final String CONTROL_ADD_ACE_PERMISSION = "addACEPermission";
+    public static final String CONTROL_REMOVE_ACE_PRINCIPAL = "removeACEPrincipal";
+    public static final String CONTROL_REMOVE_ACE_PERMISSION = "removeACEPermission";
+    public static final String CONTROL_CONTENT_TYPE = "contenttype";
+    public static final String CONTROL_FILENAME = "filename";
+
+    public static final String CONTEXT_OBJECT_ID = "org.apache.chemistry.openmis.browserbinding.objectId";
+    public static final String CONTEXT_OBJECT_TYPE_ID = "org.apache.chemistry.openmis.browserbinding.objectTypeId";
+    public static final String CONTEXT_BASETYPE_ID = "org.apache.chemistry.openmis.browserbinding.basetypeId";
+    public static final String CONTEXT_TRANSACTION = "org.apache.chemistry.openmis.browserbinding.transaction";
+
+    public enum CallUrl {
+        SERVICE, REPOSITORY, ROOT
+    }
+
+    /**
+     * Compiles the base URL for links, collections and templates.
+     */
+    public static UrlBuilder compileBaseUrl(HttpServletRequest request) {
+        UrlBuilder url = new UrlBuilder(request.getScheme(), request.getServerName(), request.getServerPort(), null);
+
+        url.addPath(request.getContextPath());
+        url.addPath(request.getServletPath());
+
+        return url;
+    }
+
+    public static UrlBuilder compileRepositoryUrl(HttpServletRequest request, String repositoryId) {
+        return compileBaseUrl(request).addPathSegment(repositoryId);
+    }
+
+    public static UrlBuilder compileRootUrl(HttpServletRequest request, String repositoryId) {
+        return compileRepositoryUrl(request, repositoryId).addPathSegment(BrowserBindingUtils.ROOT_PATH_FRAGMENT);
+    }
+
+    /**
+     * Returns the current CMIS path.
+     */
+    public static String getPath(HttpServletRequest request) {
+        String[] pathFragments = HttpUtils.splitPath(request);
+        if (pathFragments.length < 2) {
+            return null;
+        }
+        if (pathFragments.length == 2) {
+            return "/";
+        }
+
+        StringBuilder sb = new StringBuilder();
+        for (int i = 2; i < pathFragments.length; i++) {
+            if (pathFragments[i].length() == 0) {
+                continue;
+            }
+
+            sb.append("/");
+            sb.append(pathFragments[i]);
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Returns the object id of the current request.
+     */
+    public static void prepareContext(CallContext context, CallUrl callUrl, CmisService service, String repositoryId,
+            String objectId, String transaction, HttpServletRequest request) {
+        if (context instanceof CallContextImpl) {
+            ((CallContextImpl) context).put(CONTEXT_TRANSACTION, transaction);
+        }
+
+        if (callUrl != CallUrl.ROOT) {
+            return;
+        }
+
+        ObjectData object = null;
+
+        if (objectId != null) {
+            object = service.getObject(repositoryId, objectId, null, false, IncludeRelationships.NONE, "cmis:none",
+                    false, false, null);
+        } else {
+            object = service.getObjectByPath(repositoryId, getPath(request), null, false, IncludeRelationships.NONE,
+                    "cmis:none", false, false, null);
+        }
+
+        if (context instanceof CallContextImpl) {
+            ((CallContextImpl) context).put(CONTEXT_OBJECT_ID, object.getId());
+            ((CallContextImpl) context).put(CONTEXT_OBJECT_TYPE_ID,
+                    getProperty(object, PropertyIds.OBJECT_TYPE_ID, String.class));
+            ((CallContextImpl) context).put(CONTEXT_BASETYPE_ID,
+                    getProperty(object, PropertyIds.BASE_TYPE_ID, String.class));
+        }
+    }
+
+    /**
+     * Extracts a property from an object.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getProperty(ObjectData object, String name, Class<T> clazz) {
+        if (object == null) {
+            return null;
+        }
+
+        Properties propData = object.getProperties();
+        if (propData == null) {
+            return null;
+        }
+
+        Map<String, PropertyData<?>> properties = propData.getProperties();
+        if (properties == null) {
+            return null;
+        }
+
+        PropertyData<?> property = properties.get(name);
+        if (property == null) {
+            return null;
+        }
+
+        Object value = property.getFirstValue();
+        if (!clazz.isInstance(value)) {
+            return null;
+        }
+
+        return (T) value;
+    }
+
+    public static Properties createProperties(ControlParser controlParser, String typeId, TypeCache typeCache) {
+        List<String> propertyIds = controlParser.getValues(CONTROL_PROP_ID);
+        if (propertyIds == null) {
+            return null;
+        }
+
+        Map<Integer, String> singleValuePropertyMap = controlParser.getOneDimMap(CONTROL_PROP_VALUE);
+        Map<Integer, Map<Integer, String>> multiValuePropertyMap = controlParser.getTwoDimMap(CONTROL_PROP_VALUE);
+
+        if (typeId == null) {
+            // it's a create call -> find type id in properties
+            int i = 0;
+            for (String propertId : propertyIds) {
+                if (PropertyIds.OBJECT_TYPE_ID.equals(propertId)) {
+                    typeId = singleValuePropertyMap.get(i);
+                    break;
+                }
+
+                i++;
+            }
+
+            if (typeId == null) {
+                throw new CmisInvalidArgumentException(PropertyIds.OBJECT_TYPE_ID + " not set!");
+            }
+        }
+
+        TypeDefinition typeDef = typeCache.getTypeDefinition(typeId);
+        if (typeDef == null) {
+            throw new CmisInvalidArgumentException("Invalid type: " + typeId);
+        }
+
+        PropertiesImpl result = new PropertiesImpl();
+
+        int i = 0;
+        for (String propertyId : propertyIds) {
+            PropertyDefinition<?> propDef = typeDef.getPropertyDefinitions().get(propertyId);
+            if (propDef == null) {
+                throw new CmisInvalidArgumentException(propertyId + " is unknown!");
+            }
+
+            PropertyData<?> propertyData = null;
+
+            if (singleValuePropertyMap.containsKey(i)) {
+                propertyData = createPropertyData(propDef, singleValuePropertyMap.get(i));
+            } else if (multiValuePropertyMap.containsKey(i)) {
+                propertyData = createPropertyData(propDef, controlParser.getValues(CONTROL_PROP_VALUE, i));
+            } else {
+                propertyData = createPropertyData(propDef, null);
+            }
+
+            result.addProperty(propertyData);
+
+            i++;
+        }
+
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static PropertyData<?> createPropertyData(PropertyDefinition<?> propDef, Object value) {
+
+        List<String> strValues;
+        if (value == null) {
+            strValues = Collections.emptyList();
+        } else if (value instanceof String) {
+            strValues = new ArrayList<String>();
+            strValues.add((String) value);
+        } else {
+            strValues = (List<String>) value;
+        }
+
+        PropertyData<?> propertyData = null;
+        switch (propDef.getPropertyType()) {
+        case STRING:
+            propertyData = new PropertyStringImpl(propDef.getId(), strValues);
+            break;
+        case ID:
+            propertyData = new PropertyIdImpl(propDef.getId(), strValues);
+            break;
+        case BOOLEAN:
+            List<Boolean> boolValues = new ArrayList<Boolean>(strValues.size());
+            try {
+                for (String s : strValues) {
+                    boolValues.add(Boolean.valueOf(s));
+                }
+            } catch (NumberFormatException e) {
+                throw new CmisInvalidArgumentException(propDef.getId() + " value is not a boolean value!");
+            }
+            propertyData = new PropertyBooleanImpl(propDef.getId(), boolValues);
+            break;
+        case INTEGER:
+            List<BigInteger> intValues = new ArrayList<BigInteger>(strValues.size());
+            try {
+                for (String s : strValues) {
+                    intValues.add(new BigInteger(s));
+                }
+            } catch (NumberFormatException e) {
+                throw new CmisInvalidArgumentException(propDef.getId() + " value is not an integer value!");
+            }
+            propertyData = new PropertyIntegerImpl(propDef.getId(), intValues);
+            break;
+        case DECIMAL:
+            List<BigDecimal> decValues = new ArrayList<BigDecimal>(strValues.size());
+            try {
+                for (String s : strValues) {
+                    decValues.add(new BigDecimal(s));
+                }
+            } catch (NumberFormatException e) {
+                throw new CmisInvalidArgumentException(propDef.getId() + " value is not an integer value!");
+            }
+            propertyData = new PropertyDecimalImpl(propDef.getId(), decValues);
+            break;
+        case DATETIME:
+            List<GregorianCalendar> calValues = new ArrayList<GregorianCalendar>(strValues.size());
+            try {
+                for (String s : strValues) {
+                    GregorianCalendar cal = new GregorianCalendar();
+                    cal.setTimeInMillis(Long.parseLong(s));
+                    calValues.add(cal);
+                }
+            } catch (NumberFormatException e) {
+                throw new CmisInvalidArgumentException(propDef.getId() + " value is not an datetime value!");
+            }
+            propertyData = new PropertyDateTimeImpl(propDef.getId(), calValues);
+            break;
+        case HTML:
+            propertyData = new PropertyHtmlImpl(propDef.getId(), strValues);
+            break;
+        case URI:
+            propertyData = new PropertyUriImpl(propDef.getId(), strValues);
+            break;
+        }
+
+        return propertyData;
+    }
+
+    public static List<String> createPolicies(ControlParser controlParser) {
+        return controlParser.getValues(CONTROL_POLICY);
+    }
+
+    public static Acl createAddAcl(ControlParser controlParser) {
+        List<String> principals = controlParser.getValues(CONTROL_ADD_ACE_PRINCIPAL);
+        if (principals == null) {
+            return null;
+        }
+
+        List<Ace> aces = new ArrayList<Ace>();
+
+        int i = 0;
+        for (String principalId : principals) {
+            aces.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(principalId), controlParser
+                    .getValues(CONTROL_ADD_ACE_PERMISSION, i)));
+            i++;
+        }
+
+        return new AccessControlListImpl(aces);
+    }
+
+    public static Acl createRemoveAcl(ControlParser controlParser) {
+        List<String> principals = controlParser.getValues(CONTROL_REMOVE_ACE_PRINCIPAL);
+        if (principals == null) {
+            return null;
+        }
+
+        List<Ace> aces = new ArrayList<Ace>();
+
+        int i = 0;
+        for (String principalId : principals) {
+            aces.add(new AccessControlEntryImpl(new AccessControlPrincipalDataImpl(principalId), controlParser
+                    .getValues(CONTROL_REMOVE_ACE_PERMISSION, i)));
+            i++;
+        }
+
+        return new AccessControlListImpl(aces);
+    }
+
+    public static ContentStream createContentStream(HttpServletRequest request) {
+        ContentStreamImpl result = null;
+
+        if (request instanceof POSTHttpServletRequestWrapper) {
+            POSTHttpServletRequestWrapper post = (POSTHttpServletRequestWrapper) request;
+            result = new ContentStreamImpl(post.getFilename(), BigInteger.valueOf(post.getSize()),
+                    post.getContentType(), post.getStream());
+        }
+
+        return result;
+    }
+
+    /**
+     * Transforms the transaction into a cookie name.
+     */
+    public static String getCookieName(String transaction) {
+        if ((transaction == null) || (transaction.length() == 0)) {
+            return "cmis%";
+        }
+
+        return "cmis_" + Base64.encodeBytes(transaction.getBytes()).replace('=', '%');
+    }
+
+    /**
+     * Sets a transaction cookie.
+     */
+    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String repositoryId,
+            String transaction, String value) {
+        setCookie(request, response, repositoryId, transaction, value, 3600);
+    }
+
+    /**
+     * Deletes a transaction cookie.
+     */
+    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String repositoryId,
+            String transaction) {
+        setCookie(request, response, repositoryId, transaction, "", 0);
+    }
+
+    /**
+     * Sets a transaction cookie.
+     */
+    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String repositoryId,
+            String transaction, String value, int expiry) {
+        if ((transaction != null) && (transaction.length() > 0)) {
+            Cookie tansactionCookie = new Cookie(BrowserBindingUtils.getCookieName(transaction), value);
+            tansactionCookie.setMaxAge(expiry);
+            tansactionCookie.setPath(request.getContextPath() + request.getServletPath() + "/" + repositoryId);
+            response.addCookie(tansactionCookie);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static String createCookieValue(int code, String objectId, String ex, String message) {
+        JSONObject result = new JSONObject();
+
+        result.put("code", code);
+        result.put("objectId", objectId == null ? "" : objectId);
+        result.put("exception", ex == null ? "" : ex);
+        result.put("message", message == null ? "" : message);
+
+        return result.toJSONString();
+    }
+
+    /**
+     * Writes JSON to the servlet response and adds a callback wrapper if
+     * requested.
+     */
+    public static void writeJSON(JSONStreamAware json, HttpServletRequest request, HttpServletResponse response)
+            throws IOException {
+        response.setContentType(JSON_MIME_TYPE);
+        response.setCharacterEncoding("UTF-8");
+
+        String clientToken = getStringParameter(request, PARAM_CLIENTTOKEN);
+        if (clientToken != null) {
+            if (!clientToken.matches("[A-Za-z0-9._\\[\\]]*")) {
+                throw new CmisInvalidArgumentException("Invalid clientToken name!");
+            }
+            response.getWriter().print(clientToken + "(");
+        }
+
+        json.writeJSONString(response.getWriter());
+
+        if (clientToken != null) {
+            response.getWriter().print(");");
+        }
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/BrowserBindingUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java?rev=1094397&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java Mon Apr 18 09:29:45 2011
@@ -0,0 +1,352 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.chemistry.opencmis.server.impl.browser;
+
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
+
+import java.io.IOException;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisFilterNotValidException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisVersioningException;
+import org.apache.chemistry.opencmis.commons.impl.Constants;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory;
+import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener;
+import org.apache.chemistry.opencmis.server.impl.browser.BrowserBindingUtils.CallUrl;
+import org.apache.chemistry.opencmis.server.impl.browser.json.JSONConstants;
+import org.apache.chemistry.opencmis.server.shared.CallContextHandler;
+import org.apache.chemistry.opencmis.server.shared.Dispatcher;
+import org.apache.chemistry.opencmis.server.shared.ExceptionHelper;
+import org.apache.chemistry.opencmis.server.shared.HttpUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.simple.JSONObject;
+
+public class CmisBrowserBindingServlet extends HttpServlet {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final String PARAM_CALL_CONTEXT_HANDLER = "callContextHandler";
+
+    private static final Log LOG = LogFactory.getLog(CmisBrowserBindingServlet.class.getName());
+
+    private Dispatcher repositoryDispatcher;
+    private Dispatcher rootDispatcher;
+    private CallContextHandler callContextHandler;
+
+    @Override
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+
+        // initialize the call context handler
+        callContextHandler = null;
+        String callContextHandlerClass = config.getInitParameter(PARAM_CALL_CONTEXT_HANDLER);
+        if (callContextHandlerClass != null) {
+            try {
+                callContextHandler = (CallContextHandler) Class.forName(callContextHandlerClass).newInstance();
+            } catch (Exception e) {
+                throw new ServletException("Could not load call context handler: " + e, e);
+            }
+        }
+
+        // initialize the dispatchers
+        repositoryDispatcher = new Dispatcher();
+        rootDispatcher = new Dispatcher();
+
+        try {
+            repositoryDispatcher.addResource("", Dispatcher.METHOD_GET, RepositoryService.class, "getRepositoryInfo");
+            repositoryDispatcher.addResource(BrowserBindingUtils.SELECTOR_LAST_RESULT, Dispatcher.METHOD_GET,
+                    RepositoryService.class, "getLastResult");
+            repositoryDispatcher.addResource(BrowserBindingUtils.SELECTOR_TYPE_CHILDREN, Dispatcher.METHOD_GET,
+                    RepositoryService.class, "getTypeChildren");
+            repositoryDispatcher.addResource(BrowserBindingUtils.SELECTOR_TYPE_DESCENDANTS, Dispatcher.METHOD_GET,
+                    RepositoryService.class, "getTypeDescendants");
+            repositoryDispatcher.addResource(BrowserBindingUtils.SELECTOR_TYPE_DEFINITION, Dispatcher.METHOD_GET,
+                    RepositoryService.class, "getTypeDefintion");
+            repositoryDispatcher.addResource(BrowserBindingUtils.SELECTOR_QUERY, Dispatcher.METHOD_GET,
+                    DiscoveryService.class, "query");
+            repositoryDispatcher.addResource(BrowserBindingUtils.CMISACTION_QUERY, Dispatcher.METHOD_POST,
+                    DiscoveryService.class, "query");
+            repositoryDispatcher.addResource(BrowserBindingUtils.CMISACTION_CREATEDOCUMENT, Dispatcher.METHOD_POST,
+                    ObjectService.class, "createDocument");
+
+            rootDispatcher.addResource(BrowserBindingUtils.SELECTOR_OBJECT, Dispatcher.METHOD_GET, ObjectService.class,
+                    "getObject");
+            rootDispatcher.addResource(BrowserBindingUtils.SELECTOR_CONTENT, Dispatcher.METHOD_GET,
+                    ObjectService.class, "getContentStream");
+            rootDispatcher.addResource(BrowserBindingUtils.SELECTOR_CHILDREN, Dispatcher.METHOD_GET,
+                    NavigationService.class, "getChildren");
+            rootDispatcher.addResource(BrowserBindingUtils.SELECTOR_DESCENDANTS, Dispatcher.METHOD_GET,
+                    NavigationService.class, "getDescendants");
+            rootDispatcher.addResource(BrowserBindingUtils.SELECTOR_FOLDER_TREE, Dispatcher.METHOD_GET,
+                    NavigationService.class, "getFolderTree");
+            rootDispatcher.addResource(BrowserBindingUtils.SELECTOR_PARENTS, Dispatcher.METHOD_GET,
+                    NavigationService.class, "getObjectParents");
+            rootDispatcher.addResource(BrowserBindingUtils.SELECTOR_VERSIONS, Dispatcher.METHOD_GET,
+                    VersioningService.class, "getAllVersions");
+            rootDispatcher.addResource(BrowserBindingUtils.CMISACTION_CREATEDOCUMENT, Dispatcher.METHOD_POST,
+                    ObjectService.class, "createDocument");
+            rootDispatcher.addResource(BrowserBindingUtils.CMISACTION_CREATEFOLDER, Dispatcher.METHOD_POST,
+                    ObjectService.class, "createFolder");
+        } catch (NoSuchMethodException e) {
+            LOG.error("Cannot initialize dispatcher!", e);
+        }
+    }
+
+    @Override
+    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,
+            IOException {
+
+        // create a context object, dispatch and handle exceptions
+        CallContext context = null;
+        try {
+            context = HttpUtils.createContext(request, getServletContext(), CallContext.BINDING_BROWSER,
+                    callContextHandler);
+            dispatch(context, request, response);
+        } catch (Exception e) {
+            if (e instanceof CmisPermissionDeniedException) {
+                if ((context == null) || (context.getUsername() == null)) {
+                    response.setHeader("WWW-Authenticate", "Basic realm=\"CMIS\"");
+                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization Required");
+                } else {
+                    printError(e, request, response, context);
+                }
+            } else {
+                printError(e, request, response, context);
+            }
+        }
+
+        // we are done.
+        response.flushBuffer();
+    }
+
+    // --------------------------------------------------------
+
+    private void dispatch(CallContext context, HttpServletRequest request, HttpServletResponse response)
+            throws Exception {
+        CmisService service = null;
+        try {
+            // get services factory
+            CmisServiceFactory factory = (CmisServiceFactory) getServletContext().getAttribute(
+                    CmisRepositoryContextListener.SERVICES_FACTORY);
+
+            if (factory == null) {
+                throw new CmisRuntimeException("Service factory not available! Configuration problem?");
+            }
+
+            // get the service
+            service = factory.getService(context);
+
+            // analyze the path
+            String[] pathFragments = HttpUtils.splitPath(request);
+
+            if (pathFragments.length < 1) {
+                // root -> repository infos
+                RepositoryService.getRepositories(context, service, request, response);
+                return;
+            }
+
+            // select dispatcher
+
+            CallUrl callUrl = null;
+            if (pathFragments.length == 1) {
+                callUrl = CallUrl.REPOSITORY;
+            } else if (BrowserBindingUtils.ROOT_PATH_FRAGMENT.equals(pathFragments[1])) {
+                callUrl = CallUrl.ROOT;
+            }
+
+            if (callUrl == null) {
+                throw new CmisNotSupportedException("Unknown operation");
+            }
+
+            String method = request.getMethod();
+            String repositoryId = pathFragments[0];
+            boolean methodFound = false;
+
+            if (Dispatcher.METHOD_GET.equals(method)) {
+                String selector = HttpUtils.getStringParameter(request, BrowserBindingUtils.PARAM_SELECTOR);
+                String objectId = getStringParameter(request, Constants.PARAM_OBJECT_ID);
+
+                // add object id and object base type id to context
+                BrowserBindingUtils.prepareContext(context, callUrl, service, repositoryId, objectId, null, request);
+
+                // dispatch
+                if (callUrl == CallUrl.REPOSITORY) {
+                    if (selector == null) {
+                        selector = "";
+                    }
+
+                    methodFound = repositoryDispatcher.dispatch(selector, method, context, service, repositoryId,
+                            request, response);
+                } else if (callUrl == CallUrl.ROOT) {
+                    // set default method if necessary
+                    if (selector == null) {
+                        try {
+                            BaseTypeId basetype = BaseTypeId.fromValue((String) context
+                                    .get(BrowserBindingUtils.CONTEXT_BASETYPE_ID));
+                            switch (basetype) {
+                            case CMIS_DOCUMENT:
+                                selector = BrowserBindingUtils.SELECTOR_CONTENT;
+                                break;
+                            case CMIS_FOLDER:
+                                selector = BrowserBindingUtils.SELECTOR_CHILDREN;
+                                break;
+                            default:
+                                selector = BrowserBindingUtils.SELECTOR_OBJECT;
+                                break;
+                            }
+                        } catch (Exception e) {
+                            selector = BrowserBindingUtils.SELECTOR_OBJECT;
+                        }
+                    }
+
+                    methodFound = rootDispatcher.dispatch(selector, method, context, service, repositoryId, request,
+                            response);
+                }
+            } else if (Dispatcher.METHOD_POST.equals(method)) {
+                POSTHttpServletRequestWrapper postRequest = new POSTHttpServletRequestWrapper(request);
+
+                String cmisaction = HttpUtils.getStringParameter(postRequest, BrowserBindingUtils.CONTROL_CMISACTION);
+                String objectId = HttpUtils.getStringParameter(postRequest, BrowserBindingUtils.CONTROL_OBJECT_ID);
+                String transaction = HttpUtils.getStringParameter(postRequest, BrowserBindingUtils.CONTROL_TRANSACTION);
+
+                if ((cmisaction == null) || (cmisaction.length() == 0)) {
+                    throw new CmisNotSupportedException("Unknown action");
+                }
+
+                // add object id and object base type id to context
+                BrowserBindingUtils.prepareContext(context, callUrl, service, repositoryId, objectId, transaction,
+                        postRequest);
+
+                // dispatch
+                if (callUrl == CallUrl.REPOSITORY) {
+                    methodFound = repositoryDispatcher.dispatch(cmisaction, method, context, service, repositoryId,
+                            postRequest, response);
+                } else if (callUrl == CallUrl.ROOT) {
+                    methodFound = rootDispatcher.dispatch(cmisaction, method, context, service, repositoryId,
+                            postRequest, response);
+                }
+            }
+
+            // if the dispatcher couldn't find a matching method, return an
+            // error message
+            if (!methodFound) {
+                throw new CmisNotSupportedException("Unknown operation");
+            }
+        } finally {
+            if (service != null) {
+                service.close();
+            }
+        }
+    }
+
+    /**
+     * Translates an exception in an appropriate HTTP error code.
+     */
+    private int getErrorCode(CmisBaseException ex) {
+        if (ex instanceof CmisConstraintException) {
+            return 409;
+        } else if (ex instanceof CmisContentAlreadyExistsException) {
+            return 409;
+        } else if (ex instanceof CmisFilterNotValidException) {
+            return 400;
+        } else if (ex instanceof CmisInvalidArgumentException) {
+            return 400;
+        } else if (ex instanceof CmisNameConstraintViolationException) {
+            return 409;
+        } else if (ex instanceof CmisNotSupportedException) {
+            return 405;
+        } else if (ex instanceof CmisObjectNotFoundException) {
+            return 404;
+        } else if (ex instanceof CmisPermissionDeniedException) {
+            return 403;
+        } else if (ex instanceof CmisStorageException) {
+            return 500;
+        } else if (ex instanceof CmisStreamNotSupportedException) {
+            return 403;
+        } else if (ex instanceof CmisUpdateConflictException) {
+            return 409;
+        } else if (ex instanceof CmisVersioningException) {
+            return 409;
+        }
+
+        return 500;
+    }
+
+    /**
+     * Prints the error as JSON.
+     */
+    @SuppressWarnings("unchecked")
+    private void printError(Exception ex, HttpServletRequest request, HttpServletResponse response, CallContext context) {
+        int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+        String exceptionName = "runtime";
+
+        if (ex instanceof CmisRuntimeException) {
+            LOG.error(ex.getMessage(), ex);
+        } else if (ex instanceof CmisBaseException) {
+            statusCode = getErrorCode((CmisBaseException) ex);
+            exceptionName = ((CmisBaseException) ex).getExceptionName();
+        } else {
+            LOG.error(ex.getMessage(), ex);
+        }
+
+        response.setStatus(statusCode);
+        response.setContentType(BrowserBindingUtils.JSON_MIME_TYPE);
+        if (context != null) {
+            BrowserBindingUtils.setCookie(request, response, context.getRepositoryId(),
+                    (String) context.get(BrowserBindingUtils.CONTEXT_TRANSACTION),
+                    BrowserBindingUtils.createCookieValue(statusCode, null, exceptionName, ex.getMessage()));
+        }
+
+        JSONObject jsonResponse = new JSONObject();
+        jsonResponse.put(JSONConstants.ERROR_EXCEPTION, exceptionName);
+        jsonResponse.put(JSONConstants.ERROR_MESSAGE, ex.getMessage());
+
+        String st = ExceptionHelper.getStacktraceAsString(ex);
+        if (st != null) {
+            jsonResponse.put(JSONConstants.ERROR_STACKTRACE, st);
+        }
+
+        try {
+            BrowserBindingUtils.writeJSON(jsonResponse, request, response);
+        } catch (Exception e) {
+            LOG.error(e.getMessage(), e);
+        }
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/CmisBrowserBindingServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ControlParser.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ControlParser.java?rev=1094397&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ControlParser.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ControlParser.java Mon Apr 18 09:29:45 2011
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.chemistry.opencmis.server.impl.browser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
+
+/**
+ * Parses HTML form controls.
+ */
+public class ControlParser {
+
+    private HttpServletRequest request;
+
+    private Map<String, String> zeroDim = new HashMap<String, String>();
+    private Map<String, Map<Integer, String>> oneDim = new HashMap<String, Map<Integer, String>>();
+    private Map<String, Map<Integer, Map<Integer, String>>> twoDim = new HashMap<String, Map<Integer, Map<Integer, String>>>();
+
+    public ControlParser(HttpServletRequest request) {
+        this.request = request;
+        parse();
+    }
+
+    @SuppressWarnings("unchecked")
+    private void parse() {
+        // gather all controls
+        Map<String, String[]> controls = request.getParameterMap();
+        for (Map.Entry<String, String[]> control : controls.entrySet()) {
+            String controlName = control.getKey().trim().toLowerCase();
+
+            int firstIndex = getFirstIndex(controlName);
+
+            if (firstIndex == -1) {
+                zeroDim.put(controlName, control.getValue()[0]);
+            } else {
+                String strippedControlName = controlName.substring(0, controlName.indexOf('['));
+                int secondIndex = getSecondIndex(controlName);
+
+                if (secondIndex == -1) {
+                    Map<Integer, String> values = oneDim.get(strippedControlName);
+                    if (values == null) {
+                        values = new HashMap<Integer, String>();
+                        oneDim.put(strippedControlName, values);
+                    }
+
+                    values.put(firstIndex, control.getValue()[0]);
+                } else {
+                    Map<Integer, Map<Integer, String>> values = twoDim.get(strippedControlName);
+                    if (values == null) {
+                        values = new HashMap<Integer, Map<Integer, String>>();
+                        twoDim.put(strippedControlName, values);
+                    }
+
+                    Map<Integer, String> list = values.get(firstIndex);
+                    if (list == null) {
+                        list = new HashMap<Integer, String>();
+                        values.put(firstIndex, list);
+                    }
+
+                    list.put(secondIndex, control.getValue()[0]);
+                }
+            }
+        }
+    }
+
+    private int getFirstIndex(String controlName) {
+        int result = -1;
+
+        int open = controlName.indexOf('[');
+        int close = controlName.indexOf(']');
+
+        if (open == -1 || close == -1 || close < open) {
+            return result;
+        }
+
+        String indexStr = controlName.substring(open + 1, close);
+        try {
+            result = Integer.parseInt(indexStr);
+            if (result < 0) {
+                result = -1;
+            }
+        } catch (NumberFormatException e) {
+        }
+
+        return result;
+    }
+
+    private int getSecondIndex(String controlName) {
+        int result = -1;
+
+        int open = controlName.indexOf("][");
+        int close = controlName.lastIndexOf(']');
+
+        if (open == -1 || close == -1 || close < open) {
+            return result;
+        }
+
+        String indexStr = controlName.substring(open + 2, close);
+        try {
+            result = Integer.parseInt(indexStr);
+            if (result < 0) {
+                result = -1;
+            }
+        } catch (NumberFormatException e) {
+        }
+
+        return result;
+    }
+
+    private List<String> convertToList(String controlName, Map<Integer, String> map) {
+        if (map == null) {
+            return null;
+        }
+
+        int count = map.size();
+        List<String> result = new ArrayList<String>(count);
+
+        for (int i = 0; i < count; i++) {
+            String value = map.get(i);
+            if (value == null) {
+                throw new CmisInvalidArgumentException(controlName + " has gaps!");
+            }
+            result.add(value);
+        }
+
+        return result;
+    }
+
+    public String getValue(String controlName) {
+        if (controlName == null) {
+            throw new IllegalArgumentException("controlName must not be null!");
+        }
+
+        return zeroDim.get(controlName.toLowerCase());
+    }
+
+    public List<String> getValues(String controlName) {
+        if (controlName == null) {
+            throw new IllegalArgumentException("controlName must not be null!");
+        }
+
+        return convertToList(controlName, oneDim.get(controlName.toLowerCase()));
+    }
+
+    public List<String> getValues(String controlName, int index) {
+        if (controlName == null) {
+            throw new IllegalArgumentException("controlName must not be null!");
+        }
+
+        Map<Integer, Map<Integer, String>> map = twoDim.get(controlName.toLowerCase());
+        if (map == null) {
+            return null;
+        }
+
+        return convertToList(controlName, map.get(index));
+    }
+
+    public Map<Integer, String> getOneDimMap(String controlName) {
+        if (controlName == null) {
+            throw new IllegalArgumentException("controlName must not be null!");
+        }
+
+        return oneDim.get(controlName.toLowerCase());
+    }
+
+    public Map<Integer, Map<Integer, String>> getTwoDimMap(String controlName) {
+        if (controlName == null) {
+            throw new IllegalArgumentException("controlName must not be null!");
+        }
+
+        return twoDim.get(controlName.toLowerCase());
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ControlParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/DiscoveryService.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/DiscoveryService.java?rev=1094397&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/DiscoveryService.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/DiscoveryService.java Mon Apr 18 09:29:45 2011
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.chemistry.opencmis.server.impl.browser;
+
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBigIntegerParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBooleanParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getEnumParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
+
+import java.math.BigInteger;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.chemistry.opencmis.commons.data.ObjectList;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.chemistry.opencmis.commons.impl.Constants;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+import org.apache.chemistry.opencmis.server.impl.browser.json.JSONConverter;
+import org.json.simple.JSONObject;
+
+/**
+ * Discovery Service operations.
+ */
+public class DiscoveryService {
+
+    /**
+     * query.
+     */
+    public static void query(CallContext context, CmisService service, String repositoryId, HttpServletRequest request,
+            HttpServletResponse response) throws Exception {
+        // get parameters
+        String statement = getStringParameter(request, Constants.PARAM_Q);
+        Boolean searchAllVersions = getBooleanParameter(request, Constants.PARAM_SEARCH_ALL_VERSIONS);
+        Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
+        IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
+                IncludeRelationships.class);
+        String renditionFilter = null;
+        BigInteger maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
+        BigInteger skipCount = getBigIntegerParameter(request, Constants.PARAM_SKIP_COUNT);
+
+        // execute
+        ObjectList results = service.query(repositoryId, statement, searchAllVersions, includeAllowableActions,
+                includeRelationships, renditionFilter, maxItems, skipCount, null);
+
+        if (results == null) {
+            throw new CmisRuntimeException("Results are null!");
+        }
+
+        JSONObject jsonResults = JSONConverter.convert(results);
+
+        response.setStatus(HttpServletResponse.SC_OK);
+        BrowserBindingUtils.writeJSON(jsonResults, request, response);
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/DiscoveryService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/NavigationService.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/NavigationService.java?rev=1094397&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/NavigationService.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/NavigationService.java Mon Apr 18 09:29:45 2011
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.chemistry.opencmis.server.impl.browser;
+
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBigIntegerParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBooleanParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getEnumParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
+import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
+import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.chemistry.opencmis.commons.impl.Constants;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+import org.apache.chemistry.opencmis.server.impl.browser.json.JSONConverter;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+/**
+ * Navigation Service operations.
+ */
+public final class NavigationService {
+
+    /**
+     * getChildren.
+     */
+    public static void getChildren(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String folderId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        String filter = getStringParameter(request, Constants.PARAM_FILTER);
+        String orderBy = getStringParameter(request, Constants.PARAM_ORDER_BY);
+        Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
+        IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
+                IncludeRelationships.class);
+        String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+        Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
+        BigInteger maxItems = getBigIntegerParameter(request, Constants.PARAM_MAX_ITEMS);
+        BigInteger skipCount = getBigIntegerParameter(request, Constants.PARAM_SKIP_COUNT);
+
+        // execute
+        ObjectInFolderList children = service.getChildren(repositoryId, folderId, filter, orderBy,
+                includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, maxItems,
+                skipCount, null);
+
+        if (children == null) {
+            throw new CmisRuntimeException("Children are null!");
+        }
+
+        TypeCache typeCache = new TypeCache(repositoryId, service);
+        JSONObject jsonChildren = JSONConverter.convert(children, typeCache);
+
+        response.setStatus(HttpServletResponse.SC_OK);
+        BrowserBindingUtils.writeJSON(jsonChildren, request, response);
+    }
+
+    /**
+     * getDescendants.
+     */
+    @SuppressWarnings("unchecked")
+    public static void getDescendants(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String folderId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        BigInteger depth = getBigIntegerParameter(request, Constants.PARAM_DEPTH);
+        String filter = getStringParameter(request, Constants.PARAM_FILTER);
+        Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
+        IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
+                IncludeRelationships.class);
+        String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+        Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
+
+        // execute
+        List<ObjectInFolderContainer> descendants = service.getDescendants(repositoryId, folderId, depth, filter,
+                includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, null);
+
+        if (descendants == null) {
+            throw new CmisRuntimeException("Descendants are null!");
+        }
+
+        TypeCache typeCache = new TypeCache(repositoryId, service);
+        JSONArray jsonDescendants = new JSONArray();
+        for (ObjectInFolderContainer descendant : descendants) {
+            jsonDescendants.add(JSONConverter.convert(descendant, typeCache));
+        }
+
+        response.setStatus(HttpServletResponse.SC_OK);
+        BrowserBindingUtils.writeJSON(jsonDescendants, request, response);
+    }
+
+    /**
+     * getFolderTree.
+     */
+    @SuppressWarnings("unchecked")
+    public static void getFolderTree(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String folderId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        BigInteger depth = getBigIntegerParameter(request, Constants.PARAM_DEPTH);
+        String filter = getStringParameter(request, Constants.PARAM_FILTER);
+        Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
+        IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
+                IncludeRelationships.class);
+        String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+        Boolean includePathSegment = getBooleanParameter(request, Constants.PARAM_PATH_SEGMENT);
+
+        // execute
+        List<ObjectInFolderContainer> folderTree = service.getFolderTree(repositoryId, folderId, depth, filter,
+                includeAllowableActions, includeRelationships, renditionFilter, includePathSegment, null);
+
+        if (folderTree == null) {
+            throw new CmisRuntimeException("Folder Tree are null!");
+        }
+
+        TypeCache typeCache = new TypeCache(repositoryId, service);
+        JSONArray jsonDescendants = new JSONArray();
+        for (ObjectInFolderContainer descendant : folderTree) {
+            jsonDescendants.add(JSONConverter.convert(descendant, typeCache));
+        }
+
+        response.setStatus(HttpServletResponse.SC_OK);
+        BrowserBindingUtils.writeJSON(jsonDescendants, request, response);
+    }
+
+    /**
+     * getObjectParents.
+     */
+    @SuppressWarnings("unchecked")
+    public static void getObjectParents(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String objectId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        String filter = getStringParameter(request, Constants.PARAM_FILTER);
+        Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
+        IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
+                IncludeRelationships.class);
+        String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+        Boolean includeRelativePathSegment = getBooleanParameter(request, Constants.PARAM_RELATIVE_PATH_SEGMENT);
+
+        // execute
+        List<ObjectParentData> parents = service.getObjectParents(repositoryId, objectId, filter,
+                includeAllowableActions, includeRelationships, renditionFilter, includeRelativePathSegment, null);
+
+        if (parents == null) {
+            throw new CmisRuntimeException("Parents are null!");
+        }
+
+        TypeCache typeCache = new TypeCache(repositoryId, service);
+        JSONArray jsonParents = new JSONArray();
+        for (ObjectParentData parent : parents) {
+            jsonParents.add(JSONConverter.convert(parent, typeCache));
+        }
+
+        response.setStatus(HttpServletResponse.SC_OK);
+        BrowserBindingUtils.writeJSON(jsonParents, request, response);
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/NavigationService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ObjectService.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ObjectService.java?rev=1094397&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ObjectService.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ObjectService.java Mon Apr 18 09:29:45 2011
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.chemistry.opencmis.server.impl.browser;
+
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getBooleanParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getEnumParameter;
+import static org.apache.chemistry.opencmis.server.shared.HttpUtils.getStringParameter;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.data.ObjectData;
+import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
+import org.apache.chemistry.opencmis.commons.enums.VersioningState;
+import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.chemistry.opencmis.commons.impl.Constants;
+import org.apache.chemistry.opencmis.commons.impl.ReturnVersion;
+import org.apache.chemistry.opencmis.commons.server.CallContext;
+import org.apache.chemistry.opencmis.commons.server.CmisService;
+import org.apache.chemistry.opencmis.commons.server.ObjectInfo;
+import org.apache.chemistry.opencmis.server.impl.browser.json.JSONConverter;
+import org.json.simple.JSONObject;
+
+/**
+ * Object Service operations.
+ */
+public final class ObjectService {
+
+    private static final int BUFFER_SIZE = 64 * 1024;
+
+    /**
+     * createDocument.
+     */
+    public static void createDocument(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String folderId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        VersioningState versioningState = getEnumParameter(request, Constants.PARAM_VERSIONIG_STATE,
+                VersioningState.class);
+        String transaction = getStringParameter(request, BrowserBindingUtils.PARAM_TRANSACTION);
+
+        ControlParser cp = new ControlParser(request);
+
+        TypeCache typeCache = new TypeCache(repositoryId, service);
+
+        String newObjectId = service.createDocument(repositoryId,
+                BrowserBindingUtils.createProperties(cp, null, typeCache), folderId,
+                BrowserBindingUtils.createContentStream(request), versioningState,
+                BrowserBindingUtils.createPolicies(cp), BrowserBindingUtils.createAddAcl(cp),
+                BrowserBindingUtils.createRemoveAcl(cp), null);
+
+        ObjectInfo objectInfo = service.getObjectInfo(repositoryId, newObjectId);
+        if (objectInfo == null) {
+            throw new CmisRuntimeException("Object Info is missing!");
+        }
+
+        ObjectData object = objectInfo.getObject();
+        if (object == null) {
+            throw new CmisRuntimeException("Object is null!");
+        }
+
+        JSONObject jsonObject = JSONConverter.convert(object, typeCache);
+
+        response.setStatus(HttpServletResponse.SC_CREATED);
+        BrowserBindingUtils.setCookie(request, response, repositoryId, transaction,
+                BrowserBindingUtils.createCookieValue(HttpServletResponse.SC_CREATED, object.getId(), null, null));
+
+        BrowserBindingUtils.writeJSON(jsonObject, request, response);
+    }
+
+    /**
+     * createFolder.
+     */
+    public static void createFolder(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String folderId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        String transaction = getStringParameter(request, BrowserBindingUtils.PARAM_TRANSACTION);
+
+        ControlParser cp = new ControlParser(request);
+
+        TypeCache typeCache = new TypeCache(repositoryId, service);
+
+        String newObjectId = service.createFolder(repositoryId,
+                BrowserBindingUtils.createProperties(cp, null, typeCache), folderId,
+                BrowserBindingUtils.createPolicies(cp), BrowserBindingUtils.createAddAcl(cp),
+                BrowserBindingUtils.createRemoveAcl(cp), null);
+
+        ObjectInfo objectInfo = service.getObjectInfo(repositoryId, newObjectId);
+        if (objectInfo == null) {
+            throw new CmisRuntimeException("Object Info is missing!");
+        }
+
+        ObjectData object = objectInfo.getObject();
+        if (object == null) {
+            throw new CmisRuntimeException("Object is null!");
+        }
+
+        JSONObject jsonObject = JSONConverter.convert(object, typeCache);
+
+        response.setStatus(HttpServletResponse.SC_CREATED);
+        BrowserBindingUtils.setCookie(request, response, repositoryId, transaction,
+                BrowserBindingUtils.createCookieValue(HttpServletResponse.SC_CREATED, object.getId(), null, null));
+
+        BrowserBindingUtils.writeJSON(jsonObject, request, response);
+    }
+
+    /**
+     * getObject.
+     */
+    public static void getObject(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String objectId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        ReturnVersion returnVersion = getEnumParameter(request, Constants.PARAM_RETURN_VERSION, ReturnVersion.class);
+        String filter = getStringParameter(request, Constants.PARAM_FILTER);
+        Boolean includeAllowableActions = getBooleanParameter(request, Constants.PARAM_ALLOWABLE_ACTIONS);
+        IncludeRelationships includeRelationships = getEnumParameter(request, Constants.PARAM_RELATIONSHIPS,
+                IncludeRelationships.class);
+        String renditionFilter = getStringParameter(request, Constants.PARAM_RENDITION_FILTER);
+        Boolean includePolicyIds = getBooleanParameter(request, Constants.PARAM_POLICY_IDS);
+        Boolean includeAcl = getBooleanParameter(request, Constants.PARAM_ACL);
+
+        // execute
+        ObjectData object = null;
+
+        if ((returnVersion == ReturnVersion.LATEST) || (returnVersion == ReturnVersion.LASTESTMAJOR)) {
+            object = service.getObjectOfLatestVersion(repositoryId, objectId, null,
+                    returnVersion == ReturnVersion.LASTESTMAJOR, filter, includeAllowableActions, includeRelationships,
+                    renditionFilter, includePolicyIds, includeAcl, null);
+        } else {
+            object = service.getObject(repositoryId, objectId, filter, includeAllowableActions, includeRelationships,
+                    renditionFilter, includePolicyIds, includeAcl, null);
+        }
+
+        if (object == null) {
+            throw new CmisRuntimeException("Object is null!");
+        }
+
+        TypeCache typeCache = new TypeCache(repositoryId, service);
+        JSONObject jsonObject = JSONConverter.convert(object, typeCache);
+
+        response.setStatus(HttpServletResponse.SC_OK);
+        BrowserBindingUtils.writeJSON(jsonObject, request, response);
+    }
+
+    /**
+     * getContentStream.
+     */
+    public static void getContentStream(CallContext context, CmisService service, String repositoryId,
+            HttpServletRequest request, HttpServletResponse response) throws Exception {
+        // get parameters
+        String objectId = (String) context.get(BrowserBindingUtils.CONTEXT_OBJECT_ID);
+        String streamId = getStringParameter(request, Constants.PARAM_STREAM_ID);
+
+        BigInteger offset = context.getOffset();
+        BigInteger length = context.getLength();
+
+        // execute
+        ContentStream content = service.getContentStream(repositoryId, objectId, streamId, offset, length, null);
+
+        if ((content == null) || (content.getStream() == null)) {
+            throw new CmisRuntimeException("Content stream is null!");
+        }
+
+        String contentType = content.getMimeType();
+        if (contentType == null) {
+            contentType = Constants.MEDIATYPE_OCTETSTREAM;
+        }
+
+        // set headers
+        if ((offset == null) && (length == null)) {
+            response.setStatus(HttpServletResponse.SC_OK);
+        } else {
+            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
+        }
+        response.setContentType(contentType);
+
+        // send content
+        InputStream in = new BufferedInputStream(content.getStream(), BUFFER_SIZE);
+        OutputStream out = new BufferedOutputStream(response.getOutputStream());
+
+        byte[] buffer = new byte[BUFFER_SIZE];
+        int b;
+        while ((b = in.read(buffer)) > -1) {
+            out.write(buffer, 0, b);
+        }
+
+        in.close();
+        out.flush();
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/ObjectService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java?rev=1094397&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java Mon Apr 18 09:29:45 2011
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.chemistry.opencmis.server.impl.browser;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.chemistry.opencmis.commons.impl.Constants;
+import org.apache.chemistry.opencmis.server.shared.HttpUtils;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+public class POSTHttpServletRequestWrapper extends HttpServletRequestWrapper {
+    private boolean isMultipart;
+    private Map<String, String[]> parameters;
+    private String filename;
+    private String contentType;
+    private long size;
+    private InputStream stream;
+
+    public POSTHttpServletRequestWrapper(HttpServletRequest request) throws Exception {
+        this(request, 4 * 1024 * 1024);
+    }
+
+    public POSTHttpServletRequestWrapper(HttpServletRequest request, int memoryThreshold) throws Exception {
+        super(request);
+
+        isMultipart = ServletFileUpload.isMultipartContent(request);
+
+        if (isMultipart) {
+            parameters = new HashMap<String, String[]>();
+
+            DiskFileItemFactory itemFactory = new DiskFileItemFactory();
+            itemFactory.setSizeThreshold(memoryThreshold);
+
+            ServletFileUpload upload = new ServletFileUpload(itemFactory);
+            @SuppressWarnings("unchecked")
+            List<FileItem> fileItems = upload.parseRequest(request);
+
+            for (FileItem item : fileItems) {
+                if (item.isFormField()) {
+                    String[] values = parameters.get(item.getFieldName());
+
+                    if (values == null) {
+                        parameters.put(item.getFieldName(), new String[] { item.getString() });
+                    } else {
+                        String[] newValues = new String[values.length + 1];
+                        System.arraycopy(values, 0, newValues, 0, values.length);
+                        newValues[newValues.length - 1] = item.getString();
+                        parameters.put(item.getFieldName(), newValues);
+                    }
+                } else {
+                    filename = item.getName();
+                    contentType = (item.getContentType() == null ? Constants.MEDIATYPE_OCTETSTREAM : item
+                            .getContentType());
+                    size = item.getSize();
+                    stream = item.getInputStream();
+                }
+            }
+
+            String filenameControl = HttpUtils.getStringParameter(this, BrowserBindingUtils.CONTROL_FILENAME);
+            if ((filenameControl) != null && (filenameControl.trim().length() > 0)) {
+                filename = filenameControl;
+            }
+
+            String contentTypeControl = HttpUtils.getStringParameter(this, BrowserBindingUtils.CONTROL_CONTENT_TYPE);
+            if ((contentTypeControl != null) && (contentTypeControl.trim().length() > 0)) {
+                contentType = contentTypeControl;
+            }
+        }
+    }
+
+    @Override
+    public String getParameter(String name) {
+        if (!isMultipart) {
+            return super.getParameter(name);
+        }
+
+        String[] values = parameters.get(name);
+        if ((values == null) || (values.length == 0)) {
+            return null;
+        }
+
+        return values[0];
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Map<String, String[]> getParameterMap() {
+        if (!isMultipart) {
+            return super.getParameterMap();
+        }
+
+        return parameters;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Enumeration<String> getParameterNames() {
+        if (!isMultipart) {
+            return super.getParameterNames();
+        }
+
+        return Collections.enumeration(parameters.keySet());
+    }
+
+    @Override
+    public String[] getParameterValues(String name) {
+        if (!isMultipart) {
+            return super.getParameterValues(name);
+        }
+
+        return parameters.get(name);
+    }
+
+    public String getFilename() {
+        return filename;
+    }
+
+    public String getContentType() {
+        return contentType;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public InputStream getStream() {
+        return stream;
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/browser/POSTHttpServletRequestWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native