diff --git a/enterprise/j2ee.api.ejbmodule/nbproject/project.xml b/enterprise/j2ee.api.ejbmodule/nbproject/project.xml
index 67806c00d601..32419ba3813d 100644
--- a/enterprise/j2ee.api.ejbmodule/nbproject/project.xml
+++ b/enterprise/j2ee.api.ejbmodule/nbproject/project.xml
@@ -247,6 +247,7 @@
org.netbeans.modules.maven.jaxws
org.netbeans.modules.profiler.j2ee
org.netbeans.modules.web.beans
+ org.netbeans.modules.jakarta.web.beans
org.netbeans.modules.web.project
org.netbeans.modules.websvc.core
org.netbeans.modules.websvc.dev
diff --git a/enterprise/j2ee.common/nbproject/project.xml b/enterprise/j2ee.common/nbproject/project.xml
index 9c5939c006ff..7ce39afc5dc6 100644
--- a/enterprise/j2ee.common/nbproject/project.xml
+++ b/enterprise/j2ee.common/nbproject/project.xml
@@ -522,6 +522,7 @@
org.netbeans.modules.visualweb.dataconnectivity
org.netbeans.modules.visualweb.project.jsf
org.netbeans.modules.web.beans
+ org.netbeans.modules.jakarta.web.beans
org.netbeans.modules.web.core
org.netbeans.modules.web.freeform
org.netbeans.modules.web.jsf
diff --git a/enterprise/jakarta.web.beans/build.xml b/enterprise/jakarta.web.beans/build.xml
new file mode 100644
index 000000000000..bb0563e052d1
--- /dev/null
+++ b/enterprise/jakarta.web.beans/build.xml
@@ -0,0 +1,25 @@
+
+
+
+ Builds, tests, and runs the project org.netbeans.modules.jakarta.web.beans
+
+
diff --git a/enterprise/jakarta.web.beans/licenseinfo.xml b/enterprise/jakarta.web.beans/licenseinfo.xml
new file mode 100644
index 000000000000..fb786cf0fc7b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/licenseinfo.xml
@@ -0,0 +1,39 @@
+
+
+
+
+ src/org/netbeans/modules/jakarta/web/beans/resources/delegate.png
+ src/org/netbeans/modules/jakarta/web/beans/resources/injection_point.png
+ src/org/netbeans/modules/jakarta/web/beans/resources/event.png
+ src/org/netbeans/modules/jakarta/web/beans/resources/observer.png
+
+
+
+
+ src/org/netbeans/modules/jakarta/web/beans/resources/Interceptor.template
+ src/org/netbeans/modules/jakarta/web/beans/resources/Qualifier.template
+ src/org/netbeans/modules/jakarta/web/beans/resources/Scope.template
+ src/org/netbeans/modules/jakarta/web/beans/resources/Stereotype.template
+
+
+
+
diff --git a/enterprise/jakarta.web.beans/manifest.mf b/enterprise/jakarta.web.beans/manifest.mf
new file mode 100644
index 000000000000..3a8ae23a8cb9
--- /dev/null
+++ b/enterprise/jakarta.web.beans/manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.modules.jakarta.web.beans/1
+OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jakarta/web/beans/resources/Bundle.properties
+OpenIDE-Module-Layer: org/netbeans/modules/jakarta/web/beans/resources/layer.xml
+OpenIDE-Module-Specification-Version: 2.38
+AutoUpdate-Show-In-Client: false
diff --git a/enterprise/jakarta.web.beans/nbproject/org-netbeans-modules-jakarta-web-beans.sig b/enterprise/jakarta.web.beans/nbproject/org-netbeans-modules-jakarta-web-beans.sig
new file mode 100644
index 000000000000..329df3b5bcee
--- /dev/null
+++ b/enterprise/jakarta.web.beans/nbproject/org-netbeans-modules-jakarta-web-beans.sig
@@ -0,0 +1,539 @@
+#Signature file v4.1
+#Version 2.38
+
+CLSS public java.beans.FeatureDescriptor
+cons public init()
+meth public boolean isExpert()
+meth public boolean isHidden()
+meth public boolean isPreferred()
+meth public java.lang.Object getValue(java.lang.String)
+meth public java.lang.String getDisplayName()
+meth public java.lang.String getName()
+meth public java.lang.String getShortDescription()
+meth public java.lang.String toString()
+meth public java.util.Enumeration attributeNames()
+meth public void setDisplayName(java.lang.String)
+meth public void setExpert(boolean)
+meth public void setHidden(boolean)
+meth public void setName(java.lang.String)
+meth public void setPreferred(boolean)
+meth public void setShortDescription(java.lang.String)
+meth public void setValue(java.lang.String,java.lang.Object)
+supr java.lang.Object
+
+CLSS public abstract interface java.io.Serializable
+
+CLSS public abstract interface java.lang.Comparable<%0 extends java.lang.Object>
+meth public abstract int compareTo({java.lang.Comparable%0})
+
+CLSS public abstract java.lang.Enum<%0 extends java.lang.Enum<{java.lang.Enum%0}>>
+cons protected init(java.lang.String,int)
+intf java.io.Serializable
+intf java.lang.Comparable<{java.lang.Enum%0}>
+meth protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException
+meth protected final void finalize()
+meth public final boolean equals(java.lang.Object)
+meth public final int compareTo({java.lang.Enum%0})
+meth public final int hashCode()
+meth public final int ordinal()
+meth public final java.lang.Class<{java.lang.Enum%0}> getDeclaringClass()
+meth public final java.lang.String name()
+meth public java.lang.String toString()
+meth public static <%0 extends java.lang.Enum<{%%0}>> {%%0} valueOf(java.lang.Class<{%%0}>,java.lang.String)
+supr java.lang.Object
+
+CLSS public java.lang.Exception
+cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean)
+cons public init()
+cons public init(java.lang.String)
+cons public init(java.lang.String,java.lang.Throwable)
+cons public init(java.lang.Throwable)
+supr java.lang.Throwable
+
+CLSS public java.lang.Object
+cons public init()
+meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
+meth protected void finalize() throws java.lang.Throwable
+meth public boolean equals(java.lang.Object)
+meth public final java.lang.Class> getClass()
+meth public final void notify()
+meth public final void notifyAll()
+meth public final void wait() throws java.lang.InterruptedException
+meth public final void wait(long) throws java.lang.InterruptedException
+meth public final void wait(long,int) throws java.lang.InterruptedException
+meth public int hashCode()
+meth public java.lang.String toString()
+
+CLSS public java.lang.Throwable
+cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean)
+cons public init()
+cons public init(java.lang.String)
+cons public init(java.lang.String,java.lang.Throwable)
+cons public init(java.lang.Throwable)
+intf java.io.Serializable
+meth public final java.lang.Throwable[] getSuppressed()
+meth public final void addSuppressed(java.lang.Throwable)
+meth public java.lang.StackTraceElement[] getStackTrace()
+meth public java.lang.String getLocalizedMessage()
+meth public java.lang.String getMessage()
+meth public java.lang.String toString()
+meth public java.lang.Throwable fillInStackTrace()
+meth public java.lang.Throwable getCause()
+meth public java.lang.Throwable initCause(java.lang.Throwable)
+meth public void printStackTrace()
+meth public void printStackTrace(java.io.PrintStream)
+meth public void printStackTrace(java.io.PrintWriter)
+meth public void setStackTrace(java.lang.StackTraceElement[])
+supr java.lang.Object
+
+CLSS public org.netbeans.modules.jakarta.web.beans.BeansDataObject
+cons public init(org.openide.filesystems.FileObject,org.openide.loaders.MultiFileLoader) throws java.io.IOException
+meth protected int associateLookup()
+supr org.openide.loaders.MultiDataObject
+
+CLSS public org.netbeans.modules.jakarta.web.beans.CarCdiUtil
+cons public init(org.netbeans.api.project.Project)
+meth public java.util.Collection getBeansTargetFolder(boolean)
+supr org.netbeans.modules.jakarta.web.beans.CdiUtil
+
+CLSS public org.netbeans.modules.jakarta.web.beans.CdiProjectOpenHook
+cons public init(org.netbeans.api.project.Project)
+meth protected void projectClosed()
+meth protected void projectOpened()
+supr org.netbeans.spi.project.ui.ProjectOpenedHook
+hfds myProject
+
+CLSS public org.netbeans.modules.jakarta.web.beans.CdiUtil
+cons public init(org.netbeans.api.project.Project)
+fld public final static java.lang.String BEANS = "beans"
+fld public final static java.lang.String BEANS_XML = "beans.xml"
+fld public final static java.lang.String WEB_INF = "WEB-INF"
+meth protected org.netbeans.api.project.Project getProject()
+meth public boolean isCdi11OrLater()
+meth public boolean isCdiEnabled()
+meth public java.util.Collection getBeansTargetFolder(boolean)
+meth public org.openide.filesystems.FileObject enableCdi()
+ anno 0 org.netbeans.api.annotations.common.CheckForNull()
+meth public static boolean isCdi11OrLater(org.netbeans.api.project.Project)
+meth public static boolean isCdiEnabled(org.netbeans.api.project.Project)
+meth public static java.util.Collection getBeansTargetFolder(org.netbeans.api.project.Project,boolean)
+meth public void log(java.lang.String,java.lang.Class>,java.lang.Object[])
+meth public void log(java.lang.String,java.lang.Class>,java.lang.Object[],boolean)
+supr java.lang.Object
+hfds LOG,META_INF,myMessages,myProject
+
+CLSS public org.netbeans.modules.jakarta.web.beans.EjbCdiUtil
+cons public init(org.netbeans.api.project.Project)
+meth public java.util.Collection getBeansTargetFolder(boolean)
+supr org.netbeans.modules.jakarta.web.beans.CdiUtil
+
+CLSS public org.netbeans.modules.jakarta.web.beans.MetaModelSupport
+cons public init(org.netbeans.api.project.Project)
+meth public org.netbeans.api.java.classpath.ClassPath getClassPath(java.lang.String)
+meth public org.netbeans.modules.j2ee.metadata.model.api.MetadataModel getMetaModel()
+supr java.lang.Object
+hfds MODELS,myProject
+
+CLSS public org.netbeans.modules.jakarta.web.beans.WebBeanInjectionTargetQueryImplementation
+cons public init()
+intf org.netbeans.modules.javaee.injection.spi.InjectionTargetQueryImplementation
+meth public boolean isInjectionTarget(org.netbeans.api.java.source.CompilationController,javax.lang.model.element.TypeElement)
+meth public boolean isStaticReferenceRequired(org.netbeans.api.java.source.CompilationController,javax.lang.model.element.TypeElement)
+supr java.lang.Object
+
+CLSS public org.netbeans.modules.jakarta.web.beans.WebCdiUtil
+cons public init(org.netbeans.api.project.Project)
+meth public java.util.Collection getBeansTargetFolder(boolean)
+supr org.netbeans.modules.jakarta.web.beans.CdiUtil
+
+CLSS public abstract org.netbeans.modules.jakarta.web.beans.api.model.AbstractModelImplementation
+cons protected init(org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit)
+meth protected org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel getModel()
+meth protected org.netbeans.modules.jakarta.web.beans.model.spi.WebBeansModelProvider getProvider()
+meth public org.netbeans.modules.jakarta.web.beans.api.model.BeansModel getBeansModel()
+meth public org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit getModelUnit()
+supr java.lang.Object
+hfds myModel,myProvider,myUnit
+
+CLSS public final !enum org.netbeans.modules.jakarta.web.beans.api.model.BeanArchiveType
+fld public final static org.netbeans.modules.jakarta.web.beans.api.model.BeanArchiveType EXPLICIT
+fld public final static org.netbeans.modules.jakarta.web.beans.api.model.BeanArchiveType IMPLICIT
+fld public final static org.netbeans.modules.jakarta.web.beans.api.model.BeanArchiveType NONE
+meth public static org.netbeans.modules.jakarta.web.beans.api.model.BeanArchiveType valueOf(java.lang.String)
+meth public static org.netbeans.modules.jakarta.web.beans.api.model.BeanArchiveType[] values()
+supr java.lang.Enum
+
+CLSS public abstract interface org.netbeans.modules.jakarta.web.beans.api.model.BeansModel
+meth public abstract boolean isCdi11OrLater()
+meth public abstract java.util.LinkedHashSet getDecoratorClasses()
+meth public abstract java.util.LinkedHashSet getInterceptorClasses()
+meth public abstract java.util.Set getAlternativeClasses()
+meth public abstract java.util.Set getAlternativeStereotypes()
+meth public abstract org.netbeans.modules.jakarta.web.beans.api.model.BeanArchiveType getBeanArchiveType()
+
+CLSS public final org.netbeans.modules.jakarta.web.beans.api.model.BeansModelFactory
+meth public static org.netbeans.modules.jakarta.web.beans.api.model.BeansModel createModel(org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit)
+meth public static org.netbeans.modules.jakarta.web.beans.api.model.BeansModel getModel(org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit)
+supr java.lang.Object
+hfds MODELS
+
+CLSS public abstract interface org.netbeans.modules.jakarta.web.beans.api.model.BeansResult
+meth public abstract boolean isDisabled(javax.lang.model.element.Element)
+
+CLSS public org.netbeans.modules.jakarta.web.beans.api.model.CdiException
+cons public init(java.lang.String)
+supr java.lang.Exception
+hfds serialVersionUID
+
+CLSS public abstract interface org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+innr public abstract interface static ApplicableResult
+innr public abstract interface static Error
+innr public abstract interface static InjectableResult
+innr public abstract interface static ResolutionResult
+innr public final static !enum ResultKind
+meth public abstract javax.lang.model.element.VariableElement getVariable()
+meth public abstract javax.lang.model.type.TypeMirror getVariableType()
+meth public abstract org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind getKind()
+
+CLSS public abstract interface static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ApplicableResult
+ outer org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.BeansResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+meth public abstract java.util.Set getProductions()
+meth public abstract java.util.Set getTypeElements()
+
+CLSS public abstract interface static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$Error
+ outer org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+meth public abstract java.lang.String getMessage()
+
+CLSS public abstract interface static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$InjectableResult
+ outer org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+meth public abstract javax.lang.model.element.Element getElement()
+
+CLSS public abstract interface static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResolutionResult
+ outer org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.Result
+meth public abstract boolean hasAlternative(javax.lang.model.element.Element)
+meth public abstract boolean isAlternative(javax.lang.model.element.Element)
+
+CLSS public final static !enum org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind
+ outer org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult
+fld public final static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind DEFINITION_ERROR
+fld public final static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind INJECTABLES_RESOLVED
+fld public final static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind INJECTABLE_RESOLVED
+fld public final static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind RESOLUTION_ERROR
+meth public static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind valueOf(java.lang.String)
+meth public static org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult$ResultKind[] values()
+supr java.lang.Enum
+
+CLSS public org.netbeans.modules.jakarta.web.beans.api.model.InjectionPointDefinitionError
+cons public init(javax.lang.model.element.Element,java.lang.String)
+meth public javax.lang.model.element.Element getErrorElement()
+supr org.netbeans.modules.jakarta.web.beans.api.model.CdiException
+hfds myElement,serialVersionUID
+
+CLSS public abstract interface org.netbeans.modules.jakarta.web.beans.api.model.InterceptorsResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.BeansResult
+intf org.netbeans.modules.jakarta.web.beans.api.model.Result
+meth public abstract java.util.List getAllInterceptors()
+meth public abstract java.util.List getDeclaredInterceptors()
+meth public abstract java.util.List getResolvedInterceptors()
+meth public abstract javax.lang.model.element.Element getElement()
+
+CLSS public org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit
+meth public boolean equals(java.lang.Object)
+meth public int hashCode()
+meth public org.netbeans.api.java.classpath.ClassPath getBootPath()
+meth public org.netbeans.api.java.classpath.ClassPath getCompilePath()
+meth public org.netbeans.api.java.classpath.ClassPath getSourcePath()
+meth public org.netbeans.api.java.source.ClasspathInfo getClassPathInfo()
+meth public org.netbeans.api.project.Project getProject()
+meth public static org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit create(org.netbeans.api.java.classpath.ClassPath,org.netbeans.api.java.classpath.ClassPath,org.netbeans.api.java.classpath.ClassPath,org.netbeans.api.project.Project)
+supr java.lang.Object
+hfds myBootPath,myClassPathInfo,myCompilePath,myProject,mySourcePath
+
+CLSS public abstract interface org.netbeans.modules.jakarta.web.beans.api.model.Result
+meth public abstract java.util.List getAllStereotypes(javax.lang.model.element.Element)
+meth public abstract java.util.List getStereotypes(javax.lang.model.element.Element)
+
+CLSS public final org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel
+meth public boolean hasImplicitDefaultQualifier(javax.lang.model.element.Element)
+meth public boolean isCdi11OrLater()
+meth public boolean isDynamicInjectionPoint(javax.lang.model.element.VariableElement)
+meth public boolean isEventInjectionPoint(javax.lang.model.element.VariableElement)
+meth public boolean isInjectionPoint(javax.lang.model.element.VariableElement) throws org.netbeans.modules.jakarta.web.beans.api.model.InjectionPointDefinitionError
+meth public java.lang.String getName(javax.lang.model.element.Element)
+meth public java.lang.String getScope(javax.lang.model.element.Element) throws org.netbeans.modules.jakarta.web.beans.api.model.CdiException
+meth public java.util.Collection getInterceptorBindings(javax.lang.model.element.Element)
+meth public java.util.Collection getDecorators(javax.lang.model.element.TypeElement)
+meth public java.util.List getQualifiers(javax.lang.model.element.Element,boolean)
+meth public java.util.List getNamedElements()
+meth public java.util.List getObservers(javax.lang.model.element.VariableElement,javax.lang.model.type.DeclaredType)
+meth public java.util.List getEventInjectionPoints(javax.lang.model.element.ExecutableElement,javax.lang.model.type.DeclaredType)
+meth public javax.lang.model.element.VariableElement getObserverParameter(javax.lang.model.element.ExecutableElement)
+meth public javax.lang.model.type.TypeMirror resolveType(java.lang.String)
+meth public org.netbeans.api.java.source.CompilationController getCompilationController()
+meth public org.netbeans.modules.jakarta.web.beans.api.model.AbstractModelImplementation getModelImplementation()
+meth public org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult lookupInjectables(javax.lang.model.element.VariableElement,javax.lang.model.type.DeclaredType,java.util.concurrent.atomic.AtomicBoolean)
+meth public org.netbeans.modules.jakarta.web.beans.api.model.InterceptorsResult getInterceptors(javax.lang.model.element.Element)
+supr java.lang.Object
+hfds myImpl
+
+CLSS public final org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModelFactory
+meth public static org.netbeans.modules.j2ee.metadata.model.api.MetadataModel createMetaModel(org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit)
+meth public static org.netbeans.modules.j2ee.metadata.model.api.MetadataModel getMetaModel(org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit)
+supr java.lang.Object
+hfds MODELS
+
+CLSS public abstract interface org.netbeans.modules.javaee.injection.spi.InjectionTargetQueryImplementation
+meth public abstract boolean isInjectionTarget(org.netbeans.api.java.source.CompilationController,javax.lang.model.element.TypeElement)
+meth public abstract boolean isStaticReferenceRequired(org.netbeans.api.java.source.CompilationController,javax.lang.model.element.TypeElement)
+
+CLSS public abstract org.netbeans.spi.project.ui.ProjectOpenedHook
+cons protected init()
+meth protected abstract void projectClosed()
+meth protected abstract void projectOpened()
+supr java.lang.Object
+
+CLSS public abstract org.openide.loaders.DataObject
+cons public init(org.openide.filesystems.FileObject,org.openide.loaders.DataLoader) throws org.openide.loaders.DataObjectExistsException
+fld public final static java.lang.String PROP_COOKIE = "cookie"
+fld public final static java.lang.String PROP_FILES = "files"
+fld public final static java.lang.String PROP_HELP = "helpCtx"
+fld public final static java.lang.String PROP_MODIFIED = "modified"
+fld public final static java.lang.String PROP_NAME = "name"
+fld public final static java.lang.String PROP_PRIMARY_FILE = "primaryFile"
+fld public final static java.lang.String PROP_TEMPLATE = "template"
+fld public final static java.lang.String PROP_VALID = "valid"
+innr public abstract interface static !annotation Registration
+innr public abstract interface static !annotation Registrations
+innr public abstract interface static Container
+innr public abstract interface static Factory
+innr public final static Registry
+intf java.io.Serializable
+intf org.openide.nodes.Node$Cookie
+intf org.openide.util.HelpCtx$Provider
+intf org.openide.util.Lookup$Provider
+meth protected <%0 extends org.openide.nodes.Node$Cookie> {%%0} getCookie(org.openide.loaders.DataShadow,java.lang.Class<{%%0}>)
+meth protected abstract org.openide.filesystems.FileObject handleMove(org.openide.loaders.DataFolder) throws java.io.IOException
+meth protected abstract org.openide.filesystems.FileObject handleRename(java.lang.String) throws java.io.IOException
+meth protected abstract org.openide.loaders.DataObject handleCopy(org.openide.loaders.DataFolder) throws java.io.IOException
+meth protected abstract org.openide.loaders.DataObject handleCreateFromTemplate(org.openide.loaders.DataFolder,java.lang.String) throws java.io.IOException
+meth protected abstract void handleDelete() throws java.io.IOException
+meth protected final void firePropertyChange(java.lang.String,java.lang.Object,java.lang.Object)
+meth protected final void fireVetoableChange(java.lang.String,java.lang.Object,java.lang.Object) throws java.beans.PropertyVetoException
+meth protected final void markFiles() throws java.io.IOException
+meth protected org.openide.filesystems.FileLock takePrimaryFileLock() throws java.io.IOException
+meth protected org.openide.loaders.DataObject handleCopyRename(org.openide.loaders.DataFolder,java.lang.String,java.lang.String) throws java.io.IOException
+meth protected org.openide.loaders.DataShadow handleCreateShadow(org.openide.loaders.DataFolder) throws java.io.IOException
+meth protected org.openide.nodes.Node createNodeDelegate()
+meth protected void dispose()
+meth public <%0 extends org.openide.nodes.Node$Cookie> {%%0} getCookie(java.lang.Class<{%%0}>)
+meth public abstract boolean isCopyAllowed()
+meth public abstract boolean isDeleteAllowed()
+meth public abstract boolean isMoveAllowed()
+meth public abstract boolean isRenameAllowed()
+meth public abstract org.openide.util.HelpCtx getHelpCtx()
+meth public boolean isModified()
+meth public boolean isShadowAllowed()
+meth public final boolean isTemplate()
+meth public final boolean isValid()
+meth public final org.openide.filesystems.FileObject getPrimaryFile()
+meth public final org.openide.loaders.DataFolder getFolder()
+meth public final org.openide.loaders.DataLoader getLoader()
+meth public final org.openide.loaders.DataObject copy(org.openide.loaders.DataFolder) throws java.io.IOException
+meth public final org.openide.loaders.DataObject createFromTemplate(org.openide.loaders.DataFolder) throws java.io.IOException
+meth public final org.openide.loaders.DataObject createFromTemplate(org.openide.loaders.DataFolder,java.lang.String) throws java.io.IOException
+meth public final org.openide.loaders.DataObject createFromTemplate(org.openide.loaders.DataFolder,java.lang.String,java.util.Map) throws java.io.IOException
+meth public final org.openide.loaders.DataShadow createShadow(org.openide.loaders.DataFolder) throws java.io.IOException
+meth public final org.openide.nodes.Node getNodeDelegate()
+meth public final void delete() throws java.io.IOException
+meth public final void move(org.openide.loaders.DataFolder) throws java.io.IOException
+meth public final void rename(java.lang.String) throws java.io.IOException
+meth public final void setTemplate(boolean) throws java.io.IOException
+meth public java.lang.Object writeReplace()
+meth public java.lang.String getName()
+meth public java.lang.String toString()
+meth public java.util.Set files()
+meth public org.openide.util.Lookup getLookup()
+meth public static org.openide.loaders.DataObject find(org.openide.filesystems.FileObject) throws org.openide.loaders.DataObjectNotFoundException
+meth public static org.openide.loaders.DataObject$Registry getRegistry()
+meth public void addPropertyChangeListener(java.beans.PropertyChangeListener)
+meth public void addVetoableChangeListener(java.beans.VetoableChangeListener)
+meth public void removePropertyChangeListener(java.beans.PropertyChangeListener)
+meth public void removeVetoableChangeListener(java.beans.VetoableChangeListener)
+meth public void setModified(boolean)
+meth public void setValid(boolean) throws java.beans.PropertyVetoException
+supr java.lang.Object
+hfds BEING_CREATED,EA_ASSIGNED_LOADER,EA_ASSIGNED_LOADER_MODULE,LOCK,LOG,OBJ_LOG,PROGRESS_INFO_TL,REGISTRY_INSTANCE,changeSupport,changeSupportUpdater,item,loader,modif,modified,nodeDelegate,serialVersionUID,syncModified,synchObject,vetoableChangeSupport,warnedClasses
+hcls CreateAction,DOSavable,ModifiedRegistry,ProgressInfo,Replace
+
+CLSS public org.openide.loaders.MultiDataObject
+cons public init(org.openide.filesystems.FileObject,org.openide.loaders.MultiFileLoader) throws org.openide.loaders.DataObjectExistsException
+innr public abstract Entry
+meth protected final org.openide.loaders.MultiDataObject$Entry registerEntry(org.openide.filesystems.FileObject)
+meth protected final org.openide.nodes.CookieSet getCookieSet()
+meth protected final void addSecondaryEntry(org.openide.loaders.MultiDataObject$Entry)
+meth protected final void registerEditor(java.lang.String,boolean)
+meth protected final void removeSecondaryEntry(org.openide.loaders.MultiDataObject$Entry)
+meth protected final void setCookieSet(org.openide.nodes.CookieSet)
+ anno 0 java.lang.Deprecated()
+meth protected int associateLookup()
+meth protected org.openide.filesystems.FileLock takePrimaryFileLock() throws java.io.IOException
+meth protected org.openide.filesystems.FileObject handleMove(org.openide.loaders.DataFolder) throws java.io.IOException
+meth protected org.openide.filesystems.FileObject handleRename(java.lang.String) throws java.io.IOException
+meth protected org.openide.loaders.DataObject handleCopy(org.openide.loaders.DataFolder) throws java.io.IOException
+meth protected org.openide.loaders.DataObject handleCopyRename(org.openide.loaders.DataFolder,java.lang.String,java.lang.String) throws java.io.IOException
+meth protected org.openide.loaders.DataObject handleCreateFromTemplate(org.openide.loaders.DataFolder,java.lang.String) throws java.io.IOException
+meth protected org.openide.nodes.Node createNodeDelegate()
+meth protected void handleDelete() throws java.io.IOException
+meth public <%0 extends org.openide.nodes.Node$Cookie> {%%0} getCookie(java.lang.Class<{%%0}>)
+meth public boolean isCopyAllowed()
+meth public boolean isDeleteAllowed()
+meth public boolean isMoveAllowed()
+meth public boolean isRenameAllowed()
+meth public final java.util.Set secondaryEntries()
+meth public final org.openide.loaders.MultiDataObject$Entry findSecondaryEntry(org.openide.filesystems.FileObject)
+meth public final org.openide.loaders.MultiDataObject$Entry getPrimaryEntry()
+meth public final org.openide.loaders.MultiFileLoader getMultiFileLoader()
+meth public java.util.Set files()
+meth public org.openide.util.HelpCtx getHelpCtx()
+meth public org.openide.util.Lookup getLookup()
+supr org.openide.loaders.DataObject
+hfds ERR,RECOGNIZER,TEMPLATE_ATTRIBUTES,chLis,checked,cookieSet,cookieSetLock,delayProcessor,delayedPropFilesLock,delayedPropFilesTask,firingProcessor,later,primary,secondary,secondaryCreationLock,serialVersionUID
+hcls ChangeAndBefore,EmptyRecognizer,EntryReplace,Pair
+
+CLSS public abstract org.openide.nodes.Node
+cons protected init(org.openide.nodes.Children)
+cons protected init(org.openide.nodes.Children,org.openide.util.Lookup)
+fld public final static java.lang.String PROP_COOKIE = "cookie"
+fld public final static java.lang.String PROP_DISPLAY_NAME = "displayName"
+fld public final static java.lang.String PROP_ICON = "icon"
+fld public final static java.lang.String PROP_LEAF = "leaf"
+fld public final static java.lang.String PROP_NAME = "name"
+fld public final static java.lang.String PROP_OPENED_ICON = "openedIcon"
+fld public final static java.lang.String PROP_PARENT_NODE = "parentNode"
+fld public final static java.lang.String PROP_PROPERTY_SETS = "propertySets"
+fld public final static java.lang.String PROP_SHORT_DESCRIPTION = "shortDescription"
+fld public final static org.openide.nodes.Node EMPTY
+innr public abstract interface static Cookie
+innr public abstract interface static Handle
+innr public abstract static IndexedProperty
+innr public abstract static Property
+innr public abstract static PropertySet
+intf org.openide.util.HelpCtx$Provider
+intf org.openide.util.Lookup$Provider
+meth protected final boolean hasPropertyChangeListener()
+meth protected final void fireCookieChange()
+meth protected final void fireDisplayNameChange(java.lang.String,java.lang.String)
+meth protected final void fireIconChange()
+meth protected final void fireNameChange(java.lang.String,java.lang.String)
+meth protected final void fireNodeDestroyed()
+meth protected final void fireOpenedIconChange()
+meth protected final void firePropertyChange(java.lang.String,java.lang.Object,java.lang.Object)
+meth protected final void firePropertySetsChange(org.openide.nodes.Node$PropertySet[],org.openide.nodes.Node$PropertySet[])
+meth protected final void fireShortDescriptionChange(java.lang.String,java.lang.String)
+meth protected final void setChildren(org.openide.nodes.Children)
+meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
+meth public <%0 extends org.openide.nodes.Node$Cookie> {%%0} getCookie(java.lang.Class<{%%0}>)
+meth public abstract boolean canCopy()
+meth public abstract boolean canCut()
+meth public abstract boolean canDestroy()
+meth public abstract boolean canRename()
+meth public abstract boolean hasCustomizer()
+meth public abstract java.awt.Component getCustomizer()
+meth public abstract java.awt.Image getIcon(int)
+meth public abstract java.awt.Image getOpenedIcon(int)
+meth public abstract java.awt.datatransfer.Transferable clipboardCopy() throws java.io.IOException
+meth public abstract java.awt.datatransfer.Transferable clipboardCut() throws java.io.IOException
+meth public abstract java.awt.datatransfer.Transferable drag() throws java.io.IOException
+meth public abstract org.openide.nodes.Node cloneNode()
+meth public abstract org.openide.nodes.Node$Handle getHandle()
+meth public abstract org.openide.nodes.Node$PropertySet[] getPropertySets()
+meth public abstract org.openide.util.HelpCtx getHelpCtx()
+meth public abstract org.openide.util.datatransfer.NewType[] getNewTypes()
+meth public abstract org.openide.util.datatransfer.PasteType getDropType(java.awt.datatransfer.Transferable,int,int)
+meth public abstract org.openide.util.datatransfer.PasteType[] getPasteTypes(java.awt.datatransfer.Transferable)
+meth public boolean equals(java.lang.Object)
+meth public final boolean isLeaf()
+meth public final javax.swing.JPopupMenu getContextMenu()
+meth public final org.openide.nodes.Children getChildren()
+meth public final org.openide.nodes.Node getParentNode()
+meth public final org.openide.util.Lookup getLookup()
+meth public final void addNodeListener(org.openide.nodes.NodeListener)
+meth public final void addPropertyChangeListener(java.beans.PropertyChangeListener)
+meth public final void removeNodeListener(org.openide.nodes.NodeListener)
+meth public final void removePropertyChangeListener(java.beans.PropertyChangeListener)
+meth public int hashCode()
+meth public java.lang.String getHtmlDisplayName()
+meth public java.lang.String toString()
+meth public javax.swing.Action getPreferredAction()
+meth public javax.swing.Action[] getActions(boolean)
+meth public org.openide.util.actions.SystemAction getDefaultAction()
+ anno 0 java.lang.Deprecated()
+meth public org.openide.util.actions.SystemAction[] getActions()
+ anno 0 java.lang.Deprecated()
+meth public org.openide.util.actions.SystemAction[] getContextActions()
+ anno 0 java.lang.Deprecated()
+meth public void destroy() throws java.io.IOException
+meth public void setDisplayName(java.lang.String)
+meth public void setHidden(boolean)
+ anno 0 java.lang.Deprecated()
+meth public void setName(java.lang.String)
+meth public void setShortDescription(java.lang.String)
+supr java.beans.FeatureDescriptor
+hfds BLOCK_EVENTS,INIT_LOCK,LOCK,TEMPL_COOKIE,err,hierarchy,listeners,lookups,parent,warnedBadProperties
+hcls LookupEventList,PropertyEditorRef
+
+CLSS public abstract interface static org.openide.nodes.Node$Cookie
+ outer org.openide.nodes.Node
+
+CLSS public final org.openide.util.HelpCtx
+cons public init(java.lang.Class>)
+ anno 0 java.lang.Deprecated()
+cons public init(java.lang.String)
+cons public init(java.net.URL)
+ anno 0 java.lang.Deprecated()
+fld public final static org.openide.util.HelpCtx DEFAULT_HELP
+innr public abstract interface static Displayer
+innr public abstract interface static Provider
+meth public boolean display()
+meth public boolean equals(java.lang.Object)
+meth public int hashCode()
+meth public java.lang.String getHelpID()
+meth public java.lang.String toString()
+meth public java.net.URL getHelp()
+meth public static org.openide.util.HelpCtx findHelp(java.awt.Component)
+meth public static org.openide.util.HelpCtx findHelp(java.lang.Object)
+meth public static void setHelpIDString(javax.swing.JComponent,java.lang.String)
+supr java.lang.Object
+hfds err,helpCtx,helpID
+
+CLSS public abstract interface static org.openide.util.HelpCtx$Provider
+ outer org.openide.util.HelpCtx
+meth public abstract org.openide.util.HelpCtx getHelpCtx()
+
+CLSS public abstract org.openide.util.Lookup
+cons public init()
+fld public final static org.openide.util.Lookup EMPTY
+innr public abstract interface static Provider
+innr public abstract static Item
+innr public abstract static Result
+innr public final static Template
+meth public <%0 extends java.lang.Object> java.util.Collection extends {%%0}> lookupAll(java.lang.Class<{%%0}>)
+meth public <%0 extends java.lang.Object> org.openide.util.Lookup$Item<{%%0}> lookupItem(org.openide.util.Lookup$Template<{%%0}>)
+meth public <%0 extends java.lang.Object> org.openide.util.Lookup$Result<{%%0}> lookupResult(java.lang.Class<{%%0}>)
+meth public abstract <%0 extends java.lang.Object> org.openide.util.Lookup$Result<{%%0}> lookup(org.openide.util.Lookup$Template<{%%0}>)
+meth public abstract <%0 extends java.lang.Object> {%%0} lookup(java.lang.Class<{%%0}>)
+meth public static org.openide.util.Lookup getDefault()
+supr java.lang.Object
+hfds LOG,defaultLookup,defaultLookupProvider
+hcls DefLookup,Empty
+
+CLSS public abstract interface static org.openide.util.Lookup$Provider
+ outer org.openide.util.Lookup
+meth public abstract org.openide.util.Lookup getLookup()
+
diff --git a/enterprise/jakarta.web.beans/nbproject/project.properties b/enterprise/jakarta.web.beans/nbproject/project.properties
new file mode 100644
index 000000000000..ea59ff1cb5d3
--- /dev/null
+++ b/enterprise/jakarta.web.beans/nbproject/project.properties
@@ -0,0 +1,27 @@
+# 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.
+
+javac.compilerargs=-Xlint -Xlint:-serial
+javac.source=1.8
+nbm.module.author=Josh Juneau
+requires.nb.javac=true
+
+test-unit-sys-prop.java.awt.headless=true
+test.config.stable.includes=\
+**/*Test.class
+test.config.stableBTD.includes=\
+ **/xdm/model/*Test.class
diff --git a/enterprise/jakarta.web.beans/nbproject/project.xml b/enterprise/jakarta.web.beans/nbproject/project.xml
new file mode 100644
index 000000000000..87cc689e8318
--- /dev/null
+++ b/enterprise/jakarta.web.beans/nbproject/project.xml
@@ -0,0 +1,481 @@
+
+
+
+ org.netbeans.modules.apisupport.project
+
+
+ org.netbeans.modules.jakarta.web.beans
+
+
+ org.netbeans.api.annotations.common
+
+
+
+ 1
+ 1.17
+
+
+
+ org.netbeans.api.java.classpath
+
+
+
+ 1
+ 1.20
+
+
+
+ org.netbeans.api.web.webmodule
+
+
+
+ 1.0
+
+
+
+ org.netbeans.libs.javacapi
+
+
+
+ 0.5
+
+
+
+ org.netbeans.modules.editor
+
+
+
+ 3
+ 1.53
+
+
+
+ org.netbeans.modules.editor.completion
+
+
+
+ 1
+ 1.38
+
+
+
+ org.netbeans.modules.editor.document
+
+
+
+ 1.3
+
+
+
+ org.netbeans.modules.editor.lib
+
+
+
+ 3
+ 4.0
+
+
+
+ org.netbeans.modules.editor.lib2
+
+
+
+ 1
+ 2.0
+
+
+
+ org.netbeans.modules.editor.mimelookup
+
+
+
+ 1
+ 1.34
+
+
+
+ org.netbeans.modules.j2ee.api.ejbmodule
+
+
+
+ 1.15
+
+
+
+ org.netbeans.modules.j2ee.common
+
+
+
+ 1
+ 1.86
+
+
+
+ org.netbeans.modules.j2ee.core
+
+
+
+ 0-1
+ 1.1
+
+
+
+ org.netbeans.modules.j2ee.metadata
+
+
+
+ 0-1
+ 1.7
+
+
+
+ org.netbeans.modules.j2ee.metadata.model.support
+
+
+
+ 1
+ 1.14
+
+
+
+ org.netbeans.modules.java.hints.legacy.spi
+
+
+
+ 1
+ 1.0
+
+
+
+ org.netbeans.modules.java.lexer
+
+
+
+ 1
+ 1.11
+
+
+
+ org.netbeans.modules.java.project
+
+
+
+ 1
+ 1.62
+
+
+
+ org.netbeans.modules.java.source
+
+
+
+ 0.141
+
+
+
+ org.netbeans.modules.java.source.base
+
+
+
+ 1.0
+
+
+
+ org.netbeans.modules.java.sourceui
+
+
+
+ 1
+ 1.8
+
+
+
+ org.netbeans.modules.javaee.injection
+
+
+
+ 1.0
+
+
+
+ org.netbeans.modules.lexer
+
+
+
+ 2
+ 1.36
+
+
+
+ org.netbeans.modules.libs.corba.omgapi
+
+
+
+ 1.0
+
+
+
+ org.netbeans.modules.parsing.api
+
+
+
+ 1
+ 9.0
+
+
+
+ org.netbeans.modules.projectapi
+
+
+
+ 1
+
+
+
+ org.netbeans.modules.projectuiapi
+
+
+
+ 1
+ 1.78
+
+
+
+ org.netbeans.modules.projectuiapi.base
+
+
+
+ 1
+ 1.78
+
+
+
+ org.netbeans.modules.xml.lexer
+
+
+
+ 1.30
+
+
+
+ org.netbeans.modules.xml.retriever
+
+
+
+ 1
+ 1.1
+
+
+
+ org.netbeans.modules.xml.text
+
+
+
+ 2
+ 1.60
+
+
+
+ org.netbeans.modules.xml.xam
+
+
+
+ 1
+ 1.6
+
+
+
+ org.netbeans.spi.editor.hints
+
+
+
+ 0-1
+ 1.15
+
+
+
+ org.openide.awt
+
+
+
+ 7.11
+
+
+
+ org.openide.dialogs
+
+
+
+ 7.14
+
+
+
+ org.openide.filesystems
+
+
+
+ 9.0
+
+
+
+ org.openide.loaders
+
+
+
+ 7.61
+
+
+
+ org.openide.nodes
+
+
+
+ 7.13
+
+
+
+ org.openide.text
+
+
+
+ 6.40
+
+
+
+ org.openide.util
+
+
+
+ 9.3
+
+
+
+ org.openide.util.lookup
+
+
+
+ 8.0
+
+
+
+ org.openide.util.ui
+
+
+
+ 9.3
+
+
+
+ org.openide.windows
+
+
+
+ 6.28
+
+
+
+
+
+
+ unit
+
+ org.netbeans.libs.junit4
+
+
+
+ org.netbeans.modules.csl.api
+
+
+
+ org.netbeans.modules.editor.mimelookup.impl
+
+
+ org.netbeans.modules.j2ee.dd
+
+
+
+
+ org.netbeans.modules.j2ee.metadata.model.support
+
+
+
+
+ org.netbeans.modules.javahelp
+
+
+
+
+ org.netbeans.modules.masterfs
+
+
+ org.netbeans.modules.nbjunit
+
+
+
+
+ org.netbeans.modules.parsing.nb
+
+
+ org.netbeans.modules.projectapi.nb
+
+
+ org.netbeans.modules.projectui
+
+
+ org.netbeans.modules.xml.retriever
+
+
+
+ org.netbeans.modules.xml.text
+
+
+
+ org.netbeans.modules.xml.xdm
+
+
+
+ org.openide.text
+
+
+ org.openide.util.ui
+
+
+
+
+ org.openide.util.lookup
+
+
+
+
+
+
+ org.netbeans.modules.j2ee.ejbcore
+ org.netbeans.modules.web.el
+ org.netbeans.modules.web.jsf
+ org.netbeans.modules.web.jsf.editor
+ org.netbeans.gradle.javaee.project
+ org.netbeans.modules.jakarta.web.beans
+ org.netbeans.modules.jakarta.web.beans.api.model
+
+
+
+
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/BeansDataLoader.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/BeansDataLoader.java
new file mode 100644
index 000000000000..d415a39dddd4
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/BeansDataLoader.java
@@ -0,0 +1,57 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+//
+//import java.io.IOException;
+//import org.openide.filesystems.FileObject;
+//import org.openide.loaders.DataLoader;
+//import org.openide.loaders.DataObject;
+//import org.openide.util.NbBundle;
+//
+///**
+// */
+//public class BeansDataLoader extends DataLoader {
+//
+// public static final String REQUIRED_MIME = "text/x-beans-jakarta+xml";
+//
+// public BeansDataLoader() {
+// super(BeansDataObject.class.getName());
+// }
+//
+// @Override
+// protected void initialize() {
+// super.initialize();
+// }
+//
+// @Override
+// protected String defaultDisplayName() {
+// return NbBundle.getMessage(BeansDataLoader.class, "LBL_loaderName"); // NOI18N
+// }
+//
+// @Override
+// protected String actionsContext() {
+// return "Loaders/" + REQUIRED_MIME + "/Actions";
+// }
+//
+// @Override
+// protected DataObject handleFindDataObject(FileObject fo, RecognizedFiles recognized) throws IOException {
+// return new BeansDataObject(fo, this);
+// }
+//}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/BeansDataObject.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/BeansDataObject.java
new file mode 100644
index 000000000000..995e71be9d1c
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/BeansDataObject.java
@@ -0,0 +1,113 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+import java.io.IOException;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.MIMEResolver;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectExistsException;
+import org.openide.loaders.MultiDataObject;
+import org.openide.loaders.MultiFileLoader;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+import org.openide.windows.TopComponent;
+
+@Messages({
+ "LBL_Beans_LOADER_JAKARTA=Files of Beans"
+})
+@MIMEResolver.NamespaceRegistration(
+ displayName = "#LBL_Beans_LOADER_JAKARTA",
+ mimeType = "text/x-beans-jakarta+xml",
+ elementNS = {"https://jakarta.ee/xml/ns/jakartaee"},
+ position = 819
+)
+@DataObject.Registration(
+ mimeType = "text/x-beans-jakarta+xml",
+ iconBase = "org/netbeans/modules/jakarta/web/beans/resources/delegate.png",
+ displayName = "#LBL_Beans_LOADER_JAKARTA"
+)
+@ActionReferences({
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.OpenAction"),
+ position = 100,
+ separatorAfter = 200
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "Edit", id = "org.openide.actions.CutAction"),
+ position = 300
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "Edit", id = "org.openide.actions.CopyAction"),
+ position = 400,
+ separatorAfter = 500
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"),
+ position = 600
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.RenameAction"),
+ position = 700,
+ separatorAfter = 800
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"),
+ position = 900,
+ separatorAfter = 1000
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.FileSystemAction"),
+ position = 1100,
+ separatorAfter = 1200
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.ToolsAction"),
+ position = 1300
+ ),
+ @ActionReference(
+ path = "Loaders/text/x-beans-jakarta+xml/Actions",
+ id = @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"),
+ position = 1400
+ )
+})
+public class BeansDataObject extends MultiDataObject {
+
+ public BeansDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
+ super(pf, loader);
+ registerEditor("text/x-beans-jakarta+xml", false);
+ }
+
+ @Override
+ protected int associateLookup() {
+ return 1;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/Bundle.properties
new file mode 100644
index 000000000000..19b03cffa460
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/Bundle.properties
@@ -0,0 +1,18 @@
+# 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.
+
+USG_CDI_BEANS_OPENED_PROJECT=Opened Project "{0}" with existing beans.xml file.
\ No newline at end of file
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CarCdiUtil.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CarCdiUtil.java
new file mode 100644
index 000000000000..2195f29d3454
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CarCdiUtil.java
@@ -0,0 +1,59 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.j2ee.api.ejbjar.Car;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.netbeans.spi.project.ui.ProjectOpenedHook;
+import org.openide.filesystems.FileObject;
+
+
+/**
+ * @author ads
+ *
+ */
+@ProjectServiceProvider(service=CdiUtil.class, projectType = {
+ "org-netbeans-modules-j2ee-clientproject","org-netbeans-modules-maven/app-client"})
+public class CarCdiUtil extends CdiUtil {
+
+ public CarCdiUtil( Project project ) {
+ super(project);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.CdiUtil#getBeansTargetFolder(boolean)
+ */
+ @Override
+ public Collection getBeansTargetFolder( boolean create ) {
+ Project project = getProject();
+ if ( project == null ){
+ return Collections.emptyList();
+ }
+ Car cars[] = Car.getCars(project);
+ if (cars.length > 0) {
+ return Collections.singleton(cars[0].getMetaInf());
+ }
+ return super.getBeansTargetFolder(create);
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CdiProjectOpenHook.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CdiProjectOpenHook.java
new file mode 100644
index 000000000000..873f6b89d025
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CdiProjectOpenHook.java
@@ -0,0 +1,72 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+import java.lang.ref.WeakReference;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.netbeans.spi.project.ui.ProjectOpenedHook;
+
+
+/**
+ * @author ads
+ *
+ */
+@ProjectServiceProvider(service={ProjectOpenedHook.class}, projectType = {
+ "org-netbeans-modules-java-j2seproject",
+ "org-netbeans-modules-j2ee-clientproject",
+ "org-netbeans-modules-j2ee-ejbjarproject",
+ "org-netbeans-modules-web-project",
+ "org-netbeans-modules-maven/jar",
+ "org-netbeans-modules-maven/war",
+ "org-netbeans-modules-maven/ejb",
+ "org-netbeans-modules-maven/app-client"}
+ )
+public class CdiProjectOpenHook extends ProjectOpenedHook {
+
+ public CdiProjectOpenHook(Project project){
+ myProject = new WeakReference( project );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.spi.project.ui.ProjectOpenedHook#projectClosed()
+ */
+ @Override
+ protected void projectClosed() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.spi.project.ui.ProjectOpenedHook#projectOpened()
+ */
+ @Override
+ protected void projectOpened() {
+ Project project = myProject.get();
+ if ( project == null ){
+ return;
+ }
+ CdiUtil util = project.getLookup().lookup(CdiUtil.class);
+ if ( util!= null && util.isCdiEnabled() ){
+ util.log("USG_CDI_BEANS_OPENED_PROJECT", CdiProjectOpenHook.class,
+ new Object[]{project.getClass().getName()}); // NOI18N
+ }
+ }
+
+ private WeakReference myProject;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CdiUtil.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CdiUtil.java
new file mode 100644
index 000000000000..e71c949e1cc7
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/CdiUtil.java
@@ -0,0 +1,330 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import org.netbeans.api.annotations.common.CheckForNull;
+import org.netbeans.api.j2ee.core.Profile;
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.project.JavaProjectConstants;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.api.project.SourceGroupModifier;
+import org.netbeans.api.project.Sources;
+import org.netbeans.modules.j2ee.api.ejbjar.EjbJar;
+import org.netbeans.modules.j2ee.common.dd.DDHelper;
+import org.netbeans.modules.jakarta.web.beans.xml.BeansAttributes;
+import org.netbeans.modules.jakarta.web.beans.xml.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.xml.WebBeansModelFactory;
+import org.netbeans.modules.xml.retriever.catalog.Utilities;
+import org.netbeans.modules.xml.xam.ModelSource;
+import org.netbeans.modules.xml.xam.locator.CatalogModelException;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ * beware, non-static methods may behave differently in different projects(by type) if provider is overrided and registred to appropriate project type
+ * known subclasses #WebCdiUtil
+ */
+@ProjectServiceProvider(service=CdiUtil.class, projectType = {
+ "org-netbeans-modules-java-j2seproject", "org-netbeans-modules-maven/jar"})
+public class CdiUtil {
+
+ private static final Logger LOG = Logger.getLogger("org.netbeans.ui.metrics.cdi"); // NOI18N
+
+ public static final String BEANS = "beans"; // NOI18N
+ public static final String BEANS_XML = BEANS+".xml"; // NOI18N
+ private static final String META_INF = "META-INF"; // NOI18N
+ public static final String WEB_INF = "WEB-INF"; // NOI18N
+
+ public CdiUtil(Project project){
+ myProject = new WeakReference<>( project );
+ myMessages = new CopyOnWriteArraySet<>();
+ }
+
+ public void log(String message , Class> clazz, Object[] params){
+ log(message, clazz, params , false );
+ }
+
+
+ public void log(String message , Class> clazz, Object[] params, boolean once){
+ if (!once) {
+ if (myMessages.contains(message)) {
+ return;
+ }
+ else {
+ myMessages.add(message);
+ }
+ }
+
+ LogRecord logRecord = new LogRecord(Level.INFO, message);
+ logRecord.setLoggerName(LOG.getName());
+ logRecord.setResourceBundle(NbBundle.getBundle(clazz));
+ logRecord.setResourceBundleName(clazz.getPackage().getName() + ".Bundle"); // NOI18N
+ if (params != null) {
+ logRecord.setParameters(params);
+ }
+ LOG.log(logRecord);
+ }
+
+ /**
+ * check if cdi is enabled in supplied project, general implementation
+ * @param project
+ * @return
+ */
+ public static boolean isCdiEnabled(Project project){
+ return (getBeansXmlExists(project)!=null) || isCdi11OrLater(project);
+ }
+
+ private static FileObject getBeansXmlExists(Project project){
+ Collection beansTargetFolder = getBeansTargetFolder(project, false);
+ for (FileObject fileObject : beansTargetFolder) {
+ if ( fileObject != null && fileObject.getFileObject(BEANS_XML)!=null){
+ return fileObject.getFileObject(BEANS_XML);
+ }
+ }
+ return null;
+ }
+
+ private FileObject getBeansXmlExists(){
+ Collection beansTargetFolder = getBeansTargetFolder(false);
+ for (FileObject fileObject : beansTargetFolder) {
+ if ( fileObject != null && fileObject.getFileObject(BEANS_XML)!=null){
+ return fileObject.getFileObject(BEANS_XML);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * check if cdi is enabled in the project where CdiUtil is registered as a service
+ * @return ch
+ */
+ public boolean isCdiEnabled(){
+ Project project = getProject();
+ if ( project == null ){
+ return false;
+ }
+ Collection beansTargetFolder = getBeansTargetFolder(false);
+ for (FileObject fileObject : beansTargetFolder) {
+ if ( fileObject != null && fileObject.getFileObject(BEANS_XML)!=null){
+ return true;
+ }
+ }
+ // #229078 - since CDI 1.1 beans.xml is optional in case of 'implicit bean archive'
+ if (isCdi11OrLater()) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Avoid static methods usage as much as possible, use isCdi11OrLater() instead
+ * @param p
+ * @return
+ */
+ public static boolean isCdi11OrLater(Project p) {
+ if(! hasResource(p, "javax/enterprise/inject/spi/AfterTypeDiscovery.class") ) {
+ return false;
+ } else {
+ FileObject beans = getBeansXmlExists(p);
+ if(beans == null) {
+ return true;//no beans.xml and ee7 environment, default cdi 1.1 behavior
+ }
+ WebBeansModel model = WebBeansModelFactory.getInstance().getModel(getModelSource(beans, true));
+ if (model == null) {
+ return false;//???
+ }
+
+ String attribute = model.getRootComponent().getAttribute(BeansAttributes.VERSION);
+ if(attribute == null || attribute.equals("1.0")) {
+ return false;//no version attribute in cdi1.0 or equal to "1.0" in cdi 1.1.
+ }
+ return true;
+ }
+ }
+
+ public boolean isCdi11OrLater() {
+ if(! hasResource(getProject(), "javax/enterprise/inject/spi/AfterTypeDiscovery.class") ) {
+ return false;
+ } else {
+ FileObject beans = getBeansXmlExists();
+ if(beans == null) {
+ return true;//no beans.xml and ee7 environment, default cdi 1.1 behavior
+ }
+ WebBeansModel model = WebBeansModelFactory.getInstance().getModel(getModelSource(beans, true));
+ if (model == null || model.getRootComponent() == null) {
+ return false;//empty? as in cdi1.0
+ }
+
+ String attribute = model.getRootComponent().getAttribute(BeansAttributes.XMLNS);
+ String version = model.getRootComponent().getAttribute(BeansAttributes.VERSION);
+ if(attribute != null && attribute.startsWith("http://java")) {//NOI18N
+ return false;//only cdi1.0 use java.sun.com namespace, also default for future usage is cdi 1.1 (in case of corrupted beans without namespace)
+ } else if ("1.0".equals(version)){//NOI18N
+ return false;//we can fall back with version attribute if exists.
+ }
+ return true;
+ }
+ }
+
+ private static ModelSource getModelSource( FileObject fileObject ,
+ boolean isEditable )
+ {
+ try {
+ return Utilities.createModelSource( fileObject,isEditable);
+ } catch (CatalogModelException ex) {
+ Logger.getLogger("global").log(java.util.logging.Level.SEVERE,
+ ex.getMessage(), ex); // NOI18N
+ }
+ return null;
+ }
+
+ private static boolean hasResource(Project project, String resource) {
+ SourceGroup[] sgs = ProjectUtils.getSources(project).getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
+ if (sgs.length < 1) {
+ return false;
+ }
+ FileObject sourceRoot = sgs[0].getRootFolder();
+ ClassPath classPath = ClassPath.getClassPath(sourceRoot, ClassPath.COMPILE);
+ if (classPath == null) {
+ return false;
+ }
+ FileObject resourceFile = classPath.findResource(resource);
+ if (resourceFile != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public Collection getBeansTargetFolder(boolean create)
+ {
+ Project project = getProject();
+ if ( project == null ){
+ return Collections.emptyList();
+ }
+ return getBeansTargetFolder(project, create);
+ }
+
+ protected Project getProject(){
+ return myProject.get();
+ }
+
+ /**
+ * Enables CDI in the project and returns reference to the created beans.xml file if any.
+ * @return reference to beans.xml if was created, {@code null} otherwise
+ * @since 2.3
+ */
+ @CheckForNull
+ public FileObject enableCdi() {
+ Collection infs = getBeansTargetFolder(true);
+ for (FileObject inf : infs) {
+ if (inf != null) {
+ FileObject beansXml = inf.getFileObject(CdiUtil.BEANS_XML);
+ if (beansXml != null) {
+ return null;
+ }
+ try {
+ EjbJar ejbJar = EjbJar.getEjbJar(myProject.get().getProjectDirectory());
+ Profile profile = ejbJar != null ? ejbJar.getJ2eeProfile() : Profile.JAVA_EE_6_WEB;
+ LOG.log(Level.INFO, "Creating beans.xml file for project: {0}", myProject.get().getProjectDirectory());
+ return DDHelper.createBeansXml(profile, inf, CdiUtil.BEANS);
+ } catch (IOException exception) {
+ Exceptions.printStackTrace(exception);
+ }
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public static Collection getBeansTargetFolder(Project project,
+ boolean create)
+ {
+ Sources sources = ProjectUtils.getSources(project);
+ Collection result = new ArrayList<>(2);
+ SourceGroup[] sourceGroups = sources.getSourceGroups(
+ JavaProjectConstants.SOURCES_TYPE_RESOURCES );
+ if (sourceGroups != null && sourceGroups.length > 0) {
+ FileObject fileObject = getDefaultBeansTargetFolder(sourceGroups, false);
+ if (fileObject != null) {
+ result.add(fileObject);
+ }
+ }
+ else {
+ sourceGroups = sources.getSourceGroups(
+ JavaProjectConstants.SOURCES_TYPE_JAVA);
+ FileObject fileObject = getDefaultBeansTargetFolder(sourceGroups, false);
+ if ( fileObject != null ){
+ result.add(fileObject);
+ }
+ }
+ if ( result.isEmpty() && create ){
+ SourceGroup resourcesSourceGroup = SourceGroupModifier.createSourceGroup(
+ project, JavaProjectConstants.SOURCES_TYPE_RESOURCES,
+ JavaProjectConstants.SOURCES_HINT_MAIN);
+ if ( resourcesSourceGroup != null ){
+ sourceGroups = new SourceGroup[]{resourcesSourceGroup};
+ }
+ FileObject fileObject = getDefaultBeansTargetFolder(sourceGroups, true);
+ result.add(fileObject);
+ }
+ return result;
+ }
+
+ private static FileObject getDefaultBeansTargetFolder( SourceGroup[] sourceGroups,
+ boolean create )
+ {
+ if ( sourceGroups.length >0 ){
+ FileObject metaInf = sourceGroups[0].getRootFolder().getFileObject( META_INF );
+ if ( metaInf == null && create ){
+ try {
+ metaInf = FileUtil.createFolder(
+ sourceGroups[0].getRootFolder(), META_INF);
+ }
+ catch( IOException e ){
+ Logger.getLogger( CdiUtil.class.getName() ).log(
+ Level.WARNING, null, e );
+ }
+ }
+ return metaInf;
+ }
+ return null;
+ }
+
+ private WeakReference myProject;
+ private Set myMessages;
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/EjbCdiUtil.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/EjbCdiUtil.java
new file mode 100644
index 000000000000..1c5fe1ba295b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/EjbCdiUtil.java
@@ -0,0 +1,61 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.j2ee.api.ejbjar.EjbJar;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.netbeans.spi.project.ui.ProjectOpenedHook;
+import org.openide.filesystems.FileObject;
+
+
+
+/**
+ * @author ads
+ *
+ */
+@ProjectServiceProvider(service=CdiUtil.class, projectType = {
+ "org-netbeans-modules-j2ee-ejbjarproject", "org-netbeans-modules-maven/ejb"})
+public class EjbCdiUtil extends CdiUtil {
+
+ public EjbCdiUtil( Project project ) {
+ super(project);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.CdiUtil#getBeansTargetFolder(boolean)
+ */
+ @Override
+ public Collection getBeansTargetFolder(boolean create)
+ {
+ Project project = getProject();
+ if ( project == null ){
+ return Collections.emptyList();
+ }
+ EjbJar ejbs[] = EjbJar.getEjbJars(project);
+ if (ejbs.length > 0) {
+ return Collections.singleton(ejbs[0].getMetaInf());
+ }
+ return super.getBeansTargetFolder(create);
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/MetaModelSupport.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/MetaModelSupport.java
new file mode 100644
index 000000000000..8f70d513704c
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/MetaModelSupport.java
@@ -0,0 +1,108 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.WeakHashMap;
+
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.project.JavaProjectConstants;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.netbeans.api.project.Sources;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
+import org.netbeans.modules.web.api.webmodule.WebProjectConstants;
+import org.netbeans.modules.jakarta.web.beans.api.model.ModelUnit;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModelFactory;
+
+import org.netbeans.spi.java.classpath.ClassPathProvider;
+import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.openide.filesystems.FileObject;
+
+/**
+ * @author ads
+ *
+ */
+public class MetaModelSupport {
+
+ public MetaModelSupport( Project project ){
+ myProject = project;
+ }
+
+ public MetadataModel getMetaModel(){
+ synchronized (MODELS) {
+ MetadataModel metadataModel = MODELS.get( myProject );
+ if ( metadataModel != null ){
+ return metadataModel;
+ }
+ ClassPath boot = getClassPath( ClassPath.BOOT);
+ ClassPath compile = getClassPath( ClassPath.COMPILE );
+ ClassPath src = getClassPath( ClassPath.SOURCE);
+ if ( boot == null || compile == null || src == null ){
+ return null;
+ }
+ ModelUnit modelUnit = ModelUnit.create( boot, compile , src, myProject);
+ metadataModel = WebBeansModelFactory.getMetaModel( modelUnit );
+ MODELS.put( myProject, metadataModel );
+ return metadataModel;
+ }
+ }
+
+ public ClassPath getClassPath( String type ) {
+ ClassPathProvider provider = getProject().getLookup().lookup(
+ ClassPathProvider.class);
+ if ( provider == null ){
+ return null;
+ }
+ Sources sources = getProject().getLookup().lookup(Sources.class);
+ if ( sources == null ){
+ return null;
+ }
+ SourceGroup[] sourceGroups = sources.getSourceGroups(
+ JavaProjectConstants.SOURCES_TYPE_JAVA );
+ SourceGroup[] webGroup = sources.getSourceGroups(
+ WebProjectConstants.TYPE_WEB_INF);
+ ClassPath[] paths = new ClassPath[ sourceGroups.length+webGroup.length];
+ int i=0;
+ for (SourceGroup sourceGroup : sourceGroups) {
+ FileObject rootFolder = sourceGroup.getRootFolder();
+ paths[ i ] = provider.findClassPath( rootFolder, type);
+ i++;
+ }
+ for (SourceGroup sourceGroup : webGroup) {
+ FileObject rootFolder = sourceGroup.getRootFolder();
+ paths[ i ] = provider.findClassPath( rootFolder, type);
+ i++;
+ }
+ return ClassPathSupport.createProxyClassPath( paths );
+ }
+
+ private Project getProject(){
+ return myProject;
+ }
+
+ private Project myProject;
+
+ private static WeakHashMap>
+ MODELS = new WeakHashMap>();
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/WebBeanInjectionTargetQueryImplementation.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/WebBeanInjectionTargetQueryImplementation.java
new file mode 100644
index 000000000000..761f3b6a66fb
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/WebBeanInjectionTargetQueryImplementation.java
@@ -0,0 +1,122 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.javaee.injection.spi.InjectionTargetQueryImplementation;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModelAction;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModelException;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+import org.openide.util.Parameters;
+
+
+/**
+ * @author ads
+ *
+ */
+@org.openide.util.lookup.ServiceProvider(service=org.netbeans.modules.javaee.injection.spi.InjectionTargetQueryImplementation.class)
+public class WebBeanInjectionTargetQueryImplementation implements
+ InjectionTargetQueryImplementation
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.j2ee.common.queries.spi.InjectionTargetQueryImplementation#isInjectionTarget(org.netbeans.modules.j2ee.common.queries.spi.CompilationController, javax.lang.model.element.TypeElement)
+ */
+ @Override
+ public boolean isInjectionTarget( CompilationController controller,
+ TypeElement typeElement )
+ {
+ try {
+ Parameters.notNull("controller", controller);
+ Parameters.notNull("typeElement", typeElement);
+
+ Project project = FileOwnerQuery.getOwner( controller.getFileObject() );
+ if ( project == null ){
+ return false;
+ }
+ MetaModelSupport support = new MetaModelSupport(project);
+ MetadataModel metaModel = support.getMetaModel();
+ final ElementHandle handle = ElementHandle.create(typeElement);
+ return metaModel.runReadAction(new MetadataModelAction() {
+
+ @Override
+ public Boolean run( WebBeansModel model ) throws Exception {
+ TypeElement element = handle.resolve(model.getCompilationController());
+ if ( element == null ){
+ return false;
+ }
+ List qualifiers = model.getQualifiers(
+ element, true);
+ if ( qualifiers.size() == 0 ){
+ /*
+ * @Named is special case.
+ * It could be present implicitly : there are
+ * stereotype declared for the element which
+ * is annotated by @Named.
+ */
+ if ( model.getName( element ) != null ){
+ return true;
+ }
+ return false;
+ }
+ else {
+ /*
+ * There are some qualifiers.
+ * So this bean is eligible for injection. But it
+ * doesn't mean it is really managed by J2EE container.
+ */
+ return true;
+ }
+ }
+ });
+ } catch (MetadataModelException ex) {
+ Logger.getLogger( WebBeanInjectionTargetQueryImplementation.class.getName()).
+ log( Level.WARNING, ex.getMessage(), ex);
+ } catch (IOException ex) {
+ Logger.getLogger( WebBeanInjectionTargetQueryImplementation.class.getName()).
+ log( Level.WARNING, ex.getMessage(), ex);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.j2ee.common.queries.spi.InjectionTargetQueryImplementation#isStaticReferenceRequired(org.netbeans.modules.j2ee.common.queries.spi.CompilationController, javax.lang.model.element.TypeElement)
+ */
+ @Override
+ public boolean isStaticReferenceRequired( CompilationController controller,
+ TypeElement typeElement )
+ {
+ return false;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/WebCdiUtil.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/WebCdiUtil.java
new file mode 100644
index 000000000000..33607ae0a78a
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/WebCdiUtil.java
@@ -0,0 +1,71 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.web.api.webmodule.WebModule;
+import org.netbeans.spi.project.ProjectServiceProvider;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+
+
+/**
+ * @author ads
+ *
+ */
+@ProjectServiceProvider(service={CdiUtil.class}, projectType = {
+ "org-netbeans-modules-web-project", "org-netbeans-modules-maven/war"})
+public class WebCdiUtil extends CdiUtil {
+
+ public WebCdiUtil( Project project ) {
+ super(project);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.CdiUtil#getBeansTargetFolder(boolean)
+ */
+ @Override
+ public Collection getBeansTargetFolder( boolean create ) {
+ Project project = getProject();
+ if ( project == null ){
+ return Collections.emptyList();
+ }
+ WebModule wm = WebModule.getWebModule(project.getProjectDirectory());
+ if (wm != null && wm.getDocumentBase() != null) {
+ FileObject webInf = wm.getWebInf();
+ if (webInf == null && create ) {
+ try {
+ webInf = FileUtil.createFolder(wm.getDocumentBase(), WEB_INF);
+ } catch (IOException ex) {
+ Logger.getLogger( WebCdiUtil.class.getName() ).log(
+ Level.WARNING, null, ex );
+ }
+ }
+ return Collections.singleton(webInf);
+ }
+ return super.getBeansTargetFolder(create);
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/Bundle.properties
new file mode 100644
index 000000000000..034e41231a39
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/Bundle.properties
@@ -0,0 +1,31 @@
+# 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.
+
+LBL_GenerateInterceptor=Generate Interceptor...
+LBL_InterceptorName=Choose &Interceptor Name:
+ACSN_InterceptorName=Interceptor name chooser
+ACSD_InterceptorName=Enter interceptor name
+
+TITLE_Interceptor=Create Interceptor For "{0}" Interceptor Binding
+LBL_InvalidInterceptorName="{0}" is not valid Java type name.
+LBL_FileExists=File "{0}" already exists.
+
+LBL_OK=&OK
+LBL_Cancel=&Cancel
+
+USG_CDI_GENERATE_INTERCEPTOR=Generated interceptor via editor "Insert Code..." \
+context popup menu action for project "{0}".
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorFactory.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorFactory.java
new file mode 100644
index 000000000000..101acea9d17e
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorFactory.java
@@ -0,0 +1,106 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.actions;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.swing.text.JTextComponent;
+
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.spi.editor.codegen.CodeGenerator;
+import org.netbeans.spi.editor.codegen.CodeGenerator.Factory;
+import org.openide.util.Lookup;
+
+import com.sun.source.util.TreePath;
+
+
+/**
+ * @author ads
+ *
+ */
+public class InterceptorFactory implements Factory {
+
+ static final String INTERCEPTOR_BINDING = "InterceptorBinding"; // NOI18N
+
+ private static final String INTERCEPTOR_BINDING_FQN =
+ "jakarta.interceptor." +INTERCEPTOR_BINDING; // NOI18N
+
+ /* (non-Javadoc)
+ * @see org.netbeans.spi.editor.codegen.CodeGenerator.Factory#create(org.openide.util.Lookup)
+ */
+ @Override
+ public List extends CodeGenerator> create( Lookup lookup ) {
+ CompilationController controller = lookup.lookup(CompilationController.class);
+ JTextComponent component = lookup.lookup(JTextComponent.class);
+ List result = new ArrayList(1);
+ if (component != null && controller != null) {
+ try {
+ controller.toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
+
+ TypeElement interceptorBinding = controller.getElements().
+ getTypeElement( INTERCEPTOR_BINDING_FQN );
+ if ( interceptorBinding == null ){
+ return result;
+ }
+ int dot = component.getCaret().getDot();
+ TreePath tp = controller.getTreeUtilities().pathFor(dot);
+ if ( tp == null ){
+ return result;
+ }
+ Element contextElement = controller.getTrees().getElement(tp );
+ if ( contextElement == null ||
+ contextElement.getKind() != ElementKind.ANNOTATION_TYPE )
+ {
+ return result;
+ }
+
+ List extends AnnotationMirror> annotations = controller.
+ getElements().getAllAnnotationMirrors( contextElement );
+ boolean isInterceptorBinding = false;
+ for (AnnotationMirror annotation : annotations) {
+ Element annotationElement = controller.getTypes().asElement(
+ annotation.getAnnotationType());
+ if ( interceptorBinding.equals( annotationElement) ){
+ isInterceptorBinding = true;
+ break;
+ }
+ }
+ if ( isInterceptorBinding ){
+ result.add( new InterceptorGenerator(
+ contextElement.getSimpleName().toString(),
+ controller.getFileObject()) );
+ }
+ } catch (IOException ex) {
+ Logger.getLogger( InterceptorFactory.class.getName()).log(
+ Level.INFO, null, ex );
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorGenerator.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorGenerator.java
new file mode 100644
index 000000000000..7539108adc32
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorGenerator.java
@@ -0,0 +1,264 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.actions;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.swing.JButton;
+
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.java.source.ui.ElementOpen;
+import org.netbeans.api.java.source.JavaSource;
+import org.netbeans.api.java.source.ModificationResult;
+import org.netbeans.api.java.source.CancellableTask;
+import org.netbeans.api.java.source.Task;
+import org.netbeans.api.java.source.TreeMaker;
+import org.netbeans.api.java.source.TreeUtilities;
+import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.jakarta.web.beans.CdiUtil;
+import org.netbeans.spi.editor.codegen.CodeGenerator;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
+import org.openide.awt.Mnemonics;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.loaders.DataFolder;
+import org.openide.loaders.DataObject;
+import org.openide.util.HelpCtx;
+import org.openide.util.NbBundle;
+
+import com.sun.source.tree.AnnotationTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.ExpressionTree;
+import com.sun.source.tree.ModifiersTree;
+import com.sun.source.tree.Tree;
+
+
+/**
+ * @author ads
+ *
+ */
+class InterceptorGenerator implements CodeGenerator {
+
+ private static final Logger LOG = Logger.getLogger(
+ InterceptorGenerator.class.getName() );
+
+ private static final String INTERCEPTOR = "javax.interceptor.Interceptor"; // NOI18N
+
+ InterceptorGenerator( String bindingName, FileObject bindingFileObject ) {
+ myBindingName = bindingName;
+ myBindingFileObject = bindingFileObject;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.spi.editor.codegen.CodeGenerator#getDisplayName()
+ */
+ @Override
+ public String getDisplayName() {
+ return NbBundle.getMessage( InterceptorGenerator.class,
+ "LBL_GenerateInterceptor"); // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.spi.editor.codegen.CodeGenerator#invoke()
+ */
+ @Override
+ public void invoke() {
+ JButton ok = new JButton();
+ Mnemonics.setLocalizedText(ok, NbBundle.getMessage(InterceptorGenerator.class,
+ "LBL_OK") ); // NOI18N
+ JButton cancel = new JButton();
+ Mnemonics.setLocalizedText(cancel, NbBundle.getMessage(InterceptorGenerator.class,
+ "LBL_Cancel")); // NOI18N
+
+ InterceptorPanel panel = new InterceptorPanel( ok , myBindingName,
+ myBindingFileObject);
+
+ DialogDescriptor descriptor = new DialogDescriptor( panel,
+ NbBundle.getMessage(InterceptorGenerator.class, "TITLE_Interceptor",// NOI18N
+ myBindingName ),
+ true, new Object[]{ ok, cancel },
+ null, DialogDescriptor.DEFAULT_ALIGN,
+ new HelpCtx(InterceptorGenerator.class),
+ null);
+ descriptor.setClosingOptions( new Object[] { ok , cancel });
+ Object closedOption = DialogDisplayer.getDefault().notify( descriptor );
+ FileObject targetFolder = myBindingFileObject.getParent();
+ if ( closedOption == ok && targetFolder != null ){
+ createInterceptor(panel, targetFolder);
+ }
+ }
+
+ private void createInterceptor( InterceptorPanel panel,
+ FileObject targetFolder )
+ {
+ FileObject templateFileObject = FileUtil.getConfigFile(
+ "Templates/Classes/Class.java"); // NOI18N
+ try {
+ DataObject templateDataObject = DataObject
+ .find(templateFileObject);
+ DataFolder dataFolder = DataFolder.findFolder(targetFolder);
+ DataObject createdDataObject = templateDataObject.createFromTemplate(
+ dataFolder,panel.getInterceptorName(),
+ Collections. emptyMap());
+ modifyClass( createdDataObject.getPrimaryFile() ,
+ getType(myBindingFileObject, ElementKind.ANNOTATION_TYPE));
+
+ Project project = FileOwnerQuery.getOwner(myBindingFileObject);
+ if ( project != null ){
+ CdiUtil logger = project.getLookup().lookup(CdiUtil.class);
+ if ( logger != null ){
+ logger.log("USG_CDI_GENERATE_INTERCEPTOR", // NOI18N
+ InterceptorGenerator.class,
+ new Object[]{project.getClass().getName()});
+ }
+ }
+ }
+ catch (IOException e) {
+ LOG.log(Level.WARNING , null , e );
+ }
+ }
+
+ private ElementHandle getType( FileObject fileObject ,
+ final ElementKind kind ) throws IOException
+ {
+ JavaSource javaSource = JavaSource.forFileObject(fileObject);
+ final List> result =
+ new ArrayList>(1);
+ javaSource.runUserActionTask( new Task() {
+
+ @Override
+ public void run( CompilationController controller ) throws Exception {
+ controller.toPhase(JavaSource.Phase.RESOLVED);
+
+ String typeName = controller.getFileObject().getName();
+ List extends TypeElement> topLevelElements =
+ controller.getTopLevelElements();
+ for (TypeElement typeElement : topLevelElements) {
+ if ( kind == typeElement.getKind() && typeName.contentEquals(
+ typeElement.getSimpleName()))
+ {
+ result.add(ElementHandle.create( typeElement));
+ return;
+ }
+ }
+ }
+ },true);
+ return result.get(0);
+ }
+
+ private void modifyClass( FileObject fileObject ,
+ final ElementHandle handle )
+ {
+ JavaSource javaSource = JavaSource.forFileObject(fileObject);
+ try {
+ ModificationResult result = javaSource.runModificationTask(
+ new CancellableTask() {
+
+ @Override
+ public void run(WorkingCopy copy) throws IOException {
+ copy.toPhase(JavaSource.Phase.RESOLVED);
+
+ TreeMaker maker = copy.getTreeMaker();
+ ClassTree tree = getTopLevelClassTree(copy);
+ if ( tree ==null ){
+ return;
+ }
+ Element element = copy.getTrees().getElement(
+ copy.getTrees().getPath(copy.getCompilationUnit(), tree) );
+
+ ModifiersTree modifiers = tree.getModifiers();
+
+ modifiers = addAnnotation(INTERCEPTOR, maker, modifiers);
+ TypeElement annotation = handle.resolve( copy );
+ if ( annotation != null ){
+ modifiers = addAnnotation(annotation.getQualifiedName().toString(),
+ maker, modifiers);
+ }
+
+ copy.rewrite(tree.getModifiers(), modifiers);
+
+ ElementOpen.open(copy.getClasspathInfo(), element);
+ }
+
+ private ModifiersTree addAnnotation( String annotationFqn ,
+ TreeMaker maker,ModifiersTree modifiers )
+ {
+ AnnotationTree newAnnotation = maker.Annotation(
+ maker.QualIdent(annotationFqn) ,
+ Collections.emptyList());
+
+ if (modifiers != null) {
+ modifiers = maker.addModifiersAnnotation(modifiers,
+ newAnnotation);
+ }
+ return modifiers;
+ }
+
+ @Override
+ public void cancel() {
+ }
+ });
+ result.commit();
+ }
+ catch (IOException e) {
+ LOG.log(Level.WARNING , null , e );
+ }
+
+ }
+
+ public static ClassTree getTopLevelClassTree(CompilationController controller) {
+ String className = controller.getFileObject().getName();
+
+ CompilationUnitTree cu = controller.getCompilationUnit();
+ if (cu != null) {
+ List extends Tree> decls = cu.getTypeDecls();
+ for (Tree decl : decls) {
+ if (!TreeUtilities.CLASS_TREE_KINDS.contains(decl.getKind())) {
+ continue;
+ }
+
+ ClassTree classTree = (ClassTree) decl;
+
+ if (classTree.getSimpleName().contentEquals(className) &&
+ classTree.getModifiers().getFlags().contains(Modifier.PUBLIC)) {
+ return classTree;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ private String myBindingName;
+ private FileObject myBindingFileObject;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorPanel.form b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorPanel.form
new file mode 100644
index 000000000000..16680ddd9bcd
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorPanel.form
@@ -0,0 +1,98 @@
+
+
+
+
+
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorPanel.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorPanel.java
new file mode 100644
index 000000000000..9c305c302dd9
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/actions/InterceptorPanel.java
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+/*
+ * InterceptorPanel.java
+ *
+ * Created on 06.04.2011, 11:10:22
+ */
+package org.netbeans.modules.jakarta.web.beans.actions;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.BadLocationException;
+
+import org.openide.filesystems.FileObject;
+import org.openide.util.NbBundle;
+import org.openide.util.Utilities;
+
+/**
+ *
+ * @author den
+ */
+public class InterceptorPanel extends javax.swing.JPanel {
+
+ private static final long serialVersionUID = 984990919698645497L;
+
+ private static final String JAVA = "java"; // NOI18N
+
+
+ public InterceptorPanel( JButton approveButton, String bindingName,
+ FileObject bindingFileObject )
+ {
+ initComponents();
+ myBindingName = bindingName;
+ myBindingFileObject = bindingFileObject;
+
+ myInterceptorName.getDocument().addDocumentListener(
+ createValidationListener( approveButton ) );
+ myInterceptorName.setText( getProposedName() );
+ URL errorUrl;
+ try {
+ errorUrl = new URL("nbresloc:/org/netbeans/modules/dialogs/error.gif");
+ myStatusLbl.setIcon( new ImageIcon( errorUrl ));
+ }
+ catch (MalformedURLException e) {
+ assert false;
+ }
+
+ myStatusLbl.setVisible( false );
+ }
+
+ String getInterceptorName(){
+ return myInterceptorName.getText();
+ }
+
+ private DocumentListener createValidationListener(final JButton button ) {
+ DocumentListener listener = new DocumentListener() {
+
+ @Override
+ public void removeUpdate( DocumentEvent e ) {
+ checkName(e);
+ }
+
+ @Override
+ public void insertUpdate( DocumentEvent e ) {
+ checkName(e);
+ }
+
+ @Override
+ public void changedUpdate( DocumentEvent e ) {
+ checkName(e);
+ }
+
+ private void checkName(DocumentEvent e){
+ try {
+ String text = e.getDocument().getText(0,
+ e.getDocument().getLength());
+ if ( text == null || text.trim().length() == 0 ||
+ !Utilities.isJavaIdentifier( text ))
+ {
+ myStatusLbl.setText(NbBundle.getMessage(
+ InterceptorGenerator.class,
+ "LBL_InvalidInterceptorName", text ));
+ myStatusLbl.setVisible( true );
+ button.setEnabled( false );
+ return;
+ }
+ FileObject packageFolder = myBindingFileObject.getParent();
+ if ( packageFolder == null ){
+ return;
+ }
+ FileObject file = packageFolder.getFileObject( text,JAVA);
+ if ( file != null ){
+ myStatusLbl.setText(NbBundle.getMessage(
+ InterceptorGenerator.class,
+ "LBL_FileExists", file.getNameExt() ));
+ myStatusLbl.setVisible( true );
+ button.setEnabled( false );
+ return;
+ }
+
+ myStatusLbl.setText("");
+ myStatusLbl.setVisible( false );
+ button.setEnabled( true );
+ }
+ catch (BadLocationException ex ) {
+ /*
+ * should be never appear because text access is done inside
+ * event handling
+ */
+ assert false;
+ }
+ }
+ };
+ return listener;
+ }
+
+ private String getProposedName() {
+ StringBuilder result = new StringBuilder();
+ if ( myBindingName.endsWith(InterceptorFactory.INTERCEPTOR_BINDING)){
+ result.append( myBindingName.substring(0, myBindingName.length() -
+ InterceptorFactory.INTERCEPTOR_BINDING.length() ));
+ }
+ else {
+ result.append( myBindingName );
+ }
+ result.append("Interceptor"); // NOI18N
+
+ FileObject packageFolder = myBindingFileObject.getParent();
+ if ( packageFolder == null ){
+ return result.toString();
+ }
+ int index = 1;
+ String next = result.toString();
+ while( packageFolder.getFileObject( next, JAVA) != null ){
+ next = result.toString()+index;
+ index++;
+ }
+ return result.toString();
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ myInterceptorNameLbl = new javax.swing.JLabel();
+ myInterceptorName = new javax.swing.JTextField();
+ myStatusLbl = new javax.swing.JLabel();
+
+ org.openide.awt.Mnemonics.setLocalizedText(myInterceptorNameLbl, org.openide.util.NbBundle.getMessage(InterceptorPanel.class, "LBL_InterceptorName")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(myInterceptorNameLbl)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(myInterceptorName, javax.swing.GroupLayout.DEFAULT_SIZE, 244, Short.MAX_VALUE))
+ .addComponent(myStatusLbl))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(myInterceptorNameLbl)
+ .addComponent(myInterceptorName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE)
+ .addComponent(myStatusLbl)
+ .addContainerGap())
+ );
+
+ myInterceptorNameLbl.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(InterceptorPanel.class, "ACSN_InterceptorName")); // NOI18N
+ myInterceptorNameLbl.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(InterceptorPanel.class, "ACSD_InterceptorName")); // NOI18N
+ myInterceptorName.getAccessibleContext().setAccessibleName(myInterceptorNameLbl.getAccessibleContext().getAccessibleName());
+ myInterceptorName.getAccessibleContext().setAccessibleDescription(getAccessibleContext().getAccessibleDescription());
+ }// //GEN-END:initComponents
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextField myInterceptorName;
+ private javax.swing.JLabel myInterceptorNameLbl;
+ private javax.swing.JLabel myStatusLbl;
+ // End of variables declaration//GEN-END:variables
+
+ private String myBindingName;
+ private FileObject myBindingFileObject;
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/AbstractAnalysisTask.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/AbstractAnalysisTask.java
new file mode 100644
index 000000000000..f5c18d134a10
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/AbstractAnalysisTask.java
@@ -0,0 +1,65 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+
+
+/**
+ * @author ads
+ *
+ */
+abstract class AbstractAnalysisTask {
+
+ AbstractAnalysisTask( ){
+ cancel = new AtomicBoolean( false );
+ }
+
+ protected boolean isCancelled() {
+ return cancel.get();
+ }
+
+ protected AtomicBoolean getCancel(){
+ return cancel;
+ }
+
+ protected CdiAnalysisResult getResult(){
+ return myResult;
+ }
+
+ protected void setResult( CdiAnalysisResult result ){
+ myResult = result;
+ }
+
+ abstract void run( CompilationInfo compInfo );
+
+ abstract List getProblems();
+
+ void stop(){
+ cancel.set( true );
+ }
+
+ private AtomicBoolean cancel;
+ private CdiAnalysisResult myResult;
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/BeansXmlFix.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/BeansXmlFix.java
new file mode 100644
index 000000000000..eea1f406e205
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/BeansXmlFix.java
@@ -0,0 +1,95 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.netbeans.api.j2ee.core.Profile;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.j2ee.common.dd.DDHelper;
+import org.netbeans.modules.jakarta.web.beans.CdiUtil;
+import org.netbeans.spi.editor.hints.ChangeInfo;
+import org.netbeans.spi.editor.hints.Fix;
+import org.openide.filesystems.FileObject;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+class BeansXmlFix implements Fix {
+
+ BeansXmlFix( Project project , FileObject fileObject ,
+ CdiEditorAwareJavaSourceTaskFactory factory )
+ {
+ myProject = project;
+ myFileObject = fileObject;
+ myFactory = factory;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.spi.editor.hints.Fix#getText()
+ */
+ @Override
+ public String getText() {
+ return NbBundle.getMessage( BeansXmlFix.class, "MSG_HintCreateBeansXml"); // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.spi.editor.hints.Fix#implement()
+ */
+ @Override
+ public ChangeInfo implement() throws Exception {
+ CdiUtil util = myProject.getLookup().lookup( CdiUtil.class);
+ Collection infs;
+ if ( util == null ){
+ infs= CdiUtil.getBeansTargetFolder(myProject, true);
+ }
+ else {
+ infs = util.getBeansTargetFolder(true);
+ }
+ for (FileObject inf : infs) {
+ if (inf != null) {
+ FileObject beansXml = inf
+ .getFileObject(CdiUtil.BEANS_XML);
+ if (beansXml != null) {
+ return null;
+ }
+ DDHelper.createBeansXml(Profile.JAVA_EE_6_FULL, inf,
+ CdiUtil.BEANS);
+ CdiUtil logger = myProject.getLookup().lookup(CdiUtil.class);
+ if ( logger!= null ){
+ logger.log("USG_CDI_BEANS_FIX", BeansXmlFix.class,
+ new Object[]{myProject.getClass().getName()}, true );
+ }
+ if (myFactory != null) {
+ myFactory.restart(myFileObject);
+ }
+ return null;
+ }
+ }
+ return null;
+ }
+
+ private Project myProject;
+ private CdiEditorAwareJavaSourceTaskFactory myFactory;
+ private FileObject myFileObject;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/Bundle.properties
new file mode 100644
index 000000000000..a7bbcd24d870
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/Bundle.properties
@@ -0,0 +1,21 @@
+# 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.
+
+ERR_RequireWebBeans=CDI artifact is found but there is no beans.xml file.
+MSG_HintCreateBeansXml=Create beans.xml file
+
+USG_CDI_BEANS_FIX=beans.xml file is created via fix hint for project "{0}".
\ No newline at end of file
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CancellableAnalysysTask.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CancellableAnalysysTask.java
new file mode 100644
index 000000000000..6b1e5f15bb5a
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CancellableAnalysysTask.java
@@ -0,0 +1,85 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.netbeans.api.java.source.CancellableTask;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.navigation.actions.WebBeansActionHelper;
+import org.netbeans.spi.editor.hints.HintsController;
+import org.openide.filesystems.FileObject;
+
+
+/**
+ * @author ads
+ *
+ */
+abstract class CancellableAnalysysTask implements CancellableTask{
+
+ CancellableAnalysysTask(FileObject javaFile,
+ CdiEditorAwareJavaSourceTaskFactory factory )
+ {
+ myFileObject = javaFile;
+ myTask = new AtomicReference();
+ myFactory = factory;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.api.java.source.Task#run(java.lang.Object)
+ */
+ @Override
+ public void run( CompilationInfo compInfo ) throws Exception {
+ if ( !WebBeansActionHelper.isEnabled() ){
+ return;
+ }
+ AbstractAnalysisTask task = createTask();
+ myTask.set( task );
+ task.run( compInfo );
+ myTask.compareAndSet( task, null);
+ HintsController.setErrors(myFileObject, getLayerName(), task.getProblems());
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.api.java.source.CancellableTask#cancel()
+ */
+ @Override
+ public void cancel() {
+ AbstractAnalysisTask task = myTask.getAndSet(null);
+ if ( task != null ){
+ task.stop();
+ }
+ }
+
+ protected abstract String getLayerName();
+
+ protected abstract AbstractAnalysisTask createTask();
+
+ protected FileObject getFileObject(){
+ return myFileObject;
+ }
+
+ protected CdiEditorAwareJavaSourceTaskFactory getFactory(){
+ return myFactory;
+ }
+
+ private FileObject myFileObject;
+ private AtomicReference myTask;
+ private CdiEditorAwareJavaSourceTaskFactory myFactory;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiAnalysisResult.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiAnalysisResult.java
new file mode 100644
index 000000000000..95d2865c1ac0
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiAnalysisResult.java
@@ -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.netbeans.modules.jakarta.web.beans.analysis;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.lang.model.element.Element;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.jakarta.web.beans.CdiUtil;
+import org.netbeans.modules.jakarta.web.beans.hints.CDIAnnotation;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.editor.hints.Severity;
+import org.openide.filesystems.FileObject;
+import org.openide.util.NbBundle;
+
+
+
+/**
+ * @author ads
+ *
+ */
+public class CdiAnalysisResult {
+
+ public CdiAnalysisResult( CompilationInfo info,
+ CdiEditorAwareJavaSourceTaskFactory factory )
+ {
+ myInfo = info;
+ myProblems = new LinkedList();
+ myCollectedAnnotations = new LinkedList();
+ }
+
+ public void addError( Element subject, String message ) {
+ addNotification( Severity.ERROR, subject, message);
+ }
+
+ public void addError( Element subject, String message , Fix fix ) {
+ addNotification( Severity.ERROR, subject, message, fix );
+ }
+
+ public void addNotification( Severity severity,
+ Element element, String message )
+ {
+ addNotification(severity, element, message , null );
+ }
+
+ public void addNotification( Severity severity,
+ Element element, String message , Fix fix )
+ {
+ ErrorDescription description = CdiEditorAnalysisFactory.
+ createNotification( severity, element, myInfo , message, fix );
+ if ( description == null ){
+ return;
+ }
+ getProblems().add( description );
+ }
+
+ public CompilationInfo getInfo() {
+ return myInfo;
+ }
+
+ public List getProblems(){
+ return myProblems;
+ }
+
+ public void requireCdiEnabled( Element element ){
+ if ( isCdiRequired ){
+ return;
+ }
+ isCdiRequired = true;
+ FileObject fileObject = getInfo().getFileObject();
+ if ( fileObject ==null ){
+ return;
+ }
+ Project project = FileOwnerQuery.getOwner( fileObject );
+ if ( project == null ){
+ return;
+ }
+ CdiUtil lookup = project.getLookup().lookup( CdiUtil.class );
+ boolean needFix = false;
+ if ( lookup == null ){
+ //in general main use is is when lookup!=null, if lookup == null nly some general hevavior is supported
+ needFix = !CdiUtil.isCdiEnabled(project);
+ }
+ else {
+ needFix = !lookup.isCdiEnabled();
+ }
+ if ( needFix) {
+ Fix fix = new BeansXmlFix( project , fileObject , myFactory );
+ addError(element, NbBundle.getMessage(CdiAnalysisResult.class,
+ "ERR_RequireWebBeans"), fix ); // NOI18N
+ }
+ }
+
+ public boolean requireBeansXml(){
+ return isCdiRequired;
+ }
+
+ public void addAnnotation( CDIAnnotation annotation ) {
+ myCollectedAnnotations.add(annotation);
+ }
+
+ public List getAnnotations(){
+ return Collections.unmodifiableList(myCollectedAnnotations);
+ }
+
+ private CompilationInfo myInfo ;
+ private List myProblems;
+ private boolean isCdiRequired;
+ private List myCollectedAnnotations;
+ private CdiEditorAnalysisFactory myFactory;
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiAnalysisTask.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiAnalysisTask.java
new file mode 100644
index 000000000000..452f9df05d7d
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiAnalysisTask.java
@@ -0,0 +1,130 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationElementAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassElementAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.CtorAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldElementAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+
+
+/**
+ * @author ads
+ *
+ */
+public class CdiAnalysisTask extends AbstractAnalysisTask {
+
+ public CdiAnalysisTask( CdiEditorAwareJavaSourceTaskFactory factory ){
+ myFactory =factory;
+ }
+
+
+ protected CdiAnalysisResult createResult( CompilationInfo info ){
+ return new CdiAnalysisResult(info, myFactory );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.AbstractAnalysisTask#getProblems()
+ */
+ @Override
+ List getProblems() {
+ return getResult().getProblems();
+ }
+
+ @Override
+ protected void run( CompilationInfo compInfo ) {
+ setResult( createResult( compInfo ) );
+ List extends TypeElement> types = compInfo.getTopLevelElements();
+ for (TypeElement typeElement : types) {
+ if ( isCancelled() ){
+ break;
+ }
+ analyzeType(typeElement, null );
+ }
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(getResult());
+ if ( helper == null ){
+ return;
+ }
+ helper.publish( getResult() );
+ }
+
+ private void analyzeType(TypeElement typeElement , TypeElement parent )
+ {
+ ElementKind kind = typeElement.getKind();
+ ElementAnalyzer analyzer = ANALIZERS.get( kind );
+ if ( analyzer != null ){
+ analyzer.analyze(typeElement, parent, getCancel(), getResult() );
+ }
+ if ( isCancelled() ){
+ return;
+ }
+ List extends Element> enclosedElements = typeElement.getEnclosedElements();
+ List types = ElementFilter.typesIn(enclosedElements);
+ for (TypeElement innerType : types) {
+ analyzeType(innerType, typeElement );
+ }
+ Set enclosedSet = new HashSet( enclosedElements );
+ enclosedSet.removeAll( types );
+ for(Element element : enclosedSet ){
+ analyze(typeElement, element);
+ }
+ }
+
+ private void analyze( TypeElement typeElement, Element element )
+ {
+ ElementAnalyzer analyzer;
+ if ( isCancelled() ){
+ return;
+ }
+ analyzer = ANALIZERS.get( element.getKind() );
+ if ( analyzer == null ){
+ return;
+ }
+ analyzer.analyze(element, typeElement, getCancel(), getResult() );
+ }
+
+ private CdiEditorAwareJavaSourceTaskFactory myFactory;
+ private static final Map ANALIZERS =
+ new HashMap();
+
+ static {
+ ANALIZERS.put(ElementKind.CLASS, new ClassElementAnalyzer());
+ ANALIZERS.put(ElementKind.FIELD, new FieldElementAnalyzer());
+ ANALIZERS.put(ElementKind.METHOD, new MethodElementAnalyzer());
+ ANALIZERS.put(ElementKind.CONSTRUCTOR, new CtorAnalyzer());
+ ANALIZERS.put(ElementKind.ANNOTATION_TYPE, new AnnotationElementAnalyzer());
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAnalysisFactory.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAnalysisFactory.java
new file mode 100644
index 000000000000..dac280b9cc25
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAnalysisFactory.java
@@ -0,0 +1,232 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+import org.netbeans.api.java.lexer.JavaTokenId;
+import org.netbeans.api.java.source.CancellableTask;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.java.source.JavaSource.Phase;
+import org.netbeans.api.java.source.JavaSource.Priority;
+import org.netbeans.api.java.source.JavaSourceTaskFactory;
+import org.netbeans.api.java.source.TreeUtilities;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.editor.hints.Severity;
+import org.openide.filesystems.FileObject;
+import org.openide.util.lookup.ServiceProvider;
+
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.SourcePositions;
+
+
+/**
+ * @author ads
+ *
+ */
+@ServiceProvider(service=JavaSourceTaskFactory.class)
+public class CdiEditorAnalysisFactory extends CdiEditorAwareJavaSourceTaskFactory {
+
+ public CdiEditorAnalysisFactory( ){
+ super(Priority.BELOW_NORMAL);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.api.java.source.JavaSourceTaskFactory#createTask(org.openide.filesystems.FileObject)
+ */
+ @Override
+ protected CancellableTask createTask( FileObject fileObject ) {
+ return new CdiEditorAnalysisTask( fileObject , this );
+ }
+
+ public static ErrorDescription createError( Element subject ,
+ CompilationInfo info ,String description)
+ {
+ return createNotification(Severity.ERROR, subject, info, description);
+ }
+
+ public static ErrorDescription createNotification( Severity severity,
+ Element subject , CompilationInfo info ,String description)
+ {
+ return createNotification(severity, subject, info, description, null);
+ }
+
+ public static ErrorDescription createNotification( Severity severity,
+ Element subject , CompilationInfo info ,String description, Fix fix )
+ {
+ Tree elementTree = info.getTrees().getTree(subject);
+ return createNotification(severity, elementTree, info, description, fix );
+ }
+
+ public static ErrorDescription createNotification( Severity severity,
+ Element subject , WebBeansModel model, CompilationInfo info ,
+ String description)
+ {
+ return createNotification(severity, subject, model , info, description,
+ null);
+ }
+
+ public static ErrorDescription createNotification( Severity severity,
+ Element subject , WebBeansModel model, CompilationInfo info ,
+ String description, Fix fix )
+ {
+ ElementHandle handle = ElementHandle.create( subject );
+ Element element = handle.resolve(info);
+ if ( element == null){
+ return null;
+ }
+ Tree elementTree = info.getTrees().getTree(element);
+ return createNotification(severity, elementTree, info, description, fix );
+ }
+
+ public static ErrorDescription createNotification( Severity severity,
+ VariableElement element, ExecutableElement parent ,
+ WebBeansModel model, CompilationInfo info ,String description, Fix fix)
+ {
+ VariableElement var = resolveParameter(element, parent, info);
+ if ( var == null ){
+ return null;
+ }
+ Tree elementTree = info.getTrees().getTree(var);
+ return createNotification(severity, elementTree, info, description, fix );
+ }
+
+ public static ErrorDescription createNotification( Severity severity,
+ VariableElement element, ExecutableElement parent ,
+ WebBeansModel model, CompilationInfo info ,String description)
+ {
+ return createNotification( severity, element, parent, model , info ,
+ description, null );
+ }
+
+ public static VariableElement resolveParameter( VariableElement element,
+ ExecutableElement parent,CompilationInfo info )
+ {
+ List extends VariableElement> parameters = parent.getParameters();
+ int i=0;
+ for (VariableElement param : parameters) {
+ if ( param.equals( element )){
+ break;
+ }
+ i++;
+ }
+ if ( i == parameters.size() ){
+ return null;
+ }
+ ElementHandle handle = ElementHandle.create( parent );
+ ExecutableElement method = handle.resolve(info);
+ if ( method == null){
+ return null;
+ }
+ parameters = method.getParameters();
+ int j=0;
+ VariableElement var = null;
+ for (VariableElement param : parameters) {
+ if ( i==j){
+ var = param;
+ }
+ j++;
+ }
+ return var;
+ }
+
+ private static ErrorDescription createNotification( Severity severity,
+ Tree tree, CompilationInfo info, String description, Fix fix )
+ {
+
+ List fixes;
+ if ( fix != null ){
+ fixes = Collections.singletonList( fix );
+ }
+ else {
+ fixes = Collections.emptyList();
+ }
+ if (tree != null){
+ List position = getElementPosition(info, tree);
+ if(position.get(1) > position.get(0)) {
+ return ErrorDescriptionFactory.createErrorDescription(
+ severity, description, fixes,
+ info.getFileObject(), position.get(0), position.get(1));
+ }
+ }
+ return null;
+ }
+
+ public static List getElementPosition(CompilationInfo info, Tree tree){
+ SourcePositions srcPos = info.getTrees().getSourcePositions();
+
+ int startOffset = (int) srcPos.getStartPosition(info.getCompilationUnit(), tree);
+ int endOffset = (int) srcPos.getEndPosition(info.getCompilationUnit(), tree);
+
+ Tree startTree = null;
+
+ if (TreeUtilities.CLASS_TREE_KINDS.contains(tree.getKind())){
+ startTree = ((ClassTree)tree).getModifiers();
+
+ } else if (tree.getKind() == Tree.Kind.METHOD){
+ startTree = ((MethodTree)tree).getReturnType();
+ } else if (tree.getKind() == Tree.Kind.VARIABLE){
+ startTree = ((VariableTree)tree).getType();
+ }
+
+ if (startTree != null){
+ int searchStart = (int) srcPos.getEndPosition(info.getCompilationUnit(),
+ startTree);
+
+ TokenSequence> tokenSequence = info.getTreeUtilities().tokensFor(tree);
+
+ if (tokenSequence != null){
+ boolean eob = false;
+ tokenSequence.move(searchStart);
+
+ do{
+ eob = !tokenSequence.moveNext();
+ }
+ while (!eob && tokenSequence.token().id() != JavaTokenId.IDENTIFIER);
+
+ if (!eob){
+ Token> identifier = tokenSequence.token();
+ startOffset = identifier.offset(info.getTokenHierarchy());
+ endOffset = startOffset + identifier.length();
+ }
+ }
+ }
+
+ List result = new ArrayList(2);
+ result.add(startOffset);
+ result.add(endOffset );
+ return result;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAnalysisTask.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAnalysisTask.java
new file mode 100644
index 000000000000..6a97c968a7d4
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAnalysisTask.java
@@ -0,0 +1,50 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import org.openide.filesystems.FileObject;
+
+
+/**
+ * @author ads
+ *
+ */
+class CdiEditorAnalysisTask extends CancellableAnalysysTask {
+
+ CdiEditorAnalysisTask(FileObject javaFile,
+ CdiEditorAwareJavaSourceTaskFactory factory )
+ {
+ super( javaFile , factory );
+ }
+
+ @Override
+ protected String getLayerName() {
+ return "CDI Analyser"; //NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.CancellableAnalysysTask#createTask()
+ */
+ @Override
+ protected AbstractAnalysisTask createTask() {
+ return new CdiAnalysisTask( getFactory() );
+ };
+
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAwareJavaSourceTaskFactory.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAwareJavaSourceTaskFactory.java
new file mode 100644
index 000000000000..61ba37f7e71f
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/CdiEditorAwareJavaSourceTaskFactory.java
@@ -0,0 +1,45 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import org.netbeans.api.java.source.JavaSource.Phase;
+import org.netbeans.api.java.source.JavaSource.Priority;
+import org.netbeans.api.java.source.support.EditorAwareJavaSourceTaskFactory;
+import org.netbeans.modules.parsing.spi.TaskIndexingMode;
+import org.openide.filesystems.FileObject;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class CdiEditorAwareJavaSourceTaskFactory extends
+ EditorAwareJavaSourceTaskFactory
+{
+
+ protected CdiEditorAwareJavaSourceTaskFactory( Priority priority ) {
+ super(Phase.RESOLVED, priority, /*TaskIndexingMode.ALLOWED_DURING_SCAN ,*/
+ "text/x-java"); // NOI18N
+ }
+
+ void restart( FileObject fileObject ){
+ reschedule( fileObject );
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansAnalysisTask.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansAnalysisTask.java
new file mode 100644
index 000000000000..989d74f569a9
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansAnalysisTask.java
@@ -0,0 +1,206 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModel;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModelAction;
+import org.netbeans.modules.j2ee.metadata.model.api.MetadataModelException;
+import org.netbeans.modules.jakarta.web.beans.MetaModelSupport;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationModelAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldModelAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodModelAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+
+
+/**
+ * @author ads
+ *
+ */
+public class WebBeansAnalysisTask extends AbstractAnalysisTask {
+
+ private static final Logger LOG = Logger.getLogger(
+ WebBeansAnalysisTask.class.getName());
+
+ public WebBeansAnalysisTask( CdiEditorAwareJavaSourceTaskFactory factory ){
+ myFactory = factory;
+ }
+
+ protected Result createResult( CompilationInfo compInfo )
+ {
+ return new Result( compInfo , myFactory );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.AbstractAnalysisTask#getResult()
+ */
+ @Override
+ protected Result getResult() {
+ return (Result)super.getResult();
+ }
+
+ protected MetadataModel getModel(CompilationInfo compInfo){
+ Project project = FileOwnerQuery.getOwner( compInfo.getFileObject() );
+ if ( project == null ){
+ return null;
+ }
+ MetaModelSupport support = new MetaModelSupport(project);
+ return support.getMetaModel();
+ }
+
+ @Override
+ List getProblems(){
+ return getResult().getProblems();
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.AbstractAnalysisTask#run(org.netbeans.api.java.source.CompilationInfo)
+ */
+ @Override
+ protected void run( final CompilationInfo compInfo ) {
+ setResult( createResult( compInfo ) );
+ List extends TypeElement> types = compInfo.getTopLevelElements();
+ final List> handles =
+ new ArrayList>(1);
+ for (TypeElement typeElement : types) {
+ if ( isCancelled() ){
+ break;
+ }
+ handles.add(ElementHandle.create(typeElement));
+ }
+ MetadataModel metaModel = getModel(compInfo);
+ if ( metaModel == null ){
+ return;
+ }
+ try {
+ metaModel.runReadAction(
+ new MetadataModelAction()
+ {
+ @Override
+ public Void run( WebBeansModel model ) throws Exception {
+ CompilationController controller = model.getCompilationController();
+ for (ElementHandle handle : handles) {
+ if(isCancelled()) {
+ break;
+ }
+ TypeElement type = handle.resolve( controller );
+ if ( type == null ){
+ continue;
+ }
+ analyzeType( type , null , model , compInfo );
+ }
+ return null;
+ }
+ });
+ }
+ catch (MetadataModelException e) {
+ LOG.log( Level.INFO , null , e);
+ }
+ catch (IOException e) {
+ LOG.log( Level.INFO , null , e);
+ }
+ finally {
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(getResult());
+ if ( helper == null ){
+ return;
+ }
+ helper.publish( getResult() );
+ }
+ }
+
+ private void analyzeType(TypeElement typeElement , TypeElement parent ,
+ WebBeansModel model , CompilationInfo info )
+ {
+ ElementKind kind = typeElement.getKind();
+ ModelAnalyzer analyzer = ANALIZERS.get( kind );
+ if ( analyzer != null ){
+ analyzer.analyze(typeElement, parent, model, getCancel(), getResult());
+ }
+ if ( isCancelled() ){
+ return;
+ }
+ List extends Element> enclosedElements = typeElement.getEnclosedElements();
+ List types = ElementFilter.typesIn(enclosedElements);
+ for (TypeElement innerType : types) {
+ if ( innerType == null ){
+ continue;
+ }
+ analyzeType(innerType, typeElement , model , info );
+ }
+ Set enclosedSet = new HashSet( enclosedElements );
+ enclosedSet.removeAll( types );
+ for(Element element : enclosedSet ){
+ if ( element == null ){
+ continue;
+ }
+ analyze(typeElement, model, element, info );
+ }
+ }
+
+ private void analyze( TypeElement typeElement, WebBeansModel model,
+ Element element, CompilationInfo info )
+ {
+ ModelAnalyzer analyzer;
+ if ( isCancelled() ){
+ return;
+ }
+ analyzer = ANALIZERS.get( element.getKind() );
+ if ( analyzer == null ){
+ return;
+ }
+ analyzer.analyze(element, typeElement, model, getCancel(), getResult());
+ }
+
+ private CdiEditorAwareJavaSourceTaskFactory myFactory;
+
+ private static final Map ANALIZERS =
+ new HashMap();
+
+ static {
+ ANALIZERS.put(ElementKind.CLASS, new ClassModelAnalyzer());
+ ANALIZERS.put(ElementKind.FIELD, new FieldModelAnalyzer());
+ ANALIZERS.put(ElementKind.METHOD, new MethodModelAnalyzer());
+ ANALIZERS.put(ElementKind.ANNOTATION_TYPE, new AnnotationModelAnalyzer());
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansEditorAnalysisTask.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansEditorAnalysisTask.java
new file mode 100644
index 000000000000..ef7bd0a7ce5a
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansEditorAnalysisTask.java
@@ -0,0 +1,54 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import org.openide.filesystems.FileObject;
+
+
+/**
+ * @author ads
+ *
+ */
+class WebBeansEditorAnalysisTask extends CancellableAnalysysTask {
+
+
+ WebBeansEditorAnalysisTask(FileObject javaFile,
+ CdiEditorAwareJavaSourceTaskFactory factory )
+ {
+ super( javaFile , factory );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.CancellableAnalysysTask#getLayerName()
+ */
+ @Override
+ protected String getLayerName() {
+ return "Web Beans Model Analyzer"; // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.CancellableAnalysysTask#createTask()
+ */
+ @Override
+ protected AbstractAnalysisTask createTask() {
+ return new WebBeansAnalysisTask( getFactory() );
+ }
+
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansModelAnalysisFactory.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansModelAnalysisFactory.java
new file mode 100644
index 000000000000..a5ed362ecc38
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/WebBeansModelAnalysisFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis;
+
+import org.netbeans.api.java.source.CancellableTask;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.JavaSource.Priority;
+import org.netbeans.api.java.source.JavaSourceTaskFactory;
+import org.openide.filesystems.FileObject;
+import org.openide.util.lookup.ServiceProvider;
+
+
+/**
+ * @author ads
+ *
+ */
+@ServiceProvider(service=JavaSourceTaskFactory.class)
+public class WebBeansModelAnalysisFactory extends
+ CdiEditorAwareJavaSourceTaskFactory
+{
+
+ public WebBeansModelAnalysisFactory( ) {
+ super(Priority.LOW);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.api.java.source.JavaSourceTaskFactory#createTask(org.openide.filesystems.FileObject)
+ */
+ @Override
+ protected CancellableTask createTask( FileObject fileObject ) {
+ return new WebBeansEditorAnalysisTask( fileObject, this );
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractDecoratorAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractDecoratorAnalyzer.java
new file mode 100644
index 000000000000..68de8c5c40a9
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractDecoratorAnalyzer.java
@@ -0,0 +1,187 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.DelegateFieldAnalizer;
+import org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class AbstractDecoratorAnalyzer {
+
+ protected void analyzeDecoratedBeans( DependencyInjectionResult res,
+ VariableElement element, T t, TypeElement decorator ,
+ WebBeansModel model, Result result )
+ {
+ Set decoratedBeans = null;
+ if ( res instanceof DependencyInjectionResult.ApplicableResult ){
+ DependencyInjectionResult.ApplicableResult appResult =
+ (DependencyInjectionResult.ApplicableResult) res;
+ decoratedBeans = appResult.getTypeElements();
+ }
+ else if ( res instanceof DependencyInjectionResult.InjectableResult ){
+ Element decorated = ((DependencyInjectionResult.InjectableResult)res).
+ getElement();
+ if ( decorated instanceof TypeElement ){
+ decoratedBeans = Collections.singleton( (TypeElement)decorated);
+ }
+ }
+ if ( decoratedBeans == null ){
+ return;
+ }
+ for( TypeElement decorated : decoratedBeans ){
+ Set modifiers = decorated.getModifiers();
+ if ( modifiers.contains(Modifier.FINAL)){
+ addClassError( element , t , decorated, model , result );
+ return;
+ }
+ }
+ if ( decoratedBeans.isEmpty() ){
+ return;
+ }
+ /*
+ * The rule : "If a decorator matches a managed bean with a non-static,
+ * non-private, final method, the decorator shouldn't also implement that method."
+ * is actually nonsense.
+ * Each Java class has final wait(). Decorator is also java class
+ * so it also has a method wait() . So it always implements
+ * non-static, non-private final method.
+ * I believe one need to care about ONLY methods in decorated types :
+ * all methods that are defined in interfaces ( decorated types )
+ * and which are implemented in the decorator and decorated bean.
+ *
+ * Here is implementation of this requirement.
+ */
+ Collection decoratedTypes = DelegateFieldAnalizer
+ .getDecoratedTypes(decorator, model.getCompilationController());
+ for (TypeMirror typeMirror : decoratedTypes) {
+ Element decoratedTypeElement = model.getCompilationController()
+ .getTypes().asElement(typeMirror);
+ if (!(decoratedTypeElement instanceof TypeElement)) {
+ continue;
+ }
+ TypeElement iface = (TypeElement) decoratedTypeElement;
+ List methods = ElementFilter.methodsIn(iface
+ .getEnclosedElements());
+ for (ExecutableElement method : methods) {
+ Element decoratorMethod = model.getCompilationController()
+ .getElementUtilities()
+ .getImplementationOf(method, decorator);
+ if (decoratorMethod == null) {
+ continue;
+ }
+ if (decoratorMethod.getModifiers().contains(Modifier.ABSTRACT))
+ {
+ continue;
+ }
+ for (TypeElement decorated : decoratedBeans) {
+ Element decoratedMethod = model.getCompilationController()
+ .getElementUtilities()
+ .getImplementationOf(method, decorated);
+ if (decoratedMethod == null) {
+ continue;
+ }
+ if (decoratedMethod.getModifiers().contains(Modifier.FINAL))
+ {
+ addMethodError( element , t, decorated, decoratedMethod,
+ model , result );
+ }
+ }
+ }
+ }
+ }
+
+ protected boolean checkBuiltInBeans( VariableElement element,
+ TypeMirror elementType, WebBeansModel model, AtomicBoolean cancel )
+ {
+ TypeElement context = model.getCompilationController().getElements().
+ getTypeElement(AnnotationUtil.CONTEXT);
+ if ( context != null && context.equals(model.getCompilationController().
+ getTypes().asElement(elementType)))
+ {
+ /* This is built-in jakarta.enterprise.context.spi.Context bean
+ * provided by container for each scope
+ */
+ return true;
+ }
+ if ( cancel.get()){
+ return true;
+ }
+
+ Element varElement = model.getCompilationController().getTypes().
+ asElement(elementType);
+ if ( varElement instanceof TypeElement ){
+ if ( !((TypeElement)varElement).getQualifiedName().contentEquals(
+ AnnotationUtil.CONVERSATION))
+ {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+
+ if ( model.hasImplicitDefaultQualifier( element ) ){
+ return true;
+ }
+ List qualifiers = model.getQualifiers(element, true);
+ AnnotationHelper helper = new AnnotationHelper(model.getCompilationController());
+ Map qualifiersFqns = helper.
+ getAnnotationsByType(qualifiers);
+ boolean hasOnlyDefault = false;
+ if ( qualifiersFqns.containsKey(AnnotationUtil.DEFAULT_FQN)){
+ HashSet fqns = new HashSet(qualifiersFqns.keySet());
+ fqns.remove( AnnotationUtil.NAMED );
+ fqns.remove( AnnotationUtil.ANY );
+ hasOnlyDefault = fqns.size() == 1;
+ }
+ return hasOnlyDefault;
+ }
+
+ protected abstract void addMethodError( VariableElement element, T t,
+ TypeElement decorated, Element decoratedMethod,
+ WebBeansModel model, Result result );
+
+ protected abstract void addClassError( VariableElement element , T t,
+ TypeElement decoratedBean, WebBeansModel model, Result result );
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractInterceptedElementAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractInterceptedElementAnalyzer.java
new file mode 100644
index 000000000000..61e733ee6437
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractInterceptedElementAnalyzer.java
@@ -0,0 +1,51 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class AbstractInterceptedElementAnalyzer {
+
+
+ protected Set getInterceptorBindings(Element element,
+ WebBeansModel model)
+ {
+ Collection interceptorBindings = model
+ .getInterceptorBindings(element);
+ return new HashSet( interceptorBindings );
+ }
+
+ protected boolean hasInterceptorBindings(Element element,
+ WebBeansModel model )
+ {
+ return !getInterceptorBindings(element, model).isEmpty();
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractProducerAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractProducerAnalyzer.java
new file mode 100644
index 000000000000..efde11dc2877
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractProducerAnalyzer.java
@@ -0,0 +1,80 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.List;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class AbstractProducerAnalyzer {
+
+ protected abstract void hasTypeVar( Element element, TypeMirror type,
+ CdiAnalysisResult result );
+
+ protected abstract void hasWildCard(Element element, TypeMirror type,
+ CdiAnalysisResult result);
+
+ protected void checkType( Element element, TypeMirror type,
+ CdiAnalysisResult result )
+ {
+ if ( type.getKind() == TypeKind.TYPEVAR ){
+ hasTypeVar(element, type, result );
+ }
+ else if (hasWildCard(type)) {
+ hasWildCard( element, type, result );
+ return;
+ }
+ }
+
+ protected boolean hasType(TypeMirror typeMirror, TypeKind kind ){
+ if ( typeMirror instanceof DeclaredType ){
+ List extends TypeMirror> typeArguments =
+ ((DeclaredType)typeMirror).getTypeArguments();
+ for (TypeMirror paramType : typeArguments) {
+ if ( paramType.getKind() == kind ){
+ return true;
+ }
+ else {
+ if ( hasType(paramType, kind) ){
+ return true;
+ }
+ }
+ }
+ }
+ else if ( typeMirror instanceof ArrayType ){
+ return hasType( ((ArrayType)typeMirror).getComponentType(), kind);
+ }
+ return false;
+ }
+
+ private boolean hasWildCard(TypeMirror typeMirror){
+ return hasType(typeMirror, TypeKind.WILDCARD);
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractScopedAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractScopedAnalyzer.java
new file mode 100644
index 000000000000..4ecdf1a8a9aa
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractScopedAnalyzer.java
@@ -0,0 +1,138 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.CdiException;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class AbstractScopedAnalyzer {
+
+ public void analyzeScope( Element element,
+ WebBeansModel model, AtomicBoolean cancel , Result result )
+ {
+ try {
+ String scope = model.getScope( element );
+ if ( cancel.get() ){
+ return;
+ }
+ TypeElement scopeElement = model.getCompilationController().
+ getElements().getTypeElement( scope );
+ if ( scopeElement == null ){
+ return;
+ }
+ checkScope( scopeElement , element , model, cancel, result );
+ }
+ catch (CdiException e) {
+ result.requireCdiEnabled(element, model);
+ informCdiException(e, element, model, result );
+ }
+ }
+
+ protected abstract void checkScope( TypeElement scopeElement, Element element,
+ WebBeansModel model, AtomicBoolean cancel, Result result );
+
+ protected boolean hasTypeVarParameter(TypeMirror type ){
+ if ( type.getKind() == TypeKind.TYPEVAR){
+ return true;
+ }
+ if ( type instanceof DeclaredType ){
+ List extends TypeMirror> typeArguments =
+ ((DeclaredType)type).getTypeArguments();
+ for (TypeMirror typeArg : typeArguments) {
+ if ( hasTypeVarParameter(typeArg)){
+ return true;
+ }
+ }
+ }
+ else if ( type instanceof ArrayType ){
+ return hasTypeVarParameter(((ArrayType)type).getComponentType());
+ }
+ return false;
+ }
+
+ protected boolean isPassivatingScope( TypeElement scope, WebBeansModel model ) {
+ AnnotationMirror normalScope = AnnotationUtil.getAnnotationMirror(
+ scope, model.getCompilationController(), AnnotationUtil.NORMAL_SCOPE_FQN);
+ if ( normalScope==null){
+ return false;
+ }
+ Map extends ExecutableElement, ? extends AnnotationValue> elementValues =
+ normalScope.getElementValues();
+ boolean isPassivating = false;
+ for (Entry extends ExecutableElement, ? extends AnnotationValue> entry:
+ elementValues.entrySet())
+ {
+ ExecutableElement key = entry.getKey();
+ if ( key.getSimpleName().contentEquals(AnnotationUtil.PASSIVATING)){
+ isPassivating = Boolean.TRUE.toString().equals(entry.getValue().toString());
+ }
+ }
+ return isPassivating;
+ }
+
+ protected boolean isSerializable( Element element, WebBeansModel model ) {
+ TypeMirror elementType = element.asType();
+ if ( elementType == null || elementType.getKind() == TypeKind.ERROR){
+ return true;
+ }
+ return isSerializable(elementType, model);
+ }
+
+ protected boolean isSerializable( TypeMirror type, WebBeansModel model ) {
+ TypeElement serializable = model.getCompilationController().getElements().
+ getTypeElement(Serializable.class.getCanonicalName());
+ if ( serializable == null ){
+ return true;
+ }
+ TypeMirror serializableType = serializable.asType();
+ if ( serializableType == null || serializableType.getKind() == TypeKind.ERROR){
+ return true;
+ }
+ return model.getCompilationController().getTypes().isSubtype(type,
+ serializableType);
+ }
+
+ private void informCdiException(CdiException exception , Element element,
+ WebBeansModel model, Result result )
+ {
+ result.addError( element, model, exception.getMessage());
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractTypedAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractTypedAnalyzer.java
new file mode 100644
index 000000000000..bc05fd57e19e
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AbstractTypedAnalyzer.java
@@ -0,0 +1,182 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class AbstractTypedAnalyzer {
+
+ public void analyze( Element element, TypeMirror elementType,
+ AtomicBoolean cancel , CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ List list = getRestrictedTypes(element, compInfo, cancel);
+ if ( list == null ){
+ return;
+ }
+ result.requireCdiEnabled(element);
+ for (TypeMirror type : list) {
+ if ( cancel.get()){
+ return;
+ }
+ boolean isSubtype = hasBeanType(element, elementType, type, compInfo);
+ if (!isSubtype) {
+ addError(element, result );
+ }
+ }
+ // check @Specializes types restriction conformance
+ if ( cancel.get()){
+ return;
+ }
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.SPECIALIZES,
+ compInfo))
+ {
+ result.requireCdiEnabled(element);
+ checkSpecializes( element , elementType , list, cancel , result );
+ }
+ }
+
+ protected abstract void checkSpecializes( Element element, TypeMirror elementType,
+ List restrictedTypes, AtomicBoolean cancel , CdiAnalysisResult result );
+
+ protected boolean hasBeanType( Element subject, TypeMirror elementType,
+ TypeMirror requiredBeanType,CompilationInfo compInfo )
+ {
+ return compInfo.getTypes().isSubtype(elementType, requiredBeanType);
+ }
+
+ protected abstract void addError ( Element element ,
+ CdiAnalysisResult result );
+
+ protected void collectAncestors(TypeElement type , Set ancestors,
+ CompilationInfo compInfo )
+ {
+ TypeMirror superclass = type.getSuperclass();
+ addAncestor( superclass, ancestors, compInfo);
+ List extends TypeMirror> interfaces = type.getInterfaces();
+ for (TypeMirror interfaze : interfaces) {
+ addAncestor(interfaze, ancestors, compInfo);
+ }
+ }
+
+ private void addAncestor( TypeMirror parent , Set ancestors,
+ CompilationInfo compInfo)
+ {
+ if ( parent == null ){
+ return;
+ }
+ Element parentElement = compInfo.getTypes().asElement( parent );
+ if ( parentElement instanceof TypeElement ){
+ if ( ancestors.contains( (TypeElement)parentElement))
+ {
+ return;
+ }
+ ancestors.add( (TypeElement)parentElement);
+ collectAncestors((TypeElement)parentElement, ancestors, compInfo);
+ }
+ }
+
+ protected List getRestrictedTypes(Element element,
+ CompilationInfo compInfo , AtomicBoolean cancel)
+ {
+ AnnotationMirror typedMirror = AnnotationUtil.getAnnotationMirror(element,
+ AnnotationUtil.TYPED, compInfo);
+ if ( typedMirror == null ){
+ return null;
+ }
+ Map extends ExecutableElement, ? extends AnnotationValue> values =
+ typedMirror.getElementValues();
+ AnnotationValue restrictedTypes = null;
+ for (Entry extends ExecutableElement, ? extends AnnotationValue> entry :
+ values.entrySet() )
+ {
+ ExecutableElement key = entry.getKey();
+ AnnotationValue value = entry.getValue();
+ if ( AnnotationUtil.VALUE.contentEquals(key.getSimpleName())){
+ restrictedTypes = value;
+ break;
+ }
+ }
+ if ( restrictedTypes == null ){
+ return Collections.emptyList();
+ }
+ if ( cancel.get() ){
+ return Collections.emptyList();
+ }
+ Object value = restrictedTypes.getValue();
+ if ( value instanceof List> ){
+ List result = new ArrayList(((List>)value).size());
+ for( Object type : (List>)value){
+ AnnotationValue annotationValue = (AnnotationValue)type;
+ type = annotationValue.getValue();
+ if (type instanceof TypeMirror){
+ result.add( (TypeMirror)type);
+ }
+ }
+ return result;
+ }
+ return Collections.emptyList();
+ }
+
+ protected Set getUnrestrictedBeanTypes( TypeElement element,
+ CompilationInfo compInfo)
+ {
+ Set set = new HashSet();
+ set.add( element );
+ collectAncestors(element, set, compInfo);
+ return set;
+ }
+
+ protected Set getElements( Collection types ,
+ CompilationInfo info )
+ {
+ Set result = new HashSet();
+ for (TypeMirror typeMirror : types) {
+ Element element = info.getTypes().asElement(typeMirror);
+ if ( element instanceof TypeElement ){
+ result.add( (TypeElement)element);
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationElementAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationElementAnalyzer.java
new file mode 100644
index 000000000000..f80dccb6a85c
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationElementAnalyzer.java
@@ -0,0 +1,72 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.InterceptorBindingMembersAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.QualifierAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.ScopeAnalyzer;
+
+
+/**
+ * @author ads
+ *
+ */
+public class AnnotationElementAnalyzer implements ElementAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.ElementAnalyzer#analyze(javax.lang.model.element.Element, javax.lang.model.element.TypeElement, org.netbeans.api.java.source.CompilationInfo, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ TypeElement subject = (TypeElement) element;
+ for( AnnotationAnalyzer analyzer : ANALYZERS ){
+ if ( cancel.get() ){
+ return;
+ }
+ analyzer.analyze( subject, cancel , result );
+ }
+ }
+
+ public interface AnnotationAnalyzer {
+ public static final String INCORRECT_RUNTIME = "ERR_IncorrectRuntimeRetention"; //NOI18N
+
+ void analyze( TypeElement element , AtomicBoolean cancel,
+ CdiAnalysisResult result );
+ }
+
+ private static final List ANALYZERS =
+ new LinkedList();
+
+ static {
+ ANALYZERS.add( new ScopeAnalyzer() );
+ ANALYZERS.add( new QualifierAnalyzer() );
+ ANALYZERS.add( new InterceptorBindingMembersAnalyzer() );
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationModelAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationModelAnalyzer.java
new file mode 100644
index 000000000000..f5518d8cb18b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationModelAnalyzer.java
@@ -0,0 +1,69 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.InterceptorBindingAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.StereotypeAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public class AnnotationModelAnalyzer implements ModelAnalyzer {
+
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ TypeElement subject = (TypeElement) element;
+ for( AnnotationAnalyzer analyzer : ANALYZERS ){
+ if ( cancel.get() ){
+ return;
+ }
+ analyzer.analyze( subject, model, cancel, result );
+ }
+ }
+
+ public interface AnnotationAnalyzer {
+ public static final String INCORRECT_RUNTIME = "ERR_IncorrectRuntimeRetention"; //NOI18N
+
+ void analyze( TypeElement element , WebBeansModel model,
+ AtomicBoolean cancel,
+ Result result );
+ }
+
+ private static final List ANALYZERS =
+ new LinkedList();
+
+ static {
+ ANALYZERS.add( new StereotypeAnalyzer());
+ ANALYZERS.add( new InterceptorBindingAnalyzer() );
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationUtil.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationUtil.java
new file mode 100644
index 000000000000..c8436b029fce
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/AnnotationUtil.java
@@ -0,0 +1,217 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public final class AnnotationUtil {
+
+ public static final String ANY = "jakarta.enterprise.inject.Any"; // NOI18N
+
+ public static final String VALUE = "value"; // NOI18N
+
+ public static final String INJECT = "Inject"; // NOI18N
+
+ public static final String INJECT_FQN = "jakarta.inject."+INJECT; // NOI18N
+
+ public static final String DECORATOR = "jakarta.decorator.Decorator"; // NOI18N
+
+ public static final String PRODUCES = "Produces";
+
+ public static final String PRODUCES_FQN = "jakarta.enterprise.inject."+ // NOI18N
+ PRODUCES;
+
+ public static final String INTERCEPTOR_BINDING = "InterceptorBinding"; // NOI18N
+
+ public static final String INTERCEPTOR_BINDING_FQN
+ = "jakarta.interceptor."+INTERCEPTOR_BINDING; // NOI18N
+
+ public static final String INTERCEPTOR = "jakarta.interceptor.Interceptor"; // NOI18N
+
+ public static final String NORMAL_SCOPE = "NormalScope"; // NOI18N
+
+ public static final String NORMAL_SCOPE_FQN
+ = "jakarta.enterprise.context."+NORMAL_SCOPE;// NOI18N
+
+ public static final String SCOPE = "Scope"; // NOI18N
+
+ public static final String SCOPE_FQN = "jakarta.inject."+SCOPE; // NOI18N
+
+ public static final String REQUEST_SCOPE_FQN = "jakarta.enterprise.context.RequestScoped";// NOI18N
+ public static final String SESSION_SCOPE_FQN = "jakarta.enterprise.context.SessionScoped";// NOI18N
+ public static final String APPLICATION_SCOPE_FQN = "jakarta.enterprise.context.ApplicationScoped";// NOI18N
+ public static final String CONVERSATION_SCOPE_FQN = "jakarta.enterprise.context.ConversationScoped";// NOI18N
+ public static final String DEPENDENT_SCOPE_FQN = "jakarta.enterprise.context.Dependent";// NOI18N
+
+
+ public static final String DISPOSES = "Disposes"; // NOI18N
+
+ public static final String DISPOSES_FQN = "jakarta.enterprise.inject."+ // NOI18N
+ DISPOSES;
+
+ public static final String OBSERVES = "Observes"; // NOI18N
+
+ public static final String OBSERVES_FQN = "jakarta.enterprise.event."+ // NOI18N
+ OBSERVES;
+
+ public static final String STATELESS = "jakarta.ejb.Stateless"; // NOI18N
+
+ public static final String STATEFUL = "jakarta.ejb.Stateful"; // NOI18N
+
+ public static final String SINGLETON = "jakarta.ejb.Singleton"; // NOI18N
+ public static final String CDISINGLETON = "jakarta.inject.Singleton"; // NOI18N
+
+ public static final String APPLICATION_SCOPED
+ = "jakarta.enterprise.context.ApplicationScoped"; // NOI18N
+
+ public static final String DEPENDENT
+ = "jakarta.enterprise.context.Dependent"; // NOI18N
+
+ public static final String STEREOTYPE = "Stereotype"; // NOI18N
+
+ public static final String STEREOTYPE_FQN =
+ "jakarta.enterprise.inject."+STEREOTYPE; // NOI18N
+
+ public static final String NAMED = "jakarta.inject.Named"; // NOI18N
+
+ public static final String QUALIFIER = "Qualifier"; // NOI18N
+
+ public static final String QUALIFIER_FQN=
+ "jakarta.inject."+QUALIFIER; // NOI18N
+
+ public static final String DELEGATE_FQN =
+ "jakarta.decorator.Delegate"; // NOI18N
+
+ public static final String SPECIALIZES = "jakarta.enterprise.inject.Specializes"; // NOI18N
+
+ public static final String INJECTION_POINT =
+ "jakarta.enterprise.inject.spi.InjectionPoint"; // NOI18N
+
+ public static final String DEFAULT_FQN = "jakarta.enterprise.inject.Default"; // NOI18N
+
+ public static final String POST_CONSTRUCT = "jakarta.annotation.PostConstruct"; // NOI18N
+
+ public static final String PRE_DESTROY = "jakarta.annotation.PreDestroy"; // NOI18N
+
+ public static final String POST_ACTIVATE = "jakarta.ejb.PostActivate"; // NOI18N
+
+ public static final String PRE_PASSIVATE = "jakarta.ejb.PrePassivate"; // NOI18N
+
+ public static final String CONTEXT = "jakarta.enterprise.context.spi.Context"; // NOI18N
+
+ public static final String CONVERSATION = "jakarta.enterprise.context.Conversation";// NOI18N
+
+ public static final String ALTERNATVE = "jakarta.enterprise.inject.Alternative"; // NOI18N
+
+ public static final String TYPED = "jakarta.enterprise.inject.Typed"; // NOI18N
+
+ public static final String NON_BINDING = "jakarta.enterprise.util.Nonbinding"; // NOI18N
+
+ public static final String PASSIVATING = "passivating"; // NOI18N
+
+ public static final String PROVIDER = "jakarta.inject.Provider";// NOI18N
+
+ private AnnotationUtil(){
+ }
+
+ public static boolean hasAnnotation(Element element, String annotation,
+ CompilationInfo info )
+ {
+ return getAnnotationMirror(element, annotation, info)!=null;
+ }
+
+ public static AnnotationMirror getAnnotationMirror(Element element,
+ String annotation,CompilationInfo info )
+ {
+ return getAnnotationMirror(element, info, annotation);
+ }
+
+ /**
+ * return AnnotationMirror for first found annotation from annotationFqns
+ * @param element
+ * @param info
+ * @param annotationFqns
+ * @return
+ */
+ public static AnnotationMirror getAnnotationMirror(Element element,
+ CompilationInfo info , String... annotationFqns)
+ {
+ Set set = new HashSet();
+ Elements els = info.getElements();
+ for( String annotation : annotationFqns){
+ TypeElement annotationElement = els.getTypeElement(
+ annotation);
+ if ( annotationElement != null ){
+ set.add( annotationElement );
+ }
+ }
+
+ List extends AnnotationMirror> annotations =
+ els.getAllAnnotationMirrors( element );
+ for (AnnotationMirror annotationMirror : annotations) {
+ Element declaredAnnotation = info.getTypes().asElement(
+ annotationMirror.getAnnotationType());
+ if ( set.contains( declaredAnnotation ) ){
+ return annotationMirror;
+ }
+ }
+ return null;
+ }
+
+ public static boolean isSessionBean(Element element ,
+ CompilationInfo compInfo )
+ {
+ return getAnnotationMirror(element, compInfo, STATEFUL, STATELESS,
+ SINGLETON)!= null;
+ }
+
+ public static boolean isDelegate(Element element, TypeElement parent,
+ WebBeansModel model )
+ {
+ return AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.DELEGATE_FQN, model.getCompilationController())
+ && AnnotationUtil.hasAnnotation( parent,
+ AnnotationUtil.DECORATOR, model.getCompilationController());
+ }
+
+ public static boolean isLifecycleCallback( ExecutableElement element ,
+ CompilationInfo info )
+ {
+ AnnotationMirror annotationMirror = getAnnotationMirror(element, info,
+ POST_ACTIVATE, POST_CONSTRUCT , PRE_DESTROY, PRE_PASSIVATE);
+ return annotationMirror != null;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/Bundle.properties
new file mode 100644
index 000000000000..2fcfd0daeb80
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/Bundle.properties
@@ -0,0 +1,18 @@
+# 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.
+
+ERR_BadAnnotationParamCtor=A bean constructor should not have a parameter annotated @{0}.
\ No newline at end of file
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ClassElementAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ClassElementAnalyzer.java
new file mode 100644
index 000000000000..d054c4b97540
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ClassElementAnalyzer.java
@@ -0,0 +1,69 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.AnnotationsAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.CtorsAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.TypedClassAnalizer;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ClassElementAnalyzer implements ElementAnalyzer {
+
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.ElementAnalyzer#analyze(javax.lang.model.element.Element, javax.lang.model.element.TypeElement, org.netbeans.api.java.source.CompilationInfo, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ TypeElement subject = (TypeElement) element;
+ for( ClassAnalyzer analyzer : ANALYZERS ){
+ if ( cancel.get() ){
+ return;
+ }
+ analyzer.analyze( subject, parent, cancel, result );
+ }
+ }
+
+ public interface ClassAnalyzer {
+ void analyze( TypeElement element , TypeElement parent, AtomicBoolean cancel,
+ CdiAnalysisResult result );
+ }
+
+ private static final List ANALYZERS= new LinkedList();
+
+ static {
+ ANALYZERS.add( new TypedClassAnalizer() );
+ ANALYZERS.add( new AnnotationsAnalyzer());
+ ANALYZERS.add( new CtorsAnalyzer() );
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ClassModelAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ClassModelAnalyzer.java
new file mode 100644
index 000000000000..5619878d45dd
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ClassModelAnalyzer.java
@@ -0,0 +1,77 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.DeclaredIBindingsAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.InterceptedBeanAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.ManagedBeansAnalizer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.NamedModelAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.ScopedBeanAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type.SessionBeanAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ClassModelAnalyzer implements ModelAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer#analyze(javax.lang.model.element.Element, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ TypeElement subject = (TypeElement) element;
+ for( ClassAnalyzer analyzer : ANALYZERS ){
+ if ( cancel.get() ){
+ return;
+ }
+ analyzer.analyze( subject, parent, model, cancel, result);
+ }
+ }
+
+ public interface ClassAnalyzer {
+ void analyze( TypeElement element , TypeElement parent,
+ WebBeansModel model,AtomicBoolean cancel,
+ Result result );
+ }
+
+ private static final List ANALYZERS= new LinkedList();
+
+ static {
+ ANALYZERS.add( new ManagedBeansAnalizer());
+ ANALYZERS.add( new ScopedBeanAnalyzer());
+ ANALYZERS.add( new SessionBeanAnalyzer());
+ ANALYZERS.add( new InterceptedBeanAnalyzer() );
+ ANALYZERS.add( new NamedModelAnalyzer() );
+ ANALYZERS.add( new DeclaredIBindingsAnalyzer());
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/CtorAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/CtorAnalyzer.java
new file mode 100644
index 000000000000..2be7b4474e40
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/CtorAnalyzer.java
@@ -0,0 +1,67 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class CtorAnalyzer implements ElementAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.ElementAnalyzer#analyze(javax.lang.model.element.Element, javax.lang.model.element.TypeElement, org.netbeans.api.java.source.CompilationInfo, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ ExecutableElement ctor = (ExecutableElement)element;
+ List extends VariableElement> parameters = ctor.getParameters();
+ for (VariableElement param : parameters) {
+ if ( cancel.get() ){
+ return;
+ }
+ boolean isDisposer = AnnotationUtil.hasAnnotation(param,
+ AnnotationUtil.DISPOSES_FQN, result.getInfo());
+ boolean isObserver = AnnotationUtil.hasAnnotation(param,
+ AnnotationUtil.OBSERVES_FQN, result.getInfo());
+ if ( isDisposer || isObserver ){
+ result.requireCdiEnabled(element);
+ String annotation = isDisposer ? AnnotationUtil.DISPOSES :
+ AnnotationUtil.OBSERVES;
+ result.addError( element, NbBundle.getMessage(
+ CtorAnalyzer.class, "ERR_BadAnnotationParamCtor", annotation)); // NOI18N
+ break;
+ }
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ElementAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ElementAnalyzer.java
new file mode 100644
index 000000000000..05f042d51dd6
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ElementAnalyzer.java
@@ -0,0 +1,38 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+
+
+/**
+ * @author ads
+ *
+ */
+public interface ElementAnalyzer {
+
+ void analyze( Element element , TypeElement parent, AtomicBoolean cancel,
+ CdiAnalysisResult result );
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/FieldElementAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/FieldElementAnalyzer.java
new file mode 100644
index 000000000000..406509e67b12
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/FieldElementAnalyzer.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.DelegateFieldAnalizer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.ProducerFieldAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.TypedFieldAnalyzer;
+
+
+/**
+ * @author ads
+ *
+ */
+public class FieldElementAnalyzer implements ElementAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer#analyze(javax.lang.model.element.Element, javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ VariableElement var = (VariableElement) element;
+ TypeMirror varType = result.getInfo().getTypes().asMemberOf(
+ (DeclaredType)parent.asType(), var );
+ for (FieldAnalyzer analyzer : ANALYZERS) {
+ if ( cancel.get()){
+ return;
+ }
+ analyzer.analyze(var, varType, parent, cancel, result );
+ }
+ }
+
+ public interface FieldAnalyzer {
+ void analyze( VariableElement element , TypeMirror elementType,
+ TypeElement parent, AtomicBoolean cancel,
+ CdiAnalysisResult result );
+ }
+
+ private static final List ANALYZERS= new LinkedList();
+
+ static {
+ ANALYZERS.add( new TypedFieldAnalyzer() );
+ ANALYZERS.add( new DelegateFieldAnalizer());
+ ANALYZERS.add( new ProducerFieldAnalyzer());
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/FieldModelAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/FieldModelAnalyzer.java
new file mode 100644
index 000000000000..e8f5ca6a8a6e
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/FieldModelAnalyzer.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.InjectionPointAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.ScopedFieldAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public class FieldModelAnalyzer implements ModelAnalyzer {
+
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ VariableElement var = (VariableElement) element;
+ if ( cancel.get()){
+ return;
+ }
+ TypeMirror varType = model.getCompilationController().getTypes().asMemberOf(
+ (DeclaredType)parent.asType(), var );
+ for (FieldAnalyzer analyzer : ANALYZERS) {
+ if ( cancel.get()){
+ return;
+ }
+ analyzer.analyze(var, varType, parent, model, cancel, result );
+ }
+ }
+
+ public interface FieldAnalyzer {
+ void analyze( VariableElement element , TypeMirror elementType,
+ TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel, Result result );
+ }
+
+ private static final List ANALYZERS= new LinkedList();
+
+ static {
+ ANALYZERS.add( new ScopedFieldAnalyzer() );
+ ANALYZERS.add( new InjectionPointAnalyzer());
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/MethodElementAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/MethodElementAnalyzer.java
new file mode 100644
index 000000000000..fd7e08f9ccb9
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/MethodElementAnalyzer.java
@@ -0,0 +1,84 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.method.AnnotationsAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.method.DelegateMethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.method.ProducerMethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.method.TypedMethodAnalyzer;
+
+
+/**
+ * @author ads
+ *
+ */
+public class MethodElementAnalyzer implements ElementAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer#analyze(javax.lang.model.element.Element, javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ ExecutableElement method = (ExecutableElement) element;
+ TypeMirror methodType = result.getInfo().getTypes().asMemberOf(
+ (DeclaredType)parent.asType(), method );
+ if ( methodType instanceof ExecutableType ){
+ if ( cancel.get()){
+ return;
+ }
+ TypeMirror returnType = ((ExecutableType) methodType).getReturnType();
+ for (MethodAnalyzer analyzer : ANALYZERS) {
+ if ( cancel.get() ){
+ return;
+ }
+ analyzer.analyze(method, returnType, parent, cancel,
+ result );
+ }
+ }
+ }
+
+ public interface MethodAnalyzer {
+ void analyze( ExecutableElement element , TypeMirror returnType,
+ TypeElement parent, AtomicBoolean cancel , CdiAnalysisResult result );
+ }
+
+ private static final List ANALYZERS= new LinkedList();
+
+ static {
+ ANALYZERS.add( new TypedMethodAnalyzer() );
+ ANALYZERS.add( new AnnotationsAnalyzer() );
+ ANALYZERS.add( new DelegateMethodAnalyzer() );
+ ANALYZERS.add( new ProducerMethodAnalyzer() );
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/MethodModelAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/MethodModelAnalyzer.java
new file mode 100644
index 000000000000..d8e96fe62d8c
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/MethodModelAnalyzer.java
@@ -0,0 +1,81 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.method.InjectionPointParameterAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.method.InterceptedMethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.method.ScopedMethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+
+
+/**
+ * @author ads
+ *
+ */
+public class MethodModelAnalyzer implements ModelAnalyzer {
+
+ @Override
+ public void analyze( Element element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ ExecutableElement method = (ExecutableElement) element;
+ TypeMirror methodType = model.getCompilationController().getTypes().
+ asMemberOf( (DeclaredType)parent.asType(), method );
+ if ( methodType instanceof ExecutableType ){
+ if ( cancel.get()){
+ return;
+ }
+ TypeMirror returnType = ((ExecutableType) methodType).getReturnType();
+ for (MethodAnalyzer analyzer : ANALYZERS) {
+ if ( cancel.get() ){
+ return;
+ }
+ analyzer.analyze(method, returnType, parent, model,
+ cancel, result );
+ }
+ }
+ }
+
+ public interface MethodAnalyzer {
+ void analyze( ExecutableElement element , TypeMirror returnType,
+ TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel , Result result);
+ }
+
+ private static final List ANALYZERS= new LinkedList();
+
+ static {
+ ANALYZERS.add( new ScopedMethodAnalyzer() );
+ ANALYZERS.add( new InjectionPointParameterAnalyzer() );
+ ANALYZERS.add( new InterceptedMethodAnalyzer() );
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ModelAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ModelAnalyzer.java
new file mode 100644
index 000000000000..dda42f87590c
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/ModelAnalyzer.java
@@ -0,0 +1,126 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiEditorAnalysisFactory;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiEditorAwareJavaSourceTaskFactory;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Severity;
+
+
+/**
+ * @author ads
+ *
+ */
+public interface ModelAnalyzer {
+
+ void analyze( Element element , TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel, Result result );
+
+ public class Result extends CdiAnalysisResult {
+
+ public Result( CompilationInfo info ,
+ CdiEditorAwareJavaSourceTaskFactory factory )
+ {
+ super(info, factory);
+ }
+
+ public void addNotification( Severity severity, Element element,
+ WebBeansModel model, String message )
+ {
+ ErrorDescription description = CdiEditorAnalysisFactory.
+ createNotification( severity, element, model, getInfo() ,
+ message);
+ if ( description == null ){
+ return;
+ }
+ getProblems().add( description );
+ }
+
+ public void addNotification( Severity severity,
+ VariableElement element, ExecutableElement method,
+ WebBeansModel model, String message )
+ {
+ ErrorDescription description = CdiEditorAnalysisFactory.
+ createNotification( severity, element,method, model, getInfo() ,
+ message);
+ if ( description == null ){
+ return;
+ }
+ getProblems().add( description );
+ }
+
+ public void addError( Element element,
+ WebBeansModel model, String message )
+ {
+ addNotification(Severity.ERROR, element, model, message);
+ }
+
+ public void addError( VariableElement var, ExecutableElement element,
+ WebBeansModel model, String message )
+ {
+ addNotification(Severity.ERROR, var, element, model, message);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult#addError(javax.lang.model.element.Element, java.lang.String)
+ */
+ @Override
+ public void addError( Element subject, String message ) {
+ ErrorDescription description = CdiEditorAnalysisFactory.
+ createNotification( Severity.ERROR, subject, getInfo() ,
+ message);
+ if ( description == null ){
+ return;
+ }
+ getProblems().add( description );
+ }
+
+ public void requireCdiEnabled( Element element , WebBeansModel model){
+ ElementHandle handle = ElementHandle.create(element);
+ Element resolved = handle.resolve( getInfo() );
+ if ( resolved == null ){
+ return;
+ }
+ requireCdiEnabled( resolved );
+ }
+
+ public void requireCdiEnabled( VariableElement element ,
+ ExecutableElement method ,WebBeansModel model)
+ {
+ VariableElement resolved = CdiEditorAnalysisFactory.
+ resolveParameter(element, method, getInfo());
+ if ( resolved == null ){
+ return;
+ }
+ requireCdiEnabled( resolved );
+ }
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/Bundle.properties
new file mode 100644
index 000000000000..d1b1b910987c
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/Bundle.properties
@@ -0,0 +1,46 @@
+# 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.
+
+ERR_NonEmptyNamedStereotype=A stereotype should not declare a non-empty @Named annotation.
+ERR_IncorrectRuntimeRetention=The CDI annotation should be defined with @Retention(RUNTIME).
+ERR_NoTarget=The CDI annotation is defined with @{0} but has no @Target.
+ERR_NoRetention=The CDI annotation is defined with @{0} but has no @Retention.
+ERR_IncorrectScopeTarget=The CDI annotation is declared as Scope but has wrong target \
+value. Correct target values is '{METHOD, FIELD, TYPE'}.
+ERR_IncorrectInterceptorBindingTarget=The CDI Annotation is declared as Interceptor \
+Binding but it has wrong target values. Correct target values are '{METHOD, TYPE'} or TYPE.
+ERR_IncorrectStereotypeTarget=The CDI Annotation is declared as Stereotype but it has \
+wrong target values. Correct target values are are '{METHOD, FIELD, TYPE'} or \
+'{METHOD, FIELD'} or TYPE or METHOD or FIELD.
+ERR_IncorrectQualifierTarget=The CDI Annotation is declared as Qualifier but it \
+has wrong target values. Correct target values are \
+'{METHOD, FIELD, PARAMETER, TYPE'} or '{FIELD, PARAMETER'}.
+ERR_IncorrectTargetWithInterceptorBindings=A stereotype with interceptor binding \
+declared must be defined as @Target(TYPE).
+ERR_IncorrectTransitiveInterceptorBinding=Interceptor binding is defined as \
+@Target('{TYPE, METHOD'}) and declares interceptor binding {0} which is defined as \
+@Target(TYPE).
+ERR_IncorrectTransitiveTarget=Stereotypes @{0} declared @Target('{TYPE'}) and may not \
+be applied to stereotypes declared @Target('{TYPE, METHOD, FIELD'}), @Target('{METHOD'}), \
+@Target('{FIELD'}) or @Target('{METHOD, FIELD'}).
+WARN_QualifiedStereotype=A stereotype should not declare any qualifier annotation \
+other than @Named. Otherwise non-portable behavior results.
+WARN_TypedStereotype=A stereotype should not be annotated @Typed. Otherwise non-portable behavior results.
+WARN_ArrayAnnotationValuedQualifierMember=Array-valued or annotation-valued members \
+of a qualifier type should be annotated @Nonbinding. Otherwise non-portable behavior results.
+WARN_ArrayAnnotationValuedIBindingMember=Array-valued or annotation-valued members of \
+an interceptor binding type should be annotated @Nonbinding. Otherwise non-portable behavior results.
\ No newline at end of file
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/CdiAnnotationAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/CdiAnnotationAnalyzer.java
new file mode 100644
index 000000000000..3f014c227496
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/CdiAnnotationAnalyzer.java
@@ -0,0 +1,101 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+abstract class CdiAnnotationAnalyzer extends TargetAnalyzer {
+
+ CdiAnnotationAnalyzer(TypeElement element, CdiAnalysisResult result )
+ {
+ init( element , result.getInfo() );
+ myResult =result;
+ }
+
+ CdiAnnotationAnalyzer(TypeElement element, WebBeansModel model,
+ CdiAnalysisResult result )
+ {
+ init( element , model.getCompilationController() );
+ myModel = model;
+ myResult =result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.TargetAnalyzer#handleNoTarget()
+ */
+ @Override
+ protected void handleNoTarget() {
+ if ( myResult== null){
+ return;
+ }
+ Element subject = getElement();
+ if ( myModel != null ){
+ ElementHandle handle = ElementHandle.create( getElement());
+ subject = handle.resolve(getResult().getInfo());
+ }
+ if ( subject == null ){
+ return;
+ }
+ myResult.addError( subject, NbBundle.getMessage(ScopeAnalyzer.class,
+ "ERR_NoTarget" , // NOI18N
+ getCdiMetaAnnotation()));
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.RuntimeRetentionAnalyzer#handleNoRetention()
+ */
+ @Override
+ protected void handleNoRetention() {
+ if ( myResult== null){
+ return;
+ }
+ Element subject = getElement();
+ if ( myModel != null ){
+ ElementHandle handle = ElementHandle.create( getElement());
+ subject = handle.resolve(getResult().getInfo());
+ }
+ if ( subject == null ){
+ return;
+ }
+ myResult.addError( subject, NbBundle.getMessage(ScopeAnalyzer.class,
+ "ERR_NoRetention", // NOI18N
+ getCdiMetaAnnotation()));
+ }
+
+ protected abstract String getCdiMetaAnnotation();
+
+ protected CdiAnalysisResult getResult(){
+ return myResult;
+ }
+
+ private WebBeansModel myModel;
+ private CdiAnalysisResult myResult;
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingAnalyzer.java
new file mode 100644
index 000000000000..acb4181c2b9b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingAnalyzer.java
@@ -0,0 +1,146 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationModelAnalyzer.AnnotationAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class InterceptorBindingAnalyzer implements AnnotationAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationModelAnalyzer.AnnotationAnalyzer#analyze(javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, WebBeansModel model,
+ AtomicBoolean cancel ,
+ Result result )
+ {
+ if ( !AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.INTERCEPTOR_BINDING_FQN , model.getCompilationController()))
+ {
+ return;
+ }
+ result.requireCdiEnabled(element, model);
+ InterceptorTargetAnalyzer analyzer = new InterceptorTargetAnalyzer(
+ element, model, result );
+ if ( cancel.get() ){
+ return;
+ }
+ if (!analyzer.hasRuntimeRetention()) {
+ result.addError(element, model,
+ NbBundle.getMessage(InterceptorBindingAnalyzer.class,
+ INCORRECT_RUNTIME));
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ if (!analyzer.hasTarget()) {
+ result.addError(element, model,
+ NbBundle.getMessage(InterceptorBindingAnalyzer.class,
+ "ERR_IncorrectInterceptorBindingTarget")); // NOI18N
+ }
+ else {
+ if ( cancel.get() ){
+ return;
+ }
+ Set declaredTargetTypes = analyzer.getDeclaredTargetTypes();
+ if ( cancel.get() ){
+ return;
+ }
+ checkTransitiveInterceptorBindings( element, declaredTargetTypes,
+ model , result );
+ }
+ }
+
+ private void checkTransitiveInterceptorBindings( TypeElement element,
+ Set declaredTargetTypes, WebBeansModel model,
+ Result result )
+ {
+ if (declaredTargetTypes == null || declaredTargetTypes.size() == 1) {
+ return;
+ }
+ Collection interceptorBindings = model
+ .getInterceptorBindings(element);
+ for (AnnotationMirror iBinding : interceptorBindings) {
+ Element binding = iBinding.getAnnotationType().asElement();
+ if (!(binding instanceof TypeElement)) {
+ continue;
+ }
+ Set bindingTargetTypes = TargetAnalyzer
+ .getDeclaredTargetTypes(
+ new AnnotationHelper(model
+ .getCompilationController()),
+ (TypeElement) binding);
+ if (bindingTargetTypes.size() == 1
+ && bindingTargetTypes.contains(ElementType.TYPE))
+ {
+ result.addError(element, model ,
+ NbBundle.getMessage(InterceptorBindingAnalyzer.class,
+ "ERR_IncorrectTransitiveInterceptorBinding", // NOI18N
+ ((TypeElement) binding).getQualifiedName().toString()));
+ }
+
+ }
+ }
+
+ private static class InterceptorTargetAnalyzer extends CdiAnnotationAnalyzer {
+
+ InterceptorTargetAnalyzer( TypeElement element , WebBeansModel model ,
+ Result result)
+ {
+ super( element, model , result );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.CdiAnnotationAnalyzer#getCdiMetaAnnotation()
+ */
+ @Override
+ protected String getCdiMetaAnnotation() {
+ return AnnotationUtil.INTERCEPTOR_BINDING;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.TargetAnalyzer#getTargetVerifier()
+ */
+ @Override
+ protected TargetVerifier getTargetVerifier() {
+ return InterceptorBindingVerifier.getInstance();
+ }
+
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingMembersAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingMembersAnalyzer.java
new file mode 100644
index 000000000000..30bb55d24b44
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingMembersAnalyzer.java
@@ -0,0 +1,90 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationElementAnalyzer.AnnotationAnalyzer;
+import org.openide.util.NbBundle;
+import org.netbeans.spi.editor.hints.Severity;
+
+
+
+/**
+ * @author ads
+ *
+ */
+public class InterceptorBindingMembersAnalyzer implements AnnotationAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationElementAnalyzer.AnnotationAnalyzer#analyze(javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult)
+ */
+ @Override
+ public void analyze( TypeElement element, AtomicBoolean cancel,
+ CdiAnalysisResult result )
+ {
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.INTERCEPTOR_BINDING_FQN,
+ result.getInfo()))
+ {
+ checkMembers(element, result, NbBundle.getMessage(
+ QualifierAnalyzer.class,
+ "WARN_ArrayAnnotationValuedIBindingMember")); // NOI18N
+ }
+ }
+
+ protected void checkMembers( TypeElement element, CdiAnalysisResult result ,
+ String localizedWarning )
+ {
+ List methods = ElementFilter.methodsIn(
+ element.getEnclosedElements());
+ for (ExecutableElement executableElement : methods) {
+ TypeMirror returnType = executableElement.getReturnType();
+ boolean warning = false;
+ if ( returnType.getKind() == TypeKind.ARRAY ){
+ warning = true;
+ }
+ else if ( returnType.getKind() == TypeKind.DECLARED){
+ Element returnElement = result.getInfo().getTypes().asElement(
+ returnType );
+ warning = returnElement.getKind() == ElementKind.ANNOTATION_TYPE;
+ }
+ if ( !warning ){
+ continue;
+ }
+ if (AnnotationUtil.hasAnnotation(executableElement,
+ AnnotationUtil.NON_BINDING, result.getInfo()) )
+ {
+ continue;
+ }
+ result.addNotification(Severity.WARNING, element, localizedWarning);
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingVerifier.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingVerifier.java
new file mode 100644
index 000000000000..3cd27b778d6d
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/InterceptorBindingVerifier.java
@@ -0,0 +1,63 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+
+
+/**
+ * @author ads
+ *
+ */
+public class InterceptorBindingVerifier implements TargetVerifier {
+
+ private InterceptorBindingVerifier(){
+ }
+
+ private static final InterceptorBindingVerifier INSTANCE =
+ new InterceptorBindingVerifier();
+
+ public static InterceptorBindingVerifier getInstance(){
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean hasReqiredTarget( AnnotationMirror target , Set
+ targetTypes )
+ {
+ int sz = 1;
+ if(targetTypes.size()>0){
+ sz = targetTypes.size();
+ if(targetTypes.contains( ElementType.TYPE)){
+ sz--;
+ }
+ if ( targetTypes.contains( ElementType.METHOD)) {
+ sz--;
+ }
+ if (targetTypes.contains( ElementType.CONSTRUCTOR) )
+ {
+ sz--;
+ }
+ }
+ return sz==0;
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/QualifierAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/QualifierAnalyzer.java
new file mode 100644
index 000000000000..169c61e35cee
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/QualifierAnalyzer.java
@@ -0,0 +1,101 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationElementAnalyzer.AnnotationAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.openide.util.NbBundle;
+import org.netbeans.spi.editor.hints.Severity;
+
+
+/**
+ * @author ads
+ *
+ */
+public class QualifierAnalyzer extends InterceptorBindingMembersAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationElementAnalyzer.AnnotationAnalyzer#analyze(javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( TypeElement element, AtomicBoolean cancel,
+ CdiAnalysisResult result )
+ {
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.QUALIFIER_FQN,
+ result.getInfo()))
+ {
+ result.requireCdiEnabled(element);
+ QualifierTargetAnalyzer analyzer = new QualifierTargetAnalyzer(element,
+ result );
+ if ( !analyzer.hasRuntimeRetention() ){
+ result.addError( element,
+ NbBundle.getMessage(QualifierTargetAnalyzer.class,
+ INCORRECT_RUNTIME));
+ }
+ if ( !analyzer.hasTarget()){
+ result.addError( element,
+ NbBundle.getMessage(QualifierTargetAnalyzer.class,
+ "ERR_IncorrectQualifierTarget")); // NOI18N
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ checkMembers( element, result , NbBundle.getMessage(
+ QualifierAnalyzer.class,
+ "WARN_ArrayAnnotationValuedQualifierMember")); // NOI18N
+ }
+ }
+
+ private static class QualifierTargetAnalyzer extends CdiAnnotationAnalyzer{
+
+ QualifierTargetAnalyzer( TypeElement element, CdiAnalysisResult result)
+ {
+ super(element, result);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.CdiAnnotationAnalyzer#getCdiMetaAnnotation()
+ */
+ @Override
+ protected String getCdiMetaAnnotation() {
+ return AnnotationUtil.QUALIFIER;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.TargetAnalyzer#getTargetVerifier()
+ */
+ @Override
+ protected TargetVerifier getTargetVerifier() {
+ return QualifierVerifier.getInstance( true );
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/QualifierVerifier.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/QualifierVerifier.java
new file mode 100644
index 000000000000..459977029d48
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/QualifierVerifier.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+
+
+/**
+ * @author ads
+ *
+ */
+public class QualifierVerifier implements TargetVerifier {
+
+
+ private static final QualifierVerifier INSTANCE = new QualifierVerifier( false );
+
+ private static final QualifierVerifier EVENT_INSTANCE =
+ new QualifierVerifier( true );
+
+ private QualifierVerifier(boolean event){
+ isEvent = event;
+ }
+
+ public static QualifierVerifier getInstance( boolean event ){
+ if ( event ){
+ return EVENT_INSTANCE;
+ }
+ else {
+ return INSTANCE;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.TargetVerifier#hasReqiredTarget(javax.lang.model.element.AnnotationMirror, java.util.Set)
+ */
+ @Override
+ public boolean hasReqiredTarget( AnnotationMirror target,
+ Set targetTypes )
+ {
+ boolean hasRequiredTarget = false;
+// if ( isEvent() ){ TODO: any reason why it was different, ins specification event qualifier is just the same as usual, and example have 4 targets but it's just example? see #225556
+ //especially it was updated for evvents before but specification is new for all qualifiers. keep for now commented
+ boolean hasFieldParameterTarget = targetTypes.contains(
+ ElementType.FIELD) &&
+ targetTypes.contains(ElementType.PARAMETER);
+ if ( !hasFieldParameterTarget){
+ hasRequiredTarget = (targetTypes.size() == 1 &&
+ (targetTypes.contains(ElementType.TYPE) ||
+ targetTypes.contains(ElementType.METHOD) ||
+ targetTypes.contains(ElementType.FIELD))) ||
+ (targetTypes.size() == 2 &&
+ targetTypes.contains(ElementType.METHOD) &&
+ targetTypes.contains(ElementType.FIELD));//see #244059
+ }
+ else {
+ if ( targetTypes.size() == 2 ){
+ hasRequiredTarget = true;
+ }
+ else {
+ hasRequiredTarget =
+ (targetTypes.size() == 4 &&
+ targetTypes.contains( ElementType.METHOD) &&
+ targetTypes.contains( ElementType.TYPE)) ||
+ (targetTypes.size() == 3 &&
+ targetTypes.contains( ElementType.METHOD));
+ }
+ }
+// }
+// else {
+// hasRequiredTarget = targetTypes.size() == 4 &&
+// targetTypes.contains( ElementType.METHOD) &&
+// targetTypes.contains(ElementType.FIELD) &&
+// targetTypes.contains(ElementType.PARAMETER)&&
+// targetTypes.contains( ElementType.TYPE);
+// }
+
+ return hasRequiredTarget;
+ }
+
+ private boolean isEvent(){
+ return isEvent;
+ }
+
+ private boolean isEvent;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/RuntimeRetentionAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/RuntimeRetentionAnalyzer.java
new file mode 100644
index 000000000000..8d297fab7f65
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/RuntimeRetentionAnalyzer.java
@@ -0,0 +1,79 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.parser.AnnotationParser;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class RuntimeRetentionAnalyzer {
+
+ public void init( Element element, AnnotationHelper helper ) {
+ myHelper = helper;
+ myElement = element;
+ }
+
+ public void init( Element element, CompilationInfo info ) {
+ init( element , new AnnotationHelper(info));
+ }
+
+ public boolean hasRuntimeRetention() {
+ Map types = getHelper()
+ .getAnnotationsByType(getElement().getAnnotationMirrors());
+ AnnotationMirror retention = types.get(Retention.class.getCanonicalName());
+ if ( retention == null ) {
+ handleNoRetention();
+ return false;
+ }
+
+ AnnotationParser parser = AnnotationParser.create(getHelper());
+ parser.expectEnumConstant(AnnotationUtil.VALUE, getHelper().resolveType(
+ RetentionPolicy.class.getCanonicalName()), null);
+
+ String retentionPolicy = parser.parse(retention).get(AnnotationUtil.VALUE,
+ String.class);
+ return RetentionPolicy.RUNTIME.toString().equals(retentionPolicy);
+ }
+
+ protected abstract void handleNoRetention();
+
+ protected Element getElement(){
+ return myElement;
+ }
+
+ protected AnnotationHelper getHelper(){
+ return myHelper;
+ }
+
+ private AnnotationHelper myHelper;
+ private Element myElement;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/ScopeAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/ScopeAnalyzer.java
new file mode 100644
index 000000000000..616fc5f8d7ce
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/ScopeAnalyzer.java
@@ -0,0 +1,106 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationElementAnalyzer.AnnotationAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ScopeAnalyzer implements AnnotationAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationElementAnalyzer.AnnotationAnalyzer#analyze(javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( TypeElement element, AtomicBoolean cancel,
+ CdiAnalysisResult result)
+ {
+ CompilationInfo compInfo = result.getInfo();
+ boolean isScope = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.SCOPE_FQN , compInfo);
+ boolean isNormalScope = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.NORMAL_SCOPE_FQN, compInfo);
+ if ( isScope || isNormalScope ){
+ result.requireCdiEnabled(element);
+ ScopeTargetAnalyzer analyzer = new ScopeTargetAnalyzer(element,
+ result, isNormalScope);
+ if ( cancel.get() ){
+ return;
+ }
+ if ( !analyzer.hasRuntimeRetention() ){
+ result.addError( element,
+ NbBundle.getMessage(ScopeAnalyzer.class,
+ INCORRECT_RUNTIME));
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ if ( !analyzer.hasTarget()){
+ result.addError( element,
+ NbBundle.getMessage(ScopeAnalyzer.class,
+ "ERR_IncorrectScopeTarget")); // NOI18N
+ }
+ }
+ }
+
+ private static class ScopeTargetAnalyzer extends CdiAnnotationAnalyzer {
+
+ ScopeTargetAnalyzer(TypeElement element, CdiAnalysisResult result,
+ boolean normalScope )
+ {
+ super( element , result );
+ isNormalScope = normalScope;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.TargetAnalyzer#getTargetVerifier()
+ */
+ @Override
+ protected TargetVerifier getTargetVerifier() {
+ return ScopeVerifier.getInstance();
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.CdiAnnotationAnalyzer#getCdiMetaAnnotation()
+ */
+ @Override
+ protected String getCdiMetaAnnotation() {
+ if ( isNormalScope ){
+ return AnnotationUtil.NORMAL_SCOPE;
+ }
+ else {
+ return AnnotationUtil.SCOPE;
+ }
+ }
+
+ private boolean isNormalScope;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/ScopeVerifier.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/ScopeVerifier.java
new file mode 100644
index 000000000000..a816832c5906
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/ScopeVerifier.java
@@ -0,0 +1,56 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ScopeVerifier implements TargetVerifier {
+
+ private static final ScopeVerifier INSTANCE = new ScopeVerifier();
+
+ private ScopeVerifier( ){
+ }
+
+ public static ScopeVerifier getInstance(){
+ return INSTANCE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.TargetVerifier#hasReqiredTarget(javax.lang.model.element.AnnotationMirror, java.util.Set)
+ */
+ @Override
+ public boolean hasReqiredTarget( AnnotationMirror target,
+ Set targetTypes )
+ {
+ boolean hasRequiredTarget = targetTypes.contains(
+ ElementType.METHOD) &&
+ targetTypes.contains(ElementType.FIELD) &&
+ targetTypes.contains( ElementType.TYPE);
+ return hasRequiredTarget;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/StereotypeAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/StereotypeAnalyzer.java
new file mode 100644
index 000000000000..7135d923c833
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/StereotypeAnalyzer.java
@@ -0,0 +1,262 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationModelAnalyzer.AnnotationAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.impl.model.WebBeansModelProviderImpl;
+import org.openide.util.NbBundle;
+import org.netbeans.spi.editor.hints.Severity;
+
+
+/**
+ * @author ads
+ *
+ */
+public class StereotypeAnalyzer extends AbstractScopedAnalyzer implements AnnotationAnalyzer {
+
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationModelAnalyzer.AnnotationAnalyzer#analyze(javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, WebBeansModel model ,
+ AtomicBoolean cancel ,
+ Result result)
+ {
+ boolean isStereotype = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.STEREOTYPE_FQN, model.getCompilationController());
+ if ( !isStereotype ){
+ return;
+ }
+ result.requireCdiEnabled(element, model);
+ if ( cancel.get() ){
+ return;
+ }
+ analyzeScope((Element)element, model, cancel, result );
+ if (cancel.get() ){
+ return;
+ }
+ checkName( element, model, result );
+ if ( cancel.get() ){
+ return;
+ }
+ Set targets = checkDefinition( element , model, result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkInterceptorBindings( element , targets, model , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkTransitiveStereotypes( element , targets, model , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkTyped( element , model , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkQualifers( element , model, result );
+ }
+
+ private void checkQualifers( TypeElement element, WebBeansModel model,
+ Result result )
+ {
+ List qualifiers = model.getQualifiers(element, true);
+ for (AnnotationMirror annotationMirror : qualifiers) {
+ Element annotation = annotationMirror.getAnnotationType().asElement();
+ if ( annotation instanceof TypeElement &&
+ ((TypeElement)annotation).getQualifiedName().contentEquals(
+ AnnotationUtil.NAMED))
+ {
+ continue;
+ }
+ else {
+ result.addNotification( Severity.WARNING , element, model,
+ NbBundle.getMessage(StereotypeAnalyzer.class,
+ "WARN_QualifiedStereotype")); // NOI18N
+ break;
+ }
+ }
+ }
+
+ private void checkTyped( TypeElement element, WebBeansModel model,
+ Result result )
+ {
+ AnnotationMirror typed = AnnotationUtil.getAnnotationMirror(element,
+ model.getCompilationController(), AnnotationUtil.TYPED);
+ if ( typed != null ){
+ result.addNotification( Severity.WARNING , element, model,
+ NbBundle.getMessage(StereotypeAnalyzer.class,
+ "WARN_TypedStereotype")); // NOI18N
+ }
+ }
+
+ private void checkTransitiveStereotypes( TypeElement element,
+ final Set targets, WebBeansModel model,
+ Result result )
+ {
+ AnnotationHelper helper = new AnnotationHelper(
+ model.getCompilationController());
+ List stereotypes = WebBeansModelProviderImpl
+ .getAllStereotypes(element, helper);
+ for (AnnotationMirror stereotypeAnnotation : stereotypes) {
+ Element annotationElement = stereotypeAnnotation
+ .getAnnotationType().asElement();
+ if (annotationElement instanceof TypeElement) {
+ TypeElement stereotype = (TypeElement) annotationElement;
+ Set declaredTargetTypes = TargetAnalyzer
+ .getDeclaredTargetTypes(helper, stereotype);
+ if (declaredTargetTypes != null
+ && declaredTargetTypes.size() == 1
+ && declaredTargetTypes.contains(ElementType.TYPE))
+ {
+ if (targets.size() == 1
+ && targets.contains(ElementType.TYPE))
+ {
+ continue;
+ }
+ else {
+ String fqn = stereotype.getQualifiedName().toString();
+ result.addError(element, model,
+ NbBundle.getMessage(
+ StereotypeAnalyzer.class,
+ "ERR_IncorrectTransitiveTarget", // NOI18N
+ fqn));
+ }
+ }
+ }
+ }
+ }
+
+ private void checkInterceptorBindings( TypeElement element,
+ Set targets, WebBeansModel model,
+ Result result )
+ {
+ if (targets == null) {
+ return;
+ }
+ if (targets.size() == 1 && targets.contains(ElementType.TYPE)) {
+ return;
+ }
+ int interceptorsCount = model.getInterceptorBindings(element).size();
+ if (interceptorsCount != 0) {
+ result.addError(element,model,
+ NbBundle.getMessage(StereotypeAnalyzer.class,
+ "ERR_IncorrectTargetWithInterceptorBindings")); // NOI18N
+ }
+ }
+
+ private Set checkDefinition( TypeElement element,
+ WebBeansModel model , Result result )
+ {
+ StereotypeTargetAnalyzer analyzer = new StereotypeTargetAnalyzer(element,
+ model, result );
+ if ( !analyzer.hasRuntimeRetention()){
+ result.addError( element, model,
+ NbBundle.getMessage(StereotypeAnalyzer.class,
+ INCORRECT_RUNTIME));
+ }
+ if ( !analyzer.hasTarget()){
+ result.addError( element, model,
+ NbBundle.getMessage(StereotypeAnalyzer.class,
+ "ERR_IncorrectStereotypeTarget")); // NOI18N
+ return null;
+ }
+ else {
+ return analyzer.getDeclaredTargetTypes();
+ }
+ }
+
+ private void checkName( TypeElement element, WebBeansModel model,
+ Result result )
+ {
+ AnnotationMirror named = AnnotationUtil.getAnnotationMirror(element,
+ AnnotationUtil.NAMED , model.getCompilationController());
+ if ( named == null ){
+ return;
+ }
+ Map extends ExecutableElement, ? extends AnnotationValue> members =
+ named.getElementValues();
+ for (Entry extends ExecutableElement, ? extends AnnotationValue> entry:
+ members.entrySet())
+ {
+ ExecutableElement member = entry.getKey();
+ if ( member.getSimpleName().contentEquals(AnnotationUtil.VALUE)){
+ result.addError( element, model,
+ NbBundle.getMessage(StereotypeAnalyzer.class,
+ "ERR_NonEmptyNamedStereotype")); // NOI18N
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer#checkScope(javax.lang.model.element.TypeElement, javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ protected void checkScope( TypeElement scopeElement, Element element,
+ WebBeansModel model, AtomicBoolean cancel , Result result )
+ {
+ }
+
+ private static class StereotypeTargetAnalyzer extends CdiAnnotationAnalyzer{
+
+ StereotypeTargetAnalyzer( TypeElement element, WebBeansModel model,
+ Result result )
+ {
+ super(element, model, result );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.CdiAnnotationAnalyzer#getCdiMetaAnnotation()
+ */
+ @Override
+ protected String getCdiMetaAnnotation() {
+ return AnnotationUtil.STEREOTYPE;
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.annotation.TargetAnalyzer#getTargetVerifier()
+ */
+ @Override
+ protected TargetVerifier getTargetVerifier() {
+ return StereotypeVerifier.getInstance();
+ }
+
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/StereotypeVerifier.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/StereotypeVerifier.java
new file mode 100644
index 000000000000..f017ff6d47cb
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/StereotypeVerifier.java
@@ -0,0 +1,68 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+
+
+/**
+ * @author ads
+ *
+ */
+public class StereotypeVerifier implements TargetVerifier {
+
+ private static final StereotypeVerifier INSTANCE = new StereotypeVerifier();
+
+ private StereotypeVerifier(){
+ }
+
+ public static StereotypeVerifier getInstance(){
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean hasReqiredTarget( AnnotationMirror target,
+ Set targetTypes )
+ {
+ boolean hasRequiredTarget = false;
+ if ( targetTypes.contains( ElementType.METHOD) &&
+ targetTypes.contains(ElementType.FIELD) &&
+ targetTypes.contains( ElementType.TYPE)
+ && targetTypes.size() == 3)
+ {
+ hasRequiredTarget = true;
+ }
+ else if ( targetTypes.size() == 2 &&
+ targetTypes.contains( ElementType.METHOD) &&
+ targetTypes.contains(ElementType.FIELD))
+ {
+ hasRequiredTarget = true;
+ }
+ else if ( targetTypes.size() == 1 ){
+ hasRequiredTarget = targetTypes.contains( ElementType.METHOD) ||
+ targetTypes.contains( ElementType.FIELD) ||
+ targetTypes.contains( ElementType.TYPE);
+ }
+ return hasRequiredTarget;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/TargetAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/TargetAnalyzer.java
new file mode 100644
index 000000000000..91add8f98891
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/TargetAnalyzer.java
@@ -0,0 +1,123 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.parser.AnnotationParser;
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.parser.ArrayValueHandler;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class TargetAnalyzer extends RuntimeRetentionAnalyzer
+ implements TargetVerifier
+{
+
+ public boolean hasTarget() {
+ Map types = getHelper()
+ .getAnnotationsByType(getElement().getAnnotationMirrors());
+ AnnotationMirror target = types.get(Target.class.getCanonicalName());
+ if (target == null) {
+ handleNoTarget();
+ }
+ return hasReqiredTarget( target , getDeclaredTargetTypes( getHelper(),
+ target ));
+ }
+
+ public Set getDeclaredTargetTypes() {
+ Map types = getHelper()
+ .getAnnotationsByType(getElement().getAnnotationMirrors());
+ AnnotationMirror target = types.get(Target.class.getCanonicalName());
+ if (target == null) {
+ return Collections.emptySet();
+ }
+ return getDeclaredTargetTypes( getHelper(), target );
+ }
+
+ public static Set getDeclaredTargetTypes(
+ AnnotationHelper helper, TypeElement element )
+ {
+ Map types = helper
+ .getAnnotationsByType(element.getAnnotationMirrors());
+ AnnotationMirror target = types.get(Target.class.getCanonicalName());
+ if (target == null) {
+ return Collections.emptySet();
+ }
+ return getDeclaredTargetTypes( helper, target );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.TargetVerifier#hasReqiredTarget(javax.lang.model.element.AnnotationMirror, java.util.Set)
+ */
+ @Override
+ public boolean hasReqiredTarget( AnnotationMirror target,
+ Set set )
+ {
+ return getTargetVerifier().hasReqiredTarget(target, set );
+ }
+
+ protected abstract TargetVerifier getTargetVerifier();
+
+ protected abstract void handleNoTarget();
+
+ private static Set getDeclaredTargetTypes(
+ AnnotationHelper helper, AnnotationMirror target)
+ {
+ AnnotationParser parser = AnnotationParser.create(helper);
+ final Set elementTypes = new HashSet();
+ parser.expectEnumConstantArray( AnnotationUtil.VALUE,
+ helper.resolveType(
+ ElementType.class.getCanonicalName()),
+ new ArrayValueHandler() {
+
+ @Override
+ public Object handleArray( List arrayMembers ) {
+ for (AnnotationValue arrayMember : arrayMembers) {
+ String value = arrayMember.getValue().toString();
+ elementTypes.add(value);
+ }
+ return null;
+ }
+ } , null);
+
+ parser.parse( target );
+ Set result = new HashSet();
+ for (String type : elementTypes) {
+ ElementType elementType = ElementType.valueOf(ElementType.class, type);
+ result.add( elementType );
+ }
+ return result;
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/TargetVerifier.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/TargetVerifier.java
new file mode 100644
index 000000000000..00ad26e90fd1
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/annotation/TargetVerifier.java
@@ -0,0 +1,35 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation;
+
+import java.lang.annotation.ElementType;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationMirror;
+
+
+/**
+ * @author ads
+ *
+ */
+public interface TargetVerifier {
+
+ boolean hasReqiredTarget(AnnotationMirror target, Set targetTypes);
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/Bundle.properties
new file mode 100644
index 000000000000..60bbef26f1e8
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/Bundle.properties
@@ -0,0 +1,48 @@
+# 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.
+
+ERR_BadRestritedFieldType=Field\'s bean class specifies @Typed annotation, \
+and the value member specifies a class which does not correspond to a type in \
+the unrestricted set of bean types of a bean.
+ERR_DelegateHasNoInject=Field is declared as @Delegate but it is not an injection point.
+ERR_DelegateIsNotInDecorator=Field is declared as @Delegate but its enclosing \
+type element is not a decorator.
+ERR_NonStaticProducerSessionBean=A producer field must be a static field of the \
+session bean class.
+
+ERR_ProducerHasTypeVar=A producer field type should not be a type variable.
+ERR_ProducerHasWildcard=A producer field type should not contain a wildcard type parameter.
+
+ERR_WrongScopeParameterizedProducer=The producer field has parameterized type \
+with a type variable and has scope {0} (should be @Dependent).
+
+ERR_WrongQualifierInjectionPointMeta=An injection point has type InjectionPoint \
+and qualifier @Default but bean declares not @Dependent scope.
+
+ERR_DelegateTypeHasNoDecoratedType=The delegate type of a decorator must implement \
+or extend every decorated type of decorator.
+
+ERR_FinalDecoratedBean=Delegate injection point matches a managed bean {0} \
+which class is declared final.
+
+ERR_FinalMethodDecoratedBean=Delegate injection point matches a managed bean {0} \
+with final method {1} which is implemented by decorator.
+
+WARN_NamedInjectionPoint=The use of @Named as an injection point qualifier is not recommended.
+
+ERR_NotPassivationProducer=Producer field has a passivating scope {0} and should be \
+passivation capable. But its type is declared final and does not implement Serializable.
\ No newline at end of file
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/DelegateFieldAnalizer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/DelegateFieldAnalizer.java
new file mode 100644
index 000000000000..a3169a7de804
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/DelegateFieldAnalizer.java
@@ -0,0 +1,133 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.field;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldElementAnalyzer.FieldAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class DelegateFieldAnalizer implements FieldAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldElementAnalyzer.FieldAnalyzer#analyze(javax.lang.model.element.VariableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, org.netbeans.api.java.source.CompilationInfo, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( VariableElement element, TypeMirror elementType,
+ TypeElement parent, AtomicBoolean cancel,
+ CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ if (!AnnotationUtil.hasAnnotation(element, AnnotationUtil.DELEGATE_FQN,
+ compInfo))
+ {
+ return;
+ }
+ result.requireCdiEnabled(element);
+ if (!AnnotationUtil.hasAnnotation(element, AnnotationUtil.INJECT_FQN,
+ compInfo))
+ {
+ result.addError(element, NbBundle.getMessage(
+ DelegateFieldAnalizer.class,
+ "ERR_DelegateHasNoInject")); // NOI18N
+ }
+ Element clazz = element.getEnclosingElement();
+ if (!AnnotationUtil.hasAnnotation(clazz, AnnotationUtil.DECORATOR,
+ compInfo))
+ {
+ result.addError(element, NbBundle.getMessage(
+ DelegateFieldAnalizer.class,
+ "ERR_DelegateIsNotInDecorator")); // NOI18N
+ }
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(
+ result);
+ if ( helper != null ){
+ helper.addDelegate(result, element );
+ }
+ if ( cancel.get()){
+ return;
+ }
+ checkDelegateType(element, elementType, parent, result );
+ }
+
+ private void checkDelegateType( VariableElement element,
+ TypeMirror elementType, TypeElement parent,
+ CdiAnalysisResult result )
+ {
+ Collection decoratedTypes = getDecoratedTypes( parent ,
+ result.getInfo() );
+ for (TypeMirror decoratedType : decoratedTypes) {
+ if ( !result.getInfo().getTypes().isSubtype( elementType,decoratedType )){
+ result.addError(element, NbBundle.getMessage(
+ DelegateFieldAnalizer.class,
+ "ERR_DelegateTypeHasNoDecoratedType")); // NOI18N
+ return;
+ }
+ }
+ }
+
+ public static Collection getDecoratedTypes( TypeElement element ,
+ CompilationInfo info )
+ {
+ TypeElement serializable = info.getElements().getTypeElement(
+ Serializable.class.getCanonicalName());
+ Collection result = new LinkedList();
+ collectDecoratedTypes( element.asType() , result , serializable, info );
+ return result;
+ }
+
+ private static void collectDecoratedTypes( TypeMirror type,
+ Collection result, TypeElement serializable,
+ CompilationInfo info)
+ {
+ List extends TypeMirror> directSupertypes = info.getTypes().
+ directSupertypes(type);
+ for (TypeMirror superType : directSupertypes) {
+ Element element = info.getTypes().asElement(superType);
+ if( element == null || element.equals( serializable) )
+ {
+ continue;
+ }
+ if ( element.getKind() == ElementKind.INTERFACE ){
+ result.add( superType );
+ }
+ collectDecoratedTypes(superType, result, serializable, info);
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/InjectionPointAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/InjectionPointAnalyzer.java
new file mode 100644
index 000000000000..bb3a48bde1d9
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/InjectionPointAnalyzer.java
@@ -0,0 +1,226 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.field;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.swing.text.Document;
+
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractDecoratorAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldModelAnalyzer.FieldAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.CdiException;
+import org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult;
+import org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult.ResultKind;
+import org.netbeans.modules.jakarta.web.beans.api.model.InjectionPointDefinitionError;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.netbeans.spi.editor.hints.Severity;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class InjectionPointAnalyzer extends AbstractDecoratorAnalyzer implements FieldAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldModelAnalyzer.FieldAnalyzer#analyze(javax.lang.model.element.VariableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( final VariableElement element, TypeMirror elementType,
+ TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel ,
+ Result result )
+ {
+ try {
+ if (model.isInjectionPoint(element) ){
+ boolean isDelegate = false;
+ result.requireCdiEnabled(element, model);
+ checkInjectionPointMetadata( element, elementType , parent, model ,
+ cancel , result );
+ checkNamed( element, model , cancel, result);
+ if ( cancel.get() ){
+ return;
+ }
+ if ( !model.isDynamicInjectionPoint(element)) {
+ isDelegate = AnnotationUtil.isDelegate(element, parent, model);
+ if (!checkBuiltInBeans(element, elementType, model, cancel))
+ {
+ DependencyInjectionResult res = model
+ .lookupInjectables(element, null, cancel);
+ checkResult(res, element, model, result);
+ if (isDelegate) {
+ analyzeDecoratedBeans(res, element, null, parent,
+ model, result);
+ }
+ }
+ }
+ boolean isEvent = model.isEventInjectionPoint(element);
+ if ( isEvent ){
+ ElementHandle modelHandle = ElementHandle.create(element);
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(
+ result);
+ if ( helper != null ){
+ helper.addEventInjectionPoint( result,
+ modelHandle.resolve(result.getInfo()));
+ }
+ }
+ else if ( isDelegate || AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.DELEGATE_FQN, model.getCompilationController()))
+ {
+ return;
+ }
+ else {
+ ElementHandle modelHandle = ElementHandle.create(element);
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(
+ result);
+ if (helper != null ){
+ helper.addInjectionPoint( result,
+ modelHandle.resolve(result.getInfo()));
+ }
+ }
+ }
+ }
+ catch (InjectionPointDefinitionError e) {
+ result.requireCdiEnabled(element, model);
+ informInjectionPointDefError(e, element, model, result );
+ }
+ }
+
+ private void checkNamed( VariableElement element, WebBeansModel model,
+ AtomicBoolean cancel, Result result )
+ {
+ if( cancel.get() ){
+ return;
+ }
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.NAMED,
+ model.getCompilationController()) )
+ {
+ result.addNotification( Severity.WARNING , element, model,
+ NbBundle.getMessage(InjectionPointAnalyzer.class,
+ "WARN_NamedInjectionPoint")); // NOI18N
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractDecoratorAnalyzer#addClassError(javax.lang.model.element.VariableElement, java.lang.Object, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ protected void addClassError( VariableElement element, Void fake,
+ TypeElement decoratedBean, WebBeansModel model, Result result )
+ {
+ result.addError( element , model,
+ NbBundle.getMessage(InjectionPointAnalyzer.class,
+ "ERR_FinalDecoratedBean", // NOI18N
+ decoratedBean.getQualifiedName().toString()));
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractDecoratorAnalyzer#addMethodError(javax.lang.model.element.VariableElement, java.lang.Object, javax.lang.model.element.TypeElement, javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ protected void addMethodError( VariableElement element, Void fake,
+ TypeElement decoratedBean, Element decoratedMethod,
+ WebBeansModel model, Result result )
+ {
+ result.addError(
+ element, model, NbBundle.getMessage(
+ InjectionPointAnalyzer.class,
+ "ERR_FinalMethodDecoratedBean", // NOI18N
+ decoratedBean.getQualifiedName().toString(),
+ decoratedMethod.getSimpleName().toString()));
+ }
+
+ private void checkInjectionPointMetadata( VariableElement element,
+ TypeMirror elementType , TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel , Result result )
+ {
+ TypeElement injectionPointType = model.getCompilationController().
+ getElements().getTypeElement(AnnotationUtil.INJECTION_POINT);
+ if ( injectionPointType == null ){
+ return;
+ }
+ Element varElement = model.getCompilationController().getTypes().asElement(
+ elementType );
+ if ( !injectionPointType.equals(varElement)){
+ return;
+ }
+ if ( cancel.get()){
+ return;
+ }
+ List qualifiers = model.getQualifiers(element, true);
+ AnnotationHelper helper = new AnnotationHelper(model.getCompilationController());
+ Map qualifiersFqns = helper.
+ getAnnotationsByType(qualifiers);
+ boolean hasDefault = model.hasImplicitDefaultQualifier( element );
+ if ( !hasDefault && qualifiersFqns.keySet().contains(AnnotationUtil.DEFAULT_FQN)){
+ hasDefault = true;
+ }
+ if ( !hasDefault || cancel.get() ){
+ return;
+ }
+ try {
+ String scope = model.getScope( parent );
+ if ( scope != null && !AnnotationUtil.DEPENDENT.equals( scope )){
+ result.addError(element , model,
+ NbBundle.getMessage(
+ InjectionPointAnalyzer.class, "ERR_WrongQualifierInjectionPointMeta")); // NOI18N
+ }
+ }
+ catch (CdiException e) {
+ // this exception will be handled in the appropriate scope analyzer
+ return;
+ }
+ }
+
+ private void checkResult( DependencyInjectionResult res ,
+ VariableElement var, WebBeansModel model,
+ Result result )
+ {
+ if ( res instanceof DependencyInjectionResult.Error ){
+ ResultKind kind = res.getKind();
+ Severity severity = Severity.WARNING;
+ if ( kind == DependencyInjectionResult.ResultKind.DEFINITION_ERROR){
+ severity = Severity.ERROR;
+ }
+ String message = ((DependencyInjectionResult.Error)res).getMessage();
+ result.addNotification(severity, var , model, message);
+ }
+ }
+
+ private void informInjectionPointDefError(InjectionPointDefinitionError exception ,
+ Element element, WebBeansModel model,
+ Result result )
+ {
+ result.addError(element, model, exception.getMessage());
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/ProducerFieldAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/ProducerFieldAnalyzer.java
new file mode 100644
index 000000000000..f2d3cbcd328b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/ProducerFieldAnalyzer.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractProducerAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldElementAnalyzer.FieldAnalyzer;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ProducerFieldAnalyzer extends AbstractProducerAnalyzer
+ implements FieldAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldElementAnalyzer.FieldAnalyzer#analyze(javax.lang.model.element.VariableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, org.netbeans.api.java.source.CompilationInfo, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( VariableElement element, TypeMirror elementType,
+ TypeElement parent, AtomicBoolean cancel,
+ CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ if ( !AnnotationUtil.hasAnnotation(element, AnnotationUtil.PRODUCES_FQN,
+ compInfo ))
+ {
+ return;
+ }
+ result.requireCdiEnabled(element);
+ if ( cancel.get() ){
+ return;
+ }
+ checkSessionBean( element , parent , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkType( element, elementType, result );
+ }
+
+ @Override
+ protected void hasTypeVar( Element element, TypeMirror type,
+ CdiAnalysisResult result )
+ {
+ result.addError( element, NbBundle.getMessage(
+ ProducerFieldAnalyzer.class, "ERR_ProducerHasTypeVar")); // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractProducerAnalyzer#hasWildCard(javax.lang.model.element.Element, javax.lang.model.type.TypeMirror, org.netbeans.api.java.source.CompilationInfo, java.util.List)
+ */
+ @Override
+ protected void hasWildCard( Element element, TypeMirror type,
+ CdiAnalysisResult result )
+ {
+ result.addError(element, NbBundle.getMessage(
+ ProducerFieldAnalyzer.class,"ERR_ProducerHasWildcard")); // NOI18N
+ }
+
+ private void checkSessionBean( VariableElement element, TypeElement parent,
+ CdiAnalysisResult result )
+ {
+ if ( !AnnotationUtil.isSessionBean( parent , result.getInfo())) {
+ return;
+ }
+ Set modifiers = element.getModifiers();
+ if ( !modifiers.contains(Modifier.STATIC)){
+ result.addError( element, NbBundle.getMessage(
+ ProducerFieldAnalyzer.class,
+ "ERR_NonStaticProducerSessionBean")); // NOI18N
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/ScopedFieldAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/ScopedFieldAnalyzer.java
new file mode 100644
index 000000000000..e59eb61823e4
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/ScopedFieldAnalyzer.java
@@ -0,0 +1,110 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.field;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldModelAnalyzer.FieldAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ScopedFieldAnalyzer extends AbstractScopedAnalyzer implements
+ FieldAnalyzer
+{
+
+ @Override
+ public void analyze( VariableElement element, TypeMirror elementType,
+ TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel, Result result )
+ {
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.PRODUCES_FQN,
+ model.getCompilationController()))
+ {
+ result.requireCdiEnabled(element, model);
+ analyzeScope(element, model, cancel , result );
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer#checkScope(javax.lang.model.element.TypeElement, javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ protected void checkScope( TypeElement scopeElement, Element element,
+ WebBeansModel model, AtomicBoolean cancel, Result result )
+ {
+ if ( scopeElement.getQualifiedName().contentEquals( AnnotationUtil.DEPENDENT)){
+ return;
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ if (hasTypeVarParameter(element.asType())) {
+ result.addError(element, model,
+ NbBundle.getMessage(
+ ScopedFieldAnalyzer.class,
+ "ERR_WrongScopeParameterizedProducer", // NOI18N
+ scopeElement.getQualifiedName().toString()));
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ checkPassivationCapable(scopeElement, element, model, result);
+ }
+
+ private void checkPassivationCapable( TypeElement scopeElement,
+ Element element, WebBeansModel model, Result result )
+ {
+ if ( !isPassivatingScope(scopeElement, model) ){
+ return;
+ }
+ TypeMirror type = element.asType();
+ if ( type.getKind().isPrimitive() ){
+ return;
+ }
+ if ( isSerializable(type, model)){
+ return;
+ }
+ Element typeElement = model.getCompilationController().getTypes().
+ asElement( type );
+ if ( typeElement == null ){
+ return;
+ }
+ if ( typeElement.getModifiers().contains( Modifier.FINAL )){
+ result.addError( element, model,
+ NbBundle.getMessage(ScopedFieldAnalyzer.class,
+ "ERR_NotPassivationProducer", // NOI18N
+ scopeElement.getQualifiedName().toString()));
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/TypedFieldAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/TypedFieldAnalyzer.java
new file mode 100644
index 000000000000..4a1f3d802565
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/field/TypedFieldAnalyzer.java
@@ -0,0 +1,72 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.field;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldElementAnalyzer.FieldAnalyzer;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class TypedFieldAnalyzer extends AbstractTypedAnalyzer implements FieldAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.FieldElementAnalyzer.FieldAnalyzer#analyze(javax.lang.model.element.VariableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( VariableElement element, TypeMirror elementType,
+ TypeElement parent, AtomicBoolean cancel,
+ CdiAnalysisResult result )
+ {
+ analyze(element, elementType, cancel , result );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer#addError(javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void addError( Element element, CdiAnalysisResult result )
+ {
+ result.addError( element, NbBundle.getMessage(
+ TypedFieldAnalyzer.class, "ERR_BadRestritedFieldType")); // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer#checkSpecializes(javax.lang.model.element.Element, javax.lang.model.type.TypeMirror, java.util.List, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void checkSpecializes( Element element, TypeMirror elementType,
+ List restrictedTypes, AtomicBoolean cancel , CdiAnalysisResult result)
+ {
+ // production fields cannot be specialized
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/AnnotationsAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/AnnotationsAnalyzer.java
new file mode 100644
index 000000000000..d5ad97284c66
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/AnnotationsAnalyzer.java
@@ -0,0 +1,242 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.method;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class AnnotationsAnalyzer implements MethodAnalyzer {
+
+ private static final String EJB = "ejb"; // NOI18N
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer#analyze(javax.lang.model.element.ExecutableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( ExecutableElement element, TypeMirror returnType,
+ TypeElement parent, AtomicBoolean cancel , CdiAnalysisResult result )
+ {
+ checkProductionObserverDisposerInject( element , parent ,
+ cancel , result );
+ if ( cancel.get()){
+ return;
+ }
+ }
+
+ private void checkProductionObserverDisposerInject(
+ ExecutableElement element, TypeElement parent, AtomicBoolean cancel ,
+ CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ boolean isProducer = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.PRODUCES_FQN, compInfo);
+ boolean isInitializer = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.INJECT_FQN, compInfo);
+ int observesCount = 0;
+ int disposesCount = 0;
+ List extends VariableElement> parameters = element.getParameters();
+ for (VariableElement param : parameters) {
+ if ( cancel.get() ){
+ return;
+ }
+ if ( AnnotationUtil.hasAnnotation( param, AnnotationUtil.OBSERVES_FQN,
+ compInfo))
+ {
+ observesCount++;
+ }
+ if ( AnnotationUtil.hasAnnotation( param, AnnotationUtil.DISPOSES_FQN,
+ compInfo))
+ {
+ disposesCount++;
+ }
+ }
+ if ( observesCount >0 ){
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(result);
+ if ( helper != null ){
+ helper.addObserver( result , element );
+ }
+ }
+ String firstAnnotation = null;
+ String secondAnnotation = null;
+ if ( isProducer ){
+ firstAnnotation = AnnotationUtil.PRODUCES;
+ if ( isInitializer ){
+ secondAnnotation = AnnotationUtil.INJECT;
+ }
+ else if ( observesCount >0 ){
+ secondAnnotation = AnnotationUtil.OBSERVES;
+ }
+ else if ( disposesCount >0 ){
+ secondAnnotation = AnnotationUtil.DISPOSES;
+ }
+ }
+ else if ( isInitializer ){
+ firstAnnotation = AnnotationUtil.INJECT;
+ if ( observesCount >0 ){
+ secondAnnotation = AnnotationUtil.OBSERVES;
+ }
+ else if ( disposesCount >0 ){
+ secondAnnotation = AnnotationUtil.DISPOSES;
+ }
+ }
+ else if ( observesCount >0 ){
+ firstAnnotation = AnnotationUtil.OBSERVES;
+ if ( disposesCount >0 ){
+ secondAnnotation = AnnotationUtil.DISPOSES;
+ }
+ }
+ if ( firstAnnotation != null && secondAnnotation != null ){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "ERR_BothAnnotationsMethod", // NOI18N
+ firstAnnotation, secondAnnotation ));
+ }
+
+ // Test quantity of observer parameters
+ if ( observesCount > 1){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "ERR_ManyObservesParameter" )); // NOI18N
+ }
+ // Test quantity of disposes parameters
+ else if ( disposesCount >1 ){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "ERR_ManyDisposesParameter")); // NOI18N
+ }
+
+ // A producer/disposer method must be a non-abstract method .
+ checkAbstractMethod(element, result, isProducer,
+ disposesCount>0);
+
+ checkBusinessMethod( element , result, isProducer,
+ disposesCount >0 , observesCount > 0);
+
+ if ( isInitializer ){
+ checkInitializerMethod(element, parent , result );
+ }
+ }
+
+ /**
+ * A producer/disposer/observer non-static method of a session bean class
+ * should be a business method of the session bean.
+ */
+ private void checkBusinessMethod( ExecutableElement element,
+ CdiAnalysisResult result ,boolean isProducer, boolean isDisposer, boolean isObserver )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ if ( !isProducer && !isDisposer && !isObserver ){
+ return;
+ }
+ Set modifiers = element.getModifiers();
+ if ( modifiers.contains(Modifier.STATIC) ){
+ return;
+ }
+ TypeElement containingClass = compInfo.getElementUtilities().
+ enclosingTypeElement(element);
+ if ( !AnnotationUtil.isSessionBean( containingClass, compInfo) ){
+ return;
+ }
+ String methodName = element.getSimpleName().toString();
+ boolean isBusinessMethod = true;
+ if ( methodName.startsWith(EJB)){
+ isBusinessMethod = false;
+ }
+ if (AnnotationUtil.isLifecycleCallback(element, compInfo)){
+ isBusinessMethod = false;
+ }
+ if ( modifiers.contains(Modifier.FINAL) ||
+ !modifiers.contains( Modifier.PUBLIC) )
+ {
+ isBusinessMethod = false;
+ }
+ if ( !isBusinessMethod ){
+ String key = null;
+ if ( isProducer ){
+ key = "ERR_ProducerNotBusiness"; // NOI18N
+ }
+ else if ( isDisposer ){
+ key = "ERR_DisposerNotBusiness"; // NOI18N
+ }
+ else if ( isObserver ){
+ key = "ERR_ObserverNotBusiness"; // NOI18N
+ }
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, key));
+ }
+ }
+
+ private void checkInitializerMethod( ExecutableElement element,
+ TypeElement parent, CdiAnalysisResult result )
+ {
+ Set modifiers = element.getModifiers();
+ boolean isAbstract = modifiers.contains( Modifier.ABSTRACT );
+ boolean isStatic = modifiers.contains( Modifier.STATIC );
+ if ( isAbstract || isStatic ){
+ String key = isAbstract? "ERR_AbstractInitMethod":
+ "ERR_StaticInitMethod"; // NOI18N
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, key ));
+ }
+ TypeMirror method = result.getInfo().getTypes().asMemberOf(
+ (DeclaredType)parent.asType() , element);
+ if ( method instanceof ExecutableType ){
+ List extends TypeVariable> typeVariables =
+ ((ExecutableType)method).getTypeVariables();
+ if ( typeVariables != null && typeVariables.size() > 0 ){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "ERR_GenericInitMethod" ));// NOI18N
+ }
+ }
+ }
+
+ private void checkAbstractMethod( ExecutableElement element,
+ CdiAnalysisResult result ,boolean isProducer, boolean isDisposer )
+ {
+ if ( isProducer || isDisposer ){
+ String key = isProducer? "ERR_AbstractProducerMethod":
+ "ERR_AbstractDisposerMethod"; // NOI18N
+ Set modifiers = element.getModifiers();
+ if ( modifiers.contains( Modifier.ABSTRACT )){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, key ));
+ }
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/Bundle.properties
new file mode 100644
index 000000000000..aee689a71b11
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/Bundle.properties
@@ -0,0 +1,87 @@
+# 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.
+
+ERR_BadRestritedMethodType=Bean class of method return type specifies @Typed \
+annotation, and the value member specifies a class which does not correspond \
+to a type in the unrestricted set of bean types of a bean.
+ERR_BothAnnotationsMethod=The method has both {0} and {1} annotations.
+ERR_ManyObservesParameter=An observer method should have only one parameter \
+annotated by @Observes.
+ERR_ManyDisposesParameter=A disposer method should have only one parameter \
+annotated by @Disposes.
+ERR_AbstractProducerMethod=A producer method must be a non-abstract method of a \
+managed bean class or session bean class.
+ERR_AbstractDisposerMethod=A disposer method must be a non-abstract method of a \
+managed bean class or session bean class.
+ERR_WrongDelegateMethod=A delegate injection point must be initializer method \
+parameter or bean constructor method parameter.
+ERR_DelegateIsNotInDecorator=Parameter is declared as @Delegate but its enclosing \
+type element is not a decorator.
+ERR_FinalInterceptedMethod=The non-static, non-private method of a bean class of a \
+managed bean is final and declares a method level interceptor binding.
+ERR_FinalInterceptedClass=The non-static, non-private method of a final bean class of a \
+managed bean declares a method level interceptor binding.
+
+ERR_ProducerReturnIsTypeVar=A producer method return type should not be a type variable.
+ERR_ProducerReturnHasWildcard=A producer method return type should not contain a wildcard type parameter.
+
+ERR_WrongScopeParameterizedProducerReturn=The producer method return type is a \
+parameterized type with a type variable and has scope {0} (should be @Dependent).
+ERR_StaticSpecializesProducer=A producer method annotated with @Specializes must be non-static.
+ERR_NoDirectSpecializedProducer=A producer method annotated with @Specializes must \
+directly override another producer method.
+
+ERR_AbstractInitMethod=An initializer method should be a non-abstract.
+ERR_StaticInitMethod=An initializer method should be a non-static.
+ERR_GenericInitMethod=An initializer method should not be a generic.
+
+ERR_ParameterNamedInjectionPoint=An injection point has a @Named annotation \
+without value member specified.
+
+ERR_WrongQualifierInjectionPointMeta=An injection point has type InjectionPoint \
+and qualifier @Default but bean declares not @Dependent scope.
+
+ERR_BadSpecializesMethod=Method specializes another method but its bean type does \
+not have all bean types of specialized method.
+
+ERR_FinalDecoratedBean=Delegate injection point matches a managed bean {0} which \
+class is declared final.
+ERR_FinalMethodDecoratedBean=Delegate injection point matches a managed bean {0} \
+with final method {1} which is implemented by decorator.
+ERR_DelegateTypeHasNoDecoratedType=The delegate type of a decorator must implement \
+or extend every decorated type of decorator.
+
+WARN_CallbackInterceptorBinding=Interceptor bindings for lifecycle callback methods \
+includes only the interceptor bindings declared or inherited by the bean at the class \
+level.
+ERR_LifecycleInterceptorTarget=An interceptor for lifecycle callbacks may only \
+declare interceptor binding types that are defined as @Target(TYPE). Interceptor {0} \
+declares mismatch interceptor binding {1}.
+
+ERR_ProducerNotBusiness=A producer non-static method of a session bean class \
+should be a business method of the session bean.
+
+ERR_DisposerNotBusiness=A disposer non-static method of a session bean class \
+should be a business method of the session bean.
+
+ERR_ObserverNotBusiness=An observer non-static method of a session bean class \
+should be a business method of the session bean.
+
+WARN_NamedInjectionPoint=The use of @Named as an injection point qualifier is not recommended.
+
+ERR_NotPassivationProducerReturn=Producer method has a passivating scope {0} and should be \
+passivation capable. But its return type is declared final and does not implement Serializable.
\ No newline at end of file
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/DelegateMethodAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/DelegateMethodAnalyzer.java
new file mode 100644
index 000000000000..32b766b0a1d2
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/DelegateMethodAnalyzer.java
@@ -0,0 +1,138 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.method;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiEditorAnalysisFactory;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.DelegateFieldAnalizer;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class DelegateMethodAnalyzer implements MethodAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer#analyze(javax.lang.model.element.ExecutableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( ExecutableElement element, TypeMirror returnType,
+ TypeElement parent, AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ List extends VariableElement> parameters = element.getParameters();
+ int i=0;
+ for (VariableElement param : parameters) {
+ if (cancel.get()) {
+ return;
+ }
+ if (AnnotationUtil.hasAnnotation(param,
+ AnnotationUtil.DELEGATE_FQN, result.getInfo()))
+ {
+ result.requireCdiEnabled(element);
+ if (cancel.get()) {
+ return;
+ }
+ checkMethodDefinition(element, param, result );
+ if (cancel.get()) {
+ return;
+ }
+ checkClassDefinition(parent, element, param, result );
+ if (cancel.get()) {
+ return;
+ }
+ checkDelegateType(param, i, element, parent, result );
+ VariableElement var = CdiEditorAnalysisFactory.resolveParameter(
+ param, element, result.getInfo());
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.
+ getInstance(result);
+ if ( helper != null ){
+ helper.addInjectionPoint(result, var);
+ }
+ }
+ i++;
+ }
+ }
+
+ private void checkClassDefinition( TypeElement parent,
+ ExecutableElement element, VariableElement param,
+ CdiAnalysisResult result)
+ {
+ if ( !AnnotationUtil.hasAnnotation(parent, AnnotationUtil.DECORATOR,
+ result.getInfo()))
+ {
+ result.addError( param,
+ NbBundle.getMessage(DelegateFieldAnalizer.class,
+ "ERR_DelegateIsNotInDecorator")); // NOI18N
+ }
+ }
+
+ private void checkDelegateType( VariableElement element, int i,
+ ExecutableElement method, TypeElement parent,
+ CdiAnalysisResult result )
+ {
+ ExecutableType methodType = (ExecutableType) result.getInfo().getTypes()
+ .asMemberOf((DeclaredType) parent.asType(), method);
+ List extends TypeMirror> parameterTypes = methodType
+ .getParameterTypes();
+ TypeMirror parameterType = parameterTypes.get(i);
+ Collection decoratedTypes = DelegateFieldAnalizer
+ .getDecoratedTypes(parent, result.getInfo());
+ for (TypeMirror decoratedType : decoratedTypes) {
+ if (!result.getInfo().getTypes().isSubtype(parameterType, decoratedType)) {
+ result.addError(element, NbBundle.getMessage(
+ DelegateMethodAnalyzer.class,
+ "ERR_DelegateTypeHasNoDecoratedType")); // NOI18N
+ return;
+ }
+ }
+ }
+
+ private void checkMethodDefinition( ExecutableElement element,
+ VariableElement param, CdiAnalysisResult result )
+ {
+ if ( element.getKind() == ElementKind.CONSTRUCTOR ){
+ return;
+ }
+ if ( !AnnotationUtil.hasAnnotation(element, AnnotationUtil.INJECT_FQN,
+ result.getInfo()))
+ {
+ result.addError( param,
+ NbBundle.getMessage(DelegateMethodAnalyzer.class,
+ "ERR_WrongDelegateMethod")); // NOI18N
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/InjectionPointParameterAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/InjectionPointParameterAnalyzer.java
new file mode 100644
index 000000000000..9723ca5f4f37
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/InjectionPointParameterAnalyzer.java
@@ -0,0 +1,257 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.method;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiEditorAnalysisFactory;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractDecoratorAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodModelAnalyzer.MethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.field.InjectionPointAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.api.model.CdiException;
+import org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult;
+import org.netbeans.modules.jakarta.web.beans.api.model.DependencyInjectionResult.ResultKind;
+import org.netbeans.modules.jakarta.web.beans.api.model.InjectionPointDefinitionError;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.netbeans.spi.editor.hints.Severity;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class InjectionPointParameterAnalyzer
+ extends AbstractDecoratorAnalyzer implements MethodAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodModelAnalyzer.MethodAnalyzer#analyze(javax.lang.model.element.ExecutableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ public void analyze( ExecutableElement element, TypeMirror returnType,
+ TypeElement parent, WebBeansModel model ,
+ AtomicBoolean cancel , Result result )
+ {
+ for (VariableElement var : element.getParameters()) {
+ if (cancel.get()) {
+ return;
+ }
+ try {
+ if (model.isInjectionPoint(var)) {
+ boolean isDelegate = false;
+ result.requireCdiEnabled(element, model);
+ if ( cancel.get() ){
+ return;
+ }
+ if (!model.isDynamicInjectionPoint(var)) {
+ isDelegate =AnnotationUtil.isDelegate(var, parent, model);
+ if (!checkBuiltInBeans(var,
+ getParameterType(var, element, parent,
+ model.getCompilationController()),
+ model, cancel))
+ {
+ DependencyInjectionResult res = model
+ .lookupInjectables(var,
+ (DeclaredType) parent.asType(), cancel);
+ checkResult(res, element, var, model, result);
+ if (isDelegate) {
+ analyzeDecoratedBeans(res, var, element,
+ parent, model, result);
+ }
+ }
+ }
+ if ( cancel.get()){
+ return;
+ }
+ checkName(element, var, model,result );
+ if ( cancel.get()){
+ return;
+ }
+ checkInjectionPointMetadata( var, element, parent , model ,
+ cancel , result );
+ if ( isDelegate || AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.DELEGATE_FQN, model.getCompilationController()))
+ {
+ return;
+ }
+ else {
+ VariableElement param = CdiEditorAnalysisFactory.
+ resolveParameter(var, element, result.getInfo());
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.
+ getInstance(result);
+ if ( helper != null ){
+ helper.addInjectionPoint(result, param);
+ }
+ }
+ }
+ }
+ catch( InjectionPointDefinitionError e ){
+ result.requireCdiEnabled(element, model);
+ informInjectionPointDefError(e, element, model, result );
+ }
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractDecoratorAnalyzer#addClassError(javax.lang.model.element.VariableElement, java.lang.Object, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, org.netbeans.api.java.source.CompilationInfo, java.util.List)
+ */
+ @Override
+ protected void addClassError( VariableElement element, ExecutableElement method,
+ TypeElement decoratedBean, WebBeansModel model,
+ Result result )
+ {
+ result.addError( element , method, model,
+ NbBundle.getMessage(InjectionPointParameterAnalyzer.class,
+ "ERR_FinalDecoratedBean", // NOI18N
+ decoratedBean.getQualifiedName().toString()));
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractDecoratorAnalyzer#addMethodError(javax.lang.model.element.VariableElement, java.lang.Object, javax.lang.model.element.TypeElement, javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ protected void addMethodError( VariableElement element,
+ ExecutableElement method, TypeElement decoratedBean,
+ Element decoratedMethod, WebBeansModel model, Result result )
+ {
+ result.addError(
+ element, method, model, NbBundle.getMessage(
+ InjectionPointParameterAnalyzer.class,
+ "ERR_FinalMethodDecoratedBean", // NOI18N
+ decoratedBean.getQualifiedName().toString(),
+ decoratedMethod.getSimpleName().toString()));
+ }
+
+ private TypeMirror getParameterType( VariableElement var,
+ ExecutableElement element, TypeElement parent ,
+ CompilationController controller )
+ {
+ ExecutableType method = (ExecutableType)controller.getTypes().asMemberOf(
+ (DeclaredType)parent.asType(), element);
+ List extends TypeMirror> parameterTypes = method.getParameterTypes();
+ List extends VariableElement> parameters = element.getParameters();
+ int paramIndex = parameters.indexOf(var);
+ return parameterTypes.get(paramIndex);
+ }
+
+ private void checkInjectionPointMetadata( VariableElement var,
+ ExecutableElement method, TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel , Result result )
+ {
+ TypeElement injectionPointType = model.getCompilationController()
+ .getElements().getTypeElement(AnnotationUtil.INJECTION_POINT);
+ if (injectionPointType == null) {
+ return;
+ }
+ Element varElement = model.getCompilationController().getTypes()
+ .asElement(var.asType());
+ if (!injectionPointType.equals(varElement)) {
+ return;
+ }
+ if (cancel.get()) {
+ return;
+ }
+ List qualifiers = model.getQualifiers(varElement,
+ true);
+ AnnotationHelper helper = new AnnotationHelper(
+ model.getCompilationController());
+ Map qualifiersFqns = helper
+ .getAnnotationsByType(qualifiers);
+ boolean hasDefault = model.hasImplicitDefaultQualifier(varElement);
+ if (!hasDefault
+ && qualifiersFqns.containsKey(AnnotationUtil.DEFAULT_FQN))
+ {
+ hasDefault = true;
+ }
+ if (!hasDefault || cancel.get()) {
+ return;
+ }
+ try {
+ String scope = model.getScope(parent);
+ if (scope != null && !AnnotationUtil.DEPENDENT.equals(scope)) {
+ result.addError(var, method, model,
+ NbBundle.getMessage(InjectionPointParameterAnalyzer.class,"ERR_WrongQualifierInjectionPointMeta")); // NOI18N
+ }
+ }
+ catch (CdiException e) {
+ // this exception will be handled in the appropriate scope analyzer
+ return;
+ }
+ }
+
+ private void checkName( ExecutableElement element, VariableElement var,
+ WebBeansModel model, Result result)
+ {
+ AnnotationMirror annotation = AnnotationUtil.getAnnotationMirror(
+ var , AnnotationUtil.NAMED, model.getCompilationController());
+ if ( annotation!= null){
+ result.addNotification( Severity.WARNING , var, element , model,
+ NbBundle.getMessage(InjectionPointAnalyzer.class,
+ "WARN_NamedInjectionPoint")); // NOI18N
+ if ( annotation.getElementValues().size() == 0 ){
+ result.addError(var, element, model,
+ NbBundle.getMessage( InjectionPointParameterAnalyzer.class,
+ "ERR_ParameterNamedInjectionPoint")); // NOI18N
+ }
+ }
+ }
+
+ private void checkResult( DependencyInjectionResult res ,
+ ExecutableElement method , VariableElement element, WebBeansModel model,
+ Result result )
+ {
+ if ( res instanceof DependencyInjectionResult.Error ){
+ ResultKind kind = res.getKind();
+ Severity severity = Severity.WARNING;
+ if ( kind == DependencyInjectionResult.ResultKind.DEFINITION_ERROR){
+ severity = Severity.ERROR;
+ }
+ String message = ((DependencyInjectionResult.Error)res).getMessage();
+ result.addNotification(severity, element , method ,
+ model, message);
+ }
+ }
+
+ private void informInjectionPointDefError(InjectionPointDefinitionError exception ,
+ Element element, WebBeansModel model,
+ Result result )
+ {
+ result.addError(element, model, exception.getMessage());
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/InterceptedMethodAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/InterceptedMethodAnalyzer.java
new file mode 100644
index 000000000000..27eb796874f2
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/InterceptedMethodAnalyzer.java
@@ -0,0 +1,188 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.method;
+
+import java.lang.annotation.ElementType;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+import org.netbeans.api.java.source.CompilationController;
+
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.modules.j2ee.metadata.model.api.support.annotation.AnnotationHelper;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractInterceptedElementAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodModelAnalyzer.MethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.annotation.TargetAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.api.model.InterceptorsResult;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.netbeans.spi.editor.hints.Severity;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class InterceptedMethodAnalyzer extends AbstractInterceptedElementAnalyzer
+ implements MethodAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodModelAnalyzer.MethodAnalyzer#analyze(javax.lang.model.element.ExecutableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( ExecutableElement element, TypeMirror returnType,
+ TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel , Result result )
+ {
+ boolean hasInterceptorBindings = hasInterceptorBindings(element, model);
+ if ( hasInterceptorBindings ){
+ result.requireCdiEnabled(element, model);
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(result);
+ ElementHandle handle = ElementHandle.create(element);
+ if ( helper != null ){
+ helper.addInterceptedMethod(result, handle.resolve( result.getInfo()));
+ }
+ }
+ if (AnnotationUtil.isLifecycleCallback(element, model.getCompilationController() )) {
+ if (hasInterceptorBindings) {
+ result.addNotification( Severity.WARNING, element, model,
+ NbBundle.getMessage(InterceptedMethodAnalyzer.class,
+ "WARN_CallbackInterceptorBinding")); // NOI18N
+ }
+ if (cancel.get()) {
+ return;
+ }
+ InterceptorsResult interceptorResult = model
+ .getInterceptors(element);
+ List interceptors = interceptorResult
+ .getResolvedInterceptors();
+ AnnotationHelper helper = null;
+ if ( interceptors.size() >0 ){
+ helper = new AnnotationHelper(model.getCompilationController());
+ }
+ for (TypeElement interceptor : interceptors) {
+ if (isLifecycleCallbackInterceptor(interceptor, model.getCompilationController())) {
+ Collection interceptorBindings = model
+ .getInterceptorBindings(interceptor);
+ for (AnnotationMirror annotationMirror : interceptorBindings) {
+ Element iBinding = model.getCompilationController().getTypes().
+ asElement( annotationMirror.getAnnotationType() );
+ if ( !( iBinding instanceof TypeElement )) {
+ continue;
+ }
+ Set declaredTargetTypes = TargetAnalyzer.
+ getDeclaredTargetTypes(helper, (TypeElement)iBinding);
+ if ( declaredTargetTypes.size() != 1 ||
+ !declaredTargetTypes.contains(ElementType.TYPE))
+ {
+ result.addError(element, model,
+ NbBundle.getMessage(InterceptedMethodAnalyzer.class,
+ "ERR_LifecycleInterceptorTarget" , // NOI18N
+ interceptor.getQualifiedName().toString(),
+ ((TypeElement)iBinding).getQualifiedName().toString()));
+ }
+ }
+ }
+ }
+ }
+ if (cancel.get()) {
+ return;
+ }
+
+ Set modifiers = element.getModifiers();
+ if ( modifiers.contains( Modifier.STATIC ) ||
+ modifiers.contains( Modifier.PRIVATE))
+ {
+ return;
+ }
+ boolean finalMethod = modifiers.contains( Modifier.FINAL );
+ boolean finalClass = parent.getModifiers().contains( Modifier.FINAL);
+ if ( !finalMethod && !finalClass ){
+ return;
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ if ( hasInterceptorBindings){
+ if ( finalMethod ){
+ result.addError(element, model,
+ NbBundle.getMessage(
+ InterceptedMethodAnalyzer.class,
+ "ERR_FinalInterceptedMethod")); // NOI18N
+ }
+ if ( finalClass && !AnnotationUtil.hasAnnotation(parent,
+ AnnotationUtil.INTERCEPTOR, model.getCompilationController()))
+ {
+ result.addError(element, model,
+ NbBundle.getMessage(
+ InterceptedMethodAnalyzer.class,
+ "ERR_FinalInterceptedClass")); // NOI18N
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractInterceptedElementAnalyzer#getInterceptorBindings(javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel)
+ */
+ @Override
+ protected Set getInterceptorBindings( Element element,
+ WebBeansModel model )
+ {
+ Set iBindings = super.getInterceptorBindings(element, model);
+ List extends AnnotationMirror> annotations = model
+ .getCompilationController().getElements()
+ .getAllAnnotationMirrors(element);
+ iBindings.retainAll(annotations);
+ return iBindings;
+ }
+
+ private static boolean isLifecycleCallbackInterceptor(TypeElement interceptor, CompilationController info) {
+ for (Element e : interceptor.getEnclosedElements()) {
+ if (e.getKind() == ElementKind.METHOD && e instanceof ExecutableElement) {
+ if (AnnotationUtil.isLifecycleCallback((ExecutableElement) e, info)) {
+ return true;
+ }
+ }
+ }
+ TypeMirror tm = interceptor.getSuperclass();
+ if (tm.getKind() == TypeKind.DECLARED) {
+ Element e = info.getTypes().asElement(tm);
+ if (e instanceof TypeElement) {
+ return isLifecycleCallbackInterceptor((TypeElement) e, info);
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/ProducerMethodAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/ProducerMethodAnalyzer.java
new file mode 100644
index 000000000000..3c288e3ce08e
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/ProducerMethodAnalyzer.java
@@ -0,0 +1,125 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.method;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractProducerAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ProducerMethodAnalyzer extends AbstractProducerAnalyzer
+ implements MethodAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer#analyze(javax.lang.model.element.ExecutableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( ExecutableElement element, TypeMirror returnType,
+ TypeElement parent, AtomicBoolean cancel , CdiAnalysisResult result )
+ {
+ if ( !AnnotationUtil.hasAnnotation(element, AnnotationUtil.PRODUCES_FQN,
+ result.getInfo() ))
+ {
+ return;
+ }
+ result.requireCdiEnabled(element);
+ if ( cancel.get() ){
+ return;
+ }
+ checkType( element, returnType, result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkSpecializes( element , result );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractProducerAnalyzer#hasTypeVar(javax.lang.model.element.Element, javax.lang.model.type.TypeMirror, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void hasTypeVar( Element element, TypeMirror type,
+ CdiAnalysisResult result)
+ {
+ result.addError( element, NbBundle.getMessage(
+ ProducerMethodAnalyzer.class, "ERR_ProducerReturnIsTypeVar")); // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractProducerAnalyzer#hasWildCard(javax.lang.model.element.Element, javax.lang.model.type.TypeMirror, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void hasWildCard( Element element, TypeMirror type,
+ CdiAnalysisResult result )
+ {
+ result.addError(element, NbBundle.getMessage(
+ ProducerMethodAnalyzer.class,"ERR_ProducerReturnHasWildcard")); // NOI18N
+ }
+
+ private void checkSpecializes(ExecutableElement element, CdiAnalysisResult result )
+ {
+ if ( !AnnotationUtil.hasAnnotation(element, AnnotationUtil.SPECIALIZES,
+ result.getInfo() ))
+ {
+ return;
+ }
+ Set modifiers = element.getModifiers();
+ if ( modifiers.contains( Modifier.STATIC )){
+ result.addError( element, NbBundle.getMessage(
+ ProducerMethodAnalyzer.class,
+ "ERR_StaticSpecializesProducer")); // NOI18N
+ }
+ CompilationInfo compInfo = result.getInfo();
+ ExecutableElement overridenMethod = compInfo.getElementUtilities().
+ getOverriddenMethod( element );
+ if ( overridenMethod == null ){
+ return;
+ }
+ TypeElement superClass = compInfo.getElementUtilities().
+ enclosingTypeElement( overridenMethod );
+ TypeElement containingClass = compInfo.getElementUtilities().
+ enclosingTypeElement( element );
+ TypeMirror typeDirectSuper = containingClass.getSuperclass();
+ if ( !superClass.equals(compInfo.getTypes().asElement(typeDirectSuper)) ||
+ !AnnotationUtil.hasAnnotation(overridenMethod,
+ AnnotationUtil.PRODUCES_FQN, compInfo))
+ {
+ result.addError( element, NbBundle.getMessage(
+ ProducerMethodAnalyzer.class,
+ "ERR_NoDirectSpecializedProducer")); // NOI18N
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/ScopedMethodAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/ScopedMethodAnalyzer.java
new file mode 100644
index 000000000000..dc84c12c454b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/ScopedMethodAnalyzer.java
@@ -0,0 +1,120 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.method;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodModelAnalyzer.MethodAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ScopedMethodAnalyzer extends AbstractScopedAnalyzer implements
+ MethodAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodModelAnalyzer.MethodAnalyzer#analyze(javax.lang.model.element.ExecutableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ public void analyze( ExecutableElement element, TypeMirror returnType,
+ TypeElement parent, WebBeansModel model,
+ AtomicBoolean cancel, Result result )
+ {
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.PRODUCES_FQN,
+ model.getCompilationController()))
+ {
+ result.requireCdiEnabled(element,model);
+ analyzeScope(element, model, cancel, result );
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer#checkScope(javax.lang.model.element.TypeElement, javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result)
+ */
+ @Override
+ protected void checkScope( TypeElement scopeElement, Element element,
+ WebBeansModel model, AtomicBoolean cancel, Result result )
+ {
+ if ( scopeElement.getQualifiedName().contentEquals( AnnotationUtil.DEPENDENT)){
+ return;
+ }
+ TypeMirror methodType = element.asType();
+ if ( methodType instanceof ExecutableType ){
+ TypeMirror returnType = ((ExecutableType)methodType).getReturnType();
+ if ( cancel.get() ){
+ return;
+ }
+ if ( hasTypeVarParameter( returnType )){
+ result.addError( element, model,
+ NbBundle.getMessage(ScopedMethodAnalyzer.class,
+ "ERR_WrongScopeParameterizedProducerReturn", // NOI18N
+ scopeElement.getQualifiedName().toString()));
+ }
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ checkPassivationCapable( scopeElement , element , model , result );
+ }
+
+ private void checkPassivationCapable( TypeElement scopeElement,
+ Element element, WebBeansModel model, Result result )
+ {
+ if ( !isPassivatingScope(scopeElement, model) ){
+ return;
+ }
+ TypeMirror returnType = ((ExecutableElement)element).getReturnType();
+ if ( returnType == null ){
+ return;
+ }
+ if ( returnType.getKind().isPrimitive() ){
+ return;
+ }
+ if ( isSerializable(returnType, model)){
+ return;
+ }
+ Element returnTypeElement = model.getCompilationController().getTypes().
+ asElement( returnType );
+ if ( returnTypeElement == null ){
+ return;
+ }
+ if ( returnTypeElement.getModifiers().contains( Modifier.FINAL )){
+ result.addError( element, model,
+ NbBundle.getMessage(ScopedMethodAnalyzer.class,
+ "ERR_NotPassivationProducerReturn", // NOI18N
+ scopeElement.getQualifiedName().toString()));
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/TypedMethodAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/TypedMethodAnalyzer.java
new file mode 100644
index 000000000000..dd98332aa42e
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/method/TypedMethodAnalyzer.java
@@ -0,0 +1,205 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.method;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class TypedMethodAnalyzer extends AbstractTypedAnalyzer implements
+ MethodAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.MethodElementAnalyzer.MethodAnalyzer#analyze(javax.lang.model.element.ExecutableElement, javax.lang.model.type.TypeMirror, javax.lang.model.element.TypeElement, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ public void analyze( ExecutableElement element, TypeMirror returnType,
+ TypeElement parent, AtomicBoolean cancel , CdiAnalysisResult result )
+ {
+ analyze(element, returnType, cancel , result );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer#addError(javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void addError( Element element, CdiAnalysisResult result )
+ {
+ result.addError( element, NbBundle.getMessage(
+ TypedMethodAnalyzer.class, "ERR_BadRestritedMethodType")); // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analizer.AbstractTypedAnalyzer#hasBeanType(javax.lang.model.element.Element, javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror, org.netbeans.api.java.source.CompilationInfo)
+ */
+ @Override
+ protected boolean hasBeanType( Element subject, TypeMirror returnType,
+ TypeMirror requiredBeanType, CompilationInfo compInfo )
+ {
+ return compInfo.getTypes().isSubtype(returnType, requiredBeanType);
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer#checkSpecializes(javax.lang.model.element.Element, javax.lang.model.type.TypeMirror, java.util.List, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void checkSpecializes( Element element, TypeMirror elementType,
+ List restrictedTypes, AtomicBoolean cancel , CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ if (!AnnotationUtil.hasAnnotation(element, AnnotationUtil.PRODUCES_FQN,
+ compInfo))
+ {
+ return;
+ }
+ ExecutableElement method = (ExecutableElement)element;
+ ExecutableElement overriddenMethod = compInfo.getElementUtilities().
+ getOverriddenMethod(method);
+ if ( overriddenMethod == null ){
+ return;
+ }
+ TypeElement clazz = compInfo.getElementUtilities().
+ enclosingTypeElement(method);
+ TypeMirror superType = clazz.getSuperclass();
+ TypeElement superClass = compInfo.getElementUtilities().
+ enclosingTypeElement(overriddenMethod);
+ if ( !superClass.equals( compInfo.getTypes().asElement( superType))){
+ return;
+ }
+ if ( cancel.get()){
+ return;
+ }
+ List restrictedSuper = getRestrictedTypes(overriddenMethod,
+ compInfo, cancel);
+ if ( cancel.get()){
+ return;
+ }
+ if ( restrictedSuper == null ) {
+ if (!hasUnrestrictedOverridenType(elementType,
+ restrictedTypes, compInfo,overriddenMethod, superClass) )
+ {
+ result.addError( element, NbBundle.getMessage(
+ TypedMethodAnalyzer.class, "ERR_BadSpecializesMethod")); // NOI18N
+ }
+ }
+ else {
+ if (!hasRestrictedType(elementType, restrictedTypes, compInfo,
+ restrictedSuper))
+ {
+ result.addError( element, NbBundle.getMessage(
+ TypedMethodAnalyzer.class, "ERR_BadSpecializesMethod")); // NOI18N
+ }
+ }
+ }
+
+ private boolean hasRestrictedType( TypeMirror elementType,
+ List restrictedTypes, CompilationInfo compInfo,
+ List restrictedSuper )
+ {
+ if ( elementType.getKind() == TypeKind.ARRAY ){
+ for( TypeMirror mirror : restrictedSuper ){
+ boolean found = false;
+ for( TypeMirror restrictedType : restrictedTypes ){
+ if ( compInfo.getTypes().isSameType( restrictedType, mirror)){
+ found = true;
+ break;
+ }
+ }
+ if ( !found ){
+ return false;
+ }
+ }
+ return true;
+ }
+ else {
+ Set specializedBeanTypes = getElements(
+ restrictedSuper, compInfo);
+ Set restrictedElements = getElements(restrictedTypes,
+ compInfo);
+ restrictedElements.add( compInfo.getElements().getTypeElement(
+ Object.class.getCanonicalName()));
+ return restrictedElements.containsAll( specializedBeanTypes );
+ }
+ }
+
+ private boolean hasUnrestrictedOverridenType( TypeMirror elementType,
+ List restrictedTypes, CompilationInfo compInfo,
+ ExecutableElement overriddenMethod, TypeElement superClass )
+ {
+ TypeMirror methodType = compInfo.getTypes().asMemberOf(
+ (DeclaredType)superClass.asType(), overriddenMethod);
+ TypeMirror returnOverriden = ((ExecutableType)methodType).getReturnType();
+ if ( elementType.getKind() == TypeKind.ARRAY ){
+ for( TypeMirror mirror : restrictedTypes ){
+ if ( compInfo.getTypes().isSameType( mirror, returnOverriden)){
+ return true;
+ }
+ }
+ return false;
+ }
+ else if ( returnOverriden.getKind().isPrimitive() ) {
+ TypeElement boxed = compInfo.getTypes().boxedClass(
+ (PrimitiveType)returnOverriden);
+ return hasUnrestrictedType(boxed, restrictedTypes, compInfo);
+ }
+ else if ( returnOverriden instanceof DeclaredType ){
+ Element returnElement = compInfo.getTypes().asElement( returnOverriden);
+ if ( returnElement instanceof TypeElement ){
+ return hasUnrestrictedType((TypeElement)returnElement,
+ restrictedTypes, compInfo);
+ }
+ }
+ return true;
+ }
+
+ private boolean hasUnrestrictedType( TypeElement overriden,
+ List restrictedTypes,CompilationInfo compInfo )
+ {
+ Set specializedBeanTypes = getUnrestrictedBeanTypes(
+ overriden, compInfo);
+ Set restrictedElements = getElements(restrictedTypes,
+ compInfo);
+ restrictedElements.add( compInfo.getElements().getTypeElement(
+ Object.class.getCanonicalName()));
+ return restrictedElements.containsAll(specializedBeanTypes);
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/AnnotationsAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/AnnotationsAnalyzer.java
new file mode 100644
index 000000000000..323460b97166
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/AnnotationsAnalyzer.java
@@ -0,0 +1,275 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassElementAnalyzer.ClassAnalyzer;
+import org.openide.util.NbBundle;
+import org.netbeans.spi.editor.hints.Severity;
+
+
+/**
+ * @author ads
+ *
+ */
+public class AnnotationsAnalyzer implements ClassAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassElementAnalyzer.ClassAnalyzer#analyze(javax.lang.model.element.TypeElement, javax.lang.model.element.TypeElement, org.netbeans.api.java.source.CompilationInfo, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ checkDecoratorInterceptor( element , cancel, result );
+ }
+
+ private void checkDecoratorInterceptor( TypeElement element,
+ AtomicBoolean cancel , CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ boolean isDecorator = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.DECORATOR, compInfo);
+ boolean isInterceptor = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.INTERCEPTOR, compInfo);
+ if ( isDecorator && isInterceptor ){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "ERR_DecoratorInterceptor"));// NOI18N
+ }
+ if ( isDecorator || isInterceptor ){
+ result.requireCdiEnabled(element);
+ if ( cancel.get() ){
+ return;
+ }
+ checkProducerFields( element , isDecorator , result);
+ if ( cancel.get() ){
+ return;
+ }
+ checkMethods( element , isDecorator , result);
+ if ( cancel.get() ){
+ return;
+ }
+ checkSession( element , result);
+ if ( cancel.get() ){
+ return;
+ }
+ checkNamed( element , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkAlternatives(element , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkSpecializes( element , result );
+ }
+ if ( isDecorator ){
+ if ( cancel.get() ){
+ return;
+ }
+ checkDelegateInjectionPoint(element , result);
+ }
+ }
+
+ private void checkSpecializes( TypeElement element, CdiAnalysisResult result )
+ {
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.SPECIALIZES,
+ result.getInfo()) )
+ {
+ result.addNotification(Severity.WARNING, element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class,
+ "WARN_SpecializesInterceptorDecorator")); // NOI18N
+ }
+ }
+
+ private void checkAlternatives( TypeElement element,
+ CdiAnalysisResult result )
+ {
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.ALTERNATVE,
+ result.getInfo()))
+ {
+ result.addNotification(Severity.WARNING, element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class,
+ "WARN_AlternativeInterceptorDecorator")); // NOI18N
+ }
+ }
+
+ private void checkNamed( TypeElement element, CdiAnalysisResult result ) {
+ if ( AnnotationUtil.hasAnnotation(element, AnnotationUtil.NAMED,
+ result.getInfo()))
+ {
+ result.addNotification(Severity.WARNING, element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "WARN_NamedInterceptorDecorator")); // NOI18N
+ }
+ }
+
+ private void checkDelegateInjectionPoint( TypeElement element,
+ CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ List extends Element> enclosedElements = element.getEnclosedElements();
+ int count = 0;
+ for (Element child : enclosedElements) {
+ if ( child.getKind() == ElementKind.CONSTRUCTOR )
+ {
+ count +=delegateInjectionPointCount(child, compInfo);
+ }
+ else if ( ! AnnotationUtil.hasAnnotation(child, AnnotationUtil.INJECT_FQN,
+ compInfo ))
+ {
+ continue;
+ }
+ if ( child.getKind() == ElementKind.FIELD && AnnotationUtil.
+ hasAnnotation(child, AnnotationUtil.DELEGATE_FQN, compInfo ))
+ {
+ count++;
+ }
+ else if ( child.getKind() ==ElementKind.METHOD )
+ {
+ count+=delegateInjectionPointCount(child, compInfo);
+ }
+ }
+ if ( count != 1){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "ERR_IncorrectDelegateCount")); // NOI18N
+ }
+ }
+
+ private int delegateInjectionPointCount(Element element ,
+ CompilationInfo compInfo)
+ {
+ int result=0;
+ ExecutableElement method = (ExecutableElement)element;
+ List extends VariableElement> parameters = method.getParameters();
+ for (VariableElement par : parameters) {
+ if ( AnnotationUtil.hasAnnotation(par, AnnotationUtil.DELEGATE_FQN,
+ compInfo))
+ {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ private void checkSession( TypeElement element,
+ CdiAnalysisResult result )
+ {
+ if ( AnnotationUtil.isSessionBean(element, result.getInfo()) )
+ {
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, "ERR_SesssionBeanID")); // NOI18N
+ }
+ }
+
+ private void checkMethods( TypeElement element, boolean isDecorator,
+ CdiAnalysisResult result )
+ {
+ CompilationInfo compInfo = result.getInfo();
+ List methods = ElementFilter.methodsIn(
+ element.getEnclosedElements());
+ for (ExecutableElement method : methods) {
+ boolean isProducer = AnnotationUtil.hasAnnotation(method,
+ AnnotationUtil.PRODUCES_FQN, compInfo);
+ boolean isDisposer = false;
+ boolean isObserver = false;
+ List extends VariableElement> parameters = method.getParameters();
+ for (VariableElement param : parameters) {
+ if ( AnnotationUtil.hasAnnotation( param , AnnotationUtil.DISPOSES_FQN,
+ compInfo))
+ {
+ isDisposer = true;
+ break;
+ }
+ if ( AnnotationUtil.hasAnnotation( param , AnnotationUtil.OBSERVES_FQN,
+ compInfo))
+ {
+ isObserver = true;
+ break;
+ }
+ }
+ if ( isProducer || isDisposer || isObserver ){
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, getMethodErrorKey(isDecorator,
+ isProducer, isDisposer) ,
+ method.getSimpleName().toString()));
+ break;
+ }
+ }
+ }
+
+ private String getMethodErrorKey(boolean isDecorator, boolean isProducer,
+ boolean isDisposer )
+ {
+ String key= null;
+ if ( isDecorator ){
+ if ( isProducer ){
+ key = "ERR_DecoratorHasProducerMethod"; // NOI18N
+ }
+ else if ( isDisposer ){
+ key = "ERR_DecoratorHasDisposerMethod"; // NOI18N
+ }
+ else {
+ key = "ERR_DecoratorHasObserverMethod"; // NOI18N
+ }
+ }
+ else {
+ if ( isProducer ){
+ key = "ERR_InterceptorHasProducerMethod"; // NOI18N
+ }
+ else if ( isDisposer ){
+ key = "ERR_InterceptorHasDisposerMethod"; // NOI18N
+ }
+ else {
+ key = "ERR_InterceptorHasObserverMethod"; // NOI18N
+ }
+ }
+ return key;
+ }
+
+ private void checkProducerFields( TypeElement element, boolean isDecorator,
+ CdiAnalysisResult result )
+ {
+ List fields = ElementFilter.fieldsIn(
+ element.getEnclosedElements() );
+ for (VariableElement field : fields) {
+ if ( AnnotationUtil.hasAnnotation(field, AnnotationUtil.PRODUCES_FQN,
+ result.getInfo()))
+ {
+ String key= isDecorator ? "ERR_DecoratorHasProducerField":
+ "ERR_IntrerceptorHasProducerField"; // NOI18N
+ result.addError( element, NbBundle.getMessage(
+ AnnotationsAnalyzer.class, key , field.getSimpleName().toString()));
+ break;
+ }
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/Bundle.properties b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/Bundle.properties
new file mode 100644
index 000000000000..bc718fc65009
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/Bundle.properties
@@ -0,0 +1,93 @@
+# 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.
+
+ERR_BadRestritedType=Bean class specifies @Typed annotation, and the value member \
+specifies a class which does not correspond to a type in \
+the unrestricted set of bean types of a bean.
+ERR_NonStaticInnerType=Non-static inner class cannot be managed bean or \
+superclass of managed bean.
+WARN_QualifiedElementExtension=The element is not managed bean: it has \
+qualifiers but implements javax.enterprise.inject.spi.Extension.
+WARN_QualifierAbstractClass=The element is not managed bean: it has \
+qualifiers but has abstract modifier.
+WARN_QualifierNoCtorClass=The element is not managed bean: it has \
+qualifiers but does not have non-private constructor with no parameters or \
+annotated with @Inject .
+ERR_FinalScopedClass=Class is unproxyable: it has normal scope and declared final.
+WARN_FinalScopedClassMethod=Final method is declared in class with normal scope.
+ERR_DecoratorInterceptor=A managed bean cannot be annotated with both \
+@Interceptor and @Decorator stereotypes.
+
+ERR_DecoratorHasProducerField=A decorator may not declare producer field "{0}".
+ERR_IntrerceptorHasProducerField=An interceptor may not declare producer field "{0}".
+ERR_DecoratorHasProducerMethod=A decorator may not declare producer method "{0}".
+ERR_DecoratorHasDisposerMethod=A decorator may not declare disposer method "{0}".
+ERR_DecoratorHasObserverMethod=A decorator may not declare observer method "{0}".
+ERR_InterceptorHasProducerMethod=An interceptor may not declare producer method "{0}".
+ERR_InterceptorHasDisposerMethod=An interceptor may not declare disposer method "{0}".
+ERR_InterceptorHasObserverMethod=An interceptor may not declare observer method "{0}".
+
+ERR_InjectedCtor=A bean class should not have more than one constructor annotated @Inject.
+
+ERR_SesssionBeanID=A bean class of a session bean should not be annotated \
+@Interceptor or @Decorator.
+
+ERR_InvalidSingletonBeanScope=A singleton bean must belong to either the \
+@ApplicationScoped scope or to the @Dependent pseudo-scope.
+
+ERR_InvalidStatelessBeanScope=A stateless session bean must belong to the @Dependent pseudo-scope.
+
+ERR_IncorrectDelegateCount=A decorator must have exactly one delegate injection point.
+
+ERR_IcorrectScopeWithPublicField=A managed bean with a public field ("{0}") \
+should not declares any scope other than @Dependent.
+
+ERR_IncorrectScopeForParameterizedBean=A managed bean with a parameterized bean \
+class should not declares any scope other than @Dependent.
+
+ERR_FinalInterceptedBean=The bean class of a managed bean is final and declares \
+or inherits a class level interceptor binding or a stereotype with interceptor bindings.
+
+ERR_InterceptedBeanHasFinalMethod=The bean class of a managed bean has non-static, \
+non-private, final method "{0}" and declares or inherits a class level interceptor \
+binding or a stereotype with interceptor bindings.
+
+ERR_NamedSpecializes=Bean declares name explicitly using @Named but it \
+specializes another bean with name.
+
+ERR_BadSpecializesBeanType=Bean specializes another bean but it does not \
+have all bean types of specialized bean.
+
+ERR_InvalidDuplicateIBindings=The set of interceptor bindings has two instances of {0} \
+interceptor binding type and the instances have different values of some annotation member.
+
+WARN_ScopedDecoratorInterceptor=The @Dependent scope is the only scope which \
+interceptor or decorator could have. The non-portable behavior result otherwise.
+
+WARN_NamedInterceptorDecorator=An interceptor or decorator should not have a name. \
+Otherwise non-portable behavior results.
+
+WARN_AlternativeInterceptorDecorator=An interceptor or decorator should not be alternative. \
+Otherwise non-portable behavior results.
+
+WARN_SpecializesInterceptorDecorator=An interceptor or decorator should not \
+have @Specializes annotation. Otherwise non-portable behavior results.
+
+ERR_NotPassivationSessionBean=Session bean has a passivating scope {0} and should be \
+passivation capable. Stateless and singleton session beans are not passivation capable.
+ERR_NotPassivationManagedBean=Bean has a passivating scope {0} and should be \
+passivation capable. Passivation capable bean should be serializable.
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/CtorsAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/CtorsAnalyzer.java
new file mode 100644
index 000000000000..946ea48adaf3
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/CtorsAnalyzer.java
@@ -0,0 +1,67 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassElementAnalyzer.ClassAnalyzer;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class CtorsAnalyzer implements ClassAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassElementAnalyzer.ClassAnalyzer#analyze(javax.lang.model.element.TypeElement, javax.lang.model.element.TypeElement, org.netbeans.api.java.source.CompilationInfo, java.util.List, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ List constructors = ElementFilter.constructorsIn(
+ element.getEnclosedElements());
+ int injectCtorCount = 0;
+ for (ExecutableElement ctor : constructors) {
+ if ( cancel.get() ){
+ return;
+ }
+ if ( AnnotationUtil.hasAnnotation( ctor , AnnotationUtil.INJECT_FQN,
+ result.getInfo()))
+ {
+ result.requireCdiEnabled( ctor );
+ injectCtorCount++;
+ }
+ }
+ if ( injectCtorCount > 1){
+ result.addError( element, NbBundle.getMessage(
+ CtorsAnalyzer.class, "ERR_InjectedCtor"));
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/DeclaredIBindingsAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/DeclaredIBindingsAnalyzer.java
new file mode 100644
index 000000000000..009aa6413088
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/DeclaredIBindingsAnalyzer.java
@@ -0,0 +1,164 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractInterceptedElementAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class DeclaredIBindingsAnalyzer extends
+ AbstractInterceptedElementAnalyzer implements ClassAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer#analyze(javax.lang.model.element.TypeElement, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ Set interceptorBindings = getInterceptorBindings(element,
+ model);
+ Map iBindings = new HashMap();
+ if ( !interceptorBindings.isEmpty() ){
+ result.requireCdiEnabled(element, model);
+ }
+ for (AnnotationMirror annotationMirror : interceptorBindings) {
+ Element iBinding = annotationMirror.getAnnotationType().asElement();
+ AnnotationMirror found = iBindings.get( iBinding );
+ if ( found != null && !isSame( found, annotationMirror ,
+ model.getCompilationController()))
+ {
+ result.addError( element, model,
+ NbBundle.getMessage(DeclaredIBindingsAnalyzer.class,
+ "ERR_InvalidDuplicateIBindings", // NOI18N
+ ((TypeElement)iBinding).getQualifiedName().toString()));
+ break;
+ }
+ else {
+ iBindings.put(iBinding, annotationMirror );
+ }
+ }
+ }
+
+ private boolean isSame( AnnotationMirror first,
+ AnnotationMirror second , CompilationController controller )
+ {
+ Element firstElement = first.getAnnotationType().asElement();
+ Element secondElement = second.getAnnotationType().asElement();
+ if ( !firstElement.equals(secondElement)){
+ return false;
+ }
+ Map extends ExecutableElement, ? extends AnnotationValue> firstValues = first.getElementValues();
+ Map extends ExecutableElement, ? extends AnnotationValue> secondValues = second.getElementValues();
+ if ( firstValues.size() != secondValues.size() ){
+ return false;
+ }
+ for (Entry extends ExecutableElement, ? extends AnnotationValue> entry :
+ firstValues.entrySet())
+ {
+ AnnotationValue secondValue = secondValues.get(entry.getKey());
+ AnnotationValue firstValue = entry.getValue();
+ if ( !isSame( firstValue, secondValue, controller )){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isSame( AnnotationValue first,
+ AnnotationValue second , CompilationController controller)
+ {
+ Object firstValue = first.getValue();
+ Object secondValue = second.getValue();
+ if ( firstValue == null ){
+ return secondValue == null;
+ }
+ if ( firstValue instanceof TypeMirror ){
+ TypeMirror firstMirror = (TypeMirror)firstValue;
+ if ( secondValue instanceof TypeMirror ){
+ return controller.getTypes().isSameType(firstMirror,
+ (TypeMirror)secondValue );
+ }
+ else {
+ return false;
+ }
+ }
+ else if ( firstValue instanceof AnnotationMirror ){
+ if ( secondValue instanceof AnnotationMirror ){
+ return isSame((AnnotationMirror)firstValue, (AnnotationMirror)second,
+ controller);
+ }
+ else {
+ return false;
+ }
+ }
+ else if ( firstValue instanceof List>){
+ if ( secondValue instanceof List>){
+ List> firstList = (List>)firstValue;
+ List> secondList = (List>) secondValue;
+ if ( firstList.size() != secondList.size() ){
+ return false;
+ }
+ for (int i =0; i handle = ElementHandle.create(element);
+ if ( helper != null ){
+ helper.addInterceptedBean( result ,
+ handle.resolve( result.getInfo()));
+ }
+ }
+
+
+ Set modifiers = element.getModifiers();
+ boolean isFinal = modifiers.contains(Modifier.FINAL);
+ List methods = ElementFilter.methodsIn(
+ element.getEnclosedElements());
+ ExecutableElement badMethod = null;
+ for (ExecutableElement method : methods) {
+ if ( cancel.get() ){
+ return;
+ }
+ modifiers = method.getModifiers();
+ if ( !modifiers.contains( Modifier.FINAL )){
+ continue;
+ }
+ if ( modifiers.contains( Modifier.STATIC ) ||
+ modifiers.contains( Modifier.PRIVATE))
+ {
+ continue;
+ }
+ badMethod = method;
+ break;
+ }
+ if ( badMethod == null && !isFinal ){
+ return;
+ }
+ if ( cancel.get() ){
+ return;
+ }
+ if (hasIBindings && isFinal) {
+ result.addError(element, model,
+ NbBundle.getMessage(
+ InterceptedBeanAnalyzer.class,
+ "ERR_FinalInterceptedBean")); // NOI18N
+ }
+ if (hasIBindings && badMethod != null) {
+ result.addError(element, model,
+ NbBundle.getMessage(
+ InterceptedBeanAnalyzer.class,
+ "ERR_InterceptedBeanHasFinalMethod", badMethod
+ .getSimpleName().toString())); // NOI18N
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/ManagedBeansAnalizer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/ManagedBeansAnalizer.java
new file mode 100644
index 000000000000..4724b014774d
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/ManagedBeansAnalizer.java
@@ -0,0 +1,173 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.api.java.source.ElementHandle;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.modules.jakarta.web.beans.hints.EditorAnnotationsHelper;
+import org.netbeans.spi.editor.hints.Severity;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ManagedBeansAnalizer implements ClassAnalyzer {
+
+ private static final String EXTENSION = "jakarta.enterprise.inject.spi.Extension"; //NOI18N
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer#analyze(javax.lang.model.element.TypeElement, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ boolean cdiManaged = model.getQualifiers( element, true ).size()>0;
+ if ( !cdiManaged ){
+ return;
+ }
+ result.requireCdiEnabled(element, model);
+ if (cancel.get()) {
+ return;
+ }
+ checkCtor(element, model, result );
+ if (cancel.get()) {
+ return;
+ }
+ checkInner(element, parent, model, result);
+ if (cancel.get()) {
+ return;
+ }
+ checkAbstract(element, model, result);
+ if (cancel.get()) {
+ return;
+ }
+ checkImplementsExtension(element, model, result);
+ if (cancel.get()) {
+ return;
+ }
+ checkDecorators( element , model , result );
+ }
+
+ private void checkDecorators( TypeElement element, WebBeansModel model,
+ Result result )
+ {
+ Collection decorators = model.getDecorators(element);
+ if ( decorators!= null && decorators.size() >0 ){
+ EditorAnnotationsHelper helper = EditorAnnotationsHelper.getInstance(result);
+ ElementHandle handle = ElementHandle.create(element);
+ if ( helper != null ){
+ helper.addDecoratedBean( result , handle.resolve( result.getInfo() ));
+ }
+ }
+ }
+
+ private void checkImplementsExtension( TypeElement element,
+ WebBeansModel model, Result result )
+ {
+ TypeElement extension = model.getCompilationController().getElements().
+ getTypeElement(EXTENSION);
+ if ( extension == null ){
+ return;
+ }
+ TypeMirror elementType = element.asType();
+ if ( model.getCompilationController().getTypes().isSubtype(
+ elementType, extension.asType())){
+ result.addNotification(Severity.WARNING, element,
+ model, NbBundle.getMessage( ManagedBeansAnalizer.class,
+ "WARN_QualifiedElementExtension")); // NOI18N
+ }
+ }
+
+ private void checkAbstract( TypeElement element,
+ WebBeansModel model, Result result )
+ {
+ Set modifiers = element.getModifiers();
+ if ( modifiers.contains( Modifier.ABSTRACT )){
+ if ( AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.DECORATOR, model.getCompilationController()) ){
+ return;
+ }
+
+ // element is abstract and has no Decorator annotation
+ result.addNotification( Severity.WARNING, element, model,
+ NbBundle.getMessage(ManagedBeansAnalizer.class,
+ "WARN_QualifierAbstractClass")); // NOI18N
+ }
+ }
+
+ private void checkInner( TypeElement element, TypeElement parent,
+ WebBeansModel model, Result result )
+ {
+ if ( parent == null ){
+ return;
+ }
+ Set modifiers = element.getModifiers();
+ if ( !modifiers.contains( Modifier.STATIC )){
+ result.addError(element, model,
+ NbBundle.getMessage(ManagedBeansAnalizer.class,
+ "ERR_NonStaticInnerType")); // NOI18N
+ }
+ }
+
+ private void checkCtor( TypeElement element, WebBeansModel model,
+ Result result )
+ {
+ List ctors = ElementFilter.constructorsIn(
+ element.getEnclosedElements());
+ for (ExecutableElement ctor : ctors) {
+ Set modifiers = ctor.getModifiers();
+ if ( modifiers.contains( Modifier.PRIVATE )){
+ continue;
+ }
+ List extends VariableElement> parameters = ctor.getParameters();
+ if ( parameters.size() ==0 ){
+ return;
+ }
+ if ( AnnotationUtil.hasAnnotation(ctor, AnnotationUtil.INJECT_FQN,
+ model.getCompilationController()))
+ {
+ return;
+ }
+ }
+ // there is no non-private ctors without params or annotated with @Inject
+ result.addNotification( Severity.WARNING, element, model,
+ NbBundle.getMessage(ManagedBeansAnalizer.class,
+ "WARN_QualifierNoCtorClass")); // NOI18N
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/NamedModelAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/NamedModelAnalyzer.java
new file mode 100644
index 000000000000..81503316f9d0
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/NamedModelAnalyzer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class NamedModelAnalyzer implements ClassAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer#analyze(javax.lang.model.element.TypeElement, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ if ( !AnnotationUtil.hasAnnotation(element, AnnotationUtil.SPECIALIZES,
+ model.getCompilationController()))
+ {
+ return;
+ }
+ result.requireCdiEnabled(element, model);
+ if ( !AnnotationUtil.hasAnnotation(element, AnnotationUtil.NAMED,
+ model.getCompilationController()))
+ {
+ return;
+ }
+ TypeMirror superclass = element.getSuperclass();
+ Element superElement = model.getCompilationController().getTypes().
+ asElement( superclass );
+ if ( cancel.get() ){
+ return;
+ }
+ String name = model.getName(superElement);
+ if ( name == null ){
+ return;
+ }
+ result.addError( element, model, NbBundle.getMessage(
+ NamedModelAnalyzer.class, "ERR_NamedSpecializes")); // NOI18N
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/ScopedBeanAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/ScopedBeanAnalyzer.java
new file mode 100644
index 000000000000..45ffa366548a
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/ScopedBeanAnalyzer.java
@@ -0,0 +1,225 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.netbeans.spi.editor.hints.Severity;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ScopedBeanAnalyzer extends AbstractScopedAnalyzer
+ implements ClassAnalyzer
+{
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer#analyze(javax.lang.model.element.TypeElement, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel,
+ Result result )
+ {
+ analyzeScope(element, model, cancel , result );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractScopedAnalyzer#checkScope(javax.lang.model.element.TypeElement, javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ protected void checkScope( TypeElement scopeElement, Element element,
+ WebBeansModel model, AtomicBoolean cancel , Result result )
+ {
+ if ( cancel.get() ){
+ return;
+ }
+ checkProxiability(scopeElement, element, model, result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkPublicField(scopeElement , element , model , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkParameterizedBean(scopeElement , element , model , result );
+ if ( cancel.get() ){
+ return;
+ }
+ checkInterceptorDecorator( scopeElement , element , model , result);
+ if ( cancel.get() ){
+ return;
+ }
+ checkPassivationCapable( scopeElement , element , model , result );
+ }
+
+ private void checkPassivationCapable( TypeElement scopeElement,
+ Element element, WebBeansModel model, Result result )
+ {
+ if ( !isPassivatingScope(scopeElement, model) ){
+ return;
+ }
+ if ( AnnotationUtil.isSessionBean(element, model.getCompilationController())){
+ if ( AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.STATEFUL, model.getCompilationController()))
+ {
+ return;
+ }
+ else {
+ result.addError(element, model ,
+ NbBundle.getMessage(ScopedBeanAnalyzer.class,
+ "ERR_NotPassivationSessionBean", // NOI18N
+ scopeElement.getQualifiedName().toString()));
+ return;
+ }
+ }
+ if ( !isSerializable(element, model) ){
+ result.addError(element, model ,
+ NbBundle.getMessage(ScopedBeanAnalyzer.class,
+ "ERR_NotPassivationManagedBean", // NOI18N
+ scopeElement.getQualifiedName().toString()));
+ }
+ // TODO : all interceptors ans decorators of bean should be also passivation capable
+ }
+
+ private void checkInterceptorDecorator( TypeElement scopeElement,
+ Element element, WebBeansModel model, Result result )
+ {
+ if ( scopeElement.getQualifiedName().contentEquals(AnnotationUtil.DEPENDENT)){
+ return;
+ }
+ AnnotationMirror annotationMirror = AnnotationUtil.getAnnotationMirror(
+ element, model.getCompilationController(),
+ AnnotationUtil.INTERCEPTOR, AnnotationUtil.DECORATOR);
+ if ( annotationMirror!= null ){
+ result.addNotification( Severity.WARNING, element, model,
+ NbBundle.getMessage(ScopedBeanAnalyzer.class,
+ "WARN_ScopedDecoratorInterceptor" )); // NOI18N
+ }
+ }
+
+ private void checkParameterizedBean( TypeElement scopeElement,
+ Element element, WebBeansModel model,
+ Result result )
+ {
+ if ( AnnotationUtil.DEPENDENT.contentEquals(
+ scopeElement.getQualifiedName()))
+ {
+ return;
+ }
+ result.requireCdiEnabled(element, model);
+ TypeMirror type = element.asType();
+ if ( type instanceof DeclaredType ){
+ List extends TypeMirror> typeArguments = ((DeclaredType)type).getTypeArguments();
+ if ( typeArguments.size() != 0 ){
+ result.addError(element, model,
+ NbBundle.getMessage(ScopedBeanAnalyzer.class,
+ "ERR_IncorrectScopeForParameterizedBean" )); // NOI18N
+ }
+ }
+ }
+
+ private void checkPublicField( TypeElement scopeElement, Element element,
+ WebBeansModel model, Result result )
+ {
+ if ( AnnotationUtil.DEPENDENT.contentEquals(
+ scopeElement.getQualifiedName()))
+ {
+ return;
+ }
+ result.requireCdiEnabled(element, model);
+ List fields = ElementFilter.fieldsIn(
+ element.getEnclosedElements());
+ for (VariableElement field : fields) {
+ Set modifiers = field.getModifiers();
+ if ( modifiers.contains(Modifier.PUBLIC )
+ && (!modifiers.contains(Modifier.STATIC) || !model.isCdi11OrLater())){
+ result.addError(element, model ,
+ NbBundle.getMessage(ScopedBeanAnalyzer.class,
+ "ERR_IcorrectScopeWithPublicField",
+ field.getSimpleName().toString()));
+ return;
+ }
+ }
+ }
+
+ private void checkProxiability( TypeElement scopeElement, Element element,
+ WebBeansModel model, Result result )
+ {
+ boolean isNormal = AnnotationUtil.hasAnnotation(scopeElement,
+ AnnotationUtil.NORMAL_SCOPE_FQN, model.getCompilationController());
+ if ( isNormal ){
+ result.requireCdiEnabled(element, model);
+ checkFinal( element , model, result );
+ }
+ }
+
+ private void checkFinal( Element element, WebBeansModel model,
+ Result result )
+ {
+ if ( !( element instanceof TypeElement )){
+ return;
+ }
+ Set modifiers = element.getModifiers();
+ if ( modifiers.contains( Modifier.FINAL) ){
+ result.addError( element, model,
+ NbBundle.getMessage(ScopedBeanAnalyzer.class,
+ "ERR_FinalScopedClass"));
+ return;
+ }
+ List methods = ElementFilter.methodsIn(
+ element.getEnclosedElements());
+ for (ExecutableElement method : methods) {
+ modifiers = method.getModifiers();
+ if (modifiers.contains(Modifier.FINAL)) {
+ result.addNotification( Severity.WARNING, method, model,
+ NbBundle.getMessage(
+ ScopedBeanAnalyzer.class,
+ "WARN_FinalScopedClassMethod"));
+ }
+ }
+ }
+
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/SessionBeanAnalyzer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/SessionBeanAnalyzer.java
new file mode 100644
index 000000000000..e13377f48e01
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/SessionBeanAnalyzer.java
@@ -0,0 +1,89 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AnnotationUtil;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ModelAnalyzer.Result;
+import org.netbeans.modules.jakarta.web.beans.api.model.CdiException;
+import org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class SessionBeanAnalyzer implements ClassAnalyzer {
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassModelAnalyzer.ClassAnalyzer#analyze(javax.lang.model.element.TypeElement, javax.lang.model.element.TypeElement, org.netbeans.modules.jakarta.web.beans.api.model.WebBeansModel, java.util.List, org.netbeans.api.java.source.CompilationInfo, java.util.concurrent.atomic.AtomicBoolean)
+ */
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ WebBeansModel model, AtomicBoolean cancel ,
+ Result result )
+ {
+ boolean isSingleton = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.SINGLETON, model.getCompilationController());
+ boolean isStateless = AnnotationUtil.hasAnnotation(element,
+ AnnotationUtil.STATELESS, model.getCompilationController());
+ if ( cancel.get() ){
+ return;
+ }
+ try {
+ String scope = model.getScope( element );
+ if ( isSingleton ) {
+ if ( AnnotationUtil.APPLICATION_SCOPED.equals( scope ) ||
+ AnnotationUtil.DEPENDENT.equals( scope ) )
+ {
+ return;
+ }
+ result.requireCdiEnabled(element, model);
+ result.addError( element, model,
+ NbBundle.getMessage(SessionBeanAnalyzer.class,
+ "ERR_InvalidSingletonBeanScope")); // NOI18N
+ }
+ else if ( isStateless ) {
+ if ( !AnnotationUtil.DEPENDENT.equals( scope ) )
+ {
+ result.addError( element, model,
+ NbBundle.getMessage(SessionBeanAnalyzer.class,
+ "ERR_InvalidStatelessBeanScope")); // NOI18N
+ }
+ }
+ }
+ catch (CdiException e) {
+ result.requireCdiEnabled(element, model);
+ informCdiException(e, element, model, result );
+ }
+ }
+
+ private void informCdiException(CdiException exception , Element element,
+ WebBeansModel model, Result result )
+ {
+ result.addError(element, model, exception.getMessage());
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/TypedClassAnalizer.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/TypedClassAnalizer.java
new file mode 100644
index 000000000000..f25e404250ea
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/analysis/analyzer/type/TypedClassAnalizer.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.jakarta.web.beans.analysis.analyzer.type;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.modules.jakarta.web.beans.analysis.CdiAnalysisResult;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer;
+import org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ClassElementAnalyzer.ClassAnalyzer;
+import org.openide.util.NbBundle;
+
+
+/**
+ * @author ads
+ *
+ */
+public class TypedClassAnalizer extends AbstractTypedAnalyzer implements
+ ClassAnalyzer
+{
+
+ @Override
+ public void analyze( TypeElement element, TypeElement parent,
+ AtomicBoolean cancel, CdiAnalysisResult result )
+ {
+ analyze(element, element.asType() , cancel , result );
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer#addError(javax.lang.model.element.Element, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void addError( Element element, CdiAnalysisResult result )
+ {
+ result.addError( element, NbBundle.getMessage(
+ TypedClassAnalizer.class, "ERR_BadRestritedType")); // NOI18N
+ }
+
+ /* (non-Javadoc)
+ * @see org.netbeans.modules.jakarta.web.beans.analysis.analyzer.AbstractTypedAnalyzer#checkSpecializes(javax.lang.model.element.Element, javax.lang.model.type.TypeMirror, java.util.List, java.util.concurrent.atomic.AtomicBoolean, org.netbeans.modules.jakarta.web.beans.analysis.analyzer.ElementAnalyzer.Result)
+ */
+ @Override
+ protected void checkSpecializes( Element element, TypeMirror elementType,
+ List restrictedTypes, AtomicBoolean cancel , CdiAnalysisResult result )
+ {
+ TypeElement typeElement = (TypeElement)element;
+ TypeMirror superclass = typeElement.getSuperclass();
+ Element superElement = result.getInfo().getTypes().asElement(superclass);
+ if ( !( superElement instanceof TypeElement )){
+ return;
+ }
+ List restrictedSuper = getRestrictedTypes(superElement,
+ result.getInfo(), cancel);
+ if ( cancel.get()){
+ return;
+ }
+ /*
+ * No need to look at the TypeMirrors here. The correctness of the
+ * bean types are guaranteed by inheritance hierarchy.
+ * TypeMirrors here couldn't be arrays or primitives.
+ * ( But it is possible for production elements where TypeMirrors shouldn't
+ * be checked only against corresponding TypeElement ).
+ */
+
+ Set specializedBeanTypes;
+ if ( restrictedSuper == null ){
+ specializedBeanTypes = getUnrestrictedBeanTypes(
+ (TypeElement)superElement, result.getInfo());
+ }
+ else {
+ specializedBeanTypes = getElements( restrictedSuper, result.getInfo());
+ }
+ Set restrictedElements = getElements(restrictedTypes,
+ result.getInfo());
+ restrictedElements.add( result.getInfo().getElements().getTypeElement(
+ Object.class.getCanonicalName()));
+ if ( !restrictedElements.containsAll(specializedBeanTypes)){
+ result.addError( element, NbBundle.getMessage(
+ TypedClassAnalizer.class, "ERR_BadSpecializesBeanType")); // NOI18N
+ }
+ }
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/AbstractModelImplementation.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/AbstractModelImplementation.java
new file mode 100644
index 000000000000..41a6ea2efa0b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/AbstractModelImplementation.java
@@ -0,0 +1,68 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.util.Collection;
+
+import org.netbeans.modules.jakarta.web.beans.model.spi.WebBeansModelProvider;
+import org.netbeans.modules.jakarta.web.beans.model.spi.WebBeansModelProviderFactory;
+import org.openide.util.Lookup;
+
+
+/**
+ * @author ads
+ *
+ */
+public abstract class AbstractModelImplementation {
+
+ protected AbstractModelImplementation( ModelUnit unit ){
+ myUnit = unit;
+ myModel = new WebBeansModel( this );
+ Collection extends WebBeansModelProviderFactory> factories =
+ Lookup.getDefault().lookupAll(
+ WebBeansModelProviderFactory.class);
+ for( WebBeansModelProviderFactory factory : factories ){
+ myProvider = factory.createWebBeansModelProvider(this);
+ if ( myProvider != null ){
+ break;
+ }
+ }
+
+ }
+
+ public ModelUnit getModelUnit(){
+ return myUnit;
+ }
+
+ public BeansModel getBeansModel(){
+ return BeansModelFactory.getModel(getModelUnit());
+ }
+
+ protected WebBeansModel getModel(){
+ return myModel;
+ }
+
+ protected WebBeansModelProvider getProvider(){
+ return myProvider;
+ }
+
+ private ModelUnit myUnit;
+ private WebBeansModel myModel;
+ private WebBeansModelProvider myProvider;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeanArchiveType.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeanArchiveType.java
new file mode 100644
index 000000000000..e77dfb73cf15
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeanArchiveType.java
@@ -0,0 +1,29 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+/**
+ * Defines whether the given project (model) internally work with implicit or explicite bean archive.
+ * @author Martin Fousek
+ */
+public enum BeanArchiveType {
+ NONE,//not an archive
+ IMPLICIT,//annotated
+ EXPLICIT;//all
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansModel.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansModel.java
new file mode 100644
index 000000000000..791e76392b7b
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansModel.java
@@ -0,0 +1,61 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+
+/**
+ * Merged model for beans.xml files.
+ * @author ads
+ *
+ */
+public interface BeansModel {
+
+ /**
+ * @return all interceptor classes FQNs found in beans.xml files
+ */
+ LinkedHashSet getInterceptorClasses();
+
+ /**
+ * @return all decorator classes FQNs found in beans.xml files
+ */
+ LinkedHashSet getDecoratorClasses();
+
+ /**
+ * @return all alternative classes FQNs found in beans.xml files
+ */
+ Set getAlternativeClasses();
+
+ /**
+ * @return all alternative stereotypes FQNs found in beans.xml files
+ */
+ Set getAlternativeStereotypes();
+
+ /**
+ * Gets information about the Bean Archive type of the project.
+ * Introduced by CDI 1.1 with implicit bean archive.
+ * @return bean archive type, never {@code null}
+ */
+ BeanArchiveType getBeanArchiveType();
+
+ boolean isCdi11OrLater();
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansModelFactory.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansModelFactory.java
new file mode 100644
index 000000000000..9d2a1a80b355
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansModelFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.netbeans.modules.jakarta.web.beans.impl.model.BeansModelImpl;
+
+
+/**
+ * @author ads
+ *
+ */
+public final class BeansModelFactory {
+
+ private BeansModelFactory(){
+ }
+
+ public static BeansModel createModel( ModelUnit unit ){
+ return new BeansModelImpl(unit);
+ }
+
+ public static synchronized BeansModel getModel( ModelUnit unit ){
+ BeansModel model = MODELS.get( unit );
+ if ( model == null ){
+ model = createModel( unit );
+ MODELS.put(unit, model);
+ }
+ return model;
+ }
+
+ private static final Map MODELS =
+ new WeakHashMap();
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansResult.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansResult.java
new file mode 100644
index 000000000000..9a1c0df9706a
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/BeansResult.java
@@ -0,0 +1,35 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import javax.lang.model.element.Element;
+
+
+/**
+ * Common interface for result that contains elements which
+ * can be enabled/disabled via beans.xml file.
+ *
+ * @author ads
+ *
+ */
+public interface BeansResult {
+
+ boolean isDisabled( Element element );
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/CdiException.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/CdiException.java
new file mode 100644
index 000000000000..ca5b1812ad9e
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/CdiException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+
+/**
+ * @author ads
+ *
+ */
+public class CdiException extends Exception {
+
+ private static final long serialVersionUID = 8768805477182583488L;
+
+ public CdiException( String message ){
+ super( message );
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/DependencyInjectionResult.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/DependencyInjectionResult.java
new file mode 100644
index 000000000000..0e29d76d363f
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/DependencyInjectionResult.java
@@ -0,0 +1,119 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.util.Set;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+
+/**
+ * Represent eligible for injection element search result.
+ *
+ * @author ads
+ *
+ */
+public interface DependencyInjectionResult {
+
+ enum ResultKind {
+ /**
+ * This kind correspond to Error result only
+ */
+ DEFINITION_ERROR,
+ /**
+ * This kind represents at least InjectableResult and ResolutionResult.
+ * Also there could be additional hints with set of eligible for injection
+ * elements ( which are disabled , turned off alternatives, .... )
+ * represented by ApplicableResult.
+ */
+ INJECTABLE_RESOLVED,
+ /**
+ * - No eligible for injection element found at all
+ * - Only disabled beans are found
+ * - Ambiguous dependencies result
+ * It could be represented by Error only ( nothing found
+ * at all ) or Error, ResolutionResult and ApplicableResult with
+ * information about probable eligible for injection elements.
+ */
+ RESOLUTION_ERROR,
+ /**
+ * This kind is like INJECTABLE_RESOLVED but it can contain
+ * several eligible for injection elements from very beginning.
+ * It is used when multiple eligible for injection elements are
+ * valid result. F.e. it is normal to find a number elements
+ * via programmatic lookup .
+ * It is represented at least by ApplicableResult and ResolutionResult.
+ */
+ INJECTABLES_RESOLVED,
+ }
+
+ /**
+ * @return element injection point which is used for injectable search
+ */
+ VariableElement getVariable();
+
+ TypeMirror getVariableType();
+
+ ResultKind getKind();
+
+ interface Error extends DependencyInjectionResult {
+
+ String getMessage();
+ }
+
+ interface ResolutionResult extends DependencyInjectionResult, Result {
+
+ /**
+ * Check whether element
is alternative.
+ * element
could be eligible for injection element
+ * ( which is found as result here ) or stereotype.
+ * @param element checked element
+ * @return true if element
is alternative
+ */
+ boolean isAlternative( Element element );
+
+ boolean hasAlternative( Element element );
+ }
+
+ interface InjectableResult extends DependencyInjectionResult {
+ /**
+ * null
is returned if there is no eligible element for injection
+ * ( no element which could be a pretender).
+ *
+ * it could be a result of unsatisfied or ambiguous dependency.
+ * F.e. unsatisfied dependency : there is a pretender satisfy typesafe
+ * resolution but something incorrect ( parameterized type is not valid , etc. ).
+ * Ambiguous dependency : there are a number of appropriate elements.
+ *
+ *
+ * @return element ( type definition, production field/method)
+ * that is used in injected point identified by {@link #getVariable()}
+ */
+ Element getElement();
+ }
+
+ interface ApplicableResult extends DependencyInjectionResult, BeansResult {
+ public Set getTypeElements();
+
+ public Set getProductions();
+ }
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/InjectionPointDefinitionError.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/InjectionPointDefinitionError.java
new file mode 100644
index 000000000000..aca0bda1be35
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/InjectionPointDefinitionError.java
@@ -0,0 +1,53 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import javax.lang.model.element.Element;
+
+
+/**
+ * This exception could be thrown when injection point deifinition
+ * contains error.
+ * @author ads
+ *
+ */
+public class InjectionPointDefinitionError extends CdiException {
+
+ private static final long serialVersionUID = -6893993336079352757L;
+
+ public InjectionPointDefinitionError(Element errorElement, String msg) {
+ super( msg );
+ myElement = errorElement;
+ }
+
+ /**
+ * There could be errors detected when element is checked as injection point.
+ * In most such cases possible injection point is the error element.
+ * But in some cases error could be detected on enclosing element.
+ * F.e. method could be wrongly defined . In this case its parameters
+ * cannot be considered as correct injection points.
+ *
+ * @return element that is wrongly defined
+ */
+ public Element getErrorElement(){
+ return myElement;
+ }
+
+ private Element myElement;
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/InterceptorsResult.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/InterceptorsResult.java
new file mode 100644
index 000000000000..76eecb47d7bf
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/InterceptorsResult.java
@@ -0,0 +1,58 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.util.List;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
+
+/**
+ * @author ads
+ *
+ */
+public interface InterceptorsResult extends Result, BeansResult {
+
+ /**
+ * Subject element accessor .
+ * @return element which is used for interceptor resolution
+ */
+ Element getElement();
+
+ /**
+ * Returns interceptors which have @Interceptor annotation and
+ * meets the interceptor resolution requirements.
+ * @return result of interceptor resolution.
+ */
+ List getResolvedInterceptors();
+
+ /**
+ * Interceptors could be assigned via @Interceptors annotation.
+ * @return explicitly declared interceptors
+ */
+ List getDeclaredInterceptors();
+
+ /**
+ * The result is union of resolved and declared interceptors.
+ * @return all available interceptors
+ */
+ List getAllInterceptors();
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/ModelUnit.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/ModelUnit.java
new file mode 100644
index 000000000000..4a7b9d205683
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/ModelUnit.java
@@ -0,0 +1,133 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.net.URISyntaxException;
+
+import org.netbeans.api.java.classpath.ClassPath;
+import org.netbeans.api.java.source.ClasspathInfo;
+import org.netbeans.api.project.Project;
+import org.openide.filesystems.FileObject;
+
+
+/**
+ * @author ads
+ *
+ */
+public class ModelUnit {
+
+ private ModelUnit( ClassPath bootPath, ClassPath compilePath,
+ ClassPath sourcePath, Project project)
+ {
+ myBootPath= bootPath;
+ myCompilePath = compilePath;
+ mySourcePath = sourcePath;
+ myProject = project;
+ myClassPathInfo = ClasspathInfo.create(bootPath,
+ compilePath, sourcePath);
+ }
+
+ public ClassPath getBootPath() {
+ return myBootPath;
+ }
+
+ public ClassPath getCompilePath() {
+ return myCompilePath;
+ }
+
+ public ClassPath getSourcePath() {
+ return mySourcePath;
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ @Override
+ public int hashCode() {
+ return 37*(37*myBootPath.hashCode() + myCompilePath.hashCode())
+ +mySourcePath.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ModelUnit) {
+ ModelUnit unit = (ModelUnit) obj;
+ return myBootPath.equals( unit.myBootPath ) && myCompilePath.equals(
+ unit.myCompilePath ) && mySourcePath.equals( mySourcePath );
+ }
+ else {
+ return false;
+ }
+ }
+
+ public static ModelUnit create(ClassPath bootPath, ClassPath compilePath,
+ ClassPath sourcePath, Project project)
+ {
+ return new ModelUnit(bootPath, compilePath, sourcePath, project);
+ }
+
+ public ClasspathInfo getClassPathInfo(){
+ return myClassPathInfo;
+ }
+
+ private static boolean equals(ClassPath cp1, ClassPath cp2) {
+ if (cp1.entries().size() != cp2.entries().size()) {
+ return false;
+ }
+ for (int i = 0; i < cp1.entries().size(); i++) {
+ try {
+ if (!cp1.entries().get(i).getURL().toURI()
+ .equals(cp2.entries().get(i).getURL().toURI()))
+ {
+ return false;
+ }
+ }
+ catch (URISyntaxException e) {
+ if ( !cp1.entries().get(i).equals(cp2.entries().get(i)) ){
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static int computeClassPathHash(ClassPath classPath) {
+ int hashCode = 0;
+ for (ClassPath.Entry entry : classPath.entries()) {
+ hashCode = 37*hashCode + entry.getURL().getPath().hashCode();
+ }
+ return hashCode;
+ }
+
+ FileObject getSourceFileObject(){
+ FileObject[] roots = mySourcePath.getRoots();
+ if ( roots!= null && roots.length >0 ){
+ return roots[0];
+ }
+ return null;
+ }
+
+ private final ClasspathInfo myClassPathInfo;
+ private final ClassPath myBootPath;
+ private final ClassPath myCompilePath;
+ private final ClassPath mySourcePath;
+ private final Project myProject;
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/Result.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/Result.java
new file mode 100644
index 000000000000..a4021a5d2de6
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/Result.java
@@ -0,0 +1,45 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.util.List;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+
+
+/**
+ * Common interface for results that contains elements with stereotypes.
+ *
+ * @author ads
+ *
+ */
+public interface Result {
+
+ /**
+ * Return list of all element's stereotypes ( including recursively
+ * inherited ).
+ * @param element element with stereotypes
+ * @return list of element's stereotypes
+ */
+ List getAllStereotypes( Element element );
+
+ List getStereotypes( Element element );
+
+}
diff --git a/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/WebBeansModel.java b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/WebBeansModel.java
new file mode 100644
index 000000000000..bec135996eaf
--- /dev/null
+++ b/enterprise/jakarta.web.beans/src/org/netbeans/modules/jakarta/web/beans/api/model/WebBeansModel.java
@@ -0,0 +1,303 @@
+/*
+ * 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.netbeans.modules.jakarta.web.beans.api.model;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+import org.netbeans.api.java.source.CompilationController;
+import org.netbeans.modules.jakarta.web.beans.impl.model.WebBeansModelProviderImpl;
+import org.netbeans.modules.jakarta.web.beans.model.spi.WebBeansModelProvider;
+
+
+/**
+ * @author ads
+ *
+ */
+public final class WebBeansModel {
+
+ WebBeansModel( AbstractModelImplementation impl ){
+ myImpl = impl;
+ }
+
+ /**
+ * Find injectable elements that could be used for given injection point.
+ *
+ *