Example usage for javax.servlet.http HttpServletResponse SC_NOT_MODIFIED

List of usage examples for javax.servlet.http HttpServletResponse SC_NOT_MODIFIED

Introduction

In this page you can find the example usage for javax.servlet.http HttpServletResponse SC_NOT_MODIFIED.

Prototype

int SC_NOT_MODIFIED

To view the source code for javax.servlet.http HttpServletResponse SC_NOT_MODIFIED.

Click Source Link

Document

Status code (304) indicating that a conditional GET operation found that the resource was available and not modified.

Usage

From source file:de.derschimi.proxyservlet.TestServlet.java

protected boolean doResponseRedirectOrNotModifiedLogic(HttpServletRequest servletRequest,
        HttpServletResponse servletResponse, HttpResponse proxyResponse, int statusCode)
        throws ServletException, IOException {
    // Check if the proxy response is a redirect
    // The following code is adapted from org.tigris.noodle.filters.CheckForRedirect
    if (statusCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /* 300 */
            && statusCode < HttpServletResponse.SC_NOT_MODIFIED /* 304 */) {
        Header locationHeader = proxyResponse.getLastHeader(HttpHeaders.LOCATION);
        if (locationHeader == null) {
            throw new ServletException("Received status code: " + statusCode + " but no " + HttpHeaders.LOCATION
                    + " header was found in the response");
        }/*  w  w w. j  a  v  a 2 s .  co  m*/
        // Modify the redirect to go to this proxy servlet rather that the proxied host
        String locStr = rewriteUrlFromResponse(servletRequest, locationHeader.getValue());

        servletResponse.sendRedirect(locStr);
        return true;
    }
    // 304 needs special handling.  See:
    // http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304
    // We get a 304 whenever passed an 'If-Modified-Since'
    // header and the data on disk has not changed; server
    // responds w/ a 304 saying I'm not going to send the
    // body because the file has not changed.
    if (statusCode == HttpServletResponse.SC_NOT_MODIFIED) {
        servletResponse.setIntHeader(HttpHeaders.CONTENT_LENGTH, 0);
        servletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return true;
    }
    return false;
}

From source file:ch.entwine.weblounge.test.harness.content.CacheTest.java

/**
 * Tests if the modification date of a page can properly be adjusted by a
 * pagelet that is using the <code>&lt;modified&gt;</code> tag.
 * //from  w  ww .  j  a va2s.  c o m
 * @param serverUrl
 *          the server url
 * @throws Exception
 *           if the test fails
 */
private void testPageletModifcationDate(String serverUrl) throws Exception {
    logger.info("Preparing test of cache headers influenced by the 'modified' tag");

    // Load the page's modification date

    String requestUrl = UrlUtils.concat(serverUrl, "system/weblounge/pages", modificationTestPageId);
    HttpGet getPageRequest = new HttpGet(requestUrl);
    HttpClient httpClient = new DefaultHttpClient();
    Page page = null;
    logger.info("Requesting the page's modification date at {}", requestUrl);
    try {
        HttpResponse response = TestUtils.request(httpClient, getPageRequest, null);
        assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
        PageReader reader = new PageReader();
        page = reader.read(response.getEntity().getContent(), site);
    } finally {
        httpClient.getConnectionManager().shutdown();
    }

    DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
    df.setTimeZone(TimeZone.getTimeZone("GMT"));

    // Regularly load the page

    requestUrl = UrlUtils.concat(serverUrl, modificationTestPage);

    logger.info("Sending request to {}", requestUrl);
    HttpGet request = new HttpGet(requestUrl);
    request.addHeader("X-Cache-Debug", "yes");
    String[][] params = new String[][] { {} };

    // Send and the request and examine the response. Keep the modification
    // date.
    httpClient = new DefaultHttpClient();
    try {
        HttpResponse response = TestUtils.request(httpClient, request, params);

        int statusCode = response.getStatusLine().getStatusCode();
        boolean okOrNotModified = statusCode == HttpServletResponse.SC_OK
                || statusCode == HttpServletResponse.SC_NOT_MODIFIED;
        assertTrue(okOrNotModified);

        // Get the Modified header
        assertNotNull(response.getHeaders("Last-Modified"));
        assertEquals(1, response.getHeaders("Last-Modified").length);
        Date hostModified = df.parse(response.getHeaders("Last-Modified")[0].getValue());
        response.getEntity().consumeContent();

        // Make sure the page is advertised as being more recent than the page's
        // modification date
        assertTrue(hostModified.after(page.getModificationDate()));

    } finally {
        httpClient.getConnectionManager().shutdown();
    }
}

