/* * (C) Copyright 2006-2007 Nuxeo SAS <http://nuxeo.com> and others * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jean-Marc Orliaguet, Chalmers * * $Id$ */ package org.nuxeo.theme.jsf.component; import java.io.IOException; import java.io.StringWriter; import java.util.List; import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.component.UIOutput; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.view.facelets.Facelet; import com.sun.faces.application.ApplicationAssociate; import com.sun.faces.facelets.impl.DefaultFaceletFactory; public class UIFragment extends UIOutput { final String templateEngine = "jsf-facelets"; private String uid; private String engine; private String mode; @Override public void encodeAll(final FacesContext context) throws IOException { Map<String, Object> attributes = getAttributes(); uid = (String) attributes.get("uid"); engine = (String) attributes.get("engine"); mode = (String) attributes.get("mode"); final ResponseWriter response = context.getResponseWriter(); final UIViewRoot oldViewRoot = context.getViewRoot(); // Create a string writer for rendering the view final StringWriter stringWriter = new StringWriter(); context.setResponseWriter(response.cloneWithWriter(stringWriter)); // Set up a transient view root final UIViewRoot viewRoot = new UIViewRoot(); viewRoot.setRendererType(oldViewRoot.getRendererType()); viewRoot.setRenderKitId(oldViewRoot.getRenderKitId()); viewRoot.setViewId(oldViewRoot.getViewId()); viewRoot.setLocale(oldViewRoot.getLocale()); context.setViewRoot(viewRoot); // Render the view final String faceletId = String.format("nxtheme://element/%s/%s/%s/%s", engine, mode, templateEngine, uid); ApplicationAssociate associate = ApplicationAssociate.getCurrentInstance(); DefaultFaceletFactory faceletFactory = associate.getFaceletFactory(); final Facelet facelet = faceletFactory.getFacelet(context, faceletId); facelet.apply(context, viewRoot); renderChildren(context, viewRoot); // Write the rendered view into the response response.write(stringWriter.getBuffer().toString()); // Restore the response and the original view root context.setResponseWriter(response); context.setViewRoot(oldViewRoot); } @Override public boolean isTransient() { // The UIFragment component is created dynamically by the // FragmentTag filter. It must be declared as transient otherwise it // will not be handled correctly by Facelets. return true; } private static void renderChildren(FacesContext context, UIComponent component) throws IOException { List<UIComponent> children = component.getChildren(); for (Object child : children) { renderChild(context, (UIComponent) child); } } private static void renderChild(FacesContext context, UIComponent child) throws IOException { if (child.isRendered()) { child.encodeBegin(context); if (child.getRendersChildren()) { child.encodeChildren(context); } else { renderChildren(context, child); } child.encodeEnd(context); } } // Component properties public String getEngine() { return engine; } public void setEngine(String engine) { this.engine = engine; } public String getMode() { return mode; } public void setMode(String mode) { this.mode = mode; } public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } }