diff options
author | andrew <devnull@localhost> | 2010-10-19 17:55:59 +0100 |
---|---|---|
committer | andrew <devnull@localhost> | 2010-10-19 17:55:59 +0100 |
commit | 7603e948d7a0a7eb2e72358cb4a40ae6779f95da (patch) | |
tree | c6441f7d14eafe8119d890cddd09b05b8f88c52a /netx/net/sourceforge/nanoxml |
Initial import from IcedTea6.
2010-10-19 Andrew John Hughes <[email protected]>
* .hgignore,
* Makefile.am,
* acinclude.m4,
* autogen.sh,
* configure.ac,
* extra/net/sourceforge/jnlp/about/HTMLPanel.java,
* extra/net/sourceforge/jnlp/about/Main.java,
* extra/net/sourceforge/jnlp/about/resources/about.html,
* extra/net/sourceforge/jnlp/about/resources/applications.html,
* extra/net/sourceforge/jnlp/about/resources/notes.html,
* javac.in,
* javaws.desktop: Imported from IcedTea6.
* launcher/java.c,
* launcher/java.h,
* launcher/java_md.c,
* launcher/java_md.h,
* launcher/jli_util.h,
* launcher/jni.h,
* launcher/jvm.h,
* launcher/jvm_md.h,
* launcher/manifest_info.h,
* launcher/splashscreen.h,
* launcher/splashscreen_stubs.c,
* launcher/version_comp.h,
* launcher/wildcard.h: Imported from OpenJDK.
* netx/javaws.1,
* netx/javax/jnlp/BasicService.java,
* netx/javax/jnlp/ClipboardService.java,
* netx/javax/jnlp/DownloadService.java,
* netx/javax/jnlp/DownloadServiceListener.java,
* netx/javax/jnlp/ExtendedService.java,
* netx/javax/jnlp/ExtensionInstallerService.java,
* netx/javax/jnlp/FileContents.java,
* netx/javax/jnlp/FileOpenService.java,
* netx/javax/jnlp/FileSaveService.java,
* netx/javax/jnlp/JNLPRandomAccessFile.java,
* netx/javax/jnlp/PersistenceService.java,
* netx/javax/jnlp/PrintService.java,
* netx/javax/jnlp/ServiceManager.java,
* netx/javax/jnlp/ServiceManagerStub.java,
* netx/javax/jnlp/SingleInstanceListener.java,
* netx/javax/jnlp/SingleInstanceService.java,
* netx/javax/jnlp/UnavailableServiceException.java,
* netx/net/sourceforge/jnlp/AppletDesc.java,
* netx/net/sourceforge/jnlp/ApplicationDesc.java,
* netx/net/sourceforge/jnlp/AssociationDesc.java,
* netx/net/sourceforge/jnlp/ComponentDesc.java,
* netx/net/sourceforge/jnlp/DefaultLaunchHandler.java,
* netx/net/sourceforge/jnlp/ExtensionDesc.java,
* netx/net/sourceforge/jnlp/IconDesc.java,
* netx/net/sourceforge/jnlp/InformationDesc.java,
* netx/net/sourceforge/jnlp/InstallerDesc.java,
* netx/net/sourceforge/jnlp/JARDesc.java,
* netx/net/sourceforge/jnlp/JNLPFile.java,
* netx/net/sourceforge/jnlp/JNLPSplashScreen.java,
* netx/net/sourceforge/jnlp/JREDesc.java,
* netx/net/sourceforge/jnlp/LaunchException.java,
* netx/net/sourceforge/jnlp/LaunchHandler.java,
* netx/net/sourceforge/jnlp/Launcher.java,
* netx/net/sourceforge/jnlp/MenuDesc.java,
* netx/net/sourceforge/jnlp/NetxPanel.java,
* netx/net/sourceforge/jnlp/Node.java,
* netx/net/sourceforge/jnlp/PackageDesc.java,
* netx/net/sourceforge/jnlp/ParseException.java,
* netx/net/sourceforge/jnlp/Parser.java,
* netx/net/sourceforge/jnlp/PluginBridge.java,
* netx/net/sourceforge/jnlp/PropertyDesc.java,
* netx/net/sourceforge/jnlp/RelatedContentDesc.java,
* netx/net/sourceforge/jnlp/ResourcesDesc.java,
* netx/net/sourceforge/jnlp/SecurityDesc.java,
* netx/net/sourceforge/jnlp/ShortcutDesc.java,
* netx/net/sourceforge/jnlp/StreamEater.java,
* netx/net/sourceforge/jnlp/UpdateDesc.java,
* netx/net/sourceforge/jnlp/Version.java,
* netx/net/sourceforge/jnlp/cache/CacheEntry.java,
* netx/net/sourceforge/jnlp/cache/CacheUtil.java,
* netx/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java,
* netx/net/sourceforge/jnlp/cache/DownloadIndicator.java,
* netx/net/sourceforge/jnlp/cache/Resource.java,
* netx/net/sourceforge/jnlp/cache/ResourceTracker.java,
* netx/net/sourceforge/jnlp/cache/UpdatePolicy.java,
* netx/net/sourceforge/jnlp/cache/package.html,
* netx/net/sourceforge/jnlp/event/ApplicationEvent.java,
* netx/net/sourceforge/jnlp/event/ApplicationListener.java,
* netx/net/sourceforge/jnlp/event/DownloadEvent.java,
* netx/net/sourceforge/jnlp/event/DownloadListener.java,
* netx/net/sourceforge/jnlp/event/package.html,
* netx/net/sourceforge/jnlp/package.html,
* netx/net/sourceforge/jnlp/resources/Manifest.mf,
* netx/net/sourceforge/jnlp/resources/Messages.properties,
* netx/net/sourceforge/jnlp/resources/about.jnlp,
* netx/net/sourceforge/jnlp/resources/default.jnlp,
* netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java,
* netx/net/sourceforge/jnlp/runtime/AppletAudioClip.java,
* netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java,
* netx/net/sourceforge/jnlp/runtime/AppletInstance.java,
* netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java,
* netx/net/sourceforge/jnlp/runtime/Boot.java,
* netx/net/sourceforge/jnlp/runtime/Boot13.java,
* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java,
* netx/net/sourceforge/jnlp/runtime/JNLPPolicy.java,
* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java,
* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java,
* netx/net/sourceforge/jnlp/runtime/package.html,
* netx/net/sourceforge/jnlp/security/AccessWarningPane.java,
* netx/net/sourceforge/jnlp/security/AppletWarningPane.java,
* netx/net/sourceforge/jnlp/security/CertVerifier.java,
* netx/net/sourceforge/jnlp/security/CertWarningPane.java,
* netx/net/sourceforge/jnlp/security/CertsInfoPane.java,
* netx/net/sourceforge/jnlp/security/HttpsCertVerifier.java,
* netx/net/sourceforge/jnlp/security/MoreInfoPane.java,
* netx/net/sourceforge/jnlp/security/NotAllSignedWarningPane.java,
* netx/net/sourceforge/jnlp/security/SecurityDialogPanel.java,
* netx/net/sourceforge/jnlp/security/SecurityUtil.java,
* netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java,
* netx/net/sourceforge/jnlp/security/SingleCertInfoPane.java,
* netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java,
* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java,
* netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java,
* netx/net/sourceforge/jnlp/services/ExtendedSingleInstanceService.java,
* netx/net/sourceforge/jnlp/services/InstanceExistsException.java,
* netx/net/sourceforge/jnlp/services/ServiceUtil.java,
* netx/net/sourceforge/jnlp/services/SingleInstanceLock.java,
* netx/net/sourceforge/jnlp/services/XBasicService.java,
* netx/net/sourceforge/jnlp/services/XClipboardService.java,
* netx/net/sourceforge/jnlp/services/XDownloadService.java,
* netx/net/sourceforge/jnlp/services/XExtendedService.java,
* netx/net/sourceforge/jnlp/services/XExtensionInstallerService.java,
* netx/net/sourceforge/jnlp/services/XFileContents.java,
* netx/net/sourceforge/jnlp/services/XFileOpenService.java,
* netx/net/sourceforge/jnlp/services/XFileSaveService.java,
* netx/net/sourceforge/jnlp/services/XJNLPRandomAccessFile.java,
* netx/net/sourceforge/jnlp/services/XPersistenceService.java,
* netx/net/sourceforge/jnlp/services/XPrintService.java,
* netx/net/sourceforge/jnlp/services/XServiceManagerStub.java,
* netx/net/sourceforge/jnlp/services/XSingleInstanceService.java,
* netx/net/sourceforge/jnlp/services/package.html,
* netx/net/sourceforge/jnlp/tools/CharacterEncoder.java,
* netx/net/sourceforge/jnlp/tools/HexDumpEncoder.java,
* netx/net/sourceforge/jnlp/tools/JarRunner.java,
* netx/net/sourceforge/jnlp/tools/JarSigner.java,
* netx/net/sourceforge/jnlp/tools/JarSignerResources.java,
* netx/net/sourceforge/jnlp/tools/KeyStoreUtil.java,
* netx/net/sourceforge/jnlp/tools/KeyTool.java,
* netx/net/sourceforge/jnlp/util/FileUtils.java,
* netx/net/sourceforge/jnlp/util/PropertiesFile.java,
* netx/net/sourceforge/jnlp/util/Reflect.java,
* netx/net/sourceforge/jnlp/util/WeakList.java,
* netx/net/sourceforge/jnlp/util/XDesktopEntry.java,
* netx/net/sourceforge/nanoxml/XMLElement.java,
* netx/net/sourceforge/nanoxml/XMLParseException.java,
* plugin/icedteanp/IcedTeaJavaRequestProcessor.cc,
* plugin/icedteanp/IcedTeaJavaRequestProcessor.h,
* plugin/icedteanp/IcedTeaNPPlugin.cc,
* plugin/icedteanp/IcedTeaNPPlugin.h,
* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc,
* plugin/icedteanp/IcedTeaPluginRequestProcessor.h,
* plugin/icedteanp/IcedTeaPluginUtils.cc,
* plugin/icedteanp/IcedTeaPluginUtils.h,
* plugin/icedteanp/IcedTeaRunnable.cc,
* plugin/icedteanp/IcedTeaRunnable.h,
* plugin/icedteanp/IcedTeaScriptablePluginObject.cc,
* plugin/icedteanp/IcedTeaScriptablePluginObject.h,
* plugin/icedteanp/java/netscape/javascript/JSException.java,
* plugin/icedteanp/java/netscape/javascript/JSObject.java,
* plugin/icedteanp/java/netscape/javascript/JSObjectCreatePermission.java,
* plugin/icedteanp/java/netscape/javascript/JSProxy.java,
* plugin/icedteanp/java/netscape/javascript/JSRunnable.java,
* plugin/icedteanp/java/netscape/javascript/JSUtil.java,
* plugin/icedteanp/java/netscape/security/ForbiddenTargetException.java,
* plugin/icedteanp/java/sun/applet/AppletSecurityContextManager.java,
* plugin/icedteanp/java/sun/applet/GetMemberPluginCallRequest.java,
* plugin/icedteanp/java/sun/applet/GetWindowPluginCallRequest.java,
* plugin/icedteanp/java/sun/applet/JavaConsole.java,
* plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java,
* plugin/icedteanp/java/sun/applet/PasswordAuthenticationDialog.java,
* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java,
* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java,
* plugin/icedteanp/java/sun/applet/PluginCallRequest.java,
* plugin/icedteanp/java/sun/applet/PluginCallRequestFactory.java,
* plugin/icedteanp/java/sun/applet/PluginClassLoader.java,
* plugin/icedteanp/java/sun/applet/PluginCookieInfoRequest.java,
* plugin/icedteanp/java/sun/applet/PluginCookieManager.java,
* plugin/icedteanp/java/sun/applet/PluginDebug.java,
* plugin/icedteanp/java/sun/applet/PluginException.java,
* plugin/icedteanp/java/sun/applet/PluginMain.java,
* plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java,
* plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java,
* plugin/icedteanp/java/sun/applet/PluginObjectStore.java,
* plugin/icedteanp/java/sun/applet/PluginProxyInfoRequest.java,
* plugin/icedteanp/java/sun/applet/PluginProxySelector.java,
* plugin/icedteanp/java/sun/applet/PluginStreamHandler.java,
* plugin/icedteanp/java/sun/applet/RequestQueue.java,
* plugin/icedteanp/java/sun/applet/TestEnv.java,
* plugin/icedteanp/java/sun/applet/VoidPluginCallRequest.java,
* plugin/tests/LiveConnect/DummyObject.java,
* plugin/tests/LiveConnect/OverloadTestHelper1.java,
* plugin/tests/LiveConnect/OverloadTestHelper2.java,
* plugin/tests/LiveConnect/OverloadTestHelper3.java,
* plugin/tests/LiveConnect/PluginTest.java,
* plugin/tests/LiveConnect/build,
* plugin/tests/LiveConnect/common.js,
* plugin/tests/LiveConnect/index.html,
* plugin/tests/LiveConnect/jjs_eval_test.js,
* plugin/tests/LiveConnect/jjs_func_parameters_tests.js,
* plugin/tests/LiveConnect/jjs_func_rettype_tests.js,
* plugin/tests/LiveConnect/jjs_get_tests.js,
* plugin/tests/LiveConnect/jjs_set_tests.js,
* plugin/tests/LiveConnect/jsj_func_overload_tests.js,
* plugin/tests/LiveConnect/jsj_func_parameters_tests.js,
* plugin/tests/LiveConnect/jsj_func_rettype_tests.js,
* plugin/tests/LiveConnect/jsj_get_tests.js,
* plugin/tests/LiveConnect/jsj_set_tests.js,
* plugin/tests/LiveConnect/jsj_type_casting_tests.js,
* plugin/tests/LiveConnect/jsj_type_conversion_tests.js:
Initial import from IcedTea6.
* AUTHORS,
* COPYING
* INSTALL,
* NEWS,
* README: New documentation.
Diffstat (limited to 'netx/net/sourceforge/nanoxml')
-rw-r--r-- | netx/net/sourceforge/nanoxml/XMLElement.java | 1334 | ||||
-rw-r--r-- | netx/net/sourceforge/nanoxml/XMLParseException.java | 130 |
2 files changed, 1464 insertions, 0 deletions
diff --git a/netx/net/sourceforge/nanoxml/XMLElement.java b/netx/net/sourceforge/nanoxml/XMLElement.java new file mode 100644 index 0000000..520136e --- /dev/null +++ b/netx/net/sourceforge/nanoxml/XMLElement.java @@ -0,0 +1,1334 @@ +/* XMLElement.java + * + * $Revision: 1.2 $ + * $Date: 2002/08/03 04:36:34 $ + * $Name: $ + * + * This file is part of NanoXML 2 Lite. + * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from the + * use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in + * a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + *****************************************************************************/ + +/* JAM: hacked the source to remove unneeded methods and comments. */ + +package net.sourceforge.nanoxml; + +import java.io.*; +import java.util.*; + +import net.sourceforge.jnlp.runtime.JNLPRuntime; + + +/** + * XMLElement is a representation of an XML object. The object is able to parse + * XML code. + * <P><DL> + * <DT><B>Parsing XML Data</B></DT> + * <DD> + * You can parse XML data using the following code: + * <UL><CODE> + * XMLElement xml = new XMLElement();<BR> + * FileReader reader = new FileReader("filename.xml");<BR> + * xml.parseFromReader(reader); + * </CODE></UL></DD></DL> + * <DL><DT><B>Retrieving Attributes</B></DT> + * <DD> + * You can enumerate the attributes of an element using the method + * {@link #enumerateAttributeNames() enumerateAttributeNames}. + * The attribute values can be retrieved using the method + * {@link #getStringAttribute(java.lang.String) getStringAttribute}. + * The following example shows how to list the attributes of an element: + * <UL><CODE> + * XMLElement element = ...;<BR> + * Enumeration enum = element.getAttributeNames();<BR> + * while (enum.hasMoreElements()) {<BR> + * String key = (String) enum.nextElement();<BR> + * String value = element.getStringAttribute(key);<BR> + * System.out.println(key + " = " + value);<BR> + * } + * </CODE></UL></DD></DL> + * <DL><DT><B>Retrieving Child Elements</B></DT> + * <DD> + * You can enumerate the children of an element using + * {@link #enumerateChildren() enumerateChildren}. + * The number of child elements can be retrieved using + * {@link #countChildren() countChildren}. + * </DD></DL> + * <DL><DT><B>Elements Containing Character Data</B></DT> + * <DD> + * If an elements contains character data, like in the following example: + * <UL><CODE> + * <title>The Title</title> + * </CODE></UL> + * you can retrieve that data using the method + * {@link #getContent() getContent}. + * </DD></DL> + * <DL><DT><B>Subclassing XMLElement</B></DT> + * <DD> + * When subclassing XMLElement, you need to override the method + * {@link #createAnotherElement() createAnotherElement} + * which has to return a new copy of the receiver. + * </DD></DL> + * <P> + * + * @see net.sourceforge.nanoxml.XMLParseException + * + * @author Marc De Scheemaecker + * <<A href="mailto:[email protected]">[email protected]</A>> + * @version $Name: $, $Revision: 1.2 $ + */ +public class XMLElement +{ + + /** + * The attributes given to the element. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li>The field can be empty. + * <li>The field is never <code>null</code>. + * <li>The keys and the values are strings. + * </ul></dd></dl> + */ + private Hashtable attributes; + + + /** + * Child elements of the element. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li>The field can be empty. + * <li>The field is never <code>null</code>. + * <li>The elements are instances of <code>XMLElement</code> + * or a subclass of <code>XMLElement</code>. + * </ul></dd></dl> + */ + private Vector children; + + + /** + * The name of the element. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li>The field is <code>null</code> iff the element is not + * initialized by either parse or setName. + * <li>If the field is not <code>null</code>, it's not empty. + * <li>If the field is not <code>null</code>, it contains a valid + * XML identifier. + * </ul></dd></dl> + */ + private String name; + + + /** + * The #PCDATA content of the object. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li>The field is <code>null</code> iff the element is not a + * #PCDATA element. + * <li>The field can be any string, including the empty string. + * </ul></dd></dl> + */ + private String contents; + + + /** + * Conversion table for &...; entities. The keys are the entity names + * without the & and ; delimiters. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li>The field is never <code>null</code>. + * <li>The field always contains the following associations: + * "lt" => "<", "gt" => ">", + * "quot" => "\"", "apos" => "'", + * "amp" => "&" + * <li>The keys are strings + * <li>The values are char arrays + * </ul></dd></dl> + */ + private Hashtable entities; + + + /** + * The line number where the element starts. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li><code>lineNr >= 0</code> + * </ul></dd></dl> + */ + private int lineNr; + + + /** + * <code>true</code> if the case of the element and attribute names + * are case insensitive. + */ + private boolean ignoreCase; + + + /** + * <code>true</code> if the leading and trailing whitespace of #PCDATA + * sections have to be ignored. + */ + private boolean ignoreWhitespace; + + + /** + * Character read too much. + * This character provides push-back functionality to the input reader + * without having to use a PushbackReader. + * If there is no such character, this field is '\0'. + */ + private char charReadTooMuch; + + /** + * Character read too much for the comment remover. + */ + private char sanitizeCharReadTooMuch; + + /** + * The reader provided by the caller of the parse method. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li>The field is not <code>null</code> while the parse method + * is running. + * </ul></dd></dl> + */ + private Reader reader; + + + /** + * The current line number in the source content. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li>parserLineNr > 0 while the parse method is running. + * </ul></dd></dl> + */ + private int parserLineNr; + + + /** + * Creates and initializes a new XML element. + * Calling the construction is equivalent to: + * <ul><code>new XMLElement(new Hashtable(), false, true) + * </code></ul> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>countChildren() => 0 + * <li>enumerateChildren() => empty enumeration + * <li>enumeratePropertyNames() => empty enumeration + * <li>getChildren() => empty vector + * <li>getContent() => "" + * <li>getLineNr() => 0 + * <li>getName() => null + * </ul></dd></dl> + * + */ + public XMLElement() + { + this(new Hashtable(), false, true, true); + } + + + /** + * Creates and initializes a new XML element. + * <P> + * This constructor should <I>only</I> be called from + * {@link #createAnotherElement() createAnotherElement} + * to create child elements. + * + * @param entities + * The entity conversion table. + * @param skipLeadingWhitespace + * <code>true</code> if leading and trailing whitespace in PCDATA + * content has to be removed. + * @param fillBasicConversionTable + * <code>true</code> if the basic entities need to be added to + * the entity list (client code calling this constructor). + * @param ignoreCase + * <code>true</code> if the case of element and attribute names have + * to be ignored. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>entities != null</code> + * <li>if <code>fillBasicConversionTable == false</code> + * then <code>entities</code> contains at least the following + * entries: <code>amp</code>, <code>lt</code>, <code>gt</code>, + * <code>apos</code> and <code>quot</code> + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>countChildren() => 0 + * <li>enumerateChildren() => empty enumeration + * <li>enumeratePropertyNames() => empty enumeration + * <li>getChildren() => empty vector + * <li>getContent() => "" + * <li>getLineNr() => 0 + * <li>getName() => null + * </ul></dd></dl><dl> + * + */ + protected XMLElement(Hashtable entities, + boolean skipLeadingWhitespace, + boolean fillBasicConversionTable, + boolean ignoreCase) + { + this.ignoreWhitespace = skipLeadingWhitespace; + this.ignoreCase = ignoreCase; + this.name = null; + this.contents = ""; + this.attributes = new Hashtable(); + this.children = new Vector(); + this.entities = entities; + this.lineNr = 0; + Enumeration e = this.entities.keys(); + while (e.hasMoreElements()) { + Object key = e.nextElement(); + Object value = this.entities.get(key); + if (value instanceof String) { + value = ((String) value).toCharArray(); + this.entities.put(key, value); + } + } + if (fillBasicConversionTable) { + this.entities.put("amp", new char[] { '&' }); + this.entities.put("quot", new char[] { '"' }); + this.entities.put("apos", new char[] { '\'' }); + this.entities.put("lt", new char[] { '<' }); + this.entities.put("gt", new char[] { '>' }); + } + } + + + /** + * Adds a child element. + * + * @param child + * The child element to add. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>child != null</code> + * <li><code>child.getName() != null</code> + * <li><code>child</code> does not have a parent element + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>countChildren() => old.countChildren() + 1 + * <li>enumerateChildren() => old.enumerateChildren() + child + * <li>getChildren() => old.enumerateChildren() + child + * </ul></dd></dl><dl> + * + */ + public void addChild(XMLElement child) + { + this.children.addElement(child); + } + + + /** + * Adds or modifies an attribute. + * + * @param name + * The name of the attribute. + * @param value + * The value of the attribute. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>name != null</code> + * <li><code>name</code> is a valid XML identifier + * <li><code>value != null</code> + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>enumerateAttributeNames() + * => old.enumerateAttributeNames() + name + * <li>getAttribute(name) => value + * </ul></dd></dl><dl> + * + */ + public void setAttribute(String name, + Object value) + { + if (this.ignoreCase) { + name = name.toUpperCase(); + } + this.attributes.put(name, value.toString()); + } + + + /** + * Returns the number of child elements of the element. + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li><code>result >= 0</code> + * </ul></dd></dl> + * + */ + public int countChildren() + { + return this.children.size(); + } + + + /** + * Enumerates the attribute names. + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li><code>result != null</code> + * </ul></dd></dl> + * + */ + public Enumeration enumerateAttributeNames() + { + return this.attributes.keys(); + } + + + /** + * Enumerates the child elements. + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li><code>result != null</code> + * </ul></dd></dl> + * + */ + public Enumeration enumerateChildren() + { + return this.children.elements(); + } + + + /** + * Returns the PCDATA content of the object. If there is no such content, + * <CODE>null</CODE> is returned. + * + */ + public String getContent() + { + return this.contents; + } + + + /** + * Returns the line nr in the source data on which the element is found. + * This method returns <code>0</code> there is no associated source data. + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li><code>result >= 0</code> + * </ul></dd></dl> + */ + public int getLineNr() + { + return this.lineNr; + } + + + /** + * Returns an attribute of the element. + * If the attribute doesn't exist, <code>null</code> is returned. + * + * @param name The name of the attribute. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>name != null</code> + * <li><code>name</code> is a valid XML identifier + * </ul></dd></dl><dl> + * + */ + public Object getAttribute(String name) + { + if (this.ignoreCase) { + name = name.toUpperCase(); + } + Object value = this.attributes.get(name); + return value; + } + + + /** + * Returns the name of the element. + * + */ + public String getName() + { + return this.name; + } + + + /** + * Reads one XML element from a java.io.Reader and parses it. + * + * @param reader + * The reader from which to retrieve the XML data. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>reader != null</code> + * <li><code>reader</code> is not closed + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>the state of the receiver is updated to reflect the XML element + * parsed from the reader + * <li>the reader points to the first character following the last + * '>' character of the XML element + * </ul></dd></dl><dl> + * + * @throws java.io.IOException + * If an error occured while reading the input. + * @throws net.sourceforge.nanoxml.XMLParseException + * If an error occured while parsing the read data. + */ + public void parseFromReader(Reader reader) + throws IOException, XMLParseException + { + this.parseFromReader(reader, /*startingLineNr*/ 1); + } + + + /** + * Reads one XML element from a java.io.Reader and parses it. + * + * @param reader + * The reader from which to retrieve the XML data. + * @param startingLineNr + * The line number of the first line in the data. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>reader != null</code> + * <li><code>reader</code> is not closed + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>the state of the receiver is updated to reflect the XML element + * parsed from the reader + * <li>the reader points to the first character following the last + * '>' character of the XML element + * </ul></dd></dl><dl> + * + * @throws java.io.IOException + * If an error occured while reading the input. + * @throws net.sourceforge.nanoxml.XMLParseException + * If an error occured while parsing the read data. + */ + public void parseFromReader(Reader reader, + int startingLineNr) + throws IOException, XMLParseException + { + this.charReadTooMuch = '\0'; + this.reader = reader; + this.parserLineNr = startingLineNr; + + for (;;) { + char ch = this.scanWhitespace(); + + if (ch != '<') { + throw this.expectedInput("<", ch); + } + + ch = this.readChar(); + + if ((ch == '!') || (ch == '?')) { + this.skipSpecialTag(0); + } else { + this.unreadChar(ch); + this.scanElement(this); + return; + } + } + } + + + /** + * Creates a new similar XML element. + * <P> + * You should override this method when subclassing XMLElement. + */ + protected XMLElement createAnotherElement() + { + return new XMLElement(this.entities, + this.ignoreWhitespace, + false, + this.ignoreCase); + } + + + /** + * Changes the content string. + * + * @param content + * The new content string. + */ + public void setContent(String content) + { + this.contents = content; + } + + + /** + * Changes the name of the element. + * + * @param name + * The new name. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>name != null</code> + * <li><code>name</code> is a valid XML identifier + * </ul></dd></dl> + * + */ + public void setName(String name) + { + this.name = name; + } + + + /** + * Scans an identifier from the current reader. + * The scanned identifier is appended to <code>result</code>. + * + * @param result + * The buffer in which the scanned identifier will be put. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>result != null</code> + * <li>The next character read from the reader is a valid first + * character of an XML identifier. + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>The next character read from the reader won't be an identifier + * character. + * </ul></dd></dl><dl> + */ + protected void scanIdentifier(StringBuffer result) + throws IOException + { + for (;;) { + char ch = this.readChar(); + if (((ch < 'A') || (ch > 'Z')) && ((ch < 'a') || (ch > 'z')) + && ((ch < '0') || (ch > '9')) && (ch != '_') && (ch != '.') + && (ch != ':') && (ch != '-') && (ch <= '\u007E')) { + this.unreadChar(ch); + return; + } + result.append(ch); + } + } + + + /** + * This method scans an identifier from the current reader. + * + * @return the next character following the whitespace. + */ + protected char scanWhitespace() + throws IOException + { + for (;;) { + char ch = this.readChar(); + switch (ch) { + case ' ': + case '\t': + case '\n': + case '\r': + break; + default: + return ch; + } + } + } + + + /** + * This method scans an identifier from the current reader. + * The scanned whitespace is appended to <code>result</code>. + * + * @return the next character following the whitespace. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>result != null</code> + * </ul></dd></dl> + */ + protected char scanWhitespace(StringBuffer result) + throws IOException + { + for (;;) { + char ch = this.readChar(); + switch (ch) { + case ' ': + case '\t': + case '\n': + result.append(ch); + case '\r': + break; + default: + return ch; + } + } + } + + + /** + * This method scans a delimited string from the current reader. + * The scanned string without delimiters is appended to + * <code>string</code>. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>string != null</code> + * <li>the next char read is the string delimiter + * </ul></dd></dl> + */ + protected void scanString(StringBuffer string) + throws IOException + { + char delimiter = this.readChar(); + if ((delimiter != '\'') && (delimiter != '"')) { + throw this.expectedInput("' or \""); + } + for (;;) { + char ch = this.readChar(); + if (ch == delimiter) { + return; + } else if (ch == '&') { + this.resolveEntity(string); + } else { + string.append(ch); + } + } + } + + + /** + * Scans a #PCDATA element. CDATA sections and entities are resolved. + * The next < char is skipped. + * The scanned data is appended to <code>data</code>. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>data != null</code> + * </ul></dd></dl> + */ + protected void scanPCData(StringBuffer data) + throws IOException + { + for (;;) { + char ch = this.readChar(); + if (ch == '<') { + ch = this.readChar(); + if (ch == '!') { + this.checkCDATA(data); + } else { + this.unreadChar(ch); + return; + } + } else if (ch == '&') { + this.resolveEntity(data); + } else { + data.append(ch); + } + } + } + + + /** + * Scans a special tag and if the tag is a CDATA section, append its + * content to <code>buf</code>. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>buf != null</code> + * <li>The first < has already been read. + * </ul></dd></dl> + */ + protected boolean checkCDATA(StringBuffer buf) + throws IOException + { + char ch = this.readChar(); + if (ch != '[') { + this.unreadChar(ch); + this.skipSpecialTag(0); + return false; + } else if (! this.checkLiteral("CDATA[")) { + this.skipSpecialTag(1); // one [ has already been read + return false; + } else { + int delimiterCharsSkipped = 0; + while (delimiterCharsSkipped < 3) { + ch = this.readChar(); + switch (ch) { + case ']': + if (delimiterCharsSkipped < 2) { + delimiterCharsSkipped += 1; + } else { + buf.append(']'); + buf.append(']'); + delimiterCharsSkipped = 0; + } + break; + case '>': + if (delimiterCharsSkipped < 2) { + for (int i = 0; i < delimiterCharsSkipped; i++) { + buf.append(']'); + } + delimiterCharsSkipped = 0; + buf.append('>'); + } else { + delimiterCharsSkipped = 3; + } + break; + default: + for (int i = 0; i < delimiterCharsSkipped; i += 1) { + buf.append(']'); + } + buf.append(ch); + delimiterCharsSkipped = 0; + } + } + return true; + } + } + + + /** + * Skips a comment. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li>The first <!-- has already been read. + * </ul></dd></dl> + */ + protected void skipComment() + throws IOException + { + int dashesToRead = 2; + while (dashesToRead > 0) { + char ch = this.readChar(); + if (ch == '-') { + dashesToRead -= 1; + } else { + dashesToRead = 2; + } + + // Be more tolerant of extra -- (double dashes) + // in comments. + if (dashesToRead == 0) { + ch = this.readChar(); + if (ch == '>') { + return; + } else { + dashesToRead = 2; + this.unreadChar(ch); + } + } + } + /* + if (this.readChar() != '>') { + throw this.expectedInput(">"); + } + */ + } + + + /** + * Skips a special tag or comment. + * + * @param bracketLevel The number of open square brackets ([) that have + * already been read. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li>The first <! has already been read. + * <li><code>bracketLevel >= 0</code> + * </ul></dd></dl> + */ + protected void skipSpecialTag(int bracketLevel) + throws IOException + { + int tagLevel = 1; // < + char stringDelimiter = '\0'; + if (bracketLevel == 0) { + char ch = this.readChar(); + if (ch == '[') { + bracketLevel += 1; + } else if (ch == '-') { + ch = this.readChar(); + if (ch == '[') { + bracketLevel += 1; + } else if (ch == ']') { + bracketLevel -= 1; + } else if (ch == '-') { + this.skipComment(); + return; + } + } + } + while (tagLevel > 0) { + char ch = this.readChar(); + if (stringDelimiter == '\0') { + if ((ch == '"') || (ch == '\'')) { + stringDelimiter = ch; + } else if (bracketLevel <= 0) { + if (ch == '<') { + tagLevel += 1; + } else if (ch == '>') { + tagLevel -= 1; + } + } + if (ch == '[') { + bracketLevel += 1; + } else if (ch == ']') { + bracketLevel -= 1; + } + } else { + if (ch == stringDelimiter) { + stringDelimiter = '\0'; + } + } + } + } + + + /** + * Scans the data for literal text. + * Scanning stops when a character does not match or after the complete + * text has been checked, whichever comes first. + * + * @param literal the literal to check. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>literal != null</code> + * </ul></dd></dl> + */ + protected boolean checkLiteral(String literal) + throws IOException + { + int length = literal.length(); + for (int i = 0; i < length; i += 1) { + if (this.readChar() != literal.charAt(i)) { + return false; + } + } + return true; + } + + + /** + * Reads a character from a reader. + */ + protected char readChar() + throws IOException + { + if (this.charReadTooMuch != '\0') { + char ch = this.charReadTooMuch; + this.charReadTooMuch = '\0'; + return ch; + } else { + int i = this.reader.read(); + if (i < 0) { + throw this.unexpectedEndOfData(); + } else if (i == 10) { + this.parserLineNr += 1; + return '\n'; + } else { + return (char) i; + } + } + } + + + /** + * Scans an XML element. + * + * @param elt The element that will contain the result. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li>The first < has already been read. + * <li><code>elt != null</code> + * </ul></dd></dl> + */ + protected void scanElement(XMLElement elt) + throws IOException + { + StringBuffer buf = new StringBuffer(); + this.scanIdentifier(buf); + String name = buf.toString(); + elt.setName(name); + char ch = this.scanWhitespace(); + while ((ch != '>') && (ch != '/')) { + buf.setLength(0); + this.unreadChar(ch); + this.scanIdentifier(buf); + String key = buf.toString(); + ch = this.scanWhitespace(); + if (ch != '=') { + throw this.expectedInput("="); + } + this.unreadChar(this.scanWhitespace()); + buf.setLength(0); + this.scanString(buf); + elt.setAttribute(key, buf); + ch = this.scanWhitespace(); + } + if (ch == '/') { + ch = this.readChar(); + if (ch != '>') { + throw this.expectedInput(">"); + } + return; + } + buf.setLength(0); + ch = this.scanWhitespace(buf); + if (ch != '<') { + this.unreadChar(ch); + this.scanPCData(buf); + } else { + for (;;) { + ch = this.readChar(); + if (ch == '!') { + if (this.checkCDATA(buf)) { + this.scanPCData(buf); + break; + } else { + ch = this.scanWhitespace(buf); + if (ch != '<') { + this.unreadChar(ch); + this.scanPCData(buf); + break; + } + } + } else { + buf.setLength(0); + break; + } + } + } + if (buf.length() == 0) { + while (ch != '/') { + if (ch == '!') { + ch = this.readChar(); + if (ch != '-') { + throw this.expectedInput("Comment or Element"); + } + ch = this.readChar(); + if (ch != '-') { + throw this.expectedInput("Comment or Element"); + } + this.skipComment(); + } else { + this.unreadChar(ch); + XMLElement child = this.createAnotherElement(); + this.scanElement(child); + elt.addChild(child); + } + ch = this.scanWhitespace(); + if (ch != '<') { + throw this.expectedInput("<"); + } + ch = this.readChar(); + } + this.unreadChar(ch); + } else { + if (this.ignoreWhitespace) { + elt.setContent(buf.toString().trim()); + } else { + elt.setContent(buf.toString()); + } + } + ch = this.readChar(); + if (ch != '/') { + throw this.expectedInput("/"); + } + this.unreadChar(this.scanWhitespace()); + if (! this.checkLiteral(name)) { + throw this.expectedInput(name); + } + if (this.scanWhitespace() != '>') { + throw this.expectedInput(">"); + } + } + + + /** + * Resolves an entity. The name of the entity is read from the reader. + * The value of the entity is appended to <code>buf</code>. + * + * @param buf Where to put the entity value. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li>The first & has already been read. + * <li><code>buf != null</code> + * </ul></dd></dl> + */ + protected void resolveEntity(StringBuffer buf) + throws IOException + { + char ch = '\0'; + StringBuffer keyBuf = new StringBuffer(); + for (;;) { + ch = this.readChar(); + if (ch == ';') { + break; + } + keyBuf.append(ch); + } + String key = keyBuf.toString(); + if (key.charAt(0) == '#') { + try { + if (key.charAt(1) == 'x') { + ch = (char) Integer.parseInt(key.substring(2), 16); + } else { + ch = (char) Integer.parseInt(key.substring(1), 10); + } + } catch (NumberFormatException e) { + throw this.unknownEntity(key); + } + buf.append(ch); + } else { + char[] value = (char[]) this.entities.get(key); + if (value == null) { + throw this.unknownEntity(key); + } + buf.append(value); + } + } + + + /** + * Pushes a character back to the read-back buffer. + * + * @param ch The character to push back. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li>The read-back buffer is empty. + * <li><code>ch != '\0'</code> + * </ul></dd></dl> + */ + protected void unreadChar(char ch) + { + this.charReadTooMuch = ch; + } + + + /** + * Creates a parse exception for when an invalid valueset is given to + * a method. + * + * @param name The name of the entity. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>name != null</code> + * </ul></dd></dl> + */ + protected XMLParseException invalidValueSet(String name) + { + String msg = "Invalid value set (entity name = \"" + name + "\")"; + return new XMLParseException(this.getName(), this.parserLineNr, msg); + } + + + /** + * Creates a parse exception for when an invalid value is given to a + * method. + * + * @param name The name of the entity. + * @param value The value of the entity. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>name != null</code> + * <li><code>value != null</code> + * </ul></dd></dl> + */ + protected XMLParseException invalidValue(String name, + String value) + { + String msg = "Attribute \"" + name + "\" does not contain a valid " + + "value (\"" + value + "\")"; + return new XMLParseException(this.getName(), this.parserLineNr, msg); + } + + + /** + * Creates a parse exception for when the end of the data input has been + * reached. + */ + protected XMLParseException unexpectedEndOfData() + { + String msg = "Unexpected end of data reached"; + return new XMLParseException(this.getName(), this.parserLineNr, msg); + } + + + /** + * Creates a parse exception for when a syntax error occured. + * + * @param context The context in which the error occured. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>context != null</code> + * <li><code>context.length() > 0</code> + * </ul></dd></dl> + */ + protected XMLParseException syntaxError(String context) + { + String msg = "Syntax error while parsing " + context; + return new XMLParseException(this.getName(), this.parserLineNr, msg); + } + + + /** + * Creates a parse exception for when the next character read is not + * the character that was expected. + * + * @param charSet The set of characters (in human readable form) that was + * expected. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>charSet != null</code> + * <li><code>charSet.length() > 0</code> + * </ul></dd></dl> + */ + protected XMLParseException expectedInput(String charSet) + { + String msg = "Expected: " + charSet; + return new XMLParseException(this.getName(), this.parserLineNr, msg); + } + + /** + * Creates a parse exception for when the next character read is not + * the character that was expected. + * + * @param charSet The set of characters (in human readable form) that was + * expected. + * @param ch The character that was received instead. + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>charSet != null</code> + * <li><code>charSet.length() > 0</code> + * </ul></dd></dl> + */ + protected XMLParseException expectedInput(String charSet, char ch) + { + String msg = "Expected: '" + charSet +"'" + " but got: '" + ch + "'"; + return new XMLParseException(this.getName(), this.parserLineNr, msg); + } + + /** + * Creates a parse exception for when an entity could not be resolved. + * + * @param name The name of the entity. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>name != null</code> + * <li><code>name.length() > 0</code> + * </ul></dd></dl> + */ + protected XMLParseException unknownEntity(String name) + { + String msg = "Unknown or invalid entity: &" + name + ";"; + return new XMLParseException(this.getName(), this.parserLineNr, msg); + } + + /** + * Reads an xml file and removes the comments, leaving only relevant + * xml code. + * + * @param isr The reader of the InputStream containing the xml. + * @param pout The PipedOutputStream that will be receiving the filtered + * xml file. + */ + public void sanitizeInput(InputStreamReader isr, PipedOutputStream pout) { + try { + PrintStream out = new PrintStream(pout); + + this.sanitizeCharReadTooMuch = '\0'; + this.reader = isr; + this.parserLineNr = 0; + int newline = 2; + char prev = ' '; + + while(true) { + char ch; + if (this.sanitizeCharReadTooMuch != '\0') { + ch = this.sanitizeCharReadTooMuch; + this.sanitizeCharReadTooMuch = '\0'; + } else { + + int i = this.reader.read(); + if (i == -1) { + // no character in buffer, and nothing read + out.flush(); + break; + } else if (i == 10) { + ch = '\n'; + } else { + ch = (char) i; + } + } + + char next; + int i = this.reader.read(); + if (i == -1) { + // character in buffer and nothing read. write out + // what's in the buffer + out.print(ch); + out.flush(); + if (JNLPRuntime.isDebug()) { + if (ch == 10) { + System.out.println(); + System.out.print("line: " + newline + " "); + newline++; + } else { + System.out.print(ch); + } + } + break; + } else if (i == 10) { + next = '\n'; + } else { + next = (char) i; + } + + this.sanitizeCharReadTooMuch = next; + + // If the next char is a ? or !, then we've hit a special tag, + // and should skip it. + if (prev == '<' && (next == '!' || next == '?')) { + this.skipSpecialTag(0); + this.sanitizeCharReadTooMuch = '\0'; + } + // Otherwise we haven't hit a comment, and we should write ch. + else { + out.print(ch); + if (JNLPRuntime.isDebug()) { + if (ch == 10) { + System.out.println(); + System.out.print("line: " + newline + " "); + newline++; + } else { + System.out.print(ch); + } + } + } + prev = next; + } + + out.close(); + isr.close(); + } catch (Exception e) { + // Print the stack trace here -- xml.parseFromReader() will + // throw the ParseException if something goes wrong. + e.printStackTrace(); + } + } +} diff --git a/netx/net/sourceforge/nanoxml/XMLParseException.java b/netx/net/sourceforge/nanoxml/XMLParseException.java new file mode 100644 index 0000000..dfbb637 --- /dev/null +++ b/netx/net/sourceforge/nanoxml/XMLParseException.java @@ -0,0 +1,130 @@ +/* XMLParseException.java + * + * $Revision: 1.1 $ + * $Date: 2002/08/03 04:05:32 $ + * $Name: $ + * + * This file is part of NanoXML 2 Lite. + * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved. + * + * This software is provided 'as-is', without any express or implied warranty. + * In no event will the authors be held liable for any damages arising from the + * use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software in + * a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + *****************************************************************************/ + + +package net.sourceforge.nanoxml; + + +/** + * An XMLParseException is thrown when an error occures while parsing an XML + * string. + * <P> + * $Revision: 1.1 $<BR> + * $Date: 2002/08/03 04:05:32 $<P> + * + * @see net.sourceforge.nanoxml.XMLElement + * + * @author Marc De Scheemaecker + * @version $Name: $, $Revision: 1.1 $ + */ +public class XMLParseException + extends RuntimeException +{ + + /** + * Indicates that no line number has been associated with this exception. + */ + public static final int NO_LINE = -1; + + + /** + * The line number in the source code where the error occurred, or + * <code>NO_LINE</code> if the line number is unknown. + * + * <dl><dt><b>Invariants:</b></dt><dd> + * <ul><li><code>lineNr > 0 || lineNr == NO_LINE</code> + * </ul></dd></dl> + */ + private int lineNr; + + + /** + * Creates an exception. + * + * @param name The name of the element where the error is located. + * @param message A message describing what went wrong. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>message != null</code> + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>getLineNr() => NO_LINE + * </ul></dd></dl><dl> + */ + public XMLParseException(String name, + String message) + { + super("XML Parse Exception during parsing of " + + ((name == null) ? "the XML definition" + : ("a " + name + " element")) + + ": " + message); + this.lineNr = XMLParseException.NO_LINE; + } + + + /** + * Creates an exception. + * + * @param name The name of the element where the error is located. + * @param lineNr The number of the line in the input. + * @param message A message describing what went wrong. + * + * </dl><dl><dt><b>Preconditions:</b></dt><dd> + * <ul><li><code>message != null</code> + * <li><code>lineNr > 0</code> + * </ul></dd></dl> + * + * <dl><dt><b>Postconditions:</b></dt><dd> + * <ul><li>getLineNr() => lineNr + * </ul></dd></dl><dl> + */ + public XMLParseException(String name, + int lineNr, + String message) + { + super("XML Parse Exception during parsing of " + + ((name == null) ? "the XML definition" + : ("a " + name + " element")) + + " at line " + lineNr + ": " + message); + this.lineNr = lineNr; + } + + + /** + * Where the error occurred, or <code>NO_LINE</code> if the line number is + * unknown. + * + * @see net.sourceforge.nanoxml.XMLParseException#NO_LINE + */ + public int getLineNr() + { + return this.lineNr; + } + +} |