Search in sources :

Example 1 with WebScriptResponse

use of org.springframework.extensions.webscripts.WebScriptResponse in project alfresco-remote-api by Alfresco.

the class HttpRangeProcessor method processSingleRange.

/**
 * Process a single range request.
 *
 * @param res        HttpServletResponse
 * @param reader     ContentReader to retrieve content
 * @param range      Range header value
 * @param mimetype   Content mimetype
 *
 * @return true if processed range, false otherwise
 */
private boolean processSingleRange(Object res, ContentReader reader, String range, String mimetype) throws IOException {
    // Handle either HttpServletResponse or WebScriptResponse
    HttpServletResponse httpServletResponse = null;
    WebScriptResponse webScriptResponse = null;
    if (res instanceof HttpServletResponse) {
        httpServletResponse = (HttpServletResponse) res;
    } else if (res instanceof WebScriptResponse) {
        webScriptResponse = (WebScriptResponse) res;
    }
    if (httpServletResponse == null && webScriptResponse == null) {
        // Unknown response object type
        return false;
    }
    // return the specific set of bytes as requested in the content-range header
    /* Examples of byte-content-range-spec values, assuming that the entity contains total of 1234 bytes:
             The first 500 bytes:
              bytes 0-499/1234
             The second 500 bytes:
              bytes 500-999/1234
             All except for the first 500 bytes:
              bytes 500-1233/1234 */
    /* 'Range' header example:
              bytes=10485760-20971519 */
    boolean processedRange = false;
    Range r = null;
    try {
        r = Range.constructRange(range, mimetype, reader.getSize());
    } catch (IllegalArgumentException err) {
        if (getLogger().isDebugEnabled())
            getLogger().debug("Failed to parse range header - returning 416 status code: " + err.getMessage());
        if (httpServletResponse != null) {
            httpServletResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            httpServletResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\"");
            httpServletResponse.getOutputStream().close();
        } else if (webScriptResponse != null) {
            webScriptResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
            webScriptResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\"");
            webScriptResponse.getOutputStream().close();
        }
        return true;
    }
    // set Partial Content status and range headers
    String contentRange = "bytes " + Long.toString(r.start) + "-" + Long.toString(r.end) + "/" + Long.toString(reader.getSize());
    if (httpServletResponse != null) {
        httpServletResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
        httpServletResponse.setContentType(mimetype);
        httpServletResponse.setHeader(HEADER_CONTENT_RANGE, contentRange);
        httpServletResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString((r.end - r.start) + 1L));
    } else if (webScriptResponse != null) {
        webScriptResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
        webScriptResponse.setContentType(mimetype);
        webScriptResponse.setHeader(HEADER_CONTENT_RANGE, contentRange);
        webScriptResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString((r.end - r.start) + 1L));
    }
    if (getLogger().isDebugEnabled())
        getLogger().debug("Processing: Content-Range: " + contentRange);
    InputStream is = null;
    try {
        // output the binary data for the range
        OutputStream os = null;
        if (httpServletResponse != null) {
            os = httpServletResponse.getOutputStream();
        } else if (webScriptResponse != null) {
            os = webScriptResponse.getOutputStream();
        }
        is = reader.getContentInputStream();
        streamRangeBytes(r, is, os, 0L);
        os.close();
        processedRange = true;
    } catch (IOException err) {
        if (getLogger().isDebugEnabled())
            getLogger().debug("Unable to process single range due to IO Exception: " + err.getMessage());
        throw err;
    } finally {
        if (is != null)
            is.close();
    }
    return processedRange;
}
Also used : InputStream(java.io.InputStream) WebScriptResponse(org.springframework.extensions.webscripts.WebScriptResponse) OutputStream(java.io.OutputStream) ServletOutputStream(javax.servlet.ServletOutputStream) HttpServletResponse(javax.servlet.http.HttpServletResponse) IOException(java.io.IOException)

Example 2 with WebScriptResponse

use of org.springframework.extensions.webscripts.WebScriptResponse in project alfresco-remote-api by Alfresco.

the class HttpRangeProcessor method processMultiRange.

/**
 * Process multiple ranges.
 *
 * @param res        HttpServletResponse
 * @param range      Range header value
 * @param ref        NodeRef to the content for streaming
 * @param property   Content Property for the content
 * @param mimetype   Mimetype of the content
 * @param userAgent  User Agent of the caller
 *
 * @return true if processed range, false otherwise
 */
private boolean processMultiRange(Object res, String range, NodeRef ref, QName property, String mimetype, String userAgent) throws IOException {
    final Log logger = getLogger();
    // Handle either HttpServletResponse or WebScriptResponse
    HttpServletResponse httpServletResponse = null;
    WebScriptResponse webScriptResponse = null;
    if (res instanceof HttpServletResponse) {
        httpServletResponse = (HttpServletResponse) res;
    } else if (res instanceof WebScriptResponse) {
        webScriptResponse = (WebScriptResponse) res;
    }
    if (httpServletResponse == null && webScriptResponse == null) {
        // Unknown response object type
        return false;
    }
    // return the sets of bytes as requested in the content-range header
    // the response will be formatted as multipart/byteranges media type message
    /* Examples of byte-ranges-specifier values (assuming an entity-body of length 10000):

       - The first 500 bytes (byte offsets 0-499, inclusive):  bytes=0-499
       - The second 500 bytes (byte offsets 500-999, inclusive):
         bytes=500-999
       - The final 500 bytes (byte offsets 9500-9999, inclusive):
         bytes=-500
       - Or bytes=9500-
       - The first and last bytes only (bytes 0 and 9999):  bytes=0-0,-1
       - Several legal but not canonical specifications of byte offsets 500-999, inclusive:
          bytes=500-600,601-999
          bytes=500-700,601-999 */
    boolean processedRange = false;
    // get the content reader
    ContentReader reader = contentService.getReader(ref, property);
    final List<Range> ranges = new ArrayList<Range>(8);
    long entityLength = reader.getSize();
    for (StringTokenizer t = new StringTokenizer(range, ", "); t.hasMoreTokens(); ) /**/
    {
        try {
            ranges.add(Range.constructRange(t.nextToken(), mimetype, entityLength));
        } catch (IllegalArgumentException err) {
            if (getLogger().isDebugEnabled())
                getLogger().debug("Failed to parse range header - returning 416 status code: " + err.getMessage());
            if (httpServletResponse != null) {
                httpServletResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                httpServletResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\"");
                httpServletResponse.getOutputStream().close();
            } else if (webScriptResponse != null) {
                webScriptResponse.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                webScriptResponse.setHeader(HEADER_CONTENT_RANGE, "\"*\"");
                webScriptResponse.getOutputStream().close();
            }
            return true;
        }
    }
    if (ranges.size() != 0) {
        // merge byte ranges if possible - IE handles this well, FireFox not so much
        if (userAgent == null || userAgent.indexOf("MSIE ") != -1) {
            Collections.sort(ranges);
            for (int i = 0; i < ranges.size() - 1; i++) {
                Range first = ranges.get(i);
                Range second = ranges.get(i + 1);
                if (first.end + 1 >= second.start) {
                    if (logger.isDebugEnabled())
                        logger.debug("Merging byte range: " + first + " with " + second);
                    if (first.end < second.end) {
                        // merge second range into first
                        first.end = second.end;
                    }
                    // else we simply discard the second range - it is contained within the first
                    // delete second range
                    ranges.remove(i + 1);
                    // reset loop index
                    i--;
                }
            }
        }
        // calculate response content length
        long length = MULTIPART_BYTERANGES_BOUNDRY_END.length() + 2;
        for (Range r : ranges) {
            length += r.getLength();
        }
        // output headers as we have at least one range to process
        OutputStream os = null;
        if (httpServletResponse != null) {
            httpServletResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            httpServletResponse.setHeader(HEADER_CONTENT_TYPE, MULTIPART_BYTERANGES_HEADER);
            httpServletResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString(length));
            os = httpServletResponse.getOutputStream();
        } else if (webScriptResponse != null) {
            webScriptResponse.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            webScriptResponse.setHeader(HEADER_CONTENT_TYPE, MULTIPART_BYTERANGES_HEADER);
            webScriptResponse.setHeader(HEADER_CONTENT_LENGTH, Long.toString(length));
            os = webScriptResponse.getOutputStream();
        }
        InputStream is = null;
        try {
            for (Range r : ranges) {
                if (logger.isDebugEnabled())
                    logger.debug("Processing: " + r.getContentRange());
                try {
                    // output the header bytes for the range
                    if (os instanceof ServletOutputStream)
                        r.outputHeader((ServletOutputStream) os);
                    // output the binary data for the range
                    // need a new reader for each new InputStream
                    is = contentService.getReader(ref, property).getContentInputStream();
                    streamRangeBytes(r, is, os, 0L);
                    is.close();
                    is = null;
                    // section marker and flush stream
                    if (os instanceof ServletOutputStream)
                        ((ServletOutputStream) os).println();
                    os.flush();
                } catch (IOException err) {
                    if (getLogger().isDebugEnabled())
                        getLogger().debug("Unable to process multiple range due to IO Exception: " + err.getMessage());
                    throw err;
                }
            }
        } finally {
            if (is != null) {
                is.close();
            }
        }
        // end marker
        if (os instanceof ServletOutputStream)
            ((ServletOutputStream) os).println(MULTIPART_BYTERANGES_BOUNDRY_END);
        os.close();
        processedRange = true;
    }
    return processedRange;
}
Also used : Log(org.apache.commons.logging.Log) ServletOutputStream(javax.servlet.ServletOutputStream) InputStream(java.io.InputStream) ContentReader(org.alfresco.service.cmr.repository.ContentReader) OutputStream(java.io.OutputStream) ServletOutputStream(javax.servlet.ServletOutputStream) ArrayList(java.util.ArrayList) HttpServletResponse(javax.servlet.http.HttpServletResponse) IOException(java.io.IOException) StringTokenizer(java.util.StringTokenizer) WebScriptResponse(org.springframework.extensions.webscripts.WebScriptResponse)

