package org.jboss.axis.encoding;
import org.jboss.axis.AxisFault;
import org.jboss.axis.Constants;
import org.jboss.axis.Message;
import org.jboss.axis.MessageContext;
import org.jboss.axis.attachments.Attachments;
import org.jboss.axis.description.TypeDesc;
import org.jboss.axis.message.EnvelopeBuilder;
import org.jboss.axis.message.EnvelopeHandler;
import org.jboss.axis.message.IDResolver;
import org.jboss.axis.message.NullAttributes;
import org.jboss.axis.message.SAX2EventRecorder;
import org.jboss.axis.message.SOAPElementAxisImpl;
import org.jboss.axis.message.SOAPEnvelopeAxisImpl;
import org.jboss.axis.message.SOAPHandler;
import org.jboss.axis.schema.SchemaVersion;
import org.jboss.axis.soap.SOAPConstants;
import org.jboss.axis.utils.JavaUtils;
import org.jboss.axis.utils.Messages;
import org.jboss.axis.utils.NSStack;
import org.jboss.axis.utils.XMLUtils;
import org.jboss.logging.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.namespace.QName;
import javax.xml.parsers.SAXParser;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.holders.Holder;
import javax.xml.soap.SOAPException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
public class DeserializationContextImpl extends DefaultHandler implements LexicalHandler, DeserializationContext
{
private static Logger log = Logger.getLogger(DeserializationContextImpl.class.getName());
static final SchemaVersion schemaVersions[] = new SchemaVersion[]{
SchemaVersion.SCHEMA_1999,
SchemaVersion.SCHEMA_2000,
SchemaVersion.SCHEMA_2001,
};
private NSStack namespaces = new NSStack();
private Locator locator;
private SOAPHandler topHandler = null;
private ArrayList pushedDownHandlers = new ArrayList();
private SAX2EventRecorder recorder = null;
private SOAPEnvelopeAxisImpl envelope;
private HashMap idMap;
private LocalIDResolver localIDs;
private HashMap fixups;
static final SOAPHandler nullHandler = new SOAPHandler();
protected MessageContext msgContext;
private boolean doneParsing;
protected InputSource inputSource;
private SOAPElementAxisImpl curElement;
private StringBuffer curElementContent;
protected int startOfMappingsPos = -1;
protected boolean haveSeenSchemaNS = false;
private static final Class[] DESERIALIZER_CLASSES =
new Class[]{String.class, Class.class, QName.class};
private static final String DESERIALIZER_METHOD = "getDeserializer";
public void deserializing(boolean isDeserializing)
{
doneParsing = isDeserializing;
}
public DeserializationContextImpl(MessageContext ctx,
SOAPHandler initialHandler)
{
msgContext = ctx;
if (ctx == null || ctx.isHighFidelity())
recorder = new SAX2EventRecorder();
if (initialHandler instanceof EnvelopeBuilder)
{
envelope = ((EnvelopeBuilder)initialHandler).getEnvelope();
envelope.setRecorder(recorder);
}
pushElementHandler(new EnvelopeHandler(initialHandler));
}
public DeserializationContextImpl(InputSource is,
MessageContext ctx,
String messageType)
{
msgContext = ctx;
EnvelopeBuilder builder = new EnvelopeBuilder(messageType, getSOAPConstants());
if (ctx == null || ctx.isHighFidelity())
recorder = new SAX2EventRecorder();
envelope = builder.getEnvelope();
envelope.setRecorder(recorder);
pushElementHandler(new EnvelopeHandler(builder));
inputSource = is;
}
private SOAPConstants getSOAPConstants()
{
SOAPConstants constants = Constants.DEFAULT_SOAP_VERSION;
if (msgContext != null)
constants = msgContext.getSOAPConstants();
return constants;
}
public DeserializationContextImpl(InputSource is,
MessageContext ctx,
String messageType,
SOAPEnvelopeAxisImpl env)
{
EnvelopeBuilder builder = new EnvelopeBuilder(env, messageType);
msgContext = ctx;
if (ctx == null || ctx.isHighFidelity())
recorder = new SAX2EventRecorder();
envelope = builder.getEnvelope();
envelope.setRecorder(recorder);
pushElementHandler(new EnvelopeHandler(builder));
inputSource = is;
}
public void parse() throws SAXException
{
if (inputSource != null)
{
SAXParser parser = XMLUtils.getSAXParser();
try
{
parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);
parser.parse(inputSource, this);
try
{
parser.setProperty("http://xml.org/sax/properties/lexical-handler", null);
}
catch (SAXException se)
{
}
}
catch (IOException e)
{
throw new SAXException(e);
}
inputSource = null;
}
}
public SOAPElementAxisImpl getCurElement()
{
return curElement;
}
public void setCurElement(SOAPElementAxisImpl el)
{
curElement = el;
if (curElement != null && curElement.getRecorder() != recorder)
{
recorder = curElement.getRecorder();
}
}
public MessageContext getMessageContext()
{
return msgContext;
}
public SOAPEnvelopeAxisImpl getEnvelope()
{
return envelope;
}
public SAX2EventRecorder getRecorder()
{
return recorder;
}
public void setRecorder(SAX2EventRecorder recorder)
{
this.recorder = recorder;
}
public ArrayList getCurrentNSMappings()
{
return namespaces.cloneFrame();
}
public String getNamespaceURI(String prefix)
{
String result = namespaces.getNamespaceURI(prefix);
if (result != null)
return result;
if (curElement != null)
return curElement.getNamespaceURI(prefix);
return null;
}
public QName getQNameFromString(String qNameStr)
{
if (qNameStr == null)
return null;
int i = qNameStr.indexOf(':');
String nsURI;
if (i == -1)
{
nsURI = getNamespaceURI("");
}
else
{
nsURI = getNamespaceURI(qNameStr.substring(0, i));
}
return new QName(nsURI, qNameStr.substring(i + 1));
}
public QName getTypeFromXSITypeAttr(String namespace, String localName,
Attributes attrs)
{
String type = Constants.getValue(attrs, Constants.URIS_SCHEMA_XSI,
"type");
if (type != null)
{
return getQNameFromString(type);
}
return null;
}
public QName getTypeFromAttributes(String namespace, String localName,
Attributes attrs)
{
QName typeQName = getTypeFromXSITypeAttr(namespace, localName, attrs);
if ((typeQName == null) && Constants.isSOAP_ENC(namespace))
{
if (namespace.equals(Constants.URI_SOAP12_ENC))
{
typeQName = new QName(namespace, localName);
}
else if (localName.equals(Constants.SOAP_ARRAY.getLocalPart()))
{
typeQName = Constants.SOAP_ARRAY;
}
else if (localName.equals(Constants.SOAP_STRING.getLocalPart()))
{
typeQName = Constants.SOAP_STRING;
}
else if (localName.equals(Constants.SOAP_BOOLEAN.getLocalPart()))
{
typeQName = Constants.SOAP_BOOLEAN;
}
else if (localName.equals(Constants.SOAP_DOUBLE.getLocalPart()))
{
typeQName = Constants.SOAP_DOUBLE;
}
else if (localName.equals(Constants.SOAP_FLOAT.getLocalPart()))
{
typeQName = Constants.SOAP_FLOAT;
}
else if (localName.equals(Constants.SOAP_INT.getLocalPart()))
{
typeQName = Constants.SOAP_INT;
}
else if (localName.equals(Constants.SOAP_LONG.getLocalPart()))
{
typeQName = Constants.SOAP_LONG;
}
else if (localName.equals(Constants.SOAP_SHORT.getLocalPart()))
{
typeQName = Constants.SOAP_SHORT;
}
else if (localName.equals(Constants.SOAP_BYTE.getLocalPart()))
{
typeQName = Constants.SOAP_BYTE;
}
}
if (typeQName == null && attrs != null)
{
String encURI = getSOAPConstants().getEncodingURI();
String itemType = getSOAPConstants().getAttrItemType();
for (int i = 0; i < attrs.getLength(); i++)
{
if (encURI.equals(attrs.getURI(i)) &&
itemType.equals(attrs.getLocalName(i)))
{
return new QName(encURI, "Array");
}
}
}
return typeQName;
}
public Deserializer getDeserializerForClass(Class cls)
{
if (cls == null)
{
return null;
}
if (cls.isArray())
{
cls = cls.getComponentType();
}
if (Holder.class.isAssignableFrom(cls))
{
try
{
cls = cls.getField("value").getType();
}
catch (Exception e)
{
}
}
Deserializer dser = null;
try
{
Method method = cls.getMethod(DESERIALIZER_METHOD, DESERIALIZER_CLASSES);
if (method != null)
{
TypeDesc typedesc = TypeDesc.getTypeDescForClass(cls);
if (typedesc != null)
{
dser = (Deserializer)method.invoke(null,
new Object[]{msgContext.getEncodingStyle(), cls, typedesc.getXmlType()});
}
}
}
catch (Exception e)
{
log.error(Messages.getMessage("noDeser00", cls.getName()));
}
return dser;
}
public boolean isNil(Attributes attrs)
{
return JavaUtils.isTrueExplicitly(Constants.getValue(attrs, Constants.QNAMES_NIL),
false);
}
public final Deserializer getDeserializer(Class cls, QName xmlType)
{
if (xmlType == null)
return null;
log.debug("Enter:getDeserializer: [class=" + cls + ",xmlType=" + xmlType + "]");
DeserializerFactory dserF = null;
Deserializer dser = null;
try
{
dserF = (DeserializerFactory)getTypeMapping().
getDeserializer(cls, xmlType);
}
catch (JAXRPCException e)
{
log.error(Messages.getMessage("noFactory00", xmlType.toString()));
}
if (dserF != null)
{
try
{
dser = (Deserializer)dserF.getDeserializerAs(Constants.AXIS_SAX);
}
catch (JAXRPCException e)
{
log.error(Messages.getMessage("noDeser00", xmlType.toString()));
}
}
log.debug("Exit:getDeserializer: " + dser);
return dser;
}
public final Deserializer getDeserializerForType(QName xmlType)
{
return getDeserializer(null, xmlType);
}
public TypeMapping getTypeMapping()
{
TypeMappingRegistry tmr = msgContext.getTypeMappingRegistry();
return (TypeMapping)tmr.getTypeMapping(msgContext.getEncodingStyle());
}
public TypeMappingRegistry getTypeMappingRegistry()
{
return msgContext.getTypeMappingRegistry();
}
public SOAPElementAxisImpl getElementByID(String id)
{
if ((idMap != null))
{
IDResolver resolver = (IDResolver)idMap.get(id);
if (resolver != null)
{
Object ret = resolver.getReferencedObject(id);
if (ret instanceof SOAPElementAxisImpl)
return (SOAPElementAxisImpl)ret;
}
}
return null;
}
public Object getObjectByRef(String href)
{
Object ret = null;
if (href != null)
{
if ((idMap != null))
{
IDResolver resolver = (IDResolver)idMap.get(href);
if (resolver != null)
ret = resolver.getReferencedObject(href);
}
if (null == ret && !href.startsWith("#"))
{
Message msg = null;
if (null != (msg = msgContext.getCurrentMessage()))
{
Attachments attch = null;
if (null != (attch = msg.getAttachmentsImpl()))
{
try
{
ret = attch.getAttachmentByReference(href);
}
catch (AxisFault e)
{
throw new RuntimeException(e.toString() + JavaUtils.stackToString(e));
}
}
}
}
}
return ret;
}
public void addObjectById(String id, Object obj)
{
String idStr = '#' + id;
if ((idMap == null) || (id == null))
return;
IDResolver resolver = (IDResolver)idMap.get(idStr);
if (resolver == null)
return;
resolver.addReferencedObject(idStr, obj);
return;
}
public void registerFixup(String href, Deserializer dser)
{
if (fixups == null)
fixups = new HashMap();
Deserializer prev = (Deserializer)fixups.put(href, dser);
if (prev != null && prev != dser)
{
dser.moveValueTargets(prev);
if (dser.getDefaultType() == null)
{
dser.setDefaultType(prev.getDefaultType());
}
}
}
public void registerElementByID(String id, SOAPElementAxisImpl elem)
{
if (localIDs == null)
localIDs = new LocalIDResolver();
String absID = '#' + id;
localIDs.addReferencedObject(absID, elem);
registerResolverForID(absID, localIDs);
if (fixups != null)
{
Deserializer dser = (Deserializer)fixups.get(absID);
if (dser != null)
{
elem.setFixupDeserializer(dser);
}
}
}
public void registerResolverForID(String id, IDResolver resolver)
{
if ((id == null) || (resolver == null))
{
return;
}
if (idMap == null)
idMap = new HashMap();
idMap.put(id, resolver);
}
public int getCurrentRecordPos()
{
if (recorder == null) return -1;
return recorder.getLength() - 1;
}
public int getStartOfMappingsPos()
{
if (startOfMappingsPos == -1)
{
return getCurrentRecordPos() + 1;
}
return startOfMappingsPos;
}
public void pushNewElement(SOAPElementAxisImpl elem)
{
if (log.isDebugEnabled())
{
log.debug("Pushing element " + elem.getName());
}
if (!doneParsing && (recorder != null))
{
recorder.newElement(elem);
}
try
{
if (curElement != null)
elem.setParentElement(curElement);
}
catch (Exception e)
{
log.fatal(Messages.getMessage("exception00"), e);
}
curElement = elem;
if (elem.getRecorder() != recorder)
recorder = elem.getRecorder();
}
public void pushElementHandler(SOAPHandler handler)
{
if (log.isDebugEnabled())
{
log.debug(Messages.getMessage("pushHandler00", "" + handler));
}
if (topHandler != null) pushedDownHandlers.add(topHandler);
topHandler = handler;
}
public void replaceElementHandler(SOAPHandler handler)
{
topHandler = handler;
}
public SOAPHandler popElementHandler()
{
SOAPHandler result = topHandler;
int size = pushedDownHandlers.size();
if (size > 0)
{
topHandler = (SOAPHandler)pushedDownHandlers.remove(size - 1);
}
else
{
topHandler = null;
}
if (log.isDebugEnabled())
{
if (result == null)
{
log.debug(Messages.getMessage("popHandler00", "(null)"));
}
else
{
log.debug(Messages.getMessage("popHandler00", "" + result));
}
}
return result;
}
boolean processingRef = false;
public void setProcessingRef(boolean ref)
{
processingRef = ref;
}
public boolean isProcessingRef()
{
return processingRef;
}
public void startDocument() throws SAXException
{
if (!doneParsing && (recorder != null))
recorder.startDocument();
}
public void endDocument() throws SAXException
{
if (log.isDebugEnabled())
{
log.debug("Enter: DeserializationContextImpl::endDocument()");
}
if (!doneParsing && (recorder != null))
recorder.endDocument();
doneParsing = true;
if (log.isDebugEnabled())
{
log.debug("Exit: DeserializationContextImpl::endDocument()");
}
}
public boolean isDoneParsing()
{
return doneParsing;
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException
{
if (log.isDebugEnabled())
log.debug("Enter: DeserializationContextImpl::startPrefixMapping(" + prefix + ", " + uri + ")");
if ("".equals(uri))
{
log.warn("Ignoring invalid namespace mapping: [prefix=" + prefix + ",uri=" + uri + "]");
return;
}
if (!doneParsing && (recorder != null))
{
recorder.startPrefixMapping(prefix, uri);
}
if (startOfMappingsPos == -1)
{
namespaces.push();
startOfMappingsPos = getCurrentRecordPos();
}
if (prefix != null)
{
namespaces.add(uri, prefix);
}
else
{
namespaces.add(uri, "");
}
if (!haveSeenSchemaNS && msgContext != null)
{
for (int i = 0; !haveSeenSchemaNS && i < schemaVersions.length;
i++)
{
SchemaVersion schemaVersion = schemaVersions[i];
if (uri.equals(schemaVersion.getXsdURI()) ||
uri.equals(schemaVersion.getXsiURI()))
{
msgContext.setSchemaVersion(schemaVersion);
haveSeenSchemaNS = true;
}
}
}
if (topHandler != null)
{
topHandler.startPrefixMapping(prefix, uri);
}
if (log.isDebugEnabled())
log.debug("Exit: DeserializationContextImpl::startPrefixMapping()");
}
public void endPrefixMapping(String prefix)
throws SAXException
{
if (log.isDebugEnabled())
{
log.debug("Enter: DeserializationContextImpl::endPrefixMapping(" + prefix + ")");
}
if (!doneParsing && (recorder != null))
{
recorder.endPrefixMapping(prefix);
}
if (topHandler != null)
{
topHandler.endPrefixMapping(prefix);
}
if (log.isDebugEnabled())
{
log.debug("Exit: DeserializationContextImpl::endPrefixMapping()");
}
}
public void setDocumentLocator(Locator locator)
{
if (!doneParsing && (recorder != null))
{
recorder.setDocumentLocator(locator);
}
this.locator = locator;
}
public Locator getDocumentLocator()
{
return locator;
}
public void characters(char[] p1, int p2, int p3) throws SAXException
{
if (!doneParsing && (recorder != null))
{
recorder.characters(p1, p2, p3);
if (curElement != null)
{
if (curElementContent == null)
curElementContent = new StringBuffer();
String text = new String(p1, p2, p3);
curElementContent.append(text);
}
}
if (topHandler != null)
{
topHandler.characters(p1, p2, p3);
}
}
public void ignorableWhitespace(char[] p1, int p2, int p3) throws SAXException
{
if (!doneParsing && (recorder != null))
{
recorder.ignorableWhitespace(p1, p2, p3);
}
if (topHandler != null)
{
topHandler.ignorableWhitespace(p1, p2, p3);
}
}
public void processingInstruction(String p1, String p2) throws SAXException
{
throw new SAXException(Messages.getMessage("noInstructions00"));
}
public void skippedEntity(String p1) throws SAXException
{
if (!doneParsing && (recorder != null))
{
recorder.skippedEntity(p1);
}
topHandler.skippedEntity(p1);
}
public void startElement(String namespace, String localName,
String qName, Attributes attributes)
throws SAXException
{
if (log.isDebugEnabled())
{
log.debug("Enter: DeserializationContextImpl::startElement(" + namespace + ", " + localName + ")");
}
if (attributes == null || attributes.getLength() == 0)
{
attributes = NullAttributes.singleton;
}
else
{
attributes = new AttributesImpl(attributes);
SOAPConstants soapConstants = getSOAPConstants();
if (soapConstants == SOAPConstants.SOAP12_CONSTANTS)
{
if (attributes.getValue(soapConstants.getAttrHref()) != null &&
attributes.getValue(Constants.ATTR_ID) != null)
{
AxisFault fault = new AxisFault(Constants.FAULT_SOAP12_SENDER,
null, Messages.getMessage("noIDandHREFonSameElement"), null, null, null);
throw new SAXException(fault);
}
}
}
SOAPHandler nextHandler = null;
String prefix = "";
int idx = qName.indexOf(':');
if (idx > 0)
{
prefix = qName.substring(0, idx);
}
if (topHandler != null)
{
nextHandler = topHandler.onStartChild(namespace,
localName,
prefix,
attributes,
this);
}
if (nextHandler == null)
{
nextHandler = new SOAPHandler();
}
pushElementHandler(nextHandler);
nextHandler.startElement(namespace, localName, prefix,
attributes, this);
if (!doneParsing && (recorder != null))
{
recorder.startElement(namespace, localName, qName,
attributes);
if (!doneParsing)
{
curElement.setContentsIndex(recorder.getLength());
}
}
if (startOfMappingsPos != -1)
{
startOfMappingsPos = -1;
}
else
{
namespaces.push();
}
if (log.isDebugEnabled())
{
log.debug("Exit: DeserializationContextImpl::startElement()");
}
}
public void endElement(String namespace, String localName, String qName)
throws SAXException
{
if (log.isDebugEnabled())
{
log.debug("Enter: DeserializationContextImpl::endElement(" + namespace + ", " + localName + ")");
}
if (!doneParsing && (recorder != null))
{
String text = null;
try
{
if (curElementContent != null)
{
text = curElementContent.toString().trim();
if (text.length() > 0)
{
log.debug("addTextNode: '" + text + "'");
curElement.addTextNode(text);
}
curElementContent = null;
}
}
catch (SOAPException e)
{
throw new SAXException("Cannot add Text child: " + text);
}
recorder.endElement(namespace, localName, qName);
}
try
{
SOAPHandler handler = popElementHandler();
handler.endElement(namespace, localName, this);
if (topHandler != null)
{
topHandler.onEndChild(namespace, localName, this);
}
else
{
}
}
finally
{
if (curElement != null)
{
curElement = (SOAPElementAxisImpl)curElement.getParentElement();
}
namespaces.pop();
if (log.isDebugEnabled())
{
String name = curElement != null ?
curElement.getClass().getName() + ":" +
curElement.getName() : null;
log.debug("Popped element stack to " + name);
log.debug("Exit: DeserializationContextImpl::endElement()");
}
}
}
private static class LocalIDResolver implements IDResolver
{
HashMap idMap = null;
public void addReferencedObject(String id, Object referent)
{
if (idMap == null)
{
idMap = new HashMap();
}
idMap.put(id, referent);
}
public Object getReferencedObject(String href)
{
if ((idMap == null) || (href == null))
{
return null;
}
return idMap.get(href);
}
}
public void startDTD(java.lang.String name,
java.lang.String publicId,
java.lang.String systemId)
throws SAXException
{
throw new SAXException(Messages.getMessage("noInstructions00"));
}
public void endDTD()
throws SAXException
{
if (recorder != null)
recorder.endDTD();
}
public void startEntity(java.lang.String name)
throws SAXException
{
if (recorder != null)
recorder.startEntity(name);
}
public void endEntity(java.lang.String name)
throws SAXException
{
if (recorder != null)
recorder.endEntity(name);
}
public void startCDATA()
throws SAXException
{
if (recorder != null)
recorder.startCDATA();
}
public void endCDATA()
throws SAXException
{
if (recorder != null)
recorder.endCDATA();
}
public void comment(char[] ch,
int start,
int length)
throws SAXException
{
if (recorder != null)
recorder.comment(ch, start, length);
}
public InputSource resolveEntity(String publicId, String systemId)
{
return XMLUtils.getEmptyInputSource();
}
}