/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.commons.resourcehandler;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.el.ELContext;
import javax.el.ELResolver;
import javax.el.FunctionMapper;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
import javax.faces.application.ResourceHandler;
import javax.faces.context.FacesContext;
import org.apache.myfaces.commons.resourcehandler.config.element.Library;
import org.apache.myfaces.commons.resourcehandler.resource.ResourceImpl;
import org.apache.myfaces.commons.resourcehandler.resource.ResourceLoader;
import org.apache.myfaces.commons.resourcehandler.resource.ValueExpressionFilterInputStream;
/**
*
* @author Leonardo Uribe
*
*/
public class ExtendedResourceImpl extends ResourceImpl
{
private String _expectedLocalePrefix;
private ExtendedResourceMeta _extendedResourceMeta;
private ExtendedDefaultResourceHandlerSupport _extendedDefaultResourceHandlerSupport;
public ExtendedResourceImpl(ExtendedResourceMeta resourceMeta,
ResourceLoader resourceLoader, ExtendedDefaultResourceHandlerSupport support,
String contentType, String expectedLocalePrefix, String expectedLibraryName)
{
super(resourceMeta, resourceLoader, support, contentType);
_extendedResourceMeta = resourceMeta;
_expectedLocalePrefix = expectedLocalePrefix;
_extendedDefaultResourceHandlerSupport = support;
if (expectedLibraryName != null)
{
setLibraryName(expectedLibraryName);
}
}
@Override
public InputStream getInputStream() throws IOException
{
if ( getExtendedDefaultResourceHandlerSupport().isGzipResourcesEnabled() &&
getExtendedDefaultResourceHandlerSupport().isCacheDiskGzipResources() &&
getExtendedDefaultResourceHandlerSupport().isCompressable(this) &&
getExtendedDefaultResourceHandlerSupport().userAgentSupportsCompression(FacesContext.getCurrentInstance()))
{
//GZIPResourceLoader will take care of resources containing ValueExpressions
return getResourceLoader().getResourceInputStream(getResourceMeta());
}
else
{
return super.getInputStream();
}
}
@Override
public String getRequestPath()
{
String mapping = getResourceHandlerSupport().getMapping() != null ?
getResourceHandlerSupport().getMapping() :
"" ;
Library library = getExtendedDefaultResourceHandlerSupport().getMyFacesResourcesConfig().
getLibrary(getLibraryName());
if (library.getRequestPath() == null)
{
String localePrefix = getResourceMeta().getLocalePrefix() != null ?
getResourceMeta().getLocalePrefix() : _expectedLocalePrefix;
if (localePrefix == null)
{
// calculate current localePrefix (could be different from the one requested, e.g. on locale change)
localePrefix = getRequestLocalePrefix();
}
String path = null;
if (!getResourceHandlerSupport().isExtensionMapping())
{
path = mapping + getResourceHandlerSupport().getResourceIdentifier() + "/$/" +
localePrefix + '/' +
getLibraryName() + '/' +
getResourceName();
}
else
{
path = getResourceHandlerSupport().getResourceIdentifier() + "/$/" +
localePrefix + '/' +
getLibraryName() + '/' +
getResourceName() + mapping;
}
FacesContext facesContext = FacesContext.getCurrentInstance();
return facesContext.getApplication().getViewHandler().getResourceURL(facesContext, path);
}
else
{
//Redirect url assume prefix mapping.
FacesContext facesContext = FacesContext.getCurrentInstance();
return facesContext.getApplication().getViewHandler().getResourceURL(facesContext,
calculateRequestPath(facesContext, library.getRequestPath()));
}
}
public String getLocalePrefix()
{
String localePrefix = getResourceMeta().getLocalePrefix() != null ?
getResourceMeta().getLocalePrefix() : _expectedLocalePrefix;
if (localePrefix == null)
{
// calculate current localePrefix (could be different from the one requested, e.g. on locale change)
localePrefix = getRequestLocalePrefix();
}
return localePrefix;
}
private String calculateRequestPath(FacesContext context, String expression)
{
ValueExpression requestPath = getExtendedResourceMeta().getRequestPathExpression();
if (requestPath == null)
{
ELContext elContext = new ELContextWrapper(context.getELContext(), context, this);
requestPath = context.getApplication().getExpressionFactory().createValueExpression(
elContext, expression, String.class);
getExtendedResourceMeta().setRequestPathExpression(requestPath);
}
return (String) requestPath.getValue(context.getELContext());
}
protected ExtendedResourceMeta getExtendedResourceMeta()
{
return _extendedResourceMeta;
}
protected ExtendedDefaultResourceHandlerSupport getExtendedDefaultResourceHandlerSupport()
{
return _extendedDefaultResourceHandlerSupport;
}
@Override
public Map<String, String> getResponseHeaders()
{
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext.getApplication().getResourceHandler().isResourceRequest(facesContext))
{
Map<String, String> headers = super.getResponseHeaders();
if (getExtendedDefaultResourceHandlerSupport().isGzipResourcesEnabled() &&
getExtendedDefaultResourceHandlerSupport().userAgentSupportsCompression(facesContext) &&
getExtendedDefaultResourceHandlerSupport().isCompressable(this))
{
headers.put("Content-Encoding", "gzip");
}
return headers;
}
else
{
//No need to return headers
return Collections.emptyMap();
}
}
/**
* Returns the String representation of the current locale for the use in the request path.
*
* @return
*/
private static String getRequestLocalePrefix()
{
FacesContext facesContext = FacesContext.getCurrentInstance();
Locale locale = facesContext.getViewRoot().getLocale();
if (locale == null)
{
// fallback to default locale
locale = Locale.getDefault();
}
String language = locale.getLanguage();
String country = locale.getCountry();
if (country != null)
{
// de_AT
return language + "_" + country;
}
else
{
// de
return language;
}
}
private static class ELContextWrapper extends ELContext
{
private ELContext _delegate;
private VariableMapper _mapper;
private ELContextWrapper(ELContext delegate, FacesContext context, ExtendedResourceImpl resource)
{
this._delegate = delegate;
this._mapper = new VariableMapperWrapper(delegate.getVariableMapper(), context, resource);
}
public void setPropertyResolved(boolean resolved)
{
_delegate.setPropertyResolved(resolved);
}
public boolean isPropertyResolved()
{
return _delegate.isPropertyResolved();
}
public void putContext(Class key, Object contextObject)
{
_delegate.putContext(key, contextObject);
}
public Object getContext(Class key)
{
return _delegate.getContext(key);
}
public ELResolver getELResolver()
{
return _delegate.getELResolver();
}
public FunctionMapper getFunctionMapper()
{
return _delegate.getFunctionMapper();
}
public Locale getLocale()
{
return _delegate.getLocale();
}
public void setLocale(Locale locale)
{
_delegate.setLocale(locale);
}
public VariableMapper getVariableMapper()
{
return _mapper;
}
}
private static class VariableMapperWrapper extends VariableMapper
{
private VariableMapper delegate;
private Map<String, ValueExpression> map;
private VariableMapperWrapper(VariableMapper delegate, FacesContext context, ExtendedResourceImpl resource)
{
this.delegate = delegate;
map = new HashMap<String, ValueExpression>(4,1);
map.put("localePrefix", context.getApplication().getExpressionFactory().createValueExpression(resource.getLocalePrefix(), String.class));
map.put("libraryName", context.getApplication().getExpressionFactory().createValueExpression(resource.getLibraryName(), String.class));
map.put("resourceName", context.getApplication().getExpressionFactory().createValueExpression(resource.getResourceName(), String.class));
map.put("mapping", context.getApplication().getExpressionFactory().createValueExpression(
resource.getExtendedDefaultResourceHandlerSupport().getMapping(), String.class));
map.put("extensionMapping", context.getApplication().getExpressionFactory().createValueExpression(
resource.getExtendedDefaultResourceHandlerSupport().isExtensionMapping(), Boolean.class));
}
public ValueExpression resolveVariable(String variable)
{
ValueExpression value = map.get(variable);
if (value != null)
{
return value;
}
if (delegate != null)
{
return delegate.resolveVariable(variable);
}
return null;
}
public ValueExpression setVariable(String variable,
ValueExpression expression)
{
if (delegate != null)
{
return delegate.setVariable(variable, expression);
}
return null;
}
}
}