Java tutorial
/* * Copyright (c) 2001-2011 Convertigo SA. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. * * $URL$ * $Author$ * $Revision$ * $Date$ */ package com.twinsoft.convertigo.beans.transactions; import java.io.File; import java.nio.charset.Charset; import javax.xml.namespace.QName; import javax.xml.soap.SOAPException; import org.apache.commons.lang3.StringUtils; import org.apache.ws.commons.schema.XmlSchema; import org.apache.ws.commons.schema.XmlSchemaCollection; import org.apache.ws.commons.schema.XmlSchemaComplexType; import org.apache.ws.commons.schema.XmlSchemaElement; import org.apache.ws.commons.schema.XmlSchemaImport; import org.apache.ws.commons.schema.XmlSchemaInclude; import org.apache.ws.commons.schema.XmlSchemaSequence; import org.apache.ws.commons.schema.constants.Constants; import org.apache.xpath.XPathAPI; 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 com.twinsoft.convertigo.beans.common.XmlQName; import com.twinsoft.convertigo.beans.core.IElementRefAffectation; import com.twinsoft.convertigo.engine.ConvertigoError; import com.twinsoft.convertigo.engine.ConvertigoException; import com.twinsoft.convertigo.engine.Engine; import com.twinsoft.convertigo.engine.enums.ErrorType; import com.twinsoft.convertigo.engine.util.SchemaUtils; import com.twinsoft.convertigo.engine.util.VersionUtils; import com.twinsoft.convertigo.engine.util.XMLUtils; import com.twinsoft.convertigo.engine.util.XmlSchemaUtils; public class XmlHttpTransaction extends AbstractHttpTransaction implements IElementRefAffectation { private String xmlEncoding = "ISO-8859-1"; private String responseElementQName = ""; private XmlQName xmlElementRefAffectation = new XmlQName(); private boolean ignoreSoapEnveloppe = false; private boolean errorOnSoapFault = true; private static final long serialVersionUID = 1494278577299328199L; public XmlHttpTransaction() { super(); } public String getXmlEncoding() { return xmlEncoding; } public void setXmlEncoding(String xmlEncoding) { this.xmlEncoding = xmlEncoding; } /** * @return the responseElementQName */ public String getResponseElementQName() { return responseElementQName; } /** * @param responseElementQName the responseElementQName to set */ public void setResponseElementQName(String responseElementQName) { this.responseElementQName = responseElementQName; } /** * @return the ignoreSoapEnveloppe */ public boolean isIgnoreSoapEnveloppe() { return ignoreSoapEnveloppe; } /** * @param ignoreSoapEnveloppe the ignoreSoapEnveloppe to set */ public void setIgnoreSoapEnveloppe(boolean ignoreSoapEnveloppe) { this.ignoreSoapEnveloppe = ignoreSoapEnveloppe; } /** * @return the errorOnSoapFault */ public boolean isErrorOnSoapFault() { return errorOnSoapFault; } /** * @param errorOnSoapFault the errorOnSoapFault to set */ public void setErrorOnSoapFault(boolean errorOnSoapFault) { this.errorOnSoapFault = errorOnSoapFault; } @Override public void configure(Element element) throws Exception { super.configure(element); String version = element.getAttribute("version"); if (VersionUtils.compare(version, "7.3.0") < 0) { NodeList properties = element.getElementsByTagName("property"); Element propVarDom = (Element) XMLUtils.findNodeByAttributeValue(properties, "name", "errorOnSoapFault"); if (propVarDom == null) { errorOnSoapFault = false; hasChanged = true; Engine.logBeans.warn("[Project] Successfully set 'errorOnSoapFault' property for project \"" + getName() + "\" (v 7.3.0)"); } } } @Override public void makeDocument(byte[] httpData) throws Exception { Engine.logBeans.trace("makeDocument : " + getEncodingCharSet()); Charset charset = XMLUtils.getEncoding(httpData, Charset.forName(xmlEncoding)); String sdata = new String(httpData, charset); sdata = sdata.replaceFirst("[\\d\\D]*?<", "<"); Engine.logBeans.trace("makeDocument afternewString: " + sdata); Document xmlHttpDocument = requester.parseDOM(sdata); if (Engine.logBeans.isTraceEnabled()) Engine.logBeans.trace("makeDocument after parseDom: " + XMLUtils.prettyPrintDOM(xmlHttpDocument)); // Replace SOAP fault by an c8o error element if (isErrorOnSoapFault()) { Element soapFaultElement = null; soapFaultElement = getSoapFaultElement(xmlHttpDocument); if (soapFaultElement != null) { String sfm = getSoapFaultMessage(soapFaultElement); ConvertigoException ex = new ConvertigoException("The Web Service returned a SOAP Fault", new SOAPException(sfm)); ConvertigoError err = ConvertigoError.initError(ErrorType.Project, ex); Document errDocument = err.buildErrorDocument(getRequester(), context); Node error = context.outputDocument.importNode(errDocument.getDocumentElement().getFirstChild(), true); context.outputDocument.getDocumentElement().appendChild(error); return; } } if (getAllowDownloadAttachment()) { Element attachmentInfo = (Element) XPathAPI.selectSingleNode(context.outputDocument, "/document/AttachmentInfo"); if (attachmentInfo != null) { NodeList nl = XPathAPI.selectNodeList(attachmentInfo, "attachment"); for (int i = 0; i < nl.getLength(); i++) { Element attachment = (Element) nl.item(i); String cid = attachment.getAttribute("cid"); if (StringUtils.isNotBlank(cid)) { Element include = (Element) XPathAPI.selectSingleNode(xmlHttpDocument, "//*[local-name()='Include' and @href='" + cid + "']"); if (include != null) { include.appendChild(xmlHttpDocument.importNode(attachment, true)); XMLUtils.removeNode(attachment); } } } if (XPathAPI.selectSingleNode(attachmentInfo, "attachment") == null) { XMLUtils.removeNode(attachmentInfo); } } } // Removes soap elements if needed if (isIgnoreSoapEnveloppe()) { Element soapBodyResponseElement = null; soapBodyResponseElement = getSoapBodyResponseElement(xmlHttpDocument.getDocumentElement()); if (soapBodyResponseElement != null) { NamedNodeMap attributes = ((Element) soapBodyResponseElement.getParentNode()).getAttributes(); NodeList childNodes = soapBodyResponseElement.getChildNodes(); int len = childNodes.getLength(); Node child, node; for (int i = 0; i < len; i++) { node = childNodes.item(i); if (node instanceof Element) { //child = importNodeWithNoPrefix(context.outputDocument, node, true); child = context.outputDocument.importNode(node, true); // add envelope attributes (e.g namespace declarations to avoid unbound prefixes for XSL transformation) for (int j = 0; j < attributes.getLength(); j++) { Node attr = attributes.item(j); ((Element) child) .setAttributeNode((Attr) context.outputDocument.importNode(attr, true)); } context.outputDocument.getDocumentElement().appendChild(child); } } } else { XMLUtils.copyDocument(xmlHttpDocument, context.outputDocument); } } // Normal case else XMLUtils.copyDocument(xmlHttpDocument, context.outputDocument); } // private Node importNodeWithNoPrefix(Document document, Node node, boolean deep) { // Node newNode = null; // // if (node instanceof Element) { // String localName = node.getNodeName().substring(node.getNodeName().indexOf(":")+1); // newNode = document.createElement(localName); // // NodeList childNodes = node.getChildNodes(); // int len = childNodes.getLength(); // Node child; // for (int i = 0 ; i < len ; i++) { // child = childNodes.item(i); // if (deep && (child instanceof Element)) { // newNode.appendChild(importNodeWithNoPrefix(document, child, deep)); // } // else { // newNode.appendChild(document.importNode(child, deep)); // } // } // } // // return newNode; // } private String getSoapFaultMessage(Element element) { String message = "unknow reason"; if (element != null) { NodeList childNodes = element.getChildNodes(); int len = childNodes.getLength(); Node node; for (int i = 0; i < len; i++) { node = childNodes.item(i); if (node instanceof Element) { String ename = ((Element) node).getNodeName().toUpperCase(); if (ename.equals("FAULTSTRING")) { // SOAP 1.1 return ((Element) node).getTextContent(); } else if (ename.equals("TEXT")) { // SOAP 1.2 return ((Element) node).getTextContent(); } else if (ename.indexOf(":REASON") != -1) { // SOAP 1.2 return getSoapFaultMessage((Element) node); } } } } return message; } private Element getSoapFaultElement(Document document) { Element soapBodyResponseElement = null; soapBodyResponseElement = getSoapBodyResponseElement(document.getDocumentElement()); if (soapBodyResponseElement != null) { NodeList childNodes = soapBodyResponseElement.getChildNodes(); int len = childNodes.getLength(); Node node; for (int i = 0; i < len; i++) { node = childNodes.item(i); if (node instanceof Element) { String ename = ((Element) node).getNodeName().toUpperCase(); if (ename.indexOf(":FAULT") != -1) { return ((Element) node); } } } } return null; } private Element getSoapBodyResponseElement(Element element) { NodeList childNodes = element.getChildNodes(); int len = childNodes.getLength(); Element soapBody = null; Node node; for (int i = 0; i < len; i++) { node = childNodes.item(i); if (node instanceof Element) { String ename = ((Element) node).getNodeName().toUpperCase(); if ((ename.indexOf("SOAPENV:") != -1) || (ename.indexOf("SOAP-ENV:") != -1) || (ename.indexOf("SOAP:") != -1)) { if (ename.indexOf(":BODY") != -1) { soapBody = ((Element) node); } else { soapBody = getSoapBodyResponseElement((Element) node); } } } if (soapBody != null) { return soapBody; } } return null; } @Override protected String extractXsdType(Document document) throws Exception { XmlQName xmlQName = getXmlElementRefAffectation(); String reqn = getResponseElementQName(); if (!reqn.equals("") || !xmlQName.isEmpty()) return generateWsdlType(document); return super.extractXsdType(document); } @Override public String generateWsdlType(Document document) throws Exception { XmlQName xmlQName = getXmlElementRefAffectation(); String reqn = getResponseElementQName(); if (!reqn.equals("") || !xmlQName.isEmpty()) { // String opName = getName()+"Response", eltName = "response", eltType = "xsd:string"; // boolean useRef = true; // int index, index2; // if ((index = reqn.indexOf(";")) != -1) { // useRef = false; // opName = reqn.substring(0, index); // if ((index2 = reqn.indexOf(";", index+1)) != -1) { // eltName = reqn.substring(index+1,index2); // eltType = reqn.substring(index2+1); // } // } // // String prefix = getXsdTypePrefix(); // String xsdType = ""; // xsdType += "<xsd:complexType name=\""+ prefix + getName() +"Response" +"\" >\n"; // xsdType += " <xsd:sequence>\n"; // if (useRef) // xsdType += " <xsd:element ref=\""+ reqn +"\"/>\n"; // else { // xsdType += " <xsd:element name=\""+ opName +"\">\n"; // xsdType += " <xsd:complexType>\n"; // xsdType += " <xsd:sequence>\n"; // xsdType += " <xsd:element name=\""+ eltName +"\" type=\""+ eltType +"\"/>\n"; // xsdType += " </xsd:sequence>\n"; // xsdType += " </xsd:complexType>\n"; // xsdType += " </xsd:element>\n"; // } // xsdType += " </xsd:sequence>\n"; // xsdType += "</xsd:complexType>\n"; String xsdType = "<xsd:complexType name=\"" + getXsdResponseElementName() + "\" />\n"; try { XmlSchema xmlSchema = createSchema(); XmlSchemaComplexType cType = (XmlSchemaComplexType) xmlSchema .getTypeByName(getXsdResponseTypeName()); xsdType = cType.toString("xsd", 0); } catch (Exception e) { e.printStackTrace(); } return xsdType; } return super.generateWsdlType(document); } /* private void dumpByteArray(byte[] data) { byte c[] = new byte[1]; for (int j=0; j <data.length; j+= 80) { String displayH =""; String displayC =""; for (int i=0; i < 80; i++) { if ((i+j) < data.length) { byte b = data[i+j]; if (b < 16) { displayH += "0" + Integer.toHexString(b) + " "; } else { displayH += Integer.toHexString(b) + " ";; } c[0] = b; displayC += new String(c) + " "; } } Engine.logBeans.debug(displayH); Engine.logBeans.debug(displayC); } } */ @Override public void writeSchemaToFile(String xsdTypes) { XmlQName xmlQName = getXmlElementRefAffectation(); boolean bRPC = getResponseElementQName().indexOf(";") != -1; if (!xmlQName.isEmpty() || bRPC) { try { XmlSchema xmlSchema = createSchema(); String ns = getElementRefAffectation().getNamespaceURI(); XmlSchemaCollection collection = Engine.theApp.schemaManager .getSchemasForProject(getProject().getName()); XmlSchema referenced = collection.schemaForNamespace(ns); if (referenced != null) { if (ns.equals(xmlSchema.getTargetNamespace())) { XmlSchemaInclude xmlSchemaInclude = new XmlSchemaInclude(); xmlSchemaInclude.setSchemaLocation(referenced.getSourceURI()); xmlSchemaInclude.setSchema(referenced); XmlSchemaUtils.add(xmlSchema, xmlSchemaInclude); } else { XmlSchemaImport xmlSchemaImport = new XmlSchemaImport(); xmlSchemaImport.setNamespace(referenced.getTargetNamespace()); xmlSchemaImport.setSchemaLocation(referenced.getSourceURI()); xmlSchemaImport.setSchema(referenced); XmlSchemaUtils.add(xmlSchema, xmlSchemaImport); } } new File(getSchemaFileDirPath()).mkdirs(); SchemaUtils.saveSchema(getSchemaFilePath(), xmlSchema); } catch (Exception e) { e.printStackTrace(); } } else { super.writeSchemaToFile(xsdTypes); } } @SuppressWarnings("unused") @Override public XmlSchemaInclude getXmlSchemaObject(XmlSchemaCollection collection, XmlSchema schema) { XmlQName xmlQName = getXmlElementRefAffectation(); String reqn = getResponseElementQName(); if (!xmlQName.isEmpty() || !reqn.equals("")) { long timeStart = System.currentTimeMillis(); XmlSchemaInclude xmlSchemaInclude = new XmlSchemaInclude(); XmlSchema transactionSchema = createSchema(); if (transactionSchema != null) { // Transformer transformer = TransformerFactory.newInstance().newTransformer(); // transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); // transformer.transform(new DOMSource(transactionSchema.getSchemaDocument()), new StreamResult(System.out)); xmlSchemaInclude.setSchema(transactionSchema); } long timeStop = System.currentTimeMillis(); // System.out.println("Schema for \"" + getName() + "\" | Times >> total : " + (timeStop - timeStart) + " ms"); return xmlSchemaInclude; } else { return super.getXmlSchemaObject(collection, schema); } } @Override protected XmlSchemaComplexType addSchemaResponseDataType(XmlSchema xmlSchema) { XmlSchemaComplexType xmlSchemaComplexType = super.addSchemaResponseDataType(xmlSchema); XmlQName xmlQName = getXmlElementRefAffectation(); boolean bRPC = getResponseElementQName().indexOf(";") != -1; if (!xmlQName.isEmpty() || bRPC) { XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) xmlSchemaComplexType.getParticle(); if (xmlSchemaSequence == null) xmlSchemaSequence = new XmlSchemaSequence(); XmlSchemaElement xmlSchemaElement = new XmlSchemaElement(); if (bRPC) { // response is based on an element defined with a type String reqn = getResponseElementQName();// operationResponse element name; element name; element type String opName = getName() + "Response", eltName = "response", eltType = "{" + Constants.URI_2001_SCHEMA_XSD + "}string"; QName typeName = Constants.XSD_STRING; int i, j, k, z; if ((i = reqn.indexOf(";")) != -1) { opName = reqn.substring(0, i); if ((j = reqn.indexOf(";", i + 1)) != -1) { eltName = reqn.substring(i + 1, j); eltType = reqn.substring(j + 1); if ((k = eltType.indexOf("{")) != -1) { if ((z = eltType.indexOf("}")) != -1) { String ns = eltType.substring(k + 1, z); String local = eltType.substring(z + 1); typeName = new QName(ns, local); } } } } xmlSchemaElement.setName(opName); XmlSchemaComplexType cType = new XmlSchemaComplexType(xmlSchema); XmlSchemaSequence seq = new XmlSchemaSequence(); XmlSchemaElement elem = new XmlSchemaElement(); elem.setName(eltName); elem.setSchemaTypeName(typeName); seq.getItems().add(elem); cType.setParticle(seq); xmlSchemaElement.setSchemaType(cType); } else { xmlSchemaElement.setName(""); xmlSchemaElement.setRefName(xmlQName.getQName()); } if (isErrorOnSoapFault()) { xmlSchemaElement.setMinOccurs(0); } xmlSchemaSequence.getItems().add(xmlSchemaElement); xmlSchemaComplexType.setParticle(xmlSchemaSequence); } return xmlSchemaComplexType; } public XmlQName getXmlElementRefAffectation() { return xmlElementRefAffectation; } public void setXmlElementRefAffectation(XmlQName xmlComplexTypeAffectation) { this.xmlElementRefAffectation = xmlComplexTypeAffectation; } public QName getElementRefAffectation() { return getXmlElementRefAffectation().getQName(); } }