diff options
Diffstat (limited to 'spss/server/serverlib')
| -rw-r--r-- | spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/DataObjectFactory.java | 166 | 
1 files changed, 99 insertions, 67 deletions
| diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/DataObjectFactory.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/DataObjectFactory.java index 566784796..f6b8b4392 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/DataObjectFactory.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/DataObjectFactory.java @@ -27,10 +27,11 @@ import java.util.HashMap;  import java.util.Iterator;  import java.util.List;  import java.util.Map; -import java.util.Vector;  import javax.xml.parsers.ParserConfigurationException; +import org.apache.xerces.dom.CoreDocumentImpl; +import org.w3c.dom.Attr;  import org.w3c.dom.Document;  import org.w3c.dom.Element;  import org.w3c.dom.Node; @@ -70,19 +71,30 @@ import at.gv.egovernment.moa.util.XPathUtils;  /**   * A class to create <code>DataObject</code>s contained in different   * locations of the MOA XML request format. - *  + *   * @author Patrick Peck   * @author Gregor Karlinger   * @version $Id$   */  public class DataObjectFactory { +  /** +   * XPATH for registering ID attributes of known schemas if +   * validating parsing fails. +   */ +  private static final String XPATH = +    "descendant-or-self::node()[" + +    "namespace-uri()='http://www.w3.org/2000/09/xmldsig#' " + +    "or namespace-uri()='http://reference.e-government.gv.at/namespace/persondata/20020228#' " + +    "or starts-with(namespace-uri(), 'http://uri.etsi.org/01903/')" + +    "]/attribute::Id"; +    /** The single instance of this class. */    private static DataObjectFactory instance = null;    /**     * Return the only instance of this class. -   *  +   *     * @return The only instance of this class.     */    public static synchronized DataObjectFactory getInstance() { @@ -94,7 +106,7 @@ public class DataObjectFactory {    /**     * Create a new <code>DataObjectFactory</code>. -   *  +   *     * Protected to disallow multiple instances.     */    protected DataObjectFactory() { @@ -104,8 +116,8 @@ public class DataObjectFactory {     * Return the signature environment, i.e., the root element of the     * document, into which the signature will be inserted (if created) or which     * contains the signature (if verified). -   *  -   * @param content The <code>Content</code> object containing the signature  +   * +   * @param content The <code>Content</code> object containing the signature     * environment.     * @param supplements Additional schema or DTD information.     * @return The signature environment or <code>null</code>, if no @@ -128,7 +140,7 @@ public class DataObjectFactory {      checkAllowContentAndReference(content, false);      // build the EntityResolver for validating parsing -    if (supplements == null || supplements.isEmpty()) { +    if ((supplements == null) || supplements.isEmpty()) {        entityResolver = new MOAEntityResolver();      } else {        EntityResolverChain chain = new EntityResolverChain(); @@ -195,7 +207,7 @@ public class DataObjectFactory {              Element element =                checkForSingleElement(((ContentXML) content).getXMLContent());              contentBytes = DOMUtils.serializeNode(element, "UTF-8"); -             +              break;            }          default : { @@ -208,25 +220,27 @@ public class DataObjectFactory {        throw new MOAApplicationException("2219", null);      } -    // For logging in Debug-Mode: Mask baseid with xxx -    String logString = new String(contentBytes); -    // TODO use RegExp -    String startS = "<pr:Identification><pr:Value>"; -    String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>"; -    String logWithMaskedBaseid = logString; -    int start = logString.indexOf(startS); -    if (start > -1) { -       int end = logString.indexOf(endS); -       if (end > -1) { +    if (Logger.isTraceEnabled()) { +      // For logging in Debug-Mode: Mask baseid with xxx +      String logString = new String(contentBytes); +      // TODO use RegExp +      String startS = "<pr:Identification><pr:Value>"; +      String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>"; +      String logWithMaskedBaseid = logString; +      int start = logString.indexOf(startS); +      if (start > -1) { +        int end = logString.indexOf(endS); +        if (end > -1) {            logWithMaskedBaseid = logString.substring(0, start);            logWithMaskedBaseid += startS;            logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx";            logWithMaskedBaseid += logString.substring(end, logString.length()); -       } +        } +      } + +      // try to parse validating +      Logger.trace(">>> parsing the following content: \n" + logWithMaskedBaseid);      } -     -    // try to parse validating -    Logger.trace(">>> parsing the following content: \n" + logWithMaskedBaseid);      try {        ByteArrayInputStream is = new ByteArrayInputStream(contentBytes);        Document doc = @@ -250,6 +264,21 @@ public class DataObjectFactory {      try {        ByteArrayInputStream is = new ByteArrayInputStream(contentBytes);        Document doc = DOMUtils.parseDocument(is, false, null, null); +      // Since the parse tree will not contain any post schema validation information, +      // we need to register any attributes known to be of type xsd:Id manually. +      NodeList idAttributes = XPathUtils.selectNodeList(doc.getDocumentElement(), XPATH); +      for (int i = 0; i < idAttributes.getLength(); i++) { +        Node item = idAttributes.item(i); +        if (item instanceof Attr) { +          Attr attr = (Attr) item; +          Element owner = attr.getOwnerElement(); +          // Only available in DOM-Level 3 (Java 1.5): +          // owner.setIdAttributeNode(attr, true); +          if (doc instanceof CoreDocumentImpl) { +            ((CoreDocumentImpl) doc).putIdentifier(attr.getValue(), owner); +          } +        } +      }        return new XMLDataObjectImpl(doc.getDocumentElement());      } catch (Exception e) {        throw new MOAApplicationException("2218", null); @@ -258,11 +287,11 @@ public class DataObjectFactory {    /**     * Create an <code>XMLDataObject</code> from the given signature environment. -   *  +   *     * @param signatureEnvironment The signature environment contained in the     * result.     * @param uri The URI identifying the data. This must be either the empty -   * URI, an URI starting with <code>"#xpointer"</code>, <code>"#xmlns"</code>  +   * URI, an URI starting with <code>"#xpointer"</code>, <code>"#xmlns"</code>     * or <code>"#element"</code>; or an URI starting with <code>"#"</code> and     * followed by an element ID.     * @param referenceID The reference ID to set for the data object. @@ -312,16 +341,16 @@ public class DataObjectFactory {    }    /** -   * Build a <code>StreamEntityResolver</code> from a <code>List</code> of  +   * Build a <code>StreamEntityResolver</code> from a <code>List</code> of     * supplements. -   *  -   * @param supplements The supplements, given as  +   * +   * @param supplements The supplements, given as     * <code>XMLDataObjectAssociation</code>s.     * @return A <code>StreamEntityResolver</code> mapping the supplements by     * their reference URI to an <code>InputStream</code> of their respective -   * content.  +   * content.     */ -  private static StreamEntityResolver buildSupplementEntityResolver(List supplements)  +  private static StreamEntityResolver buildSupplementEntityResolver(List supplements)      throws MOAApplicationException    {      Map entities = new HashMap(); @@ -342,10 +371,10 @@ public class DataObjectFactory {          case Content.LOCREF_CONTENT:            {          	String locRefURI = ((ContentLocRef) content).getLocationReferenceURI(); -        	 +              TransactionContext context = TransactionContextManager.getInstance().getTransactionContext();          	if (context.FindResolvedEntity(locRefURI)==null) { -	 +  	            ExternalURIResolver uriResolver = new ExternalURIResolver();  	            InputStream uriStream = null;  	            byte[] contentBytes; @@ -378,17 +407,18 @@ public class DataObjectFactory {              int i = 0;              // find the first element node -            while (i < nodes.getLength() -              && nodes.item(i).getNodeType() != Node.ELEMENT_NODE) +            while ((i < nodes.getLength()) +              && (nodes.item(i).getNodeType() != Node.ELEMENT_NODE)) {                i++; +            }              // serialize the node              if (i < nodes.getLength()) { -              try  +              try                {                  byte[] serialized = DOMUtils.serializeNode(nodes.item(i), "UTF-8");                  entities.put(reference, new ByteArrayInputStream(serialized)); -              }  +              }                catch (Exception e)                {                  throw new MOAApplicationException("2281", new Object[]{reference}, e); @@ -404,7 +434,7 @@ public class DataObjectFactory {    /**     * Create a <code>DataObject</code> from a <code>Content</code> object. -   *  +   *     * @param content The <code>Content</code> object containing the data.     * @param finalDataMetaInfo The meta information corresponding with <code>content</code>.     * @param referenceID The reference ID to set in the resulting @@ -452,10 +482,10 @@ public class DataObjectFactory {      checkAllowContentAndReference(content, allowContentAndReference);      // ok, build the data object; use content first, if available -    switch (content.getContentType())  +    switch (content.getContentType())      {        case Content.XML_CONTENT : -      {   +      {          ContentXML contentXml = (ContentXML) content;          dataObject = createFromXmlContent(contentXml, xmlAsNodeList);          break; @@ -499,7 +529,7 @@ public class DataObjectFactory {    /**     * Check, if content and reference URIs are allowed in the content an throw     * an exception if an illegal combination of the two occurs. -   *  +   *     * @param content The <code>Content</code> to check.     * @param allowContentAndReference Whether explicit content and a reference     * are allowed at the same time. @@ -514,13 +544,13 @@ public class DataObjectFactory {      String reference = content.getReference();      // check for content and reference not being set -    if (content.getContentType() == Content.REFERENCE_CONTENT -      && reference == null) { +    if ((content.getContentType() == Content.REFERENCE_CONTENT) +      && (reference == null)) {        String errorCode = allowContentAndReference ? "1111" : "1110";        throw new MOAApplicationException(errorCode, null);      } -    // if we only allow either content or reference being set at once, check  +    // if we only allow either content or reference being set at once, check      if (!allowContentAndReference        && (content.getContentType() != Content.REFERENCE_CONTENT)        && (reference != null)) { @@ -531,10 +561,10 @@ public class DataObjectFactory {    /**     * Create a <code>DataObject</code> from a     * <code>XMLDataObjectAssociation</code> object. -   *  +   *     * @param xmlDataObjAssoc The <code>XMLDataObjectAssociation</code> object.     * @param xmlContentAllowed Whether the content contained in the -   * <code>xmlDataObjAssoc</code> is allowed to be of type  +   * <code>xmlDataObjAssoc</code> is allowed to be of type     * <code>XML_CONTENT</code>.     * @param binaryContentRepeatable If binary content must be provided as a     * <code>DataObject</code> that can be read multiple times. @@ -559,11 +589,11 @@ public class DataObjectFactory {      switch (content.getContentType())      {        case Content.XML_CONTENT : -      {   +      {          if (xmlContentAllowed)          {            dataObject = createFromXmlContent((ContentXML) content, true); -        }  +        }          else          {            throw new MOAApplicationException("2280", null); @@ -601,8 +631,8 @@ public class DataObjectFactory {    /**     * Create a <code>DataObject</code> from a <code>TransformParameter</code>     * object. -   *  -   * @param transformParameter The <code>TransformParameter</code> object  +   * +   * @param transformParameter The <code>TransformParameter</code> object     * containing the data.     * @return A <code>DataObject</code> representing the data in     * <code>root</code>. @@ -662,7 +692,7 @@ public class DataObjectFactory {    /**     * Create a <code>DataObject</code> from data located at the given URI. -   *  +   *     * @param uri The <code>URI</code> where the data is located. This method uses     * an <code>ExternalURIResolver</code> to resolve URIs.     * @param asXml If <code>true</code>, a <code>DataObject</code> is only @@ -682,7 +712,7 @@ public class DataObjectFactory {    /**     * Create a <code>DataObject</code> from data located at the given URI. -   *  +   *     * @param uri The <code>URI</code> where the data is located. This method uses     * an <code>ExternalURIResolver</code> to resolve URIs.     * @param asXml If <code>true</code>, a <code>DataObject</code> is only @@ -701,7 +731,7 @@ public class DataObjectFactory {      Logger.trace(">>> resolving uri \"" + uri + "\"");      ExternalURIResolver resolver = new ExternalURIResolver(); -         +      TransactionContext context = TransactionContextManager.getInstance().getTransactionContext();      InputStream is = context.ResolveURI(uri);      String contentType = null; @@ -718,12 +748,12 @@ public class DataObjectFactory {      DataObjectImpl dataObject;      // read the content -    if (contentType != null && contentTypeIsXml(contentType)) { +    if ((contentType != null) && contentTypeIsXml(contentType)) {        Document doc;        if (asXml) {          try { -          // try parsing non-validating: this has to succeed or we  +          // try parsing non-validating: this has to succeed or we            // bail out by throwing an exception            is = resolver.resolve(uri);            doc = DOMUtils.parseDocument(is, false, null, null); @@ -767,14 +797,14 @@ public class DataObjectFactory {            Logger.trace(">>> read stream for \"" + uri + "\"");          }        } -    }  -     -    else if (asXml)  +    } + +    else if (asXml)      {        // if we need XML data, we're in the wrong place here        closeInputStream(is);        throw new MOAApplicationException("2211", new Object[] { uri }); -    }  +    }      else      {        // content is binary: make it available as a binary input stream @@ -805,20 +835,22 @@ public class DataObjectFactory {      dataObject.setURI(uri);      Logger.trace("<<< resolved uri \"" + uri + "\""); -     +      return dataObject;    }    /**     * Savely closes the specified input stream. -   *  +   *     * @param is The input stream to be closed.     */    private static void closeInputStream(InputStream is)    {      try      { -      if (is != null) is.close(); +      if (is != null) { +        is.close(); +      }      }      catch (Throwable t)      { @@ -828,10 +860,10 @@ public class DataObjectFactory {    /**     * Determine whether the content type is XML. -   *  +   *     * Content types recognized as XML start with <code>text/xml</code> and     * <code>application/xml</code>. -   *  +   *     * @param contentType The content MIME type.     * @return boolean If <code>true</code>, the content type is XML, otherwise     * not. @@ -842,8 +874,8 @@ public class DataObjectFactory {    }    /** -   * Create a <code>DataObject</code> from a <code>ContentXML</code> object.  -   *  +   * Create a <code>DataObject</code> from a <code>ContentXML</code> object. +   *     * @param xmlContent The <code>ContentXML</code> object from     * which the <code>DataObject</code> is to be built.     * @param xmlAsNodeList If <code>true</code>, the children of @@ -879,7 +911,7 @@ public class DataObjectFactory {    /**     * Check, that the given <code>NodeList</code> contains a single DOM element     * node and return it, otherwise throw an exception. -   *  +   *     * @param nodes The <code>NodeList</code> to check for a single element.     * @return The single element contained in <code>nodes</code>.     * @throws MOAApplicationException Thrown, if <code>nodes</code> does not @@ -912,11 +944,11 @@ public class DataObjectFactory {    /**     * Create a <code>DataObject</code> from a <code>ContentBinary</code> object. -   *  +   *     * @param binaryContent The <code>ContentBinary</code> object containing the     * data.     * @param asXml If <code>true</code>, <code>binaryContent</code> must -   * contain XML data. Otherwise, a <code>BinaryDataObject</code> will be  +   * contain XML data. Otherwise, a <code>BinaryDataObject</code> will be     * returned containing a byte stream to the decoded Base64 data.     * @param repeatable If multiple calls to <code>getInputStream()</code> must     * repeatedly return the content of the data object. | 
