dev@javaserverfaces.java.net

Re: URGENT: in-progress fix for JAVASERVERFACES-1835

From: <edward.burns_at_oracle.com>
Date: Fri, 10 Dec 2010 18:01:02 +0000 (GMT)

Here is the changebundle to fix the problem.

Review would be appreciated.


Followup to ensure Mojarra 2.1.0 continues to run on older GlassFish
containers http://java.net/jira/browse/JAVASERVERFACES-1835


SECTION: Modified Files
----------------------------
A
jsf-ri/src/main/java/com/sun/faces/config/DelegatingAnnotationProvider.
java

- This is the most important class in this changebundle.

/*
 * This class is the default implementation of AnnotationProvider
 * referenced by the AnnotationProviderFactory. Unless someone
 * manualy provides one via in META-INF/services, this is the one
 * that will actually be instantiated and installed into Mojarra.

 * This class actually delegates the real work to one of two kinds of
 * com.sun.faces.config.AnnotationScanner subclasses.
 * JavaClassScanningAnnotationScanner or
 * DelegateToGlassFishAnnotationScanner.
 *
 */

M
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java

- return to having only one DEFAULT_ANNOTATION_PROVIDER

M jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java

- Pass the InitFacesContext to the AnnotationScanTask. This is
necessary
  so the FacesContext can be used during the annotation scan task.

- In AnnotationScanTask.call(), call callSetCurrentInstance() on our
  InitFacesContext instance. This is necessary because the call()
  method runs on a different thread than the one where InitFacesContext
  was created.

M jsf-ri/src/main/java/com/sun/faces/config/InitFacesContext.java

- Instead of using DelegateToGlassFishAnnotationScanner directly, we
now
  use DelegatingAnnotationProvider. This effectively delays the choice
  of what kind of annotation scanner to use even later in the process.

- add method

+ void callSetCurrentInstance() {
+ setCurrentInstance(this);
+ }

  used when we have a reference to the InitFacesContext, but we are
  running on a different Thread and we want to make sure the
  FacesContext.getCurrentInstance() works.

M
jsf-ri/src/main/java/com/sun/faces/config/DelegateToGlassFishAnnotation
Scanner.java
M
jsf-ri/src/main/java/com/sun/faces/config/JavaClassScanningAnnotationSc
anner.java

- Make the class package private

SECTION: Diffs
----------------------------
Index:
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java  
    (revision 8752)
+++
jsf-ri/src/main/java/com/sun/faces/spi/AnnotationProviderFactory.java  
    (working copy)
@@ -40,8 +40,7 @@
 
 package com.sun.faces.spi;
 
-import com.sun.faces.config.DelegateToGlassFishAnnotationScanner;
-import com.sun.faces.config.JavaClassScanningAnnotationScanner;
+import com.sun.faces.config.DelegatingAnnotationProvider;
 
 import javax.servlet.ServletContext;
 import javax.faces.FacesException;
@@ -53,9 +52,7 @@
 public class AnnotationProviderFactory {
 
     private static final Class<? extends AnnotationProvider>
DEFAULT_ANNOTATION_PROVIDER =
-	JavaClassScanningAnnotationScanner.class;
-    private static final Class<? extends AnnotationProvider>
GLASSFISH31_ANNOTATION_PROVIDER =
-	DelegateToGlassFishAnnotationScanner.class;
+	DelegatingAnnotationProvider.class;
 
     private static final String ANNOTATION_PROVIDER_SERVICE_KEY =
	  "com.sun.faces.spi.annotationprovider";
@@ -96,15 +93,10 @@
	 Constructor c;
 
	 try {
-	     c =
GLASSFISH31_ANNOTATION_PROVIDER.getDeclaredConstructor(new Class<?>[] {
ServletContext.class });
+	     c = DEFAULT_ANNOTATION_PROVIDER.getDeclaredConstructor(new
Class<?>[] { ServletContext.class });
	     result = (AnnotationProvider) c.newInstance(sc);
-	 } catch (Exception e) {
-	     try {
-		 c =
DEFAULT_ANNOTATION_PROVIDER.getDeclaredConstructor(new Class<?>[] {
ServletContext.class });
-		 result = (AnnotationProvider) c.newInstance(sc);
-	     } catch (Exception e2) {
-		 throw new FacesException(e2);
-	     }
+	 } catch (Exception e2) {
+	     throw new FacesException(e2);
	 }
	 return result;
     }
Index: jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java
===================================================================
--- jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java       
(revision 8752)
+++ jsf-ri/src/main/java/com/sun/faces/config/ConfigManager.java       
(working copy)
@@ -328,7 +328,7 @@
		       new
FacesConfigInfo(facesDocuments[facesDocuments.length - 1]);
 
		 facesDocuments = sortDocuments(facesDocuments,
webInfFacesConfigInfo);
-		 FacesContext context =
FacesContext.getCurrentInstance();
+		 InitFacesContext context = (InitFacesContext)
FacesContext.getCurrentInstance();
 
		 InjectionProvider containerConnector =
			
InjectionProviderFactory.createInstance(context.getExternalContext());
@@ -341,11 +341,11 @@
		     ProvideMetadataToAnnotationScanTask taskMetadata =
new ProvideMetadataToAnnotationScanTask(facesDocuments,
containerConnector);
		     Future<Map<Class<? extends
Annotation>,Set<Class<?>>>> annotationScan;
		     if (executor != null) {
-			 annotationScan = executor.submit(new
AnnotationScanTask(sc, taskMetadata));
+			 annotationScan = executor.submit(new
AnnotationScanTask(sc, context, taskMetadata));
			 pushTaskToContext(sc, annotationScan);
		     } else {
			 annotationScan =
-			       new FutureTask<Map<Class<? extends
Annotation>,Set<Class<?>>>>(new AnnotationScanTask(sc, taskMetadata));
+			       new FutureTask<Map<Class<? extends
Annotation>,Set<Class<?>>>>(new AnnotationScanTask(sc, context,
taskMetadata));
			 ((FutureTask) annotationScan).run();
		     }
		     pushTaskToContext(sc, annotationScan);
@@ -793,15 +793,15 @@
     private static class AnnotationScanTask implements
Callable<Map<Class<? extends Annotation>,Set<Class<?>>>> {
 
	 private ServletContext sc;
-	 AnnotationProvider provider;
-	 ProvideMetadataToAnnotationScanTask metadataGetter;
+	 private InitFacesContext facesContext;
+	 private AnnotationProvider provider;
+	 private ProvideMetadataToAnnotationScanTask metadataGetter;
 
	 // --------------------------------------------------------
Constructors
 
 
-	 public AnnotationScanTask(ServletContext sc,
ProvideMetadataToAnnotationScanTask metadataGetter) {
-
-	     this.sc = sc;
+	 public AnnotationScanTask(ServletContext sc, InitFacesContext
facesContext, ProvideMetadataToAnnotationScanTask metadataGetter) {
+	     this.facesContext = facesContext;
	     this.provider =
AnnotationProviderFactory.createAnnotationProvider(sc);
	     this.metadataGetter = metadataGetter;
 
@@ -818,16 +818,23 @@
		 t.startTiming();
	     }
 
+	     // We are executing on a different thread.
+	     facesContext.callSetCurrentInstance();
	     Set<URI> scanUris = null;
	     com.sun.faces.spi.AnnotationScanner annotationScanner =
		     metadataGetter.getAnnotationScanner();
 
-	     if (provider instanceof
DelegateToGlassFishAnnotationScanner &&
+	     // This is where we discover what kind of
InjectionProvider
+	     // we have.
+	     if (provider instanceof DelegatingAnnotationProvider &&
		 null != annotationScanner) {
-		
((DelegateToGlassFishAnnotationScanner)provider).setAnnotationScanner(a
nnotationScanner,
+		 // This InjectionProvider is capable of annotation
scanning *and*
+		 // injection.
+		
((DelegatingAnnotationProvider)provider).setAnnotationScanner(annotatio
nScanner,
			 metadataGetter.getJarNames());
		 scanUris = Collections.emptySet();
	     } else {
+		 // This InjectionProvider is capable of annotation
scanning only
		 scanUris = metadataGetter.getAnnotationScanURIs();
	     }
	     //AnnotationScanner scanner = new AnnotationScanner(sc);
Index:
jsf-ri/src/main/java/com/sun/faces/config/DelegatingAnnotationProvider.
java
===================================================================
---
jsf-ri/src/main/java/com/sun/faces/config/DelegatingAnnotationProvider.
java (revision 0)
+++
jsf-ri/src/main/java/com/sun/faces/config/DelegatingAnnotationProvider.
java (revision 0)
@@ -0,0 +1,78 @@
+
+/*
+ * 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.AnnotationProvider;
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+import javax.servlet.ServletContext;
+
+
+
+public class DelegatingAnnotationProvider extends AnnotationProvider {
+
+    private AnnotationScanner scanner = null;
+
+    public DelegatingAnnotationProvider(ServletContext sc) {
+	 super(sc);
+    }
+
+    @Override
+    public Map<Class<? extends Annotation>, Set<Class<?>>>
getAnnotatedClasses(Set<URI> urls) {
+	 if (null == scanner) {
+	     scanner = new JavaClassScanningAnnotationScanner(sc);
+	 }
+	 return scanner.getAnnotatedClasses(urls);
+    }
+
+    public void
setAnnotationScanner(com.sun.faces.spi.AnnotationScanner
containerConnector, Set<String> jarNamesWithoutMetadataComplete) {
+	 assert(null == scanner);
+	 DelegateToGlassFishAnnotationScanner impl =
+		 new DelegateToGlassFishAnnotationScanner(sc);
+	 impl.setAnnotationScanner(containerConnector,
jarNamesWithoutMetadataComplete);
+	 scanner = impl;
+    }
+
+
+}
Index: jsf-ri/src/main/java/com/sun/faces/config/InitFacesContext.java
===================================================================
--- jsf-ri/src/main/java/com/sun/faces/config/InitFacesContext.java    
(revision 8752)
+++ jsf-ri/src/main/java/com/sun/faces/config/InitFacesContext.java    
(working copy)
@@ -96,6 +96,10 @@
	 setCurrentInstance(this);
     }
 
+    void callSetCurrentInstance() {
+	 setCurrentInstance(this);
+    }
+
     @Override
     public Map<Object, Object> getAttributes() {
	 if (attributes == null) {
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 8752)
+++
jsf-ri/src/main/java/com/sun/faces/config/DelegateToGlassFishAnnotation
Scanner.java (working copy)
@@ -58,7 +58,7 @@
 
 
 
-public class DelegateToGlassFishAnnotationScanner extends
AnnotationScanner {
+class DelegateToGlassFishAnnotationScanner extends AnnotationScanner {
 
     private static final Logger LOGGER =
FacesLogger.CONFIG.getLogger();
 
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 8752)
+++
jsf-ri/src/main/java/com/sun/faces/config/JavaClassScanningAnnotationSc
anner.java   (working copy)
@@ -76,7 +76,7 @@
  *  <li>javax.faces.event.NamedEvent</li>
  * </ul>
  */
-public class JavaClassScanningAnnotationScanner extends
AnnotationScanner {
+class JavaClassScanningAnnotationScanner extends AnnotationScanner {
 
     private static final Logger LOGGER =
FacesLogger.CONFIG.getLogger();
 
SECTION: New Files
----------------------------
SEE ATTACHMENTS