001/* 002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Jean-Marc Orliaguet, Chalmers 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.theme.jsf.component; 023 024import java.io.IOException; 025import java.io.StringWriter; 026import java.util.List; 027import java.util.Map; 028 029import javax.faces.component.UIComponent; 030import javax.faces.component.UIOutput; 031import javax.faces.component.UIViewRoot; 032import javax.faces.context.FacesContext; 033import javax.faces.context.ResponseWriter; 034import javax.faces.view.facelets.Facelet; 035 036import com.sun.faces.application.ApplicationAssociate; 037import com.sun.faces.facelets.impl.DefaultFaceletFactory; 038 039public class UIFragment extends UIOutput { 040 041 final String templateEngine = "jsf-facelets"; 042 043 private String uid; 044 045 private String engine; 046 047 private String mode; 048 049 @Override 050 public void encodeAll(final FacesContext context) throws IOException { 051 Map<String, Object> attributes = getAttributes(); 052 uid = (String) attributes.get("uid"); 053 engine = (String) attributes.get("engine"); 054 mode = (String) attributes.get("mode"); 055 056 final ResponseWriter response = context.getResponseWriter(); 057 final UIViewRoot oldViewRoot = context.getViewRoot(); 058 059 // Create a string writer for rendering the view 060 final StringWriter stringWriter = new StringWriter(); 061 context.setResponseWriter(response.cloneWithWriter(stringWriter)); 062 063 // Set up a transient view root 064 final UIViewRoot viewRoot = new UIViewRoot(); 065 viewRoot.setRendererType(oldViewRoot.getRendererType()); 066 viewRoot.setRenderKitId(oldViewRoot.getRenderKitId()); 067 viewRoot.setViewId(oldViewRoot.getViewId()); 068 viewRoot.setLocale(oldViewRoot.getLocale()); 069 context.setViewRoot(viewRoot); 070 071 // Render the view 072 final String faceletId = String.format("nxtheme://element/%s/%s/%s/%s", engine, mode, templateEngine, uid); 073 ApplicationAssociate associate = ApplicationAssociate.getCurrentInstance(); 074 DefaultFaceletFactory faceletFactory = associate.getFaceletFactory(); 075 final Facelet facelet = faceletFactory.getFacelet(context, faceletId); 076 facelet.apply(context, viewRoot); 077 renderChildren(context, viewRoot); 078 079 // Write the rendered view into the response 080 response.write(stringWriter.getBuffer().toString()); 081 082 // Restore the response and the original view root 083 context.setResponseWriter(response); 084 context.setViewRoot(oldViewRoot); 085 } 086 087 @Override 088 public boolean isTransient() { 089 // The UIFragment component is created dynamically by the 090 // FragmentTag filter. It must be declared as transient otherwise it 091 // will not be handled correctly by Facelets. 092 return true; 093 } 094 095 private static void renderChildren(FacesContext context, UIComponent component) throws IOException { 096 List<UIComponent> children = component.getChildren(); 097 for (Object child : children) { 098 renderChild(context, (UIComponent) child); 099 } 100 } 101 102 private static void renderChild(FacesContext context, UIComponent child) throws IOException { 103 if (child.isRendered()) { 104 child.encodeBegin(context); 105 if (child.getRendersChildren()) { 106 child.encodeChildren(context); 107 } else { 108 renderChildren(context, child); 109 } 110 child.encodeEnd(context); 111 } 112 } 113 114 // Component properties 115 public String getEngine() { 116 return engine; 117 } 118 119 public void setEngine(String engine) { 120 this.engine = engine; 121 } 122 123 public String getMode() { 124 return mode; 125 } 126 127 public void setMode(String mode) { 128 this.mode = mode; 129 } 130 131 public String getUid() { 132 return uid; 133 } 134 135 public void setUid(String uid) { 136 this.uid = uid; 137 } 138}