001/* 002 * (C) Copyright 2006-2007 Nuxeo SAS <http://nuxeo.com> and others 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Jean-Marc Orliaguet, Chalmers 011 * 012 * $Id$ 013 */ 014 015package org.nuxeo.theme.jsf.component; 016 017import java.io.IOException; 018import java.io.StringWriter; 019import java.util.List; 020import java.util.Map; 021 022import javax.faces.component.UIComponent; 023import javax.faces.component.UIOutput; 024import javax.faces.component.UIViewRoot; 025import javax.faces.context.FacesContext; 026import javax.faces.context.ResponseWriter; 027import javax.faces.view.facelets.Facelet; 028 029import com.sun.faces.application.ApplicationAssociate; 030import com.sun.faces.facelets.impl.DefaultFaceletFactory; 031 032public class UIFragment extends UIOutput { 033 034 final String templateEngine = "jsf-facelets"; 035 036 private String uid; 037 038 private String engine; 039 040 private String mode; 041 042 @Override 043 public void encodeAll(final FacesContext context) throws IOException { 044 Map<String, Object> attributes = getAttributes(); 045 uid = (String) attributes.get("uid"); 046 engine = (String) attributes.get("engine"); 047 mode = (String) attributes.get("mode"); 048 049 final ResponseWriter response = context.getResponseWriter(); 050 final UIViewRoot oldViewRoot = context.getViewRoot(); 051 052 // Create a string writer for rendering the view 053 final StringWriter stringWriter = new StringWriter(); 054 context.setResponseWriter(response.cloneWithWriter(stringWriter)); 055 056 // Set up a transient view root 057 final UIViewRoot viewRoot = new UIViewRoot(); 058 viewRoot.setRendererType(oldViewRoot.getRendererType()); 059 viewRoot.setRenderKitId(oldViewRoot.getRenderKitId()); 060 viewRoot.setViewId(oldViewRoot.getViewId()); 061 viewRoot.setLocale(oldViewRoot.getLocale()); 062 context.setViewRoot(viewRoot); 063 064 // Render the view 065 final String faceletId = String.format("nxtheme://element/%s/%s/%s/%s", engine, mode, templateEngine, uid); 066 ApplicationAssociate associate = ApplicationAssociate.getCurrentInstance(); 067 DefaultFaceletFactory faceletFactory = associate.getFaceletFactory(); 068 final Facelet facelet = faceletFactory.getFacelet(context, faceletId); 069 facelet.apply(context, viewRoot); 070 renderChildren(context, viewRoot); 071 072 // Write the rendered view into the response 073 response.write(stringWriter.getBuffer().toString()); 074 075 // Restore the response and the original view root 076 context.setResponseWriter(response); 077 context.setViewRoot(oldViewRoot); 078 } 079 080 @Override 081 public boolean isTransient() { 082 // The UIFragment component is created dynamically by the 083 // FragmentTag filter. It must be declared as transient otherwise it 084 // will not be handled correctly by Facelets. 085 return true; 086 } 087 088 private static void renderChildren(FacesContext context, UIComponent component) throws IOException { 089 List<UIComponent> children = component.getChildren(); 090 for (Object child : children) { 091 renderChild(context, (UIComponent) child); 092 } 093 } 094 095 private static void renderChild(FacesContext context, UIComponent child) throws IOException { 096 if (child.isRendered()) { 097 child.encodeBegin(context); 098 if (child.getRendersChildren()) { 099 child.encodeChildren(context); 100 } else { 101 renderChildren(context, child); 102 } 103 child.encodeEnd(context); 104 } 105 } 106 107 // Component properties 108 public String getEngine() { 109 return engine; 110 } 111 112 public void setEngine(String engine) { 113 this.engine = engine; 114 } 115 116 public String getMode() { 117 return mode; 118 } 119 120 public void setMode(String mode) { 121 this.mode = mode; 122 } 123 124 public String getUid() { 125 return uid; 126 } 127 128 public void setUid(String uid) { 129 this.uid = uid; 130 } 131}