From source file:fr.aliasource.webmail.proxy.impl.ResponderImpl.java

@Override
public void sendNothingChanged() {
    resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}

From source file:com.adobe.cq.wcm.core.components.internal.servlets.AdaptiveImageServletTest.java

@Test
public void testGIFFileBrowserCached() throws Exception {
    MockSlingHttpServletResponse response = spy(aemContext.response());
    MockSlingHttpServletRequest request = prepareRequest(IMAGE5_PATH, "img", "gif");
    // 1 millisecond less than the jcr:lastModified value from test-conf.json
    request.addDateHeader("If-Modified-Since", 1489998822137L);
    servlet.doGet(request, response);//from w  w w  .  ja  v a2 s .c  o  m
    assertEquals(HttpServletResponse.SC_NOT_MODIFIED, response.getStatus());
}

From source file:org.openlaszlo.servlets.responders.ResponderCompile.java

/**
 * Process if-modified-since req header and stick last-modified
 * response header there.//from  www .  j  a va  2 s .c o m
 */
private boolean notModified(long lastModified, HttpServletRequest req, HttpServletResponse res)
        throws IOException {
    if (lastModified != 0) {

        String lms = LZHttpUtils.getDateString(lastModified);

        mLogger.debug("Last-Modified: " + lms);

        // Check last-modified and if-modified-since dates
        String ims = req.getHeader(LZHttpUtils.IF_MODIFIED_SINCE);
        long ifModifiedSince = LZHttpUtils.getDate(ims);

        if (ifModifiedSince != -1) {

            mLogger.debug("If-Modified-Since: " + ims);

            mLogger.debug(
                    /* (non-Javadoc)
                     * @i18n.test
                     * @org-mes="modsince " + p[0] + " lastmod " + p[1]
                     */
                    org.openlaszlo.i18n.LaszloMessages.getMessage(ResponderCompile.class.getName(),
                            "051018-370", new Object[] { ifModifiedSince, lastModified }));
            if (lastModified <= ifModifiedSince) {
                res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                mLogger.info(
                        /* (non-Javadoc)
                         * @i18n.test
                         * @org-mes="Responding with NOT_MODIFIED"
                         */
                        org.openlaszlo.i18n.LaszloMessages.getMessage(ResponderCompile.class.getName(),
                                "051018-379"));
                return true;
            }
        }

        res.setHeader(LZHttpUtils.LAST_MODIFIED, lms);
    }

    return false;
}

From source file:com.zimbra.cs.service.FeedManager.java

public static SubscriptionData<?> retrieveRemoteDatasource(Account acct, String url, Folder.SyncData fsd)
        throws ServiceException {
    assert !Strings.isNullOrEmpty(url);
    RemoteDataInfo rdi = null;//from   w w w. j av  a  2s. c  o m
    try {
        rdi = retrieveRemoteData(url, fsd);

        if (rdi.statusCode == HttpServletResponse.SC_NOT_MODIFIED) {
            return SubscriptionData.NOT_MODIFIED();
        }
        if (rdi.redirects > MAX_REDIRECTS) {
            throw ServiceException.TOO_MANY_PROXIES(url);
        }
        return retrieveRemoteDatasource(acct, rdi, fsd);
    } catch (HttpException e) {
        throw ServiceException.RESOURCE_UNREACHABLE("HttpException: " + e, e);
    } catch (IOException e) {
        throw ServiceException.RESOURCE_UNREACHABLE("IOException: " + e, e);
    } finally {
        if (rdi != null) {
            rdi.cleanup();
        }
    }
}

From source file:io.hops.hopsworks.api.kibana.ProxyServlet.java

