package org.jboss.axis.wsdl.fromJava;
import org.jboss.axis.AxisFault;
import org.jboss.axis.Constants;
import org.jboss.axis.InternalException;
import org.jboss.axis.description.ServiceDesc;
import org.jboss.axis.encoding.Serializer;
import org.jboss.axis.encoding.SerializerFactory;
import org.jboss.axis.encoding.SimpleType;
import org.jboss.axis.encoding.TypeMapping;
import org.jboss.axis.encoding.ser.BeanSerializerFactory;
import org.jboss.axis.encoding.ser.EnumSerializerFactory;
import org.jboss.axis.enums.Style;
import org.jboss.axis.utils.JavaUtils;
import org.jboss.axis.utils.Messages;
import org.jboss.axis.utils.XMLUtils;
import org.jboss.axis.wsdl.symbolTable.BaseTypeMapping;
import org.jboss.axis.wsdl.symbolTable.SymbolTable;
import org.jboss.logging.Logger;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.rpc.holders.Holder;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class Types
{
private static Logger log = Logger.getLogger(Types.class.getName());
Definition def;
Namespaces namespaces = null;
TypeMapping tm;
TypeMapping defaultTM;
String targetNamespace;
Element wsdlTypesElem = null;
HashMap schemaTypes = null;
HashMap schemaElementNames = null;
HashMap schemaUniqueElementNames = null;
HashMap wrapperMap = new HashMap();
List stopClasses = null;
List beanCompatErrs = new ArrayList();
ServiceDesc serviceDesc = null;
public Types(Definition def,
TypeMapping tm,
TypeMapping defaultTM,
Namespaces namespaces,
String targetNamespace,
List stopClasses,
ServiceDesc serviceDesc)
{
this.def = def;
this.serviceDesc = serviceDesc;
createDocumentFragment();
this.tm = tm;
this.defaultTM = defaultTM;
this.namespaces = namespaces;
this.targetNamespace = targetNamespace;
this.stopClasses = stopClasses;
schemaElementNames = new HashMap();
schemaUniqueElementNames = new HashMap();
schemaTypes = new HashMap();
}
public Namespaces getNamespaces()
{
return namespaces;
}
public void loadInputSchema(String inputSchema)
throws IOException, WSDLException, SAXException,
ParserConfigurationException
{
Document doc = XMLUtils.newDocument(inputSchema);
Element root = doc.getDocumentElement();
if (root.getLocalName().equals("schema") &&
Constants.isSchemaXSD(root.getNamespaceURI()))
{
Node schema = docHolder.importNode(root, true);
if (null == wsdlTypesElem)
{
writeWsdlTypesElement();
}
wsdlTypesElem.appendChild(schema);
BaseTypeMapping btm =
new BaseTypeMapping()
{
public String getBaseName(QName qNameIn)
{
QName qName = new QName(qNameIn.getNamespaceURI(),
qNameIn.getLocalPart());
Class cls = defaultTM.getClassForQName(qName);
if (cls == null)
return null;
else
return JavaUtils.getTextClassName(cls.getName());
}
};
SymbolTable symbolTable = new SymbolTable(btm,
true, false, false);
symbolTable.populateTypes(new URL(inputSchema), doc);
processSymTabEntries(symbolTable);
}
else
{
;
}
}
private void processSymTabEntries(SymbolTable symbolTable)
{
Iterator iterator = symbolTable.getElementIndex().keySet().iterator();
while (iterator.hasNext())
{
QName name = (QName)iterator.next();
addToElementsList(name);
}
iterator = symbolTable.getTypeIndex().keySet().iterator();
while (iterator.hasNext())
{
QName name = (QName)iterator.next();
addToTypesList(name);
}
}
public void loadInputTypes(String inputWSDL)
throws IOException, WSDLException,
SAXException, ParserConfigurationException
{
Document doc = XMLUtils.newDocument(inputWSDL);
NodeList elements = doc.getChildNodes();
if (elements.getLength() > 0 &&
elements.item(0).getLocalName().equals("definitions"))
{
elements = elements.item(0).getChildNodes();
for (int i = 0;
i < elements.getLength() && wsdlTypesElem == null;
i++)
{
Node node = elements.item(i);
if (node.getLocalName() != null &&
node.getLocalName().equals("types"))
{
wsdlTypesElem = (Element)node;
}
}
}
if (wsdlTypesElem == null)
{
return;
}
wsdlTypesElem =
(Element)docHolder.importNode(wsdlTypesElem, true);
docHolder.appendChild(wsdlTypesElem);
BaseTypeMapping btm =
new BaseTypeMapping()
{
public String getBaseName(QName qNameIn)
{
QName qName = new QName(qNameIn.getNamespaceURI(),
qNameIn.getLocalPart());
Class cls = defaultTM.getClassForQName(qName);
if (cls == null)
return null;
else
return JavaUtils.getTextClassName(cls.getName());
}
};
SymbolTable symbolTable = new SymbolTable(btm,
true, false, false);
symbolTable.populate(null, doc);
processSymTabEntries(symbolTable);
}
public QName writeTypeForPart(Class type, QName qname) throws AxisFault
{
if (type.getName().equals("void"))
{
return null;
}
if (Holder.class.isAssignableFrom(type))
{
type = JavaUtils.getHolderValueType(type);
}
if (qname == null ||
(Constants.isSOAP_ENC(qname.getNamespaceURI()) &&
"Array".equals(qname.getLocalPart())))
{
qname = getTypeQName(type);
if (qname == null)
{
throw new AxisFault("Class:" + type.getName());
}
}
if (!makeTypeElement(type, qname, null))
{
qname = Constants.XSD_ANYTYPE;
}
return qname;
}
public QName writeElementForPart(Class type, QName qname) throws AxisFault
{
if (type.getName().equals("void"))
{
return null;
}
if (Holder.class.isAssignableFrom(type))
{
type = JavaUtils.getHolderValueType(type);
}
if (qname == null ||
(Constants.isSOAP_ENC(qname.getNamespaceURI()) &&
"Array".equals(qname.getLocalPart())))
{
qname = getTypeQName(type);
if (qname == null)
{
throw new AxisFault("Class:" + type.getName());
}
}
String nsURI = qname.getNamespaceURI();
if (Constants.isSchemaXSD(nsURI) ||
(Constants.isSOAP_ENC(nsURI) &&
!"Array".equals(qname.getLocalPart())))
{
return null;
}
if (wsdlTypesElem == null)
{
writeWsdlTypesElement();
}
if (writeTypeAsElement(type, qname) == null)
{
qname = null;
}
return qname;
}
public Element writeWrapperElement(QName qname,
boolean request,
boolean hasParams) throws AxisFault
{
if (wsdlTypesElem == null)
{
writeWsdlTypesElement();
}
writeTypeNamespace(qname);
Element wrapperElement = docHolder.createElement("element");
writeSchemaElement(qname, wrapperElement);
wrapperElement.setAttribute("name", qname.getLocalPart());
Element complexType = docHolder.createElement("complexType");
wrapperElement.appendChild(complexType);
if (hasParams)
{
Element sequence = docHolder.createElement("sequence");
complexType.appendChild(sequence);
return sequence;
}
return null;
}
public void writeWrappedParameter(Element sequence, String name,
QName type, Class javaType)
throws AxisFault
{
if (javaType == void.class)
{
return;
}
if (type == null)
{
type = writeTypeForPart(javaType, type);
}
if (type == null)
{
}
Element childElem;
if (isAnonymousType(type))
{
childElem = createElementWithAnonymousType(name, javaType,
false, docHolder);
}
else
{
childElem = docHolder.createElement("element");
childElem.setAttribute("name", name);
String prefix = namespaces.getCreatePrefix(type.getNamespaceURI());
String prefixedName = prefix + ":" + type.getLocalPart();
childElem.setAttribute("type", prefixedName);
}
sequence.appendChild(childElem);
}
private boolean isAnonymousType(QName type)
{
return type.getLocalPart().indexOf(SymbolTable.ANON_TOKEN) != -1;
}
private QName writeTypeAsElement(Class type, QName qName) throws AxisFault
{
if (qName == null ||
Constants.equals(Constants.SOAP_ARRAY, qName))
{
qName = getTypeQName(type);
}
QName typeQName = writeTypeNamespace(type, qName);
String elementType = writeType(type, qName);
if (elementType != null)
{
Element element = createElementDecl(qName.getLocalPart(), type, qName, isNullable(type), false);
if (element != null)
writeSchemaElement(typeQName, element);
return qName;
}
return null;
}
private QName writeTypeNamespace(Class type, QName qName)
{
if (qName == null)
{
qName = getTypeQName(type);
}
writeTypeNamespace(qName);
return qName;
}
private void writeTypeNamespace(QName qName)
{
if (qName != null && !qName.getNamespaceURI().equals(""))
{
String pref = def.getPrefix(qName.getNamespaceURI());
if (pref == null)
def.addNamespace(namespaces.getCreatePrefix(qName.getNamespaceURI()),
qName.getNamespaceURI());
}
}
public QName getTypeQName(Class javaType)
{
QName qName = null;
QName dQName = null;
if (defaultTM != null)
{
dQName = defaultTM.getTypeQName(javaType);
}
if (tm != null)
{
qName = tm.getTypeQName(javaType);
}
if (qName == null)
{
qName = dQName;
}
else if (qName != null && qName != dQName)
{
if (Constants.isSchemaXSD(qName.getNamespaceURI()))
{
qName = dQName;
}
}
if (javaType.isArray() &&
qName != null &&
Constants.equals(Constants.SOAP_ARRAY, qName))
{
Class componentType = javaType.getComponentType();
QName cqName = getTypeQName(componentType);
if (targetNamespace.equals(cqName.getNamespaceURI()))
{
qName = new QName(targetNamespace,
"ArrayOf" + cqName.getLocalPart());
}
else
{
String pre = namespaces.getCreatePrefix(cqName.getNamespaceURI());
qName = new QName(targetNamespace,
"ArrayOf_" + pre + "_" + cqName.getLocalPart());
}
return qName;
}
if (qName == null)
{
String pkg = getPackageNameFromFullName(javaType.getName());
String lcl = getLocalNameFromFullName(javaType.getName());
String ns = namespaces.getCreate(pkg);
namespaces.getCreatePrefix(ns);
String localPart = lcl.replace('$', '_');
qName = new QName(ns, localPart);
}
return qName;
}
public String getQNameString(QName qname)
{
String prefix = namespaces.getCreatePrefix(qname.getNamespaceURI());
return prefix + ":" + qname.getLocalPart();
}
public static String getPackageNameFromFullName(String full)
{
if (full.lastIndexOf('.') < 0)
return "";
else
return full.substring(0, full.lastIndexOf('.'));
}
public static String getLocalNameFromFullName(String full)
{
if (full.lastIndexOf('.') < 0)
return full;
else
return full.substring(full.lastIndexOf('.') + 1);
}
public void writeSchemaElement(QName qName, Element element)
throws AxisFault
{
if (wsdlTypesElem == null)
{
try
{
writeWsdlTypesElement();
}
catch (Exception e)
{
log.error(e);
return;
}
}
String namespaceURI = qName.getNamespaceURI();
if (namespaceURI == null || namespaceURI.equals(""))
{
throw new AxisFault(Constants.FAULT_SERVER_GENERAL,
Messages.getMessage("noNamespace00",
qName.toString()),
null, null);
}
Element schemaElem = null;
NodeList nl = wsdlTypesElem.getChildNodes();
for (int i = 0; i < nl.getLength(); i++)
{
NamedNodeMap attrs = nl.item(i).getAttributes();
if (attrs != null)
{
for (int n = 0; n < attrs.getLength(); n++)
{
Attr a = (Attr)attrs.item(n);
if (a.getName().equals("targetNamespace") &&
a.getValue().equals(namespaceURI))
schemaElem = (Element)nl.item(i);
}
}
}
if (schemaElem == null)
{
schemaElem = docHolder.createElement("schema");
wsdlTypesElem.appendChild(schemaElem);
schemaElem.setAttribute("xmlns", Constants.URI_DEFAULT_SCHEMA_XSD);
schemaElem.setAttribute("targetNamespace", namespaceURI);
if (serviceDesc.getStyle() == Style.RPC)
{
Element importElem = docHolder.createElement("import");
schemaElem.appendChild(importElem);
importElem.setAttribute("namespace", Constants.URI_DEFAULT_SOAP_ENC);
}
writeTypeNamespace(qName);
}
schemaElem.appendChild(element);
}
private void writeWsdlTypesElement()
{
if (wsdlTypesElem == null)
{
wsdlTypesElem =
docHolder.createElementNS(Constants.NS_URI_WSDL11, "types");
wsdlTypesElem.setPrefix(Constants.NS_PREFIX_WSDL);
}
}
public String writeType(Class type) throws AxisFault
{
return writeType(type, null);
}
public String writeType(Class type, QName qName) throws AxisFault
{
if (qName == null ||
Constants.equals(Constants.SOAP_ARRAY, qName))
{
qName = getTypeQName(type);
}
if (!makeTypeElement(type, qName, null))
{
return null;
}
return getQNameString(qName);
}
public Element createArrayElement(String componentTypeName)
{
Element complexType = docHolder.createElement("complexType");
Element complexContent = docHolder.createElement("complexContent");
complexType.appendChild(complexContent);
Element restriction = docHolder.createElement("restriction");
complexContent.appendChild(restriction);
restriction.setAttribute("base",
Constants.NS_PREFIX_SOAP_ENC + ":Array");
Element attribute = docHolder.createElement("attribute");
restriction.appendChild(attribute);
attribute.setAttribute("ref",
Constants.NS_PREFIX_SOAP_ENC + ":arrayType");
attribute.setAttribute(Constants.NS_PREFIX_WSDL + ":arrayType",
componentTypeName);
return complexType;
}
public static boolean isEnumClass(Class cls)
{
try
{
java.lang.reflect.Method m = cls.getMethod("getValue", null);
java.lang.reflect.Method m2 = cls.getMethod("toString", null);
if (m != null && m2 != null)
{
java.lang.reflect.Method m3 =
cls.getDeclaredMethod("fromString",
new Class[]{java.lang.String.class});
java.lang.reflect.Method m4 =
cls.getDeclaredMethod("fromValue",
new Class[]{m.getReturnType()});
if (m3 != null &&
Modifier.isStatic(m3.getModifiers()) &&
Modifier.isPublic(m3.getModifiers()) &&
m4 != null &&
Modifier.isStatic(m4.getModifiers()) &&
Modifier.isPublic(m4.getModifiers()))
{
try
{
if (cls.getMethod("setValue",
new Class[]{m.getReturnType()}) == null)
return true;
return false;
}
catch (java.lang.NoSuchMethodException e)
{
return true;
}
}
}
}
catch (java.lang.NoSuchMethodException e)
{
}
return false;
}
public Element writeEnumType(QName qName, Class cls)
throws NoSuchMethodException, IllegalAccessException, AxisFault
{
if (!isEnumClass(cls))
return null;
java.lang.reflect.Method m = cls.getMethod("getValue", null);
Class base = m.getReturnType();
Element simpleType = docHolder.createElement("simpleType");
simpleType.setAttribute("name", qName.getLocalPart());
Element restriction = docHolder.createElement("restriction");
simpleType.appendChild(restriction);
String baseType = writeType(base, null);
restriction.setAttribute("base", baseType);
Field[] fields = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++)
{
Field field = fields[i];
int mod = field.getModifiers();
if (Modifier.isPublic(mod) &&
Modifier.isStatic(mod) &&
Modifier.isFinal(mod) &&
field.getType() == base)
{
Element enumeration = docHolder.createElement("enumeration");
enumeration.setAttribute("value", field.get(null).toString());
restriction.appendChild(enumeration);
}
}
return simpleType;
}
public Element createElementDecl(String name,
Class javaType,
QName typeQName,
boolean nillable,
boolean omittable) throws AxisFault
{
Element element = docHolder.createElement("element");
element.setAttribute("name", name);
if (nillable)
element.setAttribute("nillable", "true");
if (omittable)
{
element.setAttribute("minOccurs", "0");
element.setAttribute("maxOccurs", "1");
}
makeTypeElement(javaType, typeQName, element);
return element;
}
public Element createElement(String elementName,
String elementType,
boolean nullable,
boolean omittable,
Document docHolder)
{
Element element = docHolder.createElement("element");
element.setAttribute("name", elementName);
if (nullable)
element.setAttribute("nillable", "true");
if (omittable)
{
element.setAttribute("minOccurs", "0");
element.setAttribute("maxOccurs", "1");
}
if (elementType != null)
element.setAttribute("type", elementType);
return element;
}
public Element createAttributeElement(String elementName,
Class javaType,
QName xmlType,
boolean nullable,
Document docHolder) throws AxisFault
{
Element element = docHolder.createElement("attribute");
element.setAttribute("name", elementName);
if (nullable)
element.setAttribute("nillable", "true");
makeTypeElement(javaType, xmlType, element);
return element;
}
boolean isSimpleType(Class type)
{
QName qname = tm.getTypeQName(type);
if (qname == null)
return false;
String nsURI = qname.getNamespaceURI();
return (Constants.isSchemaXSD(nsURI) ||
Constants.isSOAP_ENC(nsURI));
}
public boolean isAcceptableAsAttribute(Class type)
{
return isSimpleType(type) ||
isEnumClass(type) ||
implementsSimpleType(type);
}
boolean implementsSimpleType(Class type)
{
Class[] impls = type.getInterfaces();
for (int i = 0; i < impls.length; i++)
{
if (impls[i] == SimpleType.class)
{
return true;
}
}
return false;
}
private boolean addToTypesList(QName qName)
{
boolean added = false;
ArrayList types = (ArrayList)schemaTypes.get(qName.getNamespaceURI());
if (Constants.isSchemaXSD(qName.getNamespaceURI()) ||
(Constants.isSOAP_ENC(qName.getNamespaceURI()) &&
!"Array".equals(qName.getLocalPart())))
{
writeTypeNamespace(qName);
return false;
}
if (types == null)
{
types = new ArrayList();
types.add(qName.getLocalPart());
schemaTypes.put(qName.getNamespaceURI(), types);
added = true;
}
else
{
if (!types.contains(qName.getLocalPart()))
{
types.add(qName.getLocalPart());
added = true;
}
}
if (added)
{
String prefix = namespaces.getCreatePrefix(qName.getNamespaceURI());
if (prefix.equals(Constants.NS_PREFIX_SOAP_ENV) ||
prefix.equals(Constants.NS_PREFIX_SOAP_ENC) ||
prefix.equals(Constants.NS_PREFIX_SCHEMA_XSD) ||
prefix.equals(Constants.NS_PREFIX_WSDL) ||
prefix.equals(Constants.NS_PREFIX_WSDL_SOAP))
return false;
else
return true;
}
return false;
}
private boolean addToElementsList(QName qName)
{
if (qName == null)
{
return false;
}
boolean added = false;
ArrayList elements = (ArrayList)schemaElementNames.get(qName.getNamespaceURI());
if (elements == null)
{
elements = new ArrayList();
elements.add(qName.getLocalPart());
schemaElementNames.put(qName.getNamespaceURI(), elements);
added = true;
}
else
{
if (!elements.contains(qName.getLocalPart()))
{
elements.add(qName.getLocalPart());
added = true;
}
}
return added;
}
public boolean isNullable(Class type)
{
if (type.isPrimitive() ||
(type.isArray() && type.getComponentType() == byte.class))
return false;
else
return true;
}
Document docHolder;
private void createDocumentFragment()
{
try
{
this.docHolder = XMLUtils.newDocument();
}
catch (ParserConfigurationException e)
{
throw new InternalException(e);
}
}
public void updateNamespaces()
{
Namespaces namespaces = getNamespaces();
Iterator nspIterator = namespaces.getNamespaces();
while (nspIterator.hasNext())
{
String nsp = (String)nspIterator.next();
String pref = def.getPrefix(nsp);
if (pref == null)
{
def.addNamespace(namespaces.getCreatePrefix(nsp), nsp);
}
}
}
public void insertTypesFragment(Document doc)
{
updateNamespaces();
if (wsdlTypesElem != null)
{
org.w3c.dom.Node node = doc.importNode(wsdlTypesElem, true);
doc.getDocumentElement().
insertBefore(node,
doc.getDocumentElement().getFirstChild());
}
}
public List getStopClasses()
{
return stopClasses;
}
public Element createElement(String elementName)
{
return docHolder.createElement(elementName);
}
public Element createElementWithAnonymousType(String elementName,
Class fieldType,
boolean omittable,
Document ownerDocument) throws AxisFault
{
Element element = docHolder.createElement("element");
element.setAttribute("name", elementName);
if (isNullable(fieldType))
element.setAttribute("nillable", "true");
if (omittable)
{
element.setAttribute("minOccurs", "0");
element.setAttribute("maxOccurs", "1");
}
makeTypeElement(fieldType, null, element);
return element;
}
private boolean makeTypeElement(Class type,
QName qName,
Element containingElement) throws AxisFault
{
if (qName == null ||
Constants.equals(Constants.SOAP_ARRAY, qName))
{
qName = getTypeQName(type);
}
boolean anonymous = isAnonymousType(qName);
if (anonymous && containingElement == null)
{
throw new AxisFault(Messages.getMessage("noContainerForAnonymousType",
qName.toString()));
}
if (!addToTypesList(qName))
{
if (containingElement != null)
containingElement.setAttribute("type", getQNameString(qName));
return true;
}
Serializer ser = null;
SerializerFactory factory = null;
if (tm != null)
{
factory = (SerializerFactory)tm.getSerializer(type);
}
else
{
factory = (SerializerFactory)defaultTM.getSerializer(type);
}
if (factory == null)
{
if (isEnumClass(type))
{
factory = new EnumSerializerFactory(type, qName);
}
else if (JavaUtils.isBeanCompatible(type))
{
factory = new BeanSerializerFactory(type, qName);
}
else
{
return false;
}
}
if (factory != null)
{
ser = (Serializer)factory.getSerializerAs(Constants.AXIS_SAX);
}
if (ser == null)
{
throw new AxisFault(Messages.getMessage("NoSerializer00", type.getName()));
}
Element typeEl;
try
{
typeEl = ser.writeSchema(type, this);
}
catch (Exception e)
{
throw AxisFault.makeFault(e);
}
if (anonymous)
{
containingElement.appendChild(typeEl);
}
else
{
if (typeEl != null)
{
typeEl.setAttribute("name", qName.getLocalPart());
writeSchemaElement(qName, typeEl);
}
if (containingElement != null)
containingElement.setAttribute("type", getQNameString(qName));
}
return true;
}
}