src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/output/C14nXmlOutput.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.bind.v2.runtime.output;
    28 import java.io.IOException;
    29 import java.io.OutputStream;
    30 import java.util.Arrays;
    31 import java.util.Collections;
    33 import com.sun.xml.internal.bind.api.JAXBRIContext;
    34 import com.sun.xml.internal.bind.v2.runtime.Name;
    35 import com.sun.istack.internal.FinalArrayList;
    36 import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;
    38 /**
    39  * {@link XmlOutput} that generates canonical XML.
    40  *
    41  * @see com.sun.xml.internal.bind.api.C14nSupport_ArchitectureDocument
    42  * @author Kohsuke Kawaguchi
    43  */
    44 public class C14nXmlOutput extends UTF8XmlOutput {
    45     public C14nXmlOutput(OutputStream out, Encoded[] localNames, boolean namedAttributesAreOrdered, CharacterEscapeHandler escapeHandler) {
    46         super(out, localNames, escapeHandler);
    47         this.namedAttributesAreOrdered = namedAttributesAreOrdered;
    49         for( int i=0; i<staticAttributes.length; i++ )
    50             staticAttributes[i] = new StaticAttribute();
    51     }
    53     /**
    54      * Hosts statically known attributes.
    55      *
    56      * {@link StaticAttribute} instances are reused.
    57      */
    58     private StaticAttribute[] staticAttributes = new StaticAttribute[8];
    59     private int len = 0;
    61     /**
    62      * Used to sort namespace declarations. Reused.
    63      */
    64     private int[] nsBuf = new int[8];
    66     /**
    67      * Hosts other attributes whose name are not statically known
    68      * (AKA attribute wildcard.)
    69      *
    70      * As long as this map is empty, there's no need for sorting.
    71      * see {@link com.sun.xml.internal.bind.api.C14nSupport_ArchitectureDocument} for more details.
    72      */
    73     private final FinalArrayList<DynamicAttribute> otherAttributes = new FinalArrayList<DynamicAttribute>();
    75     /**
    76      * True if {@link JAXBRIContext} is created with c14n support on,
    77      * in which case all named attributes are sorted by the marshaller
    78      * and we won't have to do it here.
    79      */
    80     private final boolean namedAttributesAreOrdered;
    82     final class StaticAttribute implements Comparable<StaticAttribute> {
    83         Name name;
    84         String value;
    86         public void set(Name name, String value) {
    87             this.name = name;
    88             this.value = value;
    89         }
    91         void write() throws IOException {
    92             C14nXmlOutput.super.attribute(name,value);
    93         }
    95         DynamicAttribute toDynamicAttribute() {
    96             int nsUriIndex = name.nsUriIndex;
    97             int prefix;
    98             if(nsUriIndex==-1)
    99                 prefix = -1;
   100             else
   101                 prefix = nsUriIndex2prefixIndex[nsUriIndex];
   102             return new DynamicAttribute(
   103                 prefix, name.localName, value );
   104         }
   106         public int compareTo(StaticAttribute that) {
   107             return this.name.compareTo(that.name);
   108         }
   110     }
   112     final class DynamicAttribute implements Comparable<DynamicAttribute> {
   113         final int prefix;
   114         final String localName;
   115         final String value;
   117         public DynamicAttribute(int prefix, String localName, String value) {
   118             this.prefix = prefix;
   119             this.localName = localName;
   120             this.value = value;
   121         }
   123         private String getURI() {
   124             if(prefix==-1)  return "";
   125             else            return nsContext.getNamespaceURI(prefix);
   126         }
   128         public int compareTo(DynamicAttribute that) {
   129             int r = this.getURI().compareTo(that.getURI());
   130             if(r!=0)    return r;
   131             return this.localName.compareTo(that.localName);
   132         }
   133     }
   135     @Override
   136     public void attribute(Name name, String value) throws IOException {
   137         if(staticAttributes.length==len) {
   138             // reallocate
   139             int newLen = len*2;
   140             StaticAttribute[] newbuf = new StaticAttribute[newLen];
   141             System.arraycopy(staticAttributes,0,newbuf,0,len);
   142             for(int i=len;i<newLen;i++)
   143                 staticAttributes[i] = new StaticAttribute();
   144             staticAttributes = newbuf;
   145         }
   147         staticAttributes[len++].set(name,value);
   148     }
   150     @Override
   151     public void attribute(int prefix, String localName, String value) throws IOException {
   152         otherAttributes.add(new DynamicAttribute(prefix,localName,value));
   153     }
   155     @Override
   156     public void endStartTag() throws IOException {
   157         if(otherAttributes.isEmpty()) {
   158             if(len!=0) {
   159                 // sort is expensive even for size 0 array,
   160                 // so it's worth checking len==0
   161                 if(!namedAttributesAreOrdered)
   162                     Arrays.sort(staticAttributes,0,len);
   163                 // this is the common case
   164                 for( int i=0; i<len; i++ )
   165                     staticAttributes[i].write();
   166                 len = 0;
   167             }
   168         } else {
   169             // this is the exceptional case
   171             // sort all the attributes, not just the other attributes
   172             for( int i=0; i<len; i++ )
   173                 otherAttributes.add(staticAttributes[i].toDynamicAttribute());
   174             len = 0;
   175             Collections.sort(otherAttributes);
   177             // write them all
   178             int size = otherAttributes.size();
   179             for( int i=0; i<size; i++ ) {
   180                 DynamicAttribute a = otherAttributes.get(i);
   181                 super.attribute(a.prefix,a.localName,a.value);
   182             }
   183             otherAttributes.clear();
   184         }
   185         super.endStartTag();
   186     }
   188     /**
   189      * Write namespace declarations after sorting them.
   190      */
   191     @Override
   192     protected void writeNsDecls(int base) throws IOException {
   193         int count = nsContext.getCurrent().count();
   195         if(count==0)
   196             return; // quickly reject the most common case
   198         if(count>nsBuf.length)
   199             nsBuf = new int[count];
   201         for( int i=count-1; i>=0; i-- )
   202             nsBuf[i] = base+i;
   204         // do a bubble sort. Hopefully # of ns decls are small enough to justify bubble sort.
   205         // faster algorithm is more compliated to implement
   206         for( int i=0; i<count; i++ ) {
   207             for( int j=i+1; j<count; j++ ) {
   208                 String p = nsContext.getPrefix(nsBuf[i]);
   209                 String q = nsContext.getPrefix(nsBuf[j]);
   210                 if( p.compareTo(q) > 0 ) {
   211                     // swap
   212                     int t = nsBuf[j];
   213                     nsBuf[j] = nsBuf[i];
   214                     nsBuf[i] = t;
   215                 }
   216             }
   217         }
   219         // write them out
   220         for( int i=0; i<count; i++ )
   221             writeNsDecl(nsBuf[i]);
   222     }
   223 }

mercurial