org.pentaho.platform.plugin.action.xmla.XMLABaseComponent.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.platform.plugin.action.xmla.XMLABaseComponent.java

Source

/*!
 * This program is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
 * Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.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 Lesser General Public License for more details.
 *
 * Copyright (c) 2002-2013 Pentaho Corporation..  All rights reserved.
 */

package org.pentaho.platform.plugin.action.xmla;

import org.apache.commons.logging.Log;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.commons.connection.memory.MemoryMetaData;
import org.pentaho.commons.connection.memory.MemoryResultSet;
import org.pentaho.platform.api.data.IDataComponent;
import org.pentaho.platform.engine.services.solution.ComponentBase;
import org.pentaho.platform.plugin.action.messages.Messages;

import javax.xml.soap.Detail;
import javax.xml.soap.DetailEntry;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.Name;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Locale;

public abstract class XMLABaseComponent extends ComponentBase implements IDataComponent {

    private static final long serialVersionUID = 8405489984774339891L;

    private static final String MDD_URI = "urn:schemas-microsoft-com:xml-analysis:mddataset"; //$NON-NLS-1$

    private static final String ROWS_URI = "urn:schemas-microsoft-com:xml-analysis:rowset"; //$NON-NLS-1$

    private static final String XMLA_URI = "urn:schemas-microsoft-com:xml-analysis"; //$NON-NLS-1$

    private static final String EXECUTE_ACTION = "\"urn:schemas-microsoft-com:xml-analysis:Execute\""; //$NON-NLS-1$

    private static final String ENCODING_STYLE = "http://schemas.xmlsoap.org/soap/encoding/"; //$NON-NLS-1$

    private static final String URI = "uri"; //$NON-NLS-1$

    private static final String USER = "user-id"; //$NON-NLS-1$

    private static final String PASSWORD = "password"; //$NON-NLS-1$

    private static final String CATALOG = "catalog"; //$NON-NLS-1$

    private static final String QUERY = "query"; //$NON-NLS-1$

    private static final int AXIS_COLUMNS = 0;

    private static final int AXIS_ROWS = 1;

    private IPentahoResultSet rSet;

    private SOAPConnectionFactory scf = null;

    private MessageFactory mf = null;

    private URL url = null;

    private int provider = 0;

    private String dataSource = null;

    public static final int PROVIDER_MICROSOFT = 1;

    public static final int PROVIDER_SAP = 2;

    public static final int PROVIDER_MONDRIAN = 3;

    public static final int PROVIDER_ESSBASE = 4;

    @Override
    public abstract boolean validateSystemSettings();

    public abstract String getResultOutputName();

    @Override
    public abstract Log getLogger();

    interface Rowhandler {
        void handleRow(SOAPElement eRow, SOAPEnvelope envelope);
    }

    public IPentahoResultSet getResultSet() {
        return rSet;
    }

