/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/store/org/apache/slide/store/tamino/datastore/XSecurityMultiUser.java,v 1.4 2004/07/30 06:51:54 ozeigermann Exp $
 * $Revision: 1.4 $
 * $Date: 2004/07/30 06:51:54 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.slide.store.tamino.datastore;

import com.softwareag.tamino.db.api.accessor.TAccessLocation;
import com.softwareag.tamino.db.api.accessor.TInsertException;
import com.softwareag.tamino.db.api.accessor.TQuery;
import com.softwareag.tamino.db.api.accessor.TXMLObjectAccessor;
import com.softwareag.tamino.db.api.common.TAccessFailureException;
import com.softwareag.tamino.db.api.common.TException;
import com.softwareag.tamino.db.api.connection.TConnection;
import com.softwareag.tamino.db.api.connection.TConnectionFactory;
import com.softwareag.tamino.db.api.connection.TLocalTransaction;
import com.softwareag.tamino.db.api.objectModel.TXMLObject;
import com.softwareag.tamino.db.api.objectModel.TXMLObjectIterator;
import com.softwareag.tamino.db.api.objectModel.dom.TDOMObjectModel;
import com.softwareag.tamino.db.api.response.TResponse;
import java.io.StringReader;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.slide.store.tamino.common.XGlobals;
import org.apache.slide.store.tamino.tools.stores.XNamespaceConfig;
import org.apache.slide.util.JDom;
import org.jdom.output.XMLOutputter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * Offers crude access to the Securtiy layer of Tamino. Allows a way to setup and use the security
 * features of Tamino
 *
 * NOTE :-  Apache MUST be configured to use Authorization, check documentation about this
 *          and default usernames and passwords MUST be setup to be used, otherwise this API will NOT work
 *
 * @author christopher.harding@softwareag.com
 *
 * @version $Revision: 1.4 $
 **/

public class XSecurityMultiUser implements XGlobals {
    private static final String INO_SECURITY_COLLECTION = "ino:security";
    //The name of the no acl for the default database entry
    private static final String NO_ACL = "taminowebdavservernoaccess";
    //The name of the write acl entry
    private static final String WRITE_ACL = "taminowebdavserverwriteaccess";

    private static final String WRITE_GROUP_NAME = "taminowebdavserverwritegroup";

    // taminoBase eg http://bolrep2.software-ag.de/tamino
    private String taminoBase;
    // tamino database
    private String database;
    // Full name repressenting the Tamino address and database name
    private String taminoFull;

    private final XNamespaceConfig config;
    
    //XML object
    private TXMLObjectAccessor xmlObjectAccessor;
    //The connection to Tamino
    private TConnection taminoConnection;
    //The Transaction
    private TLocalTransaction taminoTransaction;


    /**
     * Constructs a XSecurity object using taminoBase, database name and collection name.
     *
     * @pre     taminoBase != null
     * @pre     database != null
     *
     * @param   taminoBase      the address of Tamio. eg. http://localhost/tamino
     * @param   database        the name of the database
     *                          expected entries in the Tamino Database
     * @param   collection      collection
     * @exception   TException       tamino exception
     **/
    public XSecurityMultiUser(XNamespaceConfig config, String taminoBase, String database, String collection) throws TException {
        this.taminoBase = taminoBase;
        this.database = database;
        this.taminoFull = taminoBase+"/"+database;
        this.config = config;
        //Create the connection to Tamino
        TConnectionFactory connectionFactory = TConnectionFactory.getInstance();
        if (config.getAdminDomain().equals("")) {
            taminoConnection = connectionFactory.newConnection(this.taminoFull,
                                                               config.getAdminUser(), config.getAdminPwd());
        } else {
            taminoConnection = connectionFactory.newConnection(this.taminoFull,config.getAdminDomain(),
                                                               config.getAdminUser(), config.getAdminPwd());
        }
        if (! defaultUserExist(config.getAdminDomain(),config.getAdminUser()) ) createDefaultUser(config.getAdminDomain(), config.getAdminUser(), config.getAdminPwd());
        if (! defaultACLExist(collection) ) createDefaultACL(collection);
        if (! defaultGroupExist(collection) ) createDefaultGroup(collection,config.getAdminDomain(),config.getAdminUser());
        this.addCollection(collection);
    }

