/**
* 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.resource;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.nio.ByteBuffer;
import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import org.ajax4jsf.css.CssCompressor;
import org.ajax4jsf.renderkit.RendererBase;
import org.ajax4jsf.renderkit.compiler.HtmlCompiler;
import org.ajax4jsf.renderkit.compiler.PreparedTemplate;
import org.ajax4jsf.renderkit.compiler.TemplateContext;
import org.richfaces.skin.SkinFactory;
/**
* @author shura
*
*/
public class TemplateCSSRenderer extends StyleRenderer {
private static final String COMPILED_TEMPLATE_PROPERTY = "compiled-template";
/** Parameter allows switch on/off comressing for css */
private static final String COMPRESS_STYLE_PARAMETER = "org.ajax4jsf.COMPRESS_STYLE";
private RendererBase renderer = new RendererBase() {
protected Class getComponentClass() {
// TODO Auto-generated method stub
return UIComponent.class;
}
};
/* (non-Javadoc)
* @see org.ajax4jsf.resource.BaseResourceRenderer#send(org.ajax4jsf.resource.InternetResource, org.ajax4jsf.resource.ResourceContext)
*/
public int send(InternetResource base, ResourceContext context) throws IOException {
PreparedTemplate template = null;
CountingOutputWriter countingOutputWriter = new CountingOutputWriter();
template = getTemplate(base, context);
FacesContext facesContext = FacesContext.getCurrentInstance();
boolean _CompressStyleOn = !"false".equals(facesContext.getExternalContext()
.getInitParameter(COMPRESS_STYLE_PARAMETER));
Writer writer = context.getWriter();
int bytesLength;
if(null != facesContext) {
// Create responseWriter.
String defaultRenderKitId = facesContext.getApplication().getDefaultRenderKitId();
if (null == defaultRenderKitId) {
defaultRenderKitId = RenderKitFactory.HTML_BASIC_RENDER_KIT;
}
RenderKitFactory renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
RenderKit renderKit = renderKitFactory.getRenderKit(facesContext,defaultRenderKitId);
// TODO - handle response encoding
ResponseWriter responseWriter = renderKit.createResponseWriter(countingOutputWriter,null,"UTF-8");
facesContext.setResponseWriter(responseWriter);
responseWriter.startDocument();
// TODO - parameters and mock renderer/component ?
// for first time, this template only allow skin or faces variables interaction
template.encode(renderer,facesContext,null);
responseWriter.endDocument();
responseWriter.flush();
responseWriter.close();
if (_CompressStyleOn) {
CssCompressor compressor = new CssCompressor(countingOutputWriter.getContent()); // Compressing css document and printing result in response stream
bytesLength = compressor.compress(writer, -1);
writer.flush();
writer.close();
} else {
writer.write(countingOutputWriter.getContent().toString()); // Write not compressed style content
bytesLength = countingOutputWriter.getWritten();
writer.flush();
writer.close();
}
} else {
throw new FacesException("FacesContext for resource from template "+base.getKey()+" is null");
}
return bytesLength;
}
/**
* @param base
* @param context
* @return
* @throws IOException
*/
public synchronized PreparedTemplate getTemplate(InternetResource base, ResourceContext context) throws IOException {
PreparedTemplate template;
// if(base.isCacheable()){
template = (PreparedTemplate) base.getProperty(COMPILED_TEMPLATE_PROPERTY);
// }
if(null == template){
HtmlCompiler compiler = new HtmlCompiler();
InputStream resourceAsStream = base.getResourceAsStream(context);
template = compiler.compile(resourceAsStream, base.getKey());
base.setProperty(COMPILED_TEMPLATE_PROPERTY, template);
resourceAsStream.close();
}
return template;
}
/* (non-Javadoc)
* @see org.ajax4jsf.resource.BaseResourceRenderer#requireFacesContext()
*/
public boolean requireFacesContext() {
return true;
}
public Object getData(InternetResource base, FacesContext context, Object data) {
ResourceContext resourceContext = new FacesResourceContext(context);
PreparedTemplate template;
try {
template = getTemplate(base, resourceContext);
} catch (IOException e) {
return null;
}
UIComponent component = (UIComponent) (data instanceof UIComponent ? data:null);
TemplateContext templateContext = new TemplateContext(null,context,component);
Object value = template.getValue(templateContext);
if(null == value){
int hashCode = SkinFactory.getInstance().getSkin(context).hashCode(context);
value = ByteBuffer.allocate(4).putInt(hashCode).array();
}
return value;
}
}