You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by su...@apache.org on 2012/05/18 09:42:44 UTC

svn commit: r1340016 - in /incubator/stanbol/trunk/commons/web/base/src: main/java/org/apache/stanbol/commons/web/base/ main/resources/OSGI-INF/metatype/ test/java/org/apache/stanbol/commons/web/base/

Author: suat
Date: Fri May 18 07:42:43 2012
New Revision: 1340016

URL: http://svn.apache.org/viewvc?rev=1340016&view=rev
Log:
STANBOL-618:
Added a configuration option (CORS_ACCESS_CONTROL_EXPOSE_HEADERS) to the JerseyEndpoint so that users can specify the headers whose values they would like to access through XMLHttpRequest object in Javascript. The provided headers are returned within the "Access-Control-Expose-Headers" header.

For the time being the default value of this configuration contains only the "Location" header.

Modified:
    incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/CorsHelper.java
    incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/JerseyEndpoint.java
    incubator/stanbol/trunk/commons/web/base/src/main/resources/OSGI-INF/metatype/metatype.properties
    incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/CorsAccessControlAllowMethodTest.java
    incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/MockServletContext.java

Modified: incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/CorsHelper.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/CorsHelper.java?rev=1340016&r1=1340015&r2=1340016&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/CorsHelper.java (original)
+++ incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/CorsHelper.java Fri May 18 07:42:43 2012
@@ -1,23 +1,25 @@
 /*
-* 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.
-*/
+ * 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.stanbol.commons.web.base;
 
 import static org.apache.stanbol.commons.web.base.JerseyEndpoint.CORS_ORIGIN;
