001 /*
002 Copyright (c) 1996-2012, Damon Hart-Davis
003 All rights reserved.
004
005 Redistribution and use in source and binary forms, with or without
006 modification, are permitted provided that the following conditions are
007 met:
008
009 * Redistributions of source code must retain the above copyright
010 notice, this list of conditions and the following disclaimer.
011
012 * Redistributions in binary form must reproduce the above copyright
013 notice, this list of conditions and the following disclaimer in the
014 documentation and/or other materials provided with the
015 distribution.
016
017 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
018 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
019 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
020 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028 */
029 package org.hd.d.pg2k.webSvr.util;
030
031 //import ORG.hd.d.IsDebug;
032
033 import java.io.IOException;
034
035 import javax.servlet.Filter;
036 import javax.servlet.FilterChain;
037 import javax.servlet.FilterConfig;
038 import javax.servlet.ServletException;
039 import javax.servlet.ServletRequest;
040 import javax.servlet.ServletResponse;
041 import javax.servlet.http.HttpServletResponse;
042
043 /**Compresses XML by removing redundant whitespace (etc).
044 * Should quickly reduce the size of many XML documents on the fly
045 * without changing their semantics.
046 * <p>
047 * This will allow document streaming (ie incremental processing)
048 * and will support flush() to allow the push of partial documents,
049 * although this may not be able to push partial XML atoms
050 * (eg partial elements and entities).
051 * <p>
052 * To avoid upsetting some older consumers of XML,
053 * such as old mobile phones and PDAs,
054 * this may avoid some transformations such as
055 * <code><x></x></code> to <code><x/></code>.
056 * <p>
057 * To avoid upsetting older HTML consumers of XHTML
058 * this may avoid some transformations such as
059 * <code><br /></code> to <code><br/></code>.
060 */
061 public final class XMLCompressionFilter implements Filter
062 {
063 /**Our logger which falls back to System.out if servlet log not available; never null. */
064 private final WebUtils.ServletLoggerWithFallback logger = new WebUtils.ServletLoggerWithFallback();
065
066 /**The filter configuration object we are associated with.
067 * If this value is null, this filter instance is not currently configured.
068 */
069 private FilterConfig config;
070
071 public FilterConfig getFilterConfig()
072 {
073 return (config);
074 }
075
076 public void setFilterConfig(final FilterConfig c)
077 {
078 config = c;
079 logger.setContext((c == null) ? null : c.getServletContext());
080 }
081
082 /**Place this filter into service.
083 * @param filterConfig filter configuration object; null to unset
084 */
085 public void init(final FilterConfig filterConfig)
086 {
087 config = filterConfig;
088 logger.setContext((filterConfig == null) ? null : filterConfig.getServletContext());
089 }
090
091 /**Take this filter out of service. */
092 public void destroy()
093 {
094 config = null;
095 logger.setContext(null);
096 }
097
098 /**Compacts the (XML) reponse text when possible.
099 */
100 public void doFilter(final ServletRequest request,
101 final ServletResponse response,
102 final FilterChain chain)
103 throws IOException, ServletException
104 {
105 if(response instanceof HttpServletResponse)
106 {
107 final XMLCompressionServletResponseWrapper wrappedResponse =
108 new XMLCompressionServletResponseWrapper((HttpServletResponse) response);
109 try { chain.doFilter(request, wrappedResponse); }
110 finally { wrappedResponse.finishResponse(); }
111 return;
112 }
113
114 // Pass on unchanged...
115 chain.doFilter(request, response);
116 }
117 }
118