feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* @author Kohsuke Kawaguchi
*/
final class Attribute {
final String nsUri;
final String localName;
/**
* Attributes of an element form a linked list.
*/
Attribute next;
/**
* Attribute value that potentially contains dummy prefixes.
*/
final StringBuilder value = new StringBuilder();
Attribute(String nsUri, String localName) {
assert nsUri!=null && localName!=null;
this.nsUri = nsUri;
this.localName = localName;
}
boolean hasName( String nsUri, String localName ) {
return this.localName.equals(localName) && this.nsUri.equals(nsUri);
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* CDATA section.
*
* @author Kohsuke Kawaguchi
*/
final class Cdata extends Text {
Cdata(Document document, NamespaceResolver nsResolver, Object obj) {
super(document, nsResolver, obj);
}
void accept(ContentVisitor visitor) {
visitor.onCdata(buffer);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* Comment.
*
* @author Kohsuke Kawaguchi
*/
final class Comment extends Content {
/**
* The text to be writtten.
*/
private final StringBuilder buffer = new StringBuilder();
public Comment(Document document, NamespaceResolver nsResolver, Object obj) {
document.writeValue(obj,nsResolver,buffer);
}
boolean concludesPendingStartTag() {
return false;
}
void accept(ContentVisitor visitor) {
visitor.onComment(buffer);
}
}

View File

@@ -0,0 +1,376 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
import com.sun.xml.internal.txw2.annotation.XmlAttribute;
import com.sun.xml.internal.txw2.annotation.XmlElement;
import com.sun.xml.internal.txw2.annotation.XmlNamespace;
import com.sun.xml.internal.txw2.annotation.XmlValue;
import com.sun.xml.internal.txw2.annotation.XmlCDATA;
import javax.xml.namespace.QName;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Dynamically implements {@link TypedXmlWriter} interfaces.
*
* @author Kohsuke Kawaguchi
*/
final class ContainerElement implements InvocationHandler, TypedXmlWriter {
final Document document;
/**
* Initially, point to the start tag token, but
* once we know we are done with the start tag, we will reset it to null
* so that the token sequence can be GC-ed.
*/
StartTag startTag;
final EndTag endTag = new EndTag();
/**
* Namespace URI of this element.
*/
private final String nsUri;
/**
* When this element can accept more child content, this value
* is non-null and holds the last child {@link Content}.
*
* If this element is committed, this parameter is null.
*/
private Content tail;
/**
* Uncommitted {@link ContainerElement}s form a doubly-linked list,
* so that the parent can close them recursively.
*/
private ContainerElement prevOpen;
private ContainerElement nextOpen;
private final ContainerElement parent;
private ContainerElement lastOpenChild;
/**
* Set to true if the start eleent is blocked.
*/
private boolean blocked;
public ContainerElement(Document document,ContainerElement parent,String nsUri, String localName) {
this.parent = parent;
this.document = document;
this.nsUri = nsUri;
this.startTag = new StartTag(this,nsUri,localName);
tail = startTag;
if(isRoot())
document.setFirstContent(startTag);
}
private boolean isRoot() {
return parent==null;
}
private boolean isCommitted() {
return tail==null;
}
public Document getDocument() {
return document;
}
boolean isBlocked() {
return blocked && !isCommitted();
}
public void block() {
blocked = true;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getDeclaringClass()==TypedXmlWriter.class || method.getDeclaringClass()==Object.class) {
// forward to myself
try {
return method.invoke(this,args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
XmlAttribute xa = method.getAnnotation(XmlAttribute.class);
XmlValue xv = method.getAnnotation(XmlValue.class);
XmlElement xe = method.getAnnotation(XmlElement.class);
if(xa!=null) {
if(xv!=null || xe!=null)
throw new IllegalAnnotationException(method.toString());
addAttribute(xa,method,args);
return proxy; // allow method chaining
}
if(xv!=null) {
if(xe!=null)
throw new IllegalAnnotationException(method.toString());
_pcdata(args);
return proxy; // allow method chaining
}
return addElement(xe,method,args);
}
/**
* Writes an attribute.
*/
private void addAttribute(XmlAttribute xa, Method method, Object[] args) {
assert xa!=null;
checkStartTag();
String localName = xa.value();
if(xa.value().length()==0)
localName = method.getName();
_attribute(xa.ns(),localName,args);
}
private void checkStartTag() {
if(startTag==null)
throw new IllegalStateException("start tag has already been written");
}
/**
* Writes a new element.
*/
private Object addElement(XmlElement e, Method method, Object[] args) {
Class<?> rt = method.getReturnType();
// the last precedence: default name
String nsUri = "##default";
String localName = method.getName();
if(e!=null) {
// then the annotation on this method
if(e.value().length()!=0)
localName = e.value();
nsUri = e.ns();
}
if(nsUri.equals("##default")) {
// look for the annotation on the declaring class
Class<?> c = method.getDeclaringClass();
XmlElement ce = c.getAnnotation(XmlElement.class);
if(ce!=null) {
nsUri = ce.ns();
}
if(nsUri.equals("##default"))
// then default to the XmlNamespace
nsUri = getNamespace(c.getPackage());
}
if(rt==Void.TYPE) {
// leaf element with just a value
boolean isCDATA = method.getAnnotation(XmlCDATA.class)!=null;
StartTag st = new StartTag(document,nsUri,localName);
addChild(st);
for( Object arg : args ) {
Text text;
if(isCDATA) text = new Cdata(document,st,arg);
else text = new Pcdata(document,st,arg);
addChild(text);
}
addChild(new EndTag());
return null;
}
if(TypedXmlWriter.class.isAssignableFrom(rt)) {
// sub writer
return _element(nsUri,localName,(Class)rt);
}
throw new IllegalSignatureException("Illegal return type: "+rt);
}
/**
* Decides the namespace URI of the given package.
*/
private String getNamespace(Package pkg) {
if(pkg==null) return "";
String nsUri;
XmlNamespace ns = pkg.getAnnotation(XmlNamespace.class);
if(ns!=null)
nsUri = ns.value();
else
nsUri = "";
return nsUri;
}
/**
* Appends this child object to the tail.
*/
private void addChild(Content child) {
tail.setNext(document,child);
tail = child;
}
public void commit() {
commit(true);
}
public void commit(boolean includingAllPredecessors) {
_commit(includingAllPredecessors);
document.flush();
}
private void _commit(boolean includingAllPredecessors) {
if(isCommitted()) return;
addChild(endTag);
if(isRoot())
addChild(new EndDocument());
tail = null;
// _commit predecessors if so told
if(includingAllPredecessors) {
for( ContainerElement e=this; e!=null; e=e.parent ) {
while(e.prevOpen!=null) {
e.prevOpen._commit(false);
// e.prevOpen should change as a result of committing it.
}
}
}
// _commit all children recursively
while(lastOpenChild!=null)
lastOpenChild._commit(false);
// remove this node from the link
if(parent!=null) {
if(parent.lastOpenChild==this) {
assert nextOpen==null : "this must be the last one";
parent.lastOpenChild = prevOpen;
} else {
assert nextOpen.prevOpen==this;
nextOpen.prevOpen = this.prevOpen;
}
if(prevOpen!=null) {
assert prevOpen.nextOpen==this;
prevOpen.nextOpen = this.nextOpen;
}
}
this.nextOpen = null;
this.prevOpen = null;
}
public void _attribute(String localName, Object value) {
_attribute("",localName,value);
}
public void _attribute(String nsUri, String localName, Object value) {
checkStartTag();
startTag.addAttribute(nsUri,localName,value);
}
public void _attribute(QName attributeName, Object value) {
_attribute(attributeName.getNamespaceURI(),attributeName.getLocalPart(),value);
}
public void _namespace(String uri) {
_namespace(uri,false);
}
public void _namespace(String uri, String prefix) {
if(prefix==null)
throw new IllegalArgumentException();
checkStartTag();
startTag.addNamespaceDecl(uri,prefix,false);
}
public void _namespace(String uri, boolean requirePrefix) {
checkStartTag();
startTag.addNamespaceDecl(uri,null,requirePrefix);
}
public void _pcdata(Object value) {
// we need to allow this method even when startTag has already been completed.
// checkStartTag();
addChild(new Pcdata(document,startTag,value));
}
public void _cdata(Object value) {
addChild(new Cdata(document,startTag,value));
}
public void _comment(Object value) throws UnsupportedOperationException {
addChild(new Comment(document,startTag,value));
}
public <T extends TypedXmlWriter> T _element(String localName, Class<T> contentModel) {
return _element(nsUri,localName,contentModel);
}
public <T extends TypedXmlWriter> T _element(QName tagName, Class<T> contentModel) {
return _element(tagName.getNamespaceURI(),tagName.getLocalPart(),contentModel);
}
public <T extends TypedXmlWriter> T _element(Class<T> contentModel) {
return _element(TXW.getTagName(contentModel),contentModel);
}
public <T extends TypedXmlWriter> T _cast(Class<T> facadeType) {
return facadeType.cast(Proxy.newProxyInstance(facadeType.getClassLoader(),new Class[]{facadeType},this));
}
public <T extends TypedXmlWriter> T _element(String nsUri, String localName, Class<T> contentModel) {
ContainerElement child = new ContainerElement(document,this,nsUri,localName);
addChild(child.startTag);
tail = child.endTag;
// update uncommitted link list
if(lastOpenChild!=null) {
assert lastOpenChild.parent==this;
assert child.prevOpen==null;
assert child.nextOpen==null;
child.prevOpen = lastOpenChild;
assert lastOpenChild.nextOpen==null;
lastOpenChild.nextOpen = child;
}
this.lastOpenChild = child;
return child._cast(contentModel);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* @author Kohsuke Kawaguchi
*/
abstract class Content {
private Content next;
/**
* Returns null if the next token has not decided yet.
*/
final Content getNext() {
return next;
}
/**
*
* @param doc
* A {@link Content} object is so light-weight that
* it doesn't even remember what document it belongs to.
* So the caller needs to "remind" a {@link Content}
* who its owner is.
*/
final void setNext(Document doc,Content next) {
assert next!=null;
assert this.next==null : "next of "+this+" is already set to "+this.next;
this.next = next;
doc.run();
}
/**
* Returns true if this content is ready to be committed.
*/
boolean isReadyToCommit() {
return true;
}
/**
* Returns true if this {@link Content} can guarantee that
* no more new namespace decls is necessary for the currently
* pending start tag.
*/
abstract boolean concludesPendingStartTag();
/**
* Accepts a visitor.
*/
abstract void accept(ContentVisitor visitor);
/**
* Called when this content is written to the output.
*/
public void written() {
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* Visits {@link Content}.
*
* @author Kohsuke Kawaguchi
*/
interface ContentVisitor {
void onStartDocument();
void onEndDocument();
void onEndTag();
void onPcdata(StringBuilder buffer);
void onCdata(StringBuilder buffer);
void onStartTag(String nsUri, String localName, Attribute attributes, NamespaceDecl namespaces);
void onComment(StringBuilder buffer);
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
import java.util.AbstractList;
import java.util.Collections;
import java.util.List;
import javax.xml.namespace.QName;
/**
* Pluggable datatype writer.
*
* @author Kohsuke Kawaguchi
*/
public interface DatatypeWriter<DT> {
/**
* Gets the Java class that this writer can write.
*
* @return
* must not be null. Must be the same value always.
*/
Class<DT> getType();
/**
* Prints the given datatype object and appends that result
* into the given buffer.
*
* @param dt
* the datatype object to be printed.
* @param resolver
* allows the converter to declare additional namespace prefixes.
*/
void print(DT dt, NamespaceResolver resolver, StringBuilder buf);
static final List<DatatypeWriter<?>> BUILTIN = Collections.unmodifiableList(new AbstractList() {
private DatatypeWriter<?>[] BUILTIN_ARRAY = new DatatypeWriter<?>[] {
new DatatypeWriter<String>() {
public Class<String> getType() {
return String.class;
}
public void print(String s, NamespaceResolver resolver, StringBuilder buf) {
buf.append(s);
}
},
new DatatypeWriter<Integer>() {
public Class<Integer> getType() {
return Integer.class;
}
public void print(Integer i, NamespaceResolver resolver, StringBuilder buf) {
buf.append(i);
}
},
new DatatypeWriter<Float>() {
public Class<Float> getType() {
return Float.class;
}
public void print(Float f, NamespaceResolver resolver, StringBuilder buf) {
buf.append(f);
}
},
new DatatypeWriter<Double>() {
public Class<Double> getType() {
return Double.class;
}
public void print(Double d, NamespaceResolver resolver, StringBuilder buf) {
buf.append(d);
}
},
new DatatypeWriter<QName>() {
public Class<QName> getType() {
return QName.class;
}
public void print(QName qn, NamespaceResolver resolver, StringBuilder buf) {
String p = resolver.getPrefix(qn.getNamespaceURI());
if(p.length()!=0)
buf.append(p).append(':');
buf.append(qn.getLocalPart());
}
}
};
public DatatypeWriter<?> get(int n) {
return BUILTIN_ARRAY[n];
}
public int size() {
return BUILTIN_ARRAY.length;
}
});
}

View File

@@ -0,0 +1,338 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
import com.sun.xml.internal.txw2.output.XmlSerializer;
import java.util.Map;
import java.util.HashMap;
/**
* Coordinates the entire writing process.
*
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public final class Document {
private final XmlSerializer out;
/**
* Set to true once we invoke {@link XmlSerializer#startDocument()}.
*
* <p>
* This is so that we can defer the writing as much as possible.
*/
private boolean started=false;
/**
* Currently active writer.
*
* <p>
* This points to the last written token.
*/
private Content current = null;
private final Map<Class,DatatypeWriter> datatypeWriters = new HashMap<Class,DatatypeWriter>();
/**
* Used to generate unique namespace prefix.
*/
private int iota = 1;
/**
* Used to keep track of in-scope namespace bindings declared in ancestors.
*/
private final NamespaceSupport inscopeNamespace = new NamespaceSupport();
/**
* Remembers the namespace declarations of the last unclosed start tag,
* so that we can fix up dummy prefixes in {@link Pcdata}.
*/
private NamespaceDecl activeNamespaces;
Document(XmlSerializer out) {
this.out = out;
for( DatatypeWriter dw : DatatypeWriter.BUILTIN )
datatypeWriters.put(dw.getType(),dw);
}
void flush() {
out.flush();
}
void setFirstContent(Content c) {
assert current==null;
current = new StartDocument();
current.setNext(this,c);
}
/**
* Defines additional user object -> string conversion logic.
*
* <p>
* Applications can add their own {@link DatatypeWriter} so that
* application-specific objects can be turned into {@link String}
* for output.
*
* @param dw
* The {@link DatatypeWriter} to be added. Must not be null.
*/
public void addDatatypeWriter( DatatypeWriter<?> dw ) {
datatypeWriters.put(dw.getType(),dw);
}
/**
* Performs the output as much as possible
*/
void run() {
while(true) {
Content next = current.getNext();
if(next==null || !next.isReadyToCommit())
return;
next.accept(visitor);
next.written();
current = next;
}
}
/**
* Appends the given object to the end of the given buffer.
*
* @param nsResolver
* use
*/
void writeValue( Object obj, NamespaceResolver nsResolver, StringBuilder buf ) {
if(obj==null)
throw new IllegalArgumentException("argument contains null");
if(obj instanceof Object[]) {
for( Object o : (Object[])obj )
writeValue(o,nsResolver,buf);
return;
}
if(obj instanceof Iterable) {
for( Object o : (Iterable<?>)obj )
writeValue(o,nsResolver,buf);
return;
}
if(buf.length()>0)
buf.append(' ');
Class c = obj.getClass();
while(c!=null) {
DatatypeWriter dw = datatypeWriters.get(c);
if(dw!=null) {
dw.print(obj,nsResolver,buf);
return;
}
c = c.getSuperclass();
}
// if nothing applies, just use toString
buf.append(obj);
}
// I wanted to hide those write method from users
private final ContentVisitor visitor = new ContentVisitor() {
public void onStartDocument() {
// the startDocument token is used as the sentry, so this method shall never
// be called.
// out.startDocument() is invoked when we write the start tag of the root element.
throw new IllegalStateException();
}
public void onEndDocument() {
out.endDocument();
}
public void onEndTag() {
out.endTag();
inscopeNamespace.popContext();
activeNamespaces = null;
}
public void onPcdata(StringBuilder buffer) {
if(activeNamespaces!=null)
buffer = fixPrefix(buffer);
out.text(buffer);
}
public void onCdata(StringBuilder buffer) {
if(activeNamespaces!=null)
buffer = fixPrefix(buffer);
out.cdata(buffer);
}
public void onComment(StringBuilder buffer) {
if(activeNamespaces!=null)
buffer = fixPrefix(buffer);
out.comment(buffer);
}
public void onStartTag(String nsUri, String localName, Attribute attributes, NamespaceDecl namespaces) {
assert nsUri!=null;
assert localName!=null;
activeNamespaces = namespaces;
if(!started) {
started = true;
out.startDocument();
}
inscopeNamespace.pushContext();
// declare the explicitly bound namespaces
for( NamespaceDecl ns=namespaces; ns!=null; ns=ns.next ) {
ns.declared = false; // reset this flag
if(ns.prefix!=null) {
String uri = inscopeNamespace.getURI(ns.prefix);
if(uri!=null && uri.equals(ns.uri))
; // already declared
else {
// declare this new binding
inscopeNamespace.declarePrefix(ns.prefix,ns.uri);
ns.declared = true;
}
}
}
// then use in-scope namespace to assign prefixes to others
for( NamespaceDecl ns=namespaces; ns!=null; ns=ns.next ) {
if(ns.prefix==null) {
if(inscopeNamespace.getURI("").equals(ns.uri))
ns.prefix="";
else {
String p = inscopeNamespace.getPrefix(ns.uri);
if(p==null) {
// assign a new one
while(inscopeNamespace.getURI(p=newPrefix())!=null)
;
ns.declared = true;
inscopeNamespace.declarePrefix(p,ns.uri);
}
ns.prefix = p;
}
}
}
// the first namespace decl must be the one for the element
assert namespaces.uri.equals(nsUri);
assert namespaces.prefix!=null : "a prefix must have been all allocated";
out.beginStartTag(nsUri,localName,namespaces.prefix);
// declare namespaces
for( NamespaceDecl ns=namespaces; ns!=null; ns=ns.next ) {
if(ns.declared)
out.writeXmlns( ns.prefix, ns.uri );
}
// writeBody attributes
for( Attribute a=attributes; a!=null; a=a.next) {
String prefix;
if(a.nsUri.length()==0) prefix="";
else prefix=inscopeNamespace.getPrefix(a.nsUri);
out.writeAttribute( a.nsUri, a.localName, prefix, fixPrefix(a.value) );
}
out.endStartTag(nsUri,localName,namespaces.prefix);
}
};
/**
* Used by {@link #newPrefix()}.
*/
private final StringBuilder prefixSeed = new StringBuilder("ns");
private int prefixIota = 0;
/**
* Allocates a new unique prefix.
*/
private String newPrefix() {
prefixSeed.setLength(2);
prefixSeed.append(++prefixIota);
return prefixSeed.toString();
}
/**
* Replaces dummy prefixes in the value to the real ones
* by using {@link #activeNamespaces}.
*
* @return
* the buffer passed as the <tt>buf</tt> parameter.
*/
private StringBuilder fixPrefix(StringBuilder buf) {
assert activeNamespaces!=null;
int i;
int len=buf.length();
for(i=0;i<len;i++)
if( buf.charAt(i)==MAGIC )
break;
// typically it doens't contain any prefix.
// just return the original buffer in that case
if(i==len)
return buf;
while(i<len) {
char uriIdx = buf.charAt(i+1);
NamespaceDecl ns = activeNamespaces;
while(ns!=null && ns.uniqueId!=uriIdx)
ns=ns.next;
if(ns==null)
throw new IllegalStateException("Unexpected use of prefixes "+buf);
int length = 2;
String prefix = ns.prefix;
if(prefix.length()==0) {
if(buf.length()<=i+2 || buf.charAt(i+2)!=':')
throw new IllegalStateException("Unexpected use of prefixes "+buf);
length=3;
}
buf.replace(i,i+length,prefix);
len += prefix.length()-length;
while(i<len && buf.charAt(i)!=MAGIC)
i++;
}
return buf;
}
/**
* The first char of the dummy prefix.
*/
static final char MAGIC = '\u0000';
char assignNewId() {
return (char)iota++;
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* @author Kohsuke Kawaguchi
*/
final class EndDocument extends Content {
boolean concludesPendingStartTag() {
return true;
}
void accept(ContentVisitor visitor) {
visitor.onEndDocument();
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* @author Kohsuke Kawaguchi
*/
final class EndTag extends Content {
boolean concludesPendingStartTag() {
return true;
}
void accept(ContentVisitor visitor) {
visitor.onEndTag();
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* Signals an incorrect use of TXW annotations.
*
* @author Kohsuke Kawaguchi
*/
public class IllegalAnnotationException extends TxwException {
public IllegalAnnotationException(String message) {
super(message);
}
public IllegalAnnotationException(Throwable cause) {
super(cause);
}
public IllegalAnnotationException(String message, Throwable cause) {
super(message, cause);
}
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* Signals incorrect method signatures on {@link TypedXmlWriter}-derived interfaces.
*
* @author Kohsuke Kawaguchi
*/
public class IllegalSignatureException extends TxwException {
public IllegalSignatureException(String message) {
super(message);
}
public IllegalSignatureException(String message, Throwable cause) {
super(message, cause);
}
public IllegalSignatureException(Throwable cause) {
super(cause);
}
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* Namespace declarations.
*
* @author Kohsuke Kawaguchi
*/
final class NamespaceDecl {
final String uri;
boolean requirePrefix;
/**
* Dummy prefix assigned for this namespace decl.
*/
final String dummyPrefix;
final char uniqueId;
/**
* Set to the real prefix once that's computed.
*/
String prefix;
/**
* Used temporarily inside {@link Document#finalizeStartTag()}.
* true if this prefix is declared on the new element.
*/
boolean declared;
/**
* Namespace declarations form a linked list.
*/
NamespaceDecl next;
NamespaceDecl(char uniqueId, String uri, String prefix, boolean requirePrefix ) {
this.dummyPrefix = new StringBuilder(2).append(Document.MAGIC).append(uniqueId).toString();
this.uri = uri;
this.prefix = prefix;
this.requirePrefix = requirePrefix;
this.uniqueId = uniqueId;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* Used by {@link DatatypeWriter} to declare additional namespaces.
*
* @see DatatypeWriter
* @author Kohsuke Kawaguchi
*/
public interface NamespaceResolver {
/**
* Allocates a prefix for the specified URI and returns it.
*
* @param nsUri
* the namespace URI to be declared. Can be empty but must not be null.
* @return
* the empty string if the URI is bound to the default namespace.
* Otherwise a non-empty string that represents a prefix.
*/
String getPrefix(String nsUri);
}

View File

@@ -0,0 +1,845 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// NamespaceSupport.java - generic Namespace support for SAX.
// http://www.saxproject.org
// Written by David Megginson
// This class is in the Public Domain. NO WARRANTY!
package com.sun.xml.internal.txw2;
import java.util.EmptyStackException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
* Encapsulate Namespace logic for use by applications using SAX,
* or internally by SAX drivers.
*
* <blockquote>
* <em>This module, both source code and documentation, is in the
* Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
* See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
* for further information.
* </blockquote>
*
* <p>This class encapsulates the logic of Namespace processing: it
* tracks the declarations currently in force for each context and
* automatically processes qualified XML names into their Namespace
* parts; it can also be used in reverse for generating XML qnames
* from Namespaces.</p>
*
* <p>Namespace support objects are reusable, but the reset method
* must be invoked between each session.</p>
*
* <p>Here is a simple session:</p>
*
* <pre>
* String parts[] = new String[3];
* NamespaceSupport support = new NamespaceSupport();
*
* support.pushContext();
* support.declarePrefix("", "http://www.w3.org/1999/xhtml");
* support.declarePrefix("dc", "http://www.purl.org/dc#");
*
* parts = support.processName("p", parts, false);
* System.out.println("Namespace URI: " + parts[0]);
* System.out.println("Local name: " + parts[1]);
* System.out.println("Raw name: " + parts[2]);
*
* parts = support.processName("dc:title", parts, false);
* System.out.println("Namespace URI: " + parts[0]);
* System.out.println("Local name: " + parts[1]);
* System.out.println("Raw name: " + parts[2]);
*
* support.popContext();
* </pre>
*
* <p>Note that this class is optimized for the use case where most
* elements do not contain Namespace declarations: if the same
* prefix/URI mapping is repeated for each context (for example), this
* class will be somewhat less efficient.</p>
*
* <p>Although SAX drivers (parsers) may choose to use this class to
* implement namespace handling, they are not required to do so.
* Applications must track namespace information themselves if they
* want to use namespace information.
*
* @since SAX 2.0
* @author David Megginson
* @version 2.0.1 (sax2r2)
*/
final class NamespaceSupport
{
////////////////////////////////////////////////////////////////////
// Constants.
////////////////////////////////////////////////////////////////////
/**
* The XML Namespace URI as a constant.
* The value is <code>http://www.w3.org/XML/1998/namespace</code>
* as defined in the "Namespaces in XML" * recommendation.
*
* <p>This is the Namespace URI that is automatically mapped
* to the "xml" prefix.</p>
*/
public final static String XMLNS =
"http://www.w3.org/XML/1998/namespace";
/**
* The namespace declaration URI as a constant.
* The value is <code>http://www.w3.org/xmlns/2000/</code>, as defined
* in a backwards-incompatible erratum to the "Namespaces in XML"
* recommendation. Because that erratum postdated SAX2, SAX2 defaults
* to the original recommendation, and does not normally use this URI.
*
*
* <p>This is the Namespace URI that is optionally applied to
* <em>xmlns</em> and <em>xmlns:*</em> attributes, which are used to
* declare namespaces. </p>
*
* @since SAX 2.1alpha
* @see #setNamespaceDeclUris
* @see #isNamespaceDeclUris
*/
public final static String NSDECL =
"http://www.w3.org/xmlns/2000/";
/**
* An empty enumeration.
*/
private final static Enumeration EMPTY_ENUMERATION =
new Vector().elements();
////////////////////////////////////////////////////////////////////
// Constructor.
////////////////////////////////////////////////////////////////////
/**
* Create a new Namespace support object.
*/
public NamespaceSupport ()
{
reset();
}
////////////////////////////////////////////////////////////////////
// Context management.
////////////////////////////////////////////////////////////////////
/**
* Reset this Namespace support object for reuse.
*
* <p>It is necessary to invoke this method before reusing the
* Namespace support object for a new session. If namespace
* declaration URIs are to be supported, that flag must also
* be set to a non-default value.
* </p>
*
* @see #setNamespaceDeclUris
*/
public void reset ()
{
contexts = new Context[32];
namespaceDeclUris = false;
contextPos = 0;
contexts[contextPos] = currentContext = new Context();
currentContext.declarePrefix("xml", XMLNS);
}
/**
* Start a new Namespace context.
* The new context will automatically inherit
* the declarations of its parent context, but it will also keep
* track of which declarations were made within this context.
*
* <p>Event callback code should start a new context once per element.
* This means being ready to call this in either of two places.
* For elements that don't include namespace declarations, the
* <em>ContentHandler.startElement()</em> callback is the right place.
* For elements with such a declaration, it'd done in the first
* <em>ContentHandler.startPrefixMapping()</em> callback.
* A boolean flag can be used to
* track whether a context has been started yet. When either of
* those methods is called, it checks the flag to see if a new context
* needs to be started. If so, it starts the context and sets the
* flag. After <em>ContentHandler.startElement()</em>
* does that, it always clears the flag.
*
* <p>Normally, SAX drivers would push a new context at the beginning
* of each XML element. Then they perform a first pass over the
* attributes to process all namespace declarations, making
* <em>ContentHandler.startPrefixMapping()</em> callbacks.
* Then a second pass is made, to determine the namespace-qualified
* names for all attributes and for the element name.
* Finally all the information for the
* <em>ContentHandler.startElement()</em> callback is available,
* so it can then be made.
*
* <p>The Namespace support object always starts with a base context
* already in force: in this context, only the "xml" prefix is
* declared.</p>
*
* @see org.xml.sax.ContentHandler
* @see #popContext
*/
public void pushContext ()
{
int max = contexts.length;
contextPos++;
// Extend the array if necessary
if (contextPos >= max) {
Context newContexts[] = new Context[max*2];
System.arraycopy(contexts, 0, newContexts, 0, max);
max *= 2;
contexts = newContexts;
}
// Allocate the context if necessary.
currentContext = contexts[contextPos];
if (currentContext == null) {
contexts[contextPos] = currentContext = new Context();
}
// Set the parent, if any.
if (contextPos > 0) {
currentContext.setParent(contexts[contextPos - 1]);
}
}
/**
* Revert to the previous Namespace context.
*
* <p>Normally, you should pop the context at the end of each
* XML element. After popping the context, all Namespace prefix
* mappings that were previously in force are restored.</p>
*
* <p>You must not attempt to declare additional Namespace
* prefixes after popping a context, unless you push another
* context first.</p>
*
* @see #pushContext
*/
public void popContext ()
{
contexts[contextPos].clear();
contextPos--;
if (contextPos < 0) {
throw new EmptyStackException();
}
currentContext = contexts[contextPos];
}
////////////////////////////////////////////////////////////////////
// Operations within a context.
////////////////////////////////////////////////////////////////////
/**
* Declare a Namespace prefix. All prefixes must be declared
* before they are referenced. For example, a SAX driver (parser)
* would scan an element's attributes
* in two passes: first for namespace declarations,
* then a second pass using {@link #processName processName()} to
* interpret prefixes against (potentially redefined) prefixes.
*
* <p>This method declares a prefix in the current Namespace
* context; the prefix will remain in force until this context
* is popped, unless it is shadowed in a descendant context.</p>
*
* <p>To declare the default element Namespace, use the empty string as
* the prefix.</p>
*
* <p>Note that there is an asymmetry in this library: {@link
* #getPrefix getPrefix} will not return the "" prefix,
* even if you have declared a default element namespace.
* To check for a default namespace,
* you have to look it up explicitly using {@link #getURI getURI}.
* This asymmetry exists to make it easier to look up prefixes
* for attribute names, where the default prefix is not allowed.</p>
*
* @param prefix The prefix to declare, or the empty string to
* indicate the default element namespace. This may never have
* the value "xml" or "xmlns".
* @param uri The Namespace URI to associate with the prefix.
* @return true if the prefix was legal, false otherwise
*
* @see #processName
* @see #getURI
* @see #getPrefix
*/
public boolean declarePrefix (String prefix, String uri)
{
if (prefix.equals("xml") || prefix.equals("xmlns")) {
return false;
} else {
currentContext.declarePrefix(prefix, uri);
return true;
}
}
/**
* Process a raw XML qualified name, after all declarations in the
* current context have been handled by {@link #declarePrefix
* declarePrefix()}.
*
* <p>This method processes a raw XML qualified name in the
* current context by removing the prefix and looking it up among
* the prefixes currently declared. The return value will be the
* array supplied by the caller, filled in as follows:</p>
*
* <dl>
* <dt>parts[0]</dt>
* <dd>The Namespace URI, or an empty string if none is
* in use.</dd>
* <dt>parts[1]</dt>
* <dd>The local name (without prefix).</dd>
* <dt>parts[2]</dt>
* <dd>The original raw name.</dd>
* </dl>
*
* <p>All of the strings in the array will be internalized. If
* the raw name has a prefix that has not been declared, then
* the return value will be null.</p>
*
* <p>Note that attribute names are processed differently than
* element names: an unprefixed element name will receive the
* default Namespace (if any), while an unprefixed attribute name
* will not.</p>
*
* @param qName The XML qualified name to be processed.
* @param parts An array supplied by the caller, capable of
* holding at least three members.
* @param isAttribute A flag indicating whether this is an
* attribute name (true) or an element name (false).
* @return The supplied array holding three internalized strings
* representing the Namespace URI (or empty string), the
* local name, and the XML qualified name; or null if there
* is an undeclared prefix.
* @see #declarePrefix
* @see java.lang.String#intern */
public String [] processName (String qName, String parts[],
boolean isAttribute)
{
String myParts[] = currentContext.processName(qName, isAttribute);
if (myParts == null) {
return null;
} else {
parts[0] = myParts[0];
parts[1] = myParts[1];
parts[2] = myParts[2];
return parts;
}
}
/**
* Look up a prefix and get the currently-mapped Namespace URI.
*
* <p>This method looks up the prefix in the current context.
* Use the empty string ("") for the default Namespace.</p>
*
* @param prefix The prefix to look up.
* @return The associated Namespace URI, or null if the prefix
* is undeclared in this context.
* @see #getPrefix
* @see #getPrefixes
*/
public String getURI (String prefix)
{
return currentContext.getURI(prefix);
}
/**
* Return an enumeration of all prefixes whose declarations are
* active in the current context.
* This includes declarations from parent contexts that have
* not been overridden.
*
* <p><strong>Note:</strong> if there is a default prefix, it will not be
* returned in this enumeration; check for the default prefix
* using the {@link #getURI getURI} with an argument of "".</p>
*
* @return An enumeration of prefixes (never empty).
* @see #getDeclaredPrefixes
* @see #getURI
*/
public Enumeration getPrefixes ()
{
return currentContext.getPrefixes();
}
/**
* Return one of the prefixes mapped to a Namespace URI.
*
* <p>If more than one prefix is currently mapped to the same
* URI, this method will make an arbitrary selection; if you
* want all of the prefixes, use the {@link #getPrefixes}
* method instead.</p>
*
* <p><strong>Note:</strong> this will never return the empty (default) prefix;
* to check for a default prefix, use the {@link #getURI getURI}
* method with an argument of "".</p>
*
* @param uri the namespace URI
* @return one of the prefixes currently mapped to the URI supplied,
* or null if none is mapped or if the URI is assigned to
* the default namespace
* @see #getPrefixes(java.lang.String)
* @see #getURI
*/
public String getPrefix (String uri)
{
return currentContext.getPrefix(uri);
}
/**
* Return an enumeration of all prefixes for a given URI whose
* declarations are active in the current context.
* This includes declarations from parent contexts that have
* not been overridden.
*
* <p>This method returns prefixes mapped to a specific Namespace
* URI. The xml: prefix will be included. If you want only one
* prefix that's mapped to the Namespace URI, and you don't care
* which one you get, use the {@link #getPrefix getPrefix}
* method instead.</p>
*
* <p><strong>Note:</strong> the empty (default) prefix is <em>never</em> included
* in this enumeration; to check for the presence of a default
* Namespace, use the {@link #getURI getURI} method with an
* argument of "".</p>
*
* @param uri The Namespace URI.
* @return An enumeration of prefixes (never empty).
* @see #getPrefix
* @see #getDeclaredPrefixes
* @see #getURI
*/
public Enumeration getPrefixes (String uri)
{
Vector prefixes = new Vector();
Enumeration allPrefixes = getPrefixes();
while (allPrefixes.hasMoreElements()) {
String prefix = (String)allPrefixes.nextElement();
if (uri.equals(getURI(prefix))) {
prefixes.addElement(prefix);
}
}
return prefixes.elements();
}
/**
* Return an enumeration of all prefixes declared in this context.
*
* <p>The empty (default) prefix will be included in this
* enumeration; note that this behaviour differs from that of
* {@link #getPrefix} and {@link #getPrefixes}.</p>
*
* @return An enumeration of all prefixes declared in this
* context.
* @see #getPrefixes
* @see #getURI
*/
public Enumeration getDeclaredPrefixes ()
{
return currentContext.getDeclaredPrefixes();
}
/**
* Controls whether namespace declaration attributes are placed
* into the {@link #NSDECL NSDECL} namespace
* by {@link #processName processName()}. This may only be
* changed before any contexts have been pushed.
*
* @since SAX 2.1alpha
*
* @exception IllegalStateException when attempting to set this
* after any context has been pushed.
*/
public void setNamespaceDeclUris (boolean value)
{
if (contextPos != 0)
throw new IllegalStateException ();
if (value == namespaceDeclUris)
return;
namespaceDeclUris = value;
if (value)
currentContext.declarePrefix ("xmlns", NSDECL);
else {
contexts[contextPos] = currentContext = new Context();
currentContext.declarePrefix("xml", XMLNS);
}
}
/**
* Returns true if namespace declaration attributes are placed into
* a namespace. This behavior is not the default.
*
* @since SAX 2.1alpha
*/
public boolean isNamespaceDeclUris ()
{ return namespaceDeclUris; }
////////////////////////////////////////////////////////////////////
// Internal state.
////////////////////////////////////////////////////////////////////
private Context contexts[];
private Context currentContext;
private int contextPos;
private boolean namespaceDeclUris;
////////////////////////////////////////////////////////////////////
// Internal classes.
////////////////////////////////////////////////////////////////////
/**
* Internal class for a single Namespace context.
*
* <p>This module caches and reuses Namespace contexts,
* so the number allocated
* will be equal to the element depth of the document, not to the total
* number of elements (i.e. 5-10 rather than tens of thousands).
* Also, data structures used to represent contexts are shared when
* possible (child contexts without declarations) to further reduce
* the amount of memory that's consumed.
* </p>
*/
final class Context {
/**
* Create the root-level Namespace context.
*/
Context ()
{
copyTables();
}
/**
* (Re)set the parent of this Namespace context.
* The context must either have been freshly constructed,
* or must have been cleared.
*
* @param context The parent Namespace context object.
*/
void setParent (Context parent)
{
this.parent = parent;
declarations = null;
prefixTable = parent.prefixTable;
uriTable = parent.uriTable;
elementNameTable = parent.elementNameTable;
attributeNameTable = parent.attributeNameTable;
defaultNS = parent.defaultNS;
declSeen = false;
}
/**
* Makes associated state become collectible,
* invalidating this context.
* {@link #setParent} must be called before
* this context may be used again.
*/
void clear ()
{
parent = null;
prefixTable = null;
uriTable = null;
elementNameTable = null;
attributeNameTable = null;
defaultNS = "";
}
/**
* Declare a Namespace prefix for this context.
*
* @param prefix The prefix to declare.
* @param uri The associated Namespace URI.
* @see org.xml.sax.helpers.NamespaceSupport#declarePrefix
*/
void declarePrefix (String prefix, String uri)
{
// Lazy processing...
// if (!declsOK)
// throw new IllegalStateException (
// "can't declare any more prefixes in this context");
if (!declSeen) {
copyTables();
}
if (declarations == null) {
declarations = new Vector();
}
prefix = prefix.intern();
uri = uri.intern();
if ("".equals(prefix)) {
defaultNS = uri;
} else {
prefixTable.put(prefix, uri);
uriTable.put(uri, prefix); // may wipe out another prefix
}
declarations.addElement(prefix);
}
/**
* Process an XML qualified name in this context.
*
* @param qName The XML qualified name.
* @param isAttribute true if this is an attribute name.
* @return An array of three strings containing the
* URI part (or empty string), the local part,
* and the raw name, all internalized, or null
* if there is an undeclared prefix.
* @see org.xml.sax.helpers.NamespaceSupport#processName
*/
String [] processName (String qName, boolean isAttribute)
{
String name[];
Hashtable table;
// Select the appropriate table.
if (isAttribute) {
table = attributeNameTable;
} else {
table = elementNameTable;
}
// Start by looking in the cache, and
// return immediately if the name
// is already known in this content
name = (String[])table.get(qName);
if (name != null) {
return name;
}
// We haven't seen this name in this
// context before. Maybe in the parent
// context, but we can't assume prefix
// bindings are the same.
name = new String[3];
name[2] = qName.intern();
int index = qName.indexOf(':');
// No prefix.
if (index == -1) {
if (isAttribute) {
if (qName == "xmlns" && namespaceDeclUris)
name[0] = NSDECL;
else
name[0] = "";
} else {
name[0] = defaultNS;
}
name[1] = name[2];
}
// Prefix
else {
String prefix = qName.substring(0, index);
String local = qName.substring(index+1);
String uri;
if ("".equals(prefix)) {
uri = defaultNS;
} else {
uri = (String)prefixTable.get(prefix);
}
if (uri == null
|| (!isAttribute && "xmlns".equals (prefix))) {
return null;
}
name[0] = uri;
name[1] = local.intern();
}
// Save in the cache for future use.
// (Could be shared with parent context...)
table.put(name[2], name);
return name;
}
/**
* Look up the URI associated with a prefix in this context.
*
* @param prefix The prefix to look up.
* @return The associated Namespace URI, or null if none is
* declared.
* @see org.xml.sax.helpers.NamespaceSupport#getURI
*/
String getURI (String prefix)
{
if ("".equals(prefix)) {
return defaultNS;
} else if (prefixTable == null) {
return null;
} else {
return (String)prefixTable.get(prefix);
}
}
/**
* Look up one of the prefixes associated with a URI in this context.
*
* <p>Since many prefixes may be mapped to the same URI,
* the return value may be unreliable.</p>
*
* @param uri The URI to look up.
* @return The associated prefix, or null if none is declared.
* @see org.xml.sax.helpers.NamespaceSupport#getPrefix
*/
String getPrefix (String uri) {
if (uriTable != null) {
String uriPrefix = (String)uriTable.get(uri);
if (uriPrefix == null) return null;
String verifyNamespace = (String) prefixTable.get(uriPrefix);
if (uri.equals(verifyNamespace)) {
return uriPrefix;
}
}
return null;
}
/**
* Return an enumeration of prefixes declared in this context.
*
* @return An enumeration of prefixes (possibly empty).
* @see org.xml.sax.helpers.NamespaceSupport#getDeclaredPrefixes
*/
Enumeration getDeclaredPrefixes ()
{
if (declarations == null) {
return EMPTY_ENUMERATION;
} else {
return declarations.elements();
}
}
/**
* Return an enumeration of all prefixes currently in force.
*
* <p>The default prefix, if in force, is <em>not</em>
* returned, and will have to be checked for separately.</p>
*
* @return An enumeration of prefixes (never empty).
* @see org.xml.sax.helpers.NamespaceSupport#getPrefixes
*/
Enumeration getPrefixes ()
{
if (prefixTable == null) {
return EMPTY_ENUMERATION;
} else {
return prefixTable.keys();
}
}
////////////////////////////////////////////////////////////////
// Internal methods.
////////////////////////////////////////////////////////////////
/**
* Copy on write for the internal tables in this context.
*
* <p>This class is optimized for the normal case where most
* elements do not contain Namespace declarations.</p>
*/
private void copyTables ()
{
if (prefixTable != null) {
prefixTable = (Hashtable)prefixTable.clone();
} else {
prefixTable = new Hashtable();
}
if (uriTable != null) {
uriTable = (Hashtable)uriTable.clone();
} else {
uriTable = new Hashtable();
}
elementNameTable = new Hashtable();
attributeNameTable = new Hashtable();
declSeen = true;
}
////////////////////////////////////////////////////////////////
// Protected state.
////////////////////////////////////////////////////////////////
Hashtable prefixTable;
Hashtable uriTable;
Hashtable elementNameTable;
Hashtable attributeNameTable;
String defaultNS = "";
////////////////////////////////////////////////////////////////
// Internal state.
////////////////////////////////////////////////////////////////
private Vector declarations = null;
private boolean declSeen = false;
private Context parent = null;
}
}
// end of NamespaceSupport.java

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* PCDATA.
*
* @author Kohsuke Kawaguchi
*/
final class Pcdata extends Text {
Pcdata(Document document, NamespaceResolver nsResolver, Object obj) {
super(document, nsResolver, obj);
}
void accept(ContentVisitor visitor) {
visitor.onPcdata(buffer);
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* @author Kohsuke Kawaguchi
*/
final class StartDocument extends Content {
boolean concludesPendingStartTag() {
return true;
}
void accept(ContentVisitor visitor) {
visitor.onStartDocument();
}
}

View File

@@ -0,0 +1,248 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
import javax.xml.namespace.QName;
/**
* Start tag.
*
* <p>
* This object implements {@link NamespaceResolver} for attribute values.
*
* @author Kohsuke Kawaguchi
*/
class StartTag extends Content implements NamespaceResolver {
/**
* Tag name of the element.
*
* <p>
* This field is also used as a flag to indicate
* whether the start tag has been written.
* This field is initially set to non-null, and
* then reset to null when it's written.
*/
private String uri;
// but we keep the local name non-null so that
// we can diagnose an error
private final String localName;
private Attribute firstAtt;
private Attribute lastAtt;
/**
* If this {@link StartTag} has the parent {@link ContainerElement},
* that value. Otherwise null.
*/
private ContainerElement owner;
/**
* Explicitly given namespace declarations on this element.
*
* <p>
* Additional namespace declarations might be necessary to
* generate child {@link QName}s and attributes.
*/
private NamespaceDecl firstNs;
private NamespaceDecl lastNs;
final Document document;
public StartTag(ContainerElement owner, String uri, String localName) {
this(owner.document,uri,localName);
this.owner = owner;
}
public StartTag(Document document, String uri, String localName) {
assert uri!=null;
assert localName!=null;
this.uri = uri;
this.localName = localName;
this.document = document;
// TODO: think about a better way to maintain namespace decls.
// this requires at least one NamespaceDecl per start tag,
// which is rather expensive.
addNamespaceDecl(uri,null,false);
}
public void addAttribute(String nsUri, String localName, Object arg) {
checkWritable();
// look for the existing ones
Attribute a;
for(a=firstAtt; a!=null; a=a.next) {
if(a.hasName(nsUri,localName)) {
break;
}
}
// if not found, declare a new one
if(a==null) {
a = new Attribute(nsUri,localName);
if(lastAtt==null) {
assert firstAtt==null;
firstAtt = lastAtt = a;
} else {
assert firstAtt!=null;
lastAtt.next = a;
lastAtt = a;
}
if(nsUri.length()>0)
addNamespaceDecl(nsUri,null,true);
}
document.writeValue(arg,this,a.value);
}
/**
* Declares a new namespace URI on this tag.
*
* @param uri
* namespace URI to be bound. Can be empty, but must not be null.
* @param prefix
* If non-null and non-empty, this prefix is bound to the URI
* on this element. If empty, then the runtime will still try to
* use the URI as the default namespace, but it may fail to do so
* because of the constraints in the XML.
* <p>
* If this parameter is null, the runtime will allocate an unique prefix.
* @param requirePrefix
* Used only when the prefix parameter is null. If true, this indicates
* that the non-empty prefix must be assigned to this URI. If false,
* then this URI might be used as the default namespace.
* <p>
* Normally you just need to set it to false.
*/
public NamespaceDecl addNamespaceDecl(String uri, String prefix,boolean requirePrefix) {
checkWritable();
if(uri==null)
throw new IllegalArgumentException();
if(uri.length()==0) {
if(requirePrefix)
throw new IllegalArgumentException("The empty namespace cannot have a non-empty prefix");
if(prefix!=null && prefix.length()>0)
throw new IllegalArgumentException("The empty namespace can be only bound to the empty prefix");
prefix = "";
}
// check for the duplicate
for(NamespaceDecl n=firstNs; n!=null; n=n.next) {
if(uri.equals(n.uri)) {
if(prefix==null) {
// reuse this binding
n.requirePrefix |= requirePrefix;
return n;
}
if(n.prefix==null) {
// reuse this binding
n.prefix = prefix;
n.requirePrefix |= requirePrefix;
return n;
}
if(prefix.equals(n.prefix)) {
// reuse this binding
n.requirePrefix |= requirePrefix;
return n;
}
}
if(prefix!=null && n.prefix!=null && n.prefix.equals(prefix))
throw new IllegalArgumentException(
"Prefix '"+prefix+"' is already bound to '"+n.uri+'\'');
}
NamespaceDecl ns = new NamespaceDecl(document.assignNewId(),uri,prefix,requirePrefix);
if(lastNs==null) {
assert firstNs==null;
firstNs = lastNs = ns;
} else {
assert firstNs!=null;
lastNs.next = ns;
lastNs = ns;
}
return ns;
}
/**
* Throws an error if the start tag has already been committed.
*/
private void checkWritable() {
if(isWritten())
throw new IllegalStateException(
"The start tag of "+this.localName+" has already been written. " +
"If you need out of order writing, see the TypedXmlWriter.block method");
}
/**
* Returns true if this start tag has already been written.
*/
boolean isWritten() {
return uri==null;
}
/**
* A {@link StartTag} can be only written after
* we are sure that all the necessary namespace declarations are given.
*/
boolean isReadyToCommit() {
if(owner!=null && owner.isBlocked())
return false;
for( Content c=getNext(); c!=null; c=c.getNext() )
if(c.concludesPendingStartTag())
return true;
return false;
}
public void written() {
firstAtt = lastAtt = null;
uri = null;
if(owner!=null) {
assert owner.startTag==this;
owner.startTag = null;
}
}
boolean concludesPendingStartTag() {
return true;
}
void accept(ContentVisitor visitor) {
visitor.onStartTag(uri,localName,firstAtt,firstNs);
}
public String getPrefix(String nsUri) {
NamespaceDecl ns = addNamespaceDecl(nsUri,null,false);
if(ns.prefix!=null)
// if the prefix has already been declared, use it.
return ns.prefix;
return ns.dummyPrefix;
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
import com.sun.xml.internal.txw2.output.XmlSerializer;
import com.sun.xml.internal.txw2.output.TXWSerializer;
import com.sun.xml.internal.txw2.annotation.XmlElement;
import com.sun.xml.internal.txw2.annotation.XmlNamespace;
import javax.xml.namespace.QName;
/**
* Entry point to TXW.
*
* @author Kohsuke Kawaguchi
*/
public abstract class TXW {
private TXW() {} // no instanciation please
/*package*/ static QName getTagName( Class<?> c ) {
String localName="";
String nsUri="##default";
XmlElement xe = c.getAnnotation(XmlElement.class);
if(xe!=null) {
localName = xe.value();
nsUri = xe.ns();
}
if(localName.length()==0) {
localName = c.getName();
int idx = localName.lastIndexOf('.');
if(idx>=0)
localName = localName.substring(idx+1);
localName = Character.toLowerCase(localName.charAt(0))+localName.substring(1);
}
if(nsUri.equals("##default")) {
Package pkg = c.getPackage();
if(pkg!=null) {
XmlNamespace xn = pkg.getAnnotation(XmlNamespace.class);
if(xn!=null)
nsUri = xn.value();
}
}
if(nsUri.equals("##default"))
nsUri = "";
return new QName(nsUri,localName);
}
/**
* Creates a new {@link TypedXmlWriter} to write a new instance of a document.
*
* @param rootElement
* The {@link TypedXmlWriter} interface that declares the content model of the root element.
* This interface must have {@link XmlElement} annotation on it to designate the tag name
* of the root element.
* @param out
* The target of the writing.
*/
public static <T extends TypedXmlWriter> T create( Class<T> rootElement, XmlSerializer out ) {
if (out instanceof TXWSerializer) {
TXWSerializer txws = (TXWSerializer) out;
return txws.txw._element(rootElement);
}
Document doc = new Document(out);
QName n = getTagName(rootElement);
return new ContainerElement(doc,null,n.getNamespaceURI(),n.getLocalPart())._cast(rootElement);
}
/**
* Creates a new {@link TypedXmlWriter} to write a new instance of a document.
*
* <p>
* Similar to the other method, but this version allows the caller to set the
* tag name at the run-time.
*
* @param tagName
* The tag name of the root document.
*
* @see #create(Class,XmlSerializer)
*/
public static <T extends TypedXmlWriter> T create( QName tagName, Class<T> rootElement, XmlSerializer out ) {
if (out instanceof TXWSerializer) {
TXWSerializer txws = (TXWSerializer) out;
return txws.txw._element(tagName,rootElement);
}
return new ContainerElement(new Document(out),null,tagName.getNamespaceURI(),tagName.getLocalPart())._cast(rootElement);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* {@link Pcdata} or {@link Cdata}.
*
* @author Kohsuke Kawaguchi
*/
abstract class Text extends Content {
/**
* The text to be writtten.
*/
protected final StringBuilder buffer = new StringBuilder();
protected Text(Document document, NamespaceResolver nsResolver, Object obj) {
document.writeValue(obj,nsResolver,buffer);
}
boolean concludesPendingStartTag() {
return false;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
/**
* Signals errors in the TXW processing.
*/
public class TxwException extends RuntimeException {
public TxwException(String message) {
super(message);
}
public TxwException(Throwable cause) {
super(cause);
}
public TxwException(String message, Throwable cause) {
super(message, cause);
}
private static final long serialVersionUID = 1L;
}

View File

@@ -0,0 +1,266 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2;
import com.sun.xml.internal.txw2.annotation.XmlElement;
import com.sun.xml.internal.txw2.output.XmlSerializer;
import javax.xml.namespace.QName;
/**
* Defines common operations for all typed XML writers&#x2E;
* Root of all typed XML writer interfaces.
*
* <p>
* This interface defines a series of methods to allow client applications
* to write arbitrary well-formed documents.
*
* @author Kohsuke Kawaguchi
*/
public interface TypedXmlWriter {
/**
* Commits this element (and all its descendants) to the output.
*
* <p>
* Short for <tt>_commit(true)</tt>.
*/
void commit();
/**
* Commits this element (and all its descendants) to the output.
*
* <p>
* Once a writer is committed, nothing can be added to it further.
* Committing allows TXW to output a part of the document even
* if the rest has not yet been written.
*
* @param includingAllPredecessors
* if false, this operation will _commit this writer and all its
* descendants writers. If true, in addition to those writers,
* this operation will close all the writers before this writer
* in the document order.
*/
void commit(boolean includingAllPredecessors);
/**
* Blocks the writing of the start tag so that
* new attributes can be added even after child
* elements are appended.
*
* <p>
* This blocks the output at the token before the start tag until
* the {@link #commit()} method is called to _commit this element.
*
* <p>
* For more information, see the TXW documentation.
*/
void block();
/**
* Gets the {@link Document} object that this writer is writing to.
*
* @return
* always non-null.
*/
Document getDocument();
/**
* Adds an attribute of the given name and the value.
*
* <p>
* Short for <pre>_attribute("",localName,value);</pre>
*
* @see #_attribute(String, String, Object)
*/
void _attribute( String localName, Object value );
/**
* Adds an attribute of the given name and the value.
*
* <p>
* Short for <pre>_attribute(new QName(nsUri,localName),value);</pre>
*
* @see #_attribute(QName, Object)
*/
void _attribute( String nsUri, String localName, Object value );
/**
* Adds an attribute of the given name and the value.
*
* @param attributeName
* must not be null.
* @param value
* value of the attribute.
* must not be null.
* See the documentation for the conversion rules.
*/
void _attribute( QName attributeName, Object value );
/**
* Declares a new namespace URI on this element.
*
* <p>
* The runtime system will assign an unique prefix for the URI.
*
* @param uri
* can be empty, but must not be null.
*/
void _namespace( String uri );
/**
* Declares a new namespace URI on this element to
* a specific prefix.
*
* @param uri
* can be empty, but must not be null.
* @param prefix
* If non-empty, this prefix is bound to the URI
* on this element. If empty, then the runtime will still try to
* use the URI as the default namespace, but it may fail to do so
* because of the constraints in the XML.
*
* @throws IllegalArgumentException
* if the same prefix is already declared on this element.
*/
void _namespace( String uri, String prefix );
/**
* Declares a new namespace URI on this element.
*
* <p>
* The runtime system will assign an unique prefix for the URI.
*
* @param uri
* can be empty, but must not be null.
* @param requirePrefix
* if false, this method behaves just like {@link #_namespace(String)}.
* if true, this guarantees that the URI is bound to a non empty prefix.
*/
void _namespace( String uri, boolean requirePrefix );
/**
* Appends text data.
*
* @param value
* must not be null.
* See the documentation for the conversion rules.
*/
void _pcdata( Object value );
/**
* Appends CDATA section.
*
* @param value
* must not be null.
* See the documentation for the conversion rules.
*/
void _cdata( Object value );
/**
* Appends a comment.
*
* @param value
* must not be null.
* See the documentation for the conversion rules.
*
* @throws UnsupportedOperationException
* if the underlying {@link XmlSerializer} does not support
* writing comments, this exception can be thrown.
*/
void _comment( Object value ) throws UnsupportedOperationException;
/**
* Appends a new child element.
*
* <p>
* Short for <pre>_element(<i>URI of this element</i>,localName,contentModel);</pre>
*
* <p>
* The namespace URI will be inherited from the parent element.
*
* @see #_element(String, String, Class)
*/
<T extends TypedXmlWriter> T _element( String localName, Class<T> contentModel );
/**
* Appends a new child element.
*
* <p>
* The newly created child element is appended at the end of the children.
*
* @param nsUri
* The namespace URI of the newly created element.
* @param localName
* The local name of the newly created element.
* @param contentModel
* The typed XML writer interface used to write the children of
* the new child element.
*
* @return
* always return non-null {@link TypedXmlWriter} that can be used
* to write the contents of the newly created child element.
*/
<T extends TypedXmlWriter> T _element( String nsUri, String localName, Class<T> contentModel );
/**
* Appends a new child element.
*
* <p>
* Short for <pre>_element(tagName.getNamespaceURI(),tagName.getLocalPart(),contentModel);</pre>
*
* @see #_element(String, String, Class)
*/
<T extends TypedXmlWriter> T _element( QName tagName, Class<T> contentModel );
/**
* Appends a new child element.
*
* <p>
* This version of the _element method requires the <i>T</i> class to be
* annotated with {@link XmlElement} annotation. The element name will be
* taken from there.
*
* @see #_element(String, String, Class)
*/
<T extends TypedXmlWriter> T _element( Class<T> contentModel );
/**
* Returns a different interface for this typed XML Writer.
*
* <p>
* Semantically, this operation is a 'cast' --- it returns the same underlying
* writer in a different interface. The returned new writer and the current writer
* will write to the same element.
*
* <p>
* But this is different from Java's ordinary cast because the returned object
* is not always the same as the current object.
*
* @return
* always return non-null.
*/
<T extends TypedXmlWriter> T _cast( Class<T> targetInterface );
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.annotation;
import com.sun.xml.internal.txw2.TypedXmlWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies that the invocation of the method will produce an attribute.
*
* <p>
* The method signature has to match the form <tt>R foo(DT1,DT2,..)</tt>
*
* <p>
* R is either <tt>void</tt> or the type to which the interface that declares
* this method is assignable. In the case of the latter, the method will return
* <tt>this</tt> object, allowing you to chain the multiple attribute method
* invocations like {@link StringBuffer}.
*
* <p>
* DTi must be datatype objects.
*
* <p>
* When this method is called, a new attribute is added to the current element,
* whose value is whitespace-separated text from each of the datatype objects.
*
* @author Kohsuke Kawaguchi
*/
@Retention(RUNTIME)
@Target({METHOD})
public @interface XmlAttribute {
/**
* The local name of the attribute.
*
* <p>
* If left unspecified, the method name is used as the attribute name.
*
*/
String value() default "";
/**
* The namespace URI of the attribute.
*/
String ns() default "";
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.METHOD;
/**
* Used along with {@link XmlElement} to write a CDATA section,
* instead of the normal PCDATA.
*
* @author Kohsuke Kawaguchi
*/
@Retention(RUNTIME)
@Target({METHOD})
public @interface XmlCDATA {
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.annotation;
import com.sun.xml.internal.txw2.TypedXmlWriter;
import com.sun.xml.internal.txw2.TXW;
import com.sun.xml.internal.txw2.output.XmlSerializer;
import javax.xml.namespace.QName;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.METHOD;
/**
* Specifies the name of the XML element.
*
* <h2>Used on method</h2>
* <p>
* When used on methods declared on interfaces that derive
* from {@link TypedXmlWriter}, it specifies that the invocation
* of the method will produce an element of the specified name.
*
* <p>
* The method signature has to match one of the following patterns.
*
* <dl>
* <dt>Child writer: <tt>TW foo()</tt></dt>
* <dd>TW must be an interface derived from {@link TypedXmlWriter}.
* When this method is called, a new child element is started,
* and its content can be written by using the returned <tt>TW</tt>
* object. This child element will be ended when its _commit method
* is called.
* <dt>Leaf element: <tt>void foo(DT1,DT2,...)</tt></dt>
* <dd>DTi must be datatype objects.
* When this method is called, a new child element is started,
* followed by the whitespace-separated text data from each of
* the datatype objects, followed by the end tag.
* </dl>
*
* <h2>Used on interface</h2>
* <p>
* When used on interfaces that derive from {@link TypedXmlWriter},
* it associates an element name with that interface. This name is
* used in a few places, such as in {@link TXW#create(Class,XmlSerializer)}
* and {@link TypedXmlWriter#_element(Class)}.
*
*
* @author Kohsuke Kawaguchi
*/
@Retention(RUNTIME)
@Target({METHOD,TYPE})
public @interface XmlElement {
/**
* The local name of the element.
*/
String value() default "";
/**
* The namespace URI of this element.
*
* <p>
* If the annotation is on an interface and this paramter is left unspecified,
* then the namespace URI is taken from {@link XmlNamespace} annotation on
* the package that the interface is in. If {@link XmlNamespace} annotation
* doesn't exist, the namespace URI will be "".
*
* <p>
* If the annotation is on a method and this parameter is left unspecified,
* then the namespace URI is the same as the namespace URI of the writer interface.
*/
String ns() default "##default";
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PACKAGE;
import com.sun.xml.internal.txw2.TypedXmlWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Declares the namespace URI of the {@link TypedXmlWriter}s
* in a package.
*
* <p>
* This annotation is placed on a package. When specified,
* it sets the default value of the namespace URI for
* all the elements ({@link XmlElement}s) in the given package.
*
* @author Kohsuke Kawaguchi
*/
@Retention(RUNTIME)
@Target({PACKAGE})
public @interface XmlNamespace {
/**
* The namespace URI.
*/
String value();
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.annotation;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.METHOD;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* Specifies that the invocation of the method will produce a text
*
* <p>
* The method signature has to match the form <tt>R foo(DT1,DT2,..)</tt>
*
* <p>
* R is either <tt>void</tt> or the type to which the interface that declares
* this method is assignable. In the case of the latter, the method will return
* <tt>this</tt> object, allowing you to chain the multiple method
* invocations like {@link StringBuffer}.
*
* <p>
* DTi must be datatype objects.
*
* <p>
* When this method is called, whitespace-separated text data
* is added from each of the datatype objects.
*
* @author Kohsuke Kawaguchi
*/
@Retention(RUNTIME)
@Target({METHOD})
public @interface XmlValue {
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import java.io.IOException;
import java.io.Writer;
/**
* Performs character escaping and write the result
* to the output.
*
* @since 1.0.1
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public interface CharacterEscapeHandler {
/**
* @param ch The array of characters.
* @param start The starting position.
* @param length The number of characters to use.
* @param isAttVal true if this is an attribute value literal.
*/
void escape( char ch[], int start, int length, boolean isAttVal, Writer out ) throws IOException;
}

View File

@@ -0,0 +1,374 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
//@@3RD PARTY CODE@@
// DataWriter.java - XML writer for data-oriented files.
package com.sun.xml.internal.txw2.output;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import java.io.Writer;
import java.util.Stack;
/**
* Write data- or field-oriented XML.
*
* <p>This filter pretty-prints field-oriented XML without mixed content.
* all added indentation and newlines will be passed on down
* the filter chain (if any).</p>
*
* <p>In general, all whitespace in an XML document is potentially
* significant, so a general-purpose XML writing tool like the
* {@link XMLWriter} class cannot
* add newlines or indentation.</p>
*
* <p>There is, however, a large class of XML documents where information
* is strictly fielded: each element contains either character data
* or other elements, but not both. For this special case, it is possible
* for a writing tool to provide automatic indentation and newlines
* without requiring extra work from the user. Note that this class
* will likely not yield appropriate results for document-oriented
* XML like XHTML pages, which mix character data and elements together.</p>
*
* <p>This writer will automatically place each start tag on a new line,
* optionally indented if an indent step is provided (by default, there
* is no indentation). If an element contains other elements, the end
* tag will also appear on a new line with leading indentation. Consider,
* for example, the following code:</p>
*
* <pre>
* DataWriter w = new DataWriter();
*
* w.setIndentStep(2);
* w.startDocument();
* w.startElement("Person");
* w.dataElement("name", "Jane Smith");
* w.dataElement("date-of-birth", "1965-05-23");
* w.dataElement("citizenship", "US");
* w.endElement("Person");
* w.endDocument();
* </pre>
*
* <p>This code will produce the following document:</p>
*
* <pre>
* &lt;?xml version="1.0" standalone="yes"?>
*
* &lt;Person>
* &lt;name>Jane Smith&lt;/name>
* &lt;date-of-birth>1965-05-23&lt;/date-of-birth>
* &lt;citizenship>US&lt;/citizenship>
* &lt;/Person>
* </pre>
*
* <p>This class inherits from {@link XMLWriter},
* and provides all of the same support for Namespaces.</p>
*
* @since 1.0
* @author David Megginson, david@megginson.com
* @version 0.2
* @see XMLWriter
*/
public class DataWriter extends XMLWriter
{
////////////////////////////////////////////////////////////////////
// Constructors.
////////////////////////////////////////////////////////////////////
/**
* Create a new data writer for the specified output.
*
* @param writer The character stream where the XML document
* will be written.
* @param encoding
* If non-null string is specified, it is written as a part
* of the XML declaration.
*/
public DataWriter ( Writer writer, String encoding, CharacterEscapeHandler _escapeHandler )
{
super(writer,encoding,_escapeHandler);
}
public DataWriter (Writer writer, String encoding ) {
this( writer, encoding, DumbEscapeHandler.theInstance );
}
public DataWriter (Writer writer) {
this( writer, null, DumbEscapeHandler.theInstance );
}
////////////////////////////////////////////////////////////////////
// Accessors and setters.
////////////////////////////////////////////////////////////////////
/**
* Return the current indent step.
*
* <p>Return the current indent step: each start tag will be
* indented by this number of spaces times the number of
* ancestors that the element has.</p>
*
* @return The number of spaces in each indentation step,
* or 0 or less for no indentation.
* @see #setIndentStep(int)
*
* @deprecated
* Only return the length of the indent string.
*/
public int getIndentStep ()
{
return indentStep.length();
}
/**
* Set the current indent step.
*
* @param indentStep The new indent step (0 or less for no
* indentation).
* @see #getIndentStep()
*
* @deprecated
* Should use the version that takes string.
*/
public void setIndentStep (int indentStep)
{
StringBuilder s = new StringBuilder();
for( ; indentStep>0; indentStep-- ) s.append(' ');
setIndentStep(s.toString());
}
public void setIndentStep(String s) {
this.indentStep = s;
}
////////////////////////////////////////////////////////////////////
// Override methods from XMLWriter.
////////////////////////////////////////////////////////////////////
/**
* Reset the writer so that it can be reused.
*
* <p>This method is especially useful if the writer failed
* with an exception the last time through.</p>
*
* @see XMLWriter#reset()
*/
public void reset ()
{
depth = 0;
state = SEEN_NOTHING;
stateStack = new Stack();
super.reset();
}
/**
* Write a start tag.
*
* <p>Each tag will begin on a new line, and will be
* indented by the current indent step times the number
* of ancestors that the element has.</p>
*
* <p>The newline and indentation will be passed on down
* the filter chain through regular characters events.</p>
*
* @param uri The element's Namespace URI.
* @param localName The element's local name.
* @param qName The element's qualified (prefixed) name.
* @param atts The element's attribute list.
* @exception org.xml.sax.SAXException If there is an error
* writing the start tag, or if a filter further
* down the chain raises an exception.
* @see XMLWriter#startElement(String, String, String, Attributes)
*/
public void startElement (String uri, String localName,
String qName, Attributes atts)
throws SAXException
{
stateStack.push(SEEN_ELEMENT);
state = SEEN_NOTHING;
if (depth > 0) {
super.characters("\n");
}
doIndent();
super.startElement(uri, localName, qName, atts);
depth++;
}
/**
* Write an end tag.
*
* <p>If the element has contained other elements, the tag
* will appear indented on a new line; otherwise, it will
* appear immediately following whatever came before.</p>
*
* <p>The newline and indentation will be passed on down
* the filter chain through regular characters events.</p>
*
* @param uri The element's Namespace URI.
* @param localName The element's local name.
* @param qName The element's qualified (prefixed) name.
* @exception org.xml.sax.SAXException If there is an error
* writing the end tag, or if a filter further
* down the chain raises an exception.
* @see XMLWriter#endElement(String, String, String)
*/
public void endElement (String uri, String localName, String qName)
throws SAXException
{
depth--;
if (state == SEEN_ELEMENT) {
super.characters("\n");
doIndent();
}
super.endElement(uri, localName, qName);
state = stateStack.pop();
}
// /**
// * Write a empty element tag.
// *
// * <p>Each tag will appear on a new line, and will be
// * indented by the current indent step times the number
// * of ancestors that the element has.</p>
// *
// * <p>The newline and indentation will be passed on down
// * the filter chain through regular characters events.</p>
// *
// * @param uri The element's Namespace URI.
// * @param localName The element's local name.
// * @param qName The element's qualified (prefixed) name.
// * @param atts The element's attribute list.
// * @exception org.xml.sax.SAXException If there is an error
// * writing the empty tag, or if a filter further
// * down the chain raises an exception.
// * @see XMLWriter#emptyElement(String, String, String, Attributes)
// */
// public void emptyElement (String uri, String localName,
// String qName, Attributes atts)
// throws SAXException
// {
// state = SEEN_ELEMENT;
// if (depth > 0) {
// super.characters("\n");
// }
// doIndent();
// super.emptyElement(uri, localName, qName, atts);
// }
/**
* Write a sequence of characters.
*
* @param ch The characters to write.
* @param start The starting position in the array.
* @param length The number of characters to use.
* @exception org.xml.sax.SAXException If there is an error
* writing the characters, or if a filter further
* down the chain raises an exception.
* @see XMLWriter#characters(char[], int, int)
*/
public void characters (char ch[], int start, int length)
throws SAXException
{
state = SEEN_DATA;
super.characters(ch, start, length);
}
public void comment(char ch[], int start, int length) throws SAXException {
if (depth > 0) {
super.characters("\n");
}
doIndent();
super.comment(ch,start,length);
}
////////////////////////////////////////////////////////////////////
// Internal methods.
////////////////////////////////////////////////////////////////////
/**
* Print indentation for the current level.
*
* @exception org.xml.sax.SAXException If there is an error
* writing the indentation characters, or if a filter
* further down the chain raises an exception.
*/
private void doIndent ()
throws SAXException
{
if (depth > 0) {
char[] ch = indentStep.toCharArray();
for( int i=0; i<depth; i++ )
characters(ch, 0, ch.length);
}
}
////////////////////////////////////////////////////////////////////
// Constants.
////////////////////////////////////////////////////////////////////
private final static Object SEEN_NOTHING = new Object();
private final static Object SEEN_ELEMENT = new Object();
private final static Object SEEN_DATA = new Object();
////////////////////////////////////////////////////////////////////
// Internal state.
////////////////////////////////////////////////////////////////////
private Object state = SEEN_NOTHING;
private Stack stateStack = new Stack();
private String indentStep = "";
private int depth = 0;
}
// end of DataWriter.java

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.namespace.NamespaceContext;
/**
* Delegating {@link XMLStreamWriter}.
*
* @author Kohsuke Kawaguchi
*/
abstract class DelegatingXMLStreamWriter implements XMLStreamWriter {
private final XMLStreamWriter writer;
public DelegatingXMLStreamWriter(XMLStreamWriter writer) {
this.writer = writer;
}
public void writeStartElement(String localName) throws XMLStreamException {
writer.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
writer.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
writer.writeStartElement(prefix, localName, namespaceURI);
}
public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
writer.writeEmptyElement(namespaceURI, localName);
}
public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
writer.writeEmptyElement(prefix, localName, namespaceURI);
}
public void writeEmptyElement(String localName) throws XMLStreamException {
writer.writeEmptyElement(localName);
}
public void writeEndElement() throws XMLStreamException {
writer.writeEndElement();
}
public void writeEndDocument() throws XMLStreamException {
writer.writeEndDocument();
}
public void close() throws XMLStreamException {
writer.close();
}
public void flush() throws XMLStreamException {
writer.flush();
}
public void writeAttribute(String localName, String value) throws XMLStreamException {
writer.writeAttribute(localName, value);
}
public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
writer.writeAttribute(prefix, namespaceURI, localName, value);
}
public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
writer.writeAttribute(namespaceURI, localName, value);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
writer.writeNamespace(prefix, namespaceURI);
}
public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
writer.writeDefaultNamespace(namespaceURI);
}
public void writeComment(String data) throws XMLStreamException {
writer.writeComment(data);
}
public void writeProcessingInstruction(String target) throws XMLStreamException {
writer.writeProcessingInstruction(target);
}
public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
writer.writeProcessingInstruction(target, data);
}
public void writeCData(String data) throws XMLStreamException {
writer.writeCData(data);
}
public void writeDTD(String dtd) throws XMLStreamException {
writer.writeDTD(dtd);
}
public void writeEntityRef(String name) throws XMLStreamException {
writer.writeEntityRef(name);
}
public void writeStartDocument() throws XMLStreamException {
writer.writeStartDocument();
}
public void writeStartDocument(String version) throws XMLStreamException {
writer.writeStartDocument(version);
}
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
writer.writeStartDocument(encoding, version);
}
public void writeCharacters(String text) throws XMLStreamException {
writer.writeCharacters(text);
}
public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
writer.writeCharacters(text, start, len);
}
public String getPrefix(String uri) throws XMLStreamException {
return writer.getPrefix(uri);
}
public void setPrefix(String prefix, String uri) throws XMLStreamException {
writer.setPrefix(prefix, uri);
}
public void setDefaultNamespace(String uri) throws XMLStreamException {
writer.setDefaultNamespace(uri);
}
public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
writer.setNamespaceContext(context);
}
public NamespaceContext getNamespaceContext() {
return writer.getNamespaceContext();
}
public Object getProperty(String name) throws IllegalArgumentException {
return writer.getProperty(name);
}
}

View File

@@ -0,0 +1,311 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMResult;
import java.util.ArrayList;
import java.util.Stack;
import com.sun.xml.internal.txw2.TxwException;
/**
* {@link XmlSerializer} for {@link javax.xml.transform.dom.DOMResult} and {@link org.w3c.dom.Node}.
*
* @author Ryan.Shoemaker@Sun.COM
*/
public class DomSerializer implements XmlSerializer {
// delegate to SaxSerializer
private final SaxSerializer serializer;
public DomSerializer(Node node) {
Dom2SaxAdapter adapter = new Dom2SaxAdapter(node);
serializer = new SaxSerializer(adapter,adapter,false);
}
public DomSerializer(DOMResult domResult) {
Node node = domResult.getNode();
if (node == null) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
domResult.setNode(doc);
serializer = new SaxSerializer(new Dom2SaxAdapter(doc),null,false);
} catch (ParserConfigurationException pce) {
throw new TxwException(pce);
}
} else {
serializer = new SaxSerializer(new Dom2SaxAdapter(node),null,false);
}
}
// XmlSerializer api's - delegate to SaxSerializer
public void startDocument() {
serializer.startDocument();
}
public void beginStartTag(String uri, String localName, String prefix) {
serializer.beginStartTag(uri, localName, prefix);
}
public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) {
serializer.writeAttribute(uri, localName, prefix, value);
}
public void writeXmlns(String prefix, String uri) {
serializer.writeXmlns(prefix, uri);
}
public void endStartTag(String uri, String localName, String prefix) {
serializer.endStartTag(uri, localName, prefix);
}
public void endTag() {
serializer.endTag();
}
public void text(StringBuilder text) {
serializer.text(text);
}
public void cdata(StringBuilder text) {
serializer.cdata(text);
}
public void comment(StringBuilder comment) {
serializer.comment(comment);
}
public void endDocument() {
serializer.endDocument();
}
public void flush() {
// no flushing
}
}
/**
* Builds a DOM tree from SAX2 events.
*
* @author Vivek Pandey
*/
class Dom2SaxAdapter implements ContentHandler, LexicalHandler {
private final Node _node;
private final Stack _nodeStk = new Stack();
private boolean inCDATA;
public final Element getCurrentElement() {
return (Element) _nodeStk.peek();
}
/**
* Document object that owns the specified node.
*/
private final Document _document;
/**
* @param node
* Nodes will be created and added under this object.
*/
public Dom2SaxAdapter(Node node)
{
_node = node;
_nodeStk.push(_node);
if( node instanceof Document )
this._document = (Document)node;
else
this._document = node.getOwnerDocument();
}
/**
* Creates a fresh empty DOM document and adds nodes under this document.
*/
public Dom2SaxAdapter() throws ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
_document = factory.newDocumentBuilder().newDocument();
_node = _document;
_nodeStk.push( _document );
}
public Node getDOM() {
return _node;
}
public void startDocument() {
}
public void endDocument(){
}
public void startElement(String namespace, String localName, String qName, Attributes attrs){
// some broken DOM implementatino (we confirmed it with SAXON)
// return null from this method.
Element element = _document.createElementNS(namespace, qName);
if( element==null ) {
// if so, report an user-friendly error message,
// rather than dying mysteriously with NPE.
throw new TxwException("Your DOM provider doesn't support the createElementNS method properly");
}
// process namespace bindings
for( int i=0; i<unprocessedNamespaces.size(); i+=2 ) {
String prefix = (String)unprocessedNamespaces.get(i+0);
String uri = (String)unprocessedNamespaces.get(i+1);
String qname;
if( "".equals(prefix) || prefix==null )
qname = "xmlns";
else
qname = "xmlns:"+prefix;
// older version of Xerces (I confirmed that the bug is gone with Xerces 2.4.0)
// have a problem of re-setting the same namespace attribute twice.
// work around this bug removing it first.
if( element.hasAttributeNS("http://www.w3.org/2000/xmlns/",qname) ) {
// further workaround for an old Crimson bug where the removeAttribtueNS
// method throws NPE when the element doesn't have any attribute.
// to be on the safe side, check the existence of attributes before
// attempting to remove it.
// for details about this bug, see org.apache.crimson.tree.ElementNode2
// line 540 or the following message:
// https://jaxb.dev.java.net/servlets/ReadMsg?list=users&msgNo=2767
element.removeAttributeNS("http://www.w3.org/2000/xmlns/",qname);
}
// workaround until here
element.setAttributeNS("http://www.w3.org/2000/xmlns/",qname, uri);
}
unprocessedNamespaces.clear();
int length = attrs.getLength();
for(int i=0;i<length;i++){
String namespaceuri = attrs.getURI(i);
String value = attrs.getValue(i);
String qname = attrs.getQName(i);
element.setAttributeNS(namespaceuri, qname, value);
}
// append this new node onto current stack node
getParent().appendChild(element);
// push this node onto stack
_nodeStk.push(element);
}
private final Node getParent() {
return (Node) _nodeStk.peek();
}
public void endElement(String namespace, String localName, String qName){
_nodeStk.pop();
}
public void characters(char[] ch, int start, int length) {
Node text;
if(inCDATA)
text = _document.createCDATASection(new String(ch, start, length));
else
text = _document.createTextNode(new String(ch, start, length));
getParent().appendChild(text);
}
public void comment(char ch[], int start, int length) throws SAXException {
getParent().appendChild(_document.createComment(new String(ch,start,length)));
}
public void ignorableWhitespace(char[] ch, int start, int length) {
}
public void processingInstruction(String target, String data) throws org.xml.sax.SAXException{
Node node = _document.createProcessingInstruction(target, data);
getParent().appendChild(node);
}
public void setDocumentLocator(Locator locator) {
}
public void skippedEntity(String name) {
}
private ArrayList unprocessedNamespaces = new ArrayList();
public void startPrefixMapping(String prefix, String uri) {
unprocessedNamespaces.add(prefix);
unprocessedNamespaces.add(uri);
}
public void endPrefixMapping(String prefix) {
}
public void startDTD(String name, String publicId, String systemId) throws SAXException {
}
public void endDTD() throws SAXException {
}
public void startEntity(String name) throws SAXException {
}
public void endEntity(String name) throws SAXException {
}
public void startCDATA() throws SAXException {
inCDATA = true;
}
public void endCDATA() throws SAXException {
inCDATA = false;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import java.io.IOException;
import java.io.Writer;
/**
* Escape everything above the US-ASCII code range.
* A fallback position.
*
* Works with any JDK, any encoding.
*
* @since 1.0.1
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class DumbEscapeHandler implements CharacterEscapeHandler {
private DumbEscapeHandler() {} // no instanciation please
public static final CharacterEscapeHandler theInstance = new DumbEscapeHandler();
public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException {
int limit = start+length;
for (int i = start; i < limit; i++) {
switch (ch[i]) {
case '&':
out.write("&amp;");
break;
case '<':
out.write("&lt;");
break;
case '>':
out.write("&gt;");
break;
case '\"':
if (isAttVal) {
out.write("&quot;");
} else {
out.write('\"');
}
break;
default:
if (ch[i] > '\u007f') {
out.write("&#");
out.write(Integer.toString(ch[i]));
out.write(';');
} else {
out.write(ch[i]);
}
}
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import java.io.PrintStream;
/**
* Shows the call sequence of {@link XmlSerializer} methods.
*
* Useful for debugging and learning how TXW works.
*
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public class DumpSerializer implements XmlSerializer {
private final PrintStream out;
public DumpSerializer(PrintStream out) {
this.out = out;
}
public void beginStartTag(String uri, String localName, String prefix) {
out.println('<'+prefix+':'+localName);
}
public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) {
out.println('@'+prefix+':'+localName+'='+value);
}
public void writeXmlns(String prefix, String uri) {
out.println("xmlns:"+prefix+'='+uri);
}
public void endStartTag(String uri, String localName, String prefix) {
out.println('>');
}
public void endTag() {
out.println("</ >");
}
public void text(StringBuilder text) {
out.println(text);
}
public void cdata(StringBuilder text) {
out.println("<![CDATA[");
out.println(text);
out.println("]]>");
}
public void comment(StringBuilder comment) {
out.println("<!--");
out.println(comment);
out.println("-->");
}
public void startDocument() {
out.println("<?xml?>");
}
public void endDocument() {
out.println("done");
}
public void flush() {
out.println("flush");
}
}

View File

@@ -0,0 +1,312 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.XMLFilterImpl;
import java.util.Stack;
/**
* {@link XMLFilterImpl} that does indentation to SAX events.
*
* @author Kohsuke Kawaguchi
*/
public class IndentingXMLFilter extends XMLFilterImpl implements LexicalHandler {
private LexicalHandler lexical;
public IndentingXMLFilter() {
}
public IndentingXMLFilter(ContentHandler handler) {
setContentHandler(handler);
}
public IndentingXMLFilter(ContentHandler handler, LexicalHandler lexical) {
setContentHandler(handler);
setLexicalHandler(lexical);
}
public LexicalHandler getLexicalHandler() {
return lexical;
}
public void setLexicalHandler(LexicalHandler lexical) {
this.lexical = lexical;
}
/**
* Return the current indent step.
*
* <p>Return the current indent step: each start tag will be
* indented by this number of spaces times the number of
* ancestors that the element has.</p>
*
* @return The number of spaces in each indentation step,
* or 0 or less for no indentation.
* @see #setIndentStep(int)
*
* @deprecated
* Only return the length of the indent string.
*/
public int getIndentStep ()
{
return indentStep.length();
}
/**
* Set the current indent step.
*
* @param indentStep The new indent step (0 or less for no
* indentation).
* @see #getIndentStep()
*
* @deprecated
* Should use the version that takes string.
*/
public void setIndentStep (int indentStep)
{
StringBuilder s = new StringBuilder();
for( ; indentStep>0; indentStep-- ) s.append(' ');
setIndentStep(s.toString());
}
public void setIndentStep(String s) {
this.indentStep = s;
}
////////////////////////////////////////////////////////////////////
// Override methods from XMLWriter.
////////////////////////////////////////////////////////////////////
/**
* Write a start tag.
*
* <p>Each tag will begin on a new line, and will be
* indented by the current indent step times the number
* of ancestors that the element has.</p>
*
* <p>The newline and indentation will be passed on down
* the filter chain through regular characters events.</p>
*
* @param uri The element's Namespace URI.
* @param localName The element's local name.
* @param qName The element's qualified (prefixed) name.
* @param atts The element's attribute list.
* @exception org.xml.sax.SAXException If there is an error
* writing the start tag, or if a filter further
* down the chain raises an exception.
* @see XMLWriter#startElement(String, String, String,Attributes)
*/
public void startElement (String uri, String localName,
String qName, Attributes atts)
throws SAXException {
stateStack.push(SEEN_ELEMENT);
state = SEEN_NOTHING;
if (depth > 0) {
writeNewLine();
}
doIndent();
super.startElement(uri, localName, qName, atts);
depth++;
}
private void writeNewLine() throws SAXException {
super.characters(NEWLINE,0,NEWLINE.length);
}
private static final char[] NEWLINE = {'\n'};
/**
* Write an end tag.
*
* <p>If the element has contained other elements, the tag
* will appear indented on a new line; otherwise, it will
* appear immediately following whatever came before.</p>
*
* <p>The newline and indentation will be passed on down
* the filter chain through regular characters events.</p>
*
* @param uri The element's Namespace URI.
* @param localName The element's local name.
* @param qName The element's qualified (prefixed) name.
* @exception org.xml.sax.SAXException If there is an error
* writing the end tag, or if a filter further
* down the chain raises an exception.
* @see XMLWriter#endElement(String, String, String)
*/
public void endElement (String uri, String localName, String qName)
throws SAXException
{
depth--;
if (state == SEEN_ELEMENT) {
writeNewLine();
doIndent();
}
super.endElement(uri, localName, qName);
state = stateStack.pop();
}
// /**
// * Write a empty element tag.
// *
// * <p>Each tag will appear on a new line, and will be
// * indented by the current indent step times the number
// * of ancestors that the element has.</p>
// *
// * <p>The newline and indentation will be passed on down
// * the filter chain through regular characters events.</p>
// *
// * @param uri The element's Namespace URI.
// * @param localName The element's local name.
// * @param qName The element's qualified (prefixed) name.
// * @param atts The element's attribute list.
// * @exception org.xml.sax.SAXException If there is an error
// * writing the empty tag, or if a filter further
// * down the chain raises an exception.
// * @see XMLWriter#emptyElement(String, String, String, Attributes)
// */
// public void emptyElement (String uri, String localName,
// String qName, Attributes atts)
// throws SAXException
// {
// state = SEEN_ELEMENT;
// if (depth > 0) {
// super.characters("\n");
// }
// doIndent();
// super.emptyElement(uri, localName, qName, atts);
// }
/**
* Write a sequence of characters.
*
* @param ch The characters to write.
* @param start The starting position in the array.
* @param length The number of characters to use.
* @exception org.xml.sax.SAXException If there is an error
* writing the characters, or if a filter further
* down the chain raises an exception.
* @see XMLWriter#characters(char[], int, int)
*/
public void characters (char ch[], int start, int length)
throws SAXException
{
state = SEEN_DATA;
super.characters(ch, start, length);
}
public void comment(char ch[], int start, int length) throws SAXException {
if (depth > 0) {
writeNewLine();
}
doIndent();
if(lexical!=null)
lexical.comment(ch,start,length);
}
public void startDTD(String name, String publicId, String systemId) throws SAXException {
if(lexical!=null)
lexical.startDTD(name, publicId, systemId);
}
public void endDTD() throws SAXException {
if(lexical!=null)
lexical.endDTD();
}
public void startEntity(String name) throws SAXException {
if(lexical!=null)
lexical.startEntity(name);
}
public void endEntity(String name) throws SAXException {
if(lexical!=null)
lexical.endEntity(name);
}
public void startCDATA() throws SAXException {
if(lexical!=null)
lexical.startCDATA();
}
public void endCDATA() throws SAXException {
if(lexical!=null)
lexical.endCDATA();
}
////////////////////////////////////////////////////////////////////
// Internal methods.
////////////////////////////////////////////////////////////////////
/**
* Print indentation for the current level.
*
* @exception org.xml.sax.SAXException If there is an error
* writing the indentation characters, or if a filter
* further down the chain raises an exception.
*/
private void doIndent ()
throws SAXException
{
if (depth > 0) {
char[] ch = indentStep.toCharArray();
for( int i=0; i<depth; i++ )
characters(ch, 0, ch.length);
}
}
////////////////////////////////////////////////////////////////////
// Constants.
////////////////////////////////////////////////////////////////////
private final static Object SEEN_NOTHING = new Object();
private final static Object SEEN_ELEMENT = new Object();
private final static Object SEEN_DATA = new Object();
////////////////////////////////////////////////////////////////////
// Internal state.
////////////////////////////////////////////////////////////////////
private Object state = SEEN_NOTHING;
private Stack<Object> stateStack = new Stack<Object>();
private String indentStep = "";
private int depth = 0;
}

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.util.Stack;
/**
* @author Kohsuke Kawaguchi
*/
public class IndentingXMLStreamWriter extends DelegatingXMLStreamWriter {
private final static Object SEEN_NOTHING = new Object();
private final static Object SEEN_ELEMENT = new Object();
private final static Object SEEN_DATA = new Object();
private Object state = SEEN_NOTHING;
private Stack<Object> stateStack = new Stack<Object>();
private String indentStep = " ";
private int depth = 0;
public IndentingXMLStreamWriter(XMLStreamWriter writer) {
super(writer);
}
/**
* Return the current indent step.
*
* <p>Return the current indent step: each start tag will be
* indented by this number of spaces times the number of
* ancestors that the element has.</p>
*
* @return The number of spaces in each indentation step,
* or 0 or less for no indentation.
* @see #setIndentStep(int)
*
* @deprecated
* Only return the length of the indent string.
*/
public int getIndentStep() {
return indentStep.length();
}
/**
* Set the current indent step.
*
* @param indentStep The new indent step (0 or less for no
* indentation).
* @see #getIndentStep()
*
* @deprecated
* Should use the version that takes string.
*/
public void setIndentStep(int indentStep) {
StringBuilder s = new StringBuilder();
for (; indentStep > 0; indentStep--) s.append(' ');
setIndentStep(s.toString());
}
public void setIndentStep(String s) {
this.indentStep = s;
}
private void onStartElement() throws XMLStreamException {
stateStack.push(SEEN_ELEMENT);
state = SEEN_NOTHING;
if (depth > 0) {
super.writeCharacters("\n");
}
doIndent();
depth++;
}
private void onEndElement() throws XMLStreamException {
depth--;
if (state == SEEN_ELEMENT) {
super.writeCharacters("\n");
doIndent();
}
state = stateStack.pop();
}
private void onEmptyElement() throws XMLStreamException {
state = SEEN_ELEMENT;
if (depth > 0) {
super.writeCharacters("\n");
}
doIndent();
}
/**
* Print indentation for the current level.
*
* @exception org.xml.sax.SAXException If there is an error
* writing the indentation characters, or if a filter
* further down the chain raises an exception.
*/
private void doIndent() throws XMLStreamException {
if (depth > 0) {
for (int i = 0; i < depth; i++)
super.writeCharacters(indentStep);
}
}
public void writeStartDocument() throws XMLStreamException {
super.writeStartDocument();
super.writeCharacters("\n");
}
public void writeStartDocument(String version) throws XMLStreamException {
super.writeStartDocument(version);
super.writeCharacters("\n");
}
public void writeStartDocument(String encoding, String version) throws XMLStreamException {
super.writeStartDocument(encoding, version);
super.writeCharacters("\n");
}
public void writeStartElement(String localName) throws XMLStreamException {
onStartElement();
super.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
onStartElement();
super.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
onStartElement();
super.writeStartElement(prefix, localName, namespaceURI);
}
public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
onEmptyElement();
super.writeEmptyElement(namespaceURI, localName);
}
public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
onEmptyElement();
super.writeEmptyElement(prefix, localName, namespaceURI);
}
public void writeEmptyElement(String localName) throws XMLStreamException {
onEmptyElement();
super.writeEmptyElement(localName);
}
public void writeEndElement() throws XMLStreamException {
onEndElement();
super.writeEndElement();
}
public void writeCharacters(String text) throws XMLStreamException {
state = SEEN_DATA;
super.writeCharacters(text);
}
public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
state = SEEN_DATA;
super.writeCharacters(text, start, len);
}
public void writeCData(String data) throws XMLStreamException {
state = SEEN_DATA;
super.writeCData(data);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import javax.xml.transform.Result;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
/**
* Factory for producing XmlSerializers for various Result types.
*
* @author Ryan.Shoemaker@Sun.COM
*/
public abstract class ResultFactory {
/**
* Do not instanciate.
*/
private ResultFactory() {}
/**
* Factory method for producing {@link XmlSerializer) from {@link javax.xml.transform.Result}.
*
* This method supports {@link javax.xml.transform.sax.SAXResult},
* {@link javax.xml.transform.stream.StreamResult}, and {@link javax.xml.transform.dom.DOMResult}.
*
* @param result the Result that will receive output from the XmlSerializer
* @return an implementation of XmlSerializer that will produce output on the supplied Result
*/
public static XmlSerializer createSerializer(Result result) {
if (result instanceof SAXResult)
return new SaxSerializer((SAXResult) result);
if (result instanceof DOMResult)
return new DomSerializer((DOMResult) result);
if (result instanceof StreamResult)
return new StreamSerializer((StreamResult) result);
if (result instanceof TXWResult)
return new TXWSerializer(((TXWResult)result).getWriter());
throw new UnsupportedOperationException("Unsupported Result type: " + result.getClass().getName());
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import com.sun.xml.internal.txw2.TxwException;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
import javax.xml.transform.sax.SAXResult;
import java.util.Stack;
/**
* {@link XmlSerializer} for {@link SAXResult} and {@link ContentHandler}.
*
* @author Ryan.Shoemaker@Sun.COM
*/
public class SaxSerializer implements XmlSerializer {
private final ContentHandler writer;
private final LexicalHandler lexical;
public SaxSerializer(ContentHandler handler) {
this(handler,null,true);
}
/**
* Creates an {@link XmlSerializer} that writes SAX events.
*
* <p>
* Sepcifying a non-null {@link LexicalHandler} allows applications
* to write comments and CDATA sections.
*/
public SaxSerializer(ContentHandler handler,LexicalHandler lex) {
this(handler, lex, true);
}
public SaxSerializer(ContentHandler handler,LexicalHandler lex, boolean indenting) {
if(!indenting) {
writer = handler;
lexical = lex;
} else {
IndentingXMLFilter indenter = new IndentingXMLFilter(handler, lex);
writer = indenter;
lexical = indenter;
}
}
public SaxSerializer(SAXResult result) {
this(result.getHandler(),result.getLexicalHandler());
}
// XmlSerializer implementation
public void startDocument() {
try {
writer.startDocument();
} catch (SAXException e) {
throw new TxwException(e);
}
}
// namespace prefix bindings
// add in #writeXmlns and fired in #endStartTag
private final Stack<String> prefixBindings = new Stack<String>();
public void writeXmlns(String prefix, String uri) {
// defend against parsers that pass null in for "xmlns" prefix
if (prefix == null) {
prefix = "";
}
if (prefix.equals("xml")) {
return;
}
prefixBindings.add(uri);
prefixBindings.add(prefix);
}
// element stack
private final Stack<String> elementBindings = new Stack<String>();
public void beginStartTag(String uri, String localName, String prefix) {
// save element bindings for #endTag
elementBindings.add(getQName(prefix, localName));
elementBindings.add(localName);
elementBindings.add(uri);
}
// attribute storage
// attrs are buffered in #writeAttribute and sent to the content
// handler in #endStartTag
private final AttributesImpl attrs = new AttributesImpl();
public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) {
attrs.addAttribute(uri,
localName,
getQName(prefix, localName),
"CDATA",
value.toString());
}
public void endStartTag(String uri, String localName, String prefix) {
try {
while (prefixBindings.size() != 0) {
writer.startPrefixMapping(prefixBindings.pop(), // prefix
prefixBindings.pop() // uri
);
}
writer.startElement(uri,
localName,
getQName(prefix, localName),
attrs);
attrs.clear();
} catch (SAXException e) {
throw new TxwException(e);
}
}
public void endTag() {
try {
writer.endElement(elementBindings.pop(), // uri
elementBindings.pop(), // localName
elementBindings.pop() // qname
);
} catch (SAXException e) {
throw new TxwException(e);
}
}
public void text(StringBuilder text) {
try {
writer.characters(text.toString().toCharArray(), 0, text.length());
} catch (SAXException e) {
throw new TxwException(e);
}
}
public void cdata(StringBuilder text) {
if(lexical==null)
throw new UnsupportedOperationException("LexicalHandler is needed to write PCDATA");
try {
lexical.startCDATA();
text(text);
lexical.endCDATA();
} catch (SAXException e) {
throw new TxwException(e);
}
}
public void comment(StringBuilder comment) {
try {
if(lexical==null)
throw new UnsupportedOperationException("LexicalHandler is needed to write comments");
else
lexical.comment(comment.toString().toCharArray(), 0, comment.length() );
} catch (SAXException e) {
throw new TxwException(e);
}
}
public void endDocument() {
try {
writer.endDocument();
} catch (SAXException e) {
throw new TxwException(e);
}
}
public void flush() {
// noop
}
// other methods
private static String getQName(String prefix, String localName) {
final String qName;
if (prefix == null || prefix.length() == 0)
qName = localName;
else
qName = prefix + ':' + localName;
return qName;
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import com.sun.xml.internal.txw2.TxwException;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
/**
* XML serializer for StAX XMLStreamWriter.
*
* TODO: add support for XMLEventWriter (if it makes sense)
*
* @author Ryan.Shoemaker@Sun.COM
*/
public class StaxSerializer implements XmlSerializer {
private final XMLStreamWriter out;
public StaxSerializer(XMLStreamWriter writer) {
this(writer,true);
}
public StaxSerializer(XMLStreamWriter writer, boolean indenting) {
if(indenting)
writer = new IndentingXMLStreamWriter(writer);
this.out = writer;
}
public void startDocument() {
try {
out.writeStartDocument();
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void beginStartTag(String uri, String localName, String prefix) {
try {
out.writeStartElement(prefix, localName, uri);
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) {
try {
out.writeAttribute(prefix, uri, localName, value.toString());
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void writeXmlns(String prefix, String uri) {
try {
if (prefix.length() == 0) {
out.setDefaultNamespace(uri);
} else {
out.setPrefix(prefix, uri);
}
// this method handles "", null, and "xmlns" prefixes properly
out.writeNamespace(prefix, uri);
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void endStartTag(String uri, String localName, String prefix) {
// NO-OP
}
public void endTag() {
try {
out.writeEndElement();
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void text(StringBuilder text) {
try {
out.writeCharacters(text.toString());
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void cdata(StringBuilder text) {
try {
out.writeCData(text.toString());
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void comment(StringBuilder comment) {
try {
out.writeComment(comment.toString());
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void endDocument() {
try {
out.writeEndDocument();
out.flush();
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
public void flush() {
try {
out.flush();
} catch (XMLStreamException e) {
throw new TxwException(e);
}
}
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import com.sun.xml.internal.txw2.TxwException;
import javax.xml.transform.stream.StreamResult;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.io.UnsupportedEncodingException;
/**
* {@link XmlSerializer} for {@link javax.xml.transform.stream.StreamResult}.
*
* @author Ryan.Shoemaker@Sun.COM
*/
public class StreamSerializer implements XmlSerializer {
// delegate to SaxSerializer
private final SaxSerializer serializer;
private final XMLWriter writer;
public StreamSerializer(OutputStream out) {
this(createWriter(out));
}
public StreamSerializer(OutputStream out,String encoding) throws UnsupportedEncodingException {
this(createWriter(out,encoding));
}
public StreamSerializer(Writer out) {
this(new StreamResult(out));
}
public StreamSerializer(StreamResult streamResult) {
// if this method opened a stream, let it close it
final OutputStream[] autoClose = new OutputStream[1];
if (streamResult.getWriter() != null)
writer = createWriter(streamResult.getWriter());
else if (streamResult.getOutputStream() != null)
writer = createWriter(streamResult.getOutputStream());
else if (streamResult.getSystemId() != null) {
String fileURL = streamResult.getSystemId();
fileURL = convertURL(fileURL);
try {
FileOutputStream fos = new FileOutputStream(fileURL);
autoClose[0] = fos;
writer = createWriter(fos);
} catch (IOException e) {
throw new TxwException(e);
}
} else
throw new IllegalArgumentException();
// now delegate to the SaxSerializer
serializer = new SaxSerializer(writer,writer,false) {
public void endDocument() {
super.endDocument();
if(autoClose[0]!=null) {
try {
autoClose[0].close();
} catch (IOException e) {
throw new TxwException(e);
}
autoClose[0] = null;
}
}
};
}
private StreamSerializer(XMLWriter writer) {
this.writer = writer;
// now delegate to the SaxSerializer
serializer = new SaxSerializer(writer,writer,false);
}
private String convertURL(String url) {
url = url.replace('\\', '/');
url = url.replaceAll("//","/");
url = url.replaceAll("//","/");
if (url.startsWith("file:/")) {
if (url.substring(6).indexOf(":") > 0)
url = url.substring(6);
else
url = url.substring(5);
} // otherwise assume that it's a file name
return url;
}
// XmlSerializer api's - delegate to SaxSerializer
public void startDocument() {
serializer.startDocument();
}
public void beginStartTag(String uri, String localName, String prefix) {
serializer.beginStartTag(uri, localName, prefix);
}
public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) {
serializer.writeAttribute(uri, localName, prefix, value);
}
public void writeXmlns(String prefix, String uri) {
serializer.writeXmlns(prefix, uri);
}
public void endStartTag(String uri, String localName, String prefix) {
serializer.endStartTag(uri, localName, prefix);
}
public void endTag() {
serializer.endTag();
}
public void text(StringBuilder text) {
serializer.text(text);
}
public void cdata(StringBuilder text) {
serializer.cdata(text);
}
public void comment(StringBuilder comment) {
serializer.comment(comment);
}
public void endDocument() {
serializer.endDocument();
}
public void flush() {
serializer.flush();
try {
writer.flush();
} catch (IOException e) {
throw new TxwException(e);
}
}
// other supporting code
private static XMLWriter createWriter(Writer w) {
// buffering improves the performance
DataWriter dw = new DataWriter(new BufferedWriter(w));
dw.setIndentStep(" ");
return dw;
}
private static XMLWriter createWriter(OutputStream os, String encoding) throws UnsupportedEncodingException {
XMLWriter writer = createWriter(new OutputStreamWriter(os,encoding));
writer.setEncoding(encoding);
return writer;
}
private static XMLWriter createWriter(OutputStream os) {
try {
return createWriter(os,"UTF-8");
} catch (UnsupportedEncodingException e) {
// UTF-8 is supported on all platforms.
throw new Error(e);
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import com.sun.xml.internal.txw2.TypedXmlWriter;
import javax.xml.transform.Result;
/**
* Allow you to wrap {@link TypedXmlWriter} into a {@link Result}
* so that it can be passed to {@link ResultFactory}.
*
* <p>
* This class doesn't extend from known {@link Result} type,
* so it won't work elsewhere.
*
* @author Kohsuke Kawaguchi
*/
public class TXWResult implements Result {
private String systemId;
private TypedXmlWriter writer;
public TXWResult(TypedXmlWriter writer) {
this.writer = writer;
}
public TypedXmlWriter getWriter() {
return writer;
}
public void setWriter(TypedXmlWriter writer) {
this.writer = writer;
}
public String getSystemId() {
return systemId;
}
public void setSystemId(String systemId) {
this.systemId = systemId;
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import com.sun.xml.internal.txw2.TypedXmlWriter;
import com.sun.xml.internal.txw2.TXW;
/**
* Dummpy implementation to pass through {@link TypedXmlWriter}
* to {@link TXW}
*
* @author Kohsuke Kawaguchi
*/
public final class TXWSerializer implements XmlSerializer {
public final TypedXmlWriter txw;
public TXWSerializer(TypedXmlWriter txw) {
this.txw = txw;
}
public void startDocument() {
throw new UnsupportedOperationException();
}
public void endDocument() {
throw new UnsupportedOperationException();
}
public void beginStartTag(String uri, String localName, String prefix) {
throw new UnsupportedOperationException();
}
public void writeAttribute(String uri, String localName, String prefix, StringBuilder value) {
throw new UnsupportedOperationException();
}
public void writeXmlns(String prefix, String uri) {
throw new UnsupportedOperationException();
}
public void endStartTag(String uri, String localName, String prefix) {
throw new UnsupportedOperationException();
}
public void endTag() {
throw new UnsupportedOperationException();
}
public void text(StringBuilder text) {
throw new UnsupportedOperationException();
}
public void cdata(StringBuilder text) {
throw new UnsupportedOperationException();
}
public void comment(StringBuilder comment) {
throw new UnsupportedOperationException();
}
public void flush() {
throw new UnsupportedOperationException();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.xml.internal.txw2.output;
import com.sun.xml.internal.txw2.TypedXmlWriter;
/**
* Low-level typeless XML writer driven from {@link TypedXmlWriter}.
*
* <p>
* Applications can use one of the predefined implementations to
* send TXW output to the desired location/format, or they can
* choose to implement this interface for custom output.
*
* <p>
* One {@link XmlSerializer} instance is responsible for writing
* one XML document.
*
* <h2>Call Sequence</h2>
* TXW calls methods on this interface in the following order:
*
* <pre>
* WHOLE_SEQUENCE := startDocument ELEMENT endDocument
* ELEMENT := beginStartTag writeXmlns* writeAttribute* endStartTag CONTENT endTag
* CONTENT := (text|ELEMENT)*
* </pre>
*
* <p>
* TXW maintains all the in-scope namespace bindings and prefix allocation.
* The {@link XmlSerializer} implementation should just use the prefix
* specified.
* </p>
*
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
public interface XmlSerializer {
/**
* The first method to be called.
*/
void startDocument();
/**
* Begins writing a start tag.
*
* @param uri
* the namespace URI of the element. Can be empty but never be null.
* @param prefix
* the prefix that should be used for this element. Can be empty,
* but never null.
*/
void beginStartTag(String uri,String localName,String prefix);
/**
* Writes an attribute.
*
* @param value
* The value of the attribute. It's the callee's responsibility to
* escape special characters (such as &lt;, &gt;, and &amp;) in this buffer.
*
* @param uri
* the namespace URI of the attribute. Can be empty but never be null.
* @param prefix
* the prefix that should be used for this attribute. Can be empty,
* but never null.
*/
void writeAttribute(String uri,String localName,String prefix,StringBuilder value);
/**
* Writes a namespace declaration.
*
* @param uri
* the namespace URI to be declared. Can be empty but never be null.
* @param prefix
* the prefix that is allocated. Can be empty but never be null.
*/
void writeXmlns(String prefix,String uri);
/**
* Completes the start tag.
*
* @param uri
* the namespace URI of the element. Can be empty but never be null.
* @param prefix
* the prefix that should be used for this element. Can be empty,
* but never null.
*/
void endStartTag(String uri,String localName,String prefix);
/**
* Writes an end tag.
*/
void endTag();
/**
* Writes PCDATA.
*
* @param text
* The character data to be written. It's the callee's responsibility to
* escape special characters (such as &lt;, &gt;, and &amp;) in this buffer.
*/
void text(StringBuilder text);
/**
* Writes CDATA.
*/
void cdata(StringBuilder text);
/**
* Writes a comment.
*
* @throws UnsupportedOperationException
* if the writer doesn't support writing a comment, it can throw this exception.
*/
void comment(StringBuilder comment);
/**
* The last method to be called.
*/
void endDocument();
/**
* Flush the buffer.
*
* This method is called when applications invoke {@link TypedXmlWriter#commit(boolean)}
* method. If the implementation performs any buffering, it should flush the buffer.
*/
void flush();
}