nonjsp.application.XulViewHandlerImpl.java Source code

Java tutorial

Introduction

Here is the source code for nonjsp.application.XulViewHandlerImpl.java

Source

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 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.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.
 */

// XulViewHandlerImpl.java 

package nonjsp.application;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.RuleSetBase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.SimpleLog;

import nonjsp.util.RIConstants;

/**
 * <B>XulViewHandlerImpl</B> is the Xul non-JSP ViewHandler implementation
 *
 * @see javax.faces.application.ViewHandler
 */
public class XulViewHandlerImpl extends ViewHandler {

    // Log instance for this class
    protected static Log log = LogFactory.getLog(XulViewHandlerImpl.class);
    protected static final String CHAR_ENCODING = "ISO-8859-1";
    protected static final String CONTENT_TYPE = "text/html";

    //PENDING(rogerk) maybe config file?
    /** Should we use a validating XML parser to read the configuration file? */
    protected boolean validate = false;

    /**
     * The set of public identifiers, and corresponding resource names, for
     * the versions of the configuration file DTDs that we know about.  There
     * <strong>MUST</strong> be an even number of Strings in this list!
     * Only used if you are validating against DTD.
     * Could be read from config file instead.
     */
    protected String registrations[] = { "-//UIT//DTD UIML 2.0 Draft//EN", "UIML2_0d.dtd" };

    // Relationship Instance Variables
    protected XmlDialectProvider dialectProvider = null;

    public XulViewHandlerImpl() {
        super();
        dialectProvider = new XulDialectProvider();
    }

    // Render the components
    public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException {

        if (context == null || viewToRender == null) {
            throw new NullPointerException("RenderView: FacesContext is null");
        }

        RequestDispatcher requestDispatcher = null;

        log.trace("Determine View Identifier And Build View...");
        String viewId = viewToRender.getViewId();

        HttpServletResponse response = (HttpServletResponse) (context.getExternalContext().getResponse());
        log.trace("Set ResponseWriter in FacesContext");

        RenderKitFactory factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
        RenderKit renderKit = factory.getRenderKit(context, RenderKitFactory.HTML_BASIC_RENDER_KIT);

        ResponseWriter writer = renderKit.createResponseWriter(response.getWriter(), CONTENT_TYPE, CHAR_ENCODING);
        context.setResponseWriter(writer);
        response.setContentType(CONTENT_TYPE);

        log.trace("Call encode methods on components");
        createHeader(context);
        renderResponse(context);
        createFooter(context);

        log.trace("Save the view and locale in the session");
        Map sessionMap = getSessionMap(context);
        sessionMap.put(RIConstants.REQUEST_LOCALE, context.getViewRoot().getLocale());
        sessionMap.put(javax.faces.render.ResponseStateManager.VIEW_STATE_PARAM, context.getViewRoot());

    }

    public UIViewRoot restoreView(FacesContext context, String viewId) {
        if (context == null) {
            throw new NullPointerException("RestoreView: FacesContext is null");
        }

        if (log.isTraceEnabled()) {
            log.trace("viewId: " + viewId);
        }
        UIViewRoot root = null;
        InputStream viewInput = null;
        RuleSetBase ruleSet = null;

        root = new UIViewRoot();
        root.setRenderKitId(RenderKitFactory.HTML_BASIC_RENDER_KIT);

        if (null == viewId) {
            // PENDING(edburns): need name for default view
            // PENDING(rogerk) : what to specify for page url
            // (last parameter)????
            root.setViewId("default");
            context.setViewRoot(root);
            Locale locale = calculateLocale(context);
            root.setLocale(locale);
            return root;
        }

        try {
            viewInput = context.getExternalContext().getResourceAsStream(viewId);
            if (null == viewInput) {
                throw new NullPointerException();
            }
        } catch (Throwable e) {
            throw new FacesException("Can't get stream for " + viewId, e);
        }

        // PENDING(edburns): can this digester instance be maintained as an
        // ivar?

        Digester digester = new Digester();

        // SimpleLog implements the Log interface (from commons.logging).
        // This replaces deprecated "Digester.setDebug" method.
        // PENDING(rogerk) Perhaps the logging level should be configurable..
        // For debugging, you can set the log level to
        // "SimpleLog.LOG_LEVEL_DEBUG".
        //
        SimpleLog sLog = new SimpleLog("digesterLog");
        sLog.setLevel(SimpleLog.LOG_LEVEL_ERROR);
        digester.setLogger(sLog);

        digester.setNamespaceAware(true);

        digester.setValidating(validate);

        ruleSet = dialectProvider.getRuleSet();

        digester.addRuleSet(ruleSet);

        if (validate) {
            for (int i = 0; i < registrations.length; i += 2) {
                URL url = this.getClass().getResource(registrations[i + 1]);
                if (url != null) {
                    digester.register(registrations[i], url.toString());
                }
            }
        }

        digester.push(root);
        try {
            root = (UIViewRoot) digester.parse(viewInput);
        } catch (Throwable e) {
            throw new FacesException("Can't parse stream for " + viewId, e);
        }

        //Print view for debugging
        if (log.isDebugEnabled()) {
            printView(root);
        }

        root.setViewId(viewId);
        context.setViewRoot(root);

        return root;
    }