    /**
     * Constructs a XSecurity object using taminoBase, database name and collection name.
     * TODO: merge constructors.
     *
     * @pre     taminoBase != null
     * @pre     database != null
     *
     * @param   taminoBase      the address of Tamio. eg. http://localhost/tamino
     * @param   database        the name of the database
     *                          expected entries in the Tamino Database
     * @param   collection      collection
     * @exception   TException       tamino exception
     **/
    public XSecurityMultiUser (XNamespaceConfig config, String taminoBase, String database, String collection, String domain, String name, String password) throws TException {
        this.taminoBase = taminoBase;
        this.database = database;
        this.taminoFull = taminoBase+"/"+database;
        this.config = config;
        //Create the connection to Tamino
        TConnectionFactory connectionFactory = TConnectionFactory.getInstance();
        if (config.getAdminDomain().equals("")) {
            taminoConnection = connectionFactory.newConnection(this.taminoFull,
                                                               config.getAdminUser(), config.getAdminPwd());
        } else {
            taminoConnection = connectionFactory.newConnection(this.taminoFull,config.getAdminDomain(),
                                                               config.getAdminUser(), config.getAdminPwd());
        }
        if (! defaultUserExist(config.getAdminDomain(),config.getAdminUser()) ) createDefaultUser(config.getAdminDomain(), config.getAdminUser(), config.getAdminPwd());
        if (! defaultUserExist(domain,name) ) {
            if ((domain == null)||(domain.equals(""))) {
                createDefaultUser("", name, password);
            } else {
                createDefaultUser(domain, name, password);
            }
        }
        if (! defaultACLExist(collection) ) createDefaultACL(collection);
        if (! defaultGroupExist(collection) )  {
            if ((domain == null)||(domain.equals(""))) {
                createDefaultGroup(collection,"",name);
            } else {
                createDefaultGroup(collection,domain,name);
            }
        }

       this.addCollection(collection);
    }


    /**
     * Add the collection name to be given no access. Add the collection
     * to the default database ACL entry
     *
     * @pre         collection != null
     * @pre         collection MUST already be in the collection and the schema exist
     *
     * @param       collection      the name of the collection to add
     *
     * @exception   TException       tamino exception
     **/
    public void addCollection(String collection) throws TException {

        if (securityEntryExistsAlready(collection) ) return;  // everything done

        //Format should be correct so add this to the default ACL entry
        TResponse response;
        TXMLObject xmlObject = null;
        org.jdom.Element element;
        org.jdom.Element newACE;

        //  Enable WRITE access for "TWS" on the collection
        xmlObjectAccessor = taminoConnection.newXMLObjectAccessor( TAccessLocation.newInstance(INO_SECURITY_COLLECTION),
                                                                  TDOMObjectModel.getInstance() );
        response = xmlObjectAccessor.query( TQuery.newInstance( "ino:acl[@ino:aclname=\""+ WRITE_ACL + collection +"\"]" ) );
        //Get the id number for the default
        xmlObject = response.getFirstXMLObject();
        if (xmlObject == null || xmlObject.getId() == null || xmlObject.getId().equals("") ) {
            throw new TException ( "Unable to add "+ collection +". Missing default entry");
        }

        element = new org.jdom.input.DOMBuilder().build((org.w3c.dom.Element)xmlObject.getElement());
        newACE = new org.jdom.Element("ace", element.getNamespace("ino"));
        newACE.addContent(collection);
        newACE.setAttribute(new org.jdom.Attribute("access", "full", element.getNamespace("ino")));

        element.getChildren("ace", element.getNamespace("ino")).add(newACE);

        updateSingleDocument(getElementString(element));

        //  Enable NO access for everyone on the collection
        xmlObjectAccessor = taminoConnection.newXMLObjectAccessor( TAccessLocation.newInstance(INO_SECURITY_COLLECTION),
                                                                  TDOMObjectModel.getInstance() );
        response = xmlObjectAccessor.query( TQuery.newInstance( "ino:acl[@ino:aclname=\""+ NO_ACL + collection +"\"]" ) );
        //Get the id number for the default
        xmlObject = response.getFirstXMLObject();
        if (xmlObject.getId() == null || xmlObject.getId().equals("") ) {
            throw new TException ( "Unable to add "+ collection +". Missing default entry");
        }

        element = new org.jdom.input.DOMBuilder().build((org.w3c.dom.Element)xmlObject.getElement());
        newACE = new org.jdom.Element("ace", element.getNamespace("ino"));
        newACE.addContent(collection);
        newACE.setAttribute(new org.jdom.Attribute("access", "no", element.getNamespace("ino")));

        element.getChildren("ace", element.getNamespace("ino")).add(newACE);

        updateSingleDocument(getElementString(element));

    }

