You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@santuario.apache.org by Eric Johnson <er...@tibco.com> on 2011/10/26 14:30:26 UTC

Question on DOMXMLObject implementation in 1.4.6

In the 1.4.6 release of Santuario Java, the DOMXMLObject class underwent 
a small set of changes.

Specifically, it appears that the class now holds on to the objElem 
passed to the constructor:

public DOMXMLObject(Element objElem, XMLCryptoContext context, Provider 
provider);

It appears to do this so that the objElem can be re-used upon calling 
the "marshal" method.

Is this related to https://issues.apache.org/jira/browse/SANTUARIO-283 ?

I've been changing the marshaling code in the GenXDM port so that it 
makes minimal assumptions about the implementation of the various 
javax.xml.crypto APIs.

That is, in the GenXDM port, the equivalent marshal function looks like:

     public static<N>  void marshal(XMLObject xmlObj, MutableModel<N>  model, N parent, String dsPrefix, XMLCryptoContext context)
	throws MarshalException {

     	NodeFactory<N>  factory = model.getFactory(parent);

         N objElem = factory.createElement
             (XMLSignature.XMLNS, "Object", dsPrefix);

         // set attributes
         DOMUtils.setAttributeID(factory, model, objElem, "Id", xmlObj.getId());
         DOMUtils.setAttribute(factory, model, objElem, "MimeType", xmlObj.getMimeType());
         DOMUtils.setAttribute(factory, model, objElem, "Encoding", xmlObj.getEncoding() );

         // create and append any elements and mixed content, if necessary
         @SuppressWarnings("unchecked")
         List<XMLStructure>  content = xmlObj.getContent();
         for (XMLStructure object : content) {
             Marshaller.marshal(object, model, objElem, dsPrefix, context);
         }
	
	model.appendChild(parent, objElem);
     }


Note that this method is both static, and takes a generic XMLObject as a 
parameter, rather than the Apache implementation specific version of 
DOMXMLObject.

I'm inclined to change my port so that upon unmarshalling the node, it 
captures the namespace declarations on the node, and then in the marshal 
code above, I add a check to see if the xmlObj is an instance of a 
DOMXMLObject, and only then see if the specific known implementation has 
unmarshalled any namespace declarations, and if it has, add those as 
part of what gets output.

Alternately, I could add the namespace declarations as members of the 
getContent() collection, and if I detect them, write out the namespace 
declarations.

Either of the above has the upside that you can then "marshal" the 
object as many times as you want, to as many target trees you want, 
without worrying that the same element will be used over and over again.

Comments?

-Eric.


Re: Question on DOMXMLObject implementation in 1.4.6

Posted by Sean Mullan <se...@oracle.com>.
On 10/28/11 3:44 PM, Eric Johnson wrote:
> Hi Sean,
> 
> Thanks for the feedback.
> 
> I ended solving this by wrapping all the declared namespaces in an 
> instance of a class that extends XMLStructure (actually, the default one 
> - this would have been javax.xml.crypto.dom.DOMStructure but for the 
> fact that with the GenXDM port we need a GenXDMStructure equivalent of 
> that.). I then add that object to the "content" of the XMLObject. Then, 
> when marshaling the object, I check to see if the referenced node is a 
> namespace declaration, and declare the namespace in the target output 
> (rather than inserting the source node).
> 
> This isn't quite a perfect solution, because if the caller modifies the 
> namespace declaration, then that update will be reflected in the later 
> marshaling, but it works. And it isn't any different in that regard from 
> the solution in 1.4.6, except it is no longer destructive to the source 
> document used when unmarshaling.
> 
> Here's a question - with the current implementation in 1.4.6, it strikes 
> me that attributes like xml:base, xml:id, and xml:lang would also be 
> preserved in the new marshaling - I'm not sure that's correct. Or is it? 
> Certainly, my change to preserve namespaces doesn't preserve those 
> attributes, but perhaps it should?

Yes, if you are using C14N 1.1 : http://www.w3.org/TR/xml-c14n11/

--Sean


