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 2015/07/26 18:13:04 UTC

svn commit: r1692729 [1/2] - in /chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/ chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chem...

Author: fmui
Date: Sun Jul 26 16:13:04 2015
New Revision: 1692729

URL: http://svn.apache.org/r1692729
Log:
CMIS-914: added client part of the CMIS Endpoints Document extension

Added:
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/CmisEndpointDocumentReader.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/CmisEndpointDocumentReaderImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisAuthentication.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpoint.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpointsDocument.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisAuthenticationImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentHelper.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/endpoints/
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/endpoints/EndpointsTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/DiscoverLoginTab.java
Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/SessionParameterMap.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/SessionFactory.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/cookies/CmisCookieManager.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractCmisObject.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/test/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryFinderTest.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/SessionParameter.java
    chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/BasicLoginTab.java
    chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/LoginDialog.java
    chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/model/ClientSession.java

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/SessionParameterMap.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/SessionParameterMap.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/SessionParameterMap.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/SessionParameterMap.java Sun Jul 26 16:13:04 2015
@@ -289,7 +289,14 @@ public class SessionParameterMap extends
         }
 
         setUserAndPassword(user, password);
+        setBasicAuthentication();
+    }
 
+    /**
+     * Turns basic authentication on and UsernameToken authentication off if the
+     * standard authentication provider is used.
+     */
+    public void setBasicAuthentication() {
         put(SessionParameter.AUTH_HTTP_BASIC, true);
         put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, false);
         put(SessionParameter.AUTH_OAUTH_BEARER, false);
@@ -316,7 +323,19 @@ public class SessionParameterMap extends
         }
 
         setUserAndPassword(user, password);
+        setUsernameTokenAuthentication(basicAuth);
+    }
 
+    /**
+     * Turns UsernameToken authentication on for the Web Services binding if the
+     * standard authentication provider is used.
+     * 
+     * @param basicAuth
+     *            {@code true} if basic authentication should be used in
+     *            addition to the UsernameToken authentication (required by some
+     *            servers), {@code false} otherwise
+     */
+    public void setUsernameTokenAuthentication(boolean basicAuth) {
         put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, true);
         put(SessionParameter.AUTH_HTTP_BASIC, basicAuth);
         put(SessionParameter.AUTH_OAUTH_BEARER, false);
@@ -341,10 +360,20 @@ public class SessionParameterMap extends
         }
 
         setUserAndPassword(user, password);
+        setNtlmAuthentication();
+    }
 
+    /**
+     * Turns NTLM authentication on and basic authentication and UsernameToken
+     * authentication off.
+     * <p>
+     * <em>Works only in single user environments and only with NTLMv1!</em>
+     */
+    public void setNtlmAuthentication() {
         put(SessionParameter.AUTH_HTTP_BASIC, false);
         put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, false);
         put(SessionParameter.AUTH_OAUTH_BEARER, false);
+
         put(SessionParameter.AUTHENTICATION_PROVIDER_CLASS,
                 "org.apache.chemistry.opencmis.client.bindings.spi.NTLMAuthenticationProvider");
     }
@@ -401,10 +430,6 @@ public class SessionParameterMap extends
             throw new IllegalArgumentException("Client ID must be set!");
         }
 
-        put(SessionParameter.AUTH_HTTP_BASIC, false);
-        put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, false);
-        put(SessionParameter.AUTH_OAUTH_BEARER, false);
-
         put(SessionParameter.OAUTH_TOKEN_ENDPOINT, tokenEntpoint);
         put(SessionParameter.OAUTH_CLIENT_ID, clientId);
 
@@ -426,8 +451,7 @@ public class SessionParameterMap extends
             put(SessionParameter.OAUTH_REDIRECT_URI, redirectUri);
         }
 
-        put(SessionParameter.AUTHENTICATION_PROVIDER_CLASS,
-                "org.apache.chemistry.opencmis.client.bindings.spi.OAuthAuthenticationProvider");
+        setOAuthAuthentication();
     }
 
     /**
@@ -460,10 +484,6 @@ public class SessionParameterMap extends
             throw new IllegalArgumentException("Client ID must be set!");
         }
 
-        put(SessionParameter.AUTH_HTTP_BASIC, false);
-        put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, false);
-        put(SessionParameter.AUTH_OAUTH_BEARER, false);
-
         put(SessionParameter.OAUTH_TOKEN_ENDPOINT, tokenEntpoint);
         put(SessionParameter.OAUTH_CLIENT_ID, clientId);
 
@@ -491,6 +511,18 @@ public class SessionParameterMap extends
             put(SessionParameter.OAUTH_EXPIRATION_TIMESTAMP, expirationTimestamp);
         }
 
+        setOAuthAuthentication();
+    }
+
+    /**
+     * Turns OAuth 2.0 authentication on and basic authentication and
+     * UsernameToken authentication off.
+     */
+    public void setOAuthAuthentication() {
+        put(SessionParameter.AUTH_HTTP_BASIC, false);
+        put(SessionParameter.AUTH_SOAP_USERNAMETOKEN, false);
+        put(SessionParameter.AUTH_OAUTH_BEARER, false);
+
         put(SessionParameter.AUTHENTICATION_PROVIDER_CLASS,
                 "org.apache.chemistry.opencmis.client.bindings.spi.OAuthAuthenticationProvider");
     }
