You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2009/10/05 20:54:56 UTC
svn commit: r821961 [28/30] - in /geronimo/sandbox/djencks/osgi/framework:
./ buildsupport/ buildsupport/car-maven-plugin/
buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/
buildsupport/geronimo-maven-plugin/src/main/jav...
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXParser.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXParser.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXSerializer.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXSerializer.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXSerializer.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXSerializer.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,1121 @@
+/* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
+// for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
+
+package org.apache.geronimo.system.plugin.plexus.util.xml.pull;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+/**
+ * Implementation of XmlSerializer interface from XmlPull V1 API.
+ * This implementation is optimized for performance and low memory footprint.
+ *
+ * <p>Implemented features:<ul>
+ * <li> FEATURE_NAMES_INTERNED - when enabled all returned names
+ * (namespaces, prefixes) will be interned and it is required that
+ * all names passed as arguments MUST be interned
+ * <li> FEATURE_SERIALIZER_ATTVALUE_USE_APOSTROPHE
+ * </ul>
+ * <p>Implemented properties:<ul>
+ * <li> PROPERTY_SERIALIZER_INDENTATION
+ * <li> PROPERTY_SERIALIZER_LINE_SEPARATOR
+ * </ul>
+ *
+ */
+public class MXSerializer implements XmlSerializer {
+ protected final static String XML_URI = "http://www.w3.org/XML/1998/namespace";
+ protected final static String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+ private static final boolean TRACE_SIZING = false;
+
+ protected final String FEATURE_SERIALIZER_ATTVALUE_USE_APOSTROPHE =
+ "http://xmlpull.org/v1/doc/features.html#serializer-attvalue-use-apostrophe";
+ protected final String FEATURE_NAMES_INTERNED =
+ "http://xmlpull.org/v1/doc/features.html#names-interned";
+ protected final String PROPERTY_SERIALIZER_INDENTATION =
+ "http://xmlpull.org/v1/doc/properties.html#serializer-indentation";
+ protected final String PROPERTY_SERIALIZER_LINE_SEPARATOR =
+ "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator";
+ protected final static String PROPERTY_LOCATION =
+ "http://xmlpull.org/v1/doc/properties.html#location";
+
+ // properties/features
+ protected boolean namesInterned;
+ protected boolean attributeUseApostrophe;
+ protected String indentationString = null; //" ";
+ protected String lineSeparator = "\n";
+
+ protected String location;
+ protected Writer out;
+
+ protected int autoDeclaredPrefixes;
+
+ protected int depth = 0;
+
+ // element stack
+ protected String elNamespace[] = new String[ 2 ];
+ protected String elName[] = new String[ elNamespace.length ];
+ protected int elNamespaceCount[] = new int[ elNamespace.length ];
+
+ //namespace stack
+ protected int namespaceEnd = 0;
+ protected String namespacePrefix[] = new String[ 8 ];
+ protected String namespaceUri[] = new String[ namespacePrefix.length ];
+
+ protected boolean finished;
+ protected boolean pastRoot;
+ protected boolean setPrefixCalled;
+ protected boolean startTagIncomplete;
+
+ protected boolean doIndent;
+ protected boolean seenTag;
+
+ protected boolean seenBracket;
+ protected boolean seenBracketBracket;
+
+ // buffer output if needed to write escaped String see text(String)
+ private static final int BUF_LEN = Runtime.getRuntime().freeMemory() > 1000000L ? 8*1024 : 256;
+ protected char buf[] = new char[ BUF_LEN ];
+
+
+ protected static final String precomputedPrefixes[];
+
+ static {
+ precomputedPrefixes = new String[32]; //arbitrary number ...
+ for (int i = 0; i < precomputedPrefixes.length; i++)
+ {
+ precomputedPrefixes[i] = ("n"+i).intern();
+ }
+ }
+
+ private boolean checkNamesInterned = false;
+
+ private void checkInterning(String name) {
+ if(namesInterned && name != name.intern()) {
+ throw new IllegalArgumentException(
+ "all names passed as arguments must be interned"
+ +"when NAMES INTERNED feature is enabled");
+ }
+ }
+
+ protected void reset() {
+ location = null;
+ out = null;
+ autoDeclaredPrefixes = 0;
+ depth = 0;
+
+ // nullify references on all levels to allow it to be GCed
+ for (int i = 0; i < elNamespaceCount.length; i++)
+ {
+ elName[ i ] = null;
+ elNamespace[ i ] = null;
+ elNamespaceCount[ i ] = 2;
+ }
+
+
+ namespaceEnd = 0;
+
+
+ //NOTE: no need to intern() as all literal strings and string-valued constant expressions
+ //are interned. String literals are defined in 3.10.5 of the Java Language Specification
+ // just checking ...
+ //assert "xmlns" == "xmlns".intern();
+ //assert XMLNS_URI == XMLNS_URI.intern();
+
+ //TODO: how to prevent from reporting this namespace?
+ // this is special namespace declared for consistency with XML infoset
+ namespacePrefix[ namespaceEnd ] = "xmlns";
+ namespaceUri[ namespaceEnd ] = XMLNS_URI;
+ ++namespaceEnd;
+
+ namespacePrefix[ namespaceEnd ] = "xml";
+ namespaceUri[ namespaceEnd ] = XML_URI;
+ ++namespaceEnd;
+
+ finished = false;
+ pastRoot = false;
+ setPrefixCalled = false;
+ startTagIncomplete = false;
+ //doIntent is not changed
+ seenTag = false;
+
+ seenBracket = false;
+ seenBracketBracket = false;
+ }
+
+
+ protected void ensureElementsCapacity() {
+ final int elStackSize = elName.length;
+ //assert (depth + 1) >= elName.length;
+ // we add at least one extra slot ...
+ final int newSize = (depth >= 7 ? 2 * depth : 8) + 2; // = lucky 7 + 1 //25
+ if(TRACE_SIZING) {
+ System.err.println(
+ getClass().getName()+" elStackSize "+elStackSize+" ==> "+newSize);
+ }
+ final boolean needsCopying = elStackSize > 0;
+ String[] arr = null;
+ // reuse arr local variable slot
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(elName, 0, arr, 0, elStackSize);
+ elName = arr;
+ arr = new String[newSize];
+ if(needsCopying) System.arraycopy(elNamespace, 0, arr, 0, elStackSize);
+ elNamespace = arr;
+
+ final int[] iarr = new int[newSize];
+ if(needsCopying) {
+ System.arraycopy(elNamespaceCount, 0, iarr, 0, elStackSize);
+ } else {
+ // special initialization
+ iarr[0] = 0;
+ }
+ elNamespaceCount = iarr;
+ }
+
+ protected void ensureNamespacesCapacity() { //int size) {
+ //int namespaceSize = namespacePrefix != null ? namespacePrefix.length : 0;
+ //assert (namespaceEnd >= namespacePrefix.length);
+
+ //if(size >= namespaceSize) {
+ //int newSize = size > 7 ? 2 * size : 8; // = lucky 7 + 1 //25
+ final int newSize = namespaceEnd > 7 ? 2 * namespaceEnd : 8;
+ if(TRACE_SIZING) {
+ System.err.println(
+ getClass().getName()+" namespaceSize "+namespacePrefix.length+" ==> "+newSize);
+ }
+ final String[] newNamespacePrefix = new String[newSize];
+ final String[] newNamespaceUri = new String[newSize];
+ if(namespacePrefix != null) {
+ System.arraycopy(
+ namespacePrefix, 0, newNamespacePrefix, 0, namespaceEnd);
+ System.arraycopy(
+ namespaceUri, 0, newNamespaceUri, 0, namespaceEnd);
+ }
+ namespacePrefix = newNamespacePrefix;
+ namespaceUri = newNamespaceUri;
+
+ // TODO use hashes for quick namespace->prefix lookups
+ // if( ! allStringsInterned ) {
+ // int[] newNamespacePrefixHash = new int[newSize];
+ // if(namespacePrefixHash != null) {
+ // System.arraycopy(
+ // namespacePrefixHash, 0, newNamespacePrefixHash, 0, namespaceEnd);
+ // }
+ // namespacePrefixHash = newNamespacePrefixHash;
+ // }
+ //prefixesSize = newSize;
+ // ////assert nsPrefixes.length > size && nsPrefixes.length == newSize
+ //}
+ }
+
+
+ public void setFeature(String name,
+ boolean state) throws IllegalArgumentException, IllegalStateException
+ {
+ if(name == null) {
+ throw new IllegalArgumentException("feature name can not be null");
+ }
+ if(FEATURE_NAMES_INTERNED.equals(name)) {
+ namesInterned = state;
+ } else if(FEATURE_SERIALIZER_ATTVALUE_USE_APOSTROPHE.equals(name)) {
+ attributeUseApostrophe = state;
+ } else {
+ throw new IllegalStateException("unsupported feature "+name);
+ }
+ }
+
+ public boolean getFeature(String name) throws IllegalArgumentException
+ {
+ if(name == null) {
+ throw new IllegalArgumentException("feature name can not be null");
+ }
+ if(FEATURE_NAMES_INTERNED.equals(name)) {
+ return namesInterned;
+ } else if(FEATURE_SERIALIZER_ATTVALUE_USE_APOSTROPHE.equals(name)) {
+ return attributeUseApostrophe;
+ } else {
+ return false;
+ }
+ }
+
+ // precomputed variables to simplify writing indentation
+ protected int offsetNewLine;
+ protected int indentationJump;
+ protected char[] indentationBuf;
+ protected int maxIndentLevel;
+ protected boolean writeLineSepartor; //should end-of-line be written
+ protected boolean writeIndentation; // is indentation used?
+
+ /**
+ * For maximum efficiency when writing indents the required output is pre-computed
+ * This is internal function that recomputes buffer after user requested chnages.
+ */
+ protected void rebuildIndentationBuf() {
+ if(doIndent == false) return;
+ final int maxIndent = 65; //hardcoded maximum indentation size in characters
+ int bufSize = 0;
+ offsetNewLine = 0;
+ if(writeLineSepartor) {
+ offsetNewLine = lineSeparator.length();
+ bufSize += offsetNewLine;
+ }
+ maxIndentLevel = 0;
+ if(writeIndentation) {
+ indentationJump = indentationString.length();
+ maxIndentLevel = maxIndent / indentationJump;
+ bufSize += maxIndentLevel * indentationJump;
+ }
+ if(indentationBuf == null || indentationBuf.length < bufSize) {
+ indentationBuf = new char[bufSize + 8];
+ }
+ int bufPos = 0;
+ if(writeLineSepartor) {
+ for (int i = 0; i < lineSeparator.length(); i++)
+ {
+ indentationBuf[ bufPos++ ] = lineSeparator.charAt(i);
+ }
+ }
+ if(writeIndentation) {
+ for (int i = 0; i < maxIndentLevel; i++)
+ {
+ for (int j = 0; j < indentationString.length(); j++)
+ {
+ indentationBuf[ bufPos++ ] = indentationString.charAt(j);
+ }
+ }
+ }
+ }
+
+ // if(doIndent) writeIndent();
+ protected void writeIndent() throws IOException {
+ final int start = writeLineSepartor ? 0 : offsetNewLine;
+ final int level = (depth > maxIndentLevel) ? maxIndentLevel : depth;
+ out.write( indentationBuf, start, (level * indentationJump) + offsetNewLine);
+ }
+
+ public void setProperty(String name,
+ Object value) throws IllegalArgumentException, IllegalStateException
+ {
+ if(name == null) {
+ throw new IllegalArgumentException("property name can not be null");
+ }
+ if(PROPERTY_SERIALIZER_INDENTATION.equals(name)) {
+ indentationString = (String)value;
+ } else if(PROPERTY_SERIALIZER_LINE_SEPARATOR.equals(name)) {
+ lineSeparator = (String)value;
+ } else if(PROPERTY_LOCATION.equals(name)) {
+ location = (String) value;
+ } else {
+ throw new IllegalStateException("unsupported property "+name);
+ }
+ writeLineSepartor = lineSeparator != null && lineSeparator.length() > 0;
+ writeIndentation = indentationString != null && indentationString.length() > 0;
+ // optimize - do not write when nothing to write ...
+ doIndent = indentationString != null && (writeLineSepartor || writeIndentation);
+ //NOTE: when indentationString == null there is no indentation
+ // (even though writeLineSeparator may be true ...)
+ rebuildIndentationBuf();
+ seenTag = false; // for consistency
+ }
+
+ public Object getProperty(String name) throws IllegalArgumentException
+ {
+ if(name == null) {
+ throw new IllegalArgumentException("property name can not be null");
+ }
+ if(PROPERTY_SERIALIZER_INDENTATION.equals(name)) {
+ return indentationString;
+ } else if(PROPERTY_SERIALIZER_LINE_SEPARATOR.equals(name)) {
+ return lineSeparator;
+ } else if(PROPERTY_LOCATION.equals(name)) {
+ return location;
+ } else {
+ return null;
+ }
+ }
+
+ private String getLocation() {
+ return location != null ? " @"+location : "";
+ }
+
+ // this is special method that can be accessed directly to retrieve Writer serializer is using
+ public Writer getWriter()
+ {
+ return out;
+ }
+
+ public void setOutput(Writer writer)
+ {
+ reset();
+ out = writer;
+ }
+
+ public void setOutput(OutputStream os, String encoding) throws IOException
+ {
+ if(os == null) throw new IllegalArgumentException("output stream can not be null");
+ reset();
+ if(encoding != null) {
+ out = new OutputStreamWriter(os, encoding);
+ } else {
+ out = new OutputStreamWriter(os);
+ }
+ }
+
+ public void startDocument (String encoding, Boolean standalone) throws IOException
+ {
+ char apos = attributeUseApostrophe ? '\'' : '"';
+ if(attributeUseApostrophe) {
+ out.write("<?xml version='1.0'");
+ } else {
+ out.write("<?xml version=\"1.0\"");
+ }
+ if(encoding != null) {
+ out.write(" encoding=");
+ out.write(attributeUseApostrophe ? '\'' : '"');
+ out.write(encoding);
+ out.write(attributeUseApostrophe ? '\'' : '"');
+ //out.write('\'');
+ }
+ if(standalone != null) {
+ out.write(" standalone=");
+ out.write(attributeUseApostrophe ? '\'' : '"');
+ if(standalone.booleanValue()) {
+ out.write("yes");
+ } else {
+ out.write("no");
+ }
+ out.write(attributeUseApostrophe ? '\'' : '"');
+ // if(standalone.booleanValue()) {
+ // out.write(" standalone='yes'");
+ // } else {
+ // out.write(" standalone='no'");
+ // }
+ }
+ out.write("?>");
+ if(writeLineSepartor) {
+ out.write(lineSeparator);
+ }
+ }
+
+ public void endDocument() throws IOException
+ {
+ // close all unclosed tag;
+ while(depth > 0) {
+ endTag(elNamespace[ depth ], elName[ depth ]);
+ }
+ if(writeLineSepartor) {
+ out.write(lineSeparator);
+ }
+ //assert depth == 0;
+ //assert startTagIncomplete == false;
+ finished = pastRoot = startTagIncomplete = true;
+ out.flush();
+ }
+
+ public void setPrefix(String prefix, String namespace) throws IOException
+ {
+ if(startTagIncomplete) closeStartTag();
+ //assert prefix != null;
+ //assert namespace != null;
+ if (prefix == null) {
+ prefix = "";
+ }
+ if(!namesInterned) {
+ prefix = prefix.intern(); //will throw NPE if prefix==null
+ } else if(checkNamesInterned) {
+ checkInterning(prefix);
+ } else if(prefix == null) {
+ throw new IllegalArgumentException("prefix must be not null"+getLocation());
+ }
+
+ //check that prefix is not duplicated ...
+ for (int i = elNamespaceCount[ depth ]; i < namespaceEnd; i++)
+ {
+ if(prefix == namespacePrefix[ i ]) {
+ throw new IllegalStateException("duplicated prefix "+printable(prefix)+getLocation());
+ }
+ }
+
+ if(!namesInterned) {
+ namespace = namespace.intern();
+ } else if(checkNamesInterned) {
+ checkInterning(namespace);
+ } else if(namespace == null) {
+ throw new IllegalArgumentException("namespace must be not null"+getLocation());
+ }
+
+ if(namespaceEnd >= namespacePrefix.length) {
+ ensureNamespacesCapacity();
+ }
+ namespacePrefix[ namespaceEnd ] = prefix;
+ namespaceUri[ namespaceEnd ] = namespace;
+ ++namespaceEnd;
+ setPrefixCalled = true;
+ }
+
+ protected String lookupOrDeclarePrefix( String namespace ) {
+ return getPrefix(namespace, true);
+ }
+
+ public String getPrefix(String namespace, boolean generatePrefix)
+ {
+ //assert namespace != null;
+ if(!namesInterned) {
+ // when String is interned we can do much faster namespace stack lookups ...
+ namespace = namespace.intern();
+ } else if(checkNamesInterned) {
+ checkInterning(namespace);
+ //assert namespace != namespace.intern();
+ }
+ if(namespace == null) {
+ throw new IllegalArgumentException("namespace must be not null"+getLocation());
+ } else if(namespace.length() == 0) {
+ throw new IllegalArgumentException("default namespace cannot have prefix"+getLocation());
+ }
+
+ // first check if namespace is already in scope
+ for (int i = namespaceEnd - 1; i >= 0 ; --i)
+ {
+ if(namespace == namespaceUri[ i ]) {
+ final String prefix = namespacePrefix[ i ];
+ // now check that prefix is still in scope
+ for (int p = namespaceEnd - 1; p > i ; --p)
+ {
+ if(prefix == namespacePrefix[ p ])
+ continue; // too bad - prefix is redeclared with different namespace
+ }
+ return prefix;
+ }
+ }
+
+ // so not found it ...
+ if(!generatePrefix) {
+ return null;
+ }
+ return generatePrefix(namespace);
+ }
+
+ private String generatePrefix(String namespace) {
+ //assert namespace == namespace.intern();
+ while(true) {
+ ++autoDeclaredPrefixes;
+ //fast lookup uses table that was pre-initialized in static{} ....
+ final String prefix = autoDeclaredPrefixes < precomputedPrefixes.length
+ ? precomputedPrefixes[autoDeclaredPrefixes] : ("n"+autoDeclaredPrefixes).intern();
+ // make sure this prefix is not declared in any scope (avoid hiding in-scope prefixes)!
+ for (int i = namespaceEnd - 1; i >= 0 ; --i)
+ {
+ if(prefix == namespacePrefix[ i ]) {
+ continue; // prefix is already declared - generate new and try again
+ }
+ }
+ // declare prefix
+
+ if(namespaceEnd >= namespacePrefix.length) {
+ ensureNamespacesCapacity();
+ }
+ namespacePrefix[ namespaceEnd ] = prefix;
+ namespaceUri[ namespaceEnd ] = namespace;
+ ++namespaceEnd;
+
+ return prefix;
+ }
+ }
+
+ public int getDepth()
+ {
+ return depth;
+ }
+
+ public String getNamespace ()
+ {
+ return elNamespace[depth];
+ }
+
+ public String getName()
+ {
+ return elName[depth];
+ }
+
+ public XmlSerializer startTag (String namespace, String name) throws IOException
+ {
+
+ if(startTagIncomplete) {
+ closeStartTag();
+ }
+ seenBracket = seenBracketBracket = false;
+ if(doIndent && depth > 0 && seenTag) {
+ writeIndent();
+ }
+ seenTag = true;
+ setPrefixCalled = false;
+ startTagIncomplete = true;
+ ++depth;
+ if( (depth + 1) >= elName.length) {
+ ensureElementsCapacity();
+ }
+ ////assert namespace != null;
+
+ if(checkNamesInterned && namesInterned) checkInterning(namespace);
+ elNamespace[ depth ] = (namesInterned || namespace == null) ? namespace : namespace.intern();
+ //assert name != null;
+ //elName[ depth ] = name;
+ if(checkNamesInterned && namesInterned) checkInterning(name);
+ elName[ depth ] = (namesInterned || name == null) ? name : name.intern();
+ if(out == null) {
+ throw new IllegalStateException("setOutput() must called set before serialization can start");
+ }
+ out.write('<');
+ if(namespace != null) {
+
+ if(namespace.length() > 0) {
+ //ALEK: in future make it as feature on serializer
+ String prefix = null;
+ if(depth > 0 && (namespaceEnd - elNamespaceCount[depth-1]) == 1) {
+ // if only one prefix was declared un-declare it if prefix is already declared on parent el with the same URI
+ String uri = namespaceUri[namespaceEnd-1];
+ if(uri == namespace || uri.equals(namespace)) {
+ String elPfx = namespacePrefix[namespaceEnd-1];
+ // 2 == to skip predefined namespaces (xml and xmlns ...)
+ for(int pos = elNamespaceCount[depth-1] - 1; pos >= 2; --pos ) {
+ String pf = namespacePrefix[pos];
+ if(pf == elPfx || pf.equals(elPfx)) {
+ String n = namespaceUri[pos];
+ if(n == uri || n.equals(uri)) {
+ --namespaceEnd; //un-declare namespace
+ prefix = elPfx;
+ }
+ break;
+ }
+ }
+ }
+ }
+ if(prefix == null) {
+ prefix = lookupOrDeclarePrefix( namespace );
+ }
+ //assert prefix != null;
+ // make sure that default ("") namespace to not print ":"
+ if(prefix.length() > 0) {
+ out.write(prefix);
+ out.write(':');
+ }
+ } else {
+ // make sure that default namespace can be declared
+ for (int i = namespaceEnd - 1; i >= 0 ; --i)
+ {
+ if(namespacePrefix[ i ] == "") {
+ final String uri = namespaceUri[ i ];
+ if(uri == null) {
+ // declare default namespace
+ setPrefix("", "");
+ } else if(uri.length() > 0) {
+ throw new IllegalStateException(
+ "start tag can not be written in empty default namespace "+
+ "as default namespace is currently bound to '"+uri+"'"+getLocation());
+ }
+ break;
+ }
+ }
+ }
+
+ }
+ out.write(name);
+ return this;
+ }
+
+ public XmlSerializer attribute (String namespace, String name,
+ String value) throws IOException
+ {
+ if(!startTagIncomplete) {
+ throw new IllegalArgumentException("startTag() must be called before attribute()"+getLocation());
+ }
+ //assert setPrefixCalled == false;
+ out.write(' ');
+ ////assert namespace != null;
+ if(namespace != null && namespace.length() > 0) {
+ //namespace = namespace.intern();
+ if(!namesInterned) {
+ namespace = namespace.intern();
+ } else if(checkNamesInterned) {
+ checkInterning(namespace);
+ }
+ String prefix = lookupOrDeclarePrefix( namespace );
+ //assert( prefix != null);
+ if(prefix.length() == 0) {
+ // needs to declare prefix to hold default namespace
+ //NOTE: attributes such as a='b' are in NO namespace
+ prefix = generatePrefix(namespace);
+ }
+ out.write(prefix);
+ out.write(':');
+ // if(prefix.length() > 0) {
+ // out.write(prefix);
+ // out.write(':');
+ // }
+ }
+ //assert name != null;
+ out.write(name);
+ out.write('=');
+ //assert value != null;
+ out.write( attributeUseApostrophe ? '\'' : '"');
+ writeAttributeValue(value, out);
+ out.write( attributeUseApostrophe ? '\'' : '"');
+ return this;
+ }
+
+ protected void closeStartTag() throws IOException {
+ if(finished) {
+ throw new IllegalArgumentException("trying to write past already finished output"+getLocation());
+ }
+ if(seenBracket) {
+ seenBracket = seenBracketBracket = false;
+ }
+ if( startTagIncomplete || setPrefixCalled ) {
+ if(setPrefixCalled) {
+ throw new IllegalArgumentException(
+ "startTag() must be called immediately after setPrefix()"+getLocation());
+ }
+ if(!startTagIncomplete) {
+ throw new IllegalArgumentException("trying to close start tag that is not opened"+getLocation());
+ }
+
+ // write all namespace declarations!
+ writeNamespaceDeclarations();
+ out.write('>');
+ elNamespaceCount[ depth ] = namespaceEnd;
+ startTagIncomplete = false;
+ }
+ }
+
+ private void writeNamespaceDeclarations() throws IOException
+ {
+ //int start = elNamespaceCount[ depth - 1 ];
+ for (int i = elNamespaceCount[ depth - 1 ]; i < namespaceEnd; i++)
+ {
+ if(doIndent && namespaceUri[ i ].length() > 40) {
+ writeIndent();
+ out.write(" ");
+ }
+ if(namespacePrefix[ i ] != "") {
+ out.write(" xmlns:");
+ out.write(namespacePrefix[ i ]);
+ out.write('=');
+ } else {
+ out.write(" xmlns=");
+ }
+ out.write( attributeUseApostrophe ? '\'' : '"');
+
+ //NOTE: escaping of namespace value the same way as attributes!!!!
+ writeAttributeValue(namespaceUri[ i ], out);
+
+ out.write( attributeUseApostrophe ? '\'' : '"');
+ }
+ }
+
+ public XmlSerializer endTag(String namespace, String name) throws IOException
+ {
+ // check that level is valid
+ ////assert namespace != null;
+ //if(namespace != null) {
+ // namespace = namespace.intern();
+ //}
+ seenBracket = seenBracketBracket = false;
+ if(namespace != null) {
+ if(!namesInterned) {
+ namespace = namespace.intern();
+ } else if(checkNamesInterned) {
+ checkInterning(namespace);
+ }
+ }
+
+ if(namespace != elNamespace[ depth ])
+ {
+ throw new IllegalArgumentException(
+ "expected namespace "+printable(elNamespace[ depth ])
+ +" and not "+printable(namespace)+getLocation());
+ }
+ if(name == null) {
+ throw new IllegalArgumentException("end tag name can not be null"+getLocation());
+ }
+ if(checkNamesInterned && namesInterned) {
+ checkInterning(name);
+ }
+
+ if((!namesInterned && !name.equals(elName[ depth ]))
+ || (namesInterned && name != elName[ depth ]))
+ {
+ throw new IllegalArgumentException(
+ "expected element name "+printable(elName[ depth ])+" and not "+printable(name)+getLocation());
+ }
+ if(startTagIncomplete) {
+ writeNamespaceDeclarations();
+ out.write(" />"); //space is added to make it easier to work in XHTML!!!
+ --depth;
+ } else {
+ --depth;
+ //assert startTagIncomplete == false;
+ if(doIndent && seenTag) { writeIndent(); }
+ out.write("</");
+ if(namespace != null && namespace.length() > 0) {
+ //TODO prefix should be alredy known from matching start tag ...
+ final String prefix = lookupOrDeclarePrefix( namespace );
+ //assert( prefix != null);
+ if(prefix.length() > 0) {
+ out.write(prefix);
+ out.write(':');
+ }
+ }
+ out.write(name);
+ out.write('>');
+
+ }
+ namespaceEnd = elNamespaceCount[ depth ];
+ startTagIncomplete = false;
+ seenTag = true;
+ return this;
+ }
+
+ public XmlSerializer text (String text) throws IOException
+ {
+ //assert text != null;
+ if(startTagIncomplete || setPrefixCalled) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ writeElementContent(text, out);
+ return this;
+ }
+
+ public XmlSerializer text (char [] buf, int start, int len) throws IOException
+ {
+ if(startTagIncomplete || setPrefixCalled) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ writeElementContent(buf, start, len, out);
+ return this;
+ }
+
+ public void cdsect (String text) throws IOException
+ {
+ if(startTagIncomplete || setPrefixCalled || seenBracket) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ out.write("<![CDATA[");
+ out.write(text); //escape?
+ out.write("]]>");
+ }
+
+ public void entityRef (String text) throws IOException
+ {
+ if(startTagIncomplete || setPrefixCalled || seenBracket) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ out.write('&');
+ out.write(text); //escape?
+ out.write(';');
+ }
+
+ public void processingInstruction (String text) throws IOException
+ {
+ if(startTagIncomplete || setPrefixCalled || seenBracket) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ out.write("<?");
+ out.write(text); //escape?
+ out.write("?>");
+ }
+
+ public void comment (String text) throws IOException
+ {
+ if(startTagIncomplete || setPrefixCalled || seenBracket) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ out.write("<!--");
+ out.write(text); //escape?
+ out.write("-->");
+ }
+
+ public void docdecl (String text) throws IOException
+ {
+ if(startTagIncomplete || setPrefixCalled || seenBracket) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ out.write("<!DOCTYPE ");
+ out.write(text); //escape?
+ out.write(">");
+ }
+
+ public void ignorableWhitespace (String text) throws IOException
+ {
+ if(startTagIncomplete || setPrefixCalled || seenBracket) closeStartTag();
+ if(doIndent && seenTag) seenTag = false;
+ if(text.length() == 0) {
+ throw new IllegalArgumentException(
+ "empty string is not allowed for ignorable whitespace"+getLocation());
+ }
+ out.write(text); //no escape?
+ }
+
+ public void flush () throws IOException
+ {
+ if(!finished && startTagIncomplete) closeStartTag();
+ out.flush();
+ }
+
+ // --- utility methods
+
+ protected void writeAttributeValue(String value, Writer out) throws IOException
+ {
+ //.[apostrophe and <, & escaped],
+ final char quot = attributeUseApostrophe ? '\'' : '"';
+ final String quotEntity = attributeUseApostrophe ? "'" : """;
+
+ int pos = 0;
+ for (int i = 0; i < value.length(); i++)
+ {
+ char ch = value.charAt(i);
+ if(ch == '&') {
+ if(i > pos) out.write(value.substring(pos, i));
+ out.write("&");
+ pos = i + 1;
+ } if(ch == '<') {
+ if(i > pos) out.write(value.substring(pos, i));
+ out.write("<");
+ pos = i + 1;
+ }else if(ch == quot) {
+ if(i > pos) out.write(value.substring(pos, i));
+ out.write(quotEntity);
+ pos = i + 1;
+ } else if(ch < 32) {
+ //in XML 1.0 only legal character are #x9 | #xA | #xD
+ // and they must be escaped otherwise in attribute value they are normalized to spaces
+ if(ch == 13 || ch == 10 || ch == 9) {
+ if(i > pos) out.write(value.substring(pos, i));
+ out.write("&#");
+ out.write(Integer.toString(ch));
+ out.write(';');
+ pos = i + 1;
+ } else {
+ throw new IllegalStateException(
+ "character "+Integer.toString(ch)+" is not allowed in output"+getLocation());
+ // in XML 1.1 legal are [#x1-#xD7FF]
+ // if(ch > 0) {
+ // if(i > pos) out.write(text.substring(pos, i));
+ // out.write("&#");
+ // out.write(Integer.toString(ch));
+ // out.write(';');
+ // pos = i + 1;
+ // } else {
+ // throw new IllegalStateException(
+ // "character zero is not allowed in XML 1.1 output"+getLocation());
+ // }
+ }
+ }
+ }
+ if(pos > 0) {
+ out.write(value.substring(pos));
+ } else {
+ out.write(value); // this is shortcut to the most common case
+ }
+
+ }
+
+ protected void writeElementContent(String text, Writer out) throws IOException
+ {
+ // escape '<', '&', ']]>', <32 if necessary
+ int pos = 0;
+ for (int i = 0; i < text.length(); i++)
+ {
+ //TODO: check if doing char[] text.getChars() would be faster than getCharAt(i) ...
+ char ch = text.charAt(i);
+ if(ch == ']') {
+ if(seenBracket) {
+ seenBracketBracket = true;
+ } else {
+ seenBracket = true;
+ }
+ } else {
+ if(ch == '&') {
+ if(i > pos) out.write(text.substring(pos, i));
+ out.write("&");
+ pos = i + 1;
+ } else if(ch == '<') {
+ if(i > pos) out.write(text.substring(pos, i));
+ out.write("<");
+ pos = i + 1;
+ } else if(seenBracketBracket && ch == '>') {
+ if(i > pos) out.write(text.substring(pos, i));
+ out.write(">");
+ pos = i + 1;
+ } else if(ch < 32) {
+ //in XML 1.0 only legal character are #x9 | #xA | #xD
+ if( ch == 9 || ch == 10 || ch == 13) {
+ // pass through
+
+ // } else if(ch == 13) { //escape
+ // if(i > pos) out.write(text.substring(pos, i));
+ // out.write("&#");
+ // out.write(Integer.toString(ch));
+ // out.write(';');
+ // pos = i + 1;
+ } else {
+ throw new IllegalStateException(
+ "character "+Integer.toString(ch)+" is not allowed in output"+getLocation());
+ // in XML 1.1 legal are [#x1-#xD7FF]
+ // if(ch > 0) {
+ // if(i > pos) out.write(text.substring(pos, i));
+ // out.write("&#");
+ // out.write(Integer.toString(ch));
+ // out.write(';');
+ // pos = i + 1;
+ // } else {
+ // throw new IllegalStateException(
+ // "character zero is not allowed in XML 1.1 output"+getLocation());
+ // }
+ }
+ }
+ if(seenBracket) {
+ seenBracketBracket = seenBracket = false;
+ }
+
+ }
+ }
+ if(pos > 0) {
+ out.write(text.substring(pos));
+ } else {
+ out.write(text); // this is shortcut to the most common case
+ }
+
+
+
+ }
+
+ protected void writeElementContent(char[] buf, int off, int len, Writer out) throws IOException
+ {
+ // escape '<', '&', ']]>'
+ final int end = off + len;
+ int pos = off;
+ for (int i = off; i < end; i++)
+ {
+ final char ch = buf[i];
+ if(ch == ']') {
+ if(seenBracket) {
+ seenBracketBracket = true;
+ } else {
+ seenBracket = true;
+ }
+ } else {
+ if(ch == '&') {
+ if(i > pos) {
+ out.write(buf, pos, i - pos);
+ }
+ out.write("&");
+ pos = i + 1;
+ } else if(ch == '<') {
+ if(i > pos) {
+ out.write(buf, pos, i - pos);
+ }
+ out.write("<");
+ pos = i + 1;
+
+ } else if(seenBracketBracket && ch == '>') {
+ if(i > pos) {
+ out.write(buf, pos, i - pos);
+ }
+ out.write(">");
+ pos = i + 1;
+ } else if(ch < 32) {
+ //in XML 1.0 only legal character are #x9 | #xA | #xD
+ if( ch == 9 || ch == 10 || ch == 13) {
+ // pass through
+
+
+ // } else if(ch == 13 ) { //if(ch == '\r') {
+ // if(i > pos) {
+ // out.write(buf, pos, i - pos);
+ // }
+ // out.write("&#");
+ // out.write(Integer.toString(ch));
+ // out.write(';');
+ // pos = i + 1;
+ } else {
+ throw new IllegalStateException(
+ "character "+Integer.toString(ch)+" is not allowed in output"+getLocation());
+ // in XML 1.1 legal are [#x1-#xD7FF]
+ // if(ch > 0) {
+ // if(i > pos) out.write(text.substring(pos, i));
+ // out.write("&#");
+ // out.write(Integer.toString(ch));
+ // out.write(';');
+ // pos = i + 1;
+ // } else {
+ // throw new IllegalStateException(
+ // "character zero is not allowed in XML 1.1 output"+getLocation());
+ // }
+ }
+ }
+ if(seenBracket) {
+ seenBracketBracket = seenBracket = false;
+ }
+ // assert seenBracketBracket == seenBracket == false;
+ }
+ }
+ if(end > pos) {
+ out.write(buf, pos, end - pos);
+ }
+ }
+
+ /** simple utility method -- good for debugging */
+ protected static final String printable(String s) {
+ if(s == null) return "null";
+ StringBuffer retval = new StringBuffer(s.length() + 16);
+ retval.append("'");
+ char ch;
+ for (int i = 0; i < s.length(); i++) {
+ addPrintable(retval, s.charAt(i));
+ }
+ retval.append("'");
+ return retval.toString();
+ }
+
+ protected static final String printable(char ch) {
+ StringBuffer retval = new StringBuffer();
+ addPrintable(retval, ch);
+ return retval.toString();
+ }
+
+ private static void addPrintable(StringBuffer retval, char ch)
+ {
+ switch (ch)
+ {
+ case '\b':
+ retval.append("\\b");
+ break;
+ case '\t':
+ retval.append("\\t");
+ break;
+ case '\n':
+ retval.append("\\n");
+ break;
+ case '\f':
+ retval.append("\\f");
+ break;
+ case '\r':
+ retval.append("\\r");
+ break;
+ case '\"':
+ retval.append("\\\"");
+ break;
+ case '\'':
+ retval.append("\\\'");
+ break;
+ case '\\':
+ retval.append("\\\\");
+ break;
+ default:
+ if (ch < 0x20 || ch > 0x7e) {
+ final String ss = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + ss.substring(ss.length() - 4, ss.length()));
+ } else {
+ retval.append(ch);
+ }
+ }
+ }
+
+}
+
+
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXSerializer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXSerializer.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/xml/pull/MXSerializer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain