Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   *
   * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
   *
   * The contents of this file are subject to the terms of either the GNU
   * General Public License Version 2 only ("GPL") or the Common Development
   * and Distribution License("CDDL") (collectively, the "License").  You
   * may not use this file except in compliance with the License.  You can
  * obtain a copy of the License at
  * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
  * or packager/legal/LICENSE.txt.  See the License for the specific
  * language governing permissions and limitations under the License.
  *
  * When distributing the software, include this License Header Notice in each
  * file and include the License file at packager/legal/LICENSE.txt.
  *
  * GPL Classpath Exception:
  * Oracle designates this particular file as subject to the "Classpath"
  * exception as provided by Oracle in the GPL Version 2 section of the License
  * file that accompanied this code.
  *
  * Modifications:
  * If applicable, add the following below the License Header, with the fields
  * enclosed by brackets [] replaced by your own identifying information:
  * "Portions Copyright [year] [name of copyright owner]"
  *
  * Contributor(s):
  * If you wish your version of this file to be governed by only the CDDL or
  * only the GPL Version 2, indicate your decision by adding "[Contributor]
  * elects to include this software in this distribution under the [CDDL or GPL
  * Version 2] license."  If you don't indicate a single choice of license, a
  * recipient has the option to distribute your version of this file under
  * either the CDDL, the GPL Version 2 or to extend the choice of license to
  * its licensees as provided above.  However, if you add GPL Version 2 code
  * and therefore, elected the GPL Version 2 license, then the option applies
  * only if the new code is made subject to such option by the copyright
  * holder.
  */
 
 package com.sun.appserv.web.cache.filter;
 
 
 
 public class CachingFilter implements FilterCacheManagerListener {
 
     private static final String PROCESSING_SET =
         "com.sun.appserv.web.cache.filter.CachingFilter.PROCESSING_SET";
 
     // this servlet filter name
     String filterName;
     String servletName;
     String urlPattern;
     
     // associated cache and the helper
     CacheHelper helper;
     Cache cache;
 
     boolean isEnabled = false;
 
     private static final Logger _logger = .....;
 
     @LogMessageInfo(
             message = "CachingFilter {0} ready; isEnabled = {1} manager = {2}",
             level = "FINE")
     private static final String CACHING_FILTER_READY = "AS-WEB-00204";
 
     @LogMessageInfo(
             message = "CachingFilter {0} request is cacheable; key {1} index = {2}",
             level = "FINE")
     private static final String CACHING_FILTER_CACHEABLE = "AS-WEB-00205";
 
     @LogMessageInfo(
             message = "CachingFilter {0} request needs a refresh; key {1}",
             level = "FINE")
     private static final String CACHING_FILTER_NEEDS_REFRESH = "AS-WEB-00206";
 
     @LogMessageInfo(
             message = "CachingFilter {0} serving response from the cache  {1}",
             level = "FINE")
     private static final String CACHING_FILTER_SERVING_RESPONSE = "AS-WEB-00207";
 
     @LogMessageInfo(
            message = "CachingFilter {0} pass thru; isEnabled = {1}",
            level = "FINE")
    private static final String CACHING_FILTER_PASS_THRU = "AS-WEB-00208";
            message = "CachingFilter {0} received cacheManager enabled event",
            level = "FINE")
    private static final String CACHING_FILTER_ENABLED_EVENT = "AS-WEB-00209";
            message = "CachingFilter {0} received cacheManager disabled event",
            level = "FINE")
    private static final String CACHING_FILTER_DISABLED_EVENT = "AS-WEB-00210";

    
Called by the web container to indicate to a filter that it is being placed into service. The servlet container calls the init method exactly once after instantiating the filter. The init method must complete successfully before the filter is asked to do any filtering work.