+import static org.apache.stanbol.commons.web.base.JerseyEndpoint.CORS_ACCESS_CONTROL_EXPOSE_HEADERS;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -26,17 +28,23 @@ import javax.ws.rs.WebApplicationExcepti
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.core.Response.Status;
+
 /**
- * Utilities for adding <a href="http://dev.w3.org/2006/waf/access-control/">
- * CORS</a> support to the Stanbol RESTful API <p>
- * <p> Note that this utility depends on the 
- * {@link JerseyEndpoint#CORS_ORIGIN} property read from the Servlet Context.<p>
- * Currently this support for<ul>
- * <li> Origin header
- * <li> Preflight Requests.
+ * Utilities for adding <a href="http://dev.w3.org/2006/waf/access-control/"> CORS</a> support to the Stanbol
+ * RESTful API
+ * <p>
+ * <p>
+ * Note that this utility depends on the {@link JerseyEndpoint#CORS_ORIGIN} property read from the Servlet
+ * Context.
+ * <p>
+ * Currently this support for
+ * <ul>
+ * <li>Origin header
+ * <li>Preflight Requests.
  * </ul>
+ * 
  * @author Rupert Westenthaler
- *
+ * 
  */
 public final class CorsHelper {
 
@@ -48,7 +56,7 @@ public final class CorsHelper {
      * The ALLOW_ORIGIN header as added to responses
      */
     public static final String ALLOW_ORIGIN = "Access-Control-Allow-Origin";
-    
+
     /**
      * The "Access-Control-Request-Method" header
      */
@@ -63,68 +71,77 @@ public final class CorsHelper {
      * The "Access-Control-Request-Headers" header
      */
     public static final String ALLOW_HEADERS = "Access-Control-Allow-Headers";
-    
+
     /**
      * The "Access-Control-Allow-Methods" header
      */
     public static final String ALLOW_METHODS = "Access-Control-Allow-Methods";
 
     /**
-     * The default methods for the Access-Control-Request-Method header field.
-     * Set to "GET, POST, OPTIONS"
+     * The "Access-Control-Expose-Headers" header
+     */
+    public static final String EXPOSE_HEADERS = "Access-Control-Expose-Headers";
+
+    /**
+     * The default methods for the Access-Control-Request-Method header field. Set to "GET, POST, OPTIONS"
      */
     public static final String DEFAULT_REQUEST_METHODS = "GET, POST, OPTIONS";
-    
+
     /**
-     * This methods checks the parsed origin against the present configuration
-     * and returns if the data returned by this Stanbol instance can be shared
-     * with the parsed origin.<p>
-     * The allowed <a href="http://enable-cors.org/">CORS</a> origins for this
-     * Stanbol instance are configured for the {@link JerseyEndpoint} component
-     * and added to the {@link ServletContext} under the 
+     * This methods checks the parsed origin against the present configuration and returns if the data
+     * returned by this Stanbol instance can be shared with the parsed origin.
+     * <p>
+     * The allowed <a href="http://enable-cors.org/">CORS</a> origins for this Stanbol instance are configured
+     * for the {@link JerseyEndpoint} component and added to the {@link ServletContext} under the
      * {@link JerseyEndpoint#CORS_ORIGIN} key.
-     * @param origin the origin host
-     * @param context the servlet context
-     * @return <code>true</code> if the configuration includes the pased origin
-     * and the data can be shared with this host. Otherwise <code>false</code>.
+     * 
+     * @param origin
+     *            the origin host
+     * @param context
+     *            the servlet context
+     * @return <code>true</code> if the configuration includes the pased origin and the data can be shared
+     *         with this host. Otherwise <code>false</code>.
      */
     @SuppressWarnings("unchecked")
-    public static boolean checkCorsOrigin(String origin, ServletContext context){
-        Set<String> originsConfig = (Set<String>)context.getAttribute(CORS_ORIGIN);
+    public static boolean checkCorsOrigin(String origin, ServletContext context) {
+        Set<String> originsConfig = (Set<String>) context.getAttribute(CORS_ORIGIN);
         return originsConfig.contains("*") || originsConfig.contains(origin);
     }
+
     /**
-     * Adds the Origin response header to the parsed response builder 
-     * based on the headers of an request.
-     * @param context the ServletContext holding the
-     * {@link JerseyEndpoint#CORS_ORIGIN} configuration.
-     * @param responseBuilder The {@link ResponseBuilder} the origin header is added to
-     * if (1) a origin header is present in the request headers and (1) the parsed
-     * origin is compatible with the configuration set for the {@link JerseyEndpoint}.
-     * @param requestHeaders the request headers
-     * @return <code>true</code> if the origin header was added. Otherwise
-     * <code>false</code>
-     * @throws WebApplicationException it the request headers define multiple
-     * values for the "Origin" header an WebApplicationException with the Status
-     * "BAD_REQUEST" is thrown.
-     */
-    public static boolean addCORSOrigin(ServletContext servletContext, 
-                                    ResponseBuilder responseBuilder, 
-                                    HttpHeaders requestHeaders) throws WebApplicationException {
+     * Adds the Origin response header to the parsed response builder based on the headers of an request.
+     * 
+     * @param context
+     *            the ServletContext holding the {@link JerseyEndpoint#CORS_ORIGIN} configuration.
+     * @param responseBuilder
+     *            The {@link ResponseBuilder} the origin header is added to if (1) a origin header is present
+     *            in the request headers and (1) the parsed origin is compatible with the configuration set
+     *            for the {@link JerseyEndpoint}.
+     * @param requestHeaders
+     *            the request headers
+     * @return <code>true</code> if the origin header was added. Otherwise <code>false</code>
+     * @throws WebApplicationException
+     *             it the request headers define multiple values for the "Origin" header an
+     *             WebApplicationException with the Status "BAD_REQUEST" is thrown.
+     */
+    public static boolean addCORSOrigin(ServletContext servletContext,
+                                        ResponseBuilder responseBuilder,
+                                        HttpHeaders requestHeaders) throws WebApplicationException {
         List<String> originHeaders = requestHeaders.getRequestHeader(CorsHelper.ORIGIN);
-        if(originHeaders != null && !originHeaders.isEmpty()){
-            if(originHeaders.size() != 1){
-                throw new WebApplicationException(
-                    new IllegalStateException("Multiple 'Origin' header values '"+
-                        originHeaders+"' found in the request headers"),
-                        Status.BAD_REQUEST);
+        if (originHeaders != null && !originHeaders.isEmpty()) {
+            if (originHeaders.size() != 1) {
+                throw new WebApplicationException(new IllegalStateException(
+                        "Multiple 'Origin' header values '" + originHeaders
+                                + "' found in the request headers"), Status.BAD_REQUEST);
             } else {
-                Set<String> originsConfig = (Set<String>)servletContext.getAttribute(CORS_ORIGIN);
-                if(originsConfig.contains("*")){ //if config includes *
-                    responseBuilder.header(CorsHelper.ALLOW_ORIGIN, "*"); //add also * to the header
+                Set<String> originsConfig = (Set<String>) servletContext.getAttribute(CORS_ORIGIN);
+                if (originsConfig.contains("*")) { // if config includes *
+                    responseBuilder.header(CorsHelper.ALLOW_ORIGIN, "*"); // add also * to the header
+                    addExposedHeaders(servletContext, responseBuilder, requestHeaders);
                     return true;
-                } else if(originsConfig.contains(originHeaders.get(0))){
-                    //otherwise add the specific Origin host
+                } else if (originsConfig.contains(originHeaders.get(0))) {
+                    // otherwise add the specific Origin host
+                    addExposedHeaders(servletContext, responseBuilder, requestHeaders);
                     responseBuilder.header(CorsHelper.ALLOW_ORIGIN, originHeaders.get(0));
                     return true;
                 }
@@ -132,71 +149,107 @@ public final class CorsHelper {
         }
         return false;
     }
+
     /**
-     * Enable CORS for OPTION requests based on the provided request headers and
-     * the allowMethods.<p>
-     * The {@link #addCORSOrigin(ResponseBuilder, HttpHeaders)} method is used 
-     * deal with the origin. The allowMethods are set to the parsed values or to
-     * {@link CorsHelper#DEFAULT_REQUEST_METHODS} if non is parsed of the
-     * parsed values do not contain a single value that is not <code>null</code>
-     * nor empty.
-     * @param context the ServletContext holding the
-     * {@link JerseyEndpoint#CORS_ORIGIN} configuration.
-     * @param responseBuilder The {@link ResponseBuilder} to add the CORS headers
-     * @param requestHeaders the headers of the request
-     * @param allowMethods the allowMethods to if <code>null</code> or empty, the
-     * {@link CorsHelper#DEFAULT_REQUEST_METHODS} are added
-     * @return <code>true</code> if the CORS header where added or 
-     * @throws WebApplicationException it the request headers define multiple
-     * values for the "Origin" header an WebApplicationException with the Status
-     * "BAD_REQUEST" is thrown.
-     * @throws IllegalArgumentException if a parsed allowMethods is <code>null</code>
-     * or empty. NOT if the String array is <code>null</code> or empty, but if
-     * any of the items within the array is <code>null</code> or empty!
-     */
-    public static boolean enableCORS(ServletContext context,ResponseBuilder responseBuilder, 
-                                       HttpHeaders requestHeaders, 
-                                       String...allowMethods) throws WebApplicationException {
-        //first check if the Origin is present
-        if(addCORSOrigin(context,responseBuilder,requestHeaders)){
-            //now add the allowedMethods
+     * Adds the
+     * 
+     * @param servletContext
+     * @param responseBuilder
+     * @param httpHeaders
+     */
+    private static void addExposedHeaders(ServletContext servletContext,
+                                          ResponseBuilder responseBuilder,
+                                          HttpHeaders httpHeaders) {
+
+        Set<String> exposedHeadersConfig = (Set<String>) servletContext
+                .getAttribute(CORS_ACCESS_CONTROL_EXPOSE_HEADERS);
+        if (exposedHeadersConfig != null && !exposedHeadersConfig.isEmpty()) {
+            StringBuilder requestHeader = new StringBuilder();
+            boolean added = false;
+            for (String header : exposedHeadersConfig) {
+                if (header != null && !header.isEmpty()) {
+                    if (added) {
+                        requestHeader.append(", ");
+                    }
+                    requestHeader.append(header);
+                    added = true;
+                }
+            }
+            if (added) {
+                responseBuilder.header(EXPOSE_HEADERS, requestHeader.toString());
+            }
+        }
+    }
+
+    /**
+     * Enable CORS for OPTION requests based on the provided request headers and the allowMethods.
+     * <p>
+     * The {@link #addCORSOrigin(ResponseBuilder, HttpHeaders)} method is used deal with the origin. The
+     * allowMethods are set to the parsed values or to {@link CorsHelper#DEFAULT_REQUEST_METHODS} if non is
+     * parsed of the parsed values do not contain a single value that is not <code>null</code> nor empty.
+     * 
+     * @param context
+     *            the ServletContext holding the {@link JerseyEndpoint#CORS_ORIGIN} configuration.
+     * @param responseBuilder
+     *            The {@link ResponseBuilder} to add the CORS headers
+     * @param requestHeaders
+     *            the headers of the request
+     * @param allowMethods
+     *            the allowMethods to if <code>null</code> or empty, the
+     *            {@link CorsHelper#DEFAULT_REQUEST_METHODS} are added
+     * @return <code>true</code> if the CORS header where added or
+     * @throws WebApplicationException
+     *             it the request headers define multiple values for the "Origin" header an
+     *             WebApplicationException with the Status "BAD_REQUEST" is thrown.
+     * @throws IllegalArgumentException
+     *             if a parsed allowMethods is <code>null</code> or empty. NOT if the String array is
+     *             <code>null</code> or empty, but if any of the items within the array is <code>null</code>
+     *             or empty!
+     */
+    public static boolean enableCORS(ServletContext context,
+                                     ResponseBuilder responseBuilder,
+                                     HttpHeaders requestHeaders,
+                                     String... allowMethods) throws WebApplicationException {
+        // first check if the Origin is present
+        if (addCORSOrigin(context, responseBuilder, requestHeaders)) {
+            // now add the allowedMethods
             boolean added = false;
             StringBuilder methods = new StringBuilder();
-            if(allowMethods != null){
-                for( String method : allowMethods){
-                    if(method != null && !method.isEmpty()){
-                        if(added){
+            if (allowMethods != null) {
+                for (String method : allowMethods) {
+                    if (method != null && !method.isEmpty()) {
+                        if (added) {
                             methods.append(", ");
                         }
                         methods.append(method);
                         added = true;
                     } else {
-                        //throw an exception to make it easier to debug errors
+                        // throw an exception to make it easier to debug errors
                         throw new IllegalArgumentException("Parsed allow methods MUST NOT be NULL nor empty!");
                     }
                 }
             }
-            if(!added){
+            if (!added) {
                 methods.append(CorsHelper.DEFAULT_REQUEST_METHODS);
             }
             responseBuilder.header(CorsHelper.ALLOW_METHODS, methods.toString());
-            //third replay parsed "Access-Control-Request-Headers" values
-            //currently there is no need to restrict such headers so the simplest
-            //way is to return them as they are parsed
+            // third replay parsed "Access-Control-Request-Headers" values
+            // currently there is no need to restrict such headers so the simplest
+            // way is to return them as they are parsed
             List<String> requestHeaderValues = requestHeaders.getRequestHeader(REQUEST_HEADERS);
             added = false;
-            if(requestHeaderValues != null && !requestHeaderValues.isEmpty()){
-                StringBuilder requestHeader = new StringBuilder();                
-                for(String header : requestHeaderValues){
-                    if(header != null && !header.isEmpty()){
-                        if(added){
+            if (requestHeaderValues != null && !requestHeaderValues.isEmpty()) {
+                StringBuilder requestHeader = new StringBuilder();
+                for (String header : requestHeaderValues) {
+                    if (header != null && !header.isEmpty()) {
+                        if (added) {
                             requestHeader.append(", ");
                         }
                         requestHeader.append(header);
                         added = true;
                     }
                 }
-                if(added){
+                if (added) {
                     responseBuilder.header(ALLOW_HEADERS, requestHeader.toString());
                 }
             }
@@ -204,5 +257,5 @@ public final class CorsHelper {
         } else {
             return false;
         }
-     }
+    }
 }

Modified: incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/JerseyEndpoint.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/JerseyEndpoint.java?rev=1340016&r1=1340015&r2=1340016&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/JerseyEndpoint.java (original)
+++ incubator/stanbol/trunk/commons/web/base/src/main/java/org/apache/stanbol/commons/web/base/JerseyEndpoint.java Fri May 18 07:42:43 2012
@@ -72,6 +72,9 @@ public class JerseyEndpoint {
     @Property(cardinality = 100, value = {"*"})
     public static final String CORS_ORIGIN = "org.apache.stanbol.commons.web.cors.origin";
 
+    @Property(cardinality = 100, value = {"Location"})
+    public static final String CORS_ACCESS_CONTROL_EXPOSE_HEADERS = "org.apache.stanbol.commons.web.cors.access_control_expose_headers";
+
     @Reference
     HttpService httpService;
 
@@ -85,6 +88,8 @@ public class JerseyEndpoint {
 
     protected Set<String> corsOrigins;
 
+    protected Set<String> exposedHeaders;
+
     public Dictionary<String,String> getInitParams() {
         Dictionary<String,String> initParams = new Hashtable<String,String>();
         // make jersey automatically turn resources into Viewable models and
@@ -116,6 +121,24 @@ public class JerseyEndpoint {
             throw new ConfigurationException(CORS_ORIGIN,
                     "CORS origin(s) MUST be a String, String[], Iterable<String> (value:" + values + ")");
         }
+
+        // parse headers to be exposed
+        values = componentContext.getProperties().get(CORS_ACCESS_CONTROL_EXPOSE_HEADERS);
+        if (values instanceof String && !((String) values).isEmpty()) {
+            exposedHeaders = Collections.singleton((String) values);
+        } else if (values instanceof String[]) {
+            exposedHeaders = new HashSet<String>(Arrays.asList((String[]) values));
+        } else if (values instanceof Iterable<?>) {
+            exposedHeaders = new HashSet<String>();
+            for (Object value : (Iterable<?>) values) {
+                if (value != null && !value.toString().isEmpty()) {
+                    exposedHeaders.add(value.toString());
+                }
+            }
+        } else {
+            exposedHeaders = new HashSet<String>();
+        }
+
         if (!webFragments.isEmpty()) {
             initJersey();
         }
@@ -183,6 +206,7 @@ public class JerseyEndpoint {
         servletContext.setAttribute(BaseStanbolResource.SCRIPT_RESOURCES, scriptResources);
         servletContext.setAttribute(BaseStanbolResource.NAVIGATION_LINKS, navigationLinks);
         servletContext.setAttribute(CORS_ORIGIN, corsOrigins);
+        servletContext.setAttribute(CORS_ACCESS_CONTROL_EXPOSE_HEADERS, exposedHeaders);
 
         log.info("JerseyEndpoint servlet registered at {}", applicationAlias);
     }

Modified: incubator/stanbol/trunk/commons/web/base/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/web/base/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1340016&r1=1340015&r2=1340016&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/web/base/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ incubator/stanbol/trunk/commons/web/base/src/main/resources/OSGI-INF/metatype/metatype.properties Fri May 18 07:42:43 2012
@@ -28,4 +28,7 @@ org.apache.stanbol.commons.web.static.ur
 org.apache.stanbol.commons.web.static.url.description=The path to the static resources
 
 org.apache.stanbol.commons.web.cors.origin.name=CORS origins
-org.apache.stanbol.commons.web.cors.origin.description=The CORS origins: This list defines the hosts content returned by Stanbol supports multi-site-scripting. Add '*' to allow any domain. Note: As soon as '*' is added all the other restrictions are ignored. 
\ No newline at end of file
+org.apache.stanbol.commons.web.cors.origin.description=The CORS origins: This list defines the hosts content returned by Stanbol supports multi-site-scripting. Add '*' to allow any domain. Note: As soon as '*' is added all the other restrictions are ignored.
+
+org.apache.stanbol.commons.web.cors.access_control_expose_headers.name=CORS Access-Control-Expose-Headers
+org.apache.stanbol.commons.web.cors.access_control_expose_headers.description=This is a list containing the headers whose values to be accessed through the XMLHttpRequest instance in Java Script.   
\ No newline at end of file

Modified: incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/CorsAccessControlAllowMethodTest.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/CorsAccessControlAllowMethodTest.java?rev=1340016&r1=1340015&r2=1340016&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/CorsAccessControlAllowMethodTest.java (original)
+++ incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/CorsAccessControlAllowMethodTest.java Fri May 18 07:42:43 2012
@@ -1,19 +1,19 @@
 /*
-* 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.
-*/
+ * 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.stanbol.commons.web.base;
 
 import static javax.ws.rs.HttpMethod.GET;
@@ -23,20 +23,13 @@ import static javax.ws.rs.HttpMethod.PUT
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
 
 import javax.servlet.ServletContext;
-import javax.ws.rs.HttpMethod;
-import javax.ws.rs.core.Cookie;
 import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 
-import org.apache.stanbol.commons.web.base.CorsHelper;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -44,13 +37,14 @@ import com.sun.jersey.core.util.Multival
 
 /**
  * Tests issue reported/fix for STANBOL-616
+ * 
  * @author Rupert Westenthaler
- *
+ * 
  */
 public class CorsAccessControlAllowMethodTest {
-    
+
     @Test
-    public void testAccessControlAllowMethodTest(){
+    public void testAccessControlAllowMethodTest() {
         ServletContext context = new MockServletContext();
         context.setAttribute(JerseyEndpoint.CORS_ORIGIN, Collections.singleton("*"));
         MultivaluedMap<String,String> header = new MultivaluedMapImpl();
@@ -59,23 +53,29 @@ public class CorsAccessControlAllowMetho
         header.add("Access-Control-Request-Method", "PUT");
         HttpHeaders requestHeaders = new MockHttpHeaders(header);
 
-        
         ResponseBuilder builder = Response.ok("Test");
-        CorsHelper.enableCORS(context, builder, requestHeaders, OPTIONS,GET,POST,PUT);
+        CorsHelper.enableCORS(context, builder, requestHeaders, OPTIONS, GET, POST, PUT);
         Response response = builder.build();
         MultivaluedMap<String,Object> metadata = response.getMetadata();
-        Assert.assertTrue("'Access-Control-Allow-Headers' expected", metadata.containsKey("Access-Control-Allow-Headers"));
-        String value = (String)metadata.getFirst("Access-Control-Allow-Headers");
+        Assert.assertTrue("'Access-Control-Allow-Headers' expected",
+            metadata.containsKey("Access-Control-Allow-Headers"));
+        String value = (String) metadata.getFirst("Access-Control-Allow-Headers");
         Assert.assertTrue("'Access-Control-Allow-Headers' does not contain the expected values",
             value.contains("Origin") && value.contains("Content-Type") && value.contains("Accept"));
-        Assert.assertTrue("'Access-Control-Allow-Origin' expected", metadata.containsKey("Access-Control-Allow-Origin"));
-        Assert.assertEquals("'Access-Control-Allow-Origin' does not have the expected value '*'",
-            "*", metadata.getFirst("Access-Control-Allow-Origin"));
-        Assert.assertTrue("'Access-Control-Allow-Methods' expected", metadata.containsKey("Access-Control-Allow-Methods"));
-        value = (String)metadata.getFirst("Access-Control-Allow-Methods");
-        Assert.assertTrue("'Access-Control-Allow-Methods' does not contain the expected values", 
+        Assert.assertTrue("'Access-Control-Allow-Origin' expected",
+            metadata.containsKey("Access-Control-Allow-Origin"));
+        Assert.assertEquals("'Access-Control-Allow-Origin' does not have the expected value '*'", "*",
+            metadata.getFirst("Access-Control-Allow-Origin"));
+        Assert.assertTrue("'Access-Control-Allow-Methods' expected",
+            metadata.containsKey("Access-Control-Allow-Methods"));
+        value = (String) metadata.getFirst("Access-Control-Allow-Methods");
+        Assert.assertTrue("'Access-Control-Allow-Methods' does not contain the expected values",
             value.contains(OPTIONS) && value.contains(GET) && value.contains(POST) && value.contains(PUT));
+        Assert.assertTrue("'Access-Control-Expose-Headers' expected",
+            metadata.containsKey("Access-Control-Expose-Headers"));
+        value = (String) metadata.getFirst("Access-Control-Expose-Headers");
+        Assert.assertTrue("'Access-Control-Expose-Headers' does not contain the expected valur 'Location'",
+            value.contains("Location"));
     }
-    
 
 }

Modified: incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/MockServletContext.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/MockServletContext.java?rev=1340016&r1=1340015&r2=1340016&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/MockServletContext.java (original)
+++ incubator/stanbol/trunk/commons/web/base/src/test/java/org/apache/stanbol/commons/web/base/MockServletContext.java Fri May 18 07:42:43 2012
@@ -1,26 +1,28 @@
 /*
-* 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.
-*/
+ * 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.stanbol.commons.web.base;
 
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
@@ -32,23 +34,29 @@ import javax.servlet.ServletException;
 
 /**
  * Only implements attribute related methods
+ * 
  * @author Rupert Westenthaler
- *
+ * 
  */
 public final class MockServletContext implements ServletContext {
 
     private final Map<String,Object> attributes = new HashMap<String,Object>();
-    
-    protected MockServletContext() {}
-    
+
+    protected MockServletContext() {
+        attributes.put(JerseyEndpoint.CORS_ACCESS_CONTROL_EXPOSE_HEADERS,
+            new HashSet<String>(Arrays.asList(new String[] {"Location"})));
+    }
+
     @Override
     public Object getAttribute(String name) {
         return attributes.get(name);
     }
+
     @Override
     public Enumeration getAttributeNames() {
         return new Enumeration<String>() {
             Iterator<String> it = attributes.keySet().iterator();
+
             @Override
             public boolean hasMoreElements() {
                 // TODO Auto-generated method stub
@@ -59,7 +67,7 @@ public final class MockServletContext im
             public String nextElement() {
                 return it.next();
             }
-            
+
         };
     }
 
@@ -73,8 +81,6 @@ public final class MockServletContext im
         attributes.remove(name);
     }
 
-    
-    
     @Override
     public ServletContext getContext(String uripath) {
         return null;
@@ -136,16 +142,13 @@ public final class MockServletContext im
     }
 
     @Override
-    public void log(String msg) {
-    }
+    public void log(String msg) {}
 
     @Override
-    public void log(Exception exception, String msg) {
-    }
+    public void log(Exception exception, String msg) {}
 
     @Override
-    public void log(String message, Throwable throwable) {
-    }
+    public void log(String message, Throwable throwable) {}
 
     @Override
     public String getRealPath(String path) {