    /**
     * Add a new no access entry for the collection into the default group
     *
     * @pre         collection != null
     * @pre         collection MUST already be in the collection and the schema exist
     *
     * @param       collection      the name of the collection to add
     *
     * @exception   TException       tamino exception
     **/
    public boolean addDefaultGroupEntry(String collection) throws TException {

        //Format should be correct so add this to the default ACL entry
        TResponse response;
        TXMLObject xmlObject = null;
        org.jdom.Element element;
        org.jdom.Element newACL;
        boolean result1 = true;
        //  check if default group exists
        xmlObjectAccessor = taminoConnection.newXMLObjectAccessor( TAccessLocation.newInstance(INO_SECURITY_COLLECTION),
                                                                  TDOMObjectModel.getInstance() );
        response = xmlObjectAccessor.query( TQuery.newInstance( "ino:group[@ino:groupname=\""+ this.database +"\"]" ) );
        //Get the id number for the default
        xmlObject = response.getFirstXMLObject();
        if (xmlObject == null || xmlObject.getId() == null || xmlObject.getId().equals("") ) {
            result1 = insertSingleDocument (
            defaultSchemaVersion +
                "<ino:group xmlns:ino=\"http://namespaces.softwareag.com/tamino/response2\" ino:groupname= \"" + this.database + "\">\n"+
                "<ino:aclref>" + NO_ACL + collection + "</ino:aclref>\n" +
                "</ino:group>");
        } else {

            element = new org.jdom.input.DOMBuilder().build((org.w3c.dom.Element)xmlObject.getElement());
            newACL = new org.jdom.Element("aclref", element.getNamespace("ino"));
            newACL.addContent(NO_ACL + collection);
            element.getChildren("aclref", element.getNamespace("ino")).add(newACL);
            updateSingleDocument(getElementString(element));
        }
        return result1;
    }


    /**
     * Delete a schema from the default entry
     *
     * @pre     collection != null
     *
     * @param   collection         the collection to delete in the format
     *
     * @exception   TException       tamino exception
     **/

    public void deleteCollection(String collection) throws TException {

        if (!securityEntryExistsAlready(collection) ) return;  // everything done

        //Format should be correct so remove this to the default ACL entry
        TResponse response;
        TXMLObject xmlObject = null;
        org.jdom.Element element;
        org.jdom.Element newACE;


        //  DisEnable NO access for everyone on the collection
        xmlObjectAccessor = taminoConnection.newXMLObjectAccessor( TAccessLocation.newInstance(INO_SECURITY_COLLECTION),
                                                                  TDOMObjectModel.getInstance() );
        response = xmlObjectAccessor.query( TQuery.newInstance( "ino:acl[@ino:aclname=\""+ NO_ACL + collection +"\"]" ) );
        //Get the id number for the default
        xmlObject = response.getFirstXMLObject();
        if (xmlObject.getId() == null || xmlObject.getId().equals("") ) {
            throw new TException ( "Unable to add "+ collection +". Missing default entry");
        }

        element = new org.jdom.input.DOMBuilder().build((org.w3c.dom.Element)xmlObject.getElement());


        Iterator iter = element.getChildren("ace", element.getNamespace("ino")).iterator();
        while (iter.hasNext())
        {
            org.jdom.Element e = (org.jdom.Element)iter.next();
            if (e.getText().equals(collection)) {
                element.getChildren("ace", element.getNamespace("ino")).remove(e);
                updateSingleDocument(getElementString(element));
            }
        }


        //  Disable WRITE access for "TWS" on the collection:
        xmlObjectAccessor = taminoConnection.newXMLObjectAccessor( TAccessLocation.newInstance(INO_SECURITY_COLLECTION),
                                                                  TDOMObjectModel.getInstance() );
        response = xmlObjectAccessor.query( TQuery.newInstance( "ino:acl[@ino:aclname=\""+ WRITE_ACL +"\"]" ) );
        //Get the id number for the default
        xmlObject = response.getFirstXMLObject();
        if (xmlObject.getId() == null || xmlObject.getId().equals("") ) {
            throw new TException ( "Unable to add "+ collection +". Missing default entry");
        }

        element = new org.jdom.input.DOMBuilder().build((org.w3c.dom.Element)xmlObject.getElement());


        Iterator iter2 = element.getChildren("ace", element.getNamespace("ino")).iterator();
        while (iter2.hasNext())
        {
            org.jdom.Element e = (org.jdom.Element)iter2.next();
            if (e.getText().equals(collection)) {
                element.getChildren("ace", element.getNamespace("ino")).remove(e);
                updateSingleDocument(getElementString(element));
            }
        }


    }


