Leverage GlassFish 3.1 Annotation Scanning, if available
http://java.net/jira/browse/JAVASERVERFACES-1835
SECTION: Modified Files
----------------------------
M
jsf-ri/src/main/java/com/sun/faces/spi/InjectionProviderFactory.java
M
jsf-ri/src/main/java/com/sun/faces/vendor/WebContainerInjectionProvider
.java
- make NoOpInjectionProvider and WebContainerInjectionProvider
implement
AnnotationScanner
M
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java
- change default annotation scanner to be
DelegateToGlassFishAnnotationScanner. If not found, use
JavaClassScanningAnnotationScanner
M jsf-ri/src/main/java/com/sun/faces/spi/InjectionProvider.java
- remove newly added methods getAnnotatedClassesInCurrentModule().
Moved to new interfaces AnnotationScanner.
M jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java
- This one is a biggie.
- Make it so the InjectionProvider instance is available in the
init-time FacesContext attributes scope.
- Make it so the InjectionProvider is instantiated before annotation
scanning needs to happen.
- Modify the AnnotationScanTask to be able to leverage the
InjectionProvider as an AnnotationScanner.
M
jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.jav
a
- Used to be this class caused the InjectionProvider to be
instantiated.
No more. That happens in ConfigManager. This class now uses the
init
time FacesContext attributes scope to obtain a reference to the
InjectionProvider.
M
jsf-ri/src/main/java/com/sun/faces/config/AnnotationScanner.java
- This is now the abstract base class for both of the following two
classes.
M
jsf-ri/src/main/java/com/sun/faces/config/JavaClassScanningAnnotationSc
anner.java
- Handle the annotation scanning inside Mojarra
A
jsf-ri/src/main/java/com/sun/faces/config/DelegateToGlassFishAnnotation
Scanner.java
- Delegate to GlassFish for annotation scanning
A jsf-ri/src/main/java/com/sun/faces/spi/AnnotationScanner.java
- host to the getAnnotatedClassesInCurrentModule() method.
SECTION: Diffs
----------------------------
Index: jsf-ri/src/main/java/com/sun/faces/spi/AnnotationScanner.java
===================================================================
--- jsf-ri/src/main/java/com/sun/faces/spi/AnnotationScanner.java
(revision 0)
+++ jsf-ri/src/main/java/com/sun/faces/spi/AnnotationScanner.java
(revision 0)
@@ -0,0 +1,65 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights
reserved.
+ *
+ * The contents of this file are subject to the terms of either the
GNU
+ * General Public License Version 2 only ("GPL") or the Common
Development
+ * and Distribution License("CDDL") (collectively, the "License").
You
+ * may not use this file except in compliance with the License. You
can
+ * obtain a copy of the License at
+ *
https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice
in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the
"Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the
License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the
fields
+ * enclosed by brackets [] replaced by your own identifying
information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the
CDDL or
+ * only the GPL Version 2, indicate your decision by adding
"[Contributor]
+ * elects to include this software in this distribution under the
[CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of
license, a
+ * recipient has the option to distribute your version of this file
under
+ * either the CDDL, the GPL Version 2 or to extend the choice of
license to
+ * its licensees as provided above. However, if you add GPL Version 2
code
+ * and therefore, elected the GPL Version 2 license, then the option
applies
+ * only if the new code is made subject to such option by the
copyright
+ * holder.
+ */
+
+package com.sun.faces.spi;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+/**
+ *
+ */
+public interface AnnotationScanner {
+
+ public abstract Map<String, List<ScannedAnnotation>>
getAnnotatedClassesInCurrentModule(ServletContext extContext)
+ throws InjectionProviderException;
+
+ public interface ScannedAnnotation {
+
+ public Collection<URI> getDefiningURIs();
+
+ public String getFullyQualifiedClassName();
+
+ }
+}
Index:
jsf-ri/src/main/java/com/sun/faces/spi/InjectionProviderFactory.java
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/spi/InjectionProviderFactory.java
(revision 8751)
+++
jsf-ri/src/main/java/com/sun/faces/spi/InjectionProviderFactory.java
(working copy)
@@ -44,14 +44,12 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
-import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Enumeration;
import java.util.Map;
-import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.URL;
@@ -429,7 +427,7 @@
* be used when the #INJECTION_PROVIDER_PROPERTY is not specified
or
* is invalid.</p>
*/
- private static final class NoopInjectionProvider implements
InjectionProvider {
+ private static final class NoopInjectionProvider implements
InjectionProvider, AnnotationScanner {
/**
* <p>This is a no-op.</p>
@@ -437,7 +435,7 @@
*/
public void inject(Object managedBean) { }
- public Map<Class<? extends Annotation>, Set<Class<?>>>
getAnnotatedClassesInCurrentModule() throws InjectionProviderException
{
+ public Map<String, List<AnnotationScanner.ScannedAnnotation>>
getAnnotatedClassesInCurrentModule(ServletContext extContext) throws
InjectionProviderException {
return Collections.emptyMap();
}
Index:
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java
(revision 8751)
+++
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java
(working copy)
@@ -40,6 +40,7 @@
package com.sun.faces.spi;
+import com.sun.faces.config.DelegateToGlassFishAnnotationScanner;
import com.sun.faces.config.JavaClassScanningAnnotationScanner;
import javax.servlet.ServletContext;
@@ -53,6 +54,8 @@
private static final Class<? extends AnnotationProvider>
DEFAULT_ANNOTATION_PROVIDER =
JavaClassScanningAnnotationScanner.class;
+ private static final Class<? extends AnnotationProvider>
GLASSFISH31_ANNOTATION_PROVIDER =
+ DelegateToGlassFishAnnotationScanner.class;
private static final String ANNOTATION_PROVIDER_SERVICE_KEY =
"com.sun.faces.spi.annotationprovider";
@@ -89,13 +92,20 @@
private static AnnotationProvider
createDefaultProvider(ServletContext sc) {
+ AnnotationProvider result = null;
+ Constructor c;
try {
- Constructor c =
DEFAULT_ANNOTATION_PROVIDER.getDeclaredConstructor(new Class<?>[] {
ServletContext.class });
- return (AnnotationProvider) c.newInstance(sc);
+ c =
GLASSFISH31_ANNOTATION_PROVIDER.getDeclaredConstructor(new Class<?>[] {
ServletContext.class });
+ result = (AnnotationProvider) c.newInstance(sc);
} catch (Exception e) {
- throw new FacesException(e);
+ try {
+ c =
DEFAULT_ANNOTATION_PROVIDER.getDeclaredConstructor(new Class<?>[] {
ServletContext.class });
+ result = (AnnotationProvider) c.newInstance(sc);
+ } catch (Exception e2) {
+ throw new FacesException(e2);
+ }
}
-
+ return result;
}
}
Index: jsf-ri/src/main/java/com/sun/faces/spi/InjectionProvider.java
===================================================================
--- jsf-ri/src/main/java/com/sun/faces/spi/InjectionProvider.java
(revision 8751)
+++ jsf-ri/src/main/java/com/sun/faces/spi/InjectionProvider.java
(working copy)
@@ -96,6 +96,4 @@
public void invokePostConstruct(Object managedBean)
throws InjectionProviderException;
- public abstract Map<Class<? extends Annotation>, Set<Class<?>>>
getAnnotatedClassesInCurrentModule()
- throws InjectionProviderException;
}
Index:
jsf-ri/src/main/java/com/sun/faces/vendor/WebContainerInjectionProvider
.java
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/vendor/WebContainerInjectionProvider
.java (revision 8751)
+++
jsf-ri/src/main/java/com/sun/faces/vendor/WebContainerInjectionProvider
.java (working copy)
@@ -40,11 +40,11 @@
package com.sun.faces.vendor;
+import com.sun.faces.spi.AnnotationScanner;
import com.sun.faces.spi.InjectionProvider;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.util.FacesLogger;
import java.util.Map;
-import java.util.Set;
import javax.annotation.PreDestroy;
import javax.annotation.PostConstruct;
@@ -52,8 +52,10 @@
import java.lang.reflect.Modifier;
import java.lang.annotation.Annotation;
import java.util.Collections;
+import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;
+import javax.servlet.ServletContext;
/**
* <p>This <code>InjectionProvider</code> will be used if the
@@ -63,7 +65,7 @@
*
* <p>It's important to note that this will not provide resource
injection.</p>
*/
-public class WebContainerInjectionProvider implements
InjectionProvider {
+public class WebContainerInjectionProvider implements
InjectionProvider, AnnotationScanner {
private static final Logger LOGGER =
FacesLogger.APPLICATION.getLogger();
@@ -78,7 +80,7 @@
}
- public Map<Class<? extends Annotation>, Set<Class<?>>>
getAnnotatedClassesInCurrentModule() throws InjectionProviderException
{
+ public Map<String, List<AnnotationScanner.ScannedAnnotation>>
getAnnotatedClassesInCurrentModule(ServletContext sc) throws
InjectionProviderException {
return Collections.emptyMap();
}
Index:
jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.jav
a
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.jav
a (revision 8751)
+++
jsf-ri/src/main/java/com/sun/faces/application/ApplicationAssociate.jav
a (working copy)
@@ -41,11 +41,11 @@
package com.sun.faces.application;
import com.sun.faces.RIConstants;
-import com.sun.faces.application.ApplicationStateInfo;
import com.sun.faces.scripting.groovy.GroovyHelper;
import com.sun.faces.application.resource.ResourceCache;
import com.sun.faces.application.resource.ResourceManager;
import com.sun.faces.application.annotation.AnnotationManager;
+import com.sun.faces.config.ConfigManager;
import com.sun.faces.config.WebConfiguration;
import com.sun.faces.facelets.compiler.Compiler;
import com.sun.faces.facelets.compiler.SAXCompiler;
@@ -62,12 +62,10 @@
import com.sun.faces.facelets.util.DevTools;
import javax.faces.view.facelets.ResourceResolver;
import javax.faces.view.facelets.FaceletCache;
-import javax.faces.view.facelets.FaceletCacheFactory;
import com.sun.faces.facelets.impl.DefaultResourceResolver;
import com.sun.faces.facelets.impl.DefaultFaceletFactory;
import com.sun.faces.mgbean.BeanManager;
import com.sun.faces.spi.InjectionProvider;
-import com.sun.faces.spi.InjectionProviderFactory;
import com.sun.faces.util.MessageUtils;
import com.sun.faces.util.Util;
import com.sun.faces.util.FacesLogger;
@@ -210,7 +208,7 @@
externalContext.getApplicationMap().put(ASSOCIATE_KEY, this);
//noinspection CollectionWithoutInitialCapacity
navigationMap = new ConcurrentHashMap<String,
Set<NavigationCase>>();
- injectionProvider =
InjectionProviderFactory.createInstance(externalContext);
+ injectionProvider = (InjectionProvider)
ctx.getAttributes().get(ConfigManager.INJECTION_PROVIDER_KEY);
WebConfiguration webConfig =
WebConfiguration.getInstance(externalContext);
beanManager = new BeanManager(injectionProvider,
webConfig.isOptionEnabled(
Index: jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java
===================================================================
--- jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java
(revision 8751)
+++ jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java
(working copy)
@@ -67,6 +67,8 @@
import com.sun.faces.config.processor.ValidatorConfigProcessor;
import com.sun.faces.config.processor.FaceletTaglibConfigProcessor;
import com.sun.faces.config.processor.FacesConfigExtensionProcessor;
+import com.sun.faces.spi.InjectionProvider;
+import com.sun.faces.spi.InjectionProviderFactory;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.Timer;
import org.xml.sax.InputSource;
@@ -174,6 +176,14 @@
/**
+ * The initialization time FacesContext scoped key under which the
+ * InjectionProvider is stored.
+ */
+ public static final String INJECTION_PROVIDER_KEY =
+ ConfigManager.class.getName() + "_INJECTION_PROVIDER_TASK";
+
+
+ /**
* Name of the attribute added by {_at_link ParseTask} to indiciate a
* {_at_link Document} instance as a representation of
* <code>/WEB-INF/faces-config.xml</code>.
@@ -318,19 +328,24 @@
new
FacesConfigInfo(facesDocuments[facesDocuments.length - 1]);
facesDocuments = sortDocuments(facesDocuments,
webInfFacesConfigInfo);
+ FacesContext context =
FacesContext.getCurrentInstance();
+ InjectionProvider containerConnector =
+
InjectionProviderFactory.createInstance(context.getExternalContext());
+ context.getAttributes().put(INJECTION_PROVIDER_KEY,
containerConnector);
+
boolean isFaceletsDisabled =
isFaceletsDisabled(webConfig,
webInfFacesConfigInfo);
if (!webInfFacesConfigInfo.isWebInfFacesConfig() ||
!webInfFacesConfigInfo.isMetadataComplete()) {
// execute the Task responsible for finding
annotation classes
- FacesConfigDocumentUrlGetter urlGetter = new
FacesConfigDocumentUrlGetter(facesDocuments);
+ ProvideMetadataToAnnotationScanTask taskMetadata =
new ProvideMetadataToAnnotationScanTask(facesDocuments,
containerConnector);
Future<Map<Class<? extends
Annotation>,Set<Class<?>>>> annotationScan;
if (executor != null) {
- annotationScan = executor.submit(new
AnnotationScanTask(sc, urlGetter));
+ annotationScan = executor.submit(new
AnnotationScanTask(sc, taskMetadata));
pushTaskToContext(sc, annotationScan);
} else {
annotationScan =
- new FutureTask<Map<Class<? extends
Annotation>,Set<Class<?>>>>(new AnnotationScanTask(sc, urlGetter));
+ new FutureTask<Map<Class<? extends
Annotation>,Set<Class<?>>>>(new AnnotationScanTask(sc, taskMetadata));
((FutureTask) annotationScan).run();
}
pushTaskToContext(sc, annotationScan);
@@ -713,32 +728,61 @@
// -----------------------------------------------------------
Inner Classes
- private static final class FacesConfigDocumentUrlGetter {
+ private static final class ProvideMetadataToAnnotationScanTask {
DocumentInfo [] documentInfos;
- public FacesConfigDocumentUrlGetter(DocumentInfo []
documentInfos) {
+ InjectionProvider containerConnector;
+ Set<URI> uris = null;
+ Set<String> jarNames = null;
+
+ private ProvideMetadataToAnnotationScanTask(DocumentInfo []
documentInfos,
+ InjectionProvider containerConnector) {
this.documentInfos = documentInfos;
+ this.containerConnector = containerConnector;
}
- private Set<URI> getAnnotationScanURLs() {
- Set<URI> urls = new HashSet<URI>(documentInfos.length);
- Set<String> jarNames = new
HashSet<String>(documentInfos.length);
+ private void initializeIvars() {
+ if (null != uris || null != jarNames) {
+ assert(null != uris && null != jarNames);
+ return;
+ }
+ uris = new HashSet<URI>(documentInfos.length);
+ jarNames = new HashSet<String>(documentInfos.length);
for (DocumentInfo docInfo : documentInfos) {
- Matcher m =
JAR_PATTERN.matcher(docInfo.getSourceURI().toString());
+ URI sourceURI = docInfo.getSourceURI();
+ Matcher m = JAR_PATTERN.matcher(sourceURI.toString());
if (m.matches()) {
String jarName = m.group(2);
if (!jarNames.contains(jarName)) {
FacesConfigInfo configInfo = new
FacesConfigInfo(docInfo);
if (!configInfo.isMetadataComplete()) {
- urls.add(docInfo.getSourceURI());
+ uris.add(sourceURI);
jarNames.add(jarName);
}
}
}
- }
+ }
+ }
- return urls;
+ private Set<URI> getAnnotationScanURIs() {
+ initializeIvars();
+ return uris;
+
}
+
+ private Set<String> getJarNames() {
+ initializeIvars();
+
+ return jarNames;
+ }
+
+ private com.sun.faces.spi.AnnotationScanner
getAnnotationScanner() {
+ com.sun.faces.spi.AnnotationScanner result = null;
+ if (this.containerConnector instanceof
com.sun.faces.spi.AnnotationScanner) {
+ result = (com.sun.faces.spi.AnnotationScanner)
this.containerConnector;
+ }
+ return result;
+ }
}
@@ -750,16 +794,16 @@
private ServletContext sc;
AnnotationProvider provider;
- FacesConfigDocumentUrlGetter urlGetter;
+ ProvideMetadataToAnnotationScanTask metadataGetter;
// --------------------------------------------------------
Constructors
- public AnnotationScanTask(ServletContext sc,
FacesConfigDocumentUrlGetter urlGetter) {
+ public AnnotationScanTask(ServletContext sc,
ProvideMetadataToAnnotationScanTask metadataGetter) {
this.sc = sc;
this.provider =
AnnotationProviderFactory.createAnnotationProvider(sc);
- this.urlGetter = urlGetter;
+ this.metadataGetter = metadataGetter;
}
@@ -773,8 +817,19 @@
if (t != null) {
t.startTiming();
}
- Set<URI> scanUris = urlGetter.getAnnotationScanURLs();
+ Set<URI> scanUris = null;
+ com.sun.faces.spi.AnnotationScanner annotationScanner =
+ metadataGetter.getAnnotationScanner();
+
+ if (provider instanceof
DelegateToGlassFishAnnotationScanner &&
+ null != annotationScanner) {
+
((DelegateToGlassFishAnnotationScanner)provider).setAnnotationScanner(a
nnotationScanner,
+ metadataGetter.getJarNames());
+ scanUris = Collections.emptySet();
+ } else {
+ scanUris = metadataGetter.getAnnotationScanURIs();
+ }
//AnnotationScanner scanner = new AnnotationScanner(sc);
Map<Class<? extends Annotation>,Set<Class<?>>>
annotatedClasses =
provider.getAnnotatedClasses(scanUris);
Index: jsf-ri/src/main/java/com/sun/faces/config/AnnotationScanner.java
===================================================================
--- jsf-ri/src/main/java/com/sun/faces/config/AnnotationScanner.java
(revision 8751)
+++ jsf-ri/src/main/java/com/sun/faces/config/AnnotationScanner.java
(working copy)
@@ -40,6 +40,13 @@
package com.sun.faces.config;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import com.sun.faces.scripting.ScriptManager;
import com.sun.faces.scripting.groovy.GroovyHelper;
import com.sun.faces.scripting.groovy.GroovyScriptManager;
@@ -58,10 +65,9 @@
import javax.faces.validator.FacesValidator;
import javax.servlet.ServletContext;
import java.lang.annotation.Annotation;
-import java.net.URI;
-import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
+import static
com.sun.faces.config.WebConfiguration.WebContextInitParameter.Annotatio
nScanPackages;
/**
@@ -79,16 +85,29 @@
* <li>javax.faces.event.NamedEvent</li>
* </ul>
*/
-public class AnnotationScanner extends AnnotationProvider {
+public abstract class AnnotationScanner extends AnnotationProvider {
+
+ // <editor-fold defaultstate="collapsed" desc="data">
+
+ // <editor-fold defaultstate="collapsed" desc="private class
vars">
+
private static final Logger LOGGER =
FacesLogger.CONFIG.getLogger();
+ private static final String WILDCARD = "*";
+
+ // </editor-fold>
+ // <editor-fold defaultstate="collapsed" desc="protected class
vars">
protected static final Set<String> FACES_ANNOTATIONS;
protected static final Set<Class<? extends Annotation>>
FACES_ANNOTATION_TYPE;
+ // </editor-fold>
+
static {
HashSet<String> annotations = new HashSet<String>(8, 1.0f);
+ // JAVASERVERFACES-1835 this collection has the same
information twice.
+ // Once in javap -s format, and once as fully qualified Java
class names.
Collections.addAll(annotations,
"Ljavax/faces/component/FacesComponent;",
"Ljavax/faces/convert/FacesConverter;",
@@ -97,7 +116,15 @@
"Ljavax/faces/bean/ManagedBean;",
"Ljavax/faces/event/NamedEvent;",
"Ljavax/faces/component/behavior/FacesBehavior;",
-
"Ljavax/faces/render/FacesBehaviorRenderer;");
+
"Ljavax/faces/render/FacesBehaviorRenderer;",
+ "javax.faces.component.FacesComponent",
+ "javax.faces.convert.FacesConverter",
+ "javax.faces.validator.FacesValidator",
+ "javax.faces.render.FacesRenderer",
+ "javax.faces.bean.ManagedBean",
+ "javax.faces.event.NamedEvent",
+
"javax.faces.component.behavior.FacesBehavior",
+
"javax.faces.render.FacesBehaviorRenderer");
FACES_ANNOTATIONS = Collections.unmodifiableSet(annotations);
HashSet<Class<? extends Annotation>> annotationInstances =
new HashSet<Class<? extends Annotation>>(8, 1.0f);
@@ -114,10 +141,15 @@
}
private List<ScriptManager> scriptManagers = new
ArrayList<ScriptManager>();
+ private boolean isAnnotationScanPackagesSet = false;
+ private String[] webInfClassesPackages;
+ private Map<String,String[]> classpathPackages;
- // ------------------------------------------------------------
Constructors
+ // </editor-fold>
+ // <editor-fold defaultstate="collapsed" desc="constructors">
+
/**
* Creates a new <code>AnnotationScanner</code> instance.
*
@@ -132,32 +164,138 @@
}
WebConfiguration webConfig = WebConfiguration.getInstance(sc);
+ initializeAnnotationScanPackages(webConfig);
}
+ // </editor-fold>
- // ----------------------------------------------------------
Public Methods
+ // <editor-fold defaultstate="collapsed" desc="implementation
details">
+ private void initializeAnnotationScanPackages(WebConfiguration
webConfig) {
+ if (!webConfig.isSet(AnnotationScanPackages)) {
+ return;
+ }
+ isAnnotationScanPackagesSet = true;
+ classpathPackages = new HashMap<String,String[]>(4);
+ webInfClassesPackages = new String[0];
+ String[] options =
webConfig.getOptionValue(AnnotationScanPackages, "\\s+");
+ List<String> packages = new ArrayList<String>(4);
+ for (String option : options) {
+ if (option.length() == 0) {
+ continue;
+ }
+ if (option.startsWith("jar:")) {
+ String[] parts = Util.split(option, ":");
+ if (parts.length != 3) {
+ if (LOGGER.isLoggable(Level.WARNING)) {
+ LOGGER.log(Level.WARNING,
+
"jsf.annotation.scanner.configuration.invalid",
+ new String[] {
AnnotationScanPackages.getQualifiedName(), option });
+ }
+ } else {
+ if (WILDCARD.equals(parts[1]) &&
!classpathPackages.containsKey(WILDCARD)) {
+ classpathPackages.clear();
+ classpathPackages.put(WILDCARD,
normalizeJarPackages(Util.split(parts[2], ",")));
+ } else if (WILDCARD.equals(parts[1]) &&
classpathPackages.containsKey(WILDCARD)) {
+ if (LOGGER.isLoggable(Level.WARNING)) {
+ LOGGER.log(Level.WARNING,
+
"jsf.annotation.scanner.configuration.duplicate.wildcard",
+ new String[] {
AnnotationScanPackages.getQualifiedName(), option });
+ }
+ } else {
+ if (!classpathPackages.containsKey(WILDCARD))
{
+ classpathPackages.put(parts[1],
normalizeJarPackages(Util.split(parts[2], ",")));
+ }
+ }
+ }
+ } else {
+ if (WILDCARD.equals(option) &&
!packages.contains(WILDCARD)) {
+ packages.clear();
+ packages.add(WILDCARD);
+ } else {
+ if (!packages.contains(WILDCARD)) {
+ packages.add(option);
+ }
+ }
+ }
+ }
+ webInfClassesPackages = packages.toArray(new
String[packages.size()]);
+ }
+ private String[] normalizeJarPackages(String[] packages) {
+
+ if (packages.length == 0) {
+ return packages;
+ }
+ List<String> normalizedPackages = new
ArrayList<String>(packages.length);
+ for (String pkg : packages) {
+ if (WILDCARD.equals(pkg)) {
+ normalizedPackages.clear();
+ normalizedPackages.add(WILDCARD);
+ break;
+ } else {
+ normalizedPackages.add(pkg);
+ }
+ }
+ return normalizedPackages.toArray(new
String[normalizedPackages.size()]);
+
+ }
+
+ // </editor-fold>
+
+
+ // ---------------------------------------------------------
Protected Methods
+
+ protected boolean processJar(String entry) {
+
+ // <editor-fold defaultstate="collapsed">
+
+ return (classpathPackages == null
+ || (classpathPackages.containsKey(entry)
+ || classpathPackages.containsKey(WILDCARD)));
+
+ // </editor-fold>
+
+ }
+
/**
- * @return a <code>Map</code> of classes mapped to a specific
annotation type.
- * If no annotations are present, or the application is
considered
- * <code>metadata-complete</code> <code>null</code> will be
returned.
+ * @param candidate the class that should be processed
+ * @return <code>true</code> if the class should be processed
further,
+ * otherwise, <code>false</code>
*/
- public Map<Class<? extends Annotation>,Set<Class<?>>>
getAnnotatedClasses(Set<URI> uris) {
+ protected boolean processClass(String candidate) {
- Set<String> classList = new HashSet<String>();
+ // <editor-fold defaultstate="collapsed">
- processScripts(classList);
+ return processClass(candidate, webInfClassesPackages);
- return processClassList(classList);
+ // </editor-fold>
+ }
+ protected boolean processClass(String candidate, String []
packages) {
+
+ // <editor-fold defaultstate="collapsed">
+
+ if (packages == null) {
+ return true;
+ }
+
+ for (String packageName : packages) {
+ if (candidate.startsWith(packageName) ||
WILDCARD.equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+
+ // </editor-fold>
}
- // ---------------------------------------------------------
Protected Methods
+ protected Map<Class<? extends Annotation>,Set<Class<?>>>
processClassList(Set<String> classList) {
- protected Map<Class<? extends Annotation>,Set<Class<?>>>
processClassList(Set<String> classList) {
+ // <editor-fold defaultstate="collapsed">
+
Map<Class<? extends Annotation>,Set<Class<?>>>
annotatedClasses = null;
if (classList.size() > 0) {
annotatedClasses = new HashMap<Class<? extends
Annotation>,Set<Class<?>>>(6, 1.0f);
@@ -199,12 +337,33 @@
return ((annotatedClasses != null)
? annotatedClasses
: Collections.<Class<? extends Annotation>,
Set<Class<?>>>emptyMap());
+
+ // </editor-fold>
+
}
protected void processScripts(Set<String> classList) {
+
+ // <editor-fold defaultstate="collapsed">
+
for (ScriptManager sm : scriptManagers) {
classList.addAll(sm.getScripts());
}
+
+ // </editor-fold>
+
}
+ protected boolean isAnnotationScanPackagesSet() {
+ return isAnnotationScanPackagesSet;
+ }
+
+ protected Map<String,String[]> getClasspathPackages() {
+ return classpathPackages;
+ }
+
+ protected String [] getWebInfClassesPackages() {
+ return webInfClassesPackages;
+ }
+
}
Index:
jsf-ri/src/main/java/com/sun/faces/config/DelegateToGlassFishAnnotation
Scanner.java
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/config/DelegateToGlassFishAnnotation
Scanner.java (revision 0)
+++
jsf-ri/src/main/java/com/sun/faces/config/DelegateToGlassFishAnnotation
Scanner.java (revision 0)
@@ -0,0 +1,166 @@
+
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights
reserved.
+ *
+ * The contents of this file are subject to the terms of either the
GNU
+ * General Public License Version 2 only ("GPL") or the Common
Development
+ * and Distribution License("CDDL") (collectively, the "License").
You
+ * may not use this file except in compliance with the License. You
can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice
in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the
"Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the
License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the
fields
+ * enclosed by brackets [] replaced by your own identifying
information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the
CDDL or
+ * only the GPL Version 2, indicate your decision by adding
"[Contributor]
+ * elects to include this software in this distribution under the
[CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of
license, a
+ * recipient has the option to distribute your version of this file
under
+ * either the CDDL, the GPL Version 2 or to extend the choice of
license to
+ * its licensees as provided above. However, if you add GPL Version 2
code
+ * and therefore, elected the GPL Version 2 license, then the option
applies
+ * only if the new code is made subject to such option by the
copyright
+ * holder.
+ */
+
+package com.sun.faces.config;
+
+import com.sun.faces.spi.InjectionProviderException;
+import com.sun.faces.util.FacesLogger;
+import static com.sun.faces.spi.AnnotationScanner.ScannedAnnotation;
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.servlet.ServletContext;
+
+
+
+public class DelegateToGlassFishAnnotationScanner extends
AnnotationScanner {
+
+ private static final Logger LOGGER =
FacesLogger.CONFIG.getLogger();
+
+
+ private com.sun.faces.spi.AnnotationScanner annotationScanner =
null;
+ Set<String> jarNamesWithoutMetadataComplete = null;
+
+ public DelegateToGlassFishAnnotationScanner(ServletContext sc) {
+ super(sc);
+ }
+
+ public void
setAnnotationScanner(com.sun.faces.spi.AnnotationScanner
containerConnector, Set<String> jarNamesWithoutMetadataComplete) {
+ this.annotationScanner = containerConnector;
+ this.jarNamesWithoutMetadataComplete =
jarNamesWithoutMetadataComplete;
+ }
+
+ @Override
+ public Map<Class<? extends Annotation>,Set<Class<?>>>
getAnnotatedClasses(Set<URI> uris) {
+
+ Set<String> classList = new HashSet<String>();
+
+ processAnnotations(classList);
+ processScripts(classList);
+
+ return processClassList(classList);
+ }
+
+ private void processAnnotations(Set<String> classList) {
+ try {
+ Map<String, List<ScannedAnnotation>> classesByAnnotation =
annotationScanner.getAnnotatedClassesInCurrentModule(this.sc);
+
+ for (String curAnnotationName :
classesByAnnotation.keySet()) {
+ if (FACES_ANNOTATIONS.contains(curAnnotationName)) {
+ for (ScannedAnnotation curAnnotation :
classesByAnnotation.get(curAnnotationName)) {
+ Collection<URI> definingUris =
curAnnotation.getDefiningURIs();
+ Iterator<URI> iter = definingUris.iterator();
+ URI uri, jarUri = null;
+ String uriString, nameOfJarInJarUri = null;
+ boolean doAdd = false;
+ while (!doAdd && iter.hasNext()) {
+ uri = iter.next();
+ uriString = uri.toASCIIString();
+
+ if (uriString.endsWith("WEB-INF/classes")
|| uriString.endsWith("WEB-INF/classes/")) {
+ doAdd = true;
+ } else for (String jarName :
jarNamesWithoutMetadataComplete) {
+ if (uriString.contains(jarName)) {
+ doAdd = true;
+ jarUri = uri;
+ nameOfJarInJarUri = jarName;
+ break;
+ }
+ }
+ }
+ if (doAdd) {
+ // If the annotationScanPackages context
param is set, we
+ // may yet have to exclude the class
+ String fqcn =
curAnnotation.getFullyQualifiedClassName();
+ if (isAnnotationScanPackagesSet()) {
+ // If the class with the annotation
was found
+ // in a jar file
+ if (null != jarUri) {
+ // see if the jar file is in the
list of jars to include
+ String [] allowedPackages =
+ (getClasspathPackages() !=
null &&
+
getClasspathPackages().get(nameOfJarInJarUri) != null)
+ ?
getClasspathPackages().get(nameOfJarInJarUri)
+ : new String [0];
+ if (0 == allowedPackages.length) {
+ doAdd = false;
+ }
+ for (String curPackage :
allowedPackages) {
+ doAdd =
fqcn.contains(curPackage);
+ if (doAdd) {
+ break;
+ }
+ }
+ } else {
+ doAdd = processClass(fqcn);
+ }
+
+ }
+
+ if (doAdd) {
+ classList.add(fqcn);
+ }
+ }
+ }
+ }
+
+ }
+
+ } catch (InjectionProviderException ex) {
+ if (LOGGER.isLoggable(Level.SEVERE)) {
+ LOGGER.log(Level.SEVERE, "Unable to use GlassFish to
perform "
+ + "annotation scanning. Annotated artifacts
will not "
+ + "be declared to runtime.", ex);
+ }
+
+ }
+
+ }
+
+
+}
Index:
jsf-ri/src/main/java/com/sun/faces/config/JavaClassScanningAnnotationSc
anner.java
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/config/JavaClassScanningAnnotationSc
anner.java (revision 8751)
+++
jsf-ri/src/main/java/com/sun/faces/config/JavaClassScanningAnnotationSc
anner.java (working copy)
@@ -42,7 +42,6 @@
import java.net.URI;
import com.sun.faces.util.FacesLogger;
-import com.sun.faces.util.Util;
import javax.servlet.ServletContext;
import java.io.IOException;
@@ -61,7 +60,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static
com.sun.faces.config.WebConfiguration.WebContextInitParameter.Annotatio
nScanPackages;
/**
* This class is responsible for scanning the class file bytes of
@@ -87,11 +85,8 @@
private static final Pattern JAR_PATTERN =
Pattern.compile("(.*/(\\S*\\.jar)).*");
private static final String WEB_INF_CLASSES = "/WEB-INF/classes/";
- private static final String WILDCARD = "*";
private ClassFile classFileScanner;
- private String[] webInfClassesPackages;
- private Map<String,String[]> classpathPackages;
// ------------------------------------------------------------
Constructors
@@ -107,53 +102,6 @@
classFileScanner = new ClassFile();
- WebConfiguration webConfig = WebConfiguration.getInstance(sc);
- if (webConfig.isSet(AnnotationScanPackages)) {
- classpathPackages = new HashMap<String,String[]>(4);
- webInfClassesPackages = new String[0];
- String[] options =
webConfig.getOptionValue(AnnotationScanPackages, "\\s+");
- List<String> packages = new ArrayList<String>(4);
- for (String option : options) {
- if (option.length() == 0) {
- continue;
- }
- if (option.startsWith("jar:")) {
- String[] parts = Util.split(option, ":");
- if (parts.length != 3) {
- if (LOGGER.isLoggable(Level.WARNING)) {
- LOGGER.log(Level.WARNING,
-
"jsf.annotation.scanner.configuration.invalid",
- new String[] {
AnnotationScanPackages.getQualifiedName(), option });
- }
- } else {
- if (WILDCARD.equals(parts[1]) &&
!classpathPackages.containsKey(WILDCARD)) {
- classpathPackages.clear();
- classpathPackages.put(WILDCARD,
normalizeJarPackages(Util.split(parts[2], ",")));
- } else if (WILDCARD.equals(parts[1]) &&
classpathPackages.containsKey(WILDCARD)) {
- if (LOGGER.isLoggable(Level.WARNING)) {
- LOGGER.log(Level.WARNING,
-
"jsf.annotation.scanner.configuration.duplicate.wildcard",
- new String[] {
AnnotationScanPackages.getQualifiedName(), option });
- }
- } else {
- if
(!classpathPackages.containsKey(WILDCARD)) {
- classpathPackages.put(parts[1],
normalizeJarPackages(Util.split(parts[2], ",")));
- }
- }
- }
- } else {
- if (WILDCARD.equals(option) &&
!packages.contains(WILDCARD)) {
- packages.clear();
- packages.add(WILDCARD);
- } else {
- if (!packages.contains(WILDCARD)) {
- packages.add(option);
- }
- }
- }
- }
- webInfClassesPackages = packages.toArray(new
String[packages.size()]);
- }
}
@@ -217,8 +165,8 @@
JarFile jarFile =
((JarURLConnection)
u.openConnection()).getJarFile();
processJarEntries(jarFile,
- ((classpathPackages != null)
- ?
classpathPackages.get(jarName)
+ ((getClasspathPackages() !=
null)
+ ?
getClasspathPackages().get(jarName)
: null),
classList);
} else {
@@ -388,7 +336,7 @@
if (pathElement.endsWith(".class")) {
String cname =
convertToClassName(WEB_INF_CLASSES,
pathElement);
- if (!processClass(cname,
webInfClassesPackages)) {
+ if (!processClass(cname)) {
continue;
}
if (containsAnnotation(sc, pathElement)) {
@@ -407,26 +355,6 @@
}
- private String[] normalizeJarPackages(String[] packages) {
-
- if (packages.length == 0) {
- return packages;
- }
- List<String> normalizedPackages = new
ArrayList<String>(packages.length);
- for (String pkg : packages) {
- if (WILDCARD.equals(pkg)) {
- normalizedPackages.clear();
- normalizedPackages.add(WILDCARD);
- break;
- } else {
- normalizedPackages.add(pkg);
- }
- }
- return normalizedPackages.toArray(new
String[normalizedPackages.size()]);
-
- }
-
-
/**
* @param sc the <code>ServletContext</code> for the application
being
* scanned
@@ -510,37 +438,8 @@
}
- private boolean processJar(String entry) {
- return (classpathPackages == null
- || (classpathPackages.containsKey(entry)
- || classpathPackages.containsKey(WILDCARD)));
- }
-
-
- /**
- * @param candidate the class that should be processed
- * @param packages the packages of classes that are allowed to be
processed
- * @return <code>true</code> if the class should be processed
further,
- * otherwise, <code>false</code>
- */
- private boolean processClass(String candidate, String[] packages)
{
-
- if (packages == null) {
- return true;
- }
-
- for (String packageName : packages) {
- if (candidate.startsWith(packageName) ||
WILDCARD.equals(packageName)) {
- return true;
- }
- }
- return false;
-
- }
-
-
// -----------------------------------------------------------
Inner Classes
SECTION: New Files
----------------------------
SEE ATTACHMENTS