📄 unmarshallingcontext.java
字号:
/*
Copyright (c) 2002-2007, Dennis M. Sosnoski.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of JiBX nor the names of its contributors may be used
to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jibx.runtime.impl;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IUnmarshaller;
import org.jibx.runtime.IUnmarshallingContext;
import org.jibx.runtime.IXMLReader;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.Utility;
/**
* Pull parser wrapper supplying convenience methods for access. Most of
* these methods are designed for use in code generated by the binding
* generator.
*
* @author Dennis M. Sosnoski
*/
public class UnmarshallingContext implements IUnmarshallingContext
{
/** Starting size for object stack. */
private static final int INITIAL_STACK_SIZE = 20;
/** Empty array of strings. */
private static final String[] EMPTY_STRING_ARRAY = new String[0];
/** Factory for creating XML readers. */
private static final IXMLReaderFactory s_readerFactory;
static {
String prop = System.getProperty("org.jibx.runtime.impl.parser");
if (prop == null) {
// try XMLPull parser factory first
IXMLReaderFactory fact = null;
try {
fact = createReaderFactory
("org.jibx.runtime.impl.XMLPullReaderFactory");
} catch (Throwable e) {
fact = createReaderFactory
("org.jibx.runtime.impl.StAXReaderFactory");
}
s_readerFactory = fact;
} else {
// try loading factory class specified by property
s_readerFactory = createReaderFactory(prop);
}
}
/** Binding factory used to create this unmarshaller. */
private IBindingFactory m_factory;
/** Parser in use. */
private IXMLReader m_reader;
//
// Structures organized by mapping index number. Each unmarshaller in the
// binding definition is assigned a unique index number by the binding
// compiler. This includes both generated unmarshallers (from non-abstract
// <mapping> definitions) and user-defined unmarshallers. Instances of
// the unmarshaller classes are created as needed. The indexes for the
// unmarshallers corresponding to named mappings always precede those for
// internal mappings in the list.
/** Unmarshaller classes for mapping definition (<code>null</code> for
mappings out of context). */
protected String[] m_unmarshallerClasses;
/** Unmarshallers for classes in mapping definition (lazy create of actual
unmarshaller instances) */
protected IUnmarshaller[] m_unmarshallers;
//
// Structures organized by mapping
/** Namespaces for elements associated with class mappings. */
protected String[] m_namespaces;
/** Names for elements associated with class mappings. */
protected String[] m_names;
/** Number of classes with global unmarshallers. */
protected int m_globalCount;
/** ID maps for finding references. */
protected HashMap[] m_idMaps;
/** Class names of referenced types (<code>null</code> unless class-specific
IDs used). */
protected String[] m_idClasses;
/** Current unmarshalling stack depth. */
protected int m_stackDepth;
/** Stack of objects being unmarshalled. */
protected Object[] m_objectStack;
/** Mapping from element name to class index. If only a single namespace
is defined for a particular local name the value for that name in
this table is the Integer index of the associated class. If multiple
namespaces are defined using the same local name the value is an
ArrayList of Integer indexes. This is a high-overhead construct, so
lazy construction is used - it's built the first time needed, then kept
up to date thereafter. */
protected HashMap m_unmarshalMap;
/** Wrapped index values used with unmarshalling map. */
protected Integer[] m_indexes;
/** Last IDREF value parsed. */
protected String m_idref;
/** User context object (not used by JiBX, only for user convenience). */
protected Object m_userContext;
/**
* Parser factory class loader method. This is used during initialization to
* check that a particular factory class is usable.
*
* @param cname class name
* @return reader factory instance
* @throws RuntimeException on error creating class instance
*/
private static IXMLReaderFactory createReaderFactory(String cname) {
// try loading factory class from context loader
Class clas = null;
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader != null) {
try {
clas = loader.loadClass(cname);
} catch (ClassNotFoundException e) { /* deliberately empty */ }
}
if (clas == null) {
// next try the class loader that loaded the unmarshaller interface
try {
loader = IUnmarshallingContext.class.getClassLoader();
clas = loader.loadClass(cname);
} catch (ClassNotFoundException e) {
throw new RuntimeException
("Unable to specified parser factory class " + cname);
}
}
if (! (IXMLReaderFactory.class.isAssignableFrom(clas))) {
throw new RuntimeException("Specified parser factory class " +
cname + " does not implement IXMLReaderFactory interface");
}
// use static method to create parser factory class instance
try {
Method meth = clas.getMethod("getInstance", null);
return (IXMLReaderFactory)meth.invoke(null, null);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Specified parser factory class " +
cname + " does not define static getInstance() method");
} catch (IllegalAccessException e) {
throw new RuntimeException("Error on parser factory class " +
cname + " getInstance() method call: " + e.getMessage());
} catch (InvocationTargetException e) {
throw new RuntimeException("Error on parser factory class " +
cname + " getInstance() method call: " + e.getMessage());
}
}
/**
* Constructor. Builds the actual parser and initializes internal data
* structures.
*
* @param nmap number of mapping definitions included
* @param umcs names of unmarshaller classes for indexes with fixed
* unmarshallers (as opposed to mapping slots, which may be overridden;
* reference kept, must be constant)
* @param nss namespaces for elements of classes with global definitions
* @param names names for elements of classes with global definitions
* @param idcs array of class names with IDs (<code>null</code> if no IDs or
* global IDs)
* @param ifact binding factory creating this unmarshaller
*/
public UnmarshallingContext(int nmap, String[] umcs, String[] nss,
String[] names, String[] idcs, IBindingFactory ifact) {
// initialize internal unmarshaller state
m_globalCount = nss.length;
m_unmarshallerClasses = new String[nmap];
System.arraycopy(umcs, 0, m_unmarshallerClasses, 0, umcs.length);
m_unmarshallers = new IUnmarshaller[nmap];
m_namespaces = new String[nmap];
System.arraycopy(nss, 0, m_namespaces, 0, nss.length);
m_names = new String[nmap];
System.arraycopy(names, 0, m_names, 0, names.length);
m_idClasses = idcs;
int size = idcs == null ? 1 : idcs.length;
m_idMaps = new HashMap[size];
m_objectStack = new Object[INITIAL_STACK_SIZE];
m_factory = ifact;
}
/**
* Default constructor. This can be used for creating a context outside of
* the generated code for special purposes.
*/
public UnmarshallingContext() {
this(0, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY, null);
}
/**
* Build name with optional namespace. Just returns the appropriate
* name format.
*
* @param ns namespace URI of name
* @param name local name part of name
* @return formatted name string
*/
public static String buildNameString(String ns, String name) {
if (ns == null || "".equals(ns)) {
return "\"" + name + "\"";
} else {
return "\"{" + ns + "}" + name + "\"";
}
}
/**
* Build current element name, with optional namespace.
*
* @return formatted name string
*/
public String currentNameString() {
return buildNameString(m_reader.getNamespace(), m_reader.getName());
}
/**
* Build current parse input position description.
*
* @return text description of current parse position
*/
public String buildPositionString() {
return m_reader.buildPositionString();
}
/**
* Throw exception for expected element start tag not found.
*
* @param ns namespace URI of name
* @param name local name part of name
* @exception JiBXException always thrown
*/
public void throwStartTagNameError(String ns, String name)
throws JiBXException {
throw new JiBXException("Expected " + buildNameString(ns, name) +
" start tag, found " + currentNameString() + " start tag " +
buildPositionString());
}
/**
* Throw exception for expected element end tag not found.
*
* @param ns namespace URI of name
* @param name local name part of name
* @exception JiBXException always thrown
*/
public void throwEndTagNameError(String ns, String name)
throws JiBXException {
throw new JiBXException("Expected " + buildNameString(ns, name) +
" end tag, found " + currentNameString() + " end tag " +
buildPositionString());
}
/**
* Throw exception including a name and position information.
*
* @param msg leading message text
* @param ns namespace URI of name
* @param name local name part of name
* @exception JiBXException always thrown
*/
public void throwNameException(String msg, String ns, String name)
throws JiBXException {
throw new JiBXException(msg + buildNameString(ns, name) +
buildPositionString());
}
/**
* Advance to next parse item. This wraps the base parser call in order to
* catch and handle exceptions.
*
* @exception JiBXException on any error (possibly wrapping other exception)
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -