dev@glassfish.java.net

Jerome: cross platform problem in ClassModelImpl.java (was:Re: Mac only problem with annotation scanning in WAB?)

From: Ed Burns <edward.burns_at_oracle.com>
Date: Fri, 7 Jan 2011 12:20:58 -0800

Issue: http://java.net/jira/browse/GLASSFISH-11636

I have a clue to the cause of this problem. It's filename related.

When I copy the attached war to autodeploy/bundles, like this,

cp maven-module-that-makes-wab/target/Test1-0.0.2.war /Users/edburns/Documents/JavaEE/workareas/glassfish31-1HEAD/distributions/glassfish/target-20110104-2228/stage/glassfish3/glassfish/domains/domain1/autodeploy/bundles

This code is hit as a result.

org.glassfish.osgiweb.OSGiFacesAnnotationScanner.scan()
o.g.o.OSGiWebModuleDecorator.scanFacesAnnotations()
o.g.o.OSGiWebModuleDecorator.populateFacesInformation()
o.g.o.OSGiWebModuleDecorator.decorate()
com.sun.e.web.EmbeddedWebContainer.createContext()
com.sun.e.web.WebContainer.loadWebModule()
c.s.e.web.WebContainer.loadWebModule()
c.s.e.web.WebApplication.start()
o.g.internal.data.EngineRef.start()
o.g.i.data.ModuleInfo.start()
o.g.i.data.ApplicationInfo.start()
c.s.e.v3.server.ApplicationLifecycle.deploy()
c.s.e.v3.server.ApplicationLifecycle.deploy()
o.g.osgijavaeebase.OSGiDeploymentRequest.deploy()
o.g.o.OSGiDeploymentRequest.execute()
o.g.o.AbstractOSGiDeployer.deploy()
o.g.o.OSGiContainer.deploy()
o.g.o.JavaEEExtender.deploy()
o.g.o.JavaEEExtender.access$200()
o.g.o.JavaEEExtender$HybridBundleTrackerCustomizer$1.run()

    static Map<Class<? extends Annotation>, Set<Class<? extends Object>>> scan(Collection<URI> uris, Types types, ClassLoader cl) {
        // can't use ServletContext here, because it is not yet available as this method is called
        // from WebModuleDecorator which is called when WebModule is being created.
        // hence this is a static method.
        Map<Class<? extends Annotation>, Set<Class<? extends Object>>> result =
                new HashMap<Class<? extends Annotation>, Set<Class<? extends Object>>>();
        Class<? extends Annotation>[] annotations = getAnnotationTypes();
        if (annotations == null) return result;
        int total = 0;
        for (Class<? extends Annotation> annotationType : annotations) {
            Type type = types.getBy(annotationType.getName());
            if (type instanceof AnnotationType) {
                Collection<AnnotatedElement> elements = ((AnnotationType) type).allAnnotatedTypes();
                for (AnnotatedElement element : elements) {
                    Type t = (element instanceof Member ? ((Member) element).getDeclaringType() : (Type) element);
                    if (t.wasDefinedIn(uris)) {
                        Set<Class<? extends Object>> classes = result.get(annotationType);
                        if (classes == null) {
                            classes = new HashSet<Class<? extends Object>>();
                            result.put(annotationType, classes);
                        }
                        try {
                            final Class<?> aClass = cl.loadClass(t.getName());
                            logger.info(aClass + " contains " + annotationType);
                            total++;
                            classes.add(aClass);
                        } catch (ClassNotFoundException e) {
                            logger.log(Level.WARNING, "Not able to load " + t.getName(), e);
                        }
                    }
                }
            }
        }
        logger.info("total number of classes with faces annotation = " + total); // TODO(Sahoo): change to finer
        return result;
    }

I see that this conditional

PROBLEM_LINE> if (t.wasDefinedIn(uris)) {

never evaluates to true on the Mac, but it does on Solaris and GNU/Linux.

On the mac, the value of the uris argument to wasDefinedIn() is:

"file:/private/var/folders/fd/fdBu1IQlHx4mfVLx-JeCoE%2B5mEs/-Tmp-/osgiapp4324595333979979999/WEB-INF/classes/"
"file:/private/var/folders/fd/fdBu1IQlHx4mfVLx-JeCoE%2B5mEs/-Tmp-/osgiapp4324595333979979999/WEB-INF/lib/Bundle256.jar"
"file:/private/var/folders/fd/fdBu1IQlHx4mfVLx-JeCoE%2B5mEs/-Tmp-/osgiapp4324595333979979999/WEB-INF/lib/bean-1.0.jar"

On Solaris, I see that the values are

"file:/var/tmp/osgiapp4896518676442360146/WEB-INF/classes/"
"file:/var/tmp/osgiapp4896518676442360146/WEB-INF/lib/bean-1.0.jar"
"file:/var/tmp/osgiapp4896518676442360146/WEB-INF/lib/Bundle255.jar"
"file:/var/tmp/osgiapp4896518676442360146/WEB-INF/lib/bean-1.0.jar"
"file:/var/tmp/osgiapp4896518676442360146/WEB-INF/lib/Bundle255.jar"

Stepping into wasDefinedIn(), on Mac, the definingURIs ivar of t on
PROBLEM_LINE has the following value:

"file:/var/folders/fd/fdBu1IQlHx4mfVLx-JeCoE+5mEs/-Tmp-/osgiapp7964573048141508395/WEB-INF/lib/bean-1.0.jar"

But the as you can see above, the argument list contains

"file:/private/var/folders/fd/fdBu1IQlHx4mfVLx-JeCoE%2B5mEs/-Tmp-/osgiapp7964573048141508395/WEB-INF/lib/bean-1.0.jar"

Looking at the implementation of wasDefinedIn(), we see:

    public boolean wasDefinedIn(Collection<URI> uris) {
        for (URI uri : uris) {
            if (definingURIs.contains(uri)) {
                return true;
            }
        }
        return false;
    }

I don't think the simple contains() test can realize that these two
values are in fact equivalent. 1. "/private/var" vs. "/var" 2. "%2B"
vs. "+".

Ed

-- 
| edward.burns_at_oracle.com | office: +1 407 458 0017
| homepage:               | http://ridingthecrest.com/