> 
> -Eric.
> 
> On 10/26/11 5:40 PM, Sean Mullan wrote:
>> On 10/26/11 8:30 AM, Eric Johnson wrote:
>>> In the 1.4.6 release of Santuario Java, the DOMXMLObject class underwent
>>> a small set of changes.
>>>
>>> Specifically, it appears that the class now holds on to the objElem
>>> passed to the constructor:
>>>
>>> public DOMXMLObject(Element objElem, XMLCryptoContext context, Provider
>>> provider);
>>>
>>> It appears to do this so that the objElem can be re-used upon calling
>>> the "marshal" method.
>>>
>>> Is this related to https://issues.apache.org/jira/browse/SANTUARIO-283 ?
>> Yes.
>>
>>> I've been changing the marshaling code in the GenXDM port so that it
>>> makes minimal assumptions about the implementation of the various
>>> javax.xml.crypto APIs.
>>>
>>> That is, in the GenXDM port, the equivalent marshal function looks like:
>>>
>>>       public static<N>   void marshal(XMLObject xmlObj, MutableModel<N>   model, N parent, String dsPrefix, XMLCryptoContext context)
>>> 	throws MarshalException {
>>>
>>>       	NodeFactory<N>   factory = model.getFactory(parent);
>>>
>>>           N objElem = factory.createElement
>>>               (XMLSignature.XMLNS, "Object", dsPrefix);
>>>
>>>           // set attributes
>>>           DOMUtils.setAttributeID(factory, model, objElem, "Id", xmlObj.getId());
>>>           DOMUtils.setAttribute(factory, model, objElem, "MimeType", xmlObj.getMimeType());
>>>           DOMUtils.setAttribute(factory, model, objElem, "Encoding", xmlObj.getEncoding() );
>>>
>>>           // create and append any elements and mixed content, if necessary
>>>           @SuppressWarnings("unchecked")
>>>           List<XMLStructure>   content = xmlObj.getContent();
>>>           for (XMLStructure object : content) {
>>>               Marshaller.marshal(object, model, objElem, dsPrefix, context);
>>>           }
>>> 	
>>> 	model.appendChild(parent, objElem);
>>>       }
>>>
>>>
>>> Note that this method is both static, and takes a generic XMLObject as a
>>> parameter, rather than the Apache implementation specific version of
>>> DOMXMLObject.
>>>
>>> I'm inclined to change my port so that upon unmarshalling the node, it
>>> captures the namespace declarations on the node, and then in the marshal
>>> code above, I add a check to see if the xmlObj is an instance of a
>>> DOMXMLObject, and only then see if the specific known implementation has
>>> unmarshalled any namespace declarations, and if it has, add those as
>>> part of what gets output.
>>>
>>> Alternately, I could add the namespace declarations as members of the
>>> getContent() collection, and if I detect them, write out the namespace
>>> declarations.
>>>
>>> Either of the above has the upside that you can then "marshal" the
>>> object as many times as you want, to as many target trees you want,
>>> without worrying that the same element will be used over and over again.
>>>
>>> Comments?
>> The underlying problem is that you cannot access the namespace declarations via
>> JSR 105 XMLObject API. That should be fixed eventually but since there are no
>> immediate plans for reving the API, we need to work around it.
>>
>> Your first solution seems better. The second solution is not compliant with the
>> XMLObject.getContent() API.
>>
>> --Sean
>>
>>

Re: Question on DOMXMLObject implementation in 1.4.6

Posted by Eric Johnson <er...@tibco.com>.
Hi Sean,

Thanks for the feedback.

I ended solving this by wrapping all the declared namespaces in an 
instance of a class that extends XMLStructure (actually, the default one 
- this would have been javax.xml.crypto.dom.DOMStructure but for the 
fact that with the GenXDM port we need a GenXDMStructure equivalent of 
that.). I then add that object to the "content" of the XMLObject. Then, 
when marshaling the object, I check to see if the referenced node is a 
namespace declaration, and declare the namespace in the target output 
(rather than inserting the source node).

This isn't quite a perfect solution, because if the caller modifies the 
namespace declaration, then that update will be reflected in the later 
marshaling, but it works. And it isn't any different in that regard from 
the solution in 1.4.6, except it is no longer destructive to the source 
document used when unmarshaling.

Here's a question - with the current implementation in 1.4.6, it strikes 
me that attributes like xml:base, xml:id, and xml:lang would also be 
preserved in the new marshaling - I'm not sure that's correct. Or is it? 
Certainly, my change to preserve namespaces doesn't preserve those 
attributes, but perhaps it should?

-Eric.