protected boolean doResponseRedirectOrNotModifiedLogic(HttpServletRequest servletRequest,
        HttpServletResponse servletResponse, HttpResponse proxyResponse, int statusCode)
        throws ServletException, IOException {
    // Check if the proxy response is a redirect
    // The following code is adapted from org.tigris.noodle.filters.CheckForRedirect
    if (statusCode >= HttpServletResponse.SC_MULTIPLE_CHOICES /*
                                                              * 300
                                                              */
            && statusCode < HttpServletResponse.SC_NOT_MODIFIED /*
                                                                * 304
                                                                */) {
        Header locationHeader = proxyResponse.getLastHeader(HttpHeaders.LOCATION);
        if (locationHeader == null) {
            throw new ServletException("Received status code: " + statusCode + " but no " + HttpHeaders.LOCATION
                    + " header was found in the response");
        }//from ww  w .j  a  v  a 2  s.c  o m
        // Modify the redirect to go to this proxy servlet rather that the proxied host
        String locStr = rewriteUrlFromResponse(servletRequest, locationHeader.getValue());

        servletResponse.sendRedirect(locStr);
        return true;
    }
    // 304 needs special handling.  See:
    // http://www.ics.uci.edu/pub/ietf/http/rfc1945.html#Code304
    // We get a 304 whenever passed an 'If-Modified-Since'
    // header and the data on disk has not changed; server
    // responds w/ a 304 saying I'm not going to send the
    // body because the file has not changed.
    if (statusCode == HttpServletResponse.SC_NOT_MODIFIED) {
        servletResponse.setIntHeader(HttpHeaders.CONTENT_LENGTH, 0);
        servletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return true;
    }
    return false;
}

From source file:org.jpublish.servlet.JPublishServlet.java

