📄 xmlmapper.java
字号:
package org.apache.tomcat.util.xml;
import org.apache.tomcat.util.*;
import java.beans.*;
import java.io.*;
import java.io.IOException;
import java.lang.reflect.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.StringTokenizer;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
/**
* SAX Handler - it will read the XML and construct java objects
*
* @author costin@dnt.ro
*/
public class XmlMapper
extends HandlerBase
implements SaxContext {
Locator locator;
/**
* The URLs of DTDs that have been registered, keyed by the public
* identifier that corresponds.
*/
private Hashtable fileDTDs = new Hashtable();
private Hashtable resDTDs = new Hashtable();
// Stack of elements
Stack oStack=new Stack();
Object root;
Object attributeStack[];
String tagStack[];
int oSp;
int sp;
String body;
int debug=0;
boolean validating=false;
public XmlMapper() {
attributeStack = new Object[100]; // depth of the xml doc
tagStack = new String[100];
initDefaultRules();
}
public void setDocumentLocator (Locator locator)
{
if( debug>0 ) log("Set locator : " + locator);
this.locator = locator;
}
public void startDocument () throws SAXException
{
sp = 0;
}
public void endDocument () throws SAXException
{
if (sp != 0) {
System.out.println("The XML document is probably broken. " + sp);
}
}
public void startElement (String tag, AttributeList attributes)
throws SAXException
{
try {
// if( debug>0) log(sp + "<" + tag + " " + attributes + ">");
attributeStack[sp]=attributes;
tagStack[sp]=tag;
sp++;
matchStart( this);
body="";
} catch (Exception ex) {
// do not ignore messages, caller should handle it
throw new SAXException( positionToString(), ex );
}
}
private String positionToString() {
StringBuffer sb=new StringBuffer();
if( locator!=null ) sb.append("Line ").append(locator.getLineNumber()).append(" ");
sb.append("/");
for( int i=0; i< sp ; i++ ) sb.append( tagStack[i] ).append( "/" );
sb.append(" ");
AttributeList attributes=(AttributeList) attributeStack[sp-1];
if( attributes!=null)
for (int i = 0; i < attributes.getLength (); i++) {
sb.append(attributes.getName(i)).append( "=" ).append(attributes.getValue(i));
sb.append(" ");
}
return sb.toString();
}
public void endElement (String tag) throws SAXException
{
try {
// Find a match for the current tag in the context
matchEnd( this);
if( sp > 1 ) {
tagStack[sp] = null;
attributeStack[sp]=null;
}
sp--;
} catch (Exception ex) {
// do not ignore messages, caller should handle it
throw new SAXException( positionToString(), ex );
}
}
public void characters (char buf [], int offset, int len)
throws SAXException
{
body=body+ new String(buf, offset, len );
}
public void ignorableWhitespace (char buf [], int offset, int len)
throws SAXException
{
}
public void processingInstruction (String name, String instruction)
throws SAXException
{
}
// -------------------- Context --------------------
// provide access to the current stack and XML elements.
// -------------------- Context --------------------
public AttributeList getAttributeList( int pos ) {
return (AttributeList)attributeStack[pos];
}
public int getTagCount() {
return sp;
}
public String getTag( int pos ) {
return tagStack[pos];
}
public String getBody() {
return body;
}
public Stack getObjectStack() {
return oStack;
}
public Object getRoot() {
return root;
}
public void setRoot(Object o) {
root=o;
}
// -------------------- Utils --------------------
// Debug ( to be replaced with the real thing )
public void setDebug( int level ) {
if(level!=0) log( "Debug level: " + level );
debug=level;
}
public int getDebug() {
return debug;
}
public void setValidating( boolean validating ) {
if (debug >= 1)
log("Validating = " + validating);
this.validating = validating;
}
public boolean getValidating() {
return (this.validating);
}
public void log(String msg) {
// log is for debug only, it should't be enabled for anything else
// ( no dependency on Logger or any external tomcat package )
System.out.println("XmlMapper: " + msg);
}
/** read an XML file, construct and return the object hierarchy
*/
public Object readXml(File xmlFile, Object root)
throws Exception
{
if(root!=null) {
Stack st=this.getObjectStack();
this.root=root;
st.push( root );
}
try {
SAXParser parser=null;
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(validating);
parser = factory.newSAXParser();
parser.parse(xmlFile, this);
return root;
// assume the stack is in the right position.
// or throw an exception is more than one element is on the stack
} catch (IOException ioe) {
ioe.printStackTrace();
String msg = "Can't open config file: " + xmlFile +
" due to: " + ioe;
throw new Exception(msg);
} catch (SAXException se) {
System.out.println("ERROR reading " + xmlFile);
System.out.println("At " + se.getMessage());
// se.printStackTrace();
System.out.println();
Exception ex1=se.getException();
if( ex1 != null )
throw ex1;// xerces bug
else
throw se;
}
}
/** read an XML input stream, construct and return the object hierarchy
*/
public Object readXml(InputStream xmlFile, Object root)
throws Exception
{
if(root!=null) {
Stack st=this.getObjectStack();
this.root=root;
st.push( root );
}
SAXParser parser=null;
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(validating);
parser = factory.newSAXParser();
parser.parse(xmlFile, this);
return root;
// assume the stack is in the right position.
// or throw an exception is more than one element is on the stack
} catch (IOException ioe) {
String msg = "Can't open config file: " + xmlFile +
" due to: " + ioe;
throw new Exception(msg);
} catch (SAXException se) {
System.out.println("ERROR reading " + xmlFile);
System.out.println("At " + se.getMessage());
// se.printStackTrace();
System.out.println();
Exception ex1=se.getException();
throw ex1;
}
}
/**
* Register the specified DTD with a local file.
* This must be called prior to the first call to <code>readXml()</code>.
*
* @param publicId Public identifier of the DTD to be resolved
* @param dtdFile The local file name to use for reading this DTD
*/
public void registerDTDFile(String publicId, String dtdFile) {
fileDTDs.put(publicId, dtdFile);
}
/**
* Register the specified DTD to map to a resource in the classpath
* This must be called prior to the first call to <code>readXml()</code>.
*
* @param publicId Public identifier of the DTD to be resolved
* @param dtdRes local resource name, to be used with getResource()
*/
public void registerDTDRes(String publicId, String dtdRes) {
resDTDs.put(publicId, dtdRes);
}
class Rule {
XmlMatch match;
XmlAction action;
Rule( XmlMatch match, XmlAction action ) {
this.match=match;
this.action=action;
}
}
Rule rules[]=new Rule[100];
Rule matching[]=new Rule[100];
int ruleCount=0;
/**
*/
private void initDefaultRules() {
// One-time actions, in line
addRule( "xmlmapper:debug",
new XmlAction() {
public void start(SaxContext ctx) {
int top=ctx.getTagCount()-1;
AttributeList attributes = ctx.getAttributeList( top );
String levelS=attributes.getValue("level");
XmlMapper mapper=(XmlMapper)ctx;
if( levelS!=null)
mapper.setDebug( new Integer(levelS).intValue());
}
}
);
// ant-like
addRule( "xmlmapper:taskdef",
new XmlAction() {
public void start(SaxContext ctx) {
XmlMapper mapper=(XmlMapper)ctx;
int top=ctx.getTagCount()-1;
AttributeList attributes = ctx.getAttributeList( top );
String match=attributes.getValue("match");
if(match==null) return; //log
String obj=attributes.getValue("object-create");
String objA=attributes.getValue("object-create-attrib");
if( obj!=null || objA!=null)
mapper.addRule( match, new ObjectCreate( obj, objA));
obj=attributes.getValue("set-properties");
if( obj!=null)
mapper.addRule( match, new SetProperties());
obj=attributes.getValue("set-parent");
if( obj!=null)
mapper.addRule( match, new SetParent(obj));
obj=attributes.getValue("add-child");
objA=attributes.getValue("child-type");
if( obj!=null)
mapper.addRule( match, new AddChild(obj, objA));
// Custom actions
obj=attributes.getValue("action");
if( obj!=null) {
try {
Class c=Class.forName( obj );
Object o=c.newInstance();
mapper.addRule( match, (XmlAction)o);
} catch( Exception ex ) {
System.out.println("Can't add action " + obj);
}
}
}
}
);
}
public void addRule( String path, XmlAction action ) {
rules[ruleCount]=new Rule( new PathMatch( path ) , action);
ruleCount++;
}
private int match( SaxContext ctx, Rule matching[] ) {
int matchCount=0;
for( int i=0; i< ruleCount; i++ ) {
if( rules[i].match.match( ctx ) &&
rules[i].action != null ) {
matching[matchCount]=rules[i];
matchCount++;
}
}
return matchCount;
}
void matchStart(SaxContext ctx ) throws Exception {
int matchCount=match( ctx, matching );
for ( int i=0; i< matchCount; i++ ) {
matching[i].action.start( ctx );
}
}
void matchEnd(SaxContext ctx ) throws Exception {
int matchCount=match( ctx, matching );
for ( int i=0; i< matchCount; i++ )
matching[i].action.end( ctx );
for ( int i=0; i< matchCount; i++ )
matching[i].action.cleanup( ctx );
}
/**
* Resolve the requested external entity, replacing it by an internal
* DTD if one has been registered.
*
* @param publicId Public identifier of the entity being referenced
* @param systemId System identifier of the entity being referenced
*
* @exception SAXException if a parsing error occurs
*/
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException
{
if (publicId == null)
return (null); // if publicid is null, parser will handle that (tfr)
String dtd = (String) fileDTDs.get(publicId);
if( dtd != null ) {
File dtdF=new File( dtd );
if( dtdF.exists() )
try {
return new InputSource(new FileInputStream(dtdF));
} catch( FileNotFoundException ex ) {
}
// else continue
}
dtd = (String) resDTDs.get( publicId );
if( dtd != null ) {
InputStream is = this.getClass().getResourceAsStream( dtd );
if( is!= null )
return new InputSource(is);
System.out.println("XXX resource not found !!! " + dtd);
System.out.println(this.getClass().getClassLoader().getClass().getName());
}
log("Can't find resource for entity: " + publicId + " --> " + systemId + " \"" + dtd +"\"");
return null;
}
public void notationDecl (String name,
String publicId,
String systemId)
{
System.out.println("Notation: " + name + " " + publicId +
" " + systemId);
}
public void unparsedEntityDecl (String name,
String publicId,
String systemId,
String notationName)
{
System.out.println("Unparsed: " + name + " " + publicId +
" " + systemId + " " + notationName);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -