You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2014/08/10 16:43:37 UTC

svn commit: r1617111 - in /tomee/tomee/trunk/container: openejb-core/src/main/java/org/apache/openejb/assembler/ openejb-core/src/main/java/org/apache/openejb/assembler/classic/ openejb-core/src/main/java/org/apache/openejb/cdi/ openejb-core/src/main/j...

Author: rmannibucau
Date: Sun Aug 10 14:43:36 2014
New Revision: 1617111

URL: http://svn.apache.org/r1617111
Log:
cdi 1.1 scan config - some enhancements to be done at least in org.apache.openejb.cdi.CdiScanner#isBean

Added:
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/ExclusionInfo.java
      - copied, changed from r1616823, tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBBeanInfoService.java
    tomee/tomee/trunk/container/openejb-jee/src/main/java/org/apache/openejb/jee/Scan.java
Modified:
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/BeansInfo.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiScanner.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/ReadDescriptors.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java

Copied: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/ExclusionInfo.java (from r1616823, tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java)
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/ExclusionInfo.java?p2=tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/ExclusionInfo.java&p1=tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java&r1=1616823&r2=1617111&rev=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EjbJarInfo.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/ExclusionInfo.java Sun Aug 10 14:43:36 2014
@@ -15,49 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.openejb.assembler.classic;
+package org.apache.openejb.assembler;
 
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElements;
-import java.net.URI;
-import java.util.ArrayList;
+import org.apache.openejb.assembler.classic.CommonInfoObject;
+
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-
-public class EjbJarInfo extends CommonInfoObject {
-    public final Properties properties = new Properties();
-
-    public String moduleName;
-    public String moduleId;
-    public URI moduleUri;
-    public String path;
-    public boolean webapp;
-
-    @XmlElements({ // needed for unmarshalling
-        @XmlElement(name = "stateless", type = StatelessBeanInfo.class),
-        @XmlElement(name = "entity", type = EntityBeanInfo.class),
-        @XmlElement(name = "stateful", type = StatefulBeanInfo.class),
-        @XmlElement(name = "singleton", type = SingletonBeanInfo.class),
-        @XmlElement(name = "message-driven", type = MessageDrivenBeanInfo.class),
-        @XmlElement(name = "managed-bean", type = ManagedBeanInfo.class)
-    })
-    public final List<EnterpriseBeanInfo> enterpriseBeans = new ArrayList<EnterpriseBeanInfo>();
-
-    public final List<SecurityRoleInfo> securityRoles = new ArrayList<SecurityRoleInfo>();
-    public final List<MethodPermissionInfo> methodPermissions = new ArrayList<MethodPermissionInfo>();
-    public final List<MethodTransactionInfo> methodTransactions = new ArrayList<MethodTransactionInfo>();
-    public final List<MethodConcurrencyInfo> methodConcurrency = new ArrayList<MethodConcurrencyInfo>();
-    public final List<InterceptorInfo> interceptors = new ArrayList<InterceptorInfo>();
-    public final List<InterceptorBindingInfo> interceptorBindings = new ArrayList<InterceptorBindingInfo>();
-    public final List<MethodInfo> excludeList = new ArrayList<MethodInfo>();
-    public final List<ApplicationExceptionInfo> applicationException = new ArrayList<ApplicationExceptionInfo>();
-    public final List<PortInfo> portInfos = new ArrayList<PortInfo>();
-    public final Set<String> watchedResources = new TreeSet<String>();
-    public final JndiEncInfo moduleJndiEnc = new JndiEncInfo();
 
-    public BeansInfo beans;
-    public Set<String> mbeans = new TreeSet<String>();
-    public final List<IdPropertiesInfo> pojoConfigurations = new ArrayList<IdPropertiesInfo>();
+public class ExclusionInfo extends CommonInfoObject {
+    public final List<String> availableClasses = new LinkedList<>();
+    public final List<String> notAvailableClasses = new LinkedList<>();
+    public final List<String> systemPropertiesPresence = new LinkedList<>();
+    public final Properties systemProperties = new Properties();
 }

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java Sun Aug 10 14:43:36 2014
@@ -55,6 +55,7 @@ import org.apache.openejb.cdi.CdiResourc
 import org.apache.openejb.cdi.CdiScanner;
 import org.apache.openejb.cdi.CustomELAdapter;
 import org.apache.openejb.cdi.ManagedSecurityService;
+import org.apache.openejb.cdi.OpenEJBBeanInfoService;
 import org.apache.openejb.cdi.OpenEJBJndiService;
 import org.apache.openejb.cdi.OpenEJBTransactionService;
 import org.apache.openejb.cdi.OptimizedLoaderService;
@@ -131,6 +132,7 @@ import org.apache.openejb.util.proxy.Pro
 import org.apache.openejb.util.proxy.ProxyManager;
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.webbeans.logger.JULLoggerFactory;
+import org.apache.webbeans.spi.BeanArchiveService;
 import org.apache.webbeans.spi.ContainerLifecycle;
 import org.apache.webbeans.spi.ContextsService;
 import org.apache.webbeans.spi.JNDIService;
@@ -1294,6 +1296,7 @@ public class Assembler extends Assembler
             services.put(AppContext.class, appContext);
             services.put(TransactionService.class, new OpenEJBTransactionService());
             services.put(ScannerService.class, new CdiScanner());
+            services.put(BeanArchiveService.class, new OpenEJBBeanInfoService());
             services.put(ELAdaptor.class, new CustomELAdapter(appContext));
             services.put(LoaderService.class, new OptimizedLoaderService());
 

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/BeansInfo.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/BeansInfo.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/BeansInfo.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/BeansInfo.java Sun Aug 10 14:43:36 2014
@@ -17,10 +17,13 @@
 
 package org.apache.openejb.assembler.classic;
 
+import org.apache.openejb.assembler.ExclusionInfo;
+
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.Map;
 
 /**
  * @version $Rev$ $Date$
@@ -33,10 +36,14 @@ public class BeansInfo extends InfoObjec
     public final List<String> alternativeClasses = new ArrayList<String>();
     public final List<String> alternativeStereotypes = new ArrayList<String>();
 
-    public final Set<String> managedClasses = new TreeSet<String>();
+    public final Map<URL, List<String>> managedClasses = new HashMap<>();
 
     public final List<String> duplicatedInterceptors = new ArrayList<String>();
     public final List<String> duplicatedDecorators = new ArrayList<String>();
     public final List<String> duplicatedAlternativeClasses = new ArrayList<String>();
     public final List<String> duplicatedAlternativeStereotypes = new ArrayList<String>();
+
+    public String version = "1.1";
+    public String discoveryMode;
+    public final Map<String, ExclusionInfo> excludes = new HashMap<>();
 }

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiScanner.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiScanner.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiScanner.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/CdiScanner.java Sun Aug 10 14:43:36 2014
@@ -38,13 +38,15 @@ import org.apache.webbeans.exception.Web
 import org.apache.webbeans.inject.AlternativesManager;
 import org.apache.webbeans.intercept.InterceptorsManager;
 import org.apache.webbeans.spi.BDABeansXmlScanner;
+import org.apache.webbeans.spi.BeanArchiveService;
 import org.apache.webbeans.spi.ScannerService;
 
+import java.lang.annotation.Annotation;
 import java.net.URL;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import static java.util.Arrays.asList;
@@ -61,7 +63,13 @@ public class CdiScanner implements Scann
     };
 
     // TODO add all annotated class
-    private final Set<Class<?>> classes = new HashSet<Class<?>>();
+    private final Set<Class<?>> classes = new HashSet<>();
+
+    private WebBeansContext webBeansContext;
+
+    public void setContext(final WebBeansContext webBeansContext) {
+        this.webBeansContext = webBeansContext;
+    }
 
     @Override
     public void init(final Object object) {
@@ -172,9 +180,45 @@ public class CdiScanner implements Scann
             final ClassLoader scl = ClassLoader.getSystemClassLoader();
             final boolean filterByClassLoader = "true".equals(SystemInstance.get().getProperty(OPENEJB_CDI_FILTER_CLASSLOADER, "true"));
 
-            final Iterator<String> it = beans.managedClasses.iterator();
-            while (it.hasNext()) {
-                process(classLoader, it, startupObject, comparator, scl, filterByClassLoader);
+            final BeanArchiveService beanArchiveService = webBeansContext.getBeanArchiveService();
+            final boolean openejb = OpenEJBBeanInfoService.class.isInstance(beanArchiveService);
+
+            for (final Map.Entry<URL, List<String>> next : beans.managedClasses.entrySet()) {
+                final List<String> value = next.getValue();
+
+                final URL key = next.getKey();
+                final BeanArchiveService.BeanArchiveInformation information;
+                if (openejb) {
+                    final OpenEJBBeanInfoService beanInfoService = OpenEJBBeanInfoService.class.cast(beanArchiveService);
+                    information = beanInfoService.createBeanArchiveInformation(beans, classLoader);
+                    beanInfoService.getBeanArchiveInfo().put(key, information);
+                } else {
+                    information = beanArchiveService.getBeanArchiveInformation(key);
+                }
+
+                final boolean scanModeAnnotated = BeanArchiveService.BeanDiscoveryMode.ANNOTATED.equals(information.getBeanDiscoveryMode());
+                final boolean noScan = BeanArchiveService.BeanDiscoveryMode.NONE.equals(information.getBeanDiscoveryMode());
+                final boolean isNotEarWebApp = startupObject.getWebContext() == null;
+
+                if (!noScan) {
+                    for (final String name : value) {
+                        if (information.isClassExcluded(name)) {
+                            continue;
+                        }
+
+                        final Class clazz = load(name, classLoader);
+                        if (scanModeAnnotated) {
+                            if (clazz != null && isBean(clazz)) {
+                                classes.add(clazz);
+                            }
+                        } else {
+                            final ClassLoader loader = clazz.getClassLoader();
+                            if (!filterByClassLoader || comparator.isSame(loader) || loader.equals(scl) && isNotEarWebApp) {
+                                classes.add(clazz);
+                            }
+                        }
+                    }
+                }
             }
 
             if (startupObject.getBeanContexts() != null) { // ensure ejbs are in managed beans otherwise they will not be deployed in CDI
@@ -193,29 +237,28 @@ public class CdiScanner implements Scann
         }
     }
 
+    // TODO: reusing our finder would be a good idea to avoid reflection we already did!
+    private boolean isBean(final Class clazz) {
+        try {
+            for (final Annotation a : clazz.getAnnotations()) {
+                final Class<? extends Annotation> annotationType = a.annotationType();
+                if (webBeansContext.getBeanManagerImpl().isScope(annotationType)
+                        || webBeansContext.getBeanManagerImpl().isStereotype(annotationType)) {
+                    return true;
+                }
+            }
+        }
+        catch (final Throwable e) {
+            // no-op
+        }
+        return false;
+    }
+
     private static boolean shouldThrowCouldNotLoadException(final StartupObject startupObject) {
         final AppInfo appInfo = startupObject.getAppInfo();
         return appInfo.webAppAlone || appInfo.webApps.size() == 0 || startupObject.isFromWebApp();
     }
 
-    private void process(final ClassLoader classLoader, final Iterator<String> it, final StartupObject startupObject, final ClassLoaderComparator comparator, final ClassLoader scl, final boolean filterByClassLoader) {
-        final String className = it.next();
-        final Class clazz = load(className, classLoader);
-        if (clazz == null) {
-            return;
-        }
-
-        final ClassLoader cl = clazz.getClassLoader();
-        // 1. this classloader is the good one
-        // 2. the classloader is the appclassloader one and we are in the ear parent
-        if (!filterByClassLoader
-            || comparator.isSame(cl) || cl.equals(scl) && startupObject.getWebContext() == null) {
-            classes.add(clazz);
-        } else {
-            it.remove();
-        }
-    }
-
     private boolean addErrors(final StringBuilder errors, final String msg, final List<String> list) {
         if (!list.isEmpty()) {
             errors.append("[ ").append(msg).append(" --> ");

Added: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBBeanInfoService.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBBeanInfoService.java?rev=1617111&view=auto
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBBeanInfoService.java (added)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBBeanInfoService.java Sun Aug 10 14:43:36 2014
@@ -0,0 +1,134 @@
+/*
+ * 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.openejb.cdi;
+
+import org.apache.openejb.assembler.ExclusionInfo;
+import org.apache.openejb.assembler.classic.BeansInfo;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.webbeans.exception.WebBeansConfigurationException;
+import org.apache.webbeans.spi.BeanArchiveService;
+import org.apache.webbeans.xml.DefaultBeanArchiveInformation;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+public class OpenEJBBeanInfoService implements BeanArchiveService {
+    private Map<URL, BeanArchiveInformation> beanArchiveInfo = new HashMap<>();
+
+    public void register(final URL url, final BeansInfo info, final ClassLoader loader) {
+        final DefaultBeanArchiveInformation information = createBeanArchiveInformation(info, loader);
+        beanArchiveInfo.put(url, information);
+    }
+
+    public Map<URL, BeanArchiveInformation> getBeanArchiveInfo() {
+        return beanArchiveInfo;
+    }
+
+    public DefaultBeanArchiveInformation createBeanArchiveInformation(BeansInfo info, ClassLoader loader) {
+        if (info.version != null && !"1.0".equals(info.version) && info.discoveryMode == null) {
+            throw new WebBeansConfigurationException("beans.xml with version 1.1 and higher must declare a bean-discovery-mode!");
+        }
+
+        final DefaultBeanArchiveInformation information = new DefaultBeanArchiveInformation();
+        information.setVersion(info.version);
+        information.setBeanDiscoveryMode(info.discoveryMode == null ? BeanDiscoveryMode.ANNOTATED : BeanDiscoveryMode.valueOf(info.discoveryMode.trim().toUpperCase(Locale.ENGLISH)));
+        information.setDecorators(info.decorators);
+        information.setInterceptors(info.interceptors);
+        information.getAlternativeClasses().addAll(info.alternativeClasses);
+        information.getAlternativeStereotypes().addAll(info.alternativeStereotypes);
+
+        for (final Map.Entry<String, ExclusionInfo> exclusionInfo : info.excludes.entrySet()) {
+            final ExclusionInfo value = exclusionInfo.getValue();
+            boolean skip = false;
+            for (final String n : value.availableClasses) {
+                if (!isClassAvailable(loader, n)) {
+                    skip = true;
+                    break;
+                }
+            }
+            if (!skip) {
+                for (final String n : value.notAvailableClasses) {
+                    if (isClassAvailable(loader, n)) {
+                        skip = true;
+                        break;
+                    }
+                }
+            }
+            if (!skip) {
+                for (final String n : value.systemPropertiesPresence) {
+                    // our system instance is more powerful here
+                    if (SystemInstance.get().getProperty(n) == null) {
+                        skip = true;
+                        break;
+                    }
+                }
+            }
+            if (!skip) {
+                for (final String n : value.systemProperties.stringPropertyNames()) {
+                    // our system instance is more powerful here
+                    if (!value.systemProperties.getProperty(n).equals(SystemInstance.get().getProperty(n))) {
+                        skip = true;
+                        break;
+                    }
+                }
+            }
+            if (skip) {
+                continue;
+            }
+
+            final String name = exclusionInfo.getKey();
+            if (name.endsWith(".*")) {
+                information.addClassExclude(name.substring(0, name.length() - 2));
+            }
+            else if (name.endsWith(".**")) {
+                information.addPackageExclude(name.substring(0, name.length() - 3));
+            }
+            else {
+                information.addClassExclude(name);
+            }
+        }
+        return information;
+    }
+
+    private static boolean isClassAvailable(final ClassLoader loader, final String name) {
+        try {
+            loader.loadClass(name);
+            return true;
+        } catch (final Throwable e) {
+            return false;
+        }
+    }
+
+    @Override
+    public BeanArchiveInformation getBeanArchiveInformation(final URL beanArchiveUrl) {
+        return beanArchiveInfo.get(beanArchiveUrl);
+    }
+
+    @Override
+    public Set<URL> getRegisteredBeanArchives() {
+        return Collections.emptySet(); // avoid to register twice decorators/interceptors/stereotypes/...
+    }
+
+    @Override
+    public void release() {
+        // no-op
+    }
+}

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/OpenEJBLifecycle.java Sun Aug 10 14:43:36 2014
@@ -165,9 +165,12 @@ public class OpenEJBLifecycle implements
 
                 if (scannerService instanceof CdiScanner) {
                     final CdiScanner service = (CdiScanner) scannerService;
+                    service.setContext(webBeansContext);
                     service.init(startupObject);
                 } else {
-                    new CdiScanner().init(startupObject);
+                    final CdiScanner cdiScanner = new CdiScanner();
+                    ((CdiScanner) scannerService).setContext(webBeansContext);
+                    cdiScanner.init(startupObject);
                 }
 
                 //Scan

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java Sun Aug 10 14:43:36 2014
@@ -33,6 +33,7 @@ import org.apache.webbeans.config.WebBea
 import org.apache.webbeans.container.BeanManagerImpl;
 import org.apache.webbeans.intercept.ApplicationScopedBeanInterceptorHandler;
 import org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler;
+import org.apache.webbeans.spi.BeanArchiveService;
 import org.apache.webbeans.spi.ContainerLifecycle;
 import org.apache.webbeans.spi.ContextsService;
 import org.apache.webbeans.spi.ConversationService;
@@ -118,6 +119,7 @@ public class ThreadSingletonServiceImpl 
 
         properties.putAll(appContext.getProperties());
 
+        services.put(BeanArchiveService.class, new OpenEJBBeanInfoService());
         services.put(AppContext.class, appContext);
         services.put(JNDIService.class, new OpenEJBJndiService());
         services.put(TransactionService.class, new OpenEJBTransactionService());

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java Sun Aug 10 14:43:36 2014
@@ -125,6 +125,7 @@ import org.apache.openejb.util.LogCatego
 import org.apache.openejb.util.Logger;
 import org.apache.openejb.util.SuperProperties;
 import org.apache.openejb.util.proxy.DynamicProxyImplFactory;
+import org.apache.webbeans.corespi.scanner.xbean.BeanArchiveFilter;
 import org.apache.xbean.finder.Annotated;
 import org.apache.xbean.finder.AnnotationFinder;
 import org.apache.xbean.finder.IAnnotationFinder;
@@ -238,6 +239,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -1290,47 +1292,13 @@ public class AnnotationDeployer implemen
             final IAnnotationFinder finder = ejbModule.getFinder();
 
 
-            final List<String> managedClasses;
+            final Map<URL, List<String>> managedClasses;
             {
                 final Beans beans = ejbModule.getBeans();
 
                 if (beans != null) {
                     managedClasses = beans.getManagedClasses();
-                    final List<String> classNames = getBeanClasses(finder);
-
-                    final Set<String> notLoadedClasses = new TreeSet<String>();
-                    for (final String rawClassName : classNames) {
-                        final String className = realClassName(rawClassName);
-                        try {
-                            final ClassLoader loader = ejbModule.getClassLoader();
-                            final Class<?> clazz = loader.loadClass(className);
-
-                            // The following can NOT be beans in CDI
-
-                            // 1. Non-static inner classes
-                            if (clazz.getEnclosingClass() != null && !Modifier.isStatic(clazz.getModifiers())) {
-                                continue;
-                            }
-//
-//                            // 2. Abstract classes (unless they are an @Decorator)
-//                            if (Modifier.isAbstract(clazz.getModifiers()) && !clazz.isAnnotationPresent(javax.decorator.Decorator.class)) continue;
-//
-                            // 3. Implementations of Extension
-                            if (Extension.class.isAssignableFrom(clazz)) {
-                                continue;
-                            }
-
-                            managedClasses.add(className);
-                        } catch (final ClassNotFoundException e) {
-                            notLoadedClasses.add(rawClassName);
-                        } catch (final NoClassDefFoundError e) {
-                            // no-op
-                        }
-                    }
-
-                    if (!notLoadedClasses.isEmpty()) { // don't log in info or warning since not 100% JavaEE/CDI libs will break the whole logs
-                        logger.debug("Some classes can't be loaded: " + Join.join("\n", notLoadedClasses.toArray(new String[notLoadedClasses.size()])));
-                    }
+                    managedClasses.putAll(getBeanClasses(finder));
 
                     // passing jar location to be able to manage maven classes/test-classes which have the same moduleId
                     String id = ejbModule.getModuleId();
@@ -1345,12 +1313,10 @@ public class AnnotationDeployer implemen
                     managedBean.setTransactionType(TransactionType.BEAN);
                     ejbModule.getEjbJar().addEnterpriseBean(managedBean);
                 } else {
-                    managedClasses = new ArrayList<String>();
+                    managedClasses = new HashMap<>();
                 }
             }
 
-            final Set<Class<?>> specializingClasses = new HashSet<Class<?>>();
-
 
             // Fill in default sessionType for xml declared EJBs
             for (final EnterpriseBean bean : ejbModule.getEjbJar().getEnterpriseBeans()) {
@@ -1393,11 +1359,6 @@ public class AnnotationDeployer implemen
 
             final EjbJar ejbJar = ejbModule.getEjbJar();
             for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(Singleton.class)) {
-
-                if (beanClass.isAnnotationPresent(Specializes.class)) {
-                    specializingClasses.add(beanClass.get());
-                }
-
                 final Singleton singleton = beanClass.getAnnotation(Singleton.class);
                 final String ejbName = getEjbName(singleton, beanClass.get());
 
@@ -1425,11 +1386,6 @@ public class AnnotationDeployer implemen
             }
 
             for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(Stateless.class)) {
-
-                if (beanClass.isAnnotationPresent(Specializes.class)) {
-                    specializingClasses.add(beanClass.get());
-                }
-
                 final Stateless stateless = beanClass.getAnnotation(Stateless.class);
                 final String ejbName = getEjbName(stateless, beanClass.get());
 
@@ -1464,11 +1420,6 @@ public class AnnotationDeployer implemen
             // Anyway.. the qualifiers aren't getting inherited, so we need to fix that
 
             for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(Stateful.class)) {
-
-                if (beanClass.isAnnotationPresent(Specializes.class)) {
-                    specializingClasses.add(beanClass.get());
-                }
-
                 final Stateful stateful = beanClass.getAnnotation(Stateful.class);
                 final String ejbName = getEjbName(stateful, beanClass.get());
 
@@ -1499,11 +1450,6 @@ public class AnnotationDeployer implemen
             }
 
             for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(ManagedBean.class)) {
-
-                if (beanClass.isAnnotationPresent(Specializes.class)) {
-                    specializingClasses.add(beanClass.get());
-                }
-
                 final ManagedBean managed = beanClass.getAnnotation(ManagedBean.class);
                 final String ejbName = getEjbName(managed, beanClass.get());
 
@@ -1534,11 +1480,6 @@ public class AnnotationDeployer implemen
             }
 
             for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(MessageDriven.class)) {
-
-                if (beanClass.isAnnotationPresent(Specializes.class)) {
-                    specializingClasses.add(beanClass.get());
-                }
-
                 final MessageDriven mdb = beanClass.getAnnotation(MessageDriven.class);
                 final String ejbName = getEjbName(mdb, beanClass.get());
 
@@ -1557,33 +1498,6 @@ public class AnnotationDeployer implemen
                 LegacyProcessor.process(beanClass.get(), messageBean);
             }
 
-            /*
-            for (Class<?> specializingClass : sortClassesParentFirst(new ArrayList<Class<?>>(specializingClasses))) {
-
-                final Class<?> parent = specializingClass.getSuperclass();
-
-                if (parent == null || parent.equals(Object.class)) {
-                    ejbModule.getValidation().fail(specializingClass.getSimpleName(), "specializes.extendsNothing", specializingClass.getName());
-                }
-
-                boolean found = false;
-
-                for (EnterpriseBean enterpriseBean : ejbJar.getEnterpriseBeans()) {
-
-                    final String ejbClass = enterpriseBean.getEjbClass();
-
-                    if (ejbClass != null && ejbClass.equals(parent.getName())) {
-                        enterpriseBean.setEjbClass(specializingClass.getName());
-                        found = true;
-                    }
-                }
-
-                if (!found) {
-                    ejbModule.getValidation().fail(specializingClass.getSimpleName(), "specializes.extendsSimpleBean", specializingClass.getName());
-                }
-            }
-            */
-
             AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor();
             if (assemblyDescriptor == null) {
                 assemblyDescriptor = new AssemblyDescriptor();
@@ -1707,7 +1621,7 @@ public class AnnotationDeployer implemen
             return name != null && name.length() != 0;
         }
 
-        private List<String> getBeanClasses(final IAnnotationFinder finder) {
+        private Map<URL, List<String>> getBeanClasses(final IAnnotationFinder finder) {
 
             //  What we're hoping in this method is to get lucky and find
             //  that our 'finder' instances is an AnnotationFinder that is
@@ -1718,43 +1632,47 @@ public class AnnotationDeployer implemen
             //  more classes than actually apply to CDI.  This can "pollute"
             //  the CDI class space and break injection points
 
+            /*
             if (!(finder instanceof FinderFactory.ModuleLimitedFinder)) {
                 return finder.getAnnotatedClassNames();
             }
 
-            final IAnnotationFinder delegate = ((FinderFactory.ModuleLimitedFinder) finder).getDelegate();
             if (!(delegate instanceof AnnotationFinder)) {
                 return finder.getAnnotatedClassNames();
             }
+            */
 
+            // force cast otherwise we would be broken
+            final IAnnotationFinder delegate = ((FinderFactory.ModuleLimitedFinder) finder).getDelegate();
             final AnnotationFinder annotationFinder = (AnnotationFinder) delegate;
 
             final Archive archive = annotationFinder.getArchive();
-            if (!(archive instanceof WebappAggregatedArchive)) {
-                return finder.getAnnotatedClassNames();
-            }
+            final Map<URL, List<String>> classes = new HashMap<>();
 
-            final List<String> classes = new ArrayList<String>();
+            if (!WebappAggregatedArchive.class.isInstance(archive)) {
+                classes.put(null, annotationFinder.getAnnotatedClassNames());
+                return classes;
+            }
 
             final WebappAggregatedArchive aggregatedArchive = (WebappAggregatedArchive) archive;
             final Map<URL, List<String>> map = aggregatedArchive.getClassesMap();
 
             for (final Map.Entry<URL, List<String>> entry : map.entrySet()) {
-
-                if (hasBeansXml(entry.getKey())) {
-                    classes.addAll(entry.getValue());
+                final URL beansXml = hasBeansXml(entry.getKey());
+                if (beansXml != null) {
+                    classes.put(beansXml, entry.getValue());
                 }
             }
 
             return classes;
         }
 
-        public static boolean hasBeansXml(final URL url) {
+        public static URL hasBeansXml(final URL url) {
             if (url.getPath().endsWith("WEB-INF/classes/")) {
-                return true;
+                return url;
             }
             if (url.getPath().endsWith("!/META-INF/beans.xml")) {
-                return true;
+                return url;
             }
             try {
                 final URLClassLoader loader = new URLClassLoader(new URL[]{url}, new EmptyResourcesClassLoader());
@@ -1766,14 +1684,15 @@ public class AnnotationDeployer implemen
                 };
 
                 for (final String path : paths) {
-                    if (loader.findResource(path) != null) {
-                        return true;
+                    final URL resource = loader.findResource(path);
+                    if (resource != null) {
+                        return resource;
                     }
                 }
             } catch (final Exception e) {
                 // no-op
             }
-            return false;
+            return null;
         }
 
         private String getEjbName(final MessageDriven mdb, final Class<?> beanClass) {

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/EjbJarInfoBuilder.java Sun Aug 10 14:43:36 2014
@@ -18,6 +18,7 @@
 package org.apache.openejb.config;
 
 import org.apache.openejb.OpenEJBException;
+import org.apache.openejb.assembler.ExclusionInfo;
 import org.apache.openejb.assembler.classic.ApplicationExceptionInfo;
 import org.apache.openejb.assembler.classic.BeansInfo;
 import org.apache.openejb.assembler.classic.CallbackInfo;
@@ -50,6 +51,7 @@ import org.apache.openejb.jee.Activation
 import org.apache.openejb.jee.ActivationConfigProperty;
 import org.apache.openejb.jee.ApplicationException;
 import org.apache.openejb.jee.AsyncMethod;
+import org.apache.openejb.jee.Beans;
 import org.apache.openejb.jee.CallbackMethod;
 import org.apache.openejb.jee.CmpField;
 import org.apache.openejb.jee.CmpVersion;
@@ -102,6 +104,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -216,19 +219,44 @@ public class EjbJarInfoBuilder {
             initRelationships(jar, infos);
         }
 
-        if (jar.getBeans() != null) {
+        final Beans beans = jar.getBeans();
+        if (beans != null) {
             ejbJar.beans = new BeansInfo();
+            ejbJar.beans.version = beans.getVersion();
+            ejbJar.beans.discoveryMode = beans.getBeanDiscoveryMode();
+            if (beans.getScan() != null) {
+                for (final Beans.Scan.Exclude exclude : beans.getScan().getExclude()) {
+                    final ExclusionInfo exclusionInfo = new ExclusionInfo();
+                    for (final Object config : exclude.getIfClassAvailableOrIfClassNotAvailableOrIfSystemProperty()) {
+                        if (Beans.Scan.Exclude.IfAvailableClassCondition.class.isInstance(config)) {
+                            exclusionInfo.availableClasses.add(Beans.Scan.Exclude.ClassCondition.class.cast(config).getName());
+                        } else if (Beans.Scan.Exclude.IfNotAvailableClassCondition.class.isInstance(config)) {
+                            exclusionInfo.notAvailableClasses.add(Beans.Scan.Exclude.ClassCondition.class.cast(config).getName());
+                        } else if (Beans.Scan.Exclude.IfSystemProperty.class.isInstance(config)) {
+                            final Beans.Scan.Exclude.IfSystemProperty systemProperty = Beans.Scan.Exclude.IfSystemProperty.class.cast(config);
+                            if (systemProperty.getValue() == null) {
+                                exclusionInfo.systemPropertiesPresence.add(systemProperty.getName());
+                            } else {
+                                exclusionInfo.systemProperties.put(systemProperty.getName(), systemProperty.getValue());
+                            }
+                        } else {
+                            throw new IllegalArgumentException("Not supported: " + config);
+                        }
+                    }
+                    ejbJar.beans.excludes.put(exclude.getName(), exclusionInfo);
+                }
+            }
 
-            ejbJar.beans.interceptors.addAll(jar.getBeans().getInterceptors());
-            ejbJar.beans.decorators.addAll(jar.getBeans().getDecorators());
-            ejbJar.beans.alternativeClasses.addAll(jar.getBeans().getAlternativeClasses());
-            ejbJar.beans.alternativeStereotypes.addAll(jar.getBeans().getAlternativeStereotypes());
-            ejbJar.beans.managedClasses.addAll(jar.getBeans().getManagedClasses());
-
-            ejbJar.beans.duplicatedAlternativeClasses.addAll(jar.getBeans().getDuplicatedAlternatives().getClasses());
-            ejbJar.beans.duplicatedAlternativeStereotypes.addAll(jar.getBeans().getDuplicatedAlternatives().getStereotypes());
-            ejbJar.beans.duplicatedInterceptors.addAll(jar.getBeans().getDuplicatedInterceptors());
-            ejbJar.beans.duplicatedDecorators.addAll(jar.getBeans().getDuplicatedDecorators());
+            ejbJar.beans.interceptors.addAll(beans.getInterceptors());
+            ejbJar.beans.decorators.addAll(beans.getDecorators());
+            ejbJar.beans.alternativeClasses.addAll(beans.getAlternativeClasses());
+            ejbJar.beans.alternativeStereotypes.addAll(beans.getAlternativeStereotypes());
+            ejbJar.beans.managedClasses.putAll(beans.getManagedClasses());
+
+            ejbJar.beans.duplicatedAlternativeClasses.addAll(beans.getDuplicatedAlternatives().getClasses());
+            ejbJar.beans.duplicatedAlternativeStereotypes.addAll(beans.getDuplicatedAlternatives().getStereotypes());
+            ejbJar.beans.duplicatedInterceptors.addAll(beans.getDuplicatedInterceptors());
+            ejbJar.beans.duplicatedDecorators.addAll(beans.getDuplicatedDecorators());
         }
 
         return ejbJar;

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/ReadDescriptors.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/ReadDescriptors.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/ReadDescriptors.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/config/ReadDescriptors.java Sun Aug 10 14:43:36 2014
@@ -609,8 +609,10 @@ public class ReadDescriptors implements 
     public static Beans readBeans(final InputStream inputStream) throws OpenEJBException {
         try {
             final String content = IO.slurp(inputStream);
-            if (isEmptyBeansXml(new ByteArrayInputStream(content.getBytes()))) {
-                return new Beans();
+            if (content.length() == 0) { // otherwise we want to read <beans /> attributes
+                final Beans beans = new Beans();
+                beans.setBeanDiscoveryMode("ALL"); // backward compatibility
+                return beans;
             }
             return (Beans) JaxbJavaee.unmarshalJavaee(Beans.class, new ByteArrayInputStream(content.getBytes()));
         } catch (final SAXException e) {

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java?rev=1617111&r1=1617110&r2=1617111&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java Sun Aug 10 14:43:36 2014
@@ -636,11 +636,17 @@ public final class ApplicationComposers 
             final Beans beans = ejb.getBeans();
             if (beans != null && ejb.getEjbJar() != null) {
                 for (final EnterpriseBean bean : ejb.getEjbJar().getEnterpriseBeans()) {
-                    if (beans.getManagedClasses().contains(bean.getEjbClass())) {
-                        continue;
-                    }
+                    boolean found = false;
+                    for (final List<String> mc : beans.getManagedClasses().values()) {
+                        if (mc.contains(bean.getEjbClass())) {
+                            found = true;
+                            break;
+                        }
 
-                    beans.addManagedClass(bean.getEjbClass());
+                    }
+                    if (!found) {
+                        beans.addManagedClass(bean.getEjbClass());
+                    }
                 }
             }
         }

Added: tomee/tomee/trunk/container/openejb-jee/src/main/java/org/apache/openejb/jee/Scan.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-jee/src/main/java/org/apache/openejb/jee/Scan.java?rev=1617111&view=auto
==============================================================================
--- tomee/tomee/trunk/container/openejb-jee/src/main/java/org/apache/openejb/jee/Scan.java (added)
+++ tomee/tomee/trunk/container/openejb-jee/src/main/java/org/apache/openejb/jee/Scan.java Sun Aug 10 14:43:36 2014
@@ -0,0 +1,429 @@
+//
+// Ce fichier a été généré par l'implémentation de référence JavaTM Architecture for XML Binding (JAXB), v2.2.7 
+// Voir <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Toute modification apportée à ce fichier sera perdue lors de la recompilation du schéma source. 
+// Généré le : 2014.08.10 à 01:54:19 PM CEST 
+//
+
+
+package org.apache.openejb.jee;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Classe Java pour anonymous complex type.
+ * 
+ * <p>Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
+ * 
+ * <pre>
+ * &lt;complexType>
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence maxOccurs="unbounded" minOccurs="0">
+ *         &lt;element name="exclude">
+ *           &lt;complexType>
+ *             &lt;complexContent>
+ *               &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                 &lt;choice maxOccurs="unbounded" minOccurs="0">
+ *                   &lt;element name="if-class-available">
+ *                     &lt;complexType>
+ *                       &lt;complexContent>
+ *                         &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         &lt;/restriction>
+ *                       &lt;/complexContent>
+ *                     &lt;/complexType>
+ *                   &lt;/element>
+ *                   &lt;element name="if-class-not-available">
+ *                     &lt;complexType>
+ *                       &lt;complexContent>
+ *                         &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         &lt;/restriction>
+ *                       &lt;/complexContent>
+ *                     &lt;/complexType>
+ *                   &lt;/element>
+ *                   &lt;element name="if-system-property">
+ *                     &lt;complexType>
+ *                       &lt;complexContent>
+ *                         &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *                           &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                           &lt;attribute name="value" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                         &lt;/restriction>
+ *                       &lt;/complexContent>
+ *                     &lt;/complexType>
+ *                   &lt;/element>
+ *                 &lt;/choice>
+ *                 &lt;attribute name="name" use="required">
+ *                   &lt;simpleType>
+ *                     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *                       &lt;pattern value="([a-zA-Z_$][a-zA-Z\d_$]*\.)*([a-zA-Z_$][a-zA-Z\d_$]*|\*|\*\*)"/>
+ *                     &lt;/restriction>
+ *                   &lt;/simpleType>
+ *                 &lt;/attribute>
+ *               &lt;/restriction>
+ *             &lt;/complexContent>
+ *           &lt;/complexType>
+ *         &lt;/element>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+    "exclude"
+})
+@XmlRootElement(name = "scan")
+public class Scan {
+
+    protected List<Scan.Exclude> exclude;
+
+    /**
+     * Gets the value of the exclude property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the exclude property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getExclude().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link Scan.Exclude }
+     * 
+     * 
+     */
+    public List<Scan.Exclude> getExclude() {
+        if (exclude == null) {
+            exclude = new ArrayList<Scan.Exclude>();
+        }
+        return this.exclude;
+    }
+
+
+    /**
+     * <p>Classe Java pour anonymous complex type.
+     * 
+     * <p>Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
+     * 
+     * <pre>
+     * &lt;complexType>
+     *   &lt;complexContent>
+     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *       &lt;choice maxOccurs="unbounded" minOccurs="0">
+     *         &lt;element name="if-class-available">
+     *           &lt;complexType>
+     *             &lt;complexContent>
+     *               &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               &lt;/restriction>
+     *             &lt;/complexContent>
+     *           &lt;/complexType>
+     *         &lt;/element>
+     *         &lt;element name="if-class-not-available">
+     *           &lt;complexType>
+     *             &lt;complexContent>
+     *               &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               &lt;/restriction>
+     *             &lt;/complexContent>
+     *           &lt;/complexType>
+     *         &lt;/element>
+     *         &lt;element name="if-system-property">
+     *           &lt;complexType>
+     *             &lt;complexContent>
+     *               &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+     *                 &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *                 &lt;attribute name="value" type="{http://www.w3.org/2001/XMLSchema}string" />
+     *               &lt;/restriction>
+     *             &lt;/complexContent>
+     *           &lt;/complexType>
+     *         &lt;/element>
+     *       &lt;/choice>
+     *       &lt;attribute name="name" use="required">
+     *         &lt;simpleType>
+     *           &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string">
+     *             &lt;pattern value="([a-zA-Z_$][a-zA-Z\d_$]*\.)*([a-zA-Z_$][a-zA-Z\d_$]*|\*|\*\*)"/>
+     *           &lt;/restriction>
+     *         &lt;/simpleType>
+     *       &lt;/attribute>
+     *     &lt;/restriction>
+     *   &lt;/complexContent>
+     * &lt;/complexType>
+     * </pre>
+     * 
+     * 
+     */
+    @XmlAccessorType(XmlAccessType.FIELD)
+    @XmlType(name = "", propOrder = {
+        "ifClassAvailableOrIfClassNotAvailableOrIfSystemProperty"
+    })
+    public static class Exclude {
+
+        @XmlElements({
+            @XmlElement(name = "if-class-available", type = Scan.Exclude.IfClassAvailable.class),
+            @XmlElement(name = "if-class-not-available", type = Scan.Exclude.IfClassNotAvailable.class),
+            @XmlElement(name = "if-system-property", type = Scan.Exclude.IfSystemProperty.class)
+        })
+        protected List<Object> ifClassAvailableOrIfClassNotAvailableOrIfSystemProperty;
+        @XmlAttribute(name = "name", required = true)
+        protected String name;
+
+        /**
+         * Gets the value of the ifClassAvailableOrIfClassNotAvailableOrIfSystemProperty property.
+         * 
+         * <p>
+         * This accessor method returns a reference to the live list,
+         * not a snapshot. Therefore any modification you make to the
+         * returned list will be present inside the JAXB object.
+         * This is why there is not a <CODE>set</CODE> method for the ifClassAvailableOrIfClassNotAvailableOrIfSystemProperty property.
+         * 
+         * <p>
+         * For example, to add a new item, do as follows:
+         * <pre>
+         *    getIfClassAvailableOrIfClassNotAvailableOrIfSystemProperty().add(newItem);
+         * </pre>
+         * 
+         * 
+         * <p>
+         * Objects of the following type(s) are allowed in the list
+         * {@link Scan.Exclude.IfClassAvailable }
+         * {@link Scan.Exclude.IfClassNotAvailable }
+         * {@link Scan.Exclude.IfSystemProperty }
+         * 
+         * 
+         */
+        public List<Object> getIfClassAvailableOrIfClassNotAvailableOrIfSystemProperty() {
+            if (ifClassAvailableOrIfClassNotAvailableOrIfSystemProperty == null) {
+                ifClassAvailableOrIfClassNotAvailableOrIfSystemProperty = new ArrayList<Object>();
+            }
+            return this.ifClassAvailableOrIfClassNotAvailableOrIfSystemProperty;
+        }
+
+        /**
+         * Obtient la valeur de la propriété name.
+         * 
+         * @return
+         *     possible object is
+         *     {@link String }
+         *     
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * Définit la valeur de la propriété name.
+         * 
+         * @param value
+         *     allowed object is
+         *     {@link String }
+         *     
+         */
+        public void setName(String value) {
+            this.name = value;
+        }
+
+
+        /**
+         * <p>Classe Java pour anonymous complex type.
+         * 
+         * <p>Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
+         * 
+         * <pre>
+         * &lt;complexType>
+         *   &lt;complexContent>
+         *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     &lt;/restriction>
+         *   &lt;/complexContent>
+         * &lt;/complexType>
+         * </pre>
+         * 
+         * 
+         */
+        @XmlAccessorType(XmlAccessType.FIELD)
+        @XmlType(name = "")
+        public static class IfClassAvailable {
+
+            @XmlAttribute(name = "name", required = true)
+            protected String name;
+
+            /**
+             * Obtient la valeur de la propriété name.
+             * 
+             * @return
+             *     possible object is
+             *     {@link String }
+             *     
+             */
+            public String getName() {
+                return name;
+            }
+
+            /**
+             * Définit la valeur de la propriété name.
+             * 
+             * @param value
+             *     allowed object is
+             *     {@link String }
+             *     
+             */
+            public void setName(String value) {
+                this.name = value;
+            }
+
+        }
+
+
+        /**
+         * <p>Classe Java pour anonymous complex type.
+         * 
+         * <p>Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
+         * 
+         * <pre>
+         * &lt;complexType>
+         *   &lt;complexContent>
+         *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     &lt;/restriction>
+         *   &lt;/complexContent>
+         * &lt;/complexType>
+         * </pre>
+         * 
+         * 
+         */
+        @XmlAccessorType(XmlAccessType.FIELD)
+        @XmlType(name = "")
+        public static class IfClassNotAvailable {
+
+            @XmlAttribute(name = "name", required = true)
+            protected String name;
+
+            /**
+             * Obtient la valeur de la propriété name.
+             * 
+             * @return
+             *     possible object is
+             *     {@link String }
+             *     
+             */
+            public String getName() {
+                return name;
+            }
+
+            /**
+             * Définit la valeur de la propriété name.
+             * 
+             * @param value
+             *     allowed object is
+             *     {@link String }
+             *     
+             */
+            public void setName(String value) {
+                this.name = value;
+            }
+
+        }
+
+
+        /**
+         * <p>Classe Java pour anonymous complex type.
+         * 
+         * <p>Le fragment de schéma suivant indique le contenu attendu figurant dans cette classe.
+         * 
+         * <pre>
+         * &lt;complexType>
+         *   &lt;complexContent>
+         *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+         *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *       &lt;attribute name="value" type="{http://www.w3.org/2001/XMLSchema}string" />
+         *     &lt;/restriction>
+         *   &lt;/complexContent>
+         * &lt;/complexType>
+         * </pre>
+         * 
+         * 
+         */
+        @XmlAccessorType(XmlAccessType.FIELD)
+        @XmlType(name = "")
+        public static class IfSystemProperty {
+
+            @XmlAttribute(name = "name", required = true)
+            protected String name;
+            @XmlAttribute(name = "value")
+            protected String value;
+
+            /**
+             * Obtient la valeur de la propriété name.
+             * 
+             * @return
+             *     possible object is
+             *     {@link String }
+             *     
+             */
+            public String getName() {
+                return name;
+            }
+
+            /**
+             * Définit la valeur de la propriété name.
+             * 
+             * @param value
+             *     allowed object is
+             *     {@link String }
+             *     
+             */
+            public void setName(String value) {
+                this.name = value;
+            }
+
+            /**
+             * Obtient la valeur de la propriété value.
+             * 
+             * @return
+             *     possible object is
+             *     {@link String }
+             *     
+             */
+            public String getValue() {
+                return value;
+            }
+
+            /**
+             * Définit la valeur de la propriété value.
+             * 
+             * @param value
+             *     allowed object is
+             *     {@link String }
+             *     
+             */
+            public void setValue(String value) {
+                this.value = value;
+            }
+
+        }
+
+    }
+
+}