/**
 * Called when the HTTP request method is POST.  This method provides the
 * main control logic./*  w w  w. j a  v  a  2 s .  co m*/
 *
 * @param request  The HTTP request
 * @param response The HTTP response
 * @throws ServletException
 * @throws IOException
 */

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    ServletContext servletContext = getServletContext();

    String pathInfo = request.getPathInfo();
    if (log.isDebugEnabled())
        log.debug("Path info: " + pathInfo);

    //OLAT: PATCH BEGIN
    if (pathInfo == null) {
        // we have a direct mapping rule in web.xml like /kurs/bridge.html -> jpublish servlet
        // so we use servletPath
        //String servletPath = request.getServletPath();
        pathInfo = request.getServletPath();
    } //TODO: make more generic (use JPublish with other servlets..) and post it.

    if (log.isDebugEnabled())
        log.debug("calculated Path info: " + pathInfo);
    //OLAT: PATCH END

    String contextPath = request.getContextPath();

    if (log.isDebugEnabled())
        log.debug("Context path: " + contextPath);

    // get the real path
    String path = getRealPath(pathInfo);

    if (siteContext.getPathDispatcherManager().canDispatch(path)) {

        //only one from below ones should react
        String dispatcherName = siteContext.getPathDispatcherManager().canForwardDispatch(path);

        if (dispatcherName != null) {
            siteContext.getPathDispatcherManager().forward(request, response, dispatcherName);
        }

        dispatcherName = siteContext.getPathDispatcherManager().canIncludeDispatch(path);
        if (dispatcherName != null) {
            siteContext.getPathDispatcherManager().include(request, response, dispatcherName);
        }

        return;
    }

    if (log.isDebugEnabled())
        log.debug("Real path: " + path);

    // create the session if enabled
    HttpSession session = null;

    if (isSessionEnabled(path)) {
        session = request.getSession(true);
    }

    // get the character encoding map
    CharacterEncodingMap characterEncodingMap = siteContext.getCharacterEncodingManager().getMap(path);

    // set the request character encoding for parameter data
    if (requireVersion(2, 3)) {
        request.setCharacterEncoding(characterEncodingMap.getRequestEncoding());
    }

    // put standard servlet stuff into the context
    JPublishContext context = new JPublishContext(this);
    context.put("request", request);
    context.put("response", response);
    context.put("session", session);
    context.put("application", servletContext);

    // add the character encoding map to the context
    context.put("characterEncodingMap", characterEncodingMap);

    // add the URLUtilities to the context
    URLUtilities urlUtilities = new URLUtilities(request, response);
    context.put("urlUtilities", urlUtilities);
    // deprecated
    context.put("url_util", urlUtilities);
    context.put("url_utils", urlUtilities);

    // add the DateUtilities to the context
    context.put("dateUtilities", DateUtilities.getInstance());

    // add the NumberUtilities to the context
    context.put("numberUtilities", NumberUtilities.getInstance());

    // add the messages log to the context
    context.put("syslog", SiteContext.syslog);

    // expose the SiteContext
    context.put("site", siteContext);

    // expose the context itself for debugging purposes
    if (siteContext.isDebug()) {
        context.put("context", context);
    }

    // switch from merge to eval, while rendering Velocity templates [hack for utf8]
    if (siteContext.isEval()) {
        context.put("evaluateVelocityTemplates", "true");
    }

    if (siteContext.isProtectReservedNames()) {
        context.enableCheckReservedNames(this);
    }

    // add the repositories to the context
    Iterator repositories = siteContext.getRepositories().iterator();
    while (repositories.hasNext()) {
        Repository repository = (Repository) repositories.next();
        if (log.isDebugEnabled())
            log.debug("Adding " + repository.getClass().getName() + " as " + repository.getName());

        context.put(repository.getName(), new RepositoryWrapper(repository, context));
    }

    Writer out = null;
    try {

        if (executePreEvaluationActions(request, response, context, path))
            return;

        if (context.getStopProcessing() != null) {
            return;
        }

        // if the page is static
        StaticResourceManager staticResourceManager = siteContext.getStaticResourceManager();

        if (staticResourceManager.resourceExists(path)) {

            long ifModifiedSince = request.getDateHeader(HEADER_IF_MODIFIED);
            // will round the file's lastModified down to the nearest second by dividing by 1000 and then
            // multiplying it by 1000; florin
            long lastUpdatedTime = -1;
            try {
                lastUpdatedTime = (staticResourceManager.getLastModified(path) / 1000) * 1000;
            } catch (Exception e) {
                log.warn("Cannot read the LastModified for: " + path);
            }
            //log.info(String.format("%s: if modified since: %d, file time:%d, modified? %s", path, ifModifiedSince, lastUpdatedTime, (ifModifiedSince < lastUpdatedTime)));

            if (ifModifiedSince < lastUpdatedTime) {
                // execute the global actions
                if (executeGlobalActions(request, response, context, path))
                    return;

                if (context.getStopProcessing() != null)
                    return;

                // execute path actions
                if (executePathActions(request, response, context, path))
                    return;
                if (context.getStopProcessing() != null)
                    return;

                // execute parameter actions
                if (executeParameterActions(request, response, context, path))
                    return;
                if (context.getStopProcessing() != null)
                    return;

                // load and return the static resource
                setResponseContentType(request, response, path, characterEncodingMap);
                response.setDateHeader(HEADER_LAST_MODIFIED, lastUpdatedTime);
                response.setContentLength((int) staticResourceManager.getContentLength(path));
                try {
                    staticResourceManager.load(path, response.getOutputStream());
                } catch (SocketException e) {
                    log.warn("Error writing to output stream: " + e.getMessage());
                }
                // OLAT: PATCH: Ignore org.apache.catalina.connector.ClientAbortException
                // that is produced by InternetExplorer (6.0) browser caching.
                catch (IOException e) {
                    if (e instanceof FileNotFoundException) {
                        throw e;
                    }
                }
            } else {
                //If the browser has current version of the file, don't send it. Just say it has not changed
                response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            }
            return;
        } else {
            if (log.isDebugEnabled())
                log.debug("Static resource '" + path + "' not found");
        }

        // load the page
        if (log.isDebugEnabled())
            log.debug("Loading the page.");

        PageInstance pageInstance = siteContext.getPageManager().getPage(path);
        Page page = new Page(pageInstance);

        context.disableCheckReservedNames(this);

        // expose the page in the context
        context.put("page", page);

        // expose components in the context
        context.put("components", new ComponentMap(context));

        if (siteContext.isProtectReservedNames()) {
            context.enableCheckReservedNames(this);
        }

        request.setAttribute(JPUBLISH_CONTEXT, context);

        // execute the global actions
        if (executeGlobalActions(request, response, context, path))
            return;
        if (context.getStopProcessing() != null)
            return;

        // execute path actions
        if (executePathActions(request, response, context, path))
            return;
        if (context.getStopProcessing() != null)
            return;

        // execute parameter actions
        if (executeParameterActions(request, response, context, path))
            return;
        if (context.getStopProcessing() != null)
            return;

        // execute the page actions
        if (log.isDebugEnabled())
            log.debug("Executing page actions.");

        if (optionalRedirect(page.executeActions(context), path, response))
            return;
        if (context.getStopProcessing() != null) {
            return;
        }
        setResponseContentType(request, response, path, characterEncodingMap);

        // get the template
        // OLAT: PATCH using context.getPage() instead of page object
        // since page can be changed in internal forward and page points
        // still to the original page
        Template template = siteContext.getTemplateManager()
                .getTemplate(context.getPage().getFullTemplateName());

        // get the Servlet writer
        out = response.getWriter();

        // merge the template
        if (log.isDebugEnabled())
            log.debug("Merging with template " + template.getPath());
        // OLAT: PATCH using context.getPage() instead of page object
        // since page can be changed in internal forward and page points
        // still to the original page
        template.merge(context, context.getPage(), out);

    } catch (FileNotFoundException e) {
        log.error("[404] " + path);
        if (!response.isCommitted()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, path);
        }
    } catch (Exception e) {
        // Allow Jetty RequestRetry exception to propogate to container!
        if ("org.mortbay.jetty.RetryRequest".equals(e.getClass().getName())) {
            throw (RuntimeException) e;
        }

        JPublishError error = new JPublishError(e, context);
        Iterator errorHandlers = siteContext.getErrorHandlers(path).iterator();
        while (errorHandlers.hasNext()) {
            ((ErrorHandler) errorHandlers.next()).handleError(error);
        }

        if (!error.isConsumed()) {
            log.error("Execution error: " + MessageUtilities.format(e.getMessage()));
            if (!response.isCommitted()) {
                throw new ServletException(e);
            }
        }
    } finally {
        try {
            executePostEvaluationActions(request, response, context, path);
        } catch (Exception e) {
            log.error("Error executing post evaluation actions: " + MessageUtilities.format(e.getMessage()));
        }
    }
}

