blob: 7d9bc5030e261c59451827038c2f375832b047e0 [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.config.annotation;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.FacesException;
import javax.faces.component.FacesComponent;
import javax.faces.component.behavior.FacesBehavior;
import javax.faces.context.ExternalContext;
import javax.faces.convert.FacesConverter;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.NamedEvent;
import javax.faces.render.FacesBehaviorRenderer;
import javax.faces.render.FacesRenderer;
import javax.faces.render.RenderKitFactory;
import javax.faces.validator.FacesValidator;
import javax.faces.view.facelets.FaceletsResourceResolver;
import org.apache.myfaces.config.impl.elements.ApplicationImpl;
import org.apache.myfaces.config.impl.elements.BehaviorImpl;
import org.apache.myfaces.config.impl.elements.ComponentTagDeclarationImpl;
import org.apache.myfaces.config.impl.elements.ConverterImpl;
import org.apache.myfaces.config.impl.elements.FacesConfigImpl;
import org.apache.myfaces.spi.AnnotationProvider;
import org.apache.myfaces.spi.AnnotationProviderFactory;
import org.apache.myfaces.util.lang.StringUtils;
/**
* Configure all annotations that needs to be defined at startup.
*
* <ul>
* <li>{@link javax.faces.component.FacesComponent}</li>
* <li>{@link javax.faces.convert.FacesConverter}</li>
* <li>{@link javax.faces.validator.FacesValidator}</li>
* <li>{@link javax.faces.render.FacesRenderer}</li>
* <li>{@link javax.faces.render.FacesBehaviorRenderer}</li>
* </ul>
* <p>
* Some parts copied from org.apache.shale.tiger.view.faces.LifecycleListener2
* </p>
*
* @since 2.0
* @author Leonardo Uribe (latest modification by $Author$)
* @version $Revision$ $Date$
*/
public class AnnotationConfigurator
{
private static final Logger log = Logger.getLogger(AnnotationConfigurator.class.getName());
public AnnotationConfigurator()
{
}
public FacesConfigImpl createFacesConfig(ExternalContext externalcontext, boolean metadataComplete)
{
if (!metadataComplete)
{
AnnotationProvider provider = AnnotationProviderFactory.getAnnotationProviderFactory(externalcontext).
getAnnotationProvider(externalcontext);
Map<Class<? extends Annotation>, Set<Class<?>>> map = provider.getAnnotatedClasses(externalcontext);
return createFacesConfig(map);
}
return null;
}
/**
* TODO: Implement strategy pattern over this method.
*
* @param map
* @return
*/
protected FacesConfigImpl createFacesConfig(Map<Class<? extends Annotation>, Set<Class<?>>> map)
{
FacesConfigImpl facesConfig = new FacesConfigImpl();
Set<Class<?>> classes = map.get(FacesComponent.class);
if (classes != null && !classes.isEmpty())
{
for (Class<?> clazz : classes)
{
FacesComponent comp = (FacesComponent) clazz.getAnnotation(FacesComponent.class);
if (comp != null)
{
if (log.isLoggable(Level.FINEST))
{
log.finest("addComponent(" + comp.value() + ',' + clazz.getName() + ')');
}
String value = comp.value();
if (StringUtils.isEmpty(value))
{
String simpleName = clazz.getSimpleName();
value = Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
}
facesConfig.addComponent(value, clazz.getName());
if (comp.createTag())
{
String tagName = comp.tagName();
if (StringUtils.isEmpty(tagName))
{
tagName = clazz.getSimpleName();
tagName = Character.toLowerCase(tagName.charAt(0)) + tagName.substring(1);
}
facesConfig.addComponentTagDeclaration(value,
new ComponentTagDeclarationImpl(value, comp.namespace(), tagName));
}
}
}
}
classes = map.get(FacesConverter.class);
if (classes != null && !classes.isEmpty())
{
for (Class<?> clazz : classes)
{
FacesConverter conv = (FacesConverter) clazz.getAnnotation(FacesConverter.class);
if (conv != null)
{
if (log.isLoggable(Level.FINEST))
{
log.finest("addConverter(" + conv.value() + ',' + clazz.getName() + ')');
}
//If there is a previous entry on Application Configuration Resources,
//the entry there takes precedence
boolean hasForClass = !Object.class.equals(conv.forClass());
boolean hasValue = conv.value().length() > 0;
if (hasForClass || hasValue)
{
ConverterImpl converter = new ConverterImpl();
if (hasForClass)
{
converter.setForClass(conv.forClass().getName());
}
if (hasValue)
{
converter.setConverterId(conv.value());
}
converter.setConverterClass(clazz.getName());
facesConfig.addConverter(converter);
}
else
{
throw new FacesException("@FacesConverter must have value, forClass or both. Check annotation "
+ "@FacesConverter on class: " + clazz.getName());
}
}
}
}
classes = map.get(FacesValidator.class);
if (classes != null && !classes.isEmpty())
{
for (Class<?> clazz : classes)
{
FacesValidator val = (FacesValidator) clazz.getAnnotation(FacesValidator.class);
if (val != null)
{
if (log.isLoggable(Level.FINEST))
{
log.finest("addValidator(" + val.value() + ',' + clazz.getName() + ')');
}
String value = val.value();
if (value == null || value.isEmpty())
{
String simpleName = clazz.getSimpleName();
value = Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
}
facesConfig.addValidator(value, clazz.getName());
if (val.isDefault())
{
ApplicationImpl app = null;
if (facesConfig.getApplications().isEmpty())
{
app = new ApplicationImpl();
}
else
{
app = (ApplicationImpl) facesConfig.getApplications().get(0);
}
app.addDefaultValidatorId(value);
}
}
}
}
classes = map.get(FacesRenderer.class);
if (classes != null && !classes.isEmpty())
{
for (Class<?> clazz : classes)
{
FacesRenderer rend = (FacesRenderer) clazz.getAnnotation(FacesRenderer.class);
if (rend != null)
{
String renderKitId = rend.renderKitId();
if (renderKitId == null)
{
renderKitId = RenderKitFactory.HTML_BASIC_RENDER_KIT;
}
if (log.isLoggable(Level.FINEST))
{
log.finest("addRenderer(" + renderKitId + ", "
+ rend.componentFamily() + ", " + rend.rendererType()
+ ", " + clazz.getName() + ')');
}
org.apache.myfaces.config.impl.elements.RenderKitImpl renderKit =
(org.apache.myfaces.config.impl.elements.RenderKitImpl)
facesConfig.getRenderKit(renderKitId);
if (renderKit == null)
{
renderKit = new org.apache.myfaces.config.impl.elements.RenderKitImpl();
renderKit.setId(renderKitId);
facesConfig.addRenderKit(renderKit);
}
org.apache.myfaces.config.impl.elements.RendererImpl renderer =
new org.apache.myfaces.config.impl.elements.RendererImpl();
renderer.setComponentFamily(rend.componentFamily());
renderer.setRendererClass(clazz.getName());
renderer.setRendererType(rend.rendererType());
renderKit.addRenderer(renderer);
}
}
}
classes = map.get(NamedEvent.class);
if (classes != null && !classes.isEmpty())
{
handleNamedEvent(facesConfig, classes);
}
classes = map.get(FacesBehavior.class);
if (classes != null && !classes.isEmpty())
{
handleFacesBehavior(facesConfig, classes);
}
classes = map.get(FacesBehaviorRenderer.class);
if (classes != null && !classes.isEmpty())
{
handleFacesBehaviorRenderer(facesConfig, classes);
}
classes = map.get(FaceletsResourceResolver.class);
if (classes != null && !classes.isEmpty())
{
handleFaceletsResourceResolver(facesConfig, classes);
}
return facesConfig;
}
private void handleNamedEvent(FacesConfigImpl facesConfig, Set<Class<?>> classes)
{
for (Class<?> clazz : classes)
{
NamedEvent namedEvent = (NamedEvent) clazz.getAnnotation(NamedEvent.class);
if (namedEvent != null)
{
// Can only apply @NamedEvent to ComponentSystemEvent subclasses.
if (!ComponentSystemEvent.class.isAssignableFrom(clazz))
{
// Just log this. We'll catch it later in the runtime.
if (log.isLoggable(Level.WARNING))
{
log.warning(clazz.getName() + " is annotated with @javax.faces.event.NamedEvent, but does "
+ "not extend javax.faces.event.ComponentSystemEvent");
}
}
// Have to register @NamedEvent annotations with the NamedEventManager class since
// we need to get access to this info later and can't from the dispenser (it's not a
// singleton).
org.apache.myfaces.config.impl.elements.NamedEventImpl namedEventConfig =
new org.apache.myfaces.config.impl.elements.NamedEventImpl();
namedEventConfig.setEventClass(clazz.getName());
namedEventConfig.setShortName(namedEvent.shortName());
facesConfig.addNamedEvent(namedEventConfig);
}
}
}
private void handleFacesBehavior(FacesConfigImpl facesConfig, Set<Class<?>> classes)
{
for (Class<?> clazz : classes)
{
FacesBehavior facesBehavior = (FacesBehavior) clazz.getAnnotation(FacesBehavior.class);
if (facesBehavior != null)
{
// Can only apply @FacesBehavior to Behavior implementors.
if (!javax.faces.component.behavior.Behavior.class.isAssignableFrom(clazz))
{
// Just log this. We'll catch it later in the runtime.
if (log.isLoggable(Level.WARNING))
{
log.warning(clazz.getName()
+ " is annotated with @javax.faces.component.behavior.FacesBehavior, "
+ "but does not implement javax.faces.component.behavior.Behavior");
}
}
if (log.isLoggable(Level.FINEST))
{
log.finest("addBehavior(" + facesBehavior.value() + ", " + clazz.getName() + ')');
}
BehaviorImpl behavior = new BehaviorImpl();
behavior.setBehaviorId(facesBehavior.value());
behavior.setBehaviorClass(clazz.getName());
facesConfig.addBehavior(behavior);
}
}
}
private void handleFacesBehaviorRenderer(FacesConfigImpl facesConfig, Set<Class<?>> classes)
{
for (Class<?> clazz : classes)
{
FacesBehaviorRenderer facesBehaviorRenderer
= (FacesBehaviorRenderer) clazz.getAnnotation(FacesBehaviorRenderer.class);
if (facesBehaviorRenderer != null)
{
String renderKitId = facesBehaviorRenderer.renderKitId();
//RenderKit renderKit;
if (log.isLoggable(Level.FINEST))
{
log.finest("addClientBehaviorRenderer(" + renderKitId + ", "
+ facesBehaviorRenderer.rendererType() + ", "
+ clazz.getName() + ')');
}
org.apache.myfaces.config.impl.elements.RenderKitImpl renderKit =
(org.apache.myfaces.config.impl.elements.RenderKitImpl)
facesConfig.getRenderKit(renderKitId);
if (renderKit == null)
{
renderKit = new org.apache.myfaces.config.impl.elements.RenderKitImpl();
renderKit.setId(renderKitId);
facesConfig.addRenderKit(renderKit);
}
org.apache.myfaces.config.impl.elements.ClientBehaviorRendererImpl cbr =
new org.apache.myfaces.config.impl.elements.ClientBehaviorRendererImpl();
cbr.setRendererType(facesBehaviorRenderer.rendererType());
cbr.setRendererClass(clazz.getName());
renderKit.addClientBehaviorRenderer(cbr);
}
}
}
private void handleFaceletsResourceResolver(FacesConfigImpl facesConfig, Set<Class<?>> classes)
{
for (Class<?> clazz : classes)
{
FaceletsResourceResolver faceletsResourceResolver =
(FaceletsResourceResolver) clazz.getAnnotation(FaceletsResourceResolver.class);
if (faceletsResourceResolver != null)
{
facesConfig.addResourceResolver(clazz.getName());
}
}
}
}