@@ -581,6 +613,20 @@ public class SessionParameterMap extends
     }
 
     /**
+     * Sets the CSRF HTTP header
+     * 
+     * @param csrfHeader
+     *            name of the CSRF header
+     */
+    public void setCsrfHeader(String csrfHeader) {
+        if (csrfHeader != null) {
+            put(SessionParameter.CSRF_HEADER, csrfHeader);
+        } else {
+            remove(SessionParameter.CSRF_HEADER);
+        }
+    }
+
+    /**
      * Sets the HTTP connection timeout.
      * 
      * @param timeout

Added: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/CmisEndpointDocumentReader.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/CmisEndpointDocumentReader.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/CmisEndpointDocumentReader.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/CmisEndpointDocumentReader.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,69 @@
+/*
+ * 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.client.api;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Map;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpointsDocument;
+
+public interface CmisEndpointDocumentReader {
+
+    /**
+     * Reads a CMIS Endpoint Document from a URL.
+     */
+    CmisEndpointsDocument read(URL url) throws IOException;
+
+    /**
+     * Reads a CMIS Endpoint Document from a file.
+     */
+    CmisEndpointsDocument read(File file) throws IOException;
+
+    /**
+     * Reads a CMIS Endpoint Document from a stream.
+     */
+    CmisEndpointsDocument read(InputStream in) throws IOException;
+
+    /**
+     * Reads a CMIS Endpoint Document from a reader.
+     */
+    CmisEndpointsDocument read(Reader in) throws IOException;
+
+    /**
+     * Reads a CMIS Endpoint Document from a String.
+     */
+    CmisEndpointsDocument read(String in);
+
+    /**
+     * Prepares session parameters based on the provides authentication
+     * information.
+     * 
+     * @param authentication
+     *            a CMIS authentication object
+     * 
+     * @return an incomplete set of session parameters, never {@code null}
+     */
+    Map<String, String> pepareSessionParameters(CmisAuthentication authentication);
+
+}

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/SessionFactory.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/SessionFactory.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/SessionFactory.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/SessionFactory.java Sun Jul 26 16:13:04 2015
@@ -72,7 +72,8 @@ public interface SessionFactory {
      *            for parameters supported by OpenCMIS
      * 
      * 
-     * @return a {@link Session} connected to the CMIS repository
+     * @return a {@link Session} connected to the CMIS repository, never
+     *         {@code null}
      * 
      * @see org.apache.chemistry.opencmis.commons.SessionParameter
      */
@@ -89,7 +90,7 @@ public interface SessionFactory {
      *            {@link org.apache.chemistry.opencmis.commons.SessionParameter.REPOSITORY_ID}
      *            should not be set
      * 
-     * @return a list of all available repositories
+     * @return a list of all available repositories, never {@code null}
      * 
      * @see org.apache.chemistry.opencmis.commons.SessionParameter
      */

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/AbstractAuthenticationProvider.java Sun Jul 26 16:13:04 2015
@@ -143,4 +143,19 @@ public abstract class AbstractAuthentica
 
         return null;
     }
+
+    /**
+     * Gets the CSRF header name.
+     * 
+     * @return the CSRF header name or {@code null} if the CSRF header name is
+     *         not set
+     */
+    protected String getCsrfHeader() {
+        Object csrfHeaderObject = getSession().get(SessionParameter.CSRF_HEADER);
+        if (csrfHeaderObject instanceof String) {
+            return (String) csrfHeaderObject;
+        }
+
+        return null;
+    }
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/StandardAuthenticationProvider.java Sun Jul 26 16:13:04 2015
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.chemistry.opencmis.client.bindings.spi.cookies.CmisCookieManager;
 import org.apache.chemistry.opencmis.commons.SessionParameter;
@@ -48,19 +49,23 @@ public class StandardAuthenticationProvi
     protected static final String WSSE_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
     protected static final String WSU_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
 
+    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+
     private CmisCookieManager cookieManager;
     private Map<String, List<String>> fixedHeaders = new HashMap<String, List<String>>();
+    private String csrfHeader;
+    private String csrfValue = "fetch";
 
     @Override
     public void setSession(BindingSession session) {
         super.setSession(session);
 
-        boolean sendBasicAuth = getSendBasicAuth();
-
         if (getHandleCookies() && cookieManager == null) {
             cookieManager = new CmisCookieManager(session.getSessionId());
         }
 
+        boolean sendBasicAuth = getSendBasicAuth();
+
         // basic authentication
         if (sendBasicAuth) {
             // get user and password
@@ -94,6 +99,9 @@ public class StandardAuthenticationProvi
             fixedHeaders.put("Proxy-Authorization", createBasicAuthHeaderValue(proxyUser, proxyPassword));
         }
 
+        // CSRF header
+        csrfHeader = getCsrfHeader();
+
         // other headers
         addSessionParameterHeadersToFixedHeaders();
     }
@@ -102,12 +110,22 @@ public class StandardAuthenticationProvi
     public Map<String, List<String>> getHTTPHeaders(String url) {
         Map<String, List<String>> result = new HashMap<String, List<String>>(fixedHeaders);
 
-        // cookies
-        if (cookieManager != null) {
-            Map<String, List<String>> cookies = cookieManager.get(url, result);
-            if (!cookies.isEmpty()) {
-                result.putAll(cookies);
+        lock.readLock().lock();
+        try {
+            // cookies
+            if (cookieManager != null) {
+                Map<String, List<String>> cookies = cookieManager.get(url, result);
+                if (!cookies.isEmpty()) {
+                    result.putAll(cookies);
+                }
+            }
+
+            // CSRF header
+            if (csrfHeader != null && csrfValue != null) {
+                result.put(csrfHeader, Collections.singletonList(csrfValue));
             }
+        } finally {
+            lock.readLock().unlock();
         }
 
         return result.isEmpty() ? null : result;
@@ -115,8 +133,27 @@ public class StandardAuthenticationProvi
 
     @Override
     public void putResponseHeaders(String url, int statusCode, Map<String, List<String>> headers) {
-        if (cookieManager != null) {
-            cookieManager.put(url, headers);
+        lock.writeLock().lock();
+        try {
+            // cookies
+            if (cookieManager != null) {
+                cookieManager.put(url, headers);
+            }
+
+            // CSRF header
+            if (csrfHeader != null) {
+                for (Map.Entry<String, List<String>> header : headers.entrySet()) {
+                    if (csrfHeader.equalsIgnoreCase(header.getKey())) {
+                        List<String> values = header.getValue();
+                        if (values != null && values.size() > 0) {
+                            csrfValue = values.get(0);
+                        }
+                        break;
+                    }
+                }
+            }
+        } finally {
+            lock.writeLock().unlock();
         }
     }
 
@@ -274,6 +311,16 @@ public class StandardAuthenticationProvi
      * Returns if the authentication provider should handle cookies.
      */
     protected boolean getHandleCookies() {
-        return getSession().get(SessionParameter.COOKIES, false);
+        Object value = getSession().get(SessionParameter.COOKIES);
+
+        if (value instanceof Boolean) {
+            return ((Boolean) value).booleanValue();
+        } else if (value instanceof String) {
+            return Boolean.parseBoolean((String) value);
+        } else if (value == null) {
+            return getCsrfHeader() != null;
+        }
+
+        return false;
     }
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/cookies/CmisCookieManager.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/cookies/CmisCookieManager.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/cookies/CmisCookieManager.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-bindings/src/main/java/org/apache/chemistry/opencmis/client/bindings/spi/cookies/CmisCookieManager.java Sun Jul 26 16:13:04 2015
@@ -28,7 +28,6 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.locks.ReentrantReadWriteLock;

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractCmisObject.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractCmisObject.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractCmisObject.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/AbstractCmisObject.java Sun Jul 26 16:13:04 2015
@@ -138,9 +138,9 @@ public abstract class AbstractCmisObject
                         }
                     }
                 }
+            } else {
+                secondaryTypes = null;
             }
-        } else {
-            secondaryTypes = null;
         }
 
         // handle properties

