blob: 806dfafe131753b6a944485e622914b63133bba9 [file] [log] [blame]
/*
* 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.el.resolver;
import java.beans.FeatureDescriptor;
import java.util.Iterator;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.view.Location;
import org.apache.myfaces.renderkit.html.util.ResourceUtils;
import org.apache.myfaces.resource.ContractResource;
import org.apache.myfaces.resource.ResourceELUtils;
import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
/**
* See JSF 2.0 spec section 5.6.1.3 and 5.6.2.4
*
* @author Leonardo Uribe
*
*/
public final class ResourceResolver extends ELResolver
{
private static final String LIBRARY_THIS = "this";
/** Creates a new instance of ResourceBundleResolver */
public ResourceResolver()
{
}
@Override
public Class<?> getCommonPropertyType(final ELContext context,
final Object base)
{
return base == null ? Object.class : null;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(
final ELContext context, final Object base)
{
return null;
}
@Override
public Class<?> getType(final ELContext context, final Object base,
final Object property)
{
return null;
}
@Override
public Object getValue(final ELContext context, final Object base,
final Object property)
{
if (base != null && property != null && base instanceof ResourceHandler)
{
String reference = (String) property;
int colonIndex = (reference).indexOf(':');
Resource resource;
if (colonIndex == -1)
{
// No library name, just create as a simple resource.
resource = ((ResourceHandler) base).createResource (reference);
}
else
{
String contractName = null;
if (reference.lastIndexOf (':') != colonIndex)
{
// Max of one ":" allowed, so throw an exception.
throw new ELException ("Malformed resource reference found when " +
"resolving " + property);
}
else
{
// Otherwise, portion before the ":" is the library name.
String libraryName = reference.substring (0, colonIndex);
FacesContext facesContext = facesContext(context);
if (LIBRARY_THIS.equals(libraryName))
{
// note in this case we don't need to resolve to an specific
// composite component, instead we need to find the libraryName of the
// composite component associated with the Location. For any composite component
// instance that is created under the same facelet it will be the same,
// so it is enought to get the first one matching the Location object.
Location location = ResourceELUtils.getResourceLocationForResolver(facesContext);
if (location != null)
{
// There are two options:
UIComponent cc = CompositeComponentELUtils.
getCompositeComponentBasedOnLocation(facesContext, location);
Resource ccResource = (Resource) cc.getAttributes().get(
Resource.COMPONENT_RESOURCE_KEY);
libraryName = ccResource.getLibraryName();
contractName = ResourceUtils.getContractName(ccResource);
}
else
{
// JSF 2.2 "this" identifier can refer to a library or contract.
libraryName = ResourceELUtils.getResourceLibraryForResolver(facesContext);
contractName = ResourceELUtils.getResourceContractForResolver(facesContext);
}
}
try
{
if (contractName != null)
{
facesContext.getAttributes().put(ContractResource.CONTRACT_SELECTED, contractName);
}
resource = ((ResourceHandler) base).createResource(reference.substring(colonIndex+1),
libraryName);
}
finally
{
if (contractName != null)
{
facesContext.getAttributes().remove(ContractResource.CONTRACT_SELECTED);
}
}
}
}
context.setPropertyResolved(true);
if (resource != null)
{
return resource.getRequestPath();
}
}
return null;
}
// get the FacesContext from the ELContext
private static FacesContext facesContext(final ELContext context)
{
return (FacesContext)context.getContext(FacesContext.class);
}
@Override
public boolean isReadOnly(final ELContext context, final Object base,
final Object property)
{
//Return false on all cases
return false;
}
@Override
public void setValue(final ELContext context, final Object base,
final Object property, final Object val)
{
//No action takes place
}
}