Package de.innovationgate.webgate.api.jdbc

Source Code of de.innovationgate.webgate.api.jdbc.WGDatabaseImpl$SessionStatus

/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA 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 OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.webgate.api.jdbc;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.collections.Bag;
import org.apache.commons.collections.bag.HashBag;
import org.apache.commons.collections.map.LinkedMap;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.ObjectDeletedException;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.criterion.Restrictions;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.SQLGrammarException;
import org.hibernate.id.UUIDHexGenerator;
import org.omg.CORBA._PolicyStub;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.Dom4JDriver;

import de.innovationgate.utils.TemporaryFile;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.webgate.api.WGACLCore;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGArea;
import de.innovationgate.webgate.api.WGAuthorisationException;
import de.innovationgate.webgate.api.WGBackendException;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.webgate.api.WGContentKey;
import de.innovationgate.webgate.api.WGContentType;
import de.innovationgate.webgate.api.WGCreationException;
import de.innovationgate.webgate.api.WGDatabase;
import de.innovationgate.webgate.api.WGDatabaseCore;
import de.innovationgate.webgate.api.WGDocument;
import de.innovationgate.webgate.api.WGDocumentCore;
import de.innovationgate.webgate.api.WGDocumentKey;
import de.innovationgate.webgate.api.WGFactory;
import de.innovationgate.webgate.api.WGIllegalArgumentException;
import de.innovationgate.webgate.api.WGInvalidDatabaseException;
import de.innovationgate.webgate.api.WGLanguage;
import de.innovationgate.webgate.api.WGLanguageChooser;
import de.innovationgate.webgate.api.WGPersonalisationDatabaseCore;
import de.innovationgate.webgate.api.WGProcedureException;
import de.innovationgate.webgate.api.WGQueryException;
import de.innovationgate.webgate.api.WGRelationData;
import de.innovationgate.webgate.api.WGResultSetCore;
import de.innovationgate.webgate.api.WGSessionContext;
import de.innovationgate.webgate.api.WGStructEntry;
import de.innovationgate.webgate.api.WGSystemException;
import de.innovationgate.webgate.api.WGUnavailableException;
import de.innovationgate.webgate.api.WGUpdateLog;
import de.innovationgate.webgate.api.WGUserAccess;
import de.innovationgate.webgate.api.WGUserDetails;
import de.innovationgate.webgate.api.WGWrongRevisionException;
import de.innovationgate.webgate.api.auth.AuthenticationSession;
import de.innovationgate.webgate.api.auth.AuthenticationSourceListener;
import de.innovationgate.webgate.api.auth.MasterLoginAuthSession;
import de.innovationgate.webgate.api.jdbc.custom.JDBCConnectionException;
import de.innovationgate.webgate.api.jdbc.custom.JDBCConnectionProvider;
import de.innovationgate.webgate.api.jdbc.pool.DBCPConnectionProvider;
import de.innovationgate.webgate.api.jdbc.pool.DBCPReplicationConnectionProvider;


public class WGDatabaseImpl implements WGDatabaseCore, WGPersonalisationDatabaseCore, AuthenticationSourceListener {
   
    public static class CSVersion {
       
        private double _version;
        private int _patchLevel;
       
        public CSVersion(double version, int patchLevel) {
            _version = version;
            _patchLevel = patchLevel;
        }

        public double getVersion() {
            return _version;
        }

        public int getPatchLevel() {
            return _patchLevel;
        }
       
    }
   
    public class DocumentDependencyComparator implements Comparator<WGUpdateLog> {

        public int compare(WGUpdateLog o1, WGUpdateLog o2) {
           
            // Different times
            int timeDiff = o1.getDate().compareTo(o2.getDate());
            if (timeDiff != 0) {
                return timeDiff;
            }
           
            // Determine sort numbers for operations/doctypes
            int sortNr1 = determineSortNumber(o1);
            int sortNr2 = determineSortNumber(o2);
            return 2 - 1;
           
           
           
        }

        private int determineSortNumber(WGUpdateLog o) {
           
            int nr = 1;
           
           WGDocumentKey docKey = new WGDocumentKey(o.getDocumentKey());
           switch (docKey.getDocType()) {
              
               case WGDocument.TYPE_CONTENT:
                   nr = 3;
                   break;

               case WGDocument.TYPE_STRUCTENTRY:
                   nr = 2;
                   break;
           }
          
           if (o.getType() == WGUpdateLog.TYPE_DELETE) {
               nr = nr * -1;
           }
          
           return nr;
          
           
        }
       
    }
   
  private static final String HQLQUERY_GET_STRUCT_BY_NAME = "from StructEntry as struct where struct.uniquename=:name";
    public static final String HQL_FETCHTYPE_LAZY = "lazy";
  public static final String HQL_FETCHTYPE_STRAIGHT = "straight";
    private static final String HQLQUERY_LAZY = "select new de.innovationgate.webgate.api.WGContentKey(content.structentry.key, content.language.name, content.version) from Content as content where ";
  // enable loadbalancing feature
    public static final String COPTION_LOADBALANCE = "loadbalance";

    // when loadbalancing is enabled - how long should the updating user stay on
    // the master after the session is closed
    public static final String COPTION_MASTERPERSISTENCE_TIMEOUT = "masterPersistenceTimeout";

    public static final String DBTYPE = "jdbc/wgacontentstore";

    public static final String HIBERNATE_V3_MAPPING_FILE = "de/innovationgate/webgate/api/jdbc/Mapping.hbm.xml";
    public static final String HIBERNATE_V5_MAPPING_FILE = "de/innovationgate/webgate/api/jdbc/Mapping.v5.hbm.xml";
   
    public static final String HIBERNATE_V5_P2_MAPPING_FILE = "de/innovationgate/webgate/api/jdbc/Mapping.v5p2.hbm.xml";
   
    public static final String HIBERNATE_V5_P3_MAPPING_FILE = "de/innovationgate/webgate/api/jdbc/Mapping.v5p3.hbm.xml";

    public static final String HIBERNATE_V41_MAPPING_FILE = "de/innovationgate/webgate/api/jdbc/Mapping.optimizedFileHandling.hbm.xml";
   
    public static final String DBOPTION_MAPPINGFILE = "mapping.file";

    public static final String DBOPTION_MAPPINGRESOURCE = "mapping.resource";

    public static final String COPTION_ANONYMOUS = "AnonymousAccessLevel";
   
   
   
    private static final String HQLQUERY_STRAIGHT = "select content from Content as content where ";
   
    private static final String HQLQUERY_UPDATE_RELATIONS = "update from ContentRelation as relation set relation.target = :target where relation.targetstructentry = :structentry and relation.targetlanguage = :language";
   
    public static final String COPTION_HQL_FETCH_TYPE = "HQLFetchType";
   
    public static final String DBMETA_PATCH_LEVEL = "DDLPatchLevel";
   
    public static final Integer CURRENT_PATCH_LEVEL = 1;
   
    protected SessionFactory _sessionFactory;

    private WGDatabase _db;

    private String _path;

    private boolean _hqlLazyByDefault = true;
    private ThreadLocal _sessionStatus = new ThreadLocal();
    private ACLImpl _aclImpl = new ACLImpl(this);

   
    public static final long DEFAULT_MASTERPERSISTENCE_TIMEOUT = 1000 * 10;
    // when loadbalancing is enabled - how long should the updating user stay on
    // the master after the session is closed
  private static long _masterPersistenceTimeout = DEFAULT_MASTERPERSISTENCE_TIMEOUT;
 
  private Map _dbUpdatesByUser = new HashMap();
    protected double _ddlVersion;
    /**
     * Chooses if the "query paging" feature of the optimized file handling
     * should be disabled (which it is by default)
     */
    public static final String COPTION_OPTIMIZED_FILE_HANDLING_DISABLEQUERYPAGING = "OptimizedFileHandling.DisableQueryPaging";
    protected static final String NATIVESQL_BOOLEAN_TRUE = "booleanTrue";
    public static final String DEFAULT_MAXOPENPREPAREDSTATEMENTS = "0";

   
    public static class V5FastAccessKey {
       
        public V5FastAccessKey(int type, String id) {
            super();
            this.type = type;
            this.id = id;
        }
        private int type;
        private String id;
        public int getType() {
            return type;
        }
        public String getId() {
            return id;
        }
       
    }

  public class LogConflict {
     
      private List _logs = new ArrayList();
      private WGUpdateLog _listedLog = null;

        public WGUpdateLog getListedLog() {
            return _listedLog;
        }

        public void setListedLog(WGUpdateLog listedLog) {
            _listedLog = listedLog;
        }

        public List getLogs() {
            return _logs;
        }
     
     
     
  }

  public class SessionStatus {
      private Session _session = null;
      private WGUserDetails _userDetails = null;
        public Session getSession() {
            return _session;
        }
        public void setSession(Session session) {
            _session = session;
        }
        public WGUserDetails getUserDetails() {
            return _userDetails;
        }
        public void setUserDetails(WGUserDetails userDetails) {
            _userDetails = userDetails;
        }
    };

 
  // bean to manage dbUpdatesByUser
  private class DBUpdate {
    private String _user;
    private Date _started;
    private boolean _sessionClosed;
    private WGSessionContext _sessionContext;

    public DBUpdate(WGSessionContext sessionContext) {
      _sessionContext = sessionContext;
      _user = _sessionContext.getUser();
      _started = new Date();
      _sessionClosed = false;
    }

    public boolean isSessionClosed() {
      return _sessionClosed;
    }
    public void setSessionClosed(boolean sessionClosed) {
      _sessionClosed = sessionClosed;
    }

    public Date getStarted() {
      return _started;
    }

    public String getUser() {
      return _user;
    }

    public boolean isInProgress() {
      if (!isSessionClosed()) {
          return true;
            }
            else if (_user.equals(WGDatabase.ANONYMOUS_USER)) {
          return _sessionContext == _db.getSessionContext();      
            }
            else if ((System.currentTimeMillis() - _masterPersistenceTimeout) >= _started.getTime()) {
          return false;
            }
            else {
          return true;
        }
      }
  };



    private static Map _typeToObject = new HashMap();

    private static Map _objectToType = new HashMap();

