/*******************************************************************************
* 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);
}
}
}