You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/08/20 23:50:47 UTC
svn commit: r987645 [2/3] - in
/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces: config/
config/annotation/ spi/ spi/impl/ view/facelets/compiler/
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultAnnotationProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultAnnotationProvider.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultAnnotationProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/config/annotation/DefaultAnnotationProvider.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,659 @@
+/*
+ * 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.io.DataInputStream;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FacesException;
+import javax.faces.bean.ManagedBean;
+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.NamedEvent;
+import javax.faces.render.FacesBehaviorRenderer;
+import javax.faces.render.FacesRenderer;
+import javax.faces.validator.FacesValidator;
+
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+import org.apache.myfaces.spi.AnnotationProvider;
+import org.apache.myfaces.view.facelets.util.Classpath;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public class DefaultAnnotationProvider extends AnnotationProvider
+{
+ private static final Logger log = Logger.getLogger(DefaultAnnotationProvider.class.getName());
+
+ /**
+ * <p> Servlet context init parameter which defines which packages to scan
+ * for beans, separated by commas.</p>
+ */
+ @JSFWebConfigParam(since="2.0")
+ public static final String SCAN_PACKAGES = "org.apache.myfaces.annotation.SCAN_PACKAGES";
+
+ /**
+ * <p>Prefix path used to locate web application classes for this
+ * web application.</p>
+ */
+ private static final String WEB_CLASSES_PREFIX = "/WEB-INF/classes/";
+
+ /**
+ * <p>Prefix path used to locate web application libraries for this
+ * web application.</p>
+ */
+ private static final String WEB_LIB_PREFIX = "/WEB-INF/lib/";
+
+ private static final String META_INF_PREFIX = "META-INF/";
+
+ private static final String FACES_CONFIG_SUFFIX = ".faces-config.xml";
+
+ private static final String STANDARD_FACES_CONFIG_RESOURCE = "META-INF/standard-faces-config.xml";
+
+ /**
+ * <p>Resource path used to acquire implicit resources buried
+ * inside application JARs.</p>
+ */
+ private static final String FACES_CONFIG_IMPLICIT = "META-INF/faces-config.xml";
+
+ private final _ClassByteCodeAnnotationFilter _filter;
+
+ /**
+ * This set contains the annotation names that this AnnotationConfigurator is able to scan
+ * in the format that is read from .class file.
+ */
+ private static Set<String> byteCodeAnnotationsNames;
+
+ static
+ {
+ Set<String> bcan = new HashSet<String>(10, 1f);
+ bcan.add("Ljavax/faces/component/FacesComponent;");
+ bcan.add("Ljavax/faces/component/behavior/FacesBehavior;");
+ bcan.add("Ljavax/faces/convert/FacesConverter;");
+ bcan.add("Ljavax/faces/validator/FacesValidator;");
+ bcan.add("Ljavax/faces/render/FacesRenderer;");
+ bcan.add("Ljavax/faces/bean/ManagedBean;");
+ bcan.add("Ljavax/faces/event/NamedEvent;");
+ //bcan.add("Ljavax/faces/event/ListenerFor;");
+ //bcan.add("Ljavax/faces/event/ListenersFor;");
+ bcan.add("Ljavax/faces/render/FacesBehaviorRenderer;");
+
+ byteCodeAnnotationsNames = Collections.unmodifiableSet(bcan);
+ }
+
+ private static Set<Class<? extends Annotation>> JSF_ANNOTATION_CLASSES;
+
+ static
+ {
+ Set<Class<? extends Annotation>> bcan = new HashSet<Class<? extends Annotation>>(10, 1f);
+ bcan.add(FacesComponent.class);
+ bcan.add(FacesBehavior.class);
+ bcan.add(FacesConverter.class);
+ bcan.add(FacesValidator.class);
+ bcan.add(FacesRenderer.class);
+ bcan.add(ManagedBean.class);
+ bcan.add(NamedEvent.class);
+ bcan.add(FacesBehaviorRenderer.class);
+ JSF_ANNOTATION_CLASSES = Collections.unmodifiableSet(bcan);
+ }
+
+ public DefaultAnnotationProvider()
+ {
+ super();
+ _filter = new _ClassByteCodeAnnotationFilter();
+ }
+
+ @Override
+ public Map<Class<? extends Annotation>, Set<Class<?>>> getAnnotatedClasses(ExternalContext ctx)
+ {
+ Map<Class<? extends Annotation>,Set<Class<?>>> map = new HashMap<Class<? extends Annotation>, Set<Class<?>>>();
+ Collection<Class<?>> classes = null;
+
+ //1. Scan for annotations on /WEB-INF/classes
+ try
+ {
+ classes = getAnnotatedWebInfClasses(ctx);
+ }
+ catch (IOException e)
+ {
+ throw new FacesException(e);
+ }
+
+ for (Class<?> clazz : classes)
+ {
+ processClass(map, clazz);
+ }
+
+ //2. Scan for annotations on classpath
+ try
+ {
+ classes = getAnnotatedMetaInfClasses(ctx, getBaseUrls());
+ }
+ catch (IOException e)
+ {
+ throw new FacesException(e);
+ }
+
+ for (Class<?> clazz : classes)
+ {
+ processClass(map, clazz);
+ }
+
+ //3. Scan on myfaces-impl for annotations available on myfaces-impl.
+ //Also scan jar including META-INF/standard-faces-config.xml
+ //(myfaces-impl jar file)
+ URL url = getClassLoader().getResource(STANDARD_FACES_CONFIG_RESOURCE);
+ if (url == null)
+ {
+ url = getClass().getClassLoader().getResource(STANDARD_FACES_CONFIG_RESOURCE);
+ }
+ classes = getAnnotatedMyfacesImplClasses(ctx, url);
+ for (Class<?> clazz : classes)
+ {
+ processClass(map, clazz);
+ }
+
+ return map;
+ }
+
+ @Override
+ public Set<URL> getBaseUrls() throws IOException
+ {
+ Set<URL> urlSet = new HashSet<URL>();
+
+ //This usually happens when maven-jetty-plugin is used
+ //Scan jars looking for paths including META-INF/faces-config.xml
+ Enumeration<URL> resources = getClassLoader().getResources(FACES_CONFIG_IMPLICIT);
+ while (resources.hasMoreElements())
+ {
+ urlSet.add(resources.nextElement());
+ }
+
+ //Scan files inside META-INF ending with .faces-config.xml
+ URL[] urls = Classpath.search(getClassLoader(), META_INF_PREFIX, FACES_CONFIG_SUFFIX);
+ for (int i = 0; i < urls.length; i++)
+ {
+ urlSet.add(urls[i]);
+ }
+
+ return urlSet;
+ }
+
+ protected Collection<Class<?>> getAnnotatedMetaInfClasses(ExternalContext ctx, Set<URL> urls)
+ {
+ if (urls != null && !urls.isEmpty())
+ {
+ List<Class<?>> list = new ArrayList<Class<?>>();
+ for (URL url : urls)
+ {
+ try
+ {
+ JarFile jarFile = getJarFile(url);
+ if (jarFile != null)
+ {
+ archiveClasses(ctx, jarFile, list);
+ }
+ }
+ catch(IOException e)
+ {
+ log.log(Level.SEVERE, "cannot scan jar file for annotations:"+url, e);
+ }
+ }
+ return list;
+ }
+ return Collections.emptyList();
+ }
+
+ protected Collection<Class<?>> getAnnotatedMyfacesImplClasses(ExternalContext ctx, URL url)
+ {
+ return Collections.emptyList();
+ /*
+ try
+ {
+ List<Class<?>> list = new ArrayList<Class<?>>();
+ JarFile jarFile = getJarFile(url);
+ if (jarFile == null)
+ {
+ return list;
+ }
+ else
+ {
+ return archiveClasses(ctx, jarFile, list);
+ }
+ }
+ catch(IOException e)
+ {
+ throw new FacesException("cannot scan jar file for annotations:"+url, e);
+ }*/
+ }
+
+ protected Collection<Class<?>> getAnnotatedWebInfClasses(ExternalContext ctx) throws IOException
+ {
+ String scanPackages = ctx.getInitParameter(SCAN_PACKAGES);
+ if (scanPackages != null)
+ {
+ try
+ {
+ return packageClasses(ctx, scanPackages);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new FacesException(e);
+ }
+ catch (IOException e)
+ {
+ throw new FacesException(e);
+ }
+ }
+ else
+ {
+ return webClasses(ctx);
+ }
+ }
+
+ /**
+ * <p>Return a list of the classes defined within the given packages
+ * If there are no such classes, a zero-length list will be returned.</p>
+ *
+ * @param scanPackages the package configuration
+ *
+ * @exception ClassNotFoundException if a located class cannot be loaded
+ * @exception IOException if an input/output error occurs
+ */
+ private List<Class<?>> packageClasses(final ExternalContext externalContext,
+ final String scanPackages) throws ClassNotFoundException, IOException
+ {
+
+ List<Class<?>> list = new ArrayList<Class<?>>();
+
+ String[] scanPackageTokens = scanPackages.split(",");
+ for (String scanPackageToken : scanPackageTokens)
+ {
+ if (scanPackageToken.toLowerCase().endsWith(".jar"))
+ {
+ URL jarResource = externalContext.getResource(WEB_LIB_PREFIX
+ + scanPackageToken);
+ String jarURLString = "jar:" + jarResource.toString() + "!/";
+ URL url = new URL(jarURLString);
+ JarFile jarFile = ((JarURLConnection) url.openConnection())
+ .getJarFile();
+
+ archiveClasses(externalContext, jarFile, list);
+ }
+ else
+ {
+ List<Class> list2 = new ArrayList<Class>();
+ _PackageInfo.getInstance().getClasses(list2, scanPackageToken);
+ for (Class c : list2)
+ {
+ list.add(c);
+ }
+ }
+ }
+ return list;
+ }
+
+ /**
+ * <p>Return a list of classes to examine from the specified JAR archive.
+ * If this archive has no classes in it, a zero-length list is returned.</p>
+ *
+ * @param context <code>ExternalContext</code> instance for
+ * this application
+ * @param jar <code>JarFile</code> for the archive to be scanned
+ *
+ * @exception ClassNotFoundException if a located class cannot be loaded
+ */
+ private List<Class<?>> archiveClasses(ExternalContext context, JarFile jar, List<Class<?>> list)
+ {
+
+ // Accumulate and return a list of classes in this JAR file
+ ClassLoader loader = ClassUtils.getContextClassLoader();
+ if (loader == null)
+ {
+ loader = this.getClass().getClassLoader();
+ }
+ Enumeration<JarEntry> entries = jar.entries();
+ while (entries.hasMoreElements())
+ {
+ JarEntry entry = entries.nextElement();
+ if (entry.isDirectory())
+ {
+ continue; // This is a directory
+ }
+ String name = entry.getName();
+ if (name.startsWith("META-INF/"))
+ {
+ continue; // Attribute files
+ }
+ if (!name.endsWith(".class"))
+ {
+ continue; // This is not a class
+ }
+
+ DataInputStream in = null;
+ boolean couldContainAnnotation = false;
+ try
+ {
+ in = new DataInputStream(jar.getInputStream(entry));
+ couldContainAnnotation = _filter
+ .couldContainAnnotationsOnClassDef(in,
+ byteCodeAnnotationsNames);
+ }
+ catch (IOException e)
+ {
+ // Include this class - we can't scan this class using
+ // the filter, but it could be valid, so we need to
+ // load it using the classLoader. Anyway, log a debug
+ // message.
+ couldContainAnnotation = true;
+ if (log.isLoggable(Level.FINE))
+ {
+ log.fine("IOException when filtering class " + name
+ + " for annotations");
+ }
+ }
+ finally
+ {
+ if (in != null)
+ try
+ {
+ in.close();
+ }
+ catch (IOException e)
+ {
+ // No Op
+ }
+ }
+
+ if (couldContainAnnotation)
+ {
+ name = name.substring(0, name.length() - 6); // Trim ".class"
+ Class<?> clazz = null;
+ try
+ {
+ clazz = loader.loadClass(name.replace('/', '.'));
+ }
+ catch (NoClassDefFoundError e)
+ {
+ ; // Skip this class - we cannot analyze classes we cannot load
+ }
+ catch (Exception e)
+ {
+ ; // Skip this class - we cannot analyze classes we cannot load
+ }
+ if (clazz != null)
+ {
+ list.add(clazz);
+ }
+ }
+ }
+ return list;
+
+ }
+
+ /**
+ * <p>Return a list of the classes defined under the
+ * <code>/WEB-INF/classes</code> directory of this web
+ * application. If there are no such classes, a zero-length list
+ * will be returned.</p>
+ *
+ * @param externalContext <code>ExternalContext</code> instance for
+ * this application
+ *
+ * @exception ClassNotFoundException if a located class cannot be loaded
+ */
+ private List<Class<?>> webClasses(ExternalContext externalContext)
+ {
+ List<Class<?>> list = new ArrayList<Class<?>>();
+ webClasses(externalContext, WEB_CLASSES_PREFIX, list);
+ return list;
+ }
+
+ /**
+ * <p>Add classes found in the specified directory to the specified
+ * list, recursively calling this method when a directory is encountered.</p>
+ *
+ * @param externalContext <code>ExternalContext</code> instance for
+ * this application
+ * @param prefix Prefix specifying the "directory path" to be searched
+ * @param list List to be appended to
+ *
+ * @exception ClassNotFoundException if a located class cannot be loaded
+ */
+ private void webClasses(ExternalContext externalContext, String prefix,
+ List<Class<?>> list)
+ {
+
+ ClassLoader loader = getClassLoader();
+
+ Set<String> paths = externalContext.getResourcePaths(prefix);
+ if(paths == null)
+ {
+ return; //need this in case there is no WEB-INF/classes directory
+ }
+ if (log.isLoggable(Level.FINEST))
+ {
+ log.finest("webClasses(" + prefix + ") - Received " + paths.size()
+ + " paths to check");
+ }
+
+ String path = null;
+
+ if (paths.isEmpty())
+ {
+ if (log.isLoggable(Level.WARNING))
+ {
+ log
+ .warning("AnnotationConfigurator does not found classes "
+ + "for annotations in "
+ + prefix
+ + " ."
+ + " This could happen because maven jetty plugin is used"
+ + " (goal jetty:run). Try configure "
+ + SCAN_PACKAGES + " init parameter "
+ + "or use jetty:run-exploded instead.");
+ }
+ }
+ else
+ {
+ for (Object pathObject : paths)
+ {
+ path = (String) pathObject;
+ if (path.endsWith("/"))
+ {
+ webClasses(externalContext, path, list);
+ }
+ else if (path.endsWith(".class"))
+ {
+ DataInputStream in = null;
+ boolean couldContainAnnotation = false;
+ try
+ {
+ in = new DataInputStream(externalContext
+ .getResourceAsStream(path));
+ couldContainAnnotation = _filter
+ .couldContainAnnotationsOnClassDef(in,
+ byteCodeAnnotationsNames);
+ }
+ catch (IOException e)
+ {
+ // Include this class - we can't scan this class using
+ // the filter, but it could be valid, so we need to
+ // load it using the classLoader. Anyway, log a debug
+ // message.
+ couldContainAnnotation = true;
+ if (log.isLoggable(Level.FINE))
+ {
+ log.fine("IOException when filtering class " + path
+ + " for annotations");
+ }
+ }
+ finally
+ {
+ if (in != null)
+ try
+ {
+ in.close();
+ }
+ catch (IOException e)
+ {
+ // No Op
+ }
+ }
+
+ if (couldContainAnnotation)
+ {
+ //Load it and add it to list for later processing
+ path = path.substring(WEB_CLASSES_PREFIX.length()); // Strip prefix
+ path = path.substring(0, path.length() - 6); // Strip suffix
+ path = path.replace('/', '.'); // Convert to FQCN
+
+ Class<?> clazz = null;
+ try
+ {
+ clazz = loader.loadClass(path);
+ }
+ catch (NoClassDefFoundError e)
+ {
+ ; // Skip this class - we cannot analyze classes we cannot load
+ }
+ catch (Exception e)
+ {
+ ; // Skip this class - we cannot analyze classes we cannot load
+ }
+ if (clazz != null)
+ {
+ list.add(clazz);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private JarFile getJarFile(URL url) throws IOException
+ {
+ URLConnection conn = url.openConnection();
+ conn.setUseCaches(false);
+ conn.setDefaultUseCaches(false);
+
+ JarFile jarFile;
+ if (conn instanceof JarURLConnection)
+ {
+ jarFile = ((JarURLConnection) conn).getJarFile();
+ }
+ else
+ {
+ jarFile = _getAlternativeJarFile(url);
+ }
+ return jarFile;
+ }
+
+
+ /**
+ * taken from org.apache.myfaces.view.facelets.util.Classpath
+ *
+ * For URLs to JARs that do not use JarURLConnection - allowed by the servlet spec - attempt to produce a JarFile
+ * object all the same. Known servlet engines that function like this include Weblogic and OC4J. This is not a full
+ * solution, since an unpacked WAR or EAR will not have JAR "files" as such.
+ */
+ private static JarFile _getAlternativeJarFile(URL url) throws IOException
+ {
+ String urlFile = url.getFile();
+
+ // Trim off any suffix - which is prefixed by "!/" on Weblogic
+ int separatorIndex = urlFile.indexOf("!/");
+
+ // OK, didn't find that. Try the less safe "!", used on OC4J
+ if (separatorIndex == -1)
+ {
+ separatorIndex = urlFile.indexOf('!');
+ }
+
+ if (separatorIndex != -1)
+ {
+ String jarFileUrl = urlFile.substring(0, separatorIndex);
+ // And trim off any "file:" prefix.
+ if (jarFileUrl.startsWith("file:"))
+ {
+ jarFileUrl = jarFileUrl.substring("file:".length());
+ }
+
+ return new JarFile(jarFileUrl);
+ }
+
+ return null;
+ }
+
+ private ClassLoader getClassLoader()
+ {
+ ClassLoader loader = ClassUtils.getContextClassLoader();
+ if (loader == null)
+ {
+ loader = this.getClass().getClassLoader();
+ }
+ return loader;
+ }
+
+ private void processClass(Map<Class<? extends Annotation>,Set<Class<?>>> map, Class<?> clazz)
+ {
+ Annotation[] annotations = clazz.getAnnotations();
+ for (Annotation anno : annotations)
+ {
+ Class<? extends Annotation> annotationClass = anno.annotationType();
+ if (JSF_ANNOTATION_CLASSES.contains(annotationClass))
+ {
+ Set<Class<?>> set = map.get(annotationClass);
+ if (set == null)
+ {
+ set = new HashSet<Class<?>>();
+ set.add(clazz);
+ map.put(annotationClass, set);
+ }
+ else
+ {
+ set.add(clazz);
+ }
+
+ }
+ }
+ }
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProvider.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProvider.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,104 @@
+/*
+ * 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.spi;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.FacesWrapper;
+import javax.faces.context.ExternalContext;
+
+/**
+ * This interface provide a way to override myfaces annotation scanning algorithm that
+ * needs to be found at startup:
+ *
+ * <ul>
+ * <li>{@link javax.faces.bean.ManagedBean}</li>
+ * <li>{@link javax.faces.component.FacesComponent}</li>
+ * <li>{@link javax.faces.component.behavior.FacesBehavior}</li>
+ * <li>{@link javax.faces.convert.FacesConverter}</li>
+ * <li>{@link javax.faces.event.NamedEvent}</li>
+ * <li>{@link javax.faces.render.FacesRenderer}</li>
+ * <li>{@link javax.faces.render.FacesBehaviorRenderer}</li>
+ * <li>{@link javax.faces.validator.FacesValidator}</li>
+ * </ul>
+ *
+ * <p>This is provided to allow application containers solve the following points</p>
+ * <ul>
+ * <li>It is common application containers to have its own protocols to handle files. It is
+ * not the same to scan annotation inside a jar than look on a directory.</li>
+ * <li>If the application container has some optimization related to annotation scanning or
+ * it already did that task, it is better to reuse that information instead do the same
+ * thing twice.</li>
+ * </ul>
+ *
+ * <p>To override this class, create a file on a jar file with the following entry name:
+ * /META-INF/services/org.apache.myfaces.spi.AnnotationProvider and put the desired class name of
+ * the class that will override or extend the default AnnotationProvider.
+ * </p>
+ *
+ * <p>To wrap the default AnnotationProvider, use a constructor like
+ * CustomAnnotationProvider(AnnotationProvider ap)</p>
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public abstract class AnnotationProvider implements FacesWrapper<AnnotationProvider>
+{
+
+ /**
+ * Retrieve a map containing the classes that contains annotations used by jsf implementation at
+ * startup.
+ * <p>The default implementation must comply with JSF 2.0 spec section 11.5.1 Requirements for scanning of
+ * classes for annotations.
+ * </p>
+ * <p>This method could call getBaseUrls() to obtain a list of URL that could be used to indicate jar files of
+ * annotations in the classpath.
+ * </p>
+ * <p>If the <faces-config> element in the WEB-INF/faces-config.xml file contains metadata-complete attribute
+ * whose value is "true", this method should not be called.
+ * </p>
+ *
+ * @param ctx The current ExternalContext
+ * @param urls A set of URL pointing to faces-config.xml files that could be used to retrieve annotations from
+ * the classpath.
+ * @return A map with all classes that could contain annotations.
+ */
+ public abstract Map<Class<? extends Annotation>,Set<Class<?>>> getAnnotatedClasses(ExternalContext ctx);
+
+ /**
+ * <p>The returned Set<URL> urls are calculated in this way ( see JSF 2.0 spec section 11.4.2 for definitions )
+ * </p>
+ * <ol>
+ * <li>All resources that match either "META-INF/faces-config.xml" or end with ".facesconfig.xml" directly in
+ * the "META-INF" directory (considered <code>applicationConfigurationResources)<code></li>
+ * </ol>
+ *
+ * @return
+ */
+ public abstract Set<URL> getBaseUrls() throws IOException;
+
+ public AnnotationProvider getWrapped()
+ {
+ return null;
+ }
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProviderFactory.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/AnnotationProviderFactory.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,86 @@
+/*
+ * 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.spi;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+
+import org.apache.commons.discovery.tools.DiscoverSingleton;
+import org.apache.myfaces.spi.impl.DefaultAnnotationProviderFactory;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public abstract class AnnotationProviderFactory
+{
+ protected static final String FACTORY_DEFAULT = DefaultAnnotationProviderFactory.class.getName();
+
+ //private static final String FACTORY_KEY = AnnotationProviderFactory.class.getName();
+
+ public static AnnotationProviderFactory getAnnotationProviderFactory(ExternalContext ctx)
+ {
+ //AnnotationProviderFactory instance = (AnnotationProviderFactory) ctx.getApplicationMap().get(FACTORY_KEY);
+ //if (instance != null)
+ //{
+ // return instance;
+ //}
+ AnnotationProviderFactory lpf = null;
+ try
+ {
+
+ if (System.getSecurityManager() != null)
+ {
+ lpf = (AnnotationProviderFactory) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws PrivilegedActionException
+ {
+ return DiscoverSingleton.find(
+ AnnotationProviderFactory.class,
+ FACTORY_DEFAULT);
+ }
+ });
+ }
+ else
+ {
+ lpf = (AnnotationProviderFactory) DiscoverSingleton.find(AnnotationProviderFactory.class, FACTORY_DEFAULT);
+ }
+ }
+ catch (PrivilegedActionException pae)
+ {
+ throw new FacesException(pae);
+ }
+ //if (lpf != null)
+ //{
+ // setAnnotationProviderFactory(ctx, lpf);
+ //}
+ return lpf;
+ }
+
+ //public static void setAnnotationProviderFactory(ExternalContext ctx, AnnotationProviderFactory instance)
+ //{
+ // ctx.getApplicationMap().put(FACTORY_KEY, instance);
+ //}
+
+ public abstract AnnotationProvider createAnnotationProvider(ExternalContext externalContext);
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProvider.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProvider.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,41 @@
+/*
+ * 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.spi;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+
+import javax.faces.context.ExternalContext;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public abstract class FaceletConfigResourceProvider
+{
+
+ /**
+ *
+ * @param context
+ * @return
+ */
+ public abstract Collection<URL> getFaceletTagLibConfigurationResources(ExternalContext context) throws IOException;
+}
\ No newline at end of file
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProviderFactory.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FaceletConfigResourceProviderFactory.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,86 @@
+/*
+ * 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.spi;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+
+import org.apache.commons.discovery.tools.DiscoverSingleton;
+import org.apache.myfaces.spi.impl.DefaultFaceletConfigResourceProviderFactory;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public abstract class FaceletConfigResourceProviderFactory
+{
+ protected static final String FACTORY_DEFAULT = DefaultFaceletConfigResourceProviderFactory.class.getName();
+
+ //private static final String FACTORY_KEY = FaceletConfigResourceProviderFactory.class.getName();
+
+ public static FaceletConfigResourceProviderFactory getFacesConfigResourceProviderFactory(ExternalContext ctx)
+ {
+ //FaceletConfigResourceProviderFactory instance = (FaceletConfigResourceProviderFactory) ctx.getApplicationMap().get(FACTORY_KEY);
+ //if (instance != null)
+ //{
+ // return instance;
+ //}
+ FaceletConfigResourceProviderFactory lpf = null;
+ try
+ {
+
+ if (System.getSecurityManager() != null)
+ {
+ lpf = (FaceletConfigResourceProviderFactory) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws PrivilegedActionException
+ {
+ return DiscoverSingleton.find(
+ FaceletConfigResourceProviderFactory.class,
+ FACTORY_DEFAULT);
+ }
+ });
+ }
+ else
+ {
+ lpf = (FaceletConfigResourceProviderFactory) DiscoverSingleton.find(FaceletConfigResourceProviderFactory.class, FACTORY_DEFAULT);
+ }
+ }
+ catch (PrivilegedActionException pae)
+ {
+ throw new FacesException(pae);
+ }
+ //if (lpf != null)
+ //{
+ // setFaceletConfigResourceProviderFactory(ctx, lpf);
+ //}
+ return lpf;
+ }
+
+ //public static void setFaceletConfigResourceProviderFactory(ExternalContext ctx, FaceletConfigResourceProviderFactory instance)
+ //{
+ // ctx.getApplicationMap().put(FACTORY_KEY, instance);
+ //}
+
+ public abstract FaceletConfigResourceProvider createFaceletConfigResourceProvider(ExternalContext externalContext);
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProvider.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProvider.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,41 @@
+/*
+ * 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.spi;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+
+import javax.faces.context.ExternalContext;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public abstract class FacesConfigResourceProvider
+{
+
+ /**
+ *
+ * @param context
+ * @return
+ */
+ public abstract Collection<URL> getMetaInfConfigurationResources(ExternalContext context) throws IOException;
+}
\ No newline at end of file
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProviderFactory.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/FacesConfigResourceProviderFactory.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,86 @@
+/*
+ * 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.spi;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+
+import org.apache.commons.discovery.tools.DiscoverSingleton;
+import org.apache.myfaces.spi.impl.DefaultFacesConfigResourceProviderFactory;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public abstract class FacesConfigResourceProviderFactory
+{
+ protected static final String FACTORY_DEFAULT = DefaultFacesConfigResourceProviderFactory.class.getName();
+
+ //private static final String FACTORY_KEY = FacesConfigResourceProviderFactory.class.getName();
+
+ public static FacesConfigResourceProviderFactory getFacesConfigResourceProviderFactory(ExternalContext ctx)
+ {
+ //FacesConfigResourceProviderFactory instance = (FacesConfigResourceProviderFactory) ctx.getApplicationMap().get(FACTORY_KEY);
+ //if (instance != null)
+ //{
+ // return instance;
+ //}
+ FacesConfigResourceProviderFactory lpf = null;
+ try
+ {
+
+ if (System.getSecurityManager() != null)
+ {
+ lpf = (FacesConfigResourceProviderFactory) AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<Object>()
+ {
+ public Object run() throws PrivilegedActionException
+ {
+ return DiscoverSingleton.find(
+ FacesConfigResourceProviderFactory.class,
+ FACTORY_DEFAULT);
+ }
+ });
+ }
+ else
+ {
+ lpf = (FacesConfigResourceProviderFactory) DiscoverSingleton.find(FacesConfigResourceProviderFactory.class, FACTORY_DEFAULT);
+ }
+ }
+ catch (PrivilegedActionException pae)
+ {
+ throw new FacesException(pae);
+ }
+ //if (lpf != null)
+ //{
+ // setFacesConfigResourceProviderFactory(ctx, lpf);
+ //}
+ return lpf;
+ }
+
+ //public static void setFacesConfigResourceProviderFactory(ExternalContext ctx, FacesConfigResourceProviderFactory instance)
+ //{
+ // ctx.getApplicationMap().put(FACTORY_KEY, instance);
+ //}
+
+ public abstract FacesConfigResourceProvider createFacesConfigResourceProvider(ExternalContext externalContext);
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultAnnotationProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultAnnotationProviderFactory.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultAnnotationProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultAnnotationProviderFactory.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,266 @@
+/*
+ * 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.spi.impl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+
+import org.apache.commons.discovery.ResourceNameIterator;
+import org.apache.commons.discovery.resource.ClassLoaders;
+import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
+import org.apache.myfaces.config.annotation.DefaultAnnotationProvider;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+import org.apache.myfaces.spi.AnnotationProvider;
+import org.apache.myfaces.spi.AnnotationProviderFactory;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public class DefaultAnnotationProviderFactory extends AnnotationProviderFactory
+{
+ private static Logger log = Logger.getLogger(DefaultAnnotationProviderFactory.class.getName());
+
+ public static final String ANNOTATION_PROVIDER = AnnotationProvider.class.getName();
+
+ @Override
+ public AnnotationProvider createAnnotationProvider(
+ ExternalContext externalContext)
+ {
+ AnnotationProvider returnValue = null;
+ final ExternalContext extContext = externalContext;
+ try
+ {
+ if (System.getSecurityManager() != null)
+ {
+ returnValue = AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<AnnotationProvider>()
+ {
+ public AnnotationProvider run() throws ClassNotFoundException,
+ NoClassDefFoundError,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException,
+ PrivilegedActionException
+ {
+ return resolveAnnotationProviderFromService(extContext);
+ }
+ });
+ }
+ else
+ {
+ returnValue = resolveAnnotationProviderFromService(extContext);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // ignore
+ }
+ catch (NoClassDefFoundError e)
+ {
+ // ignore
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw new FacesException(e);
+ }
+ return returnValue;
+ }
+
+ private AnnotationProvider resolveAnnotationProviderFromService(
+ ExternalContext externalContext) throws ClassNotFoundException,
+ NoClassDefFoundError,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException,
+ PrivilegedActionException
+ {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null)
+ {
+ classLoader = this.getClass().getClassLoader();
+ }
+ ClassLoaders loaders = new ClassLoaders();
+ loaders.put(classLoader);
+ DiscoverServiceNames dsn = new DiscoverServiceNames(loaders);
+ ResourceNameIterator iter = dsn.findResourceNames(ANNOTATION_PROVIDER);
+ return getApplicationObject(AnnotationProvider.class, iter, new DefaultAnnotationProvider());
+ }
+
+ private <T> T getApplicationObject(Class<T> interfaceClass, ResourceNameIterator classNamesIterator, T defaultObject)
+ {
+ return getApplicationObject(interfaceClass, null, null, classNamesIterator, defaultObject);
+ }
+
+ /**
+ * Creates ApplicationObjects like NavigationHandler or StateManager and creates
+ * the right wrapping chain of the ApplicationObjects known as the decorator pattern.
+ * @param <T>
+ * @param interfaceClass The class from which the implementation has to inherit from.
+ * @param extendedInterfaceClass A subclass of interfaceClass which specifies a more
+ * detailed implementation.
+ * @param extendedInterfaceWrapperClass A wrapper class for the case that you have an ApplicationObject
+ * which only implements the interfaceClass but not the
+ * extendedInterfaceClass.
+ * @param classNamesIterator All the class names of the actual ApplicationObject implementations
+ * from the faces-config.xml.
+ * @param defaultObject The default implementation for the given ApplicationObject.
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ private <T> T getApplicationObject(Class<T> interfaceClass, Class<? extends T> extendedInterfaceClass,
+ Class<? extends T> extendedInterfaceWrapperClass,
+ ResourceNameIterator classNamesIterator, T defaultObject)
+ {
+ T current = defaultObject;
+
+ while (classNamesIterator.hasNext())
+ {
+ String implClassName = classNamesIterator.nextResourceName();
+ Class<? extends T> implClass = ClassUtils.simpleClassForName(implClassName);
+
+ // check, if class is of expected interface type
+ if (!interfaceClass.isAssignableFrom(implClass))
+ {
+ throw new IllegalArgumentException("Class " + implClassName + " is no " + interfaceClass.getName());
+ }
+
+ if (current == null)
+ {
+ // nothing to decorate
+ current = (T) ClassUtils.newInstance(implClass);
+ }
+ else
+ {
+ // let's check if class supports the decorator pattern
+ T newCurrent = null;
+ try
+ {
+ Constructor<? extends T> delegationConstructor = null;
+
+ // first, if there is a extendedInterfaceClass,
+ // try to find a constructor that uses that
+ if (extendedInterfaceClass != null
+ && extendedInterfaceClass.isAssignableFrom(current.getClass()))
+ {
+ try
+ {
+ delegationConstructor =
+ implClass.getConstructor(new Class[] {extendedInterfaceClass});
+ }
+ catch (NoSuchMethodException mnfe)
+ {
+ // just eat it
+ }
+ }
+ if (delegationConstructor == null)
+ {
+ // try to find the constructor with the "normal" interfaceClass
+ delegationConstructor =
+ implClass.getConstructor(new Class[] {interfaceClass});
+ }
+ // impl class supports decorator pattern at this point
+ try
+ {
+ // create new decorator wrapping current
+ newCurrent = delegationConstructor.newInstance(new Object[] { current });
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ }
+ catch (NoSuchMethodException e)
+ {
+ // no decorator pattern support
+ newCurrent = (T) ClassUtils.newInstance(implClass);
+ }
+
+ // now we have a new current object (newCurrent)
+ // --> find out if it is assignable from extendedInterfaceClass
+ // and if not, wrap it in a backwards compatible wrapper (if available)
+ if (extendedInterfaceWrapperClass != null
+ && !extendedInterfaceClass.isAssignableFrom(newCurrent.getClass()))
+ {
+ try
+ {
+ Constructor<? extends T> wrapperConstructor
+ = extendedInterfaceWrapperClass.getConstructor(
+ new Class[] {interfaceClass, extendedInterfaceClass});
+ newCurrent = wrapperConstructor.newInstance(new Object[] {newCurrent, current});
+ }
+ catch (NoSuchMethodException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ }
+
+ current = newCurrent;
+ }
+ }
+
+ return current;
+ }
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFaceletConfigResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFaceletConfigResourceProviderFactory.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFaceletConfigResourceProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFaceletConfigResourceProviderFactory.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,266 @@
+/*
+ * 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.spi.impl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+
+import org.apache.commons.discovery.ResourceNameIterator;
+import org.apache.commons.discovery.resource.ClassLoaders;
+import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+import org.apache.myfaces.spi.FaceletConfigResourceProvider;
+import org.apache.myfaces.spi.FaceletConfigResourceProviderFactory;
+import org.apache.myfaces.view.facelets.compiler.DefaultFaceletConfigResourceProvider;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public class DefaultFaceletConfigResourceProviderFactory extends FaceletConfigResourceProviderFactory
+{
+ private static Logger log = Logger.getLogger(DefaultFaceletConfigResourceProviderFactory.class.getName());
+
+ public static final String ANNOTATION_PROVIDER = FaceletConfigResourceProvider.class.getName();
+
+ @Override
+ public FaceletConfigResourceProvider createFaceletConfigResourceProvider(
+ ExternalContext externalContext)
+ {
+ FaceletConfigResourceProvider returnValue = null;
+ final ExternalContext extContext = externalContext;
+ try
+ {
+ if (System.getSecurityManager() != null)
+ {
+ returnValue = AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<FaceletConfigResourceProvider>()
+ {
+ public FaceletConfigResourceProvider run() throws ClassNotFoundException,
+ NoClassDefFoundError,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException,
+ PrivilegedActionException
+ {
+ return resolveFaceletConfigResourceProviderFromService(extContext);
+ }
+ });
+ }
+ else
+ {
+ returnValue = resolveFaceletConfigResourceProviderFromService(extContext);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // ignore
+ }
+ catch (NoClassDefFoundError e)
+ {
+ // ignore
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw new FacesException(e);
+ }
+ return returnValue;
+ }
+
+ private FaceletConfigResourceProvider resolveFaceletConfigResourceProviderFromService(
+ ExternalContext externalContext) throws ClassNotFoundException,
+ NoClassDefFoundError,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException,
+ PrivilegedActionException
+ {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null)
+ {
+ classLoader = this.getClass().getClassLoader();
+ }
+ ClassLoaders loaders = new ClassLoaders();
+ loaders.put(classLoader);
+ DiscoverServiceNames dsn = new DiscoverServiceNames(loaders);
+ ResourceNameIterator iter = dsn.findResourceNames(ANNOTATION_PROVIDER);
+ return getApplicationObject(FaceletConfigResourceProvider.class, iter, new DefaultFaceletConfigResourceProvider());
+ }
+
+ private <T> T getApplicationObject(Class<T> interfaceClass, ResourceNameIterator classNamesIterator, T defaultObject)
+ {
+ return getApplicationObject(interfaceClass, null, null, classNamesIterator, defaultObject);
+ }
+
+ /**
+ * Creates ApplicationObjects like NavigationHandler or StateManager and creates
+ * the right wrapping chain of the ApplicationObjects known as the decorator pattern.
+ * @param <T>
+ * @param interfaceClass The class from which the implementation has to inherit from.
+ * @param extendedInterfaceClass A subclass of interfaceClass which specifies a more
+ * detailed implementation.
+ * @param extendedInterfaceWrapperClass A wrapper class for the case that you have an ApplicationObject
+ * which only implements the interfaceClass but not the
+ * extendedInterfaceClass.
+ * @param classNamesIterator All the class names of the actual ApplicationObject implementations
+ * from the faces-config.xml.
+ * @param defaultObject The default implementation for the given ApplicationObject.
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ private <T> T getApplicationObject(Class<T> interfaceClass, Class<? extends T> extendedInterfaceClass,
+ Class<? extends T> extendedInterfaceWrapperClass,
+ ResourceNameIterator classNamesIterator, T defaultObject)
+ {
+ T current = defaultObject;
+
+ while (classNamesIterator.hasNext())
+ {
+ String implClassName = classNamesIterator.nextResourceName();
+ Class<? extends T> implClass = ClassUtils.simpleClassForName(implClassName);
+
+ // check, if class is of expected interface type
+ if (!interfaceClass.isAssignableFrom(implClass))
+ {
+ throw new IllegalArgumentException("Class " + implClassName + " is no " + interfaceClass.getName());
+ }
+
+ if (current == null)
+ {
+ // nothing to decorate
+ current = (T) ClassUtils.newInstance(implClass);
+ }
+ else
+ {
+ // let's check if class supports the decorator pattern
+ T newCurrent = null;
+ try
+ {
+ Constructor<? extends T> delegationConstructor = null;
+
+ // first, if there is a extendedInterfaceClass,
+ // try to find a constructor that uses that
+ if (extendedInterfaceClass != null
+ && extendedInterfaceClass.isAssignableFrom(current.getClass()))
+ {
+ try
+ {
+ delegationConstructor =
+ implClass.getConstructor(new Class[] {extendedInterfaceClass});
+ }
+ catch (NoSuchMethodException mnfe)
+ {
+ // just eat it
+ }
+ }
+ if (delegationConstructor == null)
+ {
+ // try to find the constructor with the "normal" interfaceClass
+ delegationConstructor =
+ implClass.getConstructor(new Class[] {interfaceClass});
+ }
+ // impl class supports decorator pattern at this point
+ try
+ {
+ // create new decorator wrapping current
+ newCurrent = delegationConstructor.newInstance(new Object[] { current });
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ }
+ catch (NoSuchMethodException e)
+ {
+ // no decorator pattern support
+ newCurrent = (T) ClassUtils.newInstance(implClass);
+ }
+
+ // now we have a new current object (newCurrent)
+ // --> find out if it is assignable from extendedInterfaceClass
+ // and if not, wrap it in a backwards compatible wrapper (if available)
+ if (extendedInterfaceWrapperClass != null
+ && !extendedInterfaceClass.isAssignableFrom(newCurrent.getClass()))
+ {
+ try
+ {
+ Constructor<? extends T> wrapperConstructor
+ = extendedInterfaceWrapperClass.getConstructor(
+ new Class[] {interfaceClass, extendedInterfaceClass});
+ newCurrent = wrapperConstructor.newInstance(new Object[] {newCurrent, current});
+ }
+ catch (NoSuchMethodException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ }
+
+ current = newCurrent;
+ }
+ }
+
+ return current;
+ }
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFacesConfigResourceProviderFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFacesConfigResourceProviderFactory.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFacesConfigResourceProviderFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/spi/impl/DefaultFacesConfigResourceProviderFactory.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,266 @@
+/*
+ * 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.spi.impl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+
+import org.apache.commons.discovery.ResourceNameIterator;
+import org.apache.commons.discovery.resource.ClassLoaders;
+import org.apache.commons.discovery.resource.names.DiscoverServiceNames;
+import org.apache.myfaces.config.DefaultFacesConfigResourceProvider;
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+import org.apache.myfaces.spi.FacesConfigResourceProvider;
+import org.apache.myfaces.spi.FacesConfigResourceProviderFactory;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public class DefaultFacesConfigResourceProviderFactory extends FacesConfigResourceProviderFactory
+{
+ private static Logger log = Logger.getLogger(DefaultFacesConfigResourceProviderFactory.class.getName());
+
+ public static final String ANNOTATION_PROVIDER = FacesConfigResourceProvider.class.getName();
+
+ @Override
+ public FacesConfigResourceProvider createFacesConfigResourceProvider(
+ ExternalContext externalContext)
+ {
+ FacesConfigResourceProvider returnValue = null;
+ final ExternalContext extContext = externalContext;
+ try
+ {
+ if (System.getSecurityManager() != null)
+ {
+ returnValue = AccessController.doPrivileged(new java.security.PrivilegedExceptionAction<FacesConfigResourceProvider>()
+ {
+ public FacesConfigResourceProvider run() throws ClassNotFoundException,
+ NoClassDefFoundError,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException,
+ PrivilegedActionException
+ {
+ return resolveFacesConfigResourceProviderFromService(extContext);
+ }
+ });
+ }
+ else
+ {
+ returnValue = resolveFacesConfigResourceProviderFromService(extContext);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ // ignore
+ }
+ catch (NoClassDefFoundError e)
+ {
+ // ignore
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, "", e);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw new FacesException(e);
+ }
+ return returnValue;
+ }
+
+ private FacesConfigResourceProvider resolveFacesConfigResourceProviderFromService(
+ ExternalContext externalContext) throws ClassNotFoundException,
+ NoClassDefFoundError,
+ InstantiationException,
+ IllegalAccessException,
+ InvocationTargetException,
+ PrivilegedActionException
+ {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null)
+ {
+ classLoader = this.getClass().getClassLoader();
+ }
+ ClassLoaders loaders = new ClassLoaders();
+ loaders.put(classLoader);
+ DiscoverServiceNames dsn = new DiscoverServiceNames(loaders);
+ ResourceNameIterator iter = dsn.findResourceNames(ANNOTATION_PROVIDER);
+ return getApplicationObject(FacesConfigResourceProvider.class, iter, new DefaultFacesConfigResourceProvider());
+ }
+
+ private <T> T getApplicationObject(Class<T> interfaceClass, ResourceNameIterator classNamesIterator, T defaultObject)
+ {
+ return getApplicationObject(interfaceClass, null, null, classNamesIterator, defaultObject);
+ }
+
+ /**
+ * Creates ApplicationObjects like NavigationHandler or StateManager and creates
+ * the right wrapping chain of the ApplicationObjects known as the decorator pattern.
+ * @param <T>
+ * @param interfaceClass The class from which the implementation has to inherit from.
+ * @param extendedInterfaceClass A subclass of interfaceClass which specifies a more
+ * detailed implementation.
+ * @param extendedInterfaceWrapperClass A wrapper class for the case that you have an ApplicationObject
+ * which only implements the interfaceClass but not the
+ * extendedInterfaceClass.
+ * @param classNamesIterator All the class names of the actual ApplicationObject implementations
+ * from the faces-config.xml.
+ * @param defaultObject The default implementation for the given ApplicationObject.
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ private <T> T getApplicationObject(Class<T> interfaceClass, Class<? extends T> extendedInterfaceClass,
+ Class<? extends T> extendedInterfaceWrapperClass,
+ ResourceNameIterator classNamesIterator, T defaultObject)
+ {
+ T current = defaultObject;
+
+ while (classNamesIterator.hasNext())
+ {
+ String implClassName = classNamesIterator.nextResourceName();
+ Class<? extends T> implClass = ClassUtils.simpleClassForName(implClassName);
+
+ // check, if class is of expected interface type
+ if (!interfaceClass.isAssignableFrom(implClass))
+ {
+ throw new IllegalArgumentException("Class " + implClassName + " is no " + interfaceClass.getName());
+ }
+
+ if (current == null)
+ {
+ // nothing to decorate
+ current = (T) ClassUtils.newInstance(implClass);
+ }
+ else
+ {
+ // let's check if class supports the decorator pattern
+ T newCurrent = null;
+ try
+ {
+ Constructor<? extends T> delegationConstructor = null;
+
+ // first, if there is a extendedInterfaceClass,
+ // try to find a constructor that uses that
+ if (extendedInterfaceClass != null
+ && extendedInterfaceClass.isAssignableFrom(current.getClass()))
+ {
+ try
+ {
+ delegationConstructor =
+ implClass.getConstructor(new Class[] {extendedInterfaceClass});
+ }
+ catch (NoSuchMethodException mnfe)
+ {
+ // just eat it
+ }
+ }
+ if (delegationConstructor == null)
+ {
+ // try to find the constructor with the "normal" interfaceClass
+ delegationConstructor =
+ implClass.getConstructor(new Class[] {interfaceClass});
+ }
+ // impl class supports decorator pattern at this point
+ try
+ {
+ // create new decorator wrapping current
+ newCurrent = delegationConstructor.newInstance(new Object[] { current });
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ }
+ catch (NoSuchMethodException e)
+ {
+ // no decorator pattern support
+ newCurrent = (T) ClassUtils.newInstance(implClass);
+ }
+
+ // now we have a new current object (newCurrent)
+ // --> find out if it is assignable from extendedInterfaceClass
+ // and if not, wrap it in a backwards compatible wrapper (if available)
+ if (extendedInterfaceWrapperClass != null
+ && !extendedInterfaceClass.isAssignableFrom(newCurrent.getClass()))
+ {
+ try
+ {
+ Constructor<? extends T> wrapperConstructor
+ = extendedInterfaceWrapperClass.getConstructor(
+ new Class[] {interfaceClass, extendedInterfaceClass});
+ newCurrent = wrapperConstructor.newInstance(new Object[] {newCurrent, current});
+ }
+ catch (NoSuchMethodException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InstantiationException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ log.log(Level.SEVERE, e.getMessage(), e);
+ throw new FacesException(e);
+ }
+ }
+
+ current = newCurrent;
+ }
+ }
+
+ return current;
+ }
+}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/DefaultFaceletConfigResourceProvider.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/DefaultFaceletConfigResourceProvider.java?rev=987645&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/DefaultFaceletConfigResourceProvider.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/DefaultFaceletConfigResourceProvider.java Fri Aug 20 21:50:46 2010
@@ -0,0 +1,74 @@
+/*
+ * 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.view.facelets.compiler;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.faces.context.ExternalContext;
+
+import org.apache.myfaces.shared_impl.util.ClassUtils;
+import org.apache.myfaces.spi.FaceletConfigResourceProvider;
+import org.apache.myfaces.view.facelets.util.Classpath;
+
+/**
+ *
+ * @since 2.0.2
+ * @author Leonardo Uribe
+ */
+public class DefaultFaceletConfigResourceProvider extends FaceletConfigResourceProvider
+{
+ private static final String META_INF_PREFIX = "META-INF/";
+
+ private static final String FACELET_TAGLIB_SUFFIX = ".taglib.xml";
+
+ public DefaultFaceletConfigResourceProvider()
+ {
+ super();
+ }
+
+ @Override
+ public Collection<URL> getFaceletTagLibConfigurationResources(
+ ExternalContext context) throws IOException
+ {
+ List<URL> urlSet = new ArrayList<URL>();
+
+ //Scan files inside META-INF ending with .faces-config.xml
+ URL[] urls = Classpath.search(getClassLoader(), META_INF_PREFIX, FACELET_TAGLIB_SUFFIX);
+ for (int i = 0; i < urls.length; i++)
+ {
+ urlSet.add(urls[i]);
+ }
+
+ return urlSet;
+ }
+
+ private ClassLoader getClassLoader()
+ {
+ ClassLoader loader = ClassUtils.getContextClassLoader();
+ if (loader == null)
+ {
+ loader = this.getClass().getClassLoader();
+ }
+ return loader;
+ }
+}