    static {
        _typeToObject.put(new Integer(WGDocument.TYPE_AREA), Area.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_CONTENT), Content.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_CONTENTTYPE), ContentType.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_CSSJS), CSSJSModule.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_FILECONTAINER), FileContainer.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_LANGUAGE), Language.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_STRUCTENTRY), StructEntry.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_TML), TMLModule.class);
        _typeToObject.put(new Integer(WGDocument.TYPE_USERPROFILE), UserProfile.class);

        _objectToType.put(Area.class, new Integer(WGDocument.TYPE_AREA));
        _objectToType.put(Content.class, new Integer(WGDocument.TYPE_CONTENT));
        _objectToType.put(ContentType.class, new Integer(WGDocument.TYPE_CONTENTTYPE));
        _objectToType.put(CSSJSModule.class, new Integer(WGDocument.TYPE_CSSJS));
        _objectToType.put(FileContainer.class, new Integer(WGDocument.TYPE_FILECONTAINER));
        _objectToType.put(Language.class, new Integer(WGDocument.TYPE_LANGUAGE));
        _objectToType.put(StructEntry.class, new Integer(WGDocument.TYPE_STRUCTENTRY));
        _objectToType.put(TMLModule.class, new Integer(WGDocument.TYPE_TML));
        _objectToType.put(UserProfile.class, new Integer(WGDocument.TYPE_USERPROFILE));
    }

    protected Session getSession() {
        return getSessionStatus().getSession();
    }



    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#cleanup()
     */
    public void cleanup() {
    }

    /**
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#close()
     */
    public void close() throws WGBackendException {
       
        if (getSession() != null) {
            closeSession();
        }
       
        try {
            _sessionFactory.close();
            // set factory explicit to null to ensure gc of hibernate objects
            _sessionFactory = null;
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error closing hibernate session factory", e);
        }

       
        _dbUpdatesByUser.clear();
    }

    /**
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#closeSession()
     */
    public void closeSession() throws WGBackendException {
        try {
            Transaction trans = getSession().getTransaction();
            if (trans != null && trans.isActive()) {
                trans.rollback();
            }
           
            // set session closed flag on dbupdate if present
            if (_db.isSessionOpen()) {
                String user = _db.getSessionContext().getUser();
                DBUpdate update = (DBUpdate) _dbUpdatesByUser.get(user);
                if (update != null) {
                  update.setSessionClosed(true);
                }
            }
           
            SessionStatus sessionStatus = (SessionStatus) _sessionStatus.get();
            if (sessionStatus != null) {
                if (sessionStatus.getSession() != null) {
                    sessionStatus.getSession().disconnect();
                    sessionStatus.getSession().close();
                }
   
            }
           
            _sessionStatus.set(null);
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error closing hibernate session", e);
        }
    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#createContent(WGStructEntry,
     *      WGLanguage, String)
     */
    public WGDocumentCore createContent(WGStructEntry structEntry, WGLanguage language, String title, int version) throws WGAPIException {

        Content newContent = new Content();

        // Additionally set object references, so they can be requested
        // instantly
        StructEntry structEntryEntity = (StructEntry) getEntity(structEntry);
        newContent.setStructentry(structEntryEntity);
        structEntryEntity.getContent().add(newContent);

        Language languageEntity = (Language) getEntity(language);
        newContent.setLanguage(languageEntity);

        // Initialize other data
        newContent.setVersion(new Integer(version));
        newContent.setTitle(title);
        newContent.setItems(new HashMap());
        newContent.setFiles(new HashMap());
        newContent.setRelations(new HashMap());
        newContent.setIshiddenfrom(new ArrayList());
        newContent.setKeywords(new ArrayList());
        newContent.setWfhistory(new ArrayList());
        newContent.setVisible(new Boolean(true));

        return createDocumentImpl(newContent);

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#createCopy(WGDocumentCore)
     */
    public WGDocumentCore createCopy(WGDocumentCore originalCore) throws WGCreationException {

        WGDocumentImpl originalImpl = (WGDocumentImpl) originalCore;
        Object originalEntity = originalImpl.getEntity();

        try {
            WGDocumentImpl entityCopy = null;

            if (originalEntity instanceof Content) {
                Content original = (Content) originalEntity;
                Content copy = new Content();
                copy.setTitle(original.getTitle());
                copy.setLanguage(original.getLanguage());
                copy.setStatus(original.getStatus());
                copy.setStructentry(original.getStructentry());
                copy.setVersion(original.getVersion());
                copy.setVisible(original.isVisible());
                entityCopy = createDocumentImpl(copy);
                //entityCopy.save(new java.util.Date()); // Must save to append
                // other entities to it

                copy.setAuthor(original.getAuthor());
                if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                    copy.setContentclass(original.getContentclass());
                    copy.setOwner(original.getOwner());
                    copy.setCoauthors((List) cloneCollection(original.getCoauthors()));
                }
                copy.setDescription(original.getDescription());

                copy.setLinktarget(original.getLinktarget());

                copy.setUniquename(original.getUniquename());
                copy.setValidfrom(original.getValidfrom());
                copy.setValidto(original.getValidto());

                copy.setVirtuallink(original.getVirtuallink());
                copy.setVirtuallinktype(original.getVirtuallinktype());

                copy.setIshiddenfrom((List) cloneCollection(original.getIshiddenfrom()));
                copy.setKeywords((List) cloneCollection(original.getKeywords()));
                copy.setReaders((List) cloneCollection(original.getReaders()));
                copy.setWfhistory((List) cloneCollection(original.getWfhistory()));

                if (useOptimizedFileHandling()) {
                  // init files map
                  copy.setFiles(new HashMap());
                 
                    // detach all files from originalImpl and attach on
                    // entityCopy
                  Iterator fileNames = originalImpl.getFileNames().iterator();
                  while (fileNames.hasNext()) {
                    String orgFileName = (String) fileNames.next();
                    String fileName = orgFileName.replace('/', '�');
                    TemporaryFile tempFile = new TemporaryFile(fileName, originalImpl.getFileData(orgFileName), WGFactory.getTempDir());
                    tempFile.deleteOnEviction(_db.getSessionContext());
                    entityCopy.attachFile(tempFile.getFile());
                  }
                 
                }
                else {
                  copy.setFiles(cloneContentFiles(original.getFiles(), copy));
                }
               
               
                copy.setItems(cloneContentItems(original.getItems(), copy));
               
                if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                    copy.setRelations(cloneContentRelations(original.getRelations(), copy));
                }

                if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                    copy.setExtensionData(cloneExtensionData(original.getExtensionData(), copy));
                }
               
            }
            else {
                throw new WGCreationException("Copying of document type " + WGDocument.doctypeNumberToName(originalCore.getType()) + " is not supported in this database");
            }

            return entityCopy;

        }
        catch (Exception e) {
            throw new WGCreationException("Error creating entity copy", e);
        }
    }

    /**
     * @param map
     * @return
     */
    private Map cloneContentItems(Map map, Content target) {

        Map itemCopies = new HashMap();
        Iterator itemNames = map.keySet().iterator();
        Object itemName;
        ContentItem contentItem;
        ContentItem contentItemCopy;
        while (itemNames.hasNext()) {
            itemName = itemNames.next();
            contentItem = (ContentItem) map.get(itemName);
            contentItemCopy = new ContentItem();
            contentItemCopy.setDate(contentItem.getDate());
            contentItemCopy.setName(contentItem.getName());
            contentItemCopy.setNumber(contentItem.getNumber());
            contentItemCopy.setParentcontent(target);
            contentItemCopy.setText(contentItem.getText());
            contentItemCopy.setType(contentItem.getType());
            itemCopies.put(itemName, contentItemCopy);
        }

        return itemCopies;
    }
   
    /**
     * @param map
     * @return
     */
    private Map cloneContentRelations(Map map, Content target) {

        Map itemCopies = new HashMap();
        Iterator itemNames = map.keySet().iterator();
        Object relName;
        ContentRelation contentItem;
        ContentRelation contentItemCopy;
        while (itemNames.hasNext()) {
            relName = itemNames.next();
            contentItem = (ContentRelation) map.get(relName);
            contentItemCopy = new ContentRelation();
            contentItemCopy.setName(contentItem.getName());
            contentItemCopy.setGroup(contentItem.getGroup());
            contentItemCopy.setParentcontent(target);
            contentItemCopy.setTargetlanguage(contentItem.getTargetlanguage());
            contentItemCopy.setTargetstructentry(contentItem.getTargetstructentry());
            contentItemCopy.setTarget(contentItem.getTarget());
            itemCopies.put(relName, contentItemCopy);
        }

        return itemCopies;
    }

    /**
     * @param map
     * @return
     * @throws WGBackendException
     */
    private Map cloneContentFiles(Map map, Content target) throws WGBackendException {

        try {
            Map fileCopies = new HashMap();
            Iterator fileKeys = map.keySet().iterator();
            Object fileKey;
            ContentFile contentFile;
            ContentFile contentFileCopy;
            while (fileKeys.hasNext()) {
                fileKey = fileKeys.next();
                contentFile = (ContentFile) map.get(fileKey);
                contentFileCopy = new ContentFile();
                contentFileCopy.setParentcontent(target);
                contentFileCopy.setName(contentFile.getName());
                contentFileCopy.setData(Hibernate.createBlob(contentFile.getData().getBinaryStream()));
                contentFileCopy.setExtensionData(cloneExtensionData(contentFile.getExtensionData(), contentFileCopy));
                fileCopies.put(fileKey, contentFileCopy);
            }

            return fileCopies;
        }
        catch (IOException e) {
            throw new WGBackendException("Error cloning content files.", e);
        }
        catch (SQLException e) {
            throw new WGBackendException("Error cloning content files.", e);
        }

    }

    private Map<String,ExtensionData> cloneExtensionData(Map<String,ExtensionData> map, Entity target) {
        Map<String,ExtensionData> extensionDataCopies = new HashMap<String,ExtensionData>();
        Iterator<String> edNames = map.keySet().iterator();
        String edName;
        ExtensionData extensionData;
        ExtensionData exensionDataCopy;
        while (edNames.hasNext()) {
            edName = edNames.next();
            extensionData = (ExtensionData) map.get(edName);
            exensionDataCopy = new ExtensionData();
            exensionDataCopy.setEntity(target);
            exensionDataCopy.setDate(extensionData.getDate());
            exensionDataCopy.setName(extensionData.getName());
            exensionDataCopy.setNumber(extensionData.getNumber());           
            exensionDataCopy.setText(extensionData.getText());
            exensionDataCopy.setType(extensionData.getType());
            extensionDataCopies.put(edName, exensionDataCopy);
        }
        return extensionDataCopies;
    }
   
    /**
     * @param list
     * @return
     */
    private Collection cloneCollection(Collection col) {

        if (col == null) {
            return null;
        }

        if (col instanceof List) {
            List list = new ArrayList();
            list.addAll((List) col);
            return list;
        }
        else if (col instanceof Set) {
            Set set = new HashSet();
            set.addAll((Set) col);
            return set;
        }
        else if (col instanceof Bag) {
            Bag bag = new HashBag();
            bag.addAll((Bag) col);
            return bag;
        }
        else {
            throw new IllegalArgumentException("Cannot clone collections of type: " + col.getClass().getName());
        }

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#createDesignDocument(int,
     *      String, String)
     */
    public WGDocumentCore createDesignDocument(int type, String name, String mediaKey) throws WGAuthorisationException, WGCreationException {

        MainEntity newEntity = null;

        switch (type) {

        case WGDocument.TYPE_AREA:
            Area newArea = new Area();
            newArea.setName(name);
            newArea.setReaders(new ArrayList());
            newArea.setEditors(new ArrayList());
            newArea.setRootentries(new HashMap());
            newEntity = newArea;
            break;

        case WGDocument.TYPE_CONTENTTYPE:
            ContentType newContentType = new ContentType();
            newContentType.setName(name);
            newContentType.setAllowedpositions(new ArrayList());
            newEntity = newContentType;
            break;

        case WGDocument.TYPE_CSSJS:
            CSSJSModule newCSSJSModule = new CSSJSModule();
            newCSSJSModule.setName(name);
            if (mediaKey != null) {
                newCSSJSModule.setCodetype(mediaKey);
            }
            newEntity = newCSSJSModule;
            break;

        case WGDocument.TYPE_FILECONTAINER:
            FileContainer newFileContainer = new FileContainer();
            newFileContainer.setName(name);
            newFileContainer.setFiles(new HashMap());
            newEntity = newFileContainer;
            break;

        case WGDocument.TYPE_LANGUAGE:
            Language newLanguage = new Language();
            newLanguage.setName(name);
            newEntity = newLanguage;
            break;

        case WGDocument.TYPE_TML:
            TMLModule newTMLModule = new TMLModule();
            newTMLModule.setModulekey(new TMLModuleKey(name, mediaKey));
            newTMLModule.setDirectaccess(new Boolean(true));
            newTMLModule.setCacheable(new Boolean(false));
            newEntity = newTMLModule;
            break;
        }

        if (newEntity != null) {
            return createDocumentImpl(newEntity);
        }
        else {
            return null;
        }

    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#createStructEntry(WGDocument,
     *      WGContentType)
     */
    public WGDocumentCore createStructEntry(Object key, WGDocument reference, WGContentType contentType) throws WGAPIException {

        StructEntry newStructEntry = new StructEntry();

        if (contentType != null) {
            ContentType contentTypeEntity = (ContentType) ((WGDocumentImpl) contentType.getCore()).getEntity();
            newStructEntry.setContenttype(contentTypeEntity);
        }

        if (key != null) {
            newStructEntry.setKey(String.valueOf(key));
        }
        else {
            UUIDHexGenerator idGenerator = new UUIDHexGenerator();
            newStructEntry.setKey(String.valueOf(idGenerator.generate((SessionImplementor) getSession(), newStructEntry)));
        }

        if (reference instanceof WGArea) {
            Area area = (Area) ((WGDocumentImpl) reference.getCore()).getEntity();
            newStructEntry.setArea(area);
            area.getRootentries().put(newStructEntry.getKey(), newStructEntry);

        }
        else {
            StructEntry parentEntry = (StructEntry) getEntity(reference);
            newStructEntry.setParententry(parentEntry);
            parentEntry.getChildentries().put(newStructEntry.getKey(), newStructEntry);
        }

        newStructEntry.setReaders(new ArrayList());
        newStructEntry.setChildeditors(new ArrayList());
        newStructEntry.setPageeditors(new ArrayList());
        newStructEntry.setPublished(new HashMap());
        newStructEntry.setContent(new HashSet());
        newStructEntry.setChildentries(new HashMap());

        return createDocumentImpl(newStructEntry);

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#createUserProfile(String,
     *      int)
     */
    public WGDocumentCore createUserProfile(String name, int type) throws WGAuthorisationException, WGCreationException {

        UserProfile newProfile = new UserProfile();

        if (name != null) {
            newProfile.setName(name);
        }
        else {
            UUIDHexGenerator idGenerator = new UUIDHexGenerator();
            newProfile.setName(String.valueOf(idGenerator.generate((SessionImplementor) getSession(), newProfile)));
        }
        newProfile.setType(new Integer(type));
        newProfile.setHits(new Integer(0));
        newProfile.setSessions(new Integer(0));
        newProfile.setLanguages(new ArrayList<String>());
        newProfile.setPortletkeys(new ArrayList<String>());
        newProfile.setItems(new HashMap<String,UserProfileItem>());
        newProfile.setPortlets(new HashMap<String,UserProfilePortlet>());

        return createDocumentImpl(newProfile);
    }

    /**
     * @throws WGBackendException
     * @throws WGIllegalArgumentException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#fastAccess(Object)
     */
    public WGDocumentCore fastAccess(int type, Object key) throws WGBackendException, WGIllegalArgumentException {

        if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
          V5FastAccessKey v5Key = (V5FastAccessKey) key;
          if (v5Key.getId() != null) {
              Class clazz = getClassByType(v5Key.getType());
              MainEntity entity = (MainEntity) getSession().get(clazz, v5Key.getId());
              if (entity != null) {
                  return createDocumentImpl(entity);
              }
          }         
          return null;         
        }
        else {
            if (key instanceof String) {
                String cuid = (String) key;
                Content content = null;
                try {
                    content = (Content) getSession().get(Content.class, cuid);
                }
                catch (ObjectNotFoundException e) {
                    return null;
                }
                catch (HibernateException e) {
                    throw new WGBackendException("Error fast accessing content", e);
                }
   
                if (content != null) {
                    return createDocumentImpl(content);
                }
                else {
                    return null;
                }
            }
            else {
                throw new WGIllegalArgumentException("Parameter key must be an instance of String.");
            }
        }
    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getAllContent(WGStructEntry)
     */
    public List getAllContent(WGStructEntry structEntry, boolean includeArchived) throws WGAPIException {
       
        try {
            StructEntry hentry = (StructEntry) ((WGDocumentImpl) structEntry.getCore()).getEntity();
            /*
             * try { getSession().refresh(hentry); } catch (HibernateException e) {
             * throw new
             * WGBackendException("Error retrieving content of struct entry", e); }
             * Set contents = hentry.getContent(); if (contents == null) { return
             * new ArrayList(); } Iterator contentIt = contents.iterator();
             */
           
            StringBuffer queryText = new StringBuffer();
            queryText.append("select content from Content as content where content.structentry = :entry");
            if (!includeArchived) {
                queryText.append(" and not content.status = 'a'");
            }
            Query query = getSession().createQuery(queryText.toString());
            query.setParameter("entry", hentry);
            Iterator contentIt = query.iterate();
   
            List contentList = new ArrayList();
            Content content = null;
            while (contentIt.hasNext()) {
                content = (Content) contentIt.next();
                if (isVisibleForUser(content) && (includeArchived || content.getStatus() != WGContent.STATUS_ARCHIVE)) {
                    contentList.add(createDocumentImpl(content));
                }
            }
            return contentList;
        }
        catch (HibernateException e) {
            throw new WGBackendException("Exception retrieving struct entry content", e);
        }

    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getChildEntries(WGStructEntry)
     */
    public List getChildEntries(WGStructEntry structEntry) throws WGAPIException {
        StructEntry hentry = (StructEntry) ((WGDocumentImpl) structEntry.getCore()).getEntity();
        List entryList = new ArrayList();

        Map entries = hentry.getChildentries();
        if (entries != null) {

            Iterator entryIt = entries.values().iterator();

            MainEntity entity;
            while (entryIt.hasNext()) {
                entity = (MainEntity) entryIt.next();
                if (entity != null) {
                    entryList.add(createDocumentImpl(entity));
                }
            }
        }
        return entryList;
    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getContentByKey(WGContentKey)
     */
    public WGDocumentCore getContentByKey(WGContentKey key) throws WGAPIException {

        try {
           
            Query contentQuery;
            if (key.getVersion() != 0) {
                contentQuery = getSession().createQuery("from Content as content where content.structentry.key =:structkey and content.language.name =:lang and content.version =:version");
                contentQuery.setInteger("version", key.getVersion());
            }
            else {
                contentQuery = getSession().createQuery("from Content as content where content.structentry.key =:structkey and content.language.name =:lang and content.status ='p'");
            }
            contentQuery.setString("structkey", String.valueOf(key.getStructKey()));
            contentQuery.setString("lang", key.getLanguage());

            
            List contents = contentQuery.list();

            if (contents.size() >= 1) {
                Content content = (Content) contents.get(0);
                if (isVisibleForUser(content)) {
                    return createDocumentImpl((MainEntity) contents.get(0));
                }
                else {
                    return null;
                }
            }
            else {
                return null;
            }
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error loading content by key", e);
        }

    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getContentByName(String,
     *      String)
     */
    public WGDocumentCore getContentByName(String strName, String strLanguage) throws WGAPIException {

        strName = strName.toLowerCase();
        strLanguage = (strLanguage != null ? strLanguage.toLowerCase() : null);

        String queryStr = "from Content as content where content.uniquename=:name";
        if (strLanguage != null) {
            queryStr += " and content.language.name=:lang";
        }

        Iterator contents;
        try {
            Query query = getSession().createQuery(queryStr);
            query.setString("name", strName);
            if (strLanguage != null) {
                query.setString("lang", strLanguage);
            }
           
            contents = query.iterate();
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error searching content by name", e);
        }

        Content content;
        while (contents.hasNext()) {
            content = (Content) contents.next();
            if (content.getStatus().equals(WGContent.STATUS_RELEASE) && (strLanguage == null || strLanguage.equals(content.getLanguage().getName())) && isVisibleForUser(content)) {
                return createDocumentImpl(content);
            }
        }

        return null;

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getDedicatedWorkflowEngine()
     */
    public Class getDedicatedWorkflowEngine() {
        return null;
    }

    /**
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getDesignObject(int,
     *      String, String)
     */
    public WGDocumentCore getDesignObject(int type, String name, String strMediaKey) throws WGBackendException {

        Class designClass = getClassByType(type);       
        MainEntity design = null;
        try {
            if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                design = getDesignObjectV5(name, strMediaKey, designClass);
            }
            else {
                design = getDesignObjectV4(name, strMediaKey, designClass);       
            }
        }
        catch (ObjectNotFoundException e) {
            return null;
        }
        catch (ObjectDeletedException e) {
            return null;
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error retrieving design object", e);
        }

        if (design != null) {
            return createDocumentImpl(design);
        }
        else {
            return null;
        }

    }



    private MainEntity getDesignObjectV5(String name, String strMediaKey, Class designClass) {
       
        Criteria crit = getSession().createCriteria(designClass);
        crit.add(Restrictions.eq("name", name));
        if (designClass == TMLModule.class) {
            crit.add(Restrictions.eq("mediakey", strMediaKey));
        }
        else if (designClass == CSSJSModule.class) {
            crit.add(Restrictions.eq("codetype", strMediaKey));
        }
       
        List results = crit.list();
        if (results.size() > 0) {
            return (MainEntity) results.get(0);
        }
        else {
            return null;
        }
       
    }



    private MainEntity getDesignObjectV4(String name, String strMediaKey, Class designClass) {
        MainEntity design;
        if (designClass == TMLModule.class) {
            design = (MainEntity) getSession().get(designClass, new TMLModuleKey(name, strMediaKey));
        }
        else {
            design = (MainEntity) getSession().get(designClass, name);
        }
        return design;
    }

    /**
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getDesignObjects(int)
     */
    public List getDesignObjects(int type) throws WGBackendException {

        String query = "from " + getClassByType(type).getName() + " as design";
        Iterator designs;
        try {
            designs = getSession().createQuery(query).iterate();
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error retrieving design objects.", e);          
        }

        List designList = new ArrayList();
        while (designs.hasNext()) {
            designList.add(createDocumentImpl((MainEntity) designs.next()));

        }

        return designList;

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getDummyContent(String)
     */
    public WGDocumentCore getDummyContent(String language) {
        return new de.innovationgate.webgate.api.fake.WGDummyContent(this._db, language);
    }

    /**
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getRevision()
     */
    public Comparable getRevision() throws WGBackendException {

        try {
            List result;
            if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {               
                //Sequence seq = (Sequence) getSession().get(Sequence.class, "historylog_id");
                //if (seq != null) {
                    //return (seq.getValue() - 1);
                //}
                result = getSession().createQuery("select max(entry.id) from LogEntry as entry").list();
                if (result.size() > 0) {
                    Long id = (Long) result.get(0);
                    if (id != null) {
                        return id;
                    }
                }
                    return Long.MIN_VALUE;               
                }
            else {
                result = getSession().createQuery("select max(entry.logtime) from LogEntry as entry").list();
                Date lcDate = null;
                if (result.size() > 0) {
                    lcDate = (Date) result.get(0);
                }
   
                if (lcDate != null) {
                    return lcDate;
                }
                else {
                    return new Date(Long.MIN_VALUE);
                }
            }
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error retrieving historylog of database '" + getTitle() + "'", e);           
        }

    }

    /**
     * @throws WGIllegalArgumentException
     * @throws WGBackendException
     * @throws WGSystemException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getExtensionData(String)
     */
    public Object getExtensionData(String name) throws WGIllegalArgumentException, WGBackendException, WGSystemException {
       
        name = name.toLowerCase().trim();
        ExtensionData md = retrieveExtensionData(name);
       
        if (md != null) {
            return WGDocumentImpl.readItemValue(md);
        }
        else {
            return null;
        }
       
    }



    private ExtensionData retrieveExtensionData(String name) {
        ExtensionData md = null;
        Criteria c = getSession().createCriteria(ExtensionData.class);
        c.add(Restrictions.eq("name", name));
        c.add(Restrictions.isNull("entity"));
        List<ExtensionData> results = c.list();
        if (results.size() > 0) {
            md = results.get(0);
        }
        return md;
    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getNewDesignsSince(Date)
     */
    public List getNewDesignsSince(Date date) {
        return null;
    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getParentEntry(WGStructEntry)
     */
    public WGDocumentCore getParentEntry(WGStructEntry entry) throws WGAPIException {

        StructEntry hentry = (StructEntry) ((WGDocumentImpl) entry.getCore()).getEntity();
        StructEntry parent = (StructEntry) hentry.getParententry();
        if (parent != null) {
            return createDocumentImpl(parent);
        }
        else {
            return null;
        }

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getRoles()
     */
    public List getRoles() {
        return Arrays.asList(new String[] { WGDatabase.ROLE_CONTENT, WGDatabase.ROLE_DESIGN, WGDatabase.ROLE_REPOSITORY, WGDatabase.ROLE_USERPROFILES });
    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getRootEntries(WGArea)
     */
    public List getRootEntries(WGArea area) throws WGAPIException {

        Area harea = (Area) ((WGDocumentImpl) area.getCore()).getEntity();
        Iterator entryIt = harea.getRootentries().values().iterator();
        List entryList = new ArrayList();
        Object entity;
        while (entryIt.hasNext()) {
            entity = entryIt.next();
            if (entity != null) {
                entryList.add(createDocumentImpl((MainEntity) entity));
            }

        }
        return entryList;
    }

    /**
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getStructEntryByKey(Object)
     */
    public WGDocumentCore getStructEntryByKey(Object key) throws WGBackendException {

        try {
            StructEntry entry = null;
            if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                Criteria crit = getSession().createCriteria(StructEntry.class);
                crit.add(Restrictions.eq("key", String.valueOf(key)));
                List results = crit.list();
                if (results.size() > 0) {
                    entry = (StructEntry) results.get(0);
                }
            }
            else {
                entry = (StructEntry) getSession().get(StructEntry.class, (String) key);
            }
            if (entry != null) {
                return createDocumentImpl(entry);
            }
            else {
                return null;
            }
        }
        catch (ObjectNotFoundException e) {
            return null;
        }

        catch (HibernateException e) {
            throw new WGBackendException("Error loading structentry by key", e);
        }

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getTitle()
     */
    public String getTitle() {
        return _path;
    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getTypeName()
     */
    public String getTypeName() {
        return DBTYPE;
    }

    /**
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getUserProfile(String)
     */
    public WGDocumentCore getUserProfile(String name) throws WGBackendException {

        try {
            UserProfile profile = null;
           
            if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                Criteria q = getSession().createCriteria(UserProfile.class);
                q.add(Restrictions.eq("name", name));
                List results = q.list();
                if (results.size() > 0) {
                    profile = (UserProfile) results.get(0);
                }
            }
            else {
                profile = (UserProfile) getSession().get(UserProfile.class, name);
            }
            if (profile != null) {
                return createDocumentImpl(profile);
            }
            else {
                return null;
            }
        }
        catch (ObjectNotFoundException e) {
            return null;
        }

        catch (HibernateException e) {
            throw new WGBackendException("Error loading userprofile for name '" + name + "'.", e);
        }

    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#hasFeature(String)
     */
    public boolean hasFeature(String feature) {

        if (feature.equals(WGDatabase.FEATURE_EDITABLE) || feature.equals(WGDatabase.FEATURE_FULLCONTENTFEATURES) || feature.equals(WGDatabase.FEATURE_HIERARCHICAL)
                || feature.equals(WGDatabase.FEATURE_QUERYABLE) || feature.equals(WGDatabase.FEATURE_USE_OBJECTS_AS_REFERENCES) || feature.equals(WGDatabase.FEATURE_LASTCHANGED)
                || feature.equals(WGDatabase.FEATURE_GENERATES_STRUCTKEYS) || feature.equals(WGDatabase.FEATURE_ACCEPTS_STRUCTKEYS) || feature.equals(WGDatabase.FEATURE_MULTILANGUAGE)
                || feature.equals(WGDatabase.FEATURE_ACL_MANAGEABLE) || feature.equals(WGDatabase.FEATURE_COMPLEXVALUES) || feature.equals(WGDatabase.FEATURE_FIND_UPDATED_DOCS)
                || feature.equals(WGDatabase.FEATURE_RETRIEVE_ALL_CONTENTKEYS) || feature.equals(WGDatabase.FEATURE_QUERY_PROFILES) || feature.equals(WGDatabase.FEATURE_EXTERNAL_AUTHENTICATION)
                || feature.equals(WGDatabase.FEATURE_VALIDATE_ATTACHMENTS) || feature.equals(WGDatabase.FEATURE_SELF_PERSONALIZABLE) || feature.equals(WGDatabase.FEATURE_UNLIMITED_CORES)
                || feature.equals(WGDatabase.FEATURE_TRANSACTIONS)) {
            return true;
        }
        else if (feature.equals(WGDatabase.FEATURE_LOADBALANCE)) {
            if (_db.getCreationOptions().get(COPTION_LOADBALANCE) != null && Boolean.valueOf((String) _db.getCreationOptions().get(COPTION_LOADBALANCE)).booleanValue()) {
            return true;
          }
          else {
            return false;
          }
        }
        else {
            return false;
        }

    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#isMemberOfUserList(List)
     */
    public boolean isMemberOfUserList(List userList) throws WGAPIException {
        return _db.defaultIsMemberOfUserList(userList);
    }

    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#open(WGDatabase,
     *      String, String, String, boolean)
     */
    public WGUserAccess open(WGDatabase db, String path, String user, String pwd, boolean prepareOnly) throws WGInvalidDatabaseException {

        this._db = db;
        this._path = path;
        this._aclImpl = new ACLImpl(this);

        // Determine dll version
        String jdbcDriver = (String) db.getCreationOptions().get("Driver");
        if (jdbcDriver == null) {
            jdbcDriver = (String) db.getCreationOptions().get("hibernate.connection.driver_class");
        }
       
        CSVersion version = determineCSVersion(db, jdbcDriver, path, user, pwd);
        _ddlVersion = version.getVersion();

        // Determine mapping file
        Configuration conf = new Configuration();
        try {
            if (db.getCreationOptions().containsKey(DBOPTION_MAPPINGFILE)) {
                File mappingFile = new File((String) db.getCreationOptions().get(DBOPTION_MAPPINGFILE));
                if (!mappingFile.exists() || !mappingFile.isFile()) {
                    throw new WGInvalidDatabaseException("Configured mapping file '" + db.getCreationOptions().get(DBOPTION_MAPPINGFILE) + "' does not exist or is no valid file.");
                }
                conf.addFile(mappingFile);
            }
            else if (db.getCreationOptions().containsKey(DBOPTION_MAPPINGRESOURCE)) {
                conf.addResource((String) db.getCreationOptions().get(DBOPTION_MAPPINGRESOURCE), this.getClass().getClassLoader());
            }
            else if (_ddlVersion == WGDatabase.CSVERSION_WGA5) {
               
                if (version.getPatchLevel() >= 3) {
                    conf.addResource(HIBERNATE_V5_P3_MAPPING_FILE, this.getClass().getClassLoader());
                }
                else if (version.getPatchLevel() >= 2) {
                    conf.addResource(HIBERNATE_V5_P2_MAPPING_FILE, this.getClass().getClassLoader());
                }
                else {
                    conf.addResource(HIBERNATE_V5_MAPPING_FILE, this.getClass().getClassLoader());
                }
            }
            else if (_ddlVersion == WGDatabase.CSVERSION_WGA4_1) {
                conf.addResource(HIBERNATE_V41_MAPPING_FILE, this.getClass().getClassLoader());
            } else {
              conf.addResource(HIBERNATE_V3_MAPPING_FILE, this.getClass().getClassLoader());
            }
        }
        catch (MappingException e) {
            throw new WGInvalidDatabaseException("Exception parsing hibernate mapping", e);
        }

        Properties props = new Properties();
        if (path.startsWith("jdbc:")) {
            props.put("hibernate.connection.url", path);
            putDefaultConPoolProps(props);
        }
        else {
            props.put("hibernate.connection.datasource", path);
        }

        if (user != null || pwd != null) {
            props.put("hibernate.connection.username", WGUtils.getValueOrDefault(user, ""));
            props.put("hibernate.connection.password", WGUtils.getValueOrDefault(pwd, ""));
        }
       
        if (db.getCreationOptions().containsKey("Driver")) {
            props.put("hibernate.connection.driver_class", db.getCreationOptions().get("Driver"));
        }
       
        // Move old Hibernate2 packages to Hibernate3 packages
        Iterator dbOptionsIt = db.getCreationOptions().keySet().iterator();
        while (dbOptionsIt.hasNext()) {
            Object key = dbOptionsIt.next();
            String value = (String) db.getCreationOptions().get(key);
            if (value != null && value.startsWith("net.sf.hibernate.")) {
                value = "org.hibernate." + value.substring(17);
                db.getCreationOptions().put(key, value);
            }
        }

        props.put(Environment.ISOLATION, String.valueOf(Connection.TRANSACTION_READ_COMMITTED));
        //props.put(Environment.QUERY_SUBSTITUTIONS, "true 1, false 0");

        props.putAll(db.getCreationOptions());
        conf.addProperties(props);
       
        // Create session factory
        try {
            _sessionFactory = conf.buildSessionFactory();
        }
        catch (HibernateException e) {
            throw new WGInvalidDatabaseException("Error creating session factory: " + e.getMessage(), e);
        }

        // parse masterPersistenceTimeout
        if (db.getCreationOptions().containsKey(COPTION_MASTERPERSISTENCE_TIMEOUT)) {
          _masterPersistenceTimeout = Long.parseLong((String)db.getCreationOptions().get(COPTION_MASTERPERSISTENCE_TIMEOUT));
        }

        // parse HQL query default type
        String hqlType = (String) db.getCreationOptions().get(COPTION_HQL_FETCH_TYPE);
        if (hqlType != null) {
            _hqlLazyByDefault = hqlType.equals(HQL_FETCHTYPE_LAZY);
        }
       
        // open session
        WGUserAccess accessLevel;
        try {
            accessLevel = openSession(MasterLoginAuthSession.getInstance(), pwd, true);
        }
        catch (WGUnavailableException e) {
            throw new WGInvalidDatabaseException("Error opening initial session", e);
        }
        catch (WGBackendException e) {
            throw new WGInvalidDatabaseException("Error opening initial session", e);
        }
        if (accessLevel.getAccessLevel() <= WGDatabase.ACCESSLEVEL_NOACCESS) {
            try {
                close();
            }
            catch (WGBackendException e1) {
                WGFactory.getLogger().error(e1);
            }
        }
        return accessLevel;

    }



    /**
     * @param db
     * @param jdbcDriver
     * @param path
     * @param userName
     * @param password
     * @return
     * @throws WGInvalidDatabaseException
     */
    /**
     * @param db
     * @param jdbcDriver
     * @param path
     * @param userName
     * @param password
     * @return
     * @throws WGInvalidDatabaseException
     */
    private CSVersion determineCSVersion(WGDatabase db, String jdbcDriver, String path, String userName, String password) throws WGInvalidDatabaseException {
       
        // Explicitly set content store version
        String csVersion = (String) db.getCreationOptions().get(WGDatabase.COPTION_CONTENT_STORE_VERSION);
        if (csVersion != null) {
            Double version = Double.parseDouble(csVersion);
            if (version == WGDatabase.CSVERSION_WGA3 || version == WGDatabase.CSVERSION_WGA4_1 || version == WGDatabase.CSVERSION_WGA5) {
                return new CSVersion(version, 0);
            }
        }
       
        // Auto detection by inspecting tables in the database
        try {
            Properties props = new Properties();
            Map creationOptions =  db.getCreationOptions();
            Iterator optsIt = creationOptions.keySet().iterator();
            while (optsIt.hasNext()) {
                String option = (String) optsIt.next();
                if (option.startsWith(("jdbc."))) {
                    props.put("hibernate.connection." + option.substring(5), creationOptions.get(option));
                }
            }
            props.put("user", WGUtils.getValueOrDefault(userName, ""));
            props.put("password", WGUtils.getValueOrDefault(password, ""));
            JDBCConnectionProvider connProvider = new JDBCConnectionProvider(path, (String) db.getCreationOptions().get(jdbcDriver), props, false);
            try {
                double version = determineCSVersion(connProvider);
                int patchLevel = 0;
                if (version == WGDatabase.CSVERSION_WGA5) {
                    patchLevel = determinePatchLevel(connProvider);
                }
                return new CSVersion(version, patchLevel);
            }
            finally {
                try {
                    connProvider.close();
                }
                catch (Exception e) {
                    WGFactory.getLogger().error("Exception closing JDBC connection provider", e);
                }
            }
           
        }
        catch (JDBCConnectionException e) {
            throw new WGInvalidDatabaseException("Exception connecting to database on path " + path, e);
        }
        catch (SQLException e) {
            throw new WGInvalidDatabaseException("Exception connecting to database on path " + path, e);
        }

    }



    protected double determineCSVersion(JDBCConnectionProvider connProvider) throws SQLException {
        List<String> tables = connProvider.getDatabaseTables();
       
        if (tables.contains(getCS5IndicatorTable())) {
            return WGDatabase.CSVERSION_WGA5;
        }
       
        else if (tables.contains(getCS41IndicatorTable())) {
            return WGDatabase.CSVERSION_WGA4_1;
        }
        // This is a new HSQL content store to be created - Currently we create CS5 by default
        else if (this instanceof de.innovationgate.webgate.api.hsql.WGDatabaseImpl & tables.size() == 0) {
            return WGDatabase.CSVERSION_WGA5;
        }
       
        else {
            return WGDatabase.CSVERSION_WGA3;
        }
    }



    private int determinePatchLevel(JDBCConnectionProvider connProvider) {
        int patchLevel = 0;
        Statement stmt = null;
        ResultSet res = null;
        try {
            stmt = connProvider.getConnection().createStatement();
            res = stmt.executeQuery("SELECT datatype, numbervalue, textvalue FROM extensiondata WHERE entity_id IS NULL AND name='" + DBMETA_PATCH_LEVEL.toLowerCase() + "'");
            if (res.next()) {
                int type = res.getInt(1);
                Double numberValue = res.getDouble(2);
                String textValue = res.getString(3);
                if (type == WGDocumentImpl.ITEMTYPE_NUMBER) {
                    patchLevel = numberValue.intValue();
                }
                else if (type == WGDocumentImpl.ITEMTYPE_SERIALIZED_XSTREAM) {
                    XStream xstream = new XStream(new Dom4JDriver());
                    patchLevel = ((Number) xstream.fromXML(textValue)).intValue();
                }
            }
        }
        catch (Exception e) {
            WGFactory.getLogger().error("Exception determining CS5 patch level", e);
        }
        finally {
            try {
                if (res != null) {
                    res.close();
                }
               
                if (stmt != null) {
                    stmt.close();
                }
            }
            catch (Exception e) {
                WGFactory.getLogger().error("Exception closing resource for CS version determination", e);
            }
        }
       
        return patchLevel;
    }



    protected String getCS5IndicatorTable() {
        return "extensiondata";
    }



    protected String getCS41IndicatorTable() {
        return "content_files_meta";
    }



    protected String getCS3MappingFile() {
        return HIBERNATE_V3_MAPPING_FILE;
    }



    protected String getCS41MappingFile() {
        return HIBERNATE_V41_MAPPING_FILE;
    }




   


    /**
     * @throws WGUnavailableException
     * @throws WGBackendException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#openSession(String,
     *      String)
     */
    public WGUserAccess openSession(AuthenticationSession authSession, Object pwd, boolean master) throws WGUnavailableException, WGBackendException {

        try {

            // Hibernate login
            Session session = _sessionFactory.openSession();
            // Connection conn = session.connection();
            // conn.setAutoCommit(true); //Problematic with DBCP?
            session.setFlushMode(FlushMode.COMMIT);
            getSessionStatus().setSession(session);
           
            if (!session.isOpen()) {
                throw new WGUnavailableException(_db, "Unable to connect to hibernate session");
            }
           
          // special handling if loadbalancing is enabled
            if (hasFeature(WGDatabase.FEATURE_LOADBALANCE)) {
           
                // set all connections to readonly except master sessions and if
                // update is in progress
              boolean readOnly;             
              if (master) {
                readOnly = false;
              } else {
                readOnly = !isUpdateInProgress(authSession.getDistinguishedName());
              }
             
              try {
          session.connection().setReadOnly(readOnly);
                }
                catch (SQLException e) {
          throw new WGBackendException("Unable to set readonly flag on connection." , e);
        }
            }

            if (getTransactionMode() != WGSessionContext.TRANSACTION_MODE_MANUAL) {
                session.beginTransaction();
            }

            if (master) {
                // Master login always has manager access
                getSessionStatus().setUserDetails(new WGUserDetails(WGDatabase.ACCESSLEVEL_MANAGER, WGDatabase.MASTER_USERNAME ,"(None)", null, null, null, null, null, true, true));
                return new WGUserAccess(WGDatabase.MASTER_USERNAME, WGDatabase.ACCESSLEVEL_MANAGER);
            }

            // Determine access
            WGUserDetails userDetails;
            try {
                userDetails = _db.defaultBuildUserDetails(authSession);
            }
            catch (WGBackendException e) {
                try {
                    closeSession();
                }
                catch (WGBackendException e1) {
                    WGFactory.getLogger().error(e1);
                }
                throw e;
            }
            getSessionStatus().setUserDetails(userDetails);
            if (userDetails.getAccessLevel() <= WGDatabase.ACCESSLEVEL_NOACCESS) {
                try {
                    closeSession();
                }
                catch (WGBackendException e) {
                    WGFactory.getLogger().error(e);
                }
            }

            return userDetails;

        }
        catch (HibernateException e) {
            try {
                closeSession();
            }
            catch (WGBackendException e1) {
                WGFactory.getLogger().error(e1);
            }
            throw new WGUnavailableException(_db, "Error opening hibernate session", e);
        }

    }



    private int getTransactionMode() {
        if (_db.getSessionContext() != null) {
            return _db.getSessionContext().getTransactionMode();
        } else {
            return WGSessionContext.TRANSACTION_MODE_DEFAULT;
        }
    }


    /**
     * @see de.innovationgate.webgate.api.WGDatabaseCore#parseStructKey(String)
     */
    public Object parseStructKey(String key) {

        return key;

    }

    /**
     * @throws WGAPIException
     * @see de.innovationgate.webgate.api.WGDatabaseCore#query(String, String,
     *      Map)
     */
    public WGResultSetCore query(String type, String query, Map params) throws WGAPIException {

        if (type == null) {
            type = "hql";
        }

        if (type.equals("native")) {
            type = "hql";
        }

        if (type.equals("hql") || type.equals("fullhql")) {
            return executeHQLQuery(type, query, params);
        }
        else if (type.equals("fulltext")) {
            return executeFulltextQuery(query, params);
        }
        else if (type.equals("sql")) {
            return executeSQLQuery(query, params);
        }
        else {
            throw new WGQueryException(query, "Unknown query type: " + type);
        }

    }

    /**
     * @param query
     * @param params
     * @return
     * @throws WGAPIException
     */
    private WGResultSetCore executeFulltextQuery(String query, Map params) throws WGAPIException {

        // Build base query
        query = WGUtils.strReplace(query, "'", "''", true);
        params.put(WGDatabase.QUERYOPTION_RETURNQUERY, query);
        StringBuffer builtQuery = createFulltextQuery(query);

        // Additions based on params
        if (params.containsKey(WGDatabase.QUERYOPTION_ONLYRELEASED)) {
            builtQuery.append(" and content.status = 'p'");
        }

        if (params.containsKey(WGDatabase.QUERYOPTION_ONLYLANGUAGE)) {
            builtQuery.append(" and languages.name = '").append(params.get(WGDatabase.QUERYOPTION_ONLYLANGUAGE).toString()).append("'");
        }

        if (params.containsKey(WGDatabase.QUERYOPTION_EXCLUDEDOCUMENT)) {
            WGContent content = (WGContent) params.get(WGDatabase.QUERYOPTION_EXCLUDEDOCUMENT);
            if (content.getDatabase() == this._db) {
                WGDocumentCore contentCore = content.getCore();
                if (contentCore instanceof WGDocumentImpl) {
                    Content contentEntity = (Content) ((WGDocumentImpl) content.getCore()).getEntity();
                    builtQuery.append(" and not (content.cuid = '" + contentEntity.getCuid() + "')");
                }
            }
        }

        // Execute query
        String fullQuery = builtQuery.toString();
        return executeSQLQuery(fullQuery, params);

    }

    private WGResultSetCore executeSQLQuery(String fullQuery, Map params) throws WGAPIException {
        try {
            params.put(WGDatabase.QUERYOPTION_RETURNQUERY, fullQuery);
            SQLQuery hibQuery = getSession().createSQLQuery(fullQuery);
            hibQuery.addEntity("content", Content.class);
            Map queryParams = (Map) params.get(WGDatabase.QUERYOPTION_QUERY_PARAMETERS);
            HibernateResultSet.injectQueryParams(hibQuery, queryParams);
            return new WGSQLResultSet(this, hibQuery, queryParams);
        }
        catch (SQLGrammarException e) {
            throw new WGQueryException(fullQuery, e.getMessage(), e);
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error executing SQL query", e);
        }
    }

    private StringBuffer createFulltextQuery(String query) {

        StringBuffer builtQuery = new StringBuffer();
        builtQuery
                .append("select {content.*} from content {content} left outer join content_items on content.cuid = content_items.cuid inner join languages on content.language = languages.name where (content.title like '%");
        builtQuery.append(query);
        builtQuery.append("%' or content.description like '%");
        builtQuery.append(query);
        builtQuery.append("%' or content_items.textvalue like '%");
        builtQuery.append(query);
        builtQuery.append("%')");
        return builtQuery;
    }

    private WGResultSetCore executeHQLQuery(String type, String query, Map params) throws WGAPIException {
        String builtQuery = null;

        Map queryParams = (Map) params.get(WGDatabase.QUERYOPTION_QUERY_PARAMETERS);
        if (queryParams == null) {
            queryParams = new HashMap();
        }
       
        List<WGLanguage> languagesPriorityList = null;
       
        // Determine fetch type. Lazy fetch will only retrieve content keys and
        // get content data in subsequent calls
        List options = WGUtils.deserializeCollection(String.valueOf(params.get(WGDatabase.QUERYOPTION_NATIVEOPTIONS)), ",", true);
        boolean lazyFetch = _hqlLazyByDefault;
        if (options.contains(HQL_FETCHTYPE_STRAIGHT)) {
            lazyFetch = false;
        }
        else if (options.contains(HQL_FETCHTYPE_LAZY)) {
            lazyFetch = true;
        }
       
        if (type.equals("fullhql")) {
            builtQuery = query;
        }
        if (type.equals("hql")) {
            List fullQuery = new ArrayList();
           
            // Filter invisible and unreleased docs
            if (!params.containsKey(WGDatabase.QUERYOPTION_ENHANCE) || String.valueOf(params.get(WGDatabase.QUERYOPTION_ENHANCE)).equals("true")) {
                String role = WGContent.DISPLAYTYPE_SEARCH;
                if (params.containsKey(WGDatabase.QUERYOPTION_ROLE)) {
                    role = (String) params.get(WGDatabase.QUERYOPTION_ROLE);
                }
                if (role != null && !role.equals(WGContent.DISPLAYTYPE_NONE)) {
                    fullQuery.add("content.visible=" + getNativeSQLExpression(NATIVESQL_BOOLEAN_TRUE) + " and :wgaparamRole not in elements(content.ishiddenfrom)");
                    queryParams.put("wgaparamRole", role);
                }
            }

            if (params.containsKey(WGDatabase.QUERYOPTION_ONLYRELEASED)) {
                fullQuery.add("content.status = 'p'");
            }
           
            // Filter languages
            if (params.containsKey(WGDatabase.QUERYOPTION_LANGUAGES)) {
                List<WGLanguage> langs = (List<WGLanguage>) params.get(WGDatabase.QUERYOPTION_LANGUAGES);
                if (langs.size() > 1 && lazyFetch) {
                    List languageTerms = new ArrayList();
                    for (WGLanguage lang : langs) {
                        languageTerms.add("content.language.name = '" + lang.getName() + "'");
                    }
                    fullQuery.add("(" + WGUtils.serializeCollection(languageTerms, " OR ") + ")");
                    languagesPriorityList = langs;
                }
                else if (langs.size() == 1){
                    fullQuery.add("content.language.name = :wgaparamLanguage");
                    queryParams.put("wgaparamLanguage", langs.get(0).getName());
                }
                else {
                    fullQuery.add("content.language.name = :wgaparamLanguage");
                    queryParams.put("wgaparamLanguage", getDb().getDefaultLanguage());
                }
               
            }
            else if (params.containsKey(WGDatabase.QUERYOPTION_ONLYLANGUAGE)) {
                fullQuery.add("content.language.name = '" + params.get(WGDatabase.QUERYOPTION_ONLYLANGUAGE).toString() + "'");
            }
           
            // Filter the "current document"
            if (params.containsKey(WGDatabase.QUERYOPTION_EXCLUDEDOCUMENT)) {
                WGContent content = (WGContent) params.get(WGDatabase.QUERYOPTION_EXCLUDEDOCUMENT);
                if (content.getDatabase() == this._db) {
                    WGDocumentCore contentCore = content.getCore();
                    if (contentCore instanceof WGDocumentImpl) {
                        Content contentEntity = (Content) ((WGDocumentImpl) content.getCore()).getEntity();
                        if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                            fullQuery.add("not content.id = :wgaparamEntityId");
                            queryParams.put("wgaparamEntityId", contentEntity.getId());
                        }
                        else {
                            fullQuery.add("not content.cuid = :wgaparamEntityId");
                            queryParams.put("wgaparamEntityId", contentEntity.getCuid());
                        }
                    }
                }
            }

            // Extract ORDER BY part to get it out of the brackets
            String furtherClauses = "";
            int whereClauseEndIdx = query.toLowerCase().indexOf("group by");
            if (whereClauseEndIdx == -1) {
                whereClauseEndIdx = query.toLowerCase().indexOf("order by");
            }
            if (whereClauseEndIdx != -1) {
                furtherClauses = query.substring(whereClauseEndIdx);
                query = query.substring(0, whereClauseEndIdx);
            }

            fullQuery.add("(" + query + ")");
           
           
            builtQuery = composeHQLQuery(fullQuery, furtherClauses, lazyFetch);
        }

        if (builtQuery == null) {
            throw new WGQueryException(query, "Unknown query type: " + type);
        }
       
        builtQuery = WGUtils.strReplace(builtQuery, "\"", "'", true);

        if (params != null) {
            params.put(WGDatabase.QUERYOPTION_RETURNQUERY, builtQuery);
        }

        List results = null;
        try {
            Query hibQuery = getSession().createQuery(builtQuery);
            int maxResults = 0;
            if (params.containsKey(WGDatabase.QUERYOPTION_MAXRESULTS)) {
                 maxResults = ((Number) params.get(WGDatabase.QUERYOPTION_MAXRESULTS)).intValue();
            }
            if (maxResults > 0) {
                hibQuery.setMaxResults(maxResults);
            }
           
            HibernateResultSet.injectQueryParams(hibQuery, queryParams);
            if (lazyFetch) {
                if (languagesPriorityList != null) {
                    return new WGLanguageChoosingHQLResultSet(this, hibQuery, queryParams, languagesPriorityList);
                }
                else {
                    return new WGLazyHQLResultSet(this, hibQuery, queryParams);
                }
            }
            else {
                return new WGStraightHQLResultSet(this, hibQuery, queryParams);
            }
        }
        catch (QueryException e) {
            throw new WGQueryException(builtQuery, e.getMessage(), e);
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error executing HQL query", e);
        }
       
       
           
    }



    protected String getNativeSQLExpression(String expression) {
        if (NATIVESQL_BOOLEAN_TRUE.equals(expression)) {
            return "1";
        }
        else {
            return "";
        }
    }



    protected String composeHQLQuery(List fullQuery, String orderBy, boolean lazy) {
               
        if (lazy)  {
            return HQLQUERY_LAZY + WGUtils.serializeCollection(fullQuery, " and ") + " " + orderBy;
        }
        else {
            return HQLQUERY_STRAIGHT + WGUtils.serializeCollection(fullQuery, " and ") + " " + orderBy;
        }
    }

    public static Class getClassByType(int type) {
        return (Class) _typeToObject.get(new Integer(type));
    }

    public static int getTypeByClass(Class aClass) {
        return ((Integer) _objectToType.get(aClass)).intValue();
    }

    public Object getEntity(WGDocument doc) throws WGAPIException {
        return ((WGDocumentImpl) doc.getCore()).getEntity();
    }

    /*
     * (Kein Javadoc)
     *
     * @see de.innovationgate.webgate.api.WGDatabaseCore#beginTransaction()
     */
    public boolean beginTransaction() {
        Transaction transaction = getSession().getTransaction();
        if (transaction != null && transaction.isActive()) {
            transaction.rollback();
        }       
        transaction = getSession().beginTransaction();       
        if (transaction != null) {
            getSession().setCacheMode(CacheMode.GET);
            _db.getSessionContext().setTransactionMode(WGSessionContext.TRANSACTION_MODE_MANUAL);
            return true;
        } else {
            return false;
        }
    }

    /*
     * (Kein Javadoc)
     *
     * @see de.innovationgate.webgate.api.WGDatabaseCore#commitTransaction()
     */
    public boolean commitTransaction() {
        Transaction transaction = getSession().getTransaction();
        if (transaction != null) {
            transaction.commit();
            getSession().setCacheMode(CacheMode.NORMAL);
            _db.getSessionContext().resetTransactionMode();
            getSession().beginTransaction();
            return true;
        }
      return false;    
    }
   
    public void beginUpdate() throws WGBackendException {     
      try {
        getSession().getTransaction().rollback();
        if (getSession().connection().isReadOnly()) {
          getSession().connection().setReadOnly(false);
        }
       
        String user = _db.getSessionContext().getUser();
        DBUpdate update = new DBUpdate(_db.getSessionContext());       
        _dbUpdatesByUser.put(user, update);
       
      getSession().beginTransaction();
        }
        catch (HibernateException e) {
      throw new WGBackendException("unable to start transaction", e);
        }
        catch (SQLException e) {
      throw new WGBackendException("unable to start transaction", e);
    }     
       
    }

    /**
     * checks if an update is in progress for the current session context
     *
     * @return
     */
    private boolean isUpdateInProgress() {
      if (_db.getSessionContext() != null) {
        String user = _db.getSessionContext().getUser();         
        DBUpdate update = (DBUpdate) _dbUpdatesByUser.get(user);
        if (update != null) {
          return update.isInProgress();
            }
            else {
          return false;
        }
        }
        else {
        return false;
      }
    }
   
    /**
     * checks if an update is in progress for the given user
     *
     * @param user
     * @return
     */
    private boolean isUpdateInProgress(String user) {
      DBUpdate update = (DBUpdate) _dbUpdatesByUser.get(user);
    if (update != null) {
      return update.isInProgress();
        }
        else {
        return false;
    }
    }

    /*
     * (Kein Javadoc)
     *
     * @see de.innovationgate.webgate.api.WGDatabaseCore#rollbackTransaction()
     */
    public boolean rollbackTransaction() {
        Transaction transaction = getSession().getTransaction();
        if (transaction != null && transaction.isActive()) {
            transaction.rollback();
            getSession().setCacheMode(CacheMode.NORMAL);
            _db.getSessionContext().resetTransactionMode();
            getSession().beginTransaction();
            return true;
        }
        return false;
    }

    /*
     * (Kein Javadoc)
     *
     * @see
     * de.innovationgate.webgate.api.WGDatabaseCore#execProcedure(java.lang.
     * String, java.util.List)
     */
    public Object execProcedure(String procName, List args) throws WGProcedureException {
        throw new WGProcedureException("Procedures are not yet supported");
    }

    /*
     * (Kein Javadoc)
     *
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getServerName()
     */
    public String getServerName() throws WGBackendException {

        try {
            DatabaseMetaData metaData = getSession().connection().getMetaData();
            return metaData.getDatabaseProductName() + " " + metaData.getDatabaseProductVersion();
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error retrieving server name", e);           
        }
        catch (SQLException e) {
            throw new WGBackendException("Error retrieving server name", e);
        }
    }



    protected boolean isVisibleForUser(Content content) throws WGAPIException {

        if (_db.getSessionContext().isMasterSession()) {
            return true;
        }
       
        // Hierarchy check per base WGAPI
        if (_db.isPageReadersEnabled()) {
            WGStructEntry entry = _db.getStructEntryByKey(content.getStructentry().getKey());
            if (!entry.mayReadContent()) {
                return false;
            }
        }

        // Local check
        List readers = content.getReaders();

        // If list is empty, return immediately
        if (WGDatabase.anyoneAllowed(readers)) {
            return true;
        }

        // Test user names
        return isMemberOfUserList(readers);

    }

    /*
     * (Kein Javadoc)
     *
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getACL()
     */
    public WGACLCore getACL() {
        return _aclImpl;
    }
   
    public void createLogEntry(Session session, int logType, String docKey, String entityID) throws HibernateException, WGAPIException {
        LogEntry entry = new LogEntry(new Date(), logType, docKey.toString(), _db.getSessionContext().getUser());
        entry.setTarget_id(entityID);
        if (_db.getContentStoreVersion() >= WGDatabase.CSVERSION_WGA5) {
            entry.setOperation(_db.getSessionContext().getTask());
        }
        session.save(entry);
    }

    /*
     * (Kein Javadoc)
     *
     * @see
     * de.innovationgate.webgate.api.WGDatabaseEventListener#databaseUpdate(
     * de.innovationgate.webgate.api.WGDatabaseEvent)
     */
    public void refresh() {
        Session session = getSession();
        session.flush();
        session.clear();
    }

    /*
     * (Kein Javadoc)
     *
     * @see de.innovationgate.webgate.api.WGDatabaseEventListener#isTemporary()
     */
    public boolean isTemporary() {
        return false;
    }

    /*
     * (Kein Javadoc)
     *
     * @see de.innovationgate.webgate.api.WGDatabaseCore#getNativeObject()
     */
    public Object getNativeObject() {
        return getSession();
    }

    /*
     * (Kein Javadoc)
     *
     * @see
     * de.innovationgate.webgate.api.WGDatabaseCore#resultIsFalse(java.lang.
     * Object, de.innovationgate.webgate.api.WGDocument)
     */
    public boolean resultIsFalse(Object result, WGDocument doc) {
        return false;
    }

    /*
     * (Kein Javadoc)
     *
     * @see
     * de.innovationgate.webgate.api.WGDatabaseCore#resultIsTrue(java.lang.Object
     * , de.innovationgate.webgate.api.WGDocument)
     */
    public boolean resultIsTrue(Object result, WGDocument doc) {
        return false;
    }



    /**
     * @param props
     */
    private void putDefaultConPoolProps(Properties props) {
       
      if (hasFeature(WGDatabase.FEATURE_LOADBALANCE)) {
        WGUtils.setDefaultProperty(props, "hibernate.connection.provider_class", DBCPReplicationConnectionProvider.class.getName());
        }
        else {
        WGUtils.setDefaultProperty(props, "hibernate.connection.provider_class", DBCPConnectionProvider.class.getName());
      }
        WGUtils.setDefaultProperty(props, "hibernate.dbcp.maxActive", "100");
        WGUtils.setDefaultProperty(props, "hibernate.dbcp.whenExhaustedAction", "1");
        WGUtils.setDefaultProperty(props, "hibernate.dbcp.maxWait", "120000");
        WGUtils.setDefaultProperty(props, "hibernate.dbcp.maxIdle", "10");
        WGUtils.setDefaultProperty(props, "hibernate.dbcp.poolPreparedStatements", "true");
        WGUtils.setDefaultProperty(props, "hibernate.dbcp.maxOpenPreparedStatements", DEFAULT_MAXOPENPREPAREDSTATEMENTS);
       
        if (_db.getDbReference().indexOf(":") == -1) {
            props.put("hibernate.dbcp.dbkey", _db.getDbReference());
        }

    }

    /*
     * (Kein Javadoc)
     *
     * @see
     * de.innovationgate.webgate.api.WGDatabaseCore#getUpdatedDocumentsSince
     * (java.util.Date)
     */
    public List getUpdateLogs(Comparable lastModified) throws WGBackendException {

        try {
            Iterator logEntries;
            if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                Query logEntriesQ = getSession().createQuery("from de.innovationgate.webgate.api.jdbc.LogEntry as logentry where id > :cutoff order by id asc");
                logEntriesQ.setLong("cutoff", ((Long) lastModified).longValue());
                logEntries = logEntriesQ.iterate();
            }
            else {
                Date cutoff = (Date) lastModified;
                Query logEntriesQ = getSession().createQuery("from de.innovationgate.webgate.api.jdbc.LogEntry as logentry where logtime >= :cutoff order by logtime asc");
                logEntriesQ.setTimestamp("cutoff", new java.sql.Timestamp(cutoff.getTime()));
                logEntries = logEntriesQ.iterate();
            }
           
            List wgLogs = new ArrayList();
            LinkedMap wgLogsByTarget = new LinkedMap();
            Map conflictTargets = new HashMap();

            LogEntry entry;
           
            // First pass: Create update logs
            while (logEntries.hasNext()) {
                entry = (LogEntry) logEntries.next();
                WGUpdateLog newLog = null;
                WGUpdateLog oldLog = null;
                Date currentTime = null;
                if (entry.getTarget() != null && !entry.getTarget().equals("#UNKNOWN#")) {
                    newLog = new WGUpdateLog(entry.getType(), entry.getLogtime(), entry.getLoguser(), entry.getTarget());
                    wgLogs.add(newLog);
                   
                    List logsList = (List) wgLogsByTarget.get(entry.getTarget());
                    if (logsList == null) {
                        logsList = new ArrayList();
                        wgLogsByTarget.put(entry.getTarget(), logsList);
                    }
                    logsList.add(newLog);
                }
            }
           
            // Second pass for CS version < 5 to workaround some weaknesses of the CS3/4 history log
            if (_ddlVersion < WGDatabase.CSVERSION_WGA5) {
               
                // Determine conflicting log entries, where update and delete is done on the same time and the same document
                Iterator wgLogsByTargetIt = wgLogsByTarget.values().iterator();
                while (wgLogsByTargetIt.hasNext()) {
                    List logs = (List) wgLogsByTargetIt.next();
                    WGUtils.sortByProperty(logs, "date");
                    Iterator logsIt = logs.iterator();
                    Date lastTime = null;
                    List<WGUpdateLog> logsAtSameTime = new ArrayList();
                    while (logsIt.hasNext()) {
                        WGUpdateLog log = (WGUpdateLog) logsIt.next();
                        if (log.getDate().equals(lastTime)) {
                            logsAtSameTime.add(log);
                        }
                        else {
                            resolveLogConflicts(wgLogs, logsAtSameTime);               
                            logsAtSameTime.clear();
                        }
                        lastTime = log.getDate();
                    }
                }
               
                // Order logentries that have the same time in an order that assures dependency documents are created before their dependent documents
                Collections.sort(wgLogs, new DocumentDependencyComparator());
               
            }
           
           
            return wgLogs;
        }
        catch (HibernateException e) {
            throw new WGBackendException("Unable to retrieve updated documents", e);
        }

    }

    private void resolveLogConflicts(List wgLogs, List conflictLogs) {

        // Reverse the sort order so we have the maximum logtimes at the beginning
        Collections.reverse(conflictLogs);
       
        // Get the operations having the maximum logtime
        WGUpdateLog maxUpdateLog = null;
        WGUpdateLog maxDeletionLog = null;
        Iterator logsIt = conflictLogs.iterator();
        Date maxDate = null;
        while (logsIt.hasNext()) {
            WGUpdateLog log = (WGUpdateLog) logsIt.next();
           
            if (maxDate == null) {
                maxDate = log.getDate();
            }
            else if (!maxDate.equals(log.getDate())) {
                break;
            }
           
            if (log.getType() == WGUpdateLog.TYPE_UPDATE) {
                maxUpdateLog = log;
            }
            else if (log.getType() == WGUpdateLog.TYPE_DELETE) {
                maxDeletionLog = log;
            }
        }
       
        // Now lets see what we have - If there is only one type of log we have no problem
        if (maxDeletionLog != null && maxUpdateLog == null) {
        }
        else if (maxUpdateLog != null && maxDeletionLog == null) {
        }
        else if (maxUpdateLog != null && maxDeletionLog != null) {
            // So we have an update and a deletion at the same time.
            // We cannot determine by log which was before the other.
            // Therefor we look if the document exists.
            // If so we use the update log, else the deletion log.
            // The nonused log is therefor removed from the log list
            WGDocument doc = null;
            WGDocumentKey documentKey = new WGDocumentKey(maxUpdateLog.getDocumentKey());
            if (documentKey.isRealDocumentKey()) {
                try {
                    doc = _db.getDocumentByKey(documentKey);
                    if (doc != null && !doc.isDeleted()) {
                        WGFactory.getLogger().info("Resolving log conflict about document " + maxUpdateLog.getDocumentKey() + ": Relevant log type determined as update");
                        wgLogs.remove(maxDeletionLog);                
                    }
                    else {
                        WGFactory.getLogger().info("Resolving log conflict about document " + maxUpdateLog.getDocumentKey() + ": Relevant log type determined as deletion");
                        wgLogs.remove(maxUpdateLog);
                    }
                }
                catch (WGAPIException e) {
                    WGFactory.getLogger().error("Exception resolving log conflict for document " + maxUpdateLog.getDocumentKey(), e);
                }
            }
        }
       
    }

    protected WGDocumentImpl createDocumentImpl(MainEntity entity) {

        int type;
        if (entity instanceof Content) {
            type = WGDocument.TYPE_CONTENT;
        }
        else if (entity instanceof StructEntry) {
            type = WGDocument.TYPE_STRUCTENTRY;
        }
        else if (entity instanceof Area) {
            type = WGDocument.TYPE_AREA;
        }
        else if (entity instanceof ContentType) {
            type = WGDocument.TYPE_CONTENTTYPE;
        }
        else if (entity instanceof TMLModule) {
            type = WGDocument.TYPE_TML;
        }
        else if (entity instanceof CSSJSModule) {
            type = WGDocument.TYPE_CSSJS;
        }
        else if (entity instanceof Language) {
            type = WGDocument.TYPE_LANGUAGE;
        }
        else if (entity instanceof UserProfile) {
            type = WGDocument.TYPE_USERPROFILE;
        }
        else if (entity instanceof FileContainer) {
            type = WGDocument.TYPE_FILECONTAINER;
        }
        else {
            throw new IllegalArgumentException("The given object type is no known entity: " + entity.getClass().getName());
        }

        return new WGDocumentImpl(this, entity, type);
    }

    /*
     * (non-Javadoc)
     *
     * @seede.innovationgate.webgate.api.WGDatabaseCore#moveStructEntry(de.
     * innovationgate.webgate.api.WGStructEntry,
     *      de.innovationgate.webgate.api.WGDocument)
     */
    public boolean moveStructEntry(WGStructEntry entry, WGDocument newParent) {

        try {
            StructEntry structEntry = (StructEntry) entry.getNativeObject();

            // Remove from former parent object
            // Manual initializings are workaround for hibernate bug B00005D36
            StructEntry parentEntry = structEntry.getParententry();
            if (parentEntry != null) {
                Hibernate.initialize(parentEntry.getChildentries());
                parentEntry.getChildentries().remove(structEntry.getKey());
            }
            else {
                Area area = structEntry.getArea();
                Hibernate.initialize(area.getRootentries());
                area.getRootentries().remove(structEntry.getKey());
            }

            // Set to new parent object
            if (newParent instanceof WGArea) {
                Area area = (Area) newParent.getNativeObject();
                structEntry.setParententry(null);
                structEntry.setArea(area);
                area.getRootentries().put(structEntry.getKey(), structEntry);
            }
            else if (newParent instanceof WGStructEntry) {
                StructEntry parent = (StructEntry) newParent.getNativeObject();
                structEntry.setParententry(parent);
                structEntry.setArea(null);
                parent.getChildentries().put(structEntry.getKey(), structEntry);

            }
            else {
                return false;
            }
            createLogEntry(getSession(), WGUpdateLog.TYPE_STRUCTMOVE, entry.getDocumentKey(), structEntry.getId());
            entry.save();
            return true;
        }
        catch (WGAPIException e) {
            WGFactory.getLogger().error("Error moving struct entry", e);
            e.printStackTrace();
            return false;
        }

    }

    public int getContentCount(WGStructEntry structEntry) throws WGBackendException {

        try {
            Query query;
            if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
                query = getSession().createQuery("select id from Content as content where content.structentry.key=:key");
            }
            else {
                query = getSession().createQuery("select cuid from Content as content where content.structentry.key=:key");
            }
           
            query.setParameter("key", String.valueOf(structEntry.getStructKey()));
            return query.list().size();
           
            }
        catch (HibernateException e) {
            throw new WGBackendException("Error determining content presence for  " + structEntry.getDocumentKey(), e);
        }

    }

    /*
     * (non-Javadoc)
     *
     * @seede.innovationgate.webgate.api.WGDatabaseCore#setCurrentSession(de.
     * innovationgate.webgate.api.WGSessionContext)
     */
    public void setCurrentSession(WGSessionContext context) {
    }
   
    public String convertFileNameForAttaching(String name) {
        return name.toLowerCase().replace('�', '/');
    }

    public void authenticationDataChanged() {
       
        _db.getUserCache().clear();
       
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * de.innovationgate.webgate.api.WGDatabaseCore#getAllowedCredentialClasses
     * ()
     */
    public Class[] getAllowedCredentialClasses() {
        return null;
    }
   
    public List queryUserProfileNames(String type, String query, Map params) throws WGAPIException {

        if (type == null) {
            type = "hql";
        }
       
        try {
            String fullQuery;
            if (query != null) {
                if (type.equals("hql")) {
                fullQuery = "select profile.name from UserProfile profile where (" + query + ") order by profile.name asc";
            }
                else if (type.equals("fullhql")) {
                    fullQuery = query;
                }
                else {
                    throw new WGQueryException(query, "Unknown query type '" + type + "'");
                }
            }
            else {
                fullQuery = "select profile.name from UserProfile profile order by profile.name asc";
            }
           
            Query hqlQuery = getSession().createQuery(fullQuery);
            if (params.containsKey(WGDatabase.QUERYOPTION_MAXRESULTS)) {
                Number maxResults = (Number) params.get(WGDatabase.QUERYOPTION_MAXRESULTS);
                hqlQuery.setMaxResults(maxResults.intValue());
            }
           
            return hqlQuery.list();
           
        }
        catch (QueryException e) {
           throw new WGQueryException(query, e.getMessage(), e);
        }
        catch (HibernateException e) {
           throw new WGBackendException("Error executing profile query", e);
        }
       
    }
   
    protected void commitHibernateTransaction() throws WGBackendException {
        if (getTransactionMode() != WGSessionContext.TRANSACTION_MODE_MANUAL) {
            Transaction trans = getSession().getTransaction();
            if (trans != null) {
                trans.commit();
            }
           
            // hibernate might release the underlying jdbc connection after commit
            // and get a new one
            // this connection will be readonly by default - therefore we should
            // check if we have to
            // make it read/write
            if (isUpdateInProgress()) {         
              try {
                if (getSession().connection().isReadOnly()) {
                  getSession().connection().setReadOnly(false);
            }
                }
                catch (HibernateException e) {
            throw new WGBackendException("unable to establish a read/write connection.", e);
                }
                catch (SQLException e) {
            throw new WGBackendException("unable to establish a read/write connection.", e);
          }
            }
           
            getSession().beginTransaction();
        } else {
            // perform at least a flush in this mode so JDBC driver will execute changes in current JDBC transaction
            getSession().flush();
        }
    }
   
    protected void rollbackHibernateTransaction() throws WGBackendException {
       
        if (getTransactionMode() != WGSessionContext.TRANSACTION_MODE_MANUAL) {
       
            Transaction trans = getSession().getTransaction();
            if (trans != null && trans.isActive()) {
                trans.rollback();
            }
           
            // hibernate might release the underlying jdbc connection after commit
            // and get a new one
            // this connection will be readonly by default - therefore we should
            // check if we have to
            // make it read/write
            if (isUpdateInProgress()) {         
              try {
                if (getSession().connection().isReadOnly()) {
                  getSession().connection().setReadOnly(false);
                }
                }
                catch (HibernateException e) {
            throw new WGBackendException("unable to establish a read/write connection.", e);
                }
                catch (SQLException e) {
            throw new WGBackendException("unable to establish a read/write connection.", e);
          }
            }
           
            getSession().beginTransaction();
       
        }
       
    }
   
    /*
     *  (non-Javadoc)
     *
     * @see
     * de.innovationgate.webgate.api.WGDatabaseCore#getDeletions(java.util.Set)
     */
    public Set getDeletions(Set contentKeys) throws WGAPIException {
        // unsupported for this implementation
        return Collections.EMPTY_SET;
    }
   
    public List getAllContentKeys(boolean includeArchived) throws WGBackendException {
       
        try {
            String hql = "select new de.innovationgate.webgate.api.WGContentKey(content.structentry.key, content.language.name, content.version) from Content as content";
           
            if (!includeArchived) {
                hql += " where not content.status='" + WGContent.STATUS_ARCHIVE + "'";
            }
           
            Query query = getSession().createQuery(hql);
            return new ArrayList(query.list());
        }
        catch (HibernateException e) {
            throw new WGBackendException("Exception retrieving all content keys", e);           
        }
       
       
       
    }

    public WGDatabase getDb() {
        return _db;
    }
   
    private SessionStatus getSessionStatus() {
       
        SessionStatus ss = (SessionStatus) _sessionStatus.get();
        if (ss == null) {
            ss = new SessionStatus();
            _sessionStatus.set(ss);
        }
        return ss;
       
    }
   
    public boolean isHqlLazyByDefault() {
        return _hqlLazyByDefault;
    }

    public void setHqlLazyByDefault(boolean hqlLazyByDefault) {
        _hqlLazyByDefault = hqlLazyByDefault;
    }

    public boolean useOptimizedFileHandling() throws WGAPIException {
      return _db.getContentStoreVersion() >= WGDatabase.CSVERSION_WGA4_1;
    }

    protected void updateContentRelations(Content content) {
       
        if (_ddlVersion < WGDatabase.CSVERSION_WGA5) {
            return;
        }
       
        Query query = getSession().createQuery(HQLQUERY_UPDATE_RELATIONS);
        query.setParameter("target", content);
        query.setParameter("structentry", content.getStructentry().getKey());
        query.setParameter("language", content.getLanguage().getName());
        query.executeUpdate();
    }



    public WGDocumentCore getStructEntryByName(String strName) throws WGAPIException {

        Query query = getSession().createQuery(HQLQUERY_GET_STRUCT_BY_NAME);
        query.setParameter("name", strName);
        Iterator results = query.iterate();
        if (results.hasNext()) {
            StructEntry entry = (StructEntry) results.next();
            return createDocumentImpl(entry);
        }
        else {
            return null;
        }
   
    }



    public Date getRevisionDate(Comparable lastChanged) throws WGAPIException, WGWrongRevisionException {
       
        if (_ddlVersion >= WGDatabase.CSVERSION_WGA5) {
           
            if (!(lastChanged instanceof Long)) {
                throw new WGWrongRevisionException(Long.class);
            }
           
            LogEntry entry = (LogEntry) getSession().get(LogEntry.class, (Long) lastChanged);
            if (entry != null) {
                return entry.getLogtime();
            }
            else {
                return null;
            }
        }
        else {
            try {
                return (Date) lastChanged;
            }
            catch (ClassCastException e) {
                throw new WGWrongRevisionException(Date.class);
            }
        }
       
    }



    public double getContenStoreVersion() throws WGAPIException {
        return _ddlVersion;
    }



    public void writeExtensionData(String name, Object value) throws WGAPIException {
       
        name = name.toLowerCase().trim();
       
        // Convert numbers to doubles
        if (value instanceof Number && !(value instanceof Double)) {
            value = new Double(((Number) value).doubleValue());
        }
       
        try {
            ExtensionData md = retrieveExtensionData(name);
            if (md == null) {
                md = new ExtensionData();
                md.setName(name);
                getSession().save(md);
            }
           
            WGDocumentImpl.writeItemValue(this, md, value);
           
            createLogEntry(getSession(), WGUpdateLog.TYPE_UPDATE, WGDocument.TYPENAME_DBMETADATA + "/" + name, md.getId());
            commitHibernateTransaction();
        }
        catch (HibernateException e) {
            throw new WGBackendException("Error setting database metadata.", e);  
        }
       
       
       
    }

    public void removeExtensionData(String name) throws WGAPIException {
        name = name.toLowerCase().trim();
        ExtensionData md = retrieveExtensionData(name);
        if (md != null) {
            getSession().delete(md);
            commitHibernateTransaction();
        }
       
    }
   
    public List<String> getExtensionDataNames() throws WGAPIException {
        return getSession().createQuery("select name from ExtensionData where entity = null").list();
    }


    public List<WGRelationData> getIncomingRelations(Object structKey, String language, Boolean includeUnreleased) throws WGAPIException {
        if (_ddlVersion < WGDatabase.CSVERSION_WGA5) {
            return Collections.emptyList();
        }
       
        Criteria crit = getSession().createCriteria(ContentRelation.class);
        crit.add(Restrictions.eq("targetstructentry", structKey));
        crit.add(Restrictions.eq("targetlanguage", language));
       
        if (includeUnreleased) {
            crit.createCriteria("parentcontent").add(Restrictions.in("status", new Object[] {WGContent.STATUS_DRAFT, WGContent.STATUS_REVIEW, WGContent.STATUS_RELEASE}));
        }
        else {
            crit.createCriteria("parentcontent").add(Restrictions.eq("status", WGContent.STATUS_RELEASE));
        }
       
       
        List<WGRelationData> incoming = new ArrayList();
       
        for (ContentRelation rel : (List<ContentRelation>) crit.list()) {
            WGRelationData relData = createWGRelationData(rel);
            incoming.add(relData);
        }
       
        return incoming;
       
    }



    protected WGRelationData createWGRelationData(ContentRelation rel) {
        Content content = rel.getParentcontent();
        WGContentKey cKey = new WGContentKey(content.getStructentry().getKey(), content.getLanguage().getName(), content.getVersion().intValue());
        WGRelationData relData = new WGRelationData(cKey, rel.getName(), rel.getTargetstructentry(), rel.getTargetlanguage(), rel.getType(), rel.getGroup());
        return relData;
    }



    /**
     * Returns if query paging for optimized file handling is enabled, see
     * {@link #COPTION_OPTIMIZED_FILE_HANDLING_DISABLEQUERYPAGING}
     */
    public boolean isOptimizedFileHandlingDisableQueryPaging() {
        Object disableQueryPaging = _db.getCreationOptions().get(COPTION_OPTIMIZED_FILE_HANDLING_DISABLEQUERYPAGING);
        if (disableQueryPaging != null) {
            return Boolean.valueOf((String) disableQueryPaging).booleanValue();
        }
        else {
            return true;
        }
    }



    public boolean isContentTypeUsed(WGContentType ctDoc) throws WGAPIException {
       
        // Get the entity
        WGDocumentImpl docCore = (WGDocumentImpl) ctDoc.getCore();
        ContentType ct = (ContentType) docCore.getEntity();
       
        // Do a criteria query
        Criteria crit = getSession().createCriteria(StructEntry.class);
        crit.add(Restrictions.eq("contenttype", ct));
        crit.setMaxResults(1);
        List docs = crit.list();
       
        return docs.size() > 0;
       
    }



    public boolean isLanguageUsed(WGLanguage langDoc) throws WGAPIException {

        // Get the entity
        WGDocumentImpl docCore = (WGDocumentImpl) langDoc.getCore();
        Language lang = (Language) docCore.getEntity();
       
        // Do a criteria query
        Criteria crit = getSession().createCriteria(Content.class);
        crit.add(Restrictions.eq("language", lang));
        crit.setMaxResults(1);
        List docs = crit.list();
       
        return docs.size() > 0;
       
    }



    public Iterator<String> getAllUserProfileNames() throws WGAPIException {

        try {
            String fullQuery = "select profile.name from UserProfile profile order by profile.name asc";
           
           
            Query hqlQuery = getSession().createQuery(fullQuery);
            return hqlQuery.iterate();
           
        }
        catch (QueryException e) {
           throw new WGQueryException("Querying all user profile names", e.getMessage(), e);
        }
        catch (HibernateException e) {
           throw new WGBackendException("Error executing profile query", e);
        }
       
    }   

   
}
TOP

Related Classes of de.innovationgate.webgate.api.jdbc.WGDatabaseImpl$SessionStatus

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.