/* =============================================================================== * * Part of the InfoGlue Content Management Platform (www.infoglue.org) * * =============================================================================== * * Copyright (C) * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2, as published by the * Free Software Foundation. See the file LICENSE.html for more information. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY, including 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 * this program; if not, write to the Free Software Foundation, Inc. / 59 Temple * Place, Suite 330 / Boston, MA 02111-1307 / USA. * * =============================================================================== */ package org.infoglue.cms.controllers.kernel.impl.simple; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.log4j.Category; import org.apache.log4j.Logger; import org.exolab.castor.jdo.Database; import org.exolab.castor.jdo.LockNotGrantedException; import org.exolab.castor.jdo.OQLQuery; import org.exolab.castor.jdo.ObjectNotFoundException; import org.exolab.castor.jdo.PersistenceException; import org.exolab.castor.jdo.QueryResults; import org.exolab.castor.jdo.TransactionAbortedException; import org.infoglue.cms.entities.kernel.BaseEntityVO; import org.infoglue.cms.entities.kernel.IBaseEntity; import org.infoglue.cms.entities.kernel.ValidatableEntityVO; import org.infoglue.cms.entities.management.InterceptionPointVO; import org.infoglue.cms.entities.management.InterceptorVO; import org.infoglue.cms.entities.management.TableCount; import org.infoglue.cms.exception.Bug; import org.infoglue.cms.exception.ConfigurationError; import org.infoglue.cms.exception.ConstraintException; import org.infoglue.cms.exception.SystemException; import org.infoglue.cms.security.InfoGluePrincipal; import org.infoglue.cms.security.interceptors.InfoGlueInterceptor; import org.infoglue.cms.services.InterceptionService; import org.infoglue.cms.util.CmsPropertyHandler; import org.infoglue.cms.util.ConstraintExceptionBuffer; import org.infoglue.cms.util.StringManager; import org.infoglue.cms.util.StringManagerFactory; import org.infoglue.cms.util.validators.Constants; import org.infoglue.cms.util.validators.ConstraintRule; import org.infoglue.cms.util.validators.EmailValidator; import org.infoglue.cms.util.validators.StringValidator; import org.infoglue.deliver.util.CacheController; import org.infoglue.deliver.util.RequestAnalyser; import com.opensymphony.module.propertyset.PropertySet; import com.opensymphony.module.propertyset.PropertySetManager; /** * BaseController.java * Created on 2002-aug-28 * @author Stefan Sik, ss@frovi.com * @author Mattias Bogeblad, mattias.bogeblad@sprawlsolutions.se * * Baseclass for ControllerClasses. * Various methods to load, create and delete entities * * TODO: * Now that all entities implements BaseEntity clear all reflection and simplify * arguments... * * -matbog 2002-09-15: Added and modified new read-only methods for fetching a VO-object. * These method must be called instead of the old ones when just fetching a entity * or all entities from a table. */ public abstract class BaseController { private final static Logger logger = Logger.getLogger(BaseController.class.getName()); /** * Gets a logger for the action class. */ /* protected Logger logger { return Logger.getLogger(this.getClass().getName()); } */ /** * This method is called by the controllers to let interceptors listen to events. * * @param hashMap * @param InterceptionPointName * @param infogluePrincipal * @throws ConstraintException * @throws SystemException * @throws Bug * @throws Exception */ protected void intercept(Map hashMap, String InterceptionPointName, InfoGluePrincipal infogluePrincipal) throws ConstraintException, SystemException, Bug, Exception { intercept(hashMap, InterceptionPointName, infogluePrincipal, true, false); } protected void intercept(Map hashMap, String InterceptionPointName, InfoGluePrincipal infogluePrincipal, boolean allowCreatorAccess, boolean ignoreMissingInterceptionPoint) throws ConstraintException, SystemException, Bug, Exception { InterceptionPointVO interceptionPointVO = InterceptionPointController.getController().getInterceptionPointVOWithName(InterceptionPointName); if(interceptionPointVO == null) { if(ignoreMissingInterceptionPoint) return; else throw new SystemException("The InterceptionPoint " + InterceptionPointName + " was not found. The system will not work unless you restore it."); } List interceptors = InterceptorController.getController().getInterceptorsVOList(interceptionPointVO.getInterceptionPointId()); Iterator interceptorsIterator = interceptors.iterator(); while(interceptorsIterator.hasNext()) { InterceptorVO interceptorVO = (InterceptorVO)interceptorsIterator.next(); logger.info("Adding interceptorVO:" + interceptorVO.getName()); try { InfoGlueInterceptor infoGlueInterceptor = (InfoGlueInterceptor)Class.forName(interceptorVO.getClassName()).newInstance(); infoGlueInterceptor.setInterceptorVO(interceptorVO); infoGlueInterceptor.intercept(infogluePrincipal, interceptionPointVO, hashMap, allowCreatorAccess); } catch(ClassNotFoundException e) { logger.warn("The interceptor " + interceptorVO.getClassName() + "was not found: " + e.getMessage(), e); } } } Map<String,InfoGlueInterceptor> cachedInterceptors = new HashMap<String,InfoGlueInterceptor>(); protected void intercept(Map hashMap, String InterceptionPointName, InfoGluePrincipal infogluePrincipal, boolean allowCreatorAccess) throws ConstraintException, SystemException, Bug, Exception { InterceptionPointVO interceptionPointVO = InterceptionPointController.getController().getInterceptionPointVOWithName(InterceptionPointName); if(interceptionPointVO == null) throw new SystemException("The InterceptionPoint " + InterceptionPointName + " was not found. The system will not work unless you restore it."); List interceptors = InterceptionPointController.getController().getInterceptorsVOList(interceptionPointVO.getInterceptionPointId()); Iterator interceptorsIterator = interceptors.iterator(); while(interceptorsIterator.hasNext()) { InterceptorVO interceptorVO = (InterceptorVO)interceptorsIterator.next(); logger.info("Adding interceptorVO:" + interceptorVO.getName()); try { InfoGlueInterceptor infoGlueInterceptor = cachedInterceptors.get(interceptorVO.getClassName()); if(infoGlueInterceptor == null) { infoGlueInterceptor = (InfoGlueInterceptor)Class.forName(interceptorVO.getClassName()).newInstance(); infoGlueInterceptor.setInterceptorVO(interceptorVO); cachedInterceptors.put(interceptorVO.getClassName(), infoGlueInterceptor); } infoGlueInterceptor.intercept(infogluePrincipal, interceptionPointVO, hashMap, allowCreatorAccess); } catch(ClassNotFoundException e) { logger.warn("The interceptor " + interceptorVO.getClassName() + "was not found: " + e.getMessage(), e); } } } /** * This method is called by the controllers to let interceptors listen to events. * * @param hashMap * @param InterceptionPointName * @param infogluePrincipal * @throws ConstraintException * @throws SystemException * @throws Bug * @throws Exception */ protected void intercept(Map hashMap, String InterceptionPointName, InfoGluePrincipal infogluePrincipal, Database db) throws ConstraintException, SystemException, Bug, Exception { InterceptionPointVO interceptionPointVO = InterceptionPointController.getController().getInterceptionPointVOWithName(InterceptionPointName, db); if(interceptionPointVO == null) throw new SystemException("The InterceptionPoint " + InterceptionPointName + " was not found. The system will not work unless you restore it."); List interceptors = InterceptionPointController.getController().getInterceptorsVOList(interceptionPointVO.getInterceptionPointId(), db); Iterator interceptorsIterator = interceptors.iterator(); while(interceptorsIterator.hasNext()) { InterceptorVO interceptorVO = (InterceptorVO)interceptorsIterator.next(); logger.info("Adding interceptorVO:" + interceptorVO.getName()); try { InfoGlueInterceptor infoGlueInterceptor = cachedInterceptors.get(interceptorVO.getClassName()); if(infoGlueInterceptor == null) { infoGlueInterceptor = (InfoGlueInterceptor)Class.forName(interceptorVO.getClassName()).newInstance(); infoGlueInterceptor.setInterceptorVO(interceptorVO); cachedInterceptors.put(interceptorVO.getClassName(), infoGlueInterceptor); } //InfoGlueInterceptor infoGlueInterceptor = (InfoGlueInterceptor)Class.forName(interceptorVO.getClassName()).newInstance(); infoGlueInterceptor.intercept(infogluePrincipal, interceptionPointVO, hashMap, db); } catch(ClassNotFoundException e) { logger.warn("The interceptor " + interceptorVO.getClassName() + "was not found: " + e.getMessage(), e); } } } protected void intercept(Map hashMap, String InterceptionPointName, InfoGluePrincipal infogluePrincipal, boolean allowCreatorAccess, Database db) throws ConstraintException, SystemException, Bug, Exception { InterceptionPointVO interceptionPointVO = InterceptionPointController.getController().getInterceptionPointVOWithName(InterceptionPointName, db); if(interceptionPointVO == null) throw new SystemException("The InterceptionPoint " + InterceptionPointName + " was not found. The system will not work unless you restore it."); List interceptors = InterceptionPointController.getController().getInterceptorsVOList(interceptionPointVO.getInterceptionPointId(), db); Iterator interceptorsIterator = interceptors.iterator(); while(interceptorsIterator.hasNext()) { InterceptorVO interceptorVO = (InterceptorVO)interceptorsIterator.next(); logger.info("Adding interceptorVO:" + interceptorVO.getName()); try { InfoGlueInterceptor infoGlueInterceptor = cachedInterceptors.get(interceptorVO.getClassName()); if(infoGlueInterceptor == null) { infoGlueInterceptor = (InfoGlueInterceptor)Class.forName(interceptorVO.getClassName()).newInstance(); infoGlueInterceptor.setInterceptorVO(interceptorVO); cachedInterceptors.put(interceptorVO.getClassName(), infoGlueInterceptor); } //InfoGlueInterceptor infoGlueInterceptor = (InfoGlueInterceptor)Class.forName(interceptorVO.getClassName()).newInstance(); infoGlueInterceptor.intercept(infogluePrincipal, interceptionPointVO, hashMap, allowCreatorAccess, db); } catch(ClassNotFoundException e) { logger.warn("The interceptor " + interceptorVO.getClassName() + "was not found: " + e.getMessage(), e); } } } private static Integer getEntityId(Object entity) throws Bug { Integer entityId = new Integer(-1); try { entityId = ((IBaseEntity) entity).getId(); } catch (Exception e) { e.printStackTrace(); throw new Bug("Unable to retrieve object id"); } /* try { entityId = (Integer) entity.getClass().getDeclaredMethod("getId", new Class[0]).invoke(entity, new Object[0]); } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } catch (NoSuchMethodException e) { } */ return entityId; } /*************************************************** * Create, Delete & Update operations ***************************************************/ // Create entity // The validation belongs here protected static Object createEntity(Object entity) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); try { db.create(entity); commitTransaction(db); //CmsSystem.log(entity,"Created object", CmsSystem.DBG_NORMAL); //CmsSystem.transactionLogEntry(entity.getClass().getName(), CmsSystem.TRANS_CREATE, getEntityId(entity), entity.toString()); } catch(ObjectNotFoundException e) { logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction: " + e.getMessage()); logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); //CmsSystem.log(entity,"Failed to create object", CmsSystem.DBG_LOW); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return entity; } // Create entity inside an existing transaction protected static Object createEntity(Object entity, Database db) throws SystemException, Bug, Exception { db.create(entity); return entity; } // Delete entity public static void deleteEntity(Class entClass, Integer id) throws Bug, SystemException { Database db = CastorDatabaseService.getDatabase(); Object entity = null; beginTransaction(db); try { entity = getObjectWithId(entClass, id, db); // Delete the entity db.remove(entity); commitTransaction(db); //CmsSystem.log(entity,"Deleted object", CmsSystem.DBG_NORMAL); //CmsSystem.transactionLogEntry(entClass.getName(), CmsSystem.TRANS_DELETE, id, entity.toString()); } catch(ObjectNotFoundException e) { logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction: " + e.getMessage()); logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } } // Delete entity public static void deleteEntity(Class entClass, String id) throws Bug, SystemException { Database db = CastorDatabaseService.getDatabase(); Object entity = null; beginTransaction(db); try { entity = getObjectWithId(entClass, id, db); // Delete the entity db.remove(entity); commitTransaction(db); //CmsSystem.log(entity,"Deleted object", CmsSystem.DBG_NORMAL); //CmsSystem.transactionLogEntry(entClass.getName(), CmsSystem.TRANS_DELETE, id, entity.toString()); } catch(ObjectNotFoundException e) { logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e.getMessage()); logger.warn("An error occurred so we should not complete the transaction:" + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } } // Delete entity public static void deleteEntity(Class entClass, String id, Database db) throws Bug, SystemException, Exception { Object entity = getObjectWithId(entClass, id, db); // Delete the entity db.remove(entity); } // Delete entity public static void deleteEntity(Class entClass, Integer id, Database db) throws Bug, SystemException { Object entity = null; try { entity = getObjectWithId(entClass, id, db); // Delete the entity db.remove(entity); } catch(ObjectNotFoundException e) { logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e.getMessage()); logger.warn("An error occurred so we should not complete the transaction:" + e.getMessage(), e); throw new SystemException(e.getMessage()); } } public static BaseEntityVO updateEntity(Class arg, BaseEntityVO vo) throws Bug, SystemException { Database db = CastorDatabaseService.getDatabase(); IBaseEntity entity = null; beginTransaction(db); try { entity = (IBaseEntity) getObjectWithId(arg, vo.getId(), db); entity.setVO(vo); commitTransaction(db); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction: " + e.getMessage()); logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return entity.getVO(); } public static BaseEntityVO updateEntity(Class arg, BaseEntityVO vo, Database db) throws Bug, SystemException { IBaseEntity entity = null; entity = (IBaseEntity) getObjectWithId(arg, vo.getId(), db); entity.setVO(vo); return entity.getVO(); } /* Update entity and a collection with other entities * Experimental, use with caution * */ public static BaseEntityVO updateEntity(Class entClass, BaseEntityVO vo, String collectionMethod, Class manyClass, String[] manyIds) throws ConstraintException, SystemException { Database db = CastorDatabaseService.getDatabase(); ConstraintExceptionBuffer ceb = new ConstraintExceptionBuffer(); IBaseEntity entity = null; beginTransaction(db); try { //add validation here if needed List manyList = new ArrayList(); if(manyIds != null) { for (int i=0; i < manyIds.length; i++) { IBaseEntity manyEntity = (IBaseEntity) getObjectWithId(manyClass, new Integer(manyIds[i]), db); logger.info("!!Using experimental code: BaseController::update. getting " + manyEntity.toString()); manyList.add(manyEntity); } } entity = (IBaseEntity) getObjectWithId(entClass, vo.getId(), db); entity.setVO(vo); // Now reflect to set the collection Object[] arg = {manyList}; Class[] parm = {Collection.class}; entity.getClass().getDeclaredMethod(collectionMethod, parm).invoke(entity, arg); // DONE //If any of the validations or setMethods reported an error, we throw them up now before create. ceb.throwIfNotEmpty(); commitTransaction(db); //CmsSystem.transactionLogEntry(entity.getClass().getName(), CmsSystem.TRANS_UPDATE, vo.getId(), entity.toString()); } catch(ConstraintException ce) { logger.warn("An error occurred so we should not complete the transaction:" + ce.getMessage(), ce); rollbackTransaction(db); throw ce; } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e.getMessage()); logger.warn("An error occurred so we should not complete the transaction:" + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return entity.getVO(); } /* * Update entity and a collection with other entities * Experimental, use with caution */ public static IBaseEntity updateEntity(Class entClass, BaseEntityVO vo, String collectionMethod, Class manyClass, String[] manyIds, Database db) throws ConstraintException, SystemException, Exception { IBaseEntity entity = null; List manyList = new ArrayList(); if(manyIds != null) { for (int i=0; i < manyIds.length; i++) { IBaseEntity manyEntity = (IBaseEntity) getObjectWithId(manyClass, new Integer(manyIds[i]), db); logger.info("!!Using experimental code: BaseController::update. getting " + manyEntity.toString()); manyList.add(manyEntity); } } entity = (IBaseEntity) getObjectWithId(entClass, vo.getId(), db); entity.setVO(vo); // Now reflect to set the collection Object[] arg = {manyList}; Class[] parm = {Collection.class}; entity.getClass().getDeclaredMethod(collectionMethod, parm).invoke(entity, arg); return entity; } /* protected static Object getObjectWithId(Class arg, Integer id) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); Object ret = null; try { beginTransaction(db); ret = getObjectWithId(arg, id, db); commitTransaction(db); } catch (Exception e) { rollbackTransaction(db); throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } return ret; } */ /** * This method fetches one object / entity within a transaction. **/ protected static Object getObjectWithId(Class arg, Integer id, Database db) throws SystemException, Bug { Object object = null; try { if(logger.isInfoEnabled()) logger.info("Loading " + arg + " in read/write mode."); object = db.load(arg, id); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } if(object == null) { throw new Bug("The object with id [" + id + "] was not found. This should never happen."); } return object; } /** * This method fetches one object / entity within a transaction. **/ protected static Object getObjectWithIdAsReadOnly(Class arg, Integer id, Database db) throws SystemException, Bug { Object object = null; try { RequestAnalyser.getRequestAnalyser().incApproximateNumberOfDatabaseQueries(); object = db.load(arg, id, Database.READONLY); } catch(Exception e) { logger.warn("Error getting object. Message: " + e.getMessage() + ". No retrying again."); throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } finally { RequestAnalyser.getRequestAnalyser().decApproximateNumberOfDatabaseQueries(); } if(object == null) { throw new Bug("The object with id [" + id + "] was not found. This should never happen."); } return object; } /** * This method fetches one object / entity within a transaction. **/ protected static Object getObjectWithId(Class arg, String id, Database db) throws SystemException, Bug { Object object = null; try { logger.info("Loading " + arg + " in read/write mode."); object = db.load(arg, id); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } if(object == null) { throw new Bug("The object with id [" + id + "] was not found. This should never happen."); } return object; } /** * This method converts a List of entities to a list of value-objects. */ public static List toVOList(Collection baseEntities) throws SystemException, Bug { List resultVOList = new ArrayList(); if(baseEntities != null) { Object o = null; try { Iterator iterator = baseEntities.iterator(); while (iterator.hasNext()) { o = (Object)iterator.next(); // Om metoden getValueObject saknas, kastas ett undantag. resultVOList.add(o.getClass().getDeclaredMethod("getValueObject", new Class[0]).invoke(o, new Object[0])); } } catch(NoSuchMethodException e) { throw new Bug("The object in list was of the wrong type: " + o.getClass().getName() + ". This should never happen.", e); } catch(Exception e) { throw new SystemException("An error occurred when we tried to convert the collection to a valueList. Reason:" + e.getMessage(), e); } } return resultVOList; } /** * This method converts a List of entities to a list of value-objects. */ public static List toModifiableVOList(Collection baseEntities) throws SystemException, Bug { List resultVOList = new ArrayList(); if(baseEntities != null) { Object o = null; try { Iterator iterator = baseEntities.iterator(); while (iterator.hasNext()) { o = (Object)iterator.next(); // Om metoden getValueObject saknas, kastas ett undantag. resultVOList.add(o.getClass().getDeclaredMethod("getValueObject", new Class[0]).invoke(o, new Object[0])); } } catch(NoSuchMethodException e) { throw new Bug("The object in list was of the wrong type: " + o.getClass().getName() + ". This should never happen.", e); } catch(Exception e) { throw new SystemException("An error occurred when we tried to convert the collection to a valueList. Reason:" + e.getMessage(), e); } } return resultVOList; } /*************************************************** * Read only operations ***************************************************/ /** * This method is used to fetch a ValueObject from the database. */ public static Object getVOWithId(Class arg, Integer id) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); Object ret = null; try { beginTransaction(db); ret = getVOWithId(arg, id, db); commitTransaction(db); } catch (Exception e) { rollbackTransaction(db); throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } return ret; } /** * This method is used to fetch a ValueObject from the database. */ public static Object getVOWithIdLockless(Class arg, String idName, Integer id) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); Object ret = null; try { beginTransaction(db); ret = getVOWithIdLockless(arg, idName, id, db); commitTransaction(db); } catch (Exception e) { rollbackTransaction(db); throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } return ret; } /** * This method is used to fetch a ValueObject from the database. */ public static Object getVOWithIdLockless(Class arg, String idName, Integer id, Database db) throws SystemException, Bug { Object ret = null; try { OQLQuery oql = db.getOQLQuery("SELECT u FROM " + arg.getName() + " u WHERE u." + idName +" = $1 ORDER BY u." + idName +" desc"); QueryResults results = oql.execute(Database.READONLY); if (results.hasMore()) { IBaseEntity o = (IBaseEntity)results.next(); ret = o.getVO(); } results.close(); oql.close(); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } return ret; } /** * This method fetches one object in read only mode and returns it's value object. */ public static BaseEntityVO getVOWithId(Class arg, Integer id, Database db) throws SystemException, Bug { IBaseEntity vo = null; try { vo = (IBaseEntity)db.load(arg, id, Database.READONLY); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } if(vo == null) { throw new Bug("The object with id [" + id + "] was not found. This should never happen."); } return vo.getVO(); } /** * This method is used to fetch a ValueObject from the database. */ public static Object getVOWithId(Class arg, String id) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); Object ret = null; try { beginTransaction(db); ret = getVOWithId(arg, id, db); commitTransaction(db); } catch (Exception e) { rollbackTransaction(db); throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } return ret; } /** * This method fetches one object in read only mode and returns it's value object. */ public static BaseEntityVO getVOWithId(Class arg, String id, Database db) throws SystemException, Bug { IBaseEntity vo = null; try { vo = (IBaseEntity)db.load(arg, id, Database.READONLY); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } if(vo == null) { throw new Bug("The object with id [" + id + "] was not found. This should never happen."); } return vo.getVO(); } /** * This method fetches all object in read only mode and returns a list of value objects. */ /* public static List getAllVOObjects(Class arg) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); List ret = null; try { beginTransaction(db); ret = getAllVOObjects(arg, db); commitTransaction(db); } catch(Exception e) { rollbackTransaction(db); throw new SystemException("An error occurred when we tried to fetch " + arg.getName() + " Reason:" + e.getMessage(), e); } return ret; } */ /** * This method fetches all object in read only mode and returns a list of value objects. */ public static List getAllVOObjects(Class arg, String orderByAttribute, String direction) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); List ret = null; try { beginTransaction(db); ret = getAllVOObjects(arg, orderByAttribute, direction, db); commitTransaction(db); } catch(Exception e) { rollbackTransaction(db); throw new SystemException("An error occurred when we tried to fetch " + arg.getName() + " Reason:" + e.getMessage(), e); } return ret; } /** * This method fetches all object in read only mode and returns a list of value objects. */ public static List getAllVOObjects(Class arg, String orderByField, String direction, Database db) throws SystemException, Bug { ArrayList resultList = new ArrayList(); OQLQuery oql; try { if(logger.isInfoEnabled()) logger.info("BaseHelper::GetAllObjects for " + arg.getName()); oql = db.getOQLQuery( "SELECT u FROM " + arg.getName() + " u ORDER BY u." + orderByField + " " + direction); QueryResults results = oql.execute(Database.READONLY); while (results.hasMore()) { Object o = results.next(); // Om metoden getValueObject saknas, kastas ett undantag. resultList.add(o.getClass().getDeclaredMethod("getValueObject", new Class[0]).invoke(o, new Object[0])); } } catch(NoSuchMethodException e) { throw new Bug("The object [" + arg.getName() + "] is of the wrong type. This should never happen.", e); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch " + arg.getName() + " Reason:" + e.getMessage(), e); } return resultList; } /** * This method fetches all object in read only mode and returns a list of value objects sorted on primary Key. */ public List getAllVOObjects(Class arg, String primaryKey) throws SystemException, Bug { Database db = CastorDatabaseService.getDatabase(); List ret = null; try { beginTransaction(db); ret = getAllVOObjects(arg, primaryKey, db); commitTransaction(db); } catch(Exception e) { rollbackTransaction(db); throw new SystemException("An error occurred when we tried to fetch " + arg.getName() + " Reason:" + e.getMessage(), e); } return ret; } /** * This method fetches all object in read only mode and returns a list of value objects. */ public List getAllVOObjects(Class arg, String primaryKey, Database db) throws SystemException, Bug { ArrayList resultList = new ArrayList(); OQLQuery oql; try { oql = db.getOQLQuery( "SELECT u FROM " + arg.getName() + " u ORDER BY u." + primaryKey); QueryResults results = oql.execute(Database.READONLY); while (results.hasMore()) { IBaseEntity baseEntity = (IBaseEntity)results.next(); resultList.add(baseEntity.getVO()); } } catch(ClassCastException e) { throw new Bug("The object [" + arg.getName() + "] is of the wrong type. This should never happen.", e); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch " + arg.getName() + " Reason:" + e.getMessage(), e); } return resultList; } /** * This method fetches all object in read only mode and returns a list of objects. */ public List getAllObjects(Class arg, String primaryKey, Database db) throws SystemException, Bug { ArrayList resultList = new ArrayList(); OQLQuery oql; try { oql = db.getOQLQuery( "SELECT u FROM " + arg.getName() + " u ORDER BY u." + primaryKey); QueryResults results = oql.execute(Database.READONLY); while (results.hasMore()) { IBaseEntity baseEntity = (IBaseEntity)results.next(); resultList.add(baseEntity); } } catch(ClassCastException e) { throw new Bug("The object [" + arg.getName() + "] is of the wrong type. This should never happen.", e); } catch(Exception e) { throw new SystemException("An error occurred when we tried to fetch " + arg.getName() + " Reason:" + e.getMessage(), e); } return resultList; } //--------------------------------------------------------------------- // Dynamic Query specific operations //--------------------------------------------------------------------- /** * Executes a Query with no parameters * * @param query An OQL Query * @return A VO list of the query results * @throws SystemException If an error occurs */ protected static List executeQuery(String query) throws SystemException { return executeQuery(query, Collections.EMPTY_LIST); } /** * Executes a Query with no parameters * * @param query An OQL Query * @return A VO list of the query results * @throws SystemException If an error occurs */ protected static List executeQuery(String query, Database db) throws SystemException { return executeQuery(query, Collections.EMPTY_LIST, db); } /** * Executes a Query with no parameters * * @param query An OQL Query * @return A VO list of the query results * @throws SystemException If an error occurs */ protected static List executeQueryReadOnly(String query, Database db) throws SystemException { return executeQueryReadOnly(query, Collections.EMPTY_LIST, db); } /** * Executes a Query, also binds the provided parameters * * @param query An OQL Query * @param params A List of paramters * @return A VO list of the query results * @throws SystemException If an error occurs */ protected static List executeQuery(String query, List params) throws SystemException { Database db = beginTransaction(); try { List results = new ArrayList(); results = Collections.list(createQuery(db, query, params).execute(Database.READONLY)); commitTransaction(db); return toVOList(results); } catch (Exception e) { logger.error("Error executing " + query, e); rollbackTransaction(db); throw new SystemException(e.getMessage(), e); } } /** * Executes a Query, also binds the provided parameters * * @param query An OQL Query * @param params A List of paramters * @param db A transaction object * @return A VO list of the query results * @throws SystemException If an error occurs */ protected static List executeQuery(String query, List params, Database db) throws SystemException { try { List resultList = new ArrayList(); OQLQuery oql = createQuery(db, query, params); QueryResults results = oql.execute(); resultList = Collections.list(results); results.close(); oql.close(); return resultList; } catch (Exception e) { logger.error("Error executing " + query, e); throw new SystemException(e.getMessage(), e); } } /** * Executes a Query, also binds the provided parameters * * @param query An OQL Query * @param params A List of paramters * @param db A transaction object * @return A VO list of the query results * @throws SystemException If an error occurs */ protected static List executeQueryReadOnly(String query, List params, Database db) throws SystemException { try { List resultList = new ArrayList(); OQLQuery oql = createQuery(db, query, params); QueryResults results = oql.execute(Database.READONLY); resultList = Collections.list(results); results.close(); oql.close(); return resultList; } catch (Exception e) { logger.error("Error executing " + query, e); throw new SystemException(e.getMessage(), e); } } /** * Creates an OQLQuery for the provided Database and binds the parameters to it. * * @param db The Database to create the OQLQuery on * @param query The String OQL query * @param params A List of Objects to bind to the query sequentially * @return An OQLQuery instance that can be executer * @throws PersistenceException */ protected static OQLQuery createQuery(Database db, String query, List params) throws PersistenceException { OQLQuery oql = db.getOQLQuery(query); if (params != null) for (Iterator i = params.iterator(); i.hasNext();) oql.bind(i.next()); return oql; } /*************************************************** * Validation and integrity check of entities - cre 2002-09-18 / SS * *************************************************/ public static ConstraintExceptionBuffer validateEntity(ValidatableEntityVO vo) { // This method loops through the rulelist and creates // validators according to the settings in each rule. // The old validators are used to do the actual validation // but I have changed them to use less constructor // parameter passing in favour for setters. //CmsSystem.log("ValidationController::validate()", CmsSystem.DBG_HIGH); ConstraintExceptionBuffer ceb = new ConstraintExceptionBuffer(); // Prepare the object for validation vo.PrepareValidation(); // Loop through rules and create validators Iterator iterator = vo.getConstraintRules().iterator(); while (iterator.hasNext()) { ConstraintRule cr = (ConstraintRule) iterator.next(); Integer intId = vo.getId(); logger.info("Validating object id: " + intId); // an ugly switch for now. switch (cr.getConstraintType()) { case Constants.EMAIL: { if (cr.getValue() != null) { // Create validator EmailValidator v = new EmailValidator(cr.getFieldName()); // Set properties v.setObjectClass(vo.getConstraintRuleList().getEntityClass()); v.setRange(cr.getValidRange()); v.setIsRequired(cr.required); v.setMustBeUnique(cr.unique); v.setExcludeId(intId); // Do the limbo v.validate((String) cr.getValue(), ceb); // <todo> // Note: the actual value validated should be extracted // from the vo using the fieldname with reflection. // </todo> } break; } case Constants.STRING: { if (cr.getValue() != null) { StringValidator v = new StringValidator(cr.getFieldName()); v.setObjectClass(vo.getConstraintRuleList().getEntityClass()); v.setRange(cr.getValidRange()); v.setIsRequired(cr.required); v.setMustBeUnique(cr.unique); v.setExcludeId(intId); v.validate((String) cr.getValue(), ceb); } break; } case Constants.FLOAT: { break; } case Constants.INTEGER: { break; } case Constants.PROPERNOUN: { break; } } // switch } // while return ceb; } /*************************************************** * Transaction specifik operations ***************************************************/ /** * Creates a new database and starts a transaction * @return A reference to a castor database with a new transaction * @throws SystemException if a database error occurs. */ protected static Database beginTransaction() throws SystemException { Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); return db; } /** * Begins a transaction on the named database */ protected static void beginTransaction(Database db) throws SystemException { try { //logger.info("Opening a new Transaction in cms..."); db.begin(); } catch(Exception e) { throw new SystemException("An error occurred when we tried to begin an transaction. Reason:" + e.getMessage(), e); } } /** * Ends a transaction on the named database */ protected static void commitTransaction(Database db) throws SystemException { try { //logger.info("Closing a transaction in cms..."); db.commit(); db.close(); //RegistryController.notifyTransactionCommitted(); } catch(TransactionAbortedException tae) { if(tae.getCause() instanceof LockNotGrantedException) throw new SystemException("The resource you tried to modify have just been updated by another user. Please try again later. System message: " + tae.getCause().getMessage()); else throw new SystemException("An error occurred when we tried to commit an transaction. Reason:" + tae.getMessage(), tae); } catch(LockNotGrantedException lnge) { throw new SystemException("The resource you tried to modify have just been updated by another user. Please try again later. System message: " + lnge.getMessage()); } catch(Exception e) { throw new SystemException("An error occurred when we tried to commit an transaction. Reason:" + e.getMessage(), e); } } /** * Ends a transaction on the named database */ protected static void commitRegistryAwareTransaction(Database db) throws SystemException { try { //logger.info("Closing a transaction in cms..."); db.commit(); db.close(); RegistryController.notifyTransactionCommitted(); } catch(TransactionAbortedException tae) { if(tae.getCause() instanceof LockNotGrantedException) throw new SystemException("The resource you tried to modify have just been updated by another user. Please try again later. System message: " + tae.getCause().getMessage()); else throw new SystemException("An error occurred when we tried to commit an transaction. Reason:" + tae.getMessage(), tae); } catch(LockNotGrantedException lnge) { throw new SystemException("The resource you tried to modify have just been updated by another user. Please try again later. System message: " + lnge.getMessage()); } catch(Exception e) { throw new SystemException("An error occurred when we tried to commit an transaction. Reason:" + e.getMessage(), e); } } /** * Rollbacks a transaction on the named database */ protected static void rollbackTransaction(Database db) throws SystemException { try { //logger.info("rollbackTransaction a transaction in cms..."); if (db != null && db.isActive()) { db.rollback(); db.close(); } } catch(Exception e) { logger.warn("An error occurred when we tried to rollback an transaction. Reason:" + e.getMessage()); } } /** * Rollbacks a transaction on the named database */ protected static void closeDatabase(Database db) throws SystemException { try { if (db != null) { db.close(); } } catch(Exception e) { logger.warn("An error occurred when we tried to rollback an transaction. Reason:" + e.getMessage()); } } public String getLocalizedString(Locale locale, String key) { StringManager stringManager = StringManagerFactory.getPresentationStringManager("org.infoglue.cms.applications", locale); return stringManager.getString(key); } public String getLocalizedString(Locale locale, String key, Object arg1) { String message = null; StringManager stringManager = StringManagerFactory.getPresentationStringManager("org.infoglue.cms.applications", locale); try { message = stringManager.getString(key, arg1); } catch (ConfigurationError e) { StringManager stringManagerBackup = StringManagerFactory.getPresentationStringManager("org.infoglue.cms.entities", locale); message = stringManagerBackup.getString(key, arg1); } return message; } public String getLocalizedString(Locale locale, String key, Object arg1, Object arg2) { StringManager stringManager = StringManagerFactory.getPresentationStringManager("org.infoglue.cms.applications", locale); return stringManager.getString(key, arg1, arg2); } public String getLocalizedString(Locale locale, String key, Object arg1, Object arg2, Object arg3) { StringManager stringManager = StringManagerFactory.getPresentationStringManager("org.infoglue.cms.applications", locale); return stringManager.getString(key, arg1, arg2, arg3); } public Locale getUserPrefferedLocale(String userName) { Locale locale = Locale.ENGLISH; try { List toolLocales = CmsPropertyHandler.getToolLocales(); if(toolLocales != null && toolLocales.size() > 0) locale = (Locale)toolLocales.get(0); } catch (Exception e) { logger.warn("Problem getting default tool locale: " + e.getMessage(), e); } if(userName != null) { try { Map args = new HashMap(); args.put("globalKey", "infoglue"); PropertySet ps = PropertySetManager.getInstance("jdbc", args); String languageCode = ps.getString("principal_" + userName + "_languageCode"); locale = getLocaleWithCode(languageCode); } catch (Exception e) { logger.warn("Error getting users prefferred language: " + e.getMessage(), e); } } return locale; } /** * This method returns language with the languageCode sent in. */ public Locale getLocaleWithCode(String languageCode) { String key = "" + languageCode; logger.info("key:" + key); Locale locale = (Locale)CacheController.getCachedObject("localeCache", key); if(locale != null) { logger.info("There was an cached locale:" + locale); } else { locale = Locale.getDefault(); if (languageCode != null) { try { locale = new Locale(languageCode); } catch (Exception e) { logger.error("An error occurred in getLocaleWithCode: getting locale with languageCode:" + languageCode + "," + e, e); } } CacheController.cacheObject("localeCache", key, locale); } return locale; } public static TableCount getTableCount(String tableName) throws Exception { TableCount tableCount = null; Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); try { OQLQuery oql = db.getOQLQuery("CALL SQL SELECT count(*) FROM " + tableName + " AS org.infoglue.cms.entities.management.TableCount"); QueryResults results = oql.execute(); if(results.hasMore()) { tableCount = (TableCount)results.next(); } results.close(); oql.close(); commitTransaction(db); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction: " + e.getMessage()); logger.warn("An error occurred so we should not complete the transaction: " + e.getMessage(), e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return tableCount; } public static TableCount getTableCount(String tableName, String columnName) throws Exception { TableCount tableCount = null; Database db = CastorDatabaseService.getDatabase(); beginTransaction(db); try { OQLQuery oql = db.getOQLQuery("CALL SQL SELECT count(" + columnName + ") FROM " + tableName + " AS org.infoglue.cms.entities.management.TableCount"); QueryResults results = oql.execute(); if(results.hasMore()) { tableCount = (TableCount)results.next(); } results.close(); oql.close(); commitTransaction(db); } catch(Exception e) { logger.error("An error occurred so we should not complete the transaction:" + e); logger.warn("An error occurred so we should not complete the transaction:" + e, e); rollbackTransaction(db); throw new SystemException(e.getMessage()); } return tableCount; } public static Category getCastorCategory() { Enumeration enumeration = Logger.getCurrentCategories(); while(enumeration.hasMoreElements()) { Category category = (Category)enumeration.nextElement(); if(category.getName().equalsIgnoreCase("org.exolab.castor")) return category; } return null; } public static Category getCastorJDOCategory() { Enumeration enumeration = Logger.getCurrentCategories(); while(enumeration.hasMoreElements()) { Category category = (Category)enumeration.nextElement(); if(category.getName().equalsIgnoreCase("org.exolab.castor.jdo")) return category; } return null; } public abstract BaseEntityVO getNewVO(); }