org.ajax4jsf.webapp.ConfigurableXMLFilter.java Source code

Java tutorial

Introduction

Here is the source code for org.ajax4jsf.webapp.ConfigurableXMLFilter.java

Source

/**
 * License Agreement.
 *
 * Rich Faces - Natural Ajax for Java Server Faces (JSF)
 *
 * Copyright (C) 2007 Exadel, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */
package org.ajax4jsf.webapp;

import java.io.IOException;
import java.io.InputStream;
import java.util.EmptyStackException;
import java.util.Properties;
import java.util.regex.PatternSyntaxException;

import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.ajax4jsf.Messages;
import org.ajax4jsf.io.parser.FastHtmlParser;
import org.ajax4jsf.resource.util.URLToStreamHelper;
import org.ajax4jsf.webapp.nekko.NekkoParser;
import org.ajax4jsf.webapp.tidy.TidyParser;
import org.apache.commons.collections.ArrayStack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author asmirnov
 * 
 */
public class ConfigurableXMLFilter extends BaseXMLFilter {

    public static final String NONE = "NONE";

    public static final String NEKO = "NEKO";

    public static final String TIDY = "TIDY";

    private static final Log log = LogFactory.getLog(ConfigurableXMLFilter.class);

    private static final String PARSERS_LIST_PARAMETER = "org.ajax4jsf.xmlparser.ORDER";

    private static final String VIEW_ID_PATTERN_PARAMETER = "org.ajax4jsf.xmlparser.";

    /**
     * map of the parsers names and viewId patterns for all parser type.
     */
    private ParserConfig parsers = new TidyParserConfig();

    // private ParserConfig passParserConfig = new PassParserConfig();

    public void init(FilterConfig config) throws ServletException {
        super.init(config);
        ServletContext servletContext = config.getServletContext();
        String parsersParameter = servletContext.getInitParameter(PARSERS_LIST_PARAMETER);
        if (null != parsersParameter) {
            configureParsers(servletContext, parsersParameter);
        }
    }

    /**
     * @param servletContext
     * @param parsersParameter
     * @throws ServletException
     */
    public void configureParsers(ServletContext servletContext, String parsersParameter) throws ServletException {
        String[] parsersNames = parsersParameter.split("\\s*,\\s*");
        for (int i = parsersNames.length - 1; i >= 0; i--) {
            String parserName = parsersNames[i];
            ParserConfig parserConfig;
            if (TIDY.equals(parserName)) {
                parserConfig = new TidyParserConfig();
            } else if (NEKO.equals(parserName)) {
                parserConfig = new NekoParserConfig();
            } else if (NONE.equals(parserName)) {
                parserConfig = new PassParserConfig();
            } else {
                throw new ServletException("Unknown XML parser type in config parameter " + parserName);
            }
            parserConfig.setNext(parsers);
            if (null != servletContext) {
                try {
                    String parserViewPattern = servletContext
                            .getInitParameter(VIEW_ID_PATTERN_PARAMETER + parserName);
                    parserConfig.setPatterns(parserViewPattern);

                } catch (PatternSyntaxException e) {
                    throw new ServletException(
                            "Invalid pattern for a parser " + parserName + " :" + e.getMessage());
                }
            }
            parsers = parserConfig;
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.ajax4jsf.webapp.BaseXMLFilter#getParser(java.lang.String,
     *      boolean, java.lang.String)
     */
    protected HtmlParser getParser(String mimetype, boolean isAjax, String viewId) {

        HtmlParser parser = null;

        if (isAjax || mimetype.startsWith(TEXT_HTML) || mimetype.startsWith(APPLICATION_XHTML_XML)) {
            if (isAjax || isForcexml()) {
                parser = parsers.getParser(viewId, mimetype);
            } else {
                parser = new FastHtmlParser();
            }
        }

        return parser;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.ajax4jsf.webapp.BaseXMLFilter#reuseParser(org.ajax4jsf.webapp.HtmlParser)
     */
    protected void reuseParser(HtmlParser parser) {
        parsers.reuseParser(parser);

    }

    private static final int STACK_SIZE = 100;

    private ArrayStack _xhtmlParsersPool = new ArrayStack(STACK_SIZE);

    private class NekoParserConfig extends ParserConfig {

        protected HtmlParser createParser(String mime) {
            NekkoParser parser;
            try {
                synchronized (_xhtmlParsersPool) {
                    parser = (NekkoParser) _xhtmlParsersPool.pop();
                }
            } catch (EmptyStackException e) {
                parser = new NekkoParser();
                parser.setPublicId(getPublicid());
                parser.setSystemid(getSystemid());
                parser.setNamespace(getNamespace());
                // If tidy not handle all requests, disable reorganising
                // of html
                // parser.setMoveElements(isForcexml());
                parser.init();
            }
            parser.setMime(mime);
            // TODO - set header scripts/styles filter.
            return parser;
        }

        boolean storeParser(HtmlParser parser) {
            if (null != parser && parser instanceof NekkoParser) {
                synchronized (_xhtmlParsersPool) {
                    if (_xhtmlParsersPool.size() < STACK_SIZE) {
                        ((NekkoParser) parser).reset();
                        _xhtmlParsersPool.push(parser);
                    }

                }
                return true;
            }
            return false;
        }
    }

    private class TidyParserConfig extends ParserConfig {

        protected HtmlParser createParser(String mime) {
            // TODO Auto-generated method stub
            TidyParser tidyParser = new TidyParser(getTidyProperties());
            tidyParser.setMoveElements(isForcexml());
            tidyParser.setMime(mime);
            return tidyParser;
        }

    }

    private class PassParserConfig extends ParserConfig {

        protected HtmlParser createParser(String mime) {
            return new FastHtmlParser();
        }

    }

    private Properties _tidyProperties;

    private Properties getTidyProperties() {
        if (null == _tidyProperties) {
            _tidyProperties = new Properties();
            InputStream defaultprops = null;
            InputStream props = null;
            try {
                defaultprops = URLToStreamHelper.urlToStreamSafe(TidyParser.class.getResource("tidy.properties"));
                if (null != defaultprops) {
                    _tidyProperties.load(defaultprops);
                    if (log.isDebugEnabled()) {
                        log.debug("default tidy parser properties loaded");
                    }
                } else if (log.isDebugEnabled()) {
                    log.debug("No default tidy parser properties found");
                }

                // Second part - user-defined properties.
                props = URLToStreamHelper.urlToStreamSafe(
                        Thread.currentThread().getContextClassLoader().getResource("tidy.properties"));
                if (null != props) {
                    _tidyProperties.load(props);
                    if (log.isDebugEnabled()) {
                        log.debug("application-specific tidy parser properties loaded");
                    }
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                log.warn(Messages.getMessage(Messages.READING_TIDY_PROPERTIES_ERROR), e);
            } finally {
                if (null != props) {
                    try {
                        props.close();
                    } catch (IOException e) {
                        // can be ignored
                    }
                }
                if (null != defaultprops) {
                    try {
                        defaultprops.close();
                    } catch (IOException e) {
                        // can be ignored
                    }
                }
            }
        }
        return _tidyProperties;
    }

    public ParserConfig getParsers() {
        return parsers;
    }

}