976 lines
No EOL
36 KiB
Java
976 lines
No EOL
36 KiB
Java
/*************************************************************************
|
|
*
|
|
* $RCSfile: XMLTools.java,v $
|
|
*
|
|
* $Revision: 1.1 $
|
|
*
|
|
* last change:$Date: 2003-01-27 16:26:52 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (the "License"); You may not use this file
|
|
* except in compliance with the License. You may obtain a copy of the
|
|
* License at http://www.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
package util;
|
|
|
|
import java.io.PrintWriter ;
|
|
import java.util.Vector ;
|
|
import java.util.Hashtable ;
|
|
import java.util.Enumeration ;
|
|
import java.util.HashSet ;
|
|
|
|
// access the implementations via names
|
|
import com.sun.star.uno.XInterface;
|
|
import com.sun.star.io.XOutputStream;
|
|
import com.sun.star.io.XInputStream;
|
|
import com.sun.star.io.XActiveDataSource;
|
|
import com.sun.star.ucb.XSimpleFileAccess;
|
|
import com.sun.star.lang.XMultiServiceFactory;
|
|
import com.sun.star.xml.sax.XDocumentHandler;
|
|
import com.sun.star.uno.Any;
|
|
import com.sun.star.uno.Type;
|
|
import com.sun.star.uno.UnoRuntime;
|
|
import com.sun.star.beans.PropertyValue;
|
|
import com.sun.star.xml.sax.XLocator;
|
|
import com.sun.star.xml.sax.XAttributeList;
|
|
import com.sun.star.xml.sax.XParser ;
|
|
import com.sun.star.xml.sax.InputSource ;
|
|
import com.sun.star.lang.XComponent;
|
|
import com.sun.star.document.XExporter;
|
|
import com.sun.star.document.XImporter;
|
|
import com.sun.star.document.XFilter;
|
|
|
|
|
|
public class XMLTools {
|
|
|
|
/**
|
|
* The implementation of <code>com.sun.star.xml.sax.XAttributeList</code>
|
|
* where attributes and their values can be added.
|
|
*/
|
|
public static class AttributeList implements XAttributeList {
|
|
private static class Attribute {
|
|
public String Name ;
|
|
public String Type ;
|
|
public String Value ;
|
|
}
|
|
private Hashtable attrByName = new Hashtable() ;
|
|
private Vector attributes = new Vector() ;
|
|
private PrintWriter log = null ;
|
|
|
|
/**
|
|
* Creates a class instance.
|
|
*/
|
|
public AttributeList() {}
|
|
|
|
/**
|
|
* Constructs a list which will report to <code>log</code>
|
|
* specified about each <code>XDocumentHandler</code> method
|
|
* call.
|
|
*/
|
|
public AttributeList(PrintWriter log) {
|
|
this.log = log ;
|
|
}
|
|
|
|
public AttributeList(XAttributeList list) {
|
|
if (list == null) return ;
|
|
for (short i = 0; i < list.getLength(); i++) {
|
|
add(list.getNameByIndex(i), list.getTypeByIndex(i),
|
|
list.getValueByIndex(i)) ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds an attribute with type and value specified.
|
|
* @param name The attribute name.
|
|
* @param type Value type (usually 'CDATA' used).
|
|
* @param value Attribute value.
|
|
*/
|
|
public void add(String name, String type, String value) {
|
|
Attribute attr = new Attribute() ;
|
|
attr.Name = name ;
|
|
attr.Type = type ;
|
|
attr.Value = value ;
|
|
attributes.add(attr) ;
|
|
attrByName.put(attr.Name, attr) ;
|
|
}
|
|
|
|
/**
|
|
* Adds an attribute with value specified. As a type of
|
|
* value 'CDATA' string specified.
|
|
* @param name The attribute name.
|
|
* @param value Attribute value.
|
|
*/
|
|
public void add(String name, String value) {
|
|
add(name, "CDATA", value) ;
|
|
}
|
|
|
|
/**
|
|
* Clears all attributes added before.
|
|
*/
|
|
public void clear() {
|
|
attrByName.clear() ;
|
|
attributes.clear() ;
|
|
}
|
|
|
|
/***************************************
|
|
* XAttributeList methods
|
|
****************************************/
|
|
|
|
public short getLength() {
|
|
if (log != null)
|
|
log.println("getLength() called -> " + attributes.size()) ;
|
|
return (short) attributes.size() ;
|
|
}
|
|
|
|
public String getNameByIndex(short idx) {
|
|
String name = ((Attribute) attributes.get(idx)).Name ;
|
|
if (log != null)
|
|
log.println("getNameByIndex(" + idx + ") called -> '" +
|
|
name + "'") ;
|
|
return name ;
|
|
}
|
|
|
|
public String getTypeByIndex(short idx) {
|
|
String type = ((Attribute) attributes.get(idx)).Type ;
|
|
if (log != null)
|
|
log.println("getTypeByIndex(" + idx + ") called -> '" +
|
|
type + "'") ;
|
|
return type;
|
|
}
|
|
|
|
public String getTypeByName(String name) {
|
|
String type = ((Attribute) attrByName.get(name)).Type ;
|
|
if (log != null)
|
|
log.println("getTypeByName('" + name + "') called -> '" +
|
|
type + "'") ;
|
|
return type;
|
|
}
|
|
public String getValueByIndex(short idx) {
|
|
String value = ((Attribute) attributes.get(idx)).Value ;
|
|
if (log != null)
|
|
log.println("getValueByIndex(" + idx + ") called -> '" +
|
|
value + "'") ;
|
|
return value;
|
|
}
|
|
|
|
public String getValueByName(String name) {
|
|
String value = ((Attribute) attrByName.get(name)).Value ;
|
|
if (log != null)
|
|
log.println("getValueByName('" + name + "') called -> '" +
|
|
value + "'") ;
|
|
return value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This class writes all XML data handled into a stream specified
|
|
* in the constructor.
|
|
*/
|
|
public static class XMLWriter implements XDocumentHandler {
|
|
private PrintWriter _log = null ;
|
|
private XLocator loc = null;
|
|
private String align = "" ;
|
|
|
|
/**
|
|
* Creates a SAX handler which writes all XML data
|
|
* handled into a <code>log</code> stream specified.
|
|
*/
|
|
public XMLWriter(PrintWriter log) {
|
|
_log = log ;
|
|
}
|
|
|
|
/**
|
|
* Creates a SAX handler which does nothing.
|
|
*/
|
|
public XMLWriter() {
|
|
}
|
|
|
|
public void processingInstruction(String appl, String data) {
|
|
if (_log == null) return ;
|
|
_log.println(align + "<?" + appl + " " + data + "?>") ;
|
|
}
|
|
public void startDocument() {
|
|
if (_log == null) return ;
|
|
_log.println("START DOCUMENT:") ;
|
|
}
|
|
public void endDocument() {
|
|
if (_log == null) return ;
|
|
_log.println("END DOCUMENT:") ;
|
|
}
|
|
public void setDocumentLocator(XLocator loc) {
|
|
if (_log == null) return ;
|
|
_log.println("DOCUMENT LOCATOR: ('" + loc.getPublicId() +
|
|
"','" + loc.getSystemId() + "')") ;
|
|
}
|
|
public void startElement(String name, XAttributeList attr) {
|
|
if (_log == null) return ;
|
|
_log.print(align + "<" + name + " ") ;
|
|
if (attr != null) {
|
|
short attrLen = attr.getLength() ;
|
|
for (short i = 0; i < attrLen; i++) {
|
|
if (i != 0) _log.print(align + " ") ;
|
|
_log.print(attr.getNameByIndex(i) + "[" +
|
|
attr.getTypeByIndex(i) + "]=\"" +
|
|
attr.getValueByIndex(i) + "\"") ;
|
|
if (i+1 != attrLen) {
|
|
_log.println() ;
|
|
}
|
|
}
|
|
}
|
|
_log.println(">") ;
|
|
|
|
align += " " ;
|
|
}
|
|
|
|
public void endElement(String name) {
|
|
if (_log == null) return ;
|
|
align = align.substring(3) ;
|
|
_log.println(align + "</" + name + ">") ;
|
|
}
|
|
|
|
public void characters(String chars) {
|
|
if (_log == null) return ;
|
|
_log.println(align + chars) ;
|
|
}
|
|
public void ignorableWhitespace(String sp) {
|
|
if (_log == null) return ;
|
|
_log.println(sp) ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if the XML structure is well formed (i.e. all tags opened must be
|
|
* closed and all tags opened inside a tag must be closed
|
|
* inside the same tag). It also checks parameters passed.
|
|
* If any collisions found appropriate error message is
|
|
* output into a stream specified. No XML data output, i.e.
|
|
* no output will be performed if no errors occur.<p>
|
|
* After document is completed there is a way to cehck
|
|
* if the XML data and structure was valid.
|
|
*/
|
|
public static class XMLWellFormChecker extends XMLWriter {
|
|
protected boolean docStarted = false ;
|
|
protected boolean docEnded = false ;
|
|
protected Vector tagStack = new Vector() ;
|
|
protected boolean wellFormed = true ;
|
|
protected boolean noOtherErrors = true ;
|
|
protected PrintWriter log = null ;
|
|
protected boolean printXMLData = false ;
|
|
|
|
public XMLWellFormChecker(PrintWriter log) {
|
|
super() ;
|
|
this.log = log ;
|
|
}
|
|
|
|
public XMLWellFormChecker(PrintWriter log_, boolean printXMLData) {
|
|
super(printXMLData ? log_ : null) ;
|
|
this.printXMLData = printXMLData ;
|
|
this.log = log_ ;
|
|
}
|
|
|
|
/**
|
|
* Reset all values. This is important e.g. for test of XFilter
|
|
* interface, where 'filter()' method istbstarted twice.
|
|
*/
|
|
public void reset() {
|
|
docStarted = false ;
|
|
docEnded = false ;
|
|
tagStack = new Vector() ;
|
|
wellFormed = true ;
|
|
noOtherErrors = true ;
|
|
PrintWriter log = null ;
|
|
printXMLData = false ;
|
|
}
|
|
|
|
public void startDocument() {
|
|
super.startDocument();
|
|
|
|
if (docStarted) {
|
|
printError("Document is started twice.") ;
|
|
wellFormed = false ;
|
|
}
|
|
|
|
docStarted = true ;
|
|
}
|
|
public void endDocument() {
|
|
super.endDocument();
|
|
if (!docStarted) {
|
|
wellFormed = false ;
|
|
printError("Document ended but not started.") ;
|
|
}
|
|
docEnded = true ;
|
|
}
|
|
public void startElement(String name, XAttributeList attr) {
|
|
super.startElement(name, attr);
|
|
if (attr == null) {
|
|
printError("attribute list passed as parameter to startElement()"+
|
|
" method has null value for tag <" + name + ">") ;
|
|
noOtherErrors = false ;
|
|
}
|
|
tagStack.add(0, name) ;
|
|
}
|
|
public void endElement(String name) {
|
|
super.endElement(name);
|
|
if (wellFormed) {
|
|
if (tagStack.size() == 0) {
|
|
wellFormed = false ;
|
|
printError("No tags to close (bad closing tag </" + name + ">)") ;
|
|
} else {
|
|
String startTag = (String) tagStack.elementAt(0) ;
|
|
tagStack.remove(0) ;
|
|
if (!startTag.equals(name)) {
|
|
wellFormed = false ;
|
|
printError("Bad closing tag: </" + name +
|
|
">; tag expected: </" + startTag + ">");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if there were no errors during document handling.
|
|
* I.e. startDocument() and endDocument() must be called,
|
|
* XML must be well formed, paramters must be valid.
|
|
*/
|
|
public boolean isWellFormed() {
|
|
if (!docEnded) {
|
|
printError("Document was not ended.") ;
|
|
wellFormed = false ;
|
|
}
|
|
|
|
return wellFormed && noOtherErrors ;
|
|
}
|
|
|
|
/**
|
|
* Prints error message and all tags where error occured inside.
|
|
* Also prints "Tag trace" in case if the full XML data isn't
|
|
* printed.
|
|
*/
|
|
public void printError(String msg) {
|
|
log.println("!!! Error: " + msg) ;
|
|
if (printXMLData) return ;
|
|
log.println(" Tag trace :") ;
|
|
for (int i = 0; i < tagStack.size(); i++) {
|
|
String tag = (String) tagStack.elementAt(i) ;
|
|
log.println(" <" + tag + ">") ;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Beside structure of XML this class also can check existence
|
|
* of tags, inner tags, and character data. After document
|
|
* completion there is a way to check if required tags and
|
|
* character data was found. If there any error occurs an
|
|
* appropriate message is output.
|
|
*/
|
|
public static class XMLTagsChecker extends XMLWellFormChecker {
|
|
protected Hashtable tags = new Hashtable() ;
|
|
protected Hashtable chars = new Hashtable() ;
|
|
protected boolean allOK = true ;
|
|
|
|
public XMLTagsChecker(PrintWriter log) {
|
|
super(log) ;
|
|
}
|
|
|
|
/**
|
|
* Adds a tag name which must be contained in the XML data.
|
|
*/
|
|
public void addTag(String tag) {
|
|
tags.put(tag, "") ;
|
|
}
|
|
/**
|
|
* Adds a tag name which must be contained in the XML data and
|
|
* must be inside the tag with name <code>outerTag</code>.
|
|
*/
|
|
public void addTagEnclosed(String tag, String outerTag) {
|
|
tags.put(tag, outerTag) ;
|
|
}
|
|
/**
|
|
* Adds a character data which must be contained in the XML data.
|
|
*/
|
|
public void addCharacters(String ch) {
|
|
chars.put(ch, "") ;
|
|
}
|
|
/**
|
|
* Adds a character data which must be contained in the XML data and
|
|
* must be inside the tag with name <code>outerTag</code>.
|
|
*/
|
|
public void addCharactersEnclosed(String ch, String outerTag) {
|
|
chars.put(ch, outerTag) ;
|
|
}
|
|
|
|
public void startElement(String name, XAttributeList attrs) {
|
|
super.startElement(name, attrs) ;
|
|
if (tags.containsKey(name)) {
|
|
String outerTag = (String) tags.get(name);
|
|
if (!outerTag.equals("")) {
|
|
boolean isInTag = false ;
|
|
for (int i = 0; i < tagStack.size(); i++) {
|
|
if (outerTag.equals((String) tagStack.elementAt(i))) {
|
|
isInTag = true ;
|
|
break ;
|
|
}
|
|
}
|
|
if (!isInTag) {
|
|
printError("Required tag <" + name + "> found, but is not enclosed in tag <" +
|
|
outerTag + ">") ;
|
|
allOK = false ;
|
|
}
|
|
}
|
|
tags.remove(name) ;
|
|
}
|
|
}
|
|
|
|
public void characters(String ch) {
|
|
super.characters(ch) ;
|
|
ch.trim() ;
|
|
|
|
if (chars.containsKey(ch)) {
|
|
String outerTag = (String) chars.get(ch);
|
|
if (!outerTag.equals("")) {
|
|
boolean isInTag = false ;
|
|
for (int i = 0; i < tagStack.size(); i++) {
|
|
if (outerTag.equals((String) tagStack.elementAt(i))) {
|
|
isInTag = true ;
|
|
break ;
|
|
}
|
|
}
|
|
if (!isInTag) {
|
|
printError("Required characters '" + ch + "' found, but are not enclosed in tag <" +
|
|
outerTag + ">") ;
|
|
allOK = false ;
|
|
}
|
|
}
|
|
chars.remove(ch) ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if the XML data was valid and well formed and if
|
|
* all necessary tags and character data was found.
|
|
*/
|
|
public boolean checkTags() {
|
|
allOK &= isWellFormed() ;
|
|
|
|
Enumeration badTags = tags.keys() ;
|
|
Enumeration badChars = chars.keys() ;
|
|
|
|
if (badTags.hasMoreElements()) {
|
|
allOK = false ;
|
|
log.println("Required tags were not found in export :") ;
|
|
while(badTags.hasMoreElements()) {
|
|
log.println(" <" + ((String) badTags.nextElement()) + ">") ;
|
|
}
|
|
}
|
|
if (badChars.hasMoreElements()) {
|
|
allOK = false ;
|
|
log.println("Required characters were not found in export :") ;
|
|
while(badChars.hasMoreElements()) {
|
|
log.println(" <" + ((String) badChars.nextElement()) + ">") ;
|
|
}
|
|
}
|
|
reset();
|
|
return allOK ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Represents an XML tag which must be found in XML data written.
|
|
* This tag can contain only its name or tag name and attribute
|
|
* name, or attribute value additionally.
|
|
*/
|
|
public static class Tag {
|
|
private String name = null;
|
|
private String[][] attrList = new String[0][3] ;
|
|
|
|
/**
|
|
* Creates tag which has only a name. Attributes don't make sense.
|
|
* @param tagName The name of the tag.
|
|
*/
|
|
public Tag(String tagName) {
|
|
name = tagName ;
|
|
}
|
|
|
|
/**
|
|
* Creates a tag with the name specified, which must have an
|
|
* attribute with name specified. The value of this attribute
|
|
* doesn't make sense.
|
|
* @param tagName The name of the tag.
|
|
* @param attrName The name of attribute which must be contained
|
|
* in the tag.
|
|
*/
|
|
public Tag(String tagName, String attrName) {
|
|
name = tagName ;
|
|
attrList = new String[1][3] ;
|
|
attrList[0][0] = attrName ;
|
|
}
|
|
|
|
/**
|
|
* Creates a tag with the name specified, which must have an
|
|
* attribute with the value specified. The type of value
|
|
* assumed to be 'CDATA'.
|
|
* @param tagName The name of the tag.
|
|
* @param attrName The name of attribute which must be contained
|
|
* in the tag.
|
|
* @param attrValue Attribute value.
|
|
*/
|
|
public Tag(String tagName, String attrName, String attrValue) {
|
|
name = tagName ;
|
|
attrList = new String[1][3] ;
|
|
attrList[0][0] = attrName ;
|
|
attrList[0][1] = "CDATA" ;
|
|
attrList[0][2] = attrValue ;
|
|
}
|
|
|
|
/**
|
|
* Creates a tag with the name specified, which must have
|
|
* attributes specified. The value of thesee attributes
|
|
* doesn't make sense.
|
|
* @param tagName The name of the tag.
|
|
* @param attrNames Array with names of attributes which must
|
|
* be contained in the tag.
|
|
*/
|
|
public Tag(String tagName, String[] attrNames) {
|
|
name = tagName ;
|
|
attrList = new String[attrNames.length][3] ;
|
|
for (int i = 0; i < attrNames.length; i++) {
|
|
attrList[i][0] = attrNames[i] ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a tag with the name specified, which must have an
|
|
* attributes with their values specified. The type of all values
|
|
* assumed to be 'CDATA'.
|
|
* @param tagName The name of the tag.
|
|
* @param attrValues An array with attribute names and their values.
|
|
* <code>attrValues[N][0]</code> element contains the name of Nth
|
|
* attribute, and <code>attrValues[N][1]</code> element contains
|
|
* value of Nth attribute, if value is <code>null</code> then the
|
|
* attribute value can be any.
|
|
*/
|
|
public Tag(String tagName, String[][] attrValues) {
|
|
name = tagName ;
|
|
attrList = new String[attrValues.length][3] ;
|
|
for (int i = 0; i < attrValues.length; i++) {
|
|
attrList[i][0] = attrValues[i][0] ;
|
|
attrList[i][1] = "CDATA" ;
|
|
attrList[i][2] = attrValues[i][1] ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets tag String description.
|
|
*/
|
|
public String toString() {
|
|
String ret = "<" + name ;
|
|
for (int i = 0; i < attrList.length; i++) {
|
|
ret += " " + attrList[i][0] + "=";
|
|
if (attrList[i][2] == null) {
|
|
ret += "(not specified)";
|
|
} else {
|
|
ret += "\"" + attrList[i][2] + "\"";
|
|
}
|
|
}
|
|
ret += ">";
|
|
|
|
return ret ;
|
|
}
|
|
|
|
protected boolean checkAttr(int attrListIdx, XAttributeList list) {
|
|
short j = 0 ;
|
|
int listLen = list.getLength();
|
|
while(j < listLen) {
|
|
if (attrList[attrListIdx][0].equals(list.getNameByIndex(j))) {
|
|
if (attrList[attrListIdx][2] == null) return true ;
|
|
return attrList[attrListIdx][2].equals(list.getValueByIndex(j)) ;
|
|
}
|
|
j++ ;
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
/**
|
|
* Checks if this tag matches tag passed in parameters.
|
|
* I.e. if tag specifies only it's name it mathes if names
|
|
* are equal (attributes don't make sense). If there are
|
|
* some attributes names specified in this tag method checks
|
|
* if all names present in attribute list <code>list</code>
|
|
* (attributes' values don't make sense). If attributes specified
|
|
* with values method checks if these attributes exist and
|
|
* have appropriate values.
|
|
*/
|
|
public boolean isMatchTo(String tagName, XAttributeList list) {
|
|
if (!name.equals(tagName)) return false;
|
|
boolean result = true ;
|
|
for (int i = 0; i < attrList.length; i++) {
|
|
result &= checkAttr(i, list) ;
|
|
}
|
|
return result ;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Class realises extended XML data checking. It has possibilities
|
|
* to check if a tag exists, if it has some attributes with
|
|
* values, and if this tag is contained in another tag (which
|
|
* also can specify any attributes). It can check if some
|
|
* character data exists inside any tag specified.
|
|
*/
|
|
public static class XMLChecker extends XMLWellFormChecker {
|
|
protected HashSet tagSet = new HashSet() ;
|
|
protected Vector tags = new Vector() ;
|
|
protected Vector chars = new Vector() ;
|
|
protected Vector tagStack = new Vector() ;
|
|
protected Vector attrStack = new Vector() ;
|
|
|
|
public XMLChecker(PrintWriter log, boolean writeXML) {
|
|
super(log, writeXML) ;
|
|
}
|
|
|
|
public void addTag(Tag tag) {
|
|
tags.add(new Tag[] {tag, null}) ;
|
|
tagSet.add(tag.name) ;
|
|
}
|
|
|
|
public void addTagEnclosed(Tag tag, Tag outerTag) {
|
|
tags.add(new Tag[] {tag, outerTag}) ;
|
|
tagSet.add(tag.name) ;
|
|
}
|
|
|
|
public void addCharacters(String ch) {
|
|
chars.add(new Object[] {ch.trim(), null}) ;
|
|
}
|
|
|
|
public void addCharactersEnclosed(String ch, Tag outerTag) {
|
|
chars.add(new Object[] {ch.trim(), outerTag}) ;
|
|
}
|
|
|
|
public void startElement(String name, XAttributeList attr) {
|
|
try {
|
|
super.startElement(name, attr);
|
|
|
|
if (tagSet.contains(name)) {
|
|
for (int i = 0; i < tags.size(); i++) {
|
|
Tag[] tag = (Tag[]) tags.elementAt(i);
|
|
if (tag[0].isMatchTo(name, attr)) {
|
|
if (tag[1] == null) {
|
|
tags.remove(i--);
|
|
} else {
|
|
boolean isInStack = false ;
|
|
for (int j = 0; j < tagStack.size(); j++) {
|
|
if (tag[1].isMatchTo((String) tagStack.elementAt(j),
|
|
(XAttributeList) attrStack.elementAt(j))) {
|
|
|
|
isInStack = true ;
|
|
break ;
|
|
}
|
|
}
|
|
if (isInStack) {
|
|
tags.remove(i--) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tagStack.add(0, name) ;
|
|
attrStack.add(0, new AttributeList(attr));
|
|
} catch (Exception e) {
|
|
e.printStackTrace(log);
|
|
}
|
|
}
|
|
|
|
public void characters(String ch) {
|
|
super.characters(ch) ;
|
|
ch.trim();
|
|
for (int i = 0; i < chars.size(); i++) {
|
|
Object[] chr = (Object[]) chars.elementAt(i);
|
|
if (((String) chr[0]).equals(ch)) {
|
|
if (chr[1] == null) {
|
|
chars.remove(i--);
|
|
} else {
|
|
boolean isInStack = false ;
|
|
for (int j = 0; j < tagStack.size(); j++) {
|
|
if (((Tag) chr[1]).isMatchTo((String) tagStack.elementAt(j),
|
|
(XAttributeList) attrStack.elementAt(j))) {
|
|
|
|
isInStack = true ;
|
|
break ;
|
|
}
|
|
}
|
|
if (isInStack) {
|
|
chars.remove(i--) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void endElement(String name) {
|
|
try {
|
|
super.endElement(name);
|
|
|
|
if (tagStack.size() > 0) {
|
|
tagStack.remove(0) ;
|
|
attrStack.remove(0) ;
|
|
}
|
|
} catch(Exception e) {
|
|
e.printStackTrace(log) ;
|
|
}
|
|
}
|
|
|
|
public boolean check() {
|
|
if (tags.size()> 0) {
|
|
log.println("!!! Error: Some tags were not found :") ;
|
|
for (int i = 0; i < tags.size(); i++) {
|
|
Tag[] tag = (Tag[]) tags.elementAt(i) ;
|
|
log.println(" Tag " + tag[0] + " was not found");
|
|
if (tag[1] != null)
|
|
log.println(" inside tag " + tag[1]) ;
|
|
}
|
|
}
|
|
if (chars.size() > 0) {
|
|
log.println("!!! Error: Some character data blocks were not found :") ;
|
|
for (int i = 0; i < chars.size(); i++) {
|
|
Object[] ch = (Object[]) chars.elementAt(i) ;
|
|
log.println(" Character data \"" + ch[0] + "\" was not found ") ;
|
|
if (ch[1] != null)
|
|
log.println(" inside tag " + ch[1]) ;
|
|
}
|
|
}
|
|
|
|
if (!isWellFormed())
|
|
log.println("!!! Some errors were found in XML structure") ;
|
|
|
|
boolean result = tags.size() == 0 && chars.size() == 0 && isWellFormed();
|
|
reset();
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates <code>XDocumentHandler</code> implementation in form
|
|
* of <code>com.sun.star.xml.sax.Writer</code> service, which
|
|
* writes XML data into a <code>com.sun.star.io.Pipe</code>
|
|
* created.
|
|
* @return Single element array which contains the handler
|
|
* contained in <code>Any</code> structure.
|
|
*/
|
|
public static Object[] getDocumentHandler(XMultiServiceFactory xMSF) {
|
|
Object[] ret = new Object[1];
|
|
try {
|
|
XInterface Writer = (XInterface) xMSF.createInstance(
|
|
"com.sun.star.xml.sax.Writer");
|
|
XInterface oPipe = (XInterface) xMSF.createInstance
|
|
( "com.sun.star.io.Pipe" );
|
|
XOutputStream xPipeOutput = (XOutputStream) UnoRuntime.
|
|
queryInterface(XOutputStream.class, oPipe) ;
|
|
|
|
XActiveDataSource xADS = (XActiveDataSource)
|
|
UnoRuntime.queryInterface(XActiveDataSource.class,Writer);
|
|
xADS.setOutputStream(xPipeOutput);
|
|
XDocumentHandler handler = (XDocumentHandler)
|
|
UnoRuntime.queryInterface(XDocumentHandler.class,Writer);
|
|
|
|
Any arg = new Any(new Type(XDocumentHandler.class),handler);
|
|
|
|
ret[0] = arg;
|
|
} catch (com.sun.star.uno.Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public static PropertyValue[] createMediaDescriptor(String[] propNames, Object[] values) {
|
|
PropertyValue[] props = new PropertyValue[propNames.length] ;
|
|
|
|
for (int i = 0; i < props.length; i++) {
|
|
props[i] = new PropertyValue() ;
|
|
props[i].Name = propNames[i] ;
|
|
if (values != null && i < values.length) {
|
|
props[i].Value = values[i] ;
|
|
}
|
|
}
|
|
|
|
return props ;
|
|
}
|
|
|
|
/**
|
|
* Gets the hanlder, which writes all the XML data passed to the
|
|
* file specified.
|
|
* @param xMSF Soffice <code>ServiceManager</code> factory.
|
|
* @param fileURL The file URL (in form file:///<path>) to which
|
|
* XML data is written.
|
|
* @return SAX handler to which XML data has to be written.
|
|
*/
|
|
public static XDocumentHandler getFileXMLWriter(XMultiServiceFactory xMSF, String fileURL)
|
|
throws com.sun.star.uno.Exception
|
|
{
|
|
XInterface oFacc = (XInterface)xMSF.createInstance(
|
|
"com.sun.star.comp.ucb.SimpleFileAccess");
|
|
XSimpleFileAccess xFacc = (XSimpleFileAccess)UnoRuntime.queryInterface
|
|
(XSimpleFileAccess.class, oFacc) ;
|
|
|
|
XInterface oWriter = (XInterface)xMSF.createInstance(
|
|
"com.sun.star.xml.sax.Writer");
|
|
XActiveDataSource xWriterDS = (XActiveDataSource)
|
|
UnoRuntime.queryInterface(XActiveDataSource.class, oWriter);
|
|
XDocumentHandler xDocHandWriter = (XDocumentHandler) UnoRuntime.queryInterface
|
|
(XDocumentHandler.class, oWriter) ;
|
|
|
|
if (xFacc.exists(fileURL))
|
|
xFacc.kill(fileURL);
|
|
XOutputStream fOut = xFacc.openFileWrite(fileURL) ;
|
|
xWriterDS.setOutputStream(fOut);
|
|
|
|
return xDocHandWriter ;
|
|
}
|
|
|
|
/**
|
|
* Parses XML file and passes its data to the SAX handler specified.
|
|
* @param xMSF Soffice <code>ServiceManager</code> factory.
|
|
* @param fileURL XML file name (in form file:///<path>) to be parsed.
|
|
* @param handler SAX handler to which XML data from file will
|
|
* be transferred.
|
|
*/
|
|
public static void parseXMLFile(XMultiServiceFactory xMSF,
|
|
String fileURL, XDocumentHandler handler) throws com.sun.star.uno.Exception
|
|
{
|
|
XInterface oFacc = (XInterface)xMSF.createInstance(
|
|
"com.sun.star.comp.ucb.SimpleFileAccess");
|
|
XSimpleFileAccess xFacc = (XSimpleFileAccess)UnoRuntime.queryInterface
|
|
(XSimpleFileAccess.class, oFacc) ;
|
|
XInputStream oIn = xFacc.openFileRead(fileURL) ;
|
|
|
|
XInterface oParser = (XInterface)xMSF.createInstance(
|
|
"com.sun.star.xml.sax.Parser");
|
|
XParser xParser = (XParser) UnoRuntime.queryInterface(XParser.class, oParser);
|
|
|
|
xParser.setDocumentHandler(handler) ;
|
|
InputSource inSrc = new InputSource() ;
|
|
inSrc.aInputStream = oIn ;
|
|
xParser.parseStream(inSrc) ;
|
|
|
|
oIn.closeInput();
|
|
}
|
|
|
|
/**
|
|
* Exports document (the whole or a part) into the file specified
|
|
* in XML format.
|
|
* @param xMSF Soffice <code>ServiceManager</code> factory.
|
|
* @param xDoc Document to be exported.
|
|
* @param docType Type of document (for example 'Calc', 'Writer', 'Draw')
|
|
* The type must start with <b>capital</b> letter.
|
|
* @param exportType The type of export specifies if the whole
|
|
* document will be exported or one of its parts (Meta info, Styles, etc.).
|
|
* The following types supported (it also depends of document type) :
|
|
* "" (empty string) - for the whole document ;
|
|
* "Content" - only content exported ;
|
|
* "Meta" - meta document info exported ;
|
|
* "Settings" - view settings of document exported ;
|
|
* "Styles" - document styles exported ;
|
|
* @param fileURL XML file name (in form file:///<path>) to be exported to.
|
|
*/
|
|
public static void exportDocument(XMultiServiceFactory xMSF, XComponent xDoc,
|
|
String docType, String exportType, String fileURL)
|
|
throws com.sun.star.uno.Exception {
|
|
|
|
XDocumentHandler xDocHandWriter = XMLTools.getFileXMLWriter(xMSF, fileURL) ;
|
|
|
|
Any arg = new Any(new Type(XDocumentHandler.class), xDocHandWriter);
|
|
XInterface oExp = (XInterface)xMSF.createInstanceWithArguments(
|
|
"com.sun.star.comp." + docType + ".XML" + exportType + "Exporter",
|
|
new Object[] {arg});
|
|
|
|
XExporter xExp = (XExporter) UnoRuntime.queryInterface
|
|
(XExporter.class, oExp) ;
|
|
xExp.setSourceDocument(xDoc) ;
|
|
|
|
XFilter filter = (XFilter) UnoRuntime.queryInterface(XFilter.class, oExp) ;
|
|
filter.filter(XMLTools.createMediaDescriptor(
|
|
new String[] {"FilterName"},
|
|
new Object[] {"Custom filter"})) ;
|
|
}
|
|
|
|
/**
|
|
* Imports document (the whole or a part) from the file specified
|
|
* in XML format.
|
|
* @param xMSF Soffice <code>ServiceManager</code> factory.
|
|
* @param xDoc Target document to be imported.
|
|
* @param docType Type of document (for example 'Calc', 'Writer', 'Draw')
|
|
* The type must start with <b>capital</b> letter.
|
|
* @param exportType The type of export specifies if the whole
|
|
* document will be exported or one of its parts (Meta info, Styles, etc.).
|
|
* The following types supported (it hardly depends of XML data in file) :
|
|
* "" (empty string) - for the whole document ;
|
|
* "Content" - only content exported ;
|
|
* "Meta" - meta document info exported ;
|
|
* "Settings" - view settings of document exported ;
|
|
* "Styles" - document styles exported ;
|
|
* @param fileURL XML file name (in form file:///<path>) to be imported from.
|
|
*/
|
|
public static void importDocument(XMultiServiceFactory xMSF, XComponent xDoc,
|
|
String docType, String importType, String fileURL)
|
|
throws com.sun.star.uno.Exception {
|
|
|
|
XInterface oImp = (XInterface)xMSF.createInstance(
|
|
"com.sun.star.comp." + docType + ".XML" + importType + "Importer");
|
|
XImporter xImp = (XImporter) UnoRuntime.queryInterface
|
|
(XImporter.class, oImp) ;
|
|
XDocumentHandler xDocHandImp = (XDocumentHandler) UnoRuntime.queryInterface
|
|
(XDocumentHandler.class, oImp) ;
|
|
|
|
xImp.setTargetDocument(xDoc) ;
|
|
parseXMLFile(xMSF, fileURL, xDocHandImp) ;
|
|
}
|
|
} |