    public UIViewRoot createView(FacesContext context, String viewId) {
        if (context == null) {
            throw new NullPointerException("CreateView: FacesContext is null");
        }

        return restoreView(context, viewId);
    }

    public String getActionURL(FacesContext context, String viewId) {
        if (viewId.charAt(0) != '/') {
            throw new IllegalArgumentException("Illegal view ID " + viewId + ". the ID must begin with '/'");
        }
        // PENDING(edburns): do a more complete implementation that
        // deals with the vagaries of prefix and suffix mapping.  For
        // now , just slap "/faces" onto the front.
        if (!viewId.startsWith("/faces")) {
            viewId = "/faces" + viewId;
        }
        return context.getExternalContext().getRequestContextPath() + viewId;
    }

    public String getResourceURL(FacesContext context, String path) {
        if (path.startsWith("/")) {
            return context.getExternalContext().getRequestContextPath() + path;
        } else {
            return (path);
        }
    }

    // Create the header components for this page
    private void createHeader(FacesContext context) throws IOException {

        ResponseWriter writer = context.getResponseWriter();

        writer.startElement("html", null);
        writer.writeText("\n", null);
        writer.startElement("head", null);
        writer.writeText("\n", null);
        writer.startElement("title", null);
        writer.writeText(context.getExternalContext().getRequestContextPath(), null);
        writer.endElement("title");
        writer.writeText("\n", null);
        writer.endElement("head");
        writer.writeText("\n", null);
        writer.startElement("body", null);
        writer.writeText("\n", null);
    }

    // Create the footer components for this page
    private void createFooter(FacesContext context) throws IOException {

        ResponseWriter writer = context.getResponseWriter();

        writer.endElement("body");
        writer.writeText("\n", null);
        writer.endElement("html");
        writer.writeText("\n", null);
    }

    // Render the response content for the completed page
    private void renderResponse(FacesContext context) throws IOException {

        UIComponent root = context.getViewRoot();
        if (log.isTraceEnabled()) {
            log.trace("Rendering " + root + " with " + root.getChildCount() + " children");
        }
        renderResponse(context, root);

    }

    // Render the response content for an individual component
    private void renderResponse(FacesContext context, UIComponent component) throws IOException {

        if (log.isTraceEnabled()) {
            log.trace("Render Begin: " + component.getId());
        }
        component.encodeBegin(context);
        if (component.getRendersChildren()) {
            component.encodeChildren(context);
        } else {
            Iterator kids = component.getChildren().iterator();
            while (kids.hasNext()) {
                renderResponse(context, (UIComponent) kids.next());
            }
        }
        if (log.isTraceEnabled()) {
            log.trace("Render End: " + component.getId());
        }
        component.encodeEnd(context);

    }

    private Map getSessionMap(FacesContext context) {
        if (context == null) {
            context = FacesContext.getCurrentInstance();
        }
        Map sessionMap = context.getExternalContext().getSessionMap();
        if (sessionMap == null) {
            context.getExternalContext().getSession(true);
            sessionMap = context.getExternalContext().getSessionMap();
        }
        return sessionMap;
    }

    private void printView(UIComponent uic) {
        Iterator kids = uic.getChildren().iterator();
        while (kids.hasNext()) {
            printView((UIComponent) kids.next());
        }
        log.debug("VIEW: " + uic.getId());
    }

    public void writeState(FacesContext context) throws IOException {
    }

    public Locale calculateLocale(FacesContext context) {
        Locale result = null;
        // determine the locales that are acceptable to the client based on the 
        // Accept-Language header and the find the best match among the 
        // supported locales specified by the client.
        Enumeration e = ((ServletRequest) context.getExternalContext().getRequest()).getLocales();
        while (e.hasMoreElements()) {
            Locale perf = (Locale) e.nextElement();
            result = findMatch(context, perf);
            if (result != null) {
                break;
            }
        }
        // no match is found.
        if (result == null) {
            if (context.getApplication().getDefaultLocale() == null) {
                result = Locale.getDefault();
            } else {
                result = context.getApplication().getDefaultLocale();
            }
        }
        return result;
    }

    public String calculateRenderKitId(FacesContext context) {
        return null;
    }

    /**
     * Attempts to find a matching locale based on <code>perf></code> and
     * list of supported locales, using the matching algorithm
     * as described in JSTL 8.3.2.
     */
    protected Locale findMatch(FacesContext context, Locale perf) {
        Locale result = null;
        Iterator it = context.getApplication().getSupportedLocales();
        while (it.hasNext()) {
            Locale supportedLocale = (Locale) it.next();

            if (perf.equals(supportedLocale)) {
                // exact match
                result = supportedLocale;
                break;
            } else {
                // Make sure the preferred locale doesn't have  country set, when 
                // doing a language match, For ex., if the preferred locale is
                // "en-US", if one of supported locales is "en-UK", even though 
                // its language matches that of the preferred locale, we must 
                // ignore it.
                if (perf.getLanguage().equals(supportedLocale.getLanguage())
                        && supportedLocale.getCountry().equals("")) {
                    result = supportedLocale;
                }
            }
        }
        return result;
    }
}