incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vram...@apache.org
Subject svn commit: r921261 - in /sling/trunk/bundles/servlets/post/src: main/java/org/apache/sling/servlets/post/impl/ main/java/org/apache/sling/servlets/post/impl/helper/ test/java/org/apache/sling/servlets/post/impl/ test/java/org/apache/sling/servlets/pos...
Date Wed, 10 Mar 2010 09:19:30 GMT
Author: vramdal
Date: Wed Mar 10 09:19:30 2010
New Revision: 921261

URL: http://svn.apache.org/viewvc?rev=921261&view=rev
Log:
SLING-1336 Implement JSON response option for SlingPostServlet

Added:
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/MediaRangeList.java
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/JsonResponseTest.java
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MediaRangeListTest.java
Modified:
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java?rev=921261&r1=921260&r2=921261&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
(original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
Wed Mar 10 09:19:30 2010
@@ -37,6 +37,8 @@ import org.apache.sling.servlets.post.Sl
 import org.apache.sling.servlets.post.SlingPostOperation;
 import org.apache.sling.servlets.post.SlingPostProcessor;
 import org.apache.sling.servlets.post.impl.helper.DateParser;
+import org.apache.sling.servlets.post.impl.helper.JSONResponse;
+import org.apache.sling.servlets.post.impl.helper.MediaRangeList;
 import org.apache.sling.servlets.post.impl.helper.NodeNameGenerator;
 import org.apache.sling.servlets.post.impl.operations.CopyOperation;
 import org.apache.sling.servlets.post.impl.operations.DeleteOperation;
@@ -156,7 +158,7 @@ public class SlingPostServlet extends Sl
             SlingHttpServletResponse response) throws IOException {
 
         // prepare the response
-        HtmlResponse htmlResponse = new HtmlResponse();
+        HtmlResponse htmlResponse = createHtmlResponse(request);
         htmlResponse.setReferer(request.getHeader("referer"));
 
         SlingPostOperation operation = getSlingPostOperation(request);
@@ -199,6 +201,27 @@ public class SlingPostServlet extends Sl
         htmlResponse.send(response, isSetStatus(request));
     }
 
