/* =============================================================================== * * 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.deliver.controllers.kernel.impl.simple; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; import org.exolab.castor.jdo.Database; import org.exolab.castor.jdo.OQLQuery; import org.exolab.castor.jdo.PersistenceException; import org.exolab.castor.jdo.QueryResults; import org.infoglue.cms.entities.kernel.BaseEntityVO; import org.infoglue.cms.entities.kernel.IBaseEntity; import org.infoglue.cms.exception.Bug; import org.infoglue.cms.exception.SystemException; import org.infoglue.deliver.util.RequestAnalyser; /** * BaseDeliveryController.java * * Baseclass for Castor Controller Classes. * Various methods to handle transactions and so on * */ public abstract class BaseDeliveryController { private final static Logger logger = Logger.getLogger(BaseDeliveryController.class.getName()); /** * This method fetches one object / entity within a transaction. **/ protected Object getObjectWithId(Class arg, Integer id, Database db) throws SystemException, Bug { return getObjectWithId(arg, id, db, true); } /** * This method fetches one object / entity within a transaction. **/ protected Object getObjectWithId(Class arg, Integer id, Database db, boolean retry) throws SystemException, Bug { Object object = null; try { RequestAnalyser.getRequestAnalyser().incApproximateNumberOfDatabaseQueries(); object = db.load(arg, id, Database.READONLY); } catch(Exception e) { try { if(retry) { logger.info("Error getting object. Message: " + e.getMessage() + ". Retrying..."); object = getObjectWithId(arg, id, db, false); } else { logger.info("Error getting object. Message: " + e.getMessage() + ". Not retrying..."); throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } } catch(Exception e2) { 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 in read only mode and returns it's value object. */ protected BaseEntityVO getVOWithId(Class arg, Integer id, Database db) throws SystemException, Bug { return getVOWithId(arg, id, db, true); } /** * This method fetches one object in read only mode and returns it's value object. */ protected BaseEntityVO getVOWithId(Class arg, Integer id, Database db, boolean retry) throws SystemException, Bug { IBaseEntity vo = null; try { RequestAnalyser.getRequestAnalyser().incApproximateNumberOfDatabaseQueries(); vo = (IBaseEntity)db.load(arg, id, Database.READONLY); } catch(Exception e) { try { if(retry) { logger.info("Error getting object. Message: " + e.getMessage() + ". Retrying..."); vo = (IBaseEntity)getVOWithId(arg, id, db, false); } else { logger.info("Error getting object. Message: " + e.getMessage() + ". Not retrying..."); throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } } catch(Exception e2) { throw new SystemException("An error occurred when we tried to fetch the object " + arg.getName() + ". Reason:" + e.getMessage(), e); } } finally { RequestAnalyser.getRequestAnalyser().decApproximateNumberOfDatabaseQueries(); } 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 List getAllVOObjects(Class arg, Database db) throws SystemException, Bug { ArrayList resultList = new ArrayList(); try { logger.info("BaseHelper::GetAllObjects for " + arg.getName()); OQLQuery oql = db.getOQLQuery( "SELECT u FROM " + arg.getName() + " u" ); 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])); } results.close(); oql.close(); } 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 Collections.unmodifiableList(resultList); } /** * This method fetches all object in read only mode and returns a list of value objects. */ public List getAllVOObjects(Class arg, String orderByField, String direction, Database db) throws SystemException, Bug { ArrayList resultList = new ArrayList(); try { logger.info("BaseHelper::GetAllObjects for " + arg.getName()); OQLQuery 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])); } results.close(); oql.close(); } 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 Collections.unmodifiableList(resultList); } //--------------------------------------------------------------------- // Dynamic Query specific operations //--------------------------------------------------------------------- /** * Executes a Query with no parameters * * @param query An OQL Query * @return A list of the query results as Impls * @throws SystemException If an error occurs */ protected static List executeQuery(Database db, String query) throws SystemException, Exception { return executeQuery(db, query, Collections.EMPTY_LIST); } /** * Executes a Query, also binds the provided parameters * * @param query An OQL Query * @param params A List of paramters * @return A list of the query results as Castor Impl * @throws SystemException If an error occurs */ protected static List executeQuery(Database db, String query, List params) throws Exception { 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; } /** * 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; } /** * This method converts a List of entities to a list of value-objects. */ protected static List toVOList(Collection entities) throws SystemException, Bug { List resultVOList = new ArrayList(); if(entities == null) return Collections.EMPTY_LIST; Iterator iterator = entities.iterator(); while (iterator.hasNext()) { Object o = (Object)iterator.next(); try { 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; } /** * Begins a transaction on the named database */ public static void beginTransaction(Database db) throws SystemException { try { db.begin(); logger.info("Opening a new Transaction..."); } catch(Exception e) { e.printStackTrace(); throw new SystemException("An error occurred when we tried to begin an transaction. Reason:" + e.getMessage(), e); } } /** * Rollbacks a transaction on the named database */ public static void closeTransaction(Database db) throws SystemException { logger.info("closeTransaction a transaction and closing it..."); //rollbackTransaction(db); commitTransaction(db); } /** * Ends a transaction on the named database */ public static void commitTransaction(Database db) throws SystemException { try { logger.info("Committing a transaction and closing it..."); db.commit(); db.close(); } catch(Exception e) { e.printStackTrace(); throw new SystemException("An error occurred when we tried to commit an transaction. Reason:" + e.getMessage(), e); } } /** * Rollbacks a transaction on the named database */ public static void rollbackTransaction(Database db) throws SystemException { logger.info("Rollback a transaction..."); try { if (db.isActive()) { db.rollback(); db.close(); } } catch(Exception e) { logger.info("An error occurred when we tried to rollback an transaction. Reason:" + e.getMessage()); //throw new SystemException("An error occurred when we tried to rollback an transaction. Reason:" + e.getMessage(), e); } } /** * Close the database */ public static void closeDatabase(Database db) throws SystemException { try { logger.info("Closing database..."); db.close(); } catch(Exception e) { e.printStackTrace(); throw new SystemException("An error occurred when we tried to close a database. Reason:" + e.getMessage(), e); } } }