    /**
     * Creates the default group.
     *
     * @pre         database name (database) supplied in the constructor != null
     * @pre         APACHE MUST HAVE A USER XDAV CREATED
     *
     * @return      boolean         true if successfull completed
     *
     * @exception   TException       tamino exception
     **/
    public boolean createDefaultGroup(String collection, String domain, String user) throws TException {



        //Create the Schema for the Default Group
        boolean result1 = addDefaultGroupEntry(collection);
        /*        boolean result1 = insertSingleDocument (
            defaultSchemaVersion +
                "<ino:group ino:groupname= \"" + this.database + "\">\n"+
                "<ino:aclref>" + NO_ACL + collection + "</ino:aclref>\n" +
                "</ino:group>");
         */

        //Create the default write group and ACL information for xdav user
                boolean result2 = insertSingleDocument (
            defaultSchemaVersion +
            "\n<ino:group xmlns:ino=\"http://namespaces.softwareag.com/tamino/response2\" ino:groupname=\""+WRITE_GROUP_NAME + collection +"\">\n"+
                "<ino:userref>"+ getDomain(domain) + user +"</ino:userref>\n"+
                "<ino:userref>"+ getDomain(config.getAdminDomain()) + config.getAdminUser() +"</ino:userref>\n"+
                "<ino:aclref>"+ WRITE_ACL + collection +"</ino:aclref>\n"+
                "</ino:group>");

//        return result1 && result2;
        return result1;
    }


    /**
     * Creates the default ACL entry.
     *
     * @pre         database name (database) supplied in the constructor != null
     * @pre         APACHE MUST HAVE A USER XDAV CREATED
     *
     * @return      boolean         true if successfull completed
     *
     * @exception   TException       tamino exception
     **/
    public boolean createDefaultACL(String collection) throws TException {

        boolean result2 = insertSingleDocument(
            defaultSchemaVersion +
                "\n<ino:acl xmlns:ino=\"http://namespaces.softwareag.com/tamino/response2\" ino:aclname=\""+WRITE_ACL + collection +"\" >\n"+
                "<ino:ace ino:access=\"full\">"+ META_COLLECTION +"</ino:ace>\n"+
                "<ino:ace ino:access=\"full\">"+ collection +"</ino:ace>\n"+
                "</ino:acl>");

        //Create the Schema for the ACL group
        boolean result1 = insertSingleDocument(
            defaultSchemaVersion +
                "\n<ino:acl xmlns:ino=\"http://namespaces.softwareag.com/tamino/response2\" ino:aclname=\"" + NO_ACL + collection + "\">\n" +
                "<ino:ace ino:access=\"no\">"+ META_COLLECTION + "</ino:ace>\n" +
                "<ino:ace ino:access=\"no\">"+ collection + "</ino:ace>\n" +
                "</ino:acl>");

        return result1 && result2;

    }