Added: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/CmisEndpointDocumentReaderImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/CmisEndpointDocumentReaderImpl.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/CmisEndpointDocumentReaderImpl.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/CmisEndpointDocumentReaderImpl.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,146 @@
+/*
+ * 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.client.runtime;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Map;
+
+import org.apache.chemistry.opencmis.client.SessionParameterMap;
+import org.apache.chemistry.opencmis.client.api.CmisEndpointDocumentReader;
+import org.apache.chemistry.opencmis.commons.SessionParameter;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpoint;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpointsDocument;
+import org.apache.chemistry.opencmis.commons.enums.BindingType;
+import org.apache.chemistry.opencmis.commons.impl.endpoints.CmisEndpointsDocumentHelper;
+import org.apache.chemistry.opencmis.commons.impl.json.parser.JSONParseException;
+
+public class CmisEndpointDocumentReaderImpl implements CmisEndpointDocumentReader {
+
+    @Override
+    public CmisEndpointsDocument read(URL url) throws IOException {
+        try {
+            return CmisEndpointsDocumentHelper.read(url);
+        } catch (JSONParseException e) {
+            throw new IllegalArgumentException("Not a CMIS Endpoint Document!", e);
+        }
+    }
+
+    @Override
+    public CmisEndpointsDocument read(File file) throws IOException {
+        try {
+            return CmisEndpointsDocumentHelper.read(file);
+        } catch (JSONParseException e) {
+            throw new IllegalArgumentException("Not a CMIS Endpoint Document!", e);
+        }
+    }
+
+    @Override
+    public CmisEndpointsDocument read(InputStream in) throws IOException {
+        try {
+            return CmisEndpointsDocumentHelper.read(in);
+        } catch (JSONParseException e) {
+            throw new IllegalArgumentException("Not a CMIS Endpoint Document!", e);
+        }
+    }
+
+    @Override
+    public CmisEndpointsDocument read(Reader in) throws IOException {
+        try {
+            return CmisEndpointsDocumentHelper.read(in);
+        } catch (JSONParseException e) {
+            throw new IllegalArgumentException("Not a CMIS Endpoint Document!", e);
+        }
+    }
+
+    @Override
+    public CmisEndpointsDocument read(String in) {
+        try {
+            return CmisEndpointsDocumentHelper.read(in);
+        } catch (JSONParseException e) {
+            throw new IllegalArgumentException("Not a CMIS Endpoint Document!", e);
+        }
+    }
+
+    @Override
+    public Map<String, String> pepareSessionParameters(CmisAuthentication authentication) {
+        if (authentication == null) {
+            throw new IllegalArgumentException("Authentication object must be provided!");
+        }
+        if (authentication.getEndpoint() == null) {
+            throw new IllegalArgumentException("Authentication object has no endpoint information!");
+        }
+
+        SessionParameterMap result = new SessionParameterMap();
+
+        CmisEndpoint endpoint = authentication.getEndpoint();
+
+        // -- binding --
+        String binding = endpoint.getBinding();
+
+        if (CmisEndpoint.BINDING_ATOMPUB.equals(binding)) {
+            result.setAtomPubBindingUrl(endpoint.getUrl());
+        } else if (CmisEndpoint.BINDING_BROWSER.equals(binding)) {
+            result.setBrowserBindingUrl(endpoint.getUrl());
+        } else if (CmisEndpoint.BINDING_WEBSERVICES.equals(binding)) {
+            if (endpoint.getUrl() != null) {
+                result.setWebServicesBindingUrl(endpoint.getUrl());
+            } else {
+                result.put(SessionParameter.BINDING_TYPE, BindingType.WEBSERVICES.value());
+                result.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, endpoint.getRepositoryServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, endpoint.getNavigationServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, endpoint.getObjectServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, endpoint.getVersioningServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, endpoint.getDiscoveryServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, endpoint.getMultifilingServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, endpoint.getRelationshipServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_ACL_SERVICE, endpoint.getAclServiceWdsl());
+                result.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, endpoint.getPolicyServiceWdsl());
+            }
+        }
+
+        // -- authentication --
+        if (CmisAuthentication.AUTH_NONE.equals(authentication.getType())) {
+            result.setNoAuthentication();
+        } else if (CmisAuthentication.AUTH_BASIC.equals(authentication.getType())) {
+            result.setBasicAuthentication();
+        } else if (CmisAuthentication.AUTH_USERNAME_TOKEN.equals(authentication.getType())) {
+            result.setUsernameTokenAuthentication(false);
+        } else if (CmisAuthentication.AUTH_OAUTH.equals(authentication.getType())) {
+            result.setOAuthAuthentication();
+        } else if (CmisAuthentication.AUTH_NTLM.equals(authentication.getType())) {
+            result.setNtlmAuthentication();
+        }
+
+        // -- details --
+        result.setCookies(authentication.requiresCookies()
+                || !CmisEndpoint.COOKIES_OPTIONAL.equals(endpoint.getCookies()));
+        result.setCompression(CmisEndpoint.COMPRESSION_SERVER.equals(endpoint.getCompression())
+                || CmisEndpoint.COMPRESSION_BOTH.equals(endpoint.getCompression()));
+        result.setClientCompression(CmisEndpoint.COMPRESSION_CLIENT.equals(endpoint.getCompression())
+                || CmisEndpoint.COMPRESSION_BOTH.equals(endpoint.getCompression()));
+        result.setCsrfHeader(endpoint.getCsrfHeader());
+
+        return result;
+    }
+}

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryImpl.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryImpl.java Sun Jul 26 16:13:04 2015
@@ -64,6 +64,7 @@ public class SessionFactoryImpl implemen
         return new SessionFactoryImpl();
     }
 
+    @Override
     public Session createSession(Map<String, String> parameters) {
         return createSession(parameters, null, null, null, null);
     }
@@ -108,6 +109,7 @@ public class SessionFactoryImpl implemen
         return session;
     }
 
+    @Override
     public List<Repository> getRepositories(Map<String, String> parameters) {
         return getRepositories(parameters, null, null, null, null);
     }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/test/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryFinderTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/test/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryFinderTest.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/test/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryFinderTest.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/test/java/org/apache/chemistry/opencmis/client/runtime/SessionFactoryFinderTest.java Sun Jul 26 16:13:04 2015
@@ -28,6 +28,7 @@ import org.apache.chemistry.opencmis.cli
 import org.apache.chemistry.opencmis.client.api.Repository;
 import org.apache.chemistry.opencmis.client.api.Session;
 import org.apache.chemistry.opencmis.client.api.SessionFactory;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
 import org.junit.Test;
 
 public class SessionFactoryFinderTest {
@@ -80,6 +81,10 @@ public class SessionFactoryFinderTest {
         public MockSessionFactory1() {
         }
 
+        public Map<String, String> pepareSessionParameters(CmisAuthentication authentication) {
+            return null;
+        }
+
         public Session createSession(Map<String, String> parameters) {
             return null;
         }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/SessionParameter.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/SessionParameter.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/SessionParameter.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/SessionParameter.java Sun Jul 26 16:13:04 2015
@@ -198,6 +198,14 @@ package org.apache.chemistry.opencmis.co
  * <td>-</td>
  * </tr>
  * <tr>
+ * <td>{@link #CSRF_HEADER}</td>
+ * <td>CSRF Header</td>
+ * <td>AtomPub, Web Services, Browser</td>
+ * <td>header name</td>
+ * <td>no</td>
+ * <td>-</td>
+ * </tr>
+ * <tr>
  * <td>{@link #CONNECT_TIMEOUT}</td>
  * <td>HTTP connect timeout</td>
  * <td>AtomPub, Web Services, Browser</td>
@@ -682,6 +690,8 @@ public final class SessionParameter {
     public static final String PROXY_USER = "org.apache.chemistry.opencmis.binding.proxyuser";
     public static final String PROXY_PASSWORD = "org.apache.chemistry.opencmis.binding.proxypassword";
 
+    public static final String CSRF_HEADER = "org.apache.chemistry.opencmis.binding.csrfheader";
+
     // --- cache ---
 
     public static final String CACHE_SIZE_OBJECTS = "org.apache.chemistry.opencmis.cache.objects.size";

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisAuthentication.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisAuthentication.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisAuthentication.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisAuthentication.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,75 @@
+/*
+ * 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.commons.endpoints;
+
+import java.util.Map;
+
+/**
+ * CMIS endpoint authentication information.
+ */
+public interface CmisAuthentication extends Map<String, Object> {
+
+    String KEY_TYPE = "type";
+    String KEY_DISPLAY_NAME = "displayName";
+    String KEY_DOCUMENTATION_URL = "documentationUrl";
+    String KEY_PREFERENCE = "preference";
+
+    String AUTH_NONE = "none";
+    String AUTH_BASIC = "basic";
+    String AUTH_USERNAME_TOKEN = "usernameToken";
+    String AUTH_FORM = "form";
+    String AUTH_CERT = "certificate";
+    String AUTH_SAML = "saml";
+    String AUTH_OAUTH = "oauth";
+    String AUTH_OIDC = "oidc";
+    String AUTH_NTLM = "ntlm";
+    String AUTH_KERBEROS = "kerberos";
+    String AUTH_LTPA = "ltpa";
+
+    String getType();
+
+    String getDisplayName();
+
+    String getDocumentationUrl();
+
+    Integer getPreference();
+
+    /**
+     * Returns the associated CMIS endpoint.
+     * 
+     * @return the endpoint object, never {@code null}
+     */
+    CmisEndpoint getEndpoint();
+
+    /**
+     * Returns if this authentication method requires cookies.
+     * 
+     * Implementations should take following into account:
+     * <ul>
+     * <li>the authentication method (some methods require cookies to work)</li>
+     * <li>the binding and its cookie setting</li>
+     * <li>the CSRF settings</li>
+     * </ul>
+     * 
+     * 
+     * @return {@code true} if cookies are required, {@code false} if cookies
+     *         are not required (they may be recommended, though)
+     */
+    boolean requiresCookies();
+}

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpoint.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpoint.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpoint.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpoint.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,110 @@
+/*
+ * 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.commons.endpoints;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CMIS endpoint.
+ */
+public interface CmisEndpoint extends Map<String, Object> {
+
+    String KEY_DISPLAY_NAME = "displayName";
+    String KEY_CMIS_VERSION = "cmisVersion";
+    String KEY_BINDING = "binding";
+    String KEY_URL = "url";
+    String KEY_REPOSITORY_SERVICE_WSDL = "repositoryServiceWdsl";
+    String KEY_NAVIGATION_SERVICE_WSDL = "navigationServiceWdsl";
+    String KEY_OBJECT_SERVICE_WSDL = "objectServiceWdsl";
+    String KEY_MULTIFILING_SERVICE_WSDL = "multifilingServiceWdsl";
+    String KEY_DISCOVERY_SERVICE_WSDL = "discoveryServiceWdsl";
+    String KEY_VERSIONING_SERVICE_WSDL = "versioningServiceWdsl";
+    String KEY_RELATIONSHIP_SERVICE_WSDL = "relationshipServiceWdsl";
+    String KEY_POLICY_SERVICE_WSDL = "policyServiceWdsl";
+    String KEY_ACL_SERVICE_WSDL = "aclServiceWdsl";
+    String KEY_SOAP_VERSION = "soapVersion";
+    String KEY_COOKIES = "cookies";
+    String KEY_COMPRESSION = "compression";
+    String KEY_CSRF_HEADER = "csrfHeader";
+    String KEY_CSRF_PARAMETER = "csrfParameter";
+    String KEY_AUTHENTICATION = "authentication";
+
+    String VERSION_1_0 = "1.0";
+    String VERSION_1_1 = "1.1";
+
+    String BINDING_WEBSERVICES = "webservices";
+    String BINDING_ATOMPUB = "atompub";
+    String BINDING_BROWSER = "browser";
+
+    String SOAP_VERSION_1_1 = "1.1";
+    String SOAP_VERSION_1_2 = "1.2";
+
+    String COOKIES_REQUIRED = "required";
+    String COOKIES_RECOMMENDED = "recommended";
+    String COOKIES_OPTIONAL = "optional";
+
+    String COMPRESSION_NONE = "none";
+    String COMPRESSION_SERVER = "server";
+    String COMPRESSION_CLIENT = "client";
+    String COMPRESSION_BOTH = "both";
+
+    String getDisplayName();
+
+    String getCmisVersion();
+
+    String getBinding();
+
+    String getUrl();
+
+    String getRepositoryServiceWdsl();
+
+    String getNavigationServiceWdsl();
+
+    String getObjectServiceWdsl();
+
+    String getMultifilingServiceWdsl();
+
+    String getDiscoveryServiceWdsl();
+
+    String getVersioningServiceWdsl();
+
+    String getRelationshipServiceWdsl();
+
+    String getPolicyServiceWdsl();
+
+    String getAclServiceWdsl();
+
+    String getSoapVersion();
+
+    String getCookies();
+
+    String getCompression();
+
+    String getCsrfHeader();
+
+    String getCsrfParameter();
+
+    /**
+     * Returns the list of associated authentication methods.
+     * 
+     * @return list of authentication methods, never {@code null}
+     */
+    List<CmisAuthentication> getAuthentications();
+}
\ No newline at end of file

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpointsDocument.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpointsDocument.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpointsDocument.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/endpoints/CmisEndpointsDocument.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,44 @@
+/*
+ * 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.commons.endpoints;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CMIS endpoints document.
+ */
+public interface CmisEndpointsDocument extends Map<String, Object> {
+
+    String KEY_ENDPOINTS = "endpoints";
+
+    /**
+     * Returns a list of CMIS endpoints.
+     * 
+     * @return list of endpoints, never {@code null}
+     */
+    List<CmisEndpoint> getEndpoints();
+
+    /**
+     * Returns authentication information sorted by perference.
+     * 
+     * @return list of authentication information, never {@code null}
+     */
+    List<CmisAuthentication> getAuthenticationsSortedByPreference();
+}

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisAuthenticationImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisAuthenticationImpl.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisAuthenticationImpl.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisAuthenticationImpl.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,83 @@
+package org.apache.chemistry.opencmis.commons.impl.endpoints;
+
+import java.util.LinkedHashMap;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpoint;
+
+public class CmisAuthenticationImpl extends LinkedHashMap<String, Object> implements CmisAuthentication {
+
+    private static final long serialVersionUID = 1L;
+
+    private CmisEndpoint endpoint;
+
+    public CmisAuthenticationImpl(CmisEndpoint endpoint) {
+        if (endpoint == null) {
+            throw new IllegalArgumentException("Endpoitn must be set!");
+        }
+
+        this.endpoint = endpoint;
+    }
+
+    public CmisAuthenticationImpl(CmisEndpoint endpoint, String type) {
+        this(endpoint);
+        put(KEY_TYPE, type);
+    }
+
+    @Override
+    public String getType() {
+        return getString(KEY_TYPE);
+    }
+
+    @Override
+    public String getDisplayName() {
+        return getString(KEY_DISPLAY_NAME);
+    }
+
+    @Override
+    public String getDocumentationUrl() {
+        return getString(KEY_DOCUMENTATION_URL);
+    }
+
+    @Override
+    public Integer getPreference() {
+        Object value = get(KEY_PREFERENCE);
+        if (value instanceof Number) {
+            return ((Number) value).intValue();
+        }
+
+        return null;
+    }
+
+    @Override
+    public CmisEndpoint getEndpoint() {
+        return endpoint;
+    }
+
+    @Override
+    public boolean requiresCookies() {
+        if (CmisEndpoint.COOKIES_REQUIRED.equals(endpoint.getCookies())) {
+            return true;
+        }
+
+        String type = getType();
+        if (AUTH_FORM.equals(type) || AUTH_SAML.equals(type) || AUTH_LTPA.equals(type)) {
+            return true;
+        }
+
+        if (endpoint.getCsrfHeader() != null || endpoint.getCsrfParameter() == null) {
+            return true;
+        }
+
+        return false;
+    }
+
+    protected String getString(String key) {
+        Object value = get(key);
+        if (value instanceof String) {
+            return (String) value;
+        }
+
+        return null;
+    }
+}

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointImpl.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointImpl.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointImpl.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,150 @@
+/*
+ * 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.commons.impl.endpoints;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpoint;
+
+public class CmisEndpointImpl extends LinkedHashMap<String, Object> implements CmisEndpoint {
+
+    private static final long serialVersionUID = 1L;
+
+    public CmisEndpointImpl() {
+    }
+
+    public CmisEndpointImpl(String cmisVersion, String binding) {
+        put(KEY_CMIS_VERSION, cmisVersion);
+        put(KEY_BINDING, binding);
+    }
+
+    @Override
+    public String getDisplayName() {
+        return getString(KEY_DISPLAY_NAME);
+    }
+
+    @Override
+    public String getCmisVersion() {
+        return getString(KEY_CMIS_VERSION);
+    }
+
+    @Override
+    public String getBinding() {
+        return getString(KEY_BINDING);
+    }
+
+    @Override
+    public String getUrl() {
+        return getString(KEY_URL);
+    }
+
+    @Override
+    public String getRepositoryServiceWdsl() {
+        return getString(KEY_REPOSITORY_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getNavigationServiceWdsl() {
+        return getString(KEY_NAVIGATION_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getObjectServiceWdsl() {
+        return getString(KEY_OBJECT_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getMultifilingServiceWdsl() {
+        return getString(KEY_MULTIFILING_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getDiscoveryServiceWdsl() {
+        return getString(KEY_DISCOVERY_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getVersioningServiceWdsl() {
+        return getString(KEY_VERSIONING_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getRelationshipServiceWdsl() {
+        return getString(KEY_RELATIONSHIP_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getPolicyServiceWdsl() {
+        return getString(KEY_POLICY_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getAclServiceWdsl() {
+        return getString(KEY_ACL_SERVICE_WSDL);
+    }
+
+    @Override
+    public String getSoapVersion() {
+        return getString(KEY_SOAP_VERSION);
+    }
+
+    @Override
+    public String getCookies() {
+        return getString(KEY_COOKIES);
+    }
+
+    @Override
+    public String getCompression() {
+        return getString(KEY_COMPRESSION);
+    }
+
+    @Override
+    public String getCsrfHeader() {
+        return getString(KEY_CSRF_HEADER);
+    }
+
+    @Override
+    public String getCsrfParameter() {
+        return getString(KEY_CSRF_PARAMETER);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<CmisAuthentication> getAuthentications() {
+        Object authentications = get(KEY_AUTHENTICATION);
+
+        if (authentications instanceof List) {
+            return Collections.unmodifiableList((List<CmisAuthentication>) authentications);
+        }
+
+        return Collections.emptyList();
+    }
+
+    protected String getString(String key) {
+        Object value = get(key);
+        if (value instanceof String) {
+            return (String) value;
+        }
+
+        return null;
+    }
+}

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentHelper.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentHelper.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentHelper.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentHelper.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,267 @@
+/*
+ * 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.commons.impl.endpoints;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpoint;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpointsDocument;
+import org.apache.chemistry.opencmis.commons.impl.IOUtils;
+import org.apache.chemistry.opencmis.commons.impl.json.JSONArray;
+import org.apache.chemistry.opencmis.commons.impl.json.JSONObject;
+import org.apache.chemistry.opencmis.commons.impl.json.parser.JSONParseException;
+import org.apache.chemistry.opencmis.commons.impl.json.parser.JSONParser;
+
+/**
+ * CMIS endpoints document helper methods.
+ */
+public class CmisEndpointsDocumentHelper {
+
+    // -- read --
+
+    public static CmisEndpointsDocument read(URL url) throws IOException, JSONParseException {
+        if (url == null) {
+            throw new IllegalArgumentException("URL is null!");
+        }
+
+        InputStream stream = url.openStream();
+        try {
+            return read(stream);
+        } finally {
+            IOUtils.closeQuietly(stream);
+        }
+    }
+
+    public static CmisEndpointsDocument read(File file) throws IOException, JSONParseException {
+        if (file == null) {
+            throw new IllegalArgumentException("File is null!");
+        }
+
+        InputStream stream = new BufferedInputStream(new FileInputStream(file));
+        try {
+            return read(stream);
+        } finally {
+            IOUtils.closeQuietly(stream);
+        }
+    }
+
+    public static CmisEndpointsDocument read(InputStream in) throws IOException, JSONParseException {
+        if (in == null) {
+            throw new IllegalArgumentException("InputStream is null!");
+        }
+
+        return read(new InputStreamReader(in, "UTF-8"));
+    }
+
+    public static CmisEndpointsDocument read(Reader in) throws IOException, JSONParseException {
+        if (in == null) {
+            throw new IllegalArgumentException("Reader is null!");
+        }
+
+        JSONParser parser = new JSONParser();
+        return convert(parser.parse(in));
+    }
+
+    public static CmisEndpointsDocument read(String in) throws JSONParseException {
+        if (in == null) {
+            throw new IllegalArgumentException("String is null!");
+        }
+
+        JSONParser parser = new JSONParser();
+        return convert(parser.parse(in));
+    }
+
+    private static CmisEndpointsDocument convert(Object obj) throws JSONParseException {
+        if (!(obj instanceof JSONObject)) {
+            throw new IllegalArgumentException("JSON is not a CMIS Endpoint Document!");
+        }
+
+        return convertEndpointsDocument((JSONObject) obj);
+    }
+
+    private static CmisEndpointsDocument convertEndpointsDocument(JSONObject json) {
+        CmisEndpointsDocumentImpl result = new CmisEndpointsDocumentImpl();
+
+        for (Map.Entry<String, Object> entry : json.entrySet()) {
+            if (CmisEndpointsDocument.KEY_ENDPOINTS.equals(entry.getKey()) && (entry.getValue() instanceof JSONArray)) {
+                result.put(entry.getKey(), convertEndpoints((JSONArray) entry.getValue()));
+            } else {
+                result.put(entry.getKey(), entry.getValue());
+            }
+        }
+
+        return result;
+    }
+
+    private static List<Object> convertEndpoints(JSONArray json) {
+        List<Object> result = new ArrayList<Object>();
+
+        for (Object item : json) {
+            if (item instanceof JSONObject) {
+                CmisEndpointImpl endpoint = new CmisEndpointImpl();
+
+                for (Map.Entry<String, Object> entry : ((JSONObject) item).entrySet()) {
+                    if (CmisEndpoint.KEY_AUTHENTICATION.equals(entry.getKey())
+                            && (entry.getValue() instanceof JSONArray)) {
+                        endpoint.put(entry.getKey(), convertAuthentication(endpoint, (JSONArray) entry.getValue()));
+                    } else {
+                        endpoint.put(entry.getKey(), entry.getValue());
+                    }
+                }
+
+                result.add(endpoint);
+            } else {
+                result.add(item);
+            }
+        }
+
+        return result;
+    }
+
+    private static List<Object> convertAuthentication(CmisEndpoint endpoint, JSONArray json) {
+        List<Object> result = new ArrayList<Object>();
+
+        for (Object item : json) {
+            if (item instanceof JSONObject) {
+                CmisAuthenticationImpl auth = new CmisAuthenticationImpl(endpoint);
+                auth.putAll((JSONObject) item);
+                result.add(auth);
+            } else {
+                result.add(item);
+            }
+        }
+
+        return result;
+    }
+
+    // -- write --
+
+    public static void write(CmisEndpointsDocument doc, OutputStream out) throws IOException {
+        if (doc == null) {
+            throw new IllegalArgumentException("Document must be set!");
+        }
+        if (out == null) {
+            throw new IllegalArgumentException("OutputStream is null!");
+        }
+
+        Writer writer = new OutputStreamWriter(out, "UTF-8");
+        write(doc, writer);
+        writer.flush();
+    }
+
+    public static void write(CmisEndpointsDocument doc, Writer out) throws IOException {
+        if (doc == null) {
+            throw new IllegalArgumentException("Document must be set!");
+        }
+        if (out == null) {
+            throw new IllegalArgumentException("Writer is null!");
+        }
+
+        JSONObject.writeJSONString(doc, out);
+        out.flush();
+    }
+
+    public static String write(CmisEndpointsDocument doc) {
+        if (doc == null) {
+            throw new IllegalArgumentException("Document must be set!");
+        }
+
+        return JSONObject.toJSONString(doc);
+    }
+
+    public static void write(CmisEndpoint endpoint, OutputStream out) throws IOException {
+        if (endpoint == null) {
+            throw new IllegalArgumentException("Endpoint must be set!");
+        }
+        if (out == null) {
+            throw new IllegalArgumentException("Endpoint is null!");
+        }
+
+        Writer writer = new OutputStreamWriter(out, "UTF-8");
+        write(endpoint, writer);
+        writer.flush();
+    }
+
+    public static void write(CmisEndpoint endpoint, Writer out) throws IOException {
+        if (endpoint == null) {
+            throw new IllegalArgumentException("Endpoint must be set!");
+        }
+        if (out == null) {
+            throw new IllegalArgumentException("Writer is null!");
+        }
+
+        JSONObject.writeJSONString(endpoint, out);
+        out.flush();
+    }
+
+    public static String write(CmisEndpoint endpoint) {
+        if (endpoint == null) {
+            throw new IllegalArgumentException("Endpoint must be set!");
+        }
+
+        return JSONObject.toJSONString(endpoint);
+    }
+
+    public static void write(CmisAuthentication authentication, OutputStream out) throws IOException {
+        if (authentication == null) {
+            throw new IllegalArgumentException("Authentication must be set!");
+        }
+        if (out == null) {
+            throw new IllegalArgumentException("Endpoint is null!");
+        }
+
+        Writer writer = new OutputStreamWriter(out, "UTF-8");
+        write(authentication, writer);
+        writer.flush();
+    }
+
+    public static void write(CmisAuthentication authentication, Writer out) throws IOException {
+        if (authentication == null) {
+            throw new IllegalArgumentException("Authentication must be set!");
+        }
+        if (out == null) {
+            throw new IllegalArgumentException("Writer is null!");
+        }
+
+        JSONObject.writeJSONString(authentication, out);
+        out.flush();
+    }
+
+    public static String write(CmisAuthentication authentication) {
+        if (authentication == null) {
+            throw new IllegalArgumentException("Authentication must be set!");
+        }
+
+        return JSONObject.toJSONString(authentication);
+    }
+}

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentImpl.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentImpl.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/endpoints/CmisEndpointsDocumentImpl.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,83 @@
+/*
+ * 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.commons.impl.endpoints;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpoint;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpointsDocument;
+
+public class CmisEndpointsDocumentImpl extends LinkedHashMap<String, Object> implements CmisEndpointsDocument {
+
+    private static final long serialVersionUID = 1L;
+
+    public CmisEndpointsDocumentImpl() {
+    }
+
+    public CmisEndpointsDocumentImpl(List<CmisEndpoint> endpoints) {
+        put(KEY_ENDPOINTS, endpoints);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<CmisEndpoint> getEndpoints() {
+        Object endpoints = get(KEY_ENDPOINTS);
+
+        if (endpoints instanceof List) {
+            return Collections.unmodifiableList((List<CmisEndpoint>) endpoints);
+        }
+
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<CmisAuthentication> getAuthenticationsSortedByPreference() {
+        List<CmisAuthentication> result = new ArrayList<CmisAuthentication>();
+
+        for (CmisEndpoint endpoint : getEndpoints()) {
+            for (CmisAuthentication authentication : endpoint.getAuthentications()) {
+                result.add(authentication);
+            }
+        }
+
+        Collections.sort(result, new Comparator<CmisAuthentication>() {
+            @Override
+            public int compare(CmisAuthentication ap1, CmisAuthentication ap2) {
+                if (ap1.getPreference() == null && ap2.getPreference() == null) {
+                    return 0;
+                }
+                if (ap1.getPreference() == null) {
+                    return 1;
+                }
+                if (ap2.getPreference() == null) {
+                    return -1;
+                }
+
+                return ap1.getPreference().compareTo(ap2.getPreference());
+            }
+        });
+
+        return result;
+    }
+}

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/endpoints/EndpointsTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/endpoints/EndpointsTest.java?rev=1692729&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/endpoints/EndpointsTest.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/endpoints/EndpointsTest.java Sun Jul 26 16:13:04 2015
@@ -0,0 +1,242 @@
+/*
+ * 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.commons.impl.endpoints;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.chemistry.opencmis.commons.endpoints.CmisAuthentication;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpoint;
+import org.apache.chemistry.opencmis.commons.endpoints.CmisEndpointsDocument;
+import org.junit.Test;
+
+public class EndpointsTest {
+
+    private static final String TEST_JSON = "{" + //
+            "  \"endpoints\" : [" + //
+            "    {" + //
+            "      \"displayName\" : \"DocServ CMIS 1.1 AtomPub Binding\"," + //
+            "      \"cmisVersion\" : \"1.1\"," + //
+            "      \"binding\" : \"atompub\"," + //
+            "      \"url\" : \"https://host:8080/cmis/atompub\"," + //
+            "      \"cookies\" : \"recommended\"," + //
+            "      \"compression\" : \"server\"," + //
+            "      \"csrfHeader\" : \"X-CSRF-Token\"," + //
+            "      \"csrfParameter\" : \"x-token\"," + //
+            "      \"authentication\" : " + //
+            "      [" + //
+            "        {" + //
+            "          \"type\" : \"basic\"," + //
+            "          \"displayName\" : \"HTTP basic authentication\"," + //
+            "          \"documentationUrl\" : \"http://www.example.com/docserv/cmis/basic\"," + //
+            "          \"preference\" : 5" + //
+            "        }," + //
+            "        {" + //
+            "          \"type\" : \"certificate\"," + //
+            "          \"displayName\" : \"SSL certificate authentication for employees\"," + //
+            "          \"documentationUrl\" : \"http://www.example.com/docserv/cmis/cert\"," + //
+            "          \"preference\" : 2" + //
+            "        }" + //
+            "      ]" + //
+            "    }," + //
+            "    {" + //
+            "      \"displayName\" : \"DocServ CMIS 1.1 Browser Binding\"," + //
+            "      \"cmisVersion\" : \"1.1\"," + //
+            "      \"binding\" : \"browser\"," + //
+            "      \"url\" : \"https://host:8080/cmis/browser\"," + //
+            "      \"cookies\" : \"required\"," + //
+            "      \"compression\" : \"server\"," + //
+            "      \"csrfHeader\" : \"X-CSRF-Token\"," + //
+            "      \"csrfParameter\" : \"x-token\"," + //
+            "      \"authentication\" : " + //
+            "      [" + //
+            "        {" + //
+            "          \"type\" : \"basic\"," + //
+            "          \"displayName\" : \"HTTP basic authentication\"," + //
+            "          \"documentationUrl\" : \"http://www.example.com/docserv/cmis/basic\"," + //
+            "          \"preference\" : 4" + //
+            "        }," + //
+            "        {" + //
+            "          \"type\" : \"certificate\"," + //
+            "          \"displayName\" : \"SSL certificate authentication for employees\"," + //
+            "          \"documentationUrl\" : \"http://www.example.com/docserv/cmis/cert\"," + //
+            "          \"preference\" : 1" + //
+            "        }," + //
+            "        {" + //
+            "          \"type\" : \"form\"," + //
+            "          \"displayName\" : \"Form-based authentication for guests\"," + //
+            "          \"loginUrl\" : \"http://host:8080/login\"," + //
+            "          \"documentationUrl\" : \"http://www.example.com/docserv/cmis/form\"," + //
+            "          \"preference\" : 3" + //
+            "        }" + //
+            "      ]" + //
+            "    }" + //
+            "  ]" + //
+            "}";
+
+    @Test
+    public void testReadWrite() throws Exception {
+        StringReader sr = new StringReader(TEST_JSON);
+
+        CmisEndpointsDocument doc = CmisEndpointsDocumentHelper.read(sr);
+        assertNotNull(doc);
+        assertEquals(2, doc.getEndpoints().size());
+
+        List<CmisAuthentication> prefs = doc.getAuthenticationsSortedByPreference();
+        assertNotNull(prefs);
+        assertEquals(5, prefs.size());
+
+        assertEquals(CmisEndpoint.BINDING_BROWSER, prefs.get(0).getEndpoint().getBinding());
+        assertEquals(CmisEndpoint.COOKIES_REQUIRED, prefs.get(0).getEndpoint().getCookies());
+        assertEquals(CmisEndpoint.COMPRESSION_SERVER, prefs.get(0).getEndpoint().getCompression());
+        assertEquals(CmisAuthentication.AUTH_CERT, prefs.get(0).getType());
+        assertTrue(prefs.get(0).requiresCookies());
+
+        assertEquals(CmisEndpoint.BINDING_ATOMPUB, prefs.get(1).getEndpoint().getBinding());
+        assertEquals(CmisEndpoint.COOKIES_RECOMMENDED, prefs.get(1).getEndpoint().getCookies());
+        assertEquals(CmisEndpoint.COMPRESSION_SERVER, prefs.get(1).getEndpoint().getCompression());
+        assertEquals(CmisAuthentication.AUTH_CERT, prefs.get(1).getType());
+        assertTrue(prefs.get(1).requiresCookies());
+
+        assertEquals(CmisEndpoint.BINDING_BROWSER, prefs.get(2).getEndpoint().getBinding());
+        assertEquals(CmisEndpoint.COOKIES_REQUIRED, prefs.get(2).getEndpoint().getCookies());
+        assertEquals(CmisEndpoint.COMPRESSION_SERVER, prefs.get(2).getEndpoint().getCompression());
+        assertEquals(CmisAuthentication.AUTH_FORM, prefs.get(2).getType());
+        assertTrue(prefs.get(2).requiresCookies());
+        assertEquals("http://host:8080/login", prefs.get(2).get("loginUrl"));
+
+        assertEquals(CmisEndpoint.BINDING_BROWSER, prefs.get(3).getEndpoint().getBinding());
+        assertEquals(CmisEndpoint.COOKIES_REQUIRED, prefs.get(3).getEndpoint().getCookies());
+        assertEquals(CmisEndpoint.COMPRESSION_SERVER, prefs.get(3).getEndpoint().getCompression());
+        assertEquals(CmisAuthentication.AUTH_BASIC, prefs.get(3).getType());
+        assertTrue(prefs.get(3).requiresCookies());
+
+        assertEquals(CmisEndpoint.BINDING_ATOMPUB, prefs.get(4).getEndpoint().getBinding());
+        assertEquals(CmisEndpoint.COOKIES_RECOMMENDED, prefs.get(4).getEndpoint().getCookies());
+        assertEquals(CmisEndpoint.COMPRESSION_SERVER, prefs.get(4).getEndpoint().getCompression());
+        assertEquals(CmisAuthentication.AUTH_BASIC, prefs.get(4).getType());
+        assertTrue(prefs.get(1).requiresCookies());
+
+        // -- write --
+        StringWriter sw = new StringWriter();
+        CmisEndpointsDocumentHelper.write(doc, sw);
+        assertNotNull(sw.toString());
+
+        // -- read --
+        CmisEndpointsDocument copyDoc = CmisEndpointsDocumentHelper.read(sw.toString());
+        assertNotNull(copyDoc);
+
+        // -- check --
+        assertEqualsDocument(doc, copyDoc);
+    }
+
+    @Test
+    public void testWriteRead() throws Exception {
+        CmisEndpointImpl epA1 = new CmisEndpointImpl(CmisEndpoint.VERSION_1_0, CmisEndpoint.BINDING_ATOMPUB);
+        epA1.put(CmisEndpoint.KEY_DISPLAY_NAME, "My Endpoint 1");
+        epA1.put(CmisEndpoint.KEY_URL, "http://server1/cmis1");
+        epA1.put(CmisEndpoint.KEY_COOKIES, CmisEndpoint.COOKIES_REQUIRED);
+        epA1.put(CmisEndpoint.KEY_COMPRESSION, CmisEndpoint.COMPRESSION_BOTH);
+        epA1.put(CmisEndpoint.KEY_CSRF_HEADER, "X-CSRF");
+
+        CmisEndpointImpl epA2 = new CmisEndpointImpl(CmisEndpoint.VERSION_1_1, CmisEndpoint.BINDING_BROWSER);
+        epA2.put(CmisEndpoint.KEY_DISPLAY_NAME, "My Endpoint 2");
+        epA2.put(CmisEndpoint.KEY_URL, "http://server2/cmis2");
+
+        CmisEndpointImpl epA3 = new CmisEndpointImpl(CmisEndpoint.VERSION_1_1, CmisEndpoint.BINDING_WEBSERVICES);
+        epA3.put(CmisEndpoint.KEY_SOAP_VERSION, CmisEndpoint.SOAP_VERSION_1_1);
+
+        List<CmisEndpoint> endpoints = new ArrayList<CmisEndpoint>();
+        endpoints.add(epA1);
+        endpoints.add(epA2);
+        endpoints.add(epA3);
+
+        CmisEndpointsDocumentImpl docA = new CmisEndpointsDocumentImpl(endpoints);
+        assertEquals(3, docA.getEndpoints().size());
+
+        // -- write --
+        String json = CmisEndpointsDocumentHelper.write(docA);
+        assertNotNull(json);
+
+        // -- read --
+        CmisEndpointsDocument docB = CmisEndpointsDocumentHelper.read(json);
+        assertNotNull(docB);
+
+        // -- check --
+        assertEqualsDocument(docA, docB);
+    }
+
+    private void assertEqualsDocument(CmisEndpointsDocument expected, CmisEndpointsDocument actual) {
+        assertNotNull(expected);
+        assertNotNull(actual);
+
+        assertEquals(expected.getEndpoints().size(), actual.getEndpoints().size());
+
+        int n = expected.getEndpoints().size();
+        for (int i = 0; i < n; i++) {
+            assertEqualsEndpoint(expected.getEndpoints().get(i), actual.getEndpoints().get(i));
+        }
+    }
+
+    private void assertEqualsEndpoint(CmisEndpoint expected, CmisEndpoint actual) {
+        assertNotNull(expected);
+        assertNotNull(actual);
+
+        assertEquals(expected.getDisplayName(), actual.getDisplayName());
+        assertEquals(expected.getCmisVersion(), actual.getCmisVersion());
+        assertEquals(expected.getBinding(), actual.getBinding());
+        assertEquals(expected.getUrl(), actual.getUrl());
+        assertEquals(expected.getRepositoryServiceWdsl(), actual.getRepositoryServiceWdsl());
+        assertEquals(expected.getNavigationServiceWdsl(), actual.getNavigationServiceWdsl());
+        assertEquals(expected.getObjectServiceWdsl(), actual.getObjectServiceWdsl());
+        assertEquals(expected.getMultifilingServiceWdsl(), actual.getMultifilingServiceWdsl());
+        assertEquals(expected.getDiscoveryServiceWdsl(), actual.getDiscoveryServiceWdsl());
+        assertEquals(expected.getVersioningServiceWdsl(), actual.getVersioningServiceWdsl());
+        assertEquals(expected.getRelationshipServiceWdsl(), actual.getRelationshipServiceWdsl());
+        assertEquals(expected.getPolicyServiceWdsl(), actual.getPolicyServiceWdsl());
+        assertEquals(expected.getSoapVersion(), actual.getSoapVersion());
+        assertEquals(expected.getCookies(), actual.getCookies());
+        assertEquals(expected.getCompression(), actual.getCompression());
+        assertEquals(expected.getCsrfHeader(), actual.getCsrfHeader());
+        assertEquals(expected.getCsrfParameter(), actual.getCsrfParameter());
+
+        assertEquals(expected.getAuthentications().size(), actual.getAuthentications().size());
+
+        int n = expected.getAuthentications().size();
+        for (int i = 0; i < n; i++) {
+            assertEqualsAuthentication(expected.getAuthentications().get(i), actual.getAuthentications().get(i));
+        }
+    }
+
+    private void assertEqualsAuthentication(CmisAuthentication expected, CmisAuthentication actual) {
+        assertNotNull(expected);
+        assertNotNull(actual);
+
+        assertEquals(expected.getType(), actual.getType());
+        assertEquals(expected.getDisplayName(), actual.getDisplayName());
+        assertEquals(expected.getDocumentationUrl(), actual.getDocumentationUrl());
+        assertEquals(expected.getPreference(), actual.getPreference());
+    }
+}

Modified: chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/BasicLoginTab.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/BasicLoginTab.java?rev=1692729&r1=1692728&r2=1692729&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/BasicLoginTab.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-workbench/chemistry-opencmis-workbench/src/main/java/org/apache/chemistry/opencmis/workbench/BasicLoginTab.java Sun Jul 26 16:13:04 2015
@@ -51,6 +51,7 @@ public class BasicLoginTab extends Abstr
     public static final String SYSPROP_READ_TIMEOUT = ClientSession.WORKBENCH_PREFIX + "readtimeout";
     public static final String SYSPROP_USER = ClientSession.WORKBENCH_PREFIX + "user";
     public static final String SYSPROP_PASSWORD = ClientSession.WORKBENCH_PREFIX + "password";
+    public static final String SYSPROP_CSRF_HEADER = ClientSession.WORKBENCH_PREFIX + "csrfheader";
 
     private JTextField urlField;
     private JRadioButton bindingAtomButton;
@@ -68,6 +69,7 @@ public class BasicLoginTab extends Abstr
     private JRadioButton clientCompressionOffButton;
     private JRadioButton cookiesOnButton;
     private JRadioButton cookiesOffButton;
+    private JTextField csrfHeaderField;
     private JFormattedTextField connectTimeoutField;
     private JFormattedTextField readTimeoutField;
 
@@ -98,6 +100,9 @@ public class BasicLoginTab extends Abstr
 
         createCookieButtons(this);
 
+        csrfHeaderField = createTextField(this, "CSRF Header:");
+        csrfHeaderField.setText(System.getProperty(SYSPROP_CSRF_HEADER, ""));
+
         connectTimeoutField = createIntegerField(this, "Connect timeout (secs):");
         try {
             connectTimeoutField.setValue(Long.parseLong(System.getProperty(SYSPROP_CONN_TIMEOUT, "30")));
@@ -112,7 +117,7 @@ public class BasicLoginTab extends Abstr
             readTimeoutField.setValue(600);
         }
 
-        makeCompactGrid(this, 10, 2, 5, 10, 5, 5);
+        makeCompactGrid(this, 11, 2, 5, 10, 5, 5);
     }
 
     private void createBindingButtons(Container pane) {
@@ -272,7 +277,7 @@ public class BasicLoginTab extends Abstr
 
         return ClientSession.createSessionParameters(url, binding, username, password, authentication,
                 compressionOnButton.isSelected(), clientCompressionOnButton.isSelected(), cookiesOnButton.isSelected(),
-                connectTimeout, readTimeout);
+                csrfHeaderField.getText(), connectTimeout, readTimeout);
     }
 
     @Override