Parameters:
filterConfig filter config
Throws:
javax.servlet.ServletException
    public void init(FilterConfig filterConfigthrows ServletException {
         = filterConfig.getFilterName();
         = filterConfig.getInitParameter("servletName");
         = filterConfig.getInitParameter("URLPattern");
        ServletContext context = filterConfig.getServletContext();
         = (CacheManagercontext.getAttribute(
            .);
        if ( != null && .isEnabled()) {
            this. = .getDefaultCache();
            this. = .getCacheHelperByFilterName();
            // add filter as a listener so caching can be disabled at runtime.
            .addCacheManagerListener(this);
             = true;
        }
        if (.isLoggable(.)) {
            .log(.new Object[]{});
        }
    }
    
    
The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed in to this method allows the Filter to pass on the request and response to the next entity in the chain.

Parameters:
srequest the runtime request
sresponse the runtime response
chain the filter chain to in the request processing
Throws:
java.io.IOException, ServletException - First check if this HTTP method permits caching (using helper) if not, call the downstream filter and return. - Otherwise, get the key based on the request (using helper). - Check if we have a response entry in the cache already. - If there is entry and is valid, write out the response from that entry. - create a CachingResponse and CachingOutputStream wrappers and call the downstream filter
    public void doFilter (ServletRequest srequestServletResponse sresponse,
                          FilterChain chain ) 
            throws IOExceptionServletException {
        if (!(srequest instanceof HttpServletRequest) ||
                !(sresponse instanceof HttpServletResponse)) {
            throw new ServletException();
        }
        String key;
        HttpServletRequest request = (HttpServletRequest)srequest;
        HttpServletResponse response = (HttpServletResponse)sresponse;
                                                            );
                                        );
                                        );
        boolean isFine = .isLoggable(.);
        if ( && .isCacheable((HttpServletRequest)request) &&
                (key = .getCacheKey(request)) != null) {
            // have the key index for reuse
            int index = .getIndex(key);
            if (isFine) {
                .log(.new Object[]{request.getServletPath(), keyindex});
            }
            HttpCacheEntry entry = null;
            boolean entryReady = falsewaitForRefresh = true;
            
            // if refresh is not needed then check the cache first
            if (!.isRefreshNeeded(request)) {
                do {
                    // lookup cache
                    entry = (HttpCacheEntry.get(key);
                    if (entry != null && entry.isValid()) {
                        // see if there is cached entry and is valid
                        entryReady = true;
                        break;
                    }
                    else {
                        
a cache entry needs to be generated or refreshed. if there are more than one thread tries to fill/refresh same cache entry, then all but the first thread will block.
                        waitForRefresh = waitForRefresh(requestkeyindex);
                    }
                } while (waitForRefresh);
            } else {
                if (isFine) {
                    .log(.new Object[]{request.getServletPath(), key});
                }
            }
            // do we have a valid response?
            if (entryReady) {
                if (isFine) {
                    .log(.new Object[]{request.getServletPath(), key});
                }
                sendCachedResponse(entryresponse);
            } else {
                // call the target servlet
                CachingResponseWrapper wrapper = null;
                boolean needNotify = true;
                try {
                    // setup the response wrapper (and the output stream)
                    wrapper = new CachingResponseWrapper(response);
                    // call the target resource
                    chain.doFilter(srequest, (ServletResponse)wrapper);
                    // see if the there weren't any errors
                    if (!wrapper.isError()) {
                        // create/refresh the cached response entry
                        // compute the timeout
                        int timeout = .getTimeout(request);
                        // previous entry gets replaced
                        entry = wrapper.cacheResponse();
                        if (timeout == .) {
                            // extracts this from the Expires: date header
                            Long lval = wrapper.getExpiresDateHeader();
                            if (lval == null) {
                                timeout = .getDefaultTimeout();
                                entry.computeExpireTime(timeout);
                            } else {
                                long expireTime = lval.longValue();
                                // set the time this entry would expires
                                entry.setExpireTime(expireTime);
                            }
                        } else {
                            entry.computeExpireTime(timeout);
                        }
                        .put(keyentryentry.getSize());
                        .notifyRefresh(index);
                        needNotify = false;
                        // transmit the response body content
                        writeBody(entryresponse);
                    } else {
                        
either there was an error or response from this resource is not cacheable anymore; so, remove the old entry from the cache.
                        .remove(key);
                    }
                } finally {
                    // IT 12891
                    if (needNotify) {
                        .notifyRefresh(index);
                    }
                    // clear the wrapper (XXX: cache these??)
                    if (wrapper != null) {
                        wrapper.clear();
                    }
                }
            }

            
clear the old entry? may lead to NPEs with one thread that just replaced an entry which might have just obtained before the new entry is put in cache. Must implement some sort of ref count or leave it to garbage collector if (oldEntry != null) oldEntry.clear();
        } else {
            if (isFine) {
                .log(.new Object[]{request.getServletPath(), });
            }
            // pass thru
            chain.doFilter(srequestsresponse);
        }
    }

    
called by doFilter to send out the cached response

Parameters:
entry cached response entry
response response object to write out the response
Throws:
java.io.IOException and ServletException.
    private void sendCachedResponse(HttpCacheEntry entry
                                    HttpServletResponse response)
            throws IOException {
        // status code/message
        if (entry.statusCode != .) {
            response.setStatus(entry.statusCode);
        }
        // set the outbound response headers
        for (Iterator iter = entry.responseHeaders.keySet().iterator(); 
                                                         iter.hasNext(); ) {
            String name = (String)iter.next();
            ArrayList values = (ArrayList)entry.responseHeaders.get(name);
            for (int i = 0; i < values.size(); i++) {
                response.addHeader(name, (String)values.get(i));
            }
        }
        // date headers
        for (Iterator<Stringiter = entry.dateHeaders.keySet().iterator(); 
                                                    iter.hasNext(); ) {
            String name = iter.next();
            ArrayList<Longvalues = entry.dateHeaders.get(name);
            for (int i = 0; i < values.size(); i++) {
                response.addDateHeader(name, (values.get(i)).longValue());
            }
        }
        // cookies
        for (int i = 0; i < entry.cookies.size(); i++) {
            response.addCookie(entry.cookies.get(i));
        }
        // content type, length and locale
        if (entry.contentLength != .) {
            response.setContentLength(entry.contentLength);
        }
        if (entry.contentType != null) {
            response.setContentType(entry.contentType);
        }
        if (entry.locale != null) {
            response.setLocale(entry.locale);
        }
        // the response body
        writeBody(entryresponse);
    }

    
called by doFilter/sendCachedResponse to write the body content

Parameters:
entry cached response entry
response response object to write out the response
Throws:
java.io.IOException and ServletException.
    private void writeBody(HttpCacheEntry entry
                           HttpServletResponse response)
                           throws IOException {
        ServletOutputStream out = response.getOutputStream();
        out.write(entry.bytes);
    }

    
Call cache.waitRefresh only when the cache processing is not started. See IT 17377.
    private boolean waitForRefresh(HttpServletRequest reqString keyint index) {
        Object obj = req.getAttribute();
        HashSet<StringprocessingSet = null;
        if (obj == null) {
            processingSet = new HashSet<String>();
            req.setAttribute(processingSet);
        } else if (obj instanceof HashSet) {
            @SuppressWarnings("unchecked")
            final HashSet<Stringset = (HashSet<String>)obj;
            processingSet = set;
        } else {
            throw new IllegalStateException();
        }
        if (processingSet.add(key)) {
            return .waitRefresh(index);
        } else {
            return false;
        }
    }

    
cache manager listener method
    public void cacheManagerEnabled() {
        if (.isLoggable(.))
        this. = true;
    }

    
cache manager listener method
    public void cacheManagerDisabled() {
        if (.isLoggable(.))
        this. = false;
    }

    
Called by the web container to indicate to a filter that it is being taken out of service. This method is only called once all threads within the filter's doFilter method have exited or after a timeout period has passed. After the web container calls this method, it will not call the doFilter method again on this instance of the filter.
    public void destroy() {
    }
New to GrepCode? Check out our FAQ X