From source file:info.magnolia.cms.filters.RangeSupportFilter.java

private HttpServletResponse wrapResponse(final HttpServletRequest request, final HttpServletResponse response) {
    return new HttpServletResponseWrapper(response) {

        /** default length is max. We hope that the underlying code will set proper content length as a header before we proceed serving some bytes. */
        private int length = Integer.MAX_VALUE;

        private final Map<String, Object> headers = new HashMap<String, Object>();

        private String eTag;

        private List<RangeInfo> ranges;

        private RangeInfo full;

        private ServletOutputStream stream;

        private PrintWriter writer;

        @Override/*www.j av  a 2  s .  c o  m*/
        public void addDateHeader(String name, long date) {
            super.addDateHeader(name, date);
            this.headers.put(name, date);
            if ("Last-Modified".equalsIgnoreCase(name)) {
                lastModTime = date;
            }
        }

        @Override
        public void setDateHeader(String name, long date) {
            super.setDateHeader(name, date);
            this.headers.put(name, date);
            if ("Last-Modified".equalsIgnoreCase(name)) {
                lastModTime = date;
            }
        }

        @Override
        public void addHeader(String name, String value) {
            if ("Content-Disposition".equalsIgnoreCase(name) && log.isDebugEnabled()) {
                log.warn("content disposition enforced by underlying filter/servlet");
            }
            super.addHeader(name, value);
            this.headers.put(name, value);
        }

        @Override
        public void setHeader(String name, String value) {
            if ("Content-Disposition".equalsIgnoreCase(name) && log.isDebugEnabled()) {
                log.warn("content disposition enforced by underlying filter/servlet");
            }
            super.setHeader(name, value);
            this.headers.put(name, value);
        }

        @Override
        public void addIntHeader(String name, int value) {
            super.addIntHeader(name, value);
            this.headers.put(name, value);
        }

        @Override
        public void setIntHeader(String name, int value) {
            super.setIntHeader(name, value);
            this.headers.put(name, value);
        }

        @Override
        public void setContentLength(int len) {
            this.length = len;
            // do not propagate length up. We might not be able to change it once it is set. We will set it ourselves once we are ready to serve bytes.
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            // make sure we set stream only once. Multiple calls to this method are allowed.
            if (this.stream == null) {
                ServletOutputStream stream = super.getOutputStream();
                // wrap the response to filter out everything except desired range
                this.stream = addRangeSupportWrapper(request, response, stream);

                if (!isServeContent || this.stream == null) {
                    // swallow output on head requests
                    this.stream = new ServletOutputStream() {

                        @Override
                        public void write(int b) throws IOException {
                            // do nothing, we do not write any output now
                        }
                    };
                }
            }
            return stream;
        }

        private ServletOutputStream addRangeSupportWrapper(final HttpServletRequest request,
                final HttpServletResponse response, ServletOutputStream stream) throws IOException {
            if (!processContent(request, response)) {
                // we might have to return null stream instead as the previous method already called res.sendError();
                return null;
            }

            if (headers.containsKey("Content-Range")) {
                // doesn't work for tomcat as it accesses underlying stream under our hands!!!
                log.debug("Range request was handled by underlying filter/servlet.");
                return stream;
            }
            if (ranges == null || ranges.isEmpty()) {
                // no op, serve all as usual
                log.debug("Didn't find any range to speak of. Serving all content as usual.");
                if (length != Integer.MAX_VALUE) {
                    // set real length when we know it
                    response.setContentLength(length);
                }
            } else if (ranges.size() == 1) {
                RangeInfo range = ranges.get(0);
                log.debug("Serving range [{}].", range);
                // setting 206 header is essential for some clients. The would abort if response is set to 200
                response.setStatus(SC_PARTIAL_CONTENT);
                stream = new RangedOutputStream(stream, range);
            } else {
                log.error("Requested multiple ranges [{}].", ranges.size());
                // TODO: add support for multiple ranges (sent as multipart request), for now just send error back
                response.setHeader("Content-Range", "bytes */" + length);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                // again we might have to return null stream after calling sendError() as the original stream might no longer be valid
            }
            return stream;
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            if (!wrapWriter) {
                return super.getWriter();
            }
            if (this.writer == null) {
                this.writer = new PrintWriter(new OutputStreamWriter(getOutputStream()));
            }
            return writer;
        }

        private boolean processContent(HttpServletRequest request, HttpServletResponse response)
                throws IOException {
            log.debug("Serving binary on uri {} was last modified at {}",
                    new Object[] { request.getRequestURI(), lastModTime });
            if (!isRequestValid(request, response)) {
                log.debug("Skipping request {} since it doesn't require body",
                        new Object[] { request.getRequestURI() });
                return false;
            }
            if (!processRange(request)) {
                log.debug("Could not process range of request {}", new Object[] { request.getRequestURI() });
                return false;
            }
            return true;
        }

        private boolean processRange(HttpServletRequest request) throws IOException {
            full = new RangeInfo(0, length - 1, length);
            ranges = new ArrayList<RangeInfo>();

            String range = request.getHeader("Range");

            // Valid range header format is "bytes=n-n,n-n,n-n...". If not, then return 416.
            if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
                response.setHeader("Content-Range", "bytes */" + length);
                response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                return false;
            }

            // If-Range header must match ETag or be greater then LastModified. If not, then return full file.
            String ifRange = request.getHeader("If-Range");
            if (ifRange != null && !ifRange.equals(eTag)) {
                try {
                    long ifRangeTime = request.getDateHeader("If-Range");
                    if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModTime) {
                        ranges.add(full);
                    }
                } catch (IllegalArgumentException ignore) {
                    // happens when if-range contains something else then date
                    ranges.add(full);
                }
            }

            // in case there were no invalid If-Range headers, then look at requested byte ranges.
            if (ranges.isEmpty()) {
                for (String part : range.substring(6).split(",")) {
                    int start = intSubstring(StringUtils.substringBefore(part, "-"));
                    int end = intSubstring(StringUtils.substringAfter(part, "-"));

                    if (start == -1) {
                        start = length - end;
                        end = length - 1;
                    } else if (end == -1 || end > length - 1) {
                        end = length - 1;
                    }

                    // Is range valid?
                    if (start > end) {
                        response.setHeader("Content-Range", "bytes */" + length); // Required in 416.
                        response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                        return false;
                    }

                    // Add range.
                    ranges.add(new RangeInfo(start, end, length));
                }
            }

            response.setHeader("ETag", eTag);
            if (ranges.size() == 1) {
                RangeInfo r = ranges.get(0);
                response.setHeader("Accept-Ranges", "bytes");
                response.setHeader("Content-Range",
                        "bytes " + r.start + "-" + r.end + "/" + r.totalLengthOfServedBinary);
                length = r.lengthOfRange;
            }
            return true;
        }

        private int intSubstring(String value) {
            return value.length() > 0 ? Integer.parseInt(value) : -1;
        }

        @Override
        public void flushBuffer() throws IOException {
            if (writer != null) {
                writer.flush();
            }
            if (stream != null) {
                stream.flush();
            }

            super.flushBuffer();
        }

        private boolean isRequestValid(HttpServletRequest request, HttpServletResponse response)
                throws IOException {
            String fileName = StringUtils.substringAfterLast(request.getRequestURI(), "/");
            eTag = fileName + "_" + length + "_" + lastModTime;

            // If-None-Match header should contain "*" or ETag.
            String ifNoneMatch = request.getHeader("If-None-Match");
            if (ifNoneMatch != null && matches(ifNoneMatch, eTag)) {
                response.setHeader("ETag", eTag); // Required in 304.
                log.debug("Returning {} on header If-None-Match", HttpServletResponse.SC_NOT_MODIFIED);
                response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                return false;
            }

            // If-Modified-Since header must be greater than LastModified. ignore if If-None-Match header exists
            long ifModifiedSince = request.getDateHeader("If-Modified-Since");
            if (ifNoneMatch == null && ifModifiedSince != -1 && ifModifiedSince + 1000 > lastModTime) {
                response.setHeader("ETag", eTag); // Required in 304.
                // 304 response should contain Date header unless running on timeless server (see 304 response docu)
                response.addDateHeader("Date", lastModTime);
                log.debug("Returning {} on header If-Modified-Since", HttpServletResponse.SC_NOT_MODIFIED);
                response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                return false;
            }

            // If-Match header should contain "*" or ETag.
            String ifMatch = request.getHeader("If-Match");
            if (ifMatch != null && !matches(ifMatch, eTag)) {
                log.debug("Returning {} on header If-Match", HttpServletResponse.SC_PRECONDITION_FAILED);
                response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
                return false;
            }

            // If-Unmodified-Since header must be greater than LastModified.
            long ifUnmodifiedSince = request.getDateHeader("If-Unmodified-Since");
            if (ifUnmodifiedSince != -1 && ifUnmodifiedSince + 1000 <= lastModTime) {
                log.debug("Returning {} on header If-Unmodified-Since",
                        HttpServletResponse.SC_PRECONDITION_FAILED);
                response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
                return false;
            }

            log.debug("Passed all precondition checkes for request {}", request.getRequestURI());
            return true;
        }
    };
}