    @Override
    protected boolean validateAction() {

        try {
            if (!isDefinedInput(XMLABaseComponent.URI)) {
                error(Messages.getInstance().getErrorString("XMLABaseComponent.ERROR_0001_CONNECTION_NOT_SPECIFIED", //$NON-NLS-1$
                        getActionName()));
                return false;
            }

            if (!isDefinedInput(XMLABaseComponent.USER)) {
                error(Messages.getInstance().getErrorString("XMLABaseComponent.ERROR_0002_USER_NOT_SPECIFIED", //$NON-NLS-1$
                        getActionName()));
                return false;
            }

            if (!isDefinedInput(XMLABaseComponent.PASSWORD)) {
                error(Messages.getInstance().getErrorString("XMLABaseComponent.ERROR_0003_PASSWORD_NOT_SPECIFIED", //$NON-NLS-1$
                        getActionName()));
                return false;
            }

            if (!isDefinedInput(XMLABaseComponent.CATALOG)) {
                error(Messages.getInstance().getErrorString("XMLABaseComponent.ERROR_0004_CATALOG_NOT_SPECIFIED", //$NON-NLS-1$
                        getActionName()));
                return false;
            }

            if (!isDefinedInput(XMLABaseComponent.QUERY)) {
                error(Messages.getInstance().getErrorString("XMLABaseComponent.ERROR_0005_QUERY_NOT_SPECIFIED", //$NON-NLS-1$
                        getActionName()));
                return false;
            }

            String outputName = getResultOutputName();
            if (outputName != null) {
                if (!getOutputNames().contains(outputName)) {
                    error(Messages.getInstance().getErrorString("XMLABaseComponent.ERROR_0006_OUTPUT_NOT_SPECIFIED", //$NON-NLS-1$
                            getActionName()));
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            error(Messages.getInstance().getErrorString("XMLABaseComponent.ERROR_0007_VALIDATION_FAILED",
                    getActionName()), e); //$NON-NLS-1$
        }

        return false;
    }

    @Override
    public void done() {
    }

    @Override
    protected boolean executeAction() {
        try {
            scf = SOAPConnectionFactory.newInstance();
            mf = MessageFactory.newInstance();
        } catch (UnsupportedOperationException e) {
            e.printStackTrace();
        } catch (SOAPException e) {
            e.printStackTrace();
        }

        String uri = this.getInputStringValue(XMLABaseComponent.URI);
        String user = this.getInputStringValue(XMLABaseComponent.USER);
        String password = this.getInputStringValue(XMLABaseComponent.PASSWORD);
        String catalog = this.getInputStringValue(XMLABaseComponent.CATALOG);
        String query = this.getInputStringValue(XMLABaseComponent.QUERY);

        buildURl(uri, user, password);
        try {
            setProviderAndDataSource(discoverDS());
            return executeQuery(query, catalog);
        } catch (XMLAException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return false;
    }

    private void buildURl(final String uri, final String user, final String password) {
        try {
            this.url = new URL(uri);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }

        if ((user != null) && (user.length() > 0)) {
            String newUri = this.url.getProtocol() + "://" + user; //$NON-NLS-1$
            if ((password != null) && (password.length() > 0)) {
                newUri += ":" + password; //$NON-NLS-1$
            }
            newUri += "@" + this.url.getHost() + ":" + this.url.getPort() //$NON-NLS-1$ //$NON-NLS-2$
                    + this.url.getPath();

            try {
                this.url = new URL(newUri);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Execute query
     *
     * @param query   - MDX to be executed
     * @param catalog
     * @param handler Callback handler
     * @throws XMLAException
     */
    public boolean executeQuery(final String query, final String catalog) throws XMLAException {

        Object[][] columnHeaders = null;
        Object[][] rowHeaders = null;
        Object[][] data = null;

        int columnCount = 0;
        int rowCount = 0;

        SOAPConnection connection = null;
        SOAPMessage reply = null;

        try {
            connection = scf.createConnection();
            SOAPMessage msg = mf.createMessage();

            MimeHeaders mh = msg.getMimeHeaders();
            mh.setHeader("SOAPAction", XMLABaseComponent.EXECUTE_ACTION); //$NON-NLS-1$

            SOAPPart soapPart = msg.getSOAPPart();
            SOAPEnvelope envelope = soapPart.getEnvelope();
            envelope.setEncodingStyle(XMLABaseComponent.ENCODING_STYLE);

            SOAPBody body = envelope.getBody();
            Name nEx = envelope.createName("Execute", "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$//$NON-NLS-2$

            SOAPElement eEx = body.addChildElement(nEx);
            eEx.setEncodingStyle(XMLABaseComponent.ENCODING_STYLE);

            // add the parameters

            // COMMAND parameter
            // <Command>
            // <Statement>select [Measures].members on Columns from
            // Sales</Statement>
            // </Command>
            Name nCom = envelope.createName("Command", "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$ //$NON-NLS-2$
            SOAPElement eCommand = eEx.addChildElement(nCom);
            Name nSta = envelope.createName("Statement", "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$ //$NON-NLS-2$
            SOAPElement eStatement = eCommand.addChildElement(nSta);
            eStatement.addTextNode(query);

            // <Properties>
            // <PropertyList>
            // <DataSourceInfo>Provider=MSOLAP;Data
            // Source=local</DataSourceInfo>
            // <Catalog>Foodmart 2000</Catalog>
            // <Format>Multidimensional</Format>
            // <AxisFormat>TupleFormat</AxisFormat> oder "ClusterFormat"
            // </PropertyList>
            // </Properties>
            Map paraList = new HashMap();
            paraList.put("DataSourceInfo", dataSource); //$NON-NLS-1$
            paraList.put("Catalog", catalog); //$NON-NLS-1$
            paraList.put("Format", "Multidimensional"); //$NON-NLS-1$ //$NON-NLS-2$
            paraList.put("AxisFormat", "TupleFormat"); //$NON-NLS-1$ //$NON-NLS-2$
            addParameterList(envelope, eEx, "Properties", "PropertyList", paraList); //$NON-NLS-1$ //$NON-NLS-2$

            msg.saveChanges();

            debug("Request for Execute"); //$NON-NLS-1$
            logSoapMsg(msg);

            // run the call
            reply = connection.call(msg, url);

            debug("Reply from Execute"); //$NON-NLS-1$
            logSoapMsg(reply);

            // error check
            errorCheck(reply);

            // process the reply
            SOAPElement eRoot = findExecRoot(reply);

            // for each axis, get the positions (tuples)
            Name name = envelope.createName("Axes", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$ //$NON-NLS-2$
            SOAPElement eAxes = selectSingleNode(eRoot, name);
            if (eAxes == null) {
                throw new XMLAException("Excecute result has no Axes element"); //$NON-NLS-1$
            }

            name = envelope.createName("Axis", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$ //$NON-NLS-2$
            Iterator itAxis = eAxes.getChildElements(name);

            AxisLoop: for (int iOrdinal = 0; itAxis.hasNext();) {
                SOAPElement eAxis = (SOAPElement) itAxis.next();
                name = envelope.createName("name"); //$NON-NLS-1$
                String axisName = eAxis.getAttributeValue(name);
                int axisOrdinal;
                if (axisName.equals("SlicerAxis")) { //$NON-NLS-1$
                    continue;
                } else {
                    axisOrdinal = iOrdinal++;
                }

                name = envelope.createName("Tuples", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$//$NON-NLS-2$
                SOAPElement eTuples = selectSingleNode(eAxis, name);
                if (eTuples == null) {
                    continue AxisLoop; // what else?
                }

                name = envelope.createName("Tuple", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$//$NON-NLS-2$
                Iterator itTuple = eTuples.getChildElements(name);

                // loop over tuples
                int positionOrdinal = 0;
                while (itTuple.hasNext()) { // TupleLoop

                    SOAPElement eTuple = (SOAPElement) itTuple.next();

                    if ((axisOrdinal == XMLABaseComponent.AXIS_COLUMNS) && (columnHeaders == null)) {
                        columnCount = getChildCount(envelope, eTuples, "Tuple"); //$NON-NLS-1$
                        columnHeaders = new Object[getChildCount(envelope, eTuple, "Member")][columnCount]; //$NON-NLS-1$
                    } else if ((axisOrdinal == XMLABaseComponent.AXIS_ROWS) && (rowHeaders == null)) {
                        rowCount = getChildCount(envelope, eTuples, "Tuple"); //$NON-NLS-1$
                        rowHeaders = new Object[rowCount][getChildCount(envelope, eTuple, "Member")]; //$NON-NLS-1$
                    }

                    int index = 0;
                    name = envelope.createName("Member", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$//$NON-NLS-2$
                    Iterator itMember = eTuple.getChildElements(name);
                    while (itMember.hasNext()) { // MemberLoop
                        SOAPElement eMem = (SOAPElement) itMember.next();
                        // loop over children nodes
                        String caption = null;
                        Iterator it = eMem.getChildElements();
                        InnerLoop: while (it.hasNext()) {
                            Node n = (Node) it.next();
                            if (!(n instanceof SOAPElement)) {
                                continue InnerLoop;
                            }
                            SOAPElement el = (SOAPElement) n;
                            String enam = el.getElementName().getLocalName();
                            if (enam.equals("Caption")) { //$NON-NLS-1$
                                caption = el.getValue();
                            }
                        }
                        if (axisOrdinal == XMLABaseComponent.AXIS_COLUMNS) {
                            columnHeaders[index][positionOrdinal] = caption;
                        } else if (axisOrdinal == XMLABaseComponent.AXIS_ROWS) {
                            rowHeaders[positionOrdinal][index] = caption;
                        }
                        ++index;
                    } // MemberLoop

                    ++positionOrdinal;
                } // TupleLoop
            } // AxisLoop

            data = new Object[rowCount][columnCount];
            // loop over cells in result set
            name = envelope.createName("CellData", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$//$NON-NLS-2$
            SOAPElement eCellData = selectSingleNode(eRoot, name);
            name = envelope.createName("Cell", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$//$NON-NLS-2$
            Iterator itSoapCell = eCellData.getChildElements(name);
            while (itSoapCell.hasNext()) { // CellLoop
                SOAPElement eCell = (SOAPElement) itSoapCell.next();
                name = envelope.createName("CellOrdinal", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                String cellOrdinal = eCell.getAttributeValue(name);
                int ordinal = Integer.parseInt(cellOrdinal);
                name = envelope.createName("Value", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$//$NON-NLS-2$
                Object value = selectSingleNode(eCell, name).getValue();

                int rowLoc = ordinal / columnCount;
                int columnLoc = ordinal % columnCount;

                data[rowLoc][columnLoc] = value;
            } // CellLoop

            MemoryResultSet resultSet = new MemoryResultSet();
            MemoryMetaData metaData = new MemoryMetaData(columnHeaders, rowHeaders);
            resultSet.setMetaData(metaData);
            for (Object[] element : data) {
                resultSet.addRow(element);
            }
            rSet = resultSet;
            if (resultSet != null) {
                if (getResultOutputName() != null) {
                    setOutputValue(getResultOutputName(), resultSet);
                }
                return true;
            }
            return false;

        } catch (SOAPException se) {
            throw new XMLAException(se);
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SOAPException e) {
                    // log and ignore
                    error("?", e); //$NON-NLS-1$
                }
            }

        }

    }

    private int getChildCount(final SOAPEnvelope envelope, final SOAPElement element, final String childName)
            throws SOAPException {
        Name name = envelope.createName(childName, "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$
        Iterator iter = element.getChildElements(name);
        int value = 0;
        while (iter.hasNext()) {
            value++;
            iter.next();
        }
        return value;
    }

    private void setProviderAndDataSource(final Map resMap) throws XMLAException {
        if ((resMap == null) || (resMap.size() == 0)) {
            error(Messages.getInstance().getString("XMLABaseComponent.ERROR_0008_NO_RESOURCE_MAP")); //$NON-NLS-1$
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0008_NO_RESOURCE_MAP")); //$NON-NLS-1$
        }

        String pstr = (String) resMap.get("ProviderName"); //$NON-NLS-1$

        if (pstr == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0009_NO_PROVIDER_NAME")); //$NON-NLS-1$
        }

        provider = determineProvider("Provider=" + pstr); //$NON-NLS-1$

        debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0001_PROVIDER_ID") + provider); //$NON-NLS-1$

        debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0002_DATASOURCE_NAME")
                + String.valueOf(resMap.get("DataSourceName"))); //$NON-NLS-1$ //$NON-NLS-2$
        debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0003_DATASOURCE_INFO")
                + String.valueOf(resMap.get("DataSourceInfo"))); //$NON-NLS-1$ //$NON-NLS-2$

        dataSource = (String) resMap.get("DataSourceInfo"); //$NON-NLS-1$

        if ((dataSource == null) || (dataSource.length() < 1)) {
            dataSource = (String) resMap.get("DataSourceName"); //$NON-NLS-1$
        }

        if (dataSource == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0010_NO_DATASOURCE_NAME")); //$NON-NLS-1$
        }

        debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0004_DISCOVER_DATASOURCE_SET")
                + dataSource); //$NON-NLS-1$

    }

    /**
     * retrieve data source properties
     *
     * @return Map of key/value strings
     * @see DataSourceBrowser
     */
    public Map discoverDS() throws XMLAException {
        // Microsoft wants restrictions
        HashMap rHash = new HashMap();

        HashMap pHash = new HashMap();
        pHash.put("Content", "Data"); //$NON-NLS-1$ //$NON-NLS-2$
        final Map resultMap = new HashMap();
        Rowhandler rh = new Rowhandler() {

            public void handleRow(SOAPElement eRow, SOAPEnvelope envelope) {

                /*
                 * <row><DataSourceName>SAP_BW</DataSourceName> <DataSourceDescription>SAP BW Release 3.0A XML f. Analysis
                 * Service</DataSourceDescription> <URL>http://155.56.49.46:83/SAP/BW/XML/SOAP/XMLA</URL>
                 * <DataSourceInfo>default</DataSourceInfo> <ProviderName>SAP BW</ProviderName> <ProviderType>MDP</ProviderType>
                 * <AuthenticationMode>Integrated</AuthenticationMode></row>
                 */
                Iterator it = eRow.getChildElements();
                while (it.hasNext()) {
                    Object o = it.next();
                    if (!(o instanceof SOAPElement)) {
                        continue; // bypass text nodes
                    }
                    SOAPElement e = (SOAPElement) o;
                    String name = e.getElementName().getLocalName();
                    String value = e.getValue();
                    resultMap.put(name, value);
                }
            }
        };

        discover("DISCOVER_DATASOURCES", url, rHash, pHash, rh); //$NON-NLS-1$
        debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0005_DISCOVER_DATASOURCE_FOUND")
                + resultMap.size()); //$NON-NLS-1$
        return resultMap;

    }

    /**
     * discover
     *
     * @param request
     * @param discoverUrl
     * @param restrictions
     * @param properties
     * @param rh
     * @throws XMLAException
     */
    private void discover(final String request, final URL discoverUrl, final Map restrictions, final Map properties,
            final Rowhandler rh) throws XMLAException {

        try {
            SOAPConnection connection = scf.createConnection();

            SOAPMessage msg = mf.createMessage();

            MimeHeaders mh = msg.getMimeHeaders();
            mh.setHeader("SOAPAction", "\"urn:schemas-microsoft-com:xml-analysis:Discover\""); //$NON-NLS-1$ //$NON-NLS-2$

            SOAPPart soapPart = msg.getSOAPPart();
            SOAPEnvelope envelope = soapPart.getEnvelope();
            envelope.addNamespaceDeclaration("xsi", "http://www.w3.org/2001/XMLSchema-instance"); //$NON-NLS-1$//$NON-NLS-2$
            envelope.addNamespaceDeclaration("xsd", "http://www.w3.org/2001/XMLSchema"); //$NON-NLS-1$ //$NON-NLS-2$
            SOAPBody body = envelope.getBody();
            Name nDiscover = envelope.createName("Discover", "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$//$NON-NLS-2$

            SOAPElement eDiscover = body.addChildElement(nDiscover);
            eDiscover.setEncodingStyle(XMLABaseComponent.ENCODING_STYLE);

            Name nPara = envelope.createName("RequestType", "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$//$NON-NLS-2$
            SOAPElement eRequestType = eDiscover.addChildElement(nPara);
            eRequestType.addTextNode(request);

            // add the parameters
            if (restrictions != null) {
                addParameterList(envelope, eDiscover, "Restrictions", "RestrictionList", restrictions); //$NON-NLS-1$ //$NON-NLS-2$
            }
            addParameterList(envelope, eDiscover, "Properties", "PropertyList", properties); //$NON-NLS-1$//$NON-NLS-2$

            msg.saveChanges();

            debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0006_DISCOVER_REQUEST") + request); //$NON-NLS-1$
            logSoapMsg(msg);

            // run the call
            SOAPMessage reply = connection.call(msg, discoverUrl);

            debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0007_DISCOVER_RESPONSE") + request); //$NON-NLS-1$
            logSoapMsg(reply);

            errorCheck(reply);

            SOAPElement eRoot = findDiscoverRoot(reply);

            Name nRow = envelope.createName("row", "", XMLABaseComponent.ROWS_URI); //$NON-NLS-1$ //$NON-NLS-2$
            Iterator itRow = eRoot.getChildElements(nRow);
            while (itRow.hasNext()) { // RowLoop

                SOAPElement eRow = (SOAPElement) itRow.next();
                rh.handleRow(eRow, envelope);

            } // RowLoop

            connection.close();
        } catch (UnsupportedOperationException e) {
            throw new XMLAException(e);
        } catch (SOAPException e) {
            throw new XMLAException(e);
        }

    }

    /**
     * add a list of Restrictions/Properties ...
     */
    private void addParameterList(final SOAPEnvelope envelope, final SOAPElement eParent, final String typeName,
            final String listName, final Map params) throws SOAPException {
        Name nPara = envelope.createName(typeName, "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$
        SOAPElement eType = eParent.addChildElement(nPara);
        nPara = envelope.createName(listName, "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$
        SOAPElement eList = eType.addChildElement(nPara);
        if (params == null) {
            return;
        }
        Iterator it = params.keySet().iterator();
        while (it.hasNext()) {
            String tag = (String) it.next();
            String value = (String) params.get(tag);
            nPara = envelope.createName(tag, "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$
            SOAPElement eTag = eList.addChildElement(nPara);
            eTag.addTextNode(value);
        }
    }

    /**
     * locate "root" in ExecuteResponse
     */
    private SOAPElement findExecRoot(final SOAPMessage reply) throws SOAPException, XMLAException {
        SOAPPart sp = reply.getSOAPPart();
        SOAPEnvelope envelope = sp.getEnvelope();
        SOAPBody body = envelope.getBody();

        Name name;
        name = envelope.createName("ExecuteResponse", "m", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$//$NON-NLS-2$
        SOAPElement eResponse = selectSingleNode(body, name);
        if (eResponse == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0011_NO_EXECUTE_RESPONSE_ELEMENT")); //$NON-NLS-1$
        }

        name = envelope.createName("return", "m", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$//$NON-NLS-2$
        SOAPElement eReturn = selectSingleNode(eResponse, name);

        name = envelope.createName("root", "", XMLABaseComponent.MDD_URI); //$NON-NLS-1$//$NON-NLS-2$
        SOAPElement eRoot = selectSingleNode(eReturn, name);
        if (eRoot == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0012_NO_RESPONSE_ROOT_ELEMENT"));
        } //$NON-NLS-1$
        return eRoot;
    }

    /**
     * locate "root" in DisoverResponse
     */
    private SOAPElement findDiscoverRoot(final SOAPMessage reply) throws SOAPException, XMLAException {

        SOAPPart sp = reply.getSOAPPart();
        SOAPEnvelope envelope = sp.getEnvelope();
        SOAPBody body = envelope.getBody();
        Name childName;
        SOAPElement eResponse = null;
        if (provider == 0) {
            // unknown provider - recognize by prefix of DiscoverResponse
            Iterator itBody = body.getChildElements();
            while (itBody.hasNext()) {
                Node n = (Node) itBody.next();
                if (!(n instanceof SOAPElement)) {
                    continue;
                }
                Name name = ((SOAPElement) n).getElementName();
                if (name.getLocalName().equals("DiscoverResponse")) { //$NON-NLS-1$
                    eResponse = (SOAPElement) n;
                    provider = getProviderFromDiscoverResponse(envelope, eResponse);
                    break;
                }
            }
            if (eResponse == null) {
                throw new XMLAException(
                        Messages.getInstance().getString("XMLABaseComponent.ERROR_0013_NO_DISCOVER_RESPONSE")); //$NON-NLS-1$
            }

        } else {
            if ((provider == XMLABaseComponent.PROVIDER_MICROSOFT)
                    || (provider == XMLABaseComponent.PROVIDER_ESSBASE)) { // Microsoft
                // or
                // Essbase
                childName = envelope.createName("DiscoverResponse", "m", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$ //$NON-NLS-2$
            } else if ((provider == XMLABaseComponent.PROVIDER_SAP)
                    || (provider == XMLABaseComponent.PROVIDER_MONDRIAN)) { // SAP
                // or
                // Mondrian
                childName = envelope.createName("DiscoverResponse", "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$ //$NON-NLS-2$
            } else {
                throw new IllegalArgumentException(
                        Messages.getInstance().getString("XMLABaseComponent.ERROR_0014_NO_PROVIDER_SPEC")); //$NON-NLS-1$
            }
            eResponse = selectSingleNode(body, childName);
            if (eResponse == null) {
                throw new XMLAException(Messages.getInstance()
                        .getString("XMLABaseComponent.ERROR_0015_NO_DISCOVER_RESPONSE_ELEMENT")); //$NON-NLS-1$
            }
        }

        SOAPElement eReturn = getDiscoverReturn(envelope, eResponse);
        if (eReturn == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0016_NO_RESULT_RETURN_ELEMENT")); //$NON-NLS-1$
        }

        SOAPElement eRoot = getDiscoverRoot(envelope, eReturn);
        if (eRoot == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0017_NO_RESULT_ROOT_ELEMENT")); //$NON-NLS-1$
        }
        return eRoot;
    }

    /**
     * Find the Provider type in the DiscoverResponse
     *
     * @param n
     * @return
     * @throws XMLAException
     * @throws SOAPException
     */
    private int getProviderFromDiscoverResponse(final SOAPEnvelope envelope, final SOAPElement e)
            throws XMLAException, SOAPException {
        Name name = e.getElementName();
        if (!name.getLocalName().equals("DiscoverResponse")) { //$NON-NLS-1$
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0018_NOT_A_DISCOVER_RESPONSE") //$NON-NLS-1$
                            + name.getLocalName());
        }

        // Look for return/root/row/ProviderName

        SOAPElement walker = getDiscoverReturn(envelope, e);

        if (walker == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0019_NO_RESULT_DISCOVER_RESPONSE")); //$NON-NLS-1$
        }

        walker = getDiscoverRoot(envelope, walker);

        if (walker == null) {
            throw new XMLAException(Messages.getInstance()
                    .getString("XMLABaseComponent.ERROR_0020_NO_RESULT_DISCOVER_RETURN_ROOT")); //$NON-NLS-1$
        }

        walker = getDiscoverRow(envelope, walker);

        if (walker == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0021_NO_DISCOVER_RESPONSE_ROW")); //$NON-NLS-1$
        }

        /*
         * Name nProviderName = envelope.createName("ProviderName", "", ROWS_URI); SOAPElement eProviderName =
         * selectSingleNode(e, nProviderName);
         * 
         * if (eProviderName == null) { throw new OlapException("Discover result has no
         * DiscoverResponse/return/root/row/ProviderName element"); } value = eProviderName.getValue();
         */
        String value = null;
        Iterator it = walker.getChildElements();
        while (it.hasNext()) {
            Object o = it.next();
            if (!(o instanceof SOAPElement)) {
                continue; // bypass text nodes
            }
            SOAPElement e2 = (SOAPElement) o;
            String nameString = e2.getElementName().getLocalName();
            if (nameString.equals("ProviderName")) { //$NON-NLS-1$
                value = e2.getValue();
                debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0008_FOUND_PROVIDER") + value); //$NON-NLS-1$
                break;
            }
        }

        if ((value == null) || (value.trim().length() == 0)) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0022_NO_PROVIDER_NAME_ELEMENT")); //$NON-NLS-1$
        }

        return determineProvider("Provider=" + value); //$NON-NLS-1$
    }

    /**
     * Get provider id from String
     *
     * @param dataSourceString
     * @return provider id from OlapDiscoverer
     * @throws XMLAException
     */
    private int determineProvider(final String dataSourceString) throws XMLAException {
        debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0009_DETERMINE_PROVIDER")
                + dataSourceString); //$NON-NLS-1$
        if (dataSourceString == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0023_NO_DATASOURCE_GIVEN")); //$NON-NLS-1$
        }

        String upperDSString = dataSourceString.toUpperCase(Locale.US);
        if (!upperDSString.startsWith("PROVIDER=")) { //$NON-NLS-1$
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0024_MALFORMED_DATASOURCE")); //$NON-NLS-1$
        }

        if (upperDSString.startsWith("PROVIDER=SAP")) { //$NON-NLS-1$
            debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0009_SAP_PROVIDER")); //$NON-NLS-1$
            return XMLABaseComponent.PROVIDER_SAP;
        } else if (upperDSString.startsWith("PROVIDER=MONDRIAN")) { //$NON-NLS-1$
            debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0010_MONDRIAN_PROVIDER")); //$NON-NLS-1$
            return XMLABaseComponent.PROVIDER_MONDRIAN;
        } else if (upperDSString.startsWith("PROVIDER=MS")) { //$NON-NLS-1$ //not sure if this is needed?
            debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0011_MICROSOFT_PROVIDER")); //$NON-NLS-1$
            return XMLABaseComponent.PROVIDER_MICROSOFT;
        } else if (upperDSString.startsWith("PROVIDER=MICROSOFT")) { //$NON-NLS-1$ // return value from MSAS: "Microsoft XML for Analysis"
            debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0011_MICROSOFT_PROVIDER")); //$NON-NLS-1$
            return XMLABaseComponent.PROVIDER_MICROSOFT; //
        } else if (upperDSString.startsWith("PROVIDER=ESSBASE")) { //$NON-NLS-1$ // return value from MSAS: "Microsoft XML for Analysis"
            debug(Messages.getInstance().getString("XMLABaseComponent.DEBUG_0012_ESSBASE_PROVIDER")); //$NON-NLS-1$
            return XMLABaseComponent.PROVIDER_ESSBASE; //
        } else {
            error(Messages.getInstance().getString("XMLABaseComponent.ERROR_0023_CANNOT_DETERMINE_PROVIDER")
                    + dataSourceString); //$NON-NLS-1$
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0024_UNSUPPORTED_PROVIDER")); //$NON-NLS-1$
        }

    }

    private SOAPElement getDiscoverReturn(final SOAPEnvelope envelope, final SOAPElement e)
            throws XMLAException, SOAPException {

        Name nReturn;
        if ((provider == XMLABaseComponent.PROVIDER_MICROSOFT)
                || (provider == XMLABaseComponent.PROVIDER_ESSBASE)) {
            nReturn = envelope.createName("return", "m", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$ //$NON-NLS-2$
        } else {
            nReturn = envelope.createName("return", "", XMLABaseComponent.XMLA_URI); //$NON-NLS-1$ //$NON-NLS-2$
        }
        SOAPElement eReturn = selectSingleNode(e, nReturn);
        if (eReturn == null) {
            // old Microsoft XMLA SDK 1.0 does not have "m" prefix - try
            nReturn = envelope.createName("return", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            eReturn = selectSingleNode(e, nReturn);
            if (eReturn == null) {
                throw new XMLAException(Messages.getInstance()
                        .getString("XMLABaseComponent.ERROR_0025_NO_RETURN_DISCOVER_ELEMENT")); //$NON-NLS-1$
            }
        }
        return eReturn;
    }

    private SOAPElement getDiscoverRoot(final SOAPEnvelope envelope, final SOAPElement e)
            throws XMLAException, SOAPException {

        Name nRoot = envelope.createName("root", "", XMLABaseComponent.ROWS_URI); //$NON-NLS-1$ //$NON-NLS-2$
        SOAPElement eRoot = selectSingleNode(e, nRoot);
        if (eRoot == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0026_NO_ROOT_DISCOVER_ELEMENT"));
        } //$NON-NLS-1$
        return eRoot;

    }

    private SOAPElement getDiscoverRow(final SOAPEnvelope envelope, final SOAPElement e)
            throws XMLAException, SOAPException {

        Name nRow = envelope.createName("row", "", XMLABaseComponent.ROWS_URI); //$NON-NLS-1$ //$NON-NLS-2$
        SOAPElement eRow = selectSingleNode(e, nRow);
        if (eRow == null) {
            throw new XMLAException(
                    Messages.getInstance().getString("XMLABaseComponent.ERROR_0027_NO_DISCOVER_ROW_ELEMENT"));
        } //$NON-NLS-1$
        return eRow;

    }

    // error check
    private void errorCheck(final SOAPMessage reply) throws SOAPException, XMLAException {
        String[] strings = new String[4];
        if (soapFault(reply, strings)) {
            String faultString = "Soap Fault code=" + strings[0] + " fault string=" + strings[1] + " fault actor="
                    + strings[2]; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            if (strings[3] != null) {
                faultString += "\ndetail:" + strings[3]; //$NON-NLS-1$
            }
            throw new XMLAException(faultString);
        }
    }

    /**
     * check SOAP reply for Error, return fault Code
     *
     * @param reply   the message to check
     * @param aReturn ArrayList containing faultcode,faultstring,faultactor
     */
    private boolean soapFault(final SOAPMessage reply, final String[] faults) throws SOAPException {
        SOAPPart sp = reply.getSOAPPart();
        SOAPEnvelope envelope = sp.getEnvelope();
        SOAPBody body = envelope.getBody();
        if (!body.hasFault()) {
            return false;
        }
        SOAPFault fault = body.getFault();

        faults[0] = fault.getFaultCode();
        faults[1] = fault.getFaultString();
        faults[2] = fault.getFaultActor();

        // probably not neccessary with Microsoft;
        Detail detail = fault.getDetail();
        if (detail == null) {
            return true;
        }
        String detailMsg = ""; //$NON-NLS-1$
        Iterator it = detail.getDetailEntries();
        for (; it.hasNext();) {
            DetailEntry det = (DetailEntry) it.next();
            Iterator ita = det.getAllAttributes();
            for (boolean cont = false; ita.hasNext(); cont = true) {
                Name name = (Name) ita.next();
                if (cont) {
                    detailMsg += "; "; //$NON-NLS-1$
                }
                detailMsg += name.getLocalName();
                detailMsg += " = "; //$NON-NLS-1$
                detailMsg += det.getAttributeValue(name);
            }
        }
        faults[3] = detailMsg;

        return true;
    }

    /**
     * @param contextNode
     * @param childPath
     * @return
     */
    private SOAPElement selectSingleNode(final SOAPElement contextNode, final Name childName) {

        Iterator it = contextNode.getChildElements(childName);
        if (it.hasNext()) {
            return (SOAPElement) it.next();
        }
        return null;
    }

    /**
     * log the reply message
     */
    private void logSoapMsg(final SOAPMessage msg) {
        try {
            Writer writer = new StringWriter();
            TransformerFactory tFact = TransformerFactory.newInstance();
            Transformer transformer = tFact.newTransformer();
            Source src = msg.getSOAPPart().getContent();
            StreamResult result = new StreamResult(writer);
            transformer.transform(src, result);
            debug(writer.toString());
        } catch (Exception e) {
            // no big problen - just for debugging
            error("?", e); //$NON-NLS-1$
        }
    }

    public void dispose() {
    }

    @Override
    public boolean init() {
        return true;
    }
}