org.richfaces.resource.CompiledCSSResource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richfaces-core Show documentation
Show all versions of richfaces-core Show documentation
The RichFaces core framework.
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.richfaces.resource;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.MessageFormat;
import javax.faces.application.ProjectStage;
import javax.faces.application.Resource;
import javax.faces.context.FacesContext;
import org.richfaces.log.Logger;
import org.richfaces.log.RichfacesLogger;
import org.richfaces.resource.css.CSSVisitorImpl;
import org.richfaces.skin.Skin;
import org.richfaces.skin.SkinFactory;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.CSSParseException;
import org.w3c.css.sac.ErrorHandler;
import org.w3c.css.sac.InputSource;
import org.w3c.dom.css.CSSStyleSheet;
import com.steadystate.css.parser.CSSOMParser;
import com.steadystate.css.parser.SACParserCSS3;
/**
* @author amarkhel Class, that represented dynamic CSS resource.
*/
public class CompiledCSSResource extends AbstractCacheableResource implements StateHolderResource {
private static final Logger LOGGER = RichfacesLogger.RESOURCE.getLogger();
private static final String NULL_STYLESHEET = "Parsed stylesheet for ''{0}'':''{1}'' resource is null.";
// TODO handle sourceResources headers, etc.
private Resource sourceResource;
public CompiledCSSResource(Resource sourceResource) {
assert sourceResource != null;
this.sourceResource = sourceResource;
}
@Override
public String getLibraryName() {
return sourceResource.getLibraryName();
}
@Override
public void setLibraryName(String libraryName) {
sourceResource.setLibraryName(libraryName);
}
@Override
public String getResourceName() {
return sourceResource.getResourceName();
}
@Override
public void setResourceName(String resourceName) {
sourceResource.setResourceName(resourceName);
}
public InputStream getResourceInputStream() throws IOException {
return sourceResource.getInputStream();
}
@Override
public InputStream getInputStream() throws IOException {
FacesContext ctx = FacesContext.getCurrentInstance();
InputStream stream = null;
CSSStyleSheet styleSheet = null;
try {
stream = getResourceInputStream();
if (null == stream) {
return null;
}
InputSource source = new InputSource(new InputStreamReader(stream));
CSSOMParser parser = new CSSOMParser(new SACParserCSS3());
ErrorHandlerImpl errorHandler = new ErrorHandlerImpl(this, ctx.isProjectStage(ProjectStage.Production));
parser.setErrorHandler(errorHandler);
// parse and create a stylesheet composition
styleSheet = parser.parseStyleSheet(source, null, null);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
LOGGER.warn(e.getMessage(), e);
}
}
}
if (styleSheet != null) {
// TODO nick - handle encoding
String encoding = ctx.getExternalContext().getResponseCharacterEncoding();
CSSVisitorImpl cssVisitor = new CSSVisitorImpl(ctx);
cssVisitor.setEncoding(encoding != null ? encoding : "UTF-8");
cssVisitor.visitStyleSheet(styleSheet);
String cssText = cssVisitor.getCSSText();
return new ByteArrayInputStream(cssText.getBytes(cssVisitor.getEncoding()));
} else {
if (!ctx.isProjectStage(ProjectStage.Production)) {
LOGGER.info(MessageFormat.format(NULL_STYLESHEET, getLibraryName(), getResourceName()));
}
return null;
}
}
@Override
public String getContentType() {
return "text/css";
}
private static int getSkinHashCode(FacesContext context) {
Skin skin = SkinFactory.getInstance(context).getSkin(context);
return skin.hashCode(context);
}
@Override
public boolean userAgentNeedsUpdate(FacesContext context) {
// TODO nick - review
// return resourceDelegate.userAgentNeedsUpdate(context);
if (context.isProjectStage(ProjectStage.Development)) {
return true;
}
return super.userAgentNeedsUpdate(context);
}
private static final class ErrorHandlerImpl implements ErrorHandler {
// TODO nick - sort out logging between stages
private boolean productionStage;
private Resource resource;
private String resourceLocator;
public ErrorHandlerImpl(Resource resource, boolean productionStage) {
super();
this.resource = resource;
this.productionStage = productionStage;
}
private String getResourceLocator() {
if (resourceLocator == null) {
String libraryName = resource.getLibraryName();
String resourceName = resource.getResourceName();
if (libraryName != null && libraryName.length() != 0) {
resourceLocator = libraryName + '/' + resourceName;
} else {
resourceLocator = resourceName;
}
}
return resourceLocator;
}
private void logException(CSSParseException e) {
String formattedMessage = MessageFormat.format("Problem parsing ''{0}'' resource: {1}", getResourceLocator(),
e.getMessage());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(formattedMessage, e);
} else {
LOGGER.warn(formattedMessage);
}
}
public void error(CSSParseException e) throws CSSException {
logException(e);
}
public void fatalError(CSSParseException e) throws CSSException {
logException(e);
}
public void warning(CSSParseException e) throws CSSException {
logException(e);
}
}
public boolean isTransient() {
return false;
}
public void readState(FacesContext context, DataInput dataInput) throws IOException {
// do nothing
}
public void writeState(FacesContext context, DataOutput dataOutput) throws IOException {
dataOutput.writeInt(getSkinHashCode(context));
}
}