On 10/26/11 5:40 PM, Sean Mullan wrote:
> On 10/26/11 8:30 AM, Eric Johnson wrote:
>> In the 1.4.6 release of Santuario Java, the DOMXMLObject class underwent
>> a small set of changes.
>>
>> Specifically, it appears that the class now holds on to the objElem
>> passed to the constructor:
>>
>> public DOMXMLObject(Element objElem, XMLCryptoContext context, Provider
>> provider);
>>
>> It appears to do this so that the objElem can be re-used upon calling
>> the "marshal" method.
>>
>> Is this related to https://issues.apache.org/jira/browse/SANTUARIO-283 ?
> Yes.
>
>> I've been changing the marshaling code in the GenXDM port so that it
>> makes minimal assumptions about the implementation of the various
>> javax.xml.crypto APIs.
>>
>> That is, in the GenXDM port, the equivalent marshal function looks like:
>>
>>       public static<N>   void marshal(XMLObject xmlObj, MutableModel<N>   model, N parent, String dsPrefix, XMLCryptoContext context)
>> 	throws MarshalException {
>>
>>       	NodeFactory<N>   factory = model.getFactory(parent);
>>
>>           N objElem = factory.createElement
>>               (XMLSignature.XMLNS, "Object", dsPrefix);
>>
>>           // set attributes
>>           DOMUtils.setAttributeID(factory, model, objElem, "Id", xmlObj.getId());
>>           DOMUtils.setAttribute(factory, model, objElem, "MimeType", xmlObj.getMimeType());
>>           DOMUtils.setAttribute(factory, model, objElem, "Encoding", xmlObj.getEncoding() );
>>
>>           // create and append any elements and mixed content, if necessary
>>           @SuppressWarnings("unchecked")
>>           List<XMLStructure>   content = xmlObj.getContent();
>>           for (XMLStructure object : content) {
>>               Marshaller.marshal(object, model, objElem, dsPrefix, context);
>>           }
>> 	
>> 	model.appendChild(parent, objElem);
>>       }
>>
>>
>> Note that this method is both static, and takes a generic XMLObject as a
>> parameter, rather than the Apache implementation specific version of
>> DOMXMLObject.
>>
>> I'm inclined to change my port so that upon unmarshalling the node, it
>> captures the namespace declarations on the node, and then in the marshal
>> code above, I add a check to see if the xmlObj is an instance of a
>> DOMXMLObject, and only then see if the specific known implementation has
>> unmarshalled any namespace declarations, and if it has, add those as
>> part of what gets output.
>>
>> Alternately, I could add the namespace declarations as members of the
>> getContent() collection, and if I detect them, write out the namespace
>> declarations.
>>
>> Either of the above has the upside that you can then "marshal" the
>> object as many times as you want, to as many target trees you want,
>> without worrying that the same element will be used over and over again.
>>
>> Comments?
> The underlying problem is that you cannot access the namespace declarations via
> JSR 105 XMLObject API. That should be fixed eventually but since there are no
> immediate plans for reving the API, we need to work around it.
>
> Your first solution seems better. The second solution is not compliant with the
> XMLObject.getContent() API.
>
> --Sean
>
>

Re: Question on DOMXMLObject implementation in 1.4.6

Posted by Sean Mullan <se...@oracle.com>.
On 10/26/11 8:30 AM, Eric Johnson wrote:
> In the 1.4.6 release of Santuario Java, the DOMXMLObject class underwent 
> a small set of changes.
> 
> Specifically, it appears that the class now holds on to the objElem 
> passed to the constructor:
> 
> public DOMXMLObject(Element objElem, XMLCryptoContext context, Provider 
> provider);
> 
> It appears to do this so that the objElem can be re-used upon calling 
> the "marshal" method.
> 
> Is this related to https://issues.apache.org/jira/browse/SANTUARIO-283 ?

Yes.

> I've been changing the marshaling code in the GenXDM port so that it 
> makes minimal assumptions about the implementation of the various 
> javax.xml.crypto APIs.
> 
> That is, in the GenXDM port, the equivalent marshal function looks like:
> 
>      public static<N>  void marshal(XMLObject xmlObj, MutableModel<N>  model, N parent, String dsPrefix, XMLCryptoContext context)
> 	throws MarshalException {
> 
>      	NodeFactory<N>  factory = model.getFactory(parent);
> 
>          N objElem = factory.createElement
>              (XMLSignature.XMLNS, "Object", dsPrefix);
> 
>          // set attributes
>          DOMUtils.setAttributeID(factory, model, objElem, "Id", xmlObj.getId());
>          DOMUtils.setAttribute(factory, model, objElem, "MimeType", xmlObj.getMimeType());
>          DOMUtils.setAttribute(factory, model, objElem, "Encoding", xmlObj.getEncoding() );
> 
>          // create and append any elements and mixed content, if necessary
>          @SuppressWarnings("unchecked")
>          List<XMLStructure>  content = xmlObj.getContent();
>          for (XMLStructure object : content) {
>              Marshaller.marshal(object, model, objElem, dsPrefix, context);
>          }
> 	
> 	model.appendChild(parent, objElem);
>      }
> 
> 
> Note that this method is both static, and takes a generic XMLObject as a 
> parameter, rather than the Apache implementation specific version of 
> DOMXMLObject.
> 
> I'm inclined to change my port so that upon unmarshalling the node, it 
> captures the namespace declarations on the node, and then in the marshal 
> code above, I add a check to see if the xmlObj is an instance of a 
> DOMXMLObject, and only then see if the specific known implementation has 
> unmarshalled any namespace declarations, and if it has, add those as 
> part of what gets output.
> 
> Alternately, I could add the namespace declarations as members of the 
> getContent() collection, and if I detect them, write out the namespace 
> declarations.
> 
> Either of the above has the upside that you can then "marshal" the 
> object as many times as you want, to as many target trees you want, 
> without worrying that the same element will be used over and over again.
> 
> Comments?

The underlying problem is that you cannot access the namespace declarations via
JSR 105 XMLObject API. That should be fixed eventually but since there are no
immediate plans for reving the API, we need to work around it.

Your first solution seems better. The second solution is not compliant with the
XMLObject.getContent() API.

--Sean