    /**
     * Creates the default user in Tamino
     *
     * @pre         database name (database) supplied in the constructor != null
     * @pre         APACHE MUST HAVE A USER XDAV CREATED
     *
     * @return      boolean         true if successfull completed
     *
     * @exception   TException       tamino exception
     **/
    public boolean createDefaultUser(String domain, String user, String password) throws TException {


        //Create the Schema for the default user
        return insertSingleDocument(
            "<ino:user ino:unencryptedpassword=\"" + password + "\" xmlns:ino=\"http://namespaces.softwareag.com/tamino/response2\" ino:userid=\"" + getDomain(domain) + user + "\">\n" +
                user + ", Tamino WebDAV Server User" +
                "</ino:user>");


    }

    public String getDomain(String domain) {
        if ((domain == null) || (domain.equals(""))) return "";
        else return domain + "\\";
    }

    /**
     * Check to see if the Security entry exists.
     * @param       collection      collection
     * @return      boolean         true is returned if default ACL entry exists
     *
     * @exception   TException       tamino exception
     **/
    public boolean securityEntryExistsAlready(String collection) throws TException{
        return getCountDocuments("ino:acl[@ino:aclname=\"" + WRITE_ACL + collection + "\" and ino:ace=\"" + collection + "\"]" ) == 1 &&
            getCountDocuments("ino:acl[@ino:aclname=\"" + NO_ACL + collection + "\" and ino:ace=\"" + collection + "\"]" ) == 1 ;
    }



    /**
     * Check to see if the default ACL exists
     *
     * @return      boolean         true is returned if default ACL entry exists
     *
     * @throws      TException
     **/
    public boolean defaultACLExist(String collection) throws TException{
        return getCountDocuments("ino:acl[@ino:aclname=\"" + WRITE_ACL + collection + "\"]" ) == 1 &&
            getCountDocuments("ino:acl[@ino:aclname=\"" + NO_ACL + collection + "\"]" ) == 1 ;
    }


    /**
     * Check to see if the default Group exists
     *
     * @return      boolean         true is returned if default ACL entry exists
     *
     * @throws      TException
     **/
    public boolean defaultGroupExist(String collection) throws TException{
        return getCountDocuments("ino:group[@ino:groupname=\"" + WRITE_GROUP_NAME + collection + "\"]" ) == 1 &&
            getCountDocuments("ino:group[@ino:groupname=\"" + this.database + "\"]" ) == 1 ;
    }


    /**
     * Check to see if the default User exists
     *
     * @return      boolean         true is returned if default ACL entry exists
     *
     * @throws      TException
     **/
    public boolean defaultUserExist(String domain, String user) throws TException{
        return getCountDocuments("ino:user[@ino:userid=\"" + getDomain(domain) +user + "\"]" ) == 1 ;
    }


    /**
     * Create a <code>org.w3c.dom.Document</code> from the String supplied
     *
     *  @pre        xml != null
     *
     *  @param      xml         The xml to use to create the document
     *
     *  @return     org.w3c.dom.Document        null if error occurs
     **/
    public org.w3c.dom.Document createNewDocument(String xml) {
        Document doc = null;
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(false);
            factory.setValidating(false);
            DocumentBuilder builder = factory.newDocumentBuilder();

            //System.out.println( xml );

            doc = builder.parse(new InputSource ( new StringReader (xml) ) );
        }
        catch (Exception e) {
            doc = null;
            e.printStackTrace();
        }

