8 Replies Latest reply on Mar 25, 2008 3:25 PM by Adrian Brock

    Getting content of XML element

    Kabir Khan Master

      Can somebody please tell me how to get the contents of the annotation? i.e. I want: @org.jboss.test.microcontainer.beans2.Annotation1. It does not appear to be accessible from any of the things passed in to the methods of AnnotationOverrideHandler?

      Also, for a similar schenario I will need to construct a org.w3c.dom.Element from the nested contents of a element. Is that possible?

      Schema:

      <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       targetNamespace="urn:jboss:aop-beans:1.0"
       xmlns="urn:jboss:aop-beans:1.0"
       xmlns:mc="urn:jboss:bean-deployer:2.0"
       elementFormDefault="qualified"
       attributeFormDefault="unqualified"
       version="1.0"
      >
       ...
      
       <xsd:element name="annotation" type="annotationType">
       <xsd:annotation>
       <xsd:documentation>
       <![CDATA[
       A annotation override
       ]]>
       </xsd:documentation>
       </xsd:annotation>
       </xsd:element>
      
       <xsd:complexType name="annotationType">
       <xsd:annotation>
       <xsd:documentation>
       <![CDATA[
       A annotation override
       ]]>
       </xsd:documentation>
       </xsd:annotation>
       <xsd:complexContent>
       <xsd:attribute name="expr" type="xsd:string" use="required"/>
       <xsd:attribute name="invisible" type="xsd:string" use="required"/>
       </xsd:complexContent>
       </xsd:complexType>
      
      </xsd:schema>
      
      


      XML:
      <?xml version="1.0" encoding="UTF-8"?>
      
      <deployment xmlns="urn:jboss:bean-deployer:2.0">
      ...
       <annotation xmlns="urn:jboss:aop-beans:1.0" expr="class(org.jboss.test.microcontainer.beans2.POJO)" invisible="false">
       @org.jboss.test.microcontainer.beans2.Annotation1
       </annotation>
      ...
      </deployment>
      
      


      SchemaBindingIntitializer:
      public class AOPBeansSchemaInitializer implements SchemaBindingInitializer
      {
      ...
      
       private static final QName annotationTypeQName = new QName(AOP_BEANS_NS, "annotationType");
      
       TypeBinding type = schema.getType(annotationTypeQName);
       type.setHandler(AnnotationOverrideHandler.HANDLER);
       //type.pushInterceptor(annotationQName, AnnotationContentInterceptor.INTERCEPTOR);
      ....
      
      
       private static class AnnotationOverrideHandler extends DefaultElementHandler
       {
       public static final AnnotationOverrideHandler HANDLER = new AnnotationOverrideHandler();
      
       @Override
       public Object startElement(Object parent, QName name, ElementBinding element)
       {
       return new AbstractBeanMetaData(AnnotationOverride.class.getName());
       }
      
       @Override
       public void attributes(Object o, QName elementName, ElementBinding element, Attributes attrs, NamespaceContext nsCtx)
       {
       AspectBeanMetaDataUtil util = new AspectBeanMetaDataUtil();
       AbstractBeanMetaData pointcut = (AbstractBeanMetaData)o;
      
       for (int i = 0; i < attrs.getLength(); ++i)
       {
       ....
       }
       }
      
       @Override
       public Object endElement(Object o, QName name, ElementBinding element)
       {
       return super.endElement(o, name, element);
       }
      
      
       }
      
       private static class AnnotationContentInterceptor extends DefaultElementInterceptor
       {
       public static final AnnotationContentInterceptor INTERCEPTOR = new AnnotationContentInterceptor();
      
       @Override
       public void add (Object parent, Object child, QName name)
       {
       System.out.println("-----------> " + child);
       }
       }
      }
      


        • 1. Re: Getting content of XML element
          Adrian Brock Master

           


          <xsd:complexType name="annotationType">
          <xsd:annotation>
          <xsd:documentation>
          <![CDATA[
          A annotation override
          ]]>
          </xsd:documentation>
          </xsd:annotation>
          <xsd:complexContent>
          <xsd:attribute name="expr" type="xsd:string" use="required"/>
          <xsd:attribute name="invisible" type="xsd:string" use="required"/>
          </xsd:complexContent>
          </xsd:complexType>


          Shouldn't his be in the JBossXB forum? :-)

          You need to use either simpleContent and/or mixed=true

          e.g. (with attributes - the alias type in the MC)
           <xsd:complexType name="aliasType" mixed="true">
           <xsd:annotation>
           <xsd:documentation>
           <![CDATA[
           Bean's aliases.
          
           e.g.
           <bean name="MyName" class="com.acme.POJO">
           <alias>YourName</alias>
           <alias><value class="java.lang.Class">com.acme.POJO</value></alias>
           <alias><value class="java.lang.Integer">1234</value></alias>
           </bean>
           ]]>
           </xsd:documentation>
           </xsd:annotation>
           <xsd:simpleContent>
           <xsd:extension base="xsd:string">
           <xsd:attribute name="class" type="classNameType" use="optional"/>
           <xsd:attribute name="replace" type="xsd:boolean"/>
           </xsd:extension>
           </xsd:simpleContent>
           </xsd:complexType>
          


          Then you need a characters handler like
          org.jboss.kernel.plugins.deployment.xml.AnnotationCharactersHandler

           TypeBinding annotationType = schemaBinding.getType(annotationTypeQName);
          
           ...
          
           // annotation can take characters
           annotationType.setSimpleType(AnnotationCharactersHandler.HANDLER);
          


          • 2. Re: Getting content of XML element
            Adrian Brock Master

             

            "kabir.khan@jboss.com" wrote:

            Also, for a similar schenario I will need to construct a org.w3c.dom.Element from the nested contents of a element. Is that possible?


            It works with the annotation based parsing.
            public class ElementWildcard
            {
             private Element wildcard;
            
             public Element getWildcard()
             {
             return wildcard;
             }
            
             @XmlAnyElement(lax=true)
             public void setWildcard(Element wildcard)
             {
             this.wildcard = wildcard;
             }
            }
            

            I couldn't get it to work properly with the old parser.

            Why do you want to do this? This is usually horrible.
            Is this the old XmlLoadable stuff?

            You should remove this, and configure them using the MC as normal beans.

            Then if somebody really wants to do this horrible thing you just do
            <property name='bad" type="org.w3c.dom.Element"><![CDATA[<xml-here/>]]></property>
            


            • 3. Re: Getting content of XML element
              Kabir Khan Master

               

              "adrian@jboss.org" wrote:

              Why do you want to do this? This is usually horrible.
              Is this the old XmlLoadable stuff?


              It is to support the ClassMetaData stuff, e.g. I need to be able to translate the following -aop.xml style stuff
               <metadata tag="SomeTag" class="org.jboss.test.aop.bean.POJOConstructorTest">
               <constructor expr="POJO()">
               <data>ctor</data>
               </constructor>
               <method expr="int *(..)">
               <data>method1</data>
               </method>
               <method expr="void *()">
               <data>method2</data>
               </method>
               </metadata>
              


              into

               <bean name="ClassMetaData" class="org.jboss.aop.microcontainer.beans2.ClassMetaData">
               <property name="manager"><inject bean="AspectManager"/></property>
               <property name="tag">SomeTag</property>
               <property name="className">org.jboss.test.microcontainer.beans2.POJO</property>
               <property name="element">
               <![CDATA[
               <metadata>
               <constructor expr="POJO()">
               <data>ctor</data>
               </constructor>
               <method expr="int *(..)">
               <data>method1</data>
               </method>
               <method expr="void *()">
               <data>method2</data>
               </method>
               </metadata>
               ]]>
               </property>
               </bean>
              


              • 4. Re: Getting content of XML element
                Adrian Brock Master

                 

                "kabir.khan@jboss.com" wrote:
                "adrian@jboss.org" wrote:

                Why do you want to do this? This is usually horrible.
                Is this the old XmlLoadable stuff?


                It is to support the ClassMetaData stuff, e.g. I need to be able to translate the following -aop.xml style stuff


                That doesn't make sense, you should be able to parse it to a real model,
                e.g. in JAXB.

                @XmlType(name="metadata")
                public class AOPClassMetaData
                {
                 @XmlAttribute(name="tag")
                 private String tag;
                
                 @XmlAttribute(name="class")
                 private String name;
                
                 @XmlElement(name="constructor")
                 private Collection<AOPConstructorMetaData> constructors;
                
                 // etc.
                }
                


                Why a DOM element and then reparse inside AOP?

                • 5. Re: Getting content of XML element
                  Kabir Khan Master

                   

                  "adrian@jboss.org" wrote:

                  Why a DOM element and then reparse inside AOP?


                  That's the way the AOP metadata stuff works, the xml is pretty freeform and the metadataloader's can be swapped out. You can basically make it take any xml you like

                  • 6. Re: Getting content of XML element
                    Adrian Brock Master

                     

                    "kabir.khan@jboss.com" wrote:
                    "adrian@jboss.org" wrote:

                    Why a DOM element and then reparse inside AOP?


                    That's the way the AOP metadata stuff works, the xml is pretty freeform and the metadataloader's can be swapped out. You can basically make it take any xml you like


                    "Because that's the way it does it", is not an answer. :-)
                    If its broken we need to fix it. How do you expect the management console to
                    deal with this?

                    • 7. Re: Getting content of XML element
                      Kabir Khan Master

                      Revisiting this, as first implemented by Bill there are pluggable metadata loaders. The simplest case using the "standard" metadata loader is shown here:

                       <metadata tag="test" class="org.jboss.test.aop.bean.POJOConstructorTest">
                       <constructor expr="POJOConstructorTest()">
                       <data>empty</data>
                       </constructor>
                       <method expr="* another()">
                       <data>another()</data>
                       </method>
                       <field expr="void another(int, int)">
                       <data>another(int, int)</data>
                       </field>
                       </metadata>
                      


                      and
                       <metadata tag="introduction-tag" class="org.jboss.test.aop.bean.NoInterceptorsPOJO">
                       <class/> <!-- just tagging the class -->
                       </metadata>
                      


                      and
                       <metadata tag="transaction" class="org.jboss.test.aop.bean.TxPOJO">
                       <default>
                       <trans-attribute>NotSupported</trans-attribute>
                       </default>
                       <method name="never">
                       <trans-attribute>Never</trans-attribute>
                       </method>
                       <method name="supports">
                       <trans-attribute>Supports</trans-attribute>
                       </method>
                       </metadata>
                      


                      Although there are a few standard tags within the metadata (default, method, field, constructor), the actual content of these is free-form. E.g. The first example uses the nested element "data" and the third uses the nested element "trans-attribute".

                      Then we have more complicated things like the following, it uses the org.jboss.aspects.security.SecurityClassMetaDataLoader to parse the xml shown into aop metadata.


                       <metadata tag="security" class="org.jboss.test.aop.bean.SecuredPOJO">
                       <security-domain>other</security-domain>
                       <method-permission>
                       <role-name>allowed</role-name>
                       <method>
                       <method-name>someMethod</method-name>
                       </method>
                       </method-permission>
                       <method-permission>
                       <unchecked/>
                       <method>
                       <method-name>unchecked</method-name>
                       </method>
                       </method-permission>
                       <field-permission>
                       <role-name>allowed</role-name>
                       <field>
                       <field-name>someField</field-name>
                       </field>
                       </field-permission>
                       <field-permission>
                       <unchecked/>
                       <field>
                       <field-name>uncheckedField</field-name>
                       </field>
                       </field-permission>
                       <constructor-permission>
                       <unchecked/>
                       <constructor>
                       <constructor-params/>
                       </constructor>
                       </constructor-permission>
                       <constructor-permission>
                       <role-name>allowed</role-name>
                       <constructor>
                       <constructor-params>
                       <constructor-param>int</constructor-param>
                       </constructor-params>
                       </constructor>
                       </constructor-permission>
                      
                       <exclude-list>
                       <description>Methods that connect be used</description>
                       <method>
                       <method-name>excluded</method-name>
                       </method>
                       <field>
                       <field-name>excludedField</field-name>
                       </field>
                       <constructor>
                       <constructor-params>
                       <constructor-param>java.lang.String</constructor-param>
                       </constructor-params>
                       </constructor>
                       </exclude-list>
                       </metadata>
                      


                      All the examples are from the AS 5 testsuite, and I think we need to continue supporting this stuff? From base-aspects.xml:

                       <!-- custom configuration for AOP Security -->
                       <metadata-loader tag="security" class="org.jboss.aspects.security.SecurityClassMetaDataLoader"/>
                      


                      I think the simple cases can be rewritten using Element for the nested data/transaction-attribute elements? They only map onto name/value pairs - the name of the tag being the name, and the content being the value.

                      The SecurityClassMetaDataLoader needs replacing with something else, but it should be able to parse the style of xml shown. I don't see any other way at the moment than being able to take Element?

                      • 8. Re: Getting content of XML element
                        Adrian Brock Master

                         

                        "kabir.khan@jboss.com" wrote:

                        I think the simple cases can be rewritten using Element for the nested data/transaction-attribute elements? They only map onto name/value pairs - the name of the tag being the name, and the content being the value.

                        The SecurityClassMetaDataLoader needs replacing with something else, but it should be able to parse the style of xml shown. I don't see any other way at the moment than being able to take Element?


                        You can get JBossXB/JAXB to pass you the element. That's how we do the
                        old InvokerProxyBindings in EJB2, but then you have to parse it (again) yourself.

                        http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/metadata/trunk/src/main/java/org/jboss/metadata/ejb/jboss/InvokerProxyBindingMetaData.java?revision=65629&view=markup

                        Of course this kind of usage of xml makes schema validation impossible
                        so lots of typos by the user unfortunatley. ;-)