From source file:com.tasktop.c2c.server.internal.wiki.server.WikiServiceController.java

@Section(value = "Attachments")
@Title("Retrieve Image")
@Documentation("Retrieve an Image from a Page")
@RequestMapping(value = "{pageId}/attachment/{name:.*}", method = RequestMethod.GET)
public void getImage(@PathVariable(value = "pageId") Integer pageId,
        @PathVariable(value = "name") String imageName, HttpServletRequest request,
        HttpServletResponse response) throws IOException {
    String etag = request.getHeader("If-None-Match");
    if (etag != null && etag.length() > 1 && etag.charAt(0) == '"' && etag.charAt(etag.length() - 1) == '"') {
        etag = etag.substring(1, etag.length() - 1);
    }//from  w w w . j av a2 s.c o m
    Attachment attachment;
    try {
        attachment = service.retrieveAttachmentByNameWithETag(pageId, imageName, etag);
    } catch (EntityNotFoundException e) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
    }
    if (attachment.getContent() == null) {
        // ETag match
        response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
        return;
    }
    String modified = formatRFC2822(attachment.getModificationDate());
    if (modified.equals(request.getHeader("If-Modified-Since"))) {
        response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
        return;
    }
    response.setStatus(HttpServletResponse.SC_OK);
    response.setContentLength(attachment.getSize());
    response.setContentType(attachment.getMimeType());
    response.setHeader("ETag", "\"" + attachment.getEtag() + "\"");
    response.setHeader("Modified", modified);

    ServletOutputStream outputStream = response.getOutputStream();
    try {
        outputStream.write(attachment.getContent());
    } finally {
        outputStream.close();
    }
}