        return doc;
    }

    /**
     * Find an the supplied <code>value</code> in the document, returning <code>true</code> if found
     *
     * @pre     list != null
     * @pre     value != null
     * @pre     found = true
     *
     * @param   list        the NodeList of the document children
     * @param   value       the value to search for
     * @param   found       recursive value, should be set to <code>false</code> when first called
     *
     **/
    private boolean findDocumentEntry(NodeList list, String value, boolean found )
    {
        for (int i = 0; i < list.getLength(); i++) {
            switch (list.item(i).getNodeType()) {
                case Node.TEXT_NODE :
                    String nodeValue = list.item(i).getNodeValue();
                    if (nodeValue.equalsIgnoreCase(value) ) {
                        found = true;
                    }

                    break;
            } //End switch

            if ( list.item(i).hasChildNodes() ) {
                found = findDocumentEntry(list.item(i).getChildNodes(), value, found );
            }
        } //End for loop
        return found;
    }


    private static String defaultSchemaVersion = "<?xml version=\"1.0\"?>";




    /**
     * return the number of response documents for a specific query
     *
     * @return      int     number of found documents
     *
     * @throws      TException
     **/
    private int getCountDocuments(String queryString) throws TException{
        int result = 0;
        //Create the XPath query
        TAccessLocation location = TAccessLocation.newInstance( INO_SECURITY_COLLECTION );
        //Create the Object Accessor
        xmlObjectAccessor = taminoConnection.newXMLObjectAccessor( location,
                                                                  TDOMObjectModel.getInstance() );
        //Create the XPath query, in this case check for the database name
        TQuery query = TQuery.newInstance( queryString );

        //Check the response
        TResponse response = xmlObjectAccessor.query( query );
        TXMLObjectIterator iterator = response.getXMLObjectIterator();
        while (iterator.hasNext()) {
            result ++;
            iterator.next();
        }
        return result;

    }




    /**
     * Insert a single document.
     *
     * @pre         database name (database) supplied in the constructor != null
     * @pre         APACHE MUST HAVE A USER XDAV CREATED
     * @param       documentString  document string
     * @return      boolean         true if successfull completed
     *
     * @throws      TException
     **/
    public boolean insertSingleDocument(String documentString) throws TException {

        TResponse  response = null;
        TXMLObject xmlObject = null;
        boolean    transactionIsOpen = false;
        boolean    result = true;

        try
        {

            xmlObjectAccessor = taminoConnection.newXMLObjectAccessor(TAccessLocation.newInstance(INO_SECURITY_COLLECTION),
                                                                      TDOMObjectModel.getInstance());
            xmlObject = TXMLObject.newInstance( createNewDocument(documentString).getDocumentElement() );
            taminoConnection.useAutoCommitMode();
            taminoTransaction = taminoConnection.useLocalTransactionMode();
            transactionIsOpen = true;
            response = xmlObjectAccessor.insert(xmlObject);
            //Commit the Transaction
            taminoTransaction.commit();
            transactionIsOpen = false;
            taminoTransaction = null;

        }
        catch (TInsertException e)  {
            TException nestedException = e.getRootTCause();
            if ( nestedException instanceof TAccessFailureException &&
                    (((TAccessFailureException) nestedException).getReturnValue().equals("8610"))) {

                taminoTransaction.commit();
                transactionIsOpen = false;

            }
            else {
                result = false;
                throw e;
            }

        }
        finally {
            if (transactionIsOpen) taminoTransaction.rollback();
        }


        return result;

    }




    /**
     * Update a single document.
     *
     * @pre         database name (database) supplied in the constructor != null
     * @pre         APACHE MUST HAVE A USER XDAV CREATED
     * @param       documentString  document string
     * @return      boolean         true if successfull completed
     *
     * @throws      TException
     **/
    public boolean updateSingleDocument(String documentString) throws TException {

        TResponse  response = null;
        TXMLObject xmlObject = null;
        boolean    transactionIsOpen = false;
        boolean    result = true;

        try
        {

            xmlObjectAccessor = taminoConnection.newXMLObjectAccessor(TAccessLocation.newInstance(INO_SECURITY_COLLECTION),
                                                                      TDOMObjectModel.getInstance());
            xmlObject = TXMLObject.newInstance( createNewDocument(documentString).getDocumentElement() );
            taminoConnection.useAutoCommitMode();
            taminoTransaction = taminoConnection.useLocalTransactionMode();
            transactionIsOpen = true;
            response = xmlObjectAccessor.update(xmlObject);
            //Commit the Transaction
            taminoTransaction.commit();
            transactionIsOpen = false;
            taminoTransaction = null;

        }
        finally {
            if (transactionIsOpen) taminoTransaction.rollback();
            taminoConnection.useAutoCommitMode();
        }


        return result;

    }

    /**
     *
     */
    private static String getElementString (Element e) {
        return getElementString(new org.jdom.input.DOMBuilder().build(e));
    }



    /**
     *
     */
    private static String getElementString (org.jdom.Element e) {
        XMLOutputter out = JDom.outputter();
        String result = null;

        try {
            result = out.outputString (e);
        }
        catch (Exception ex) {}

        return result;
    }



}