Example 3 with WebScriptResponse

use of org.springframework.extensions.webscripts.WebScriptResponse in project records-management by Alfresco.

the class BaseWebScriptUnitTest method executeWebScript.

/**
 * Execute web script and return result as a string.
 *
 * @param parameters            map of all parameter values
 * @return {@link String}       result of web script
 */
protected String executeWebScript(Map<String, String> parameters, String content) throws Exception {
    AbstractWebScript webScript = getWebScript();
    String template = getWebScriptTemplate();
    // initialise webscript
    webScript.init(getMockedContainer(template), getMockedDescription());
    // execute webscript
    WebScriptResponse mockedResponse = getMockedWebScriptResponse();
    webScript.execute(getMockedWebScriptRequest(webScript, parameters, content), mockedResponse);
    // return results
    return mockedResponse.getWriter().toString();
}
Also used : AbstractWebScript(org.springframework.extensions.webscripts.AbstractWebScript) WebScriptResponse(org.springframework.extensions.webscripts.WebScriptResponse) Matchers.anyString(org.mockito.Matchers.anyString)

Example 4 with WebScriptResponse

use of org.springframework.extensions.webscripts.WebScriptResponse in project alfresco-remote-api by Alfresco.

the class ExecutionTests method testInvalidUrls.

@Test
public void testInvalidUrls() throws IOException {
    AbstractResourceWebScript executor = getExecutor();
    Map<String, String> templateVars = new HashMap();
    templateVars.put("apiScope", "private");
    templateVars.put("apiVersion", "1");
    templateVars.put("apiName", "alfrescomock");
    WebScriptResponse response = mockResponse();
    templateVars.put(ResourceLocator.COLLECTION_RESOURCE, "blah:");
    executor.execute(api, mockRequest(templateVars, new HashMap<String, List<String>>(1)), response);
    // Can't find it so a 404
    verify(response, times(1)).setStatus(HttpServletResponse.SC_NOT_FOUND);
}
Also used : HashMap(java.util.HashMap) AbstractResourceWebScript(org.alfresco.rest.framework.webscripts.AbstractResourceWebScript) WebScriptResponse(org.springframework.extensions.webscripts.WebScriptResponse) Matchers.anyString(org.mockito.Matchers.anyString) Test(org.junit.Test)