+    /**
+     * Creates an instance of a HtmlResponse.
+     * @param req The request being serviced
+     * @return a {@link org.apache.sling.servlets.post.impl.helper.JSONResponse} if any of
these conditions are true:
+     * <ul>
+     *   <li> the request has an <code>Accept</code> header of <code>application/json</code></li>
+     *   <li>the request is a JSON POST request (see SLING-1172)</li>
+     *   <li>the request has a request parameter <code>:accept=application/json</code></li>
+     * </ul>
+     * or a {@link org.apache.sling.api.servlets.HtmlResponse} otherwise
+     */
+     HtmlResponse createHtmlResponse(SlingHttpServletRequest req) {
+        @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
+        MediaRangeList mediaRangeList = new MediaRangeList(req);
+        if (mediaRangeList.prefer("text/html", JSONResponse.RESPONSE_CONTENT_TYPE).equals(JSONResponse.RESPONSE_CONTENT_TYPE))
{
+            return new JSONResponse();
+        } else {
+            return new HtmlResponse();
+        }
+    }
+
     private SlingPostOperation getSlingPostOperation(
             SlingHttpServletRequest request) {
         String operation = request.getParameter(SlingPostConstants.RP_OPERATION);

Added: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java?rev=921261&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java
(added)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java
Wed Mar 10 09:19:30 2010
@@ -0,0 +1,171 @@
+/*
+ * 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.sling.servlets.post.impl.helper;
+
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Represents a JSON response to be sent to the client. For backward compatibility,
+ * this extends {@link org.apache.sling.api.servlets.HtmlResponse}.
+ */
+public class JSONResponse extends HtmlResponse {
+    private JSONObject json = new JSONObject();
+    private JSONArray changes = new JSONArray();
+    private Boolean delayedIsCreateRequest;
+    static final String PROP_CHANGES = "changes";
+    static final String PROP_TYPE = "type";
+    static final String PROP_ARGUMENT = "argument";
+    public static final String RESPONSE_CONTENT_TYPE = "application/json";
+    static final String RESPONSE_CHARSET = "UTF-8";
+    private Throwable error;
+
+    public JSONResponse() throws JSONResponseException {
+        try {
+            json = new JSONObject();
+            changes = new JSONArray();
+            json.put(PROP_CHANGES, changes);
+            if (delayedIsCreateRequest != null) {
+                this.setCreateRequest(this.delayedIsCreateRequest);
+            }
+        } catch (Throwable e) {
+            throw new JSONResponseException(e);
+        }
+    }
+
+    @Override
+    public void onChange(String type, String... arguments)  throws JSONResponseException
{
+        try {
+            JSONObject change = new JSONObject();
+            change.put(PROP_TYPE, type);
+            for (String argument : arguments) {
+                change.accumulate(PROP_ARGUMENT, argument);
+            }
+            changes.put(change);
+        } catch (JSONException e) {
+            throw new JSONResponseException(e);
+        }
+    }
+
+    @Override
+    public void setError(Throwable error) {
+        try {
+            this.error = error;
+            JSONObject jsonError = new JSONObject();
+            jsonError.put("class", error.getClass().getName());
+            jsonError.put("message", error.getMessage());
+            json.put("error", jsonError);
+        } catch (JSONException e) {
+            throw new JSONResponseException(e);
+        }
+    }
+
+    @Override
+    public Throwable getError() {
+        return this.error;
+    }
+
+    @Override
+    public void setCreateRequest(boolean isCreateRequest) {
+        if (json != null) {
+            super.setCreateRequest(isCreateRequest);
+        } else {
+            // This is called by HtmlResponse constructor, before our json object is initiated.
+            // Store this in a member variable, so we can set it from our own constructor.
+            this.delayedIsCreateRequest = isCreateRequest;
+        }
+    }
+
+    @Override
+    public void setProperty(String name, Object value) {
+        try {
+            this.json.put(name, value);
+        } catch (Throwable e) {
+            throw new JSONResponseException("Error setting JSON property '" + name + "' to
'" + value + "'", e);
+        }
+    }
+
+    @Override
+    public Object getProperty(String name) throws JSONResponseException {
+        try {
+            if (json.has(name)) {
+                return json.get(name);
+            } else {
+                return null;
+            }
+        } catch (JSONException e) {
+            throw new JSONResponseException("Error getting JSON property '" + name + "'",
e);
+        }
+    }
+
+    @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"})
+    @Override
+    public void send(HttpServletResponse response, boolean setStatus) throws IOException
{
+        String path = getPath();
+        if (getProperty(PN_STATUS_CODE) == null) {
+            if (getError() != null) {
+                setStatus(500, getError().toString());
+                setTitle("Error while processing " + path);
+            } else {
+                if (isCreateRequest()) {
+                    setStatus(201, "Created");
+                    setTitle("Content created " + path);
+                } else {
+                    setStatus(200, "OK");
+                    setTitle("Content modified " + path);
+                }
+            }
+        }
+
+        String referer = getReferer();
+        if (referer == null) {
+            referer = "";
+        }
+        setReferer(referer);
+        response.setContentType(RESPONSE_CONTENT_TYPE);
+        response.setCharacterEncoding(RESPONSE_CHARSET);
+
+        try {
+            json.write(response.getWriter());
+        } catch (JSONException e) {
+            IOException ioe = new IOException("Error creating JSON response");
+            ioe.initCause(e);
+            throw ioe;
+        }
+    }
+
+    JSONObject getJson() {
+        return json;
+    }
+
+    public class JSONResponseException extends RuntimeException {
+
+        public JSONResponseException(String message, Throwable exception) {
+            super(message, exception);
+        }
+
+        public JSONResponseException(Throwable e) {
+            super("Error building JSON response", e);
+        }
+    }
+}

Added: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/MediaRangeList.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/MediaRangeList.java?rev=921261&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/MediaRangeList.java
(added)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/MediaRangeList.java
Wed Mar 10 09:19:30 2010
@@ -0,0 +1,326 @@
+/*
+ * 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.sling.servlets.post.impl.helper;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Facilitates parsing of the Accept HTTP request header.
+ * See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">RFC
2616 section 14.1</a>
+ */
+public class MediaRangeList extends TreeSet<MediaRangeList.MediaRange> {
+    public static final String HEADER_ACCEPT = "Accept";
+    public static final String PARAM_ACCEPT = ":http-equiv-accept";
+    public static final String WILDCARD = "*";
+    boolean matchesAll = false;
+
+    private static final Logger log = LoggerFactory.getLogger(MediaRangeList.class);
+
+    /**
+     * Constructs a <code>MediaRangeList</code> using information from the supplied
<code>HttpServletRequest</code>.
+     * if the request contains a {@link #PARAM_ACCEPT} query parameter, the query parameter
value overrides any
+     * {@link #HEADER_ACCEPT} header value.
+     * If the request contains no {@link #PARAM_ACCEPT} parameter, or the parameter value
is empty, the value of the
+     * {@link #HEADER_ACCEPT} is used. If both values are missing, it is assumed that the
client accepts all media types,
+     * as per the RFC. See also {@link MediaRangeList#MediaRangeList(java.lang.String)}
+     * @param request The <code>HttpServletRequest</code> to extract a <code>MediaRangeList</code>
from
+     */
+    public MediaRangeList(HttpServletRequest request) {
+        String queryParam = request.getParameter(PARAM_ACCEPT);
+        if (queryParam != null && queryParam.trim().length() != 0) {
+            init(queryParam);
+        } else {
+           init(request.getHeader(HEADER_ACCEPT));
+        }
+    }
+
+    /**
+     * Constructs a <code>MediaRangeList</code> using a list of media ranges
specified in a <code>java.lang.String</code>.
+     * The string is a comma-separated list of media ranges, as specified by the RFC.<br
/>
+     * Examples:
+     * <ul>
+     * <li><code>text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4,
*&#47;*;q=0.5</code></li>
+     * <li><code>text/html;q=0.8, application/json</code></li>
+     * </ul>
+     *
+     * @param listStr The list of media range specifications
+     */
+    public MediaRangeList(String listStr) {
+        try {
+            init(listStr);
+        } catch (Throwable t) {
+            log.error("Error building MediaRangeList from '" + listStr + "' - will assume
client accepts all media types", t);
+            init(null);
+        }
+    }
+
+    private void init(String headerValue) {
+        if (headerValue == null || headerValue.trim().length() == 0) {
+            // RFC 2616: "If no Accept header field is present,
+            // then it is assumed that the client accepts all media types."
+            this.matchesAll = true;
+            this.add(new MediaRange(WILDCARD + "/" + WILDCARD));
+        } else {
+            String[] mediaTypes = headerValue.split(",");
+            for (String type : mediaTypes) {
+                try {
+                    MediaRange range = new MediaRange(type);
+                    this.add(range);
+                    if (range.matchesAll()) {
+                        this.matchesAll = true;
+                    }
+                } catch (Throwable throwable) {
+                    log.warn("Error registering media type " + type, throwable);
+                }
+            }
+        }
+    }
+
+    /**
+     * Determines if this MediaRangeList contains a given media type.
+     * @param mediaType A string on the form <code>type/subtype</code>. Neither
<code>type</code>
+     * or <code>subtype</code> should be wildcard (<code>*</code>).
+     * @return <code>true</code> if this <code>MediaRangeList</code>
contains a media type that matches
+     * <code>mediaType</code>, <code>false</code> otherwise
+     * @throws IllegalArgumentException if <code>mediaType</code> is not on an
accepted form
+     * @throws NullPointerException if <code>mediaType</code> is <code>null</code>
+     */
+    public boolean contains(String mediaType) {
+        //noinspection SuspiciousMethodCalls
+        MediaRange comp = new MediaRange(mediaType);
+        return this.matchesAll || this.contains(comp);
+    }
+
+    /**
+     * Given a list of media types, returns the one is preferred by this <code>MediaRangeList</code>.
+     * @param mediaRanges An array of possible {@link org.apache.sling.servlets.post.impl.helper.MediaRangeList.MediaRange}s
+     * @return One of the <code>mediaRanges</code> that this <code>MediaRangeList</code>
prefers;
+     * or <code>null</code> if this <code>MediaRangeList</code> does
not contain any of the <code>mediaRanges</code>
+     * @throws NullPointerException if <code>mediaRanges</code> is <code>null</code>
or contains a <code>null</code> value
+     */
+    public MediaRange prefer(Set<MediaRange> mediaRanges) {
+        for (MediaRange range : this) {
+            for (MediaRange mediaType : mediaRanges) {
+                if (range.equals(mediaType)) {
+                    return mediaType;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Determines which of the <code>mediaRanges</code> specifiactions is prefered
by this <code>MediaRangeList</code>.
+     * @param mediaRanges String representations of <code>MediaRange</code>s.
The strings must be
+     * on the form required by {@link MediaRange#MediaRange(String)}
+     * @see #prefer(java.util.Set)
+     * @return the <code>toString</code> representation of the prefered <code>MediaRange</code>,
or <code>null</code>
+     * if this <code>MediaRangeList</code> does not contain any of the <code>mediaRanges</code>
+     */
+    public String prefer(String... mediaRanges) {
+        Set<MediaRange> ranges = new HashSet<MediaRange>();
+        for (String mediaRange : mediaRanges) {
+            ranges.add(new MediaRange(mediaRange));
+        }
+        return prefer(ranges).toString();
+    }
+
+    /**
+     * A code <code>MediaRange</code> represents an entry in a <code>MediaRangeList</code>.
+     * The <code>MediaRange</code> consists of a <code>supertype</code>
and a <code>subtype</code>,
+     * optionally a quality factor parameter <code>q</code> and other arbitrary
parameters.
+     */
+    public class MediaRange implements Comparable<MediaRange> {
+        private String supertype;
+        private double q = 1;
+        private Map<String, String> parameters;
+        private String subtype;
+
+        /**
+         * Constructs a <code>MediaRange</code> from a <code>String</code>
expression.
+         * @param exp The <code>String</code> to constuct the <code>MediaRange</code>
from. The string is
+         * expected to be on the form ( "*&#47;*"
+         *               | ( type "/" "*" )
+         *               | ( type "/" subtype )
+         *               ) *( ";" parameter )<br/>
+         * as specified by RFC 2616, section 14.1. <br/>
+         * Examples:
+         * <ul>
+         * <li><code>text/html;q=0.8</code></li>
+         * <li><code>text/html</code></li>
+         * <li><code>text/html;level=3</code></li>
+         * <li><code>text/html;level=3;q=0.7</code></li>
+         * <li><code>text/*</code></li>
+         * <li><code>*&#47;*</code></li>
+         * </ul>
+         * Note that if the supertype component is wildcard (<code>*</code>),
then the subtype component
+         * must also be wildcard.<br />
+         * The quality factor parameter must be between <code>0</code> and <code>1</code>,
inclusive
+         * (see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.9">RFC
2616 section 3.9</a>).
+         * If the expression does not contain a <code>q</code> parameter, the
<code>MediaRange</code> is given
+         * a default quality factor of <code>1</code>.
+         * @throws IllegalArgumentException if <code>exp</code> can not be parsed
to a valid media range
+         * @throws NullPointerException if <code>exp</code> is <code>null</code>
+         */
+        public MediaRange(String exp) {
+            String[] parts = exp.split(";");
+            this.setType(parts[0].trim());
+            if (parts.length > 1) {
+                this.parameters  = new HashMap<String, String>(parts.length - 1);
+            }
+            for (int i = 1, partsLength = parts.length; i < partsLength; i++) {
+                String parameter = parts[i];
+                String[] keyValue = parameter.split("=");
+                if (keyValue[0].equals("q")) {
+                    this.q = Double.parseDouble(keyValue[1]);
+                    if (this.q < 0 || this.q > 1) {
+                        throw new IllegalArgumentException("Quality factor out of bounds:
" + exp);
+                    }
+                }
+                this.parameters.put(keyValue[0], keyValue[1]);
+            }
+        }
+
+        /**
+         * Constructs a <code>MediaRange</code> of the given <code>supertype</code>
and <code>subtype</code>.
+         * The quality factor is given the default value of <code>1</code>.
+         * @param supertype The super type of the media range
+         * @param subtype The sub type of the media range
+         */
+        MediaRange(String supertype, String subtype) {
+            this.setType(supertype, subtype);
+        }
+
+
+        /**
+         * Returns <code>true</code> if this is a catch-all media range (<code>*&#47;*</code>).
+         * @return <code>true</code> if this range is a catch-all media range,
<code>false</code> otherwise
+         */
+        public boolean matchesAll() {
+            return this.supertype.equals(WILDCARD) && this.subtype.equals(WILDCARD);
+        }
+
+        private void setType(String supertype, String subtype) {
+            this.supertype = supertype == null ? WILDCARD : supertype;
+            this.subtype = subtype == null ? WILDCARD : subtype;
+            if (this.supertype.equals(WILDCARD) && !this.subtype.equals(WILDCARD))
{
+                throw new IllegalArgumentException("Supertype cannot be wildcard if subtype
is not");
+            }
+        }
+
+        private void setType(String typeDef) {
+            String[] parts = typeDef.split("/");
+            this.setType(parts[0], parts[1]);
+        }
+
+        MediaRange(String supertype, String subtype, double q) {
+            this(supertype, subtype);
+            this.q = q;
+        }
+
+
+        public String getParameter(String key) {
+            if (parameters != null) {
+                return parameters.get(key);
+            } else {
+                return null;
+            }
+        }
+
+        public String getSupertype() {
+            return supertype;
+        }
+
+        public String getSubtype() {
+            return subtype;
+        }
+
+        /**
+         * Get the value of the quality factor parameter (<code>q</code>).
+         * @return the quality factor
+         */
+        public double getQ() {
+            return q;
+        }
+
+        public Map<String, String> getParameters() {
+            return parameters != null ? parameters : new HashMap<String, String>(0);
+        }
+
+        /* -- Comparable implementation -- */
+        public int compareTo(MediaRange o) {
+            double diff = this.q - o.getQ();
+            if (diff == 0) {
+                // Compare parameters
+                int paramDiff = o.getParameters().size() - this.getParameters().size();
+                if (paramDiff != 0) {
+                    return paramDiff;
+                }
+                // Compare wildcards
+                if (this.supertype.equals(WILDCARD) && !o.getSupertype().equals(WILDCARD))
{
+                    return 1;
+                } else if (!this.supertype.equals(WILDCARD) && o.getSupertype().equals(WILDCARD))
{
+                    return -1;
+                }
+                if (this.subtype.equals(WILDCARD) && !o.getSubtype().equals(WILDCARD))
{
+                    return 1;
+                } else if (!this.subtype.equals(WILDCARD) && o.getSubtype().equals(WILDCARD))
{
+                    return -1;
+                }
+                // Compare names
+                return this.toString().compareTo(o.toString());
+            } else {
+                return diff > 0 ? -1 : 1;
+            }
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof MediaRange) {
+                MediaRange mr = (MediaRange) obj;
+                return mr.getSupertype().equals(this.supertype) && mr.getSubtype().equals(this.subtype);
+            }
+            return super.equals(obj);
+        }
+
+        public boolean equals(String s) {
+            return (this.supertype + "/" + this.subtype).equals(s);
+        }
+
+        @Override
+        public String toString() {
+            StringBuffer buf = new StringBuffer(this.supertype + "/" + this.subtype);
+            if (parameters != null) {
+                String delimiter = ";";
+                for (String key : parameters.keySet()) {
+                    buf.append(delimiter);
+                    buf.append(key).append("=").append(parameters.get(key));
+                }
+            }
+            return buf.toString();
+        }
+    }
+}

Modified: sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java?rev=921261&r1=921260&r2=921261&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java
(original)
+++ sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java
Wed Mar 10 09:19:30 2010
@@ -20,8 +20,11 @@ package org.apache.sling.servlets.post.i
 
 import junit.framework.TestCase;
 
+import org.apache.sling.api.servlets.HtmlResponse;
 import org.apache.sling.commons.testing.sling.MockSlingHttpServletRequest;
 import org.apache.sling.servlets.post.SlingPostConstants;
+import org.apache.sling.servlets.post.impl.helper.JSONResponse;
+import org.apache.sling.servlets.post.impl.helper.MediaRangeList;
 
 public class SlingPostServletTest extends TestCase {
 
@@ -53,6 +56,22 @@ public class SlingPostServletTest extend
             servlet.isSetStatus(req));
     }
 
+    public void testGetJsonResponse() {
+        MockSlingHttpServletRequest req = new MockSlingHttpServletRequest(null, null, null,
null, null) {
+            @Override
+            public String getHeader(String name) {
+                return name.equals(MediaRangeList.HEADER_ACCEPT) ? "application/json" : super.getHeader(name);
+            }
+
+            public <AdapterType> AdapterType adaptTo(Class<AdapterType> type)
{
+                return null;
+            }
+        };
+        SlingPostServlet servlet = new SlingPostServlet();
+        HtmlResponse result = servlet.createHtmlResponse(req);
+        assertTrue(result instanceof JSONResponse);
+    }
+
     private static class StatusParamSlingHttpServletRequest extends
             MockSlingHttpServletRequest {
 
@@ -75,5 +94,9 @@ public class SlingPostServletTest extend
         void setStatusParam(String statusParam) {
             this.statusParam = statusParam;
         }
+
+        public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+            return null;
+        }
     }
 }

Added: sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/JsonResponseTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/JsonResponseTest.java?rev=921261&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/JsonResponseTest.java
(added)
+++ sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/JsonResponseTest.java
Wed Mar 10 09:19:30 2010
@@ -0,0 +1,266 @@
+/*
+ * 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.sling.servlets.post.impl.helper;
+
+import junit.framework.TestCase;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Locale;
+
+public class JsonResponseTest extends TestCase {
+    protected JSONResponse res;
+
+    public void setUp() throws Exception {
+        res = new JSONResponse();
+        super.setUp();
+    }
+
+    public void testOnChange() throws Exception {
+        res.onChange("modified", "argument1", "argument2");
+        Object prop = res.getProperty("changes");
+        JSONArray changes = assertInstanceOf(prop, JSONArray.class);
+        assertEquals(1, changes.length());
+        Object obj = changes.get(0);
+        JSONObject change = assertInstanceOf(obj, JSONObject.class);
+        assertEquals("modified", assertProperty(change, JSONResponse.PROP_TYPE, String.class));
+        JSONArray arguments = assertProperty(change, JSONResponse.PROP_ARGUMENT, JSONArray.class);
+        assertEquals(2, arguments.length());
+    }
+
+    public void testSetProperty() throws Exception {
+        res.setProperty("prop", "value");
+        assertProperty(res.getJson(), "prop", String.class);
+    }
+
+    @SuppressWarnings({"ThrowableInstanceNeverThrown"})
+    public void testSetError() throws IOException, JSONException {
+        String errMsg = "Dummy error";
+        res.setError(new Error(errMsg));
+        MockHttpServletResponse resp = new MockHttpServletResponse();
+        res.send(resp, true);
+        JSONObject json = res.getJson();
+        JSONObject error = assertProperty(json, "error", JSONObject.class);
+        assertProperty(error, "class", Error.class.getName());
+        assertProperty(error, "message", errMsg);
+    }
+
+    public void testSend() throws Exception {
+        res.onChange("modified", "argument1");
+        MockHttpServletResponse response = new MockHttpServletResponse();
+        res.send(response, true);
+        JSONObject result = new JSONObject(response.getOutput().toString());
+        assertProperty(result, HtmlResponse.PN_STATUS_CODE, HttpServletResponse.SC_OK);
+        assertEquals(JSONResponse.RESPONSE_CONTENT_TYPE, response.getContentType());
+        assertEquals(JSONResponse.RESPONSE_CHARSET, response.getCharacterEncoding());
+    }
+
+    private static <T> T assertProperty(JSONObject obj, String key, Class<T>
clazz) throws JSONException {
+        assertTrue("JSON object does not have property " + key, obj.has(key));
+        return assertInstanceOf(obj.get(key), clazz);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private static <T> T assertProperty(JSONObject obj, String key, T expected) throws
JSONException {
+        T res = (T) assertProperty(obj, key, expected.getClass());
+        assertEquals(expected, res);
+        return res;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private static <T> T assertInstanceOf(Object obj, Class<T> clazz) {
+        try {
+            return (T) obj;
+        } catch (ClassCastException e) {
+            TestCase.fail("Object is of unexpected type. Expected: " + clazz.getName() +
", actual: " + obj.getClass().getName());
+            return null;
+        }
+    }
+
+    private static class MockHttpServletResponse implements HttpServletResponse {
+
+        private StringBuffer output = new StringBuffer();
+        private String contentType;
+        private String encoding;
+
+        public StringBuffer getOutput() {
+            return output;
+        }
+
+        public void addCookie(Cookie cookie) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".addCookie");
+        }
+
+        public boolean containsHeader(String s) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".containsHeader");
+        }
+
+        public String encodeURL(String s) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".encodeURL");
+        }
+
+        public String encodeRedirectURL(String s) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".encodeRedirectURL");
+        }
+
+        public String encodeUrl(String s) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".encodeUrl");
+        }
+
+        public String encodeRedirectUrl(String s) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".encodeRedirectUrl");
+        }
+
+        public void sendError(int i, String s) throws IOException {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".sendError");
+        }
+
+        public void sendError(int i) throws IOException {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".sendError");
+        }
+
+        public void sendRedirect(String s) throws IOException {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".sendRedirect");
+        }
+
+        public void setDateHeader(String s, long l) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setDateHeader");
+        }
+
+        public void addDateHeader(String s, long l) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".addDateHeader");
+        }
+
+        public void setHeader(String s, String s1) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setHeader");
+        }
+
+        public void addHeader(String s, String s1) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".addHeader");
+        }
+
+        public void setIntHeader(String s, int i) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setIntHeader");
+        }
+
+        public void addIntHeader(String s, int i) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".addIntHeader");
+        }
+
+        public void setStatus(int i) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setStatus");
+        }
+
+        public void setStatus(int i, String s) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setStatus");
+        }
+
+        public String getCharacterEncoding() {
+            return encoding;
+        }
+
+        public String getContentType() {
+            return contentType;
+        }
+
+        public ServletOutputStream getOutputStream() throws IOException {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".getOutputStream");
+        }
+
+        public PrintWriter getWriter() throws IOException {
+            MockHttpServletResponse.MockWriter writer = new MockWriter(output);
+            return new PrintWriter(writer);
+        }
+
+        public void setCharacterEncoding(String encoding) {
+            this.encoding = encoding;
+        }
+
+        public void setContentLength(int i) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setContentLength");
+        }
+
+        public void setContentType(String contentType) {
+            this.contentType = contentType;
+        }
+
+        public void setBufferSize(int i) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setBufferSize");
+        }
+
+        public int getBufferSize() {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".getBufferSize");
+        }
+
+        public void flushBuffer() throws IOException {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".flushBuffer");
+        }
+
+        public void resetBuffer() {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".resetBuffer");
+        }
+
+        public boolean isCommitted() {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".isCommitted");
+        }
+
+        public void reset() {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".reset");
+        }
+
+        public void setLocale(Locale locale) {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".setLocale");
+        }
+
+        public Locale getLocale() {
+            throw new UnsupportedOperationException("Not implemented: " + getClass().getName()
+ ".getLocale");
+        }
+
+        private class MockWriter extends Writer {
+            private StringBuffer buf;
+
+            public MockWriter(StringBuffer output) {
+                buf = output;
+            }
+
+            @Override
+            public void write(char[] cbuf, int off, int len) throws IOException {
+                buf.append(cbuf, off, len);
+            }
+
+            @Override
+            public void flush() throws IOException {
+                buf.setLength(0);
+            }
+
+            @Override
+            public void close() throws IOException {
+                buf = null;
+            }
+        }
+    }
+
+}

Added: sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MediaRangeListTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MediaRangeListTest.java?rev=921261&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MediaRangeListTest.java
(added)
+++ sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MediaRangeListTest.java
Wed Mar 10 09:19:30 2010
@@ -0,0 +1,66 @@
+/*
+ * 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.sling.servlets.post.impl.helper;
+
+import junit.framework.TestCase;
+import org.apache.sling.commons.testing.sling.MockSlingHttpServletRequest;
+
+public class MediaRangeListTest extends TestCase {
+    protected MediaRangeList rangeList;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        rangeList = new MediaRangeList("text/*;q=0.3, text/html;q=0.7, text/html;level=1,\n"
+
+                "               text/html;level=2;q=0.4, */*;q=0.5");
+    }
+
+    public void testContains() throws Exception {
+        assertTrue(rangeList.contains("text/html"));
+        assertTrue(rangeList.contains("application/json")); // Since rangeList contains */*
+        assertTrue(rangeList.contains("text/plain"));
+    }
+
+    public void testPrefer() throws Exception {
+        assertEquals("text/html;level=1", rangeList.prefer("text/html;level=1", "*/*"));
+    }
+
+    public void testPreferJson() {
+        MediaRangeList rangeList = new MediaRangeList("text/html;q=0.8, application/json");
+        assertEquals("application/json", rangeList.prefer("text/html", "application/json"));
+    }
+
+    public void testHttpEquivParam() {
+        MockSlingHttpServletRequest req = new MockSlingHttpServletRequest(null, null, null,
null, null) {
+            @Override
+            public String getHeader(String name) {
+                return name.equals(MediaRangeList.HEADER_ACCEPT) ? "text/plain" : super.getHeader(name);
+            }
+
+            @Override
+            public String getParameter(String name) {
+                return name.equals(MediaRangeList.PARAM_ACCEPT) ? "text/html" : super.getParameter(name);
+            }
+
+            public <AdapterType> AdapterType adaptTo(Class<AdapterType> type)
{
+                return null;
+            }
+        };
+        MediaRangeList rangeList = new MediaRangeList(req);
+        assertTrue("Did not contain media type from query param", rangeList.contains("text/html"));
+        assertFalse("Contained media type from overridden Accept header", rangeList.contains("text/plain"));
+    }
+}



Mime
View raw message