/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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. * * * Copyright 2005 - 2008 Pentaho Corporation. All rights reserved. * * @created Jul 17, 2005 * @author James Dixon * */ package org.pentaho.platform.engine.services; import java.io.IOException; import java.io.OutputStream; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.tree.DefaultElement; import org.pentaho.commons.connection.IPentahoResultSet; import org.pentaho.platform.api.engine.IOutputHandler; import org.pentaho.platform.api.engine.IRuntimeContext; import org.pentaho.platform.api.repository.IContentItem; import org.pentaho.platform.engine.core.output.SimpleOutputHandler; import org.pentaho.platform.engine.services.messages.Messages; import org.pentaho.platform.util.messages.LocaleHelper; public class SoapHelper { private static final Log logger = LogFactory.getLog(SoapHelper.class); public static String getSoapHeader() { return "<SOAP-ENV:Envelope " + //$NON-NLS-1$ "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" " + //$NON-NLS-1$ "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n " + //$NON-NLS-1$ "<SOAP-ENV:Body>\n"; //$NON-NLS-1$ } public static String getSoapFooter() { return "</SOAP-ENV:Body>\n</SOAP-ENV:Envelope>"; //$NON-NLS-1$ } public static String openSoapResponse() { return "<ExecuteActivityResponse xmlns:m=\"http://pentaho.org\">\n"; //$NON-NLS-1$ } public static String closeSoapResponse() { return "</ExecuteActivityResponse>\n"; //$NON-NLS-1$ } private static Element createActivityResponseElement() { Element element = new DefaultElement("ExecuteActivityResponse"); element.addAttribute("xmlns:m", "http://pentaho.org"); return element; } private static Element createSoapElement(String name, Object value) { if (value instanceof String) { return createSoapElement(name, (String) value); } else if (value instanceof List) { return createSoapElement(name, (List) value); } else if (value instanceof IPentahoResultSet) { return createSoapElement(name, (IPentahoResultSet) value); } else if (value instanceof IContentItem) { return createSoapElement(name, ((IContentItem) value).getId()); } return null; } private static Element createSoapElement(String name, String value) { Element element = new DefaultElement(name); element.addCDATA(value); return element; } private static Element createSoapElement(String name, List value) { Element element = new DefaultElement(name); element.addCDATA(value.toString()); return element; } private static Element createSoapElement(String name, IPentahoResultSet resultSet) { Element resultSetElement = new DefaultElement(name); Object[][] columnHeaders = resultSet.getMetaData().getColumnHeaders(); Object[][] rowHeaders = resultSet.getMetaData().getRowHeaders(); boolean hasColumnHeaders = columnHeaders != null; boolean hasRowHeaders = rowHeaders != null; if (hasColumnHeaders) { for (Object[] element : columnHeaders) { Element columnHeaderRowElement = resultSetElement.addElement("COLUMN-HDR-ROW"); //$NON-NLS-1$ for (int column = 0; column < element.length; column++) { columnHeaderRowElement.addElement("COLUMN-HDR-ITEM").addCDATA(element[column].toString()); //$NON-NLS-1$ } } } if (hasRowHeaders) { for (Object[] element : rowHeaders) { Element rowHeaderRowElement = resultSetElement.addElement("ROW-HDR-ROW"); //$NON-NLS-1$ for (int column = 0; column < element.length; column++) { rowHeaderRowElement.addElement("ROW-HDR-ITEM").addCDATA(element[column].toString()); //$NON-NLS-1$ } } } Object[] dataRow = resultSet.next(); while (dataRow != null) { Element dataRowElement = resultSetElement.addElement("DATA-ROW"); //$NON-NLS-1$ for (Object element : dataRow) { dataRowElement.addElement("DATA-ITEM").addCDATA(element.toString()); //$NON-NLS-1$ } dataRow = resultSet.next(); } return resultSetElement; } private static Element createSoapEnvelope() { Element envelope = new DefaultElement("SOAP-ENV:Envelope"); envelope.addAttribute("xmlns:SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"); envelope.addAttribute("SOAP-ENV:encodingStyle", "http://schemas.xmlsoap.org/soap/encoding/"); return envelope; } private static Element createSoapBody() { return new DefaultElement("SOAP-ENV:Body"); } public static Document createSoapDocument() { Document document = DocumentHelper.createDocument(); Element envelope = createSoapEnvelope(); document.setRootElement(envelope); envelope.add(createSoapBody()); return document; } public static Document createSoapResponseDocument(Document[] documents) { return createSoapResponseDocument(documents, "content"); } public static Document createSoapResponseDocument(Document responseXml) { return createSoapResponseDocument(responseXml, "content"); } private static Element createSoapFaultElement(List messages) { Element faultElement = new DefaultElement("SOAP-ENV:Fault"); // TODO mlowery begin hack: copied in getFirstError code from MessageFormatter // to avoid needing an IPentahoSession String message = null; String errorStart = PentahoMessenger.getUserString("ERROR"); //$NON-NLS-1$ int pos = errorStart.indexOf('{'); if (pos != -1) { errorStart = errorStart.substring(0, pos); } Iterator msgIterator = messages.iterator(); while (msgIterator.hasNext()) { String msg = (String) msgIterator.next(); if (msg.indexOf(errorStart) == 0) { message = msg; } } // TODO mlowery end hack if (message == null) { message = Messages.getInstance().getErrorString("SoapHelper.ERROR_0001_UNKNOWN_ERROR"); //$NON-NLS-1$ } // Envelope envelope = new Envelope(); // Fault fault = new Fault( ); // TODO: Generate the following message using the envelope and fault objects // TODO determine if this is a reciever or a sender problem by examining // the error code boolean senderFault = (message.indexOf("SolutionEngine.ERROR_0002") != -1) || //$NON-NLS-1$ // solution not specifed (message.indexOf("SolutionEngine.ERROR_0003") != -1) || //$NON-NLS-1$ // Path not specifeid (message.indexOf("SolutionEngine.ERROR_0004") != -1) || //$NON-NLS-1$ // Action not specified (message.indexOf("SolutionEngine.ERROR_0005") != -1); //$NON-NLS-1$ // Action not found // send the error code // TODO parse out the error code faultElement .addElement("SOAP-ENV:Fault").addElement("SOAP-ENV:Subcode").addElement("SOAP-ENV:Value").addCDATA(message); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (senderFault) { faultElement.addElement("SOAP-ENV:faultactor").setText("SOAP-ENV:Client"); //$NON-NLS-1$ //$NON-NLS-2$ } else { faultElement.addElement("SOAP-ENV:faultactor").setText("SOAP-ENV:Server"); //$NON-NLS-1$ //$NON-NLS-2$ } Element faultTextElement = faultElement.addElement("SOAP-ENV:faultstring").addElement("SOAP-ENV:Text"); faultTextElement.addAttribute("xml:lang", LocaleHelper.getDefaultLocale().toString()); faultTextElement.addCDATA(message); Element detailElement = faultElement.addElement("SOAP-ENV:Detail"); Iterator messageIterator = messages.iterator(); while (messageIterator.hasNext()) { detailElement.addElement("message").addAttribute("name", "trace").addCDATA((String) messageIterator.next()); } return faultElement; } public static Document createSoapResponseDocument(IRuntimeContext context, SimpleOutputHandler outputHandler, OutputStream contentStream, List messages) { Document document = createSoapDocument(); if ((context == null) || (context.getStatus() != IRuntimeContext.RUNTIME_STATUS_SUCCESS)) { document.getRootElement().element("SOAP-ENV:Body").add(createSoapFaultElement(messages)); //$NON-NLS-1$ } else { Element activityResponse = createActivityResponseElement(); document.getRootElement().element("SOAP-ENV:Body").add(activityResponse); //$NON-NLS-1$ IContentItem contentItem = outputHandler.getFeedbackContentItem(); // hmm do we need this to be ordered? Set outputNames = context.getOutputNames(); Iterator outputNameIterator = outputNames.iterator(); while (outputNameIterator.hasNext()) { String outputName = (String) outputNameIterator.next(); contentItem = outputHandler.getOutputContentItem(IOutputHandler.RESPONSE, IOutputHandler.CONTENT, context .getSolutionName(), context.getInstanceId(), "text/xml"); //$NON-NLS-1$ if ((outputNames.size() == 1) && (contentItem != null)) { String mimeType = contentItem.getMimeType(); if ((mimeType != null) && mimeType.startsWith("text/")) { //$NON-NLS-1$ if (mimeType.equals("text/xml")) { //$NON-NLS-1$ activityResponse.addElement(outputName).setText(contentStream.toString()); } else if (mimeType.startsWith("text/")) { //$NON-NLS-1$ activityResponse.addElement(outputName).addCDATA(contentStream.toString()); } } else { Object value = context.getOutputParameter(outputName).getValue(); if (value == null) { value = ""; //$NON-NLS-1$ } activityResponse.add(createSoapElement(outputName, value)); } } else { Object value = context.getOutputParameter(outputName).getValue(); if (value == null) { value = ""; //$NON-NLS-1$ } activityResponse.add(createSoapElement(outputName, value)); } } } return document; } public static Document createSoapResponseDocument(Document[] documents, String contentNodeName) { Document document = createSoapDocument(); Element activityResponse = createActivityResponseElement(); document.getRootElement().element("SOAP-ENV:Body").add(activityResponse); Element contentElement = activityResponse.addElement(contentNodeName); for (Document contentDocument : documents) { if ((contentDocument != null) && (contentDocument.getRootElement() != null)) { contentElement.add(contentDocument.getRootElement()); } } return document; } public static Document createSoapResponseDocument(Document contentDocument, String contentNodeName) { Document document = createSoapDocument(); Element activityResponse = createActivityResponseElement(); document.getRootElement().element("SOAP-ENV:Body").add(activityResponse); Element contentElement = activityResponse.addElement(contentNodeName); if ((contentDocument != null) && (contentDocument.getRootElement() != null)) { contentElement.add(contentDocument.getRootElement()); } return document; } public static Document createSoapResponseDocument(String responseString) { return createSoapResponseDocument(responseString, "content"); } public static Document createSoapResponseDocument(String responseString, String contentNodeName) { Document document = createSoapDocument(); Element activityResponse = document.getRootElement().element("SOAP-ENV:Body").addElement("ExecuteActivityResponse").addAttribute("xmlns:m", "\"http://pentaho.org\""); Element contentElement = activityResponse.addElement(contentNodeName); contentElement.setText(responseString); return document; } }