Example 5 with WebScriptResponse

use of org.springframework.extensions.webscripts.WebScriptResponse in project alfresco-remote-api by Alfresco.

the class ExecutionTests method testInvokeAbstract.

@Test
public void testInvokeAbstract() throws IOException {
    AbstractResourceWebScript executor = getExecutor();
    Map<String, String> templateVars = new HashMap();
    templateVars.put("apiScope", "private");
    templateVars.put("apiVersion", "1");
    templateVars.put("apiName", "alfrescomock");
    templateVars.put(ResourceLocator.COLLECTION_RESOURCE, "sheep");
    executor.execute(ApiAssistant.determineApi(templateVars), mockRequest(templateVars, new HashMap<String, List<String>>(1)), mock(WebScriptResponse.class));
    WebScriptResponse response = mockResponse();
    templateVars.put(ResourceLocator.COLLECTION_RESOURCE, "bad");
    executor.execute(api, mockRequest(templateVars, new HashMap<String, List<String>>(1)), response);
    // throws a runtime exception so INTERNAL_SERVER_ERROR
    verify(response, times(1)).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    response = mockResponse();
    templateVars.put(ResourceLocator.ENTITY_ID, "badId");
    executor.execute(api, mockRequest(templateVars, new HashMap<String, List<String>>(1)), response);
    // throws a IntegrityException so 422
    verify(response, times(1)).setStatus(422);
}
Also used : HashMap(java.util.HashMap) AbstractResourceWebScript(org.alfresco.rest.framework.webscripts.AbstractResourceWebScript) WebScriptResponse(org.springframework.extensions.webscripts.WebScriptResponse) Matchers.anyString(org.mockito.Matchers.anyString) Test(org.junit.Test)

Aggregations

WebScriptResponse (org.springframework.extensions.webscripts.WebScriptResponse)10 AbstractResourceWebScript (org.alfresco.rest.framework.webscripts.AbstractResourceWebScript)5 Test (org.junit.Test)5 Matchers.anyString (org.mockito.Matchers.anyString)5 HashMap (java.util.HashMap)3 IOException (java.io.IOException)2 InputStream (java.io.InputStream)2 OutputStream (java.io.OutputStream)2 ServletOutputStream (javax.servlet.ServletOutputStream)2 HttpServletResponse (javax.servlet.http.HttpServletResponse)2 ResourceWithMetadata (org.alfresco.rest.framework.core.ResourceWithMetadata)2 WebScriptRequest (org.springframework.extensions.webscripts.WebScriptRequest)2 StringWriter (java.io.StringWriter)1 ArrayList (java.util.ArrayList)1 StringTokenizer (java.util.StringTokenizer)1 Goat (org.alfresco.rest.framework.tests.api.mocks.Goat)1 Grass (org.alfresco.rest.framework.tests.api.mocks.Grass)1 Sheep (org.alfresco.rest.framework.tests.api.mocks.Sheep)1 ApiAssistant (org.alfresco.rest.framework.tools.ApiAssistant)1 ResourceWebScriptDelete (org.alfresco.rest.framework.webscripts.ResourceWebScriptDelete)1