/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Release: 1.0
*
*@author fmillevi@yahoo.com
*
*/
package org.objectweb.speedo.j2eedo.web;
import java.io.IOException;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.objectweb.speedo.j2eedo.common.PMHolder;
import org.objectweb.speedo.j2eedo.ejb.StoreServicesLocal;
import org.objectweb.speedo.j2eedo.ejb.StoreServicesLocalHome;
import org.objectweb.speedo.j2eedo.ejb.StoreServicesRemote;
import org.objectweb.speedo.j2eedo.ejb.StoreServicesRemoteHome;
import org.objectweb.util.monolog.Monolog;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
abstract class MainServlet extends HttpServlet {
// define the class name parameter
/**
* The constant <code>WITHOUT_TRANSACTION_PARAMETER</code> is used
* to retrive the HTTP request parameter <b>"withoutTrans"</b> used by the servlet
* to know if a transaction must be start at the servlet level.
*/
public final static String WITH_TRANSACTION_PARAMETER = "withTrans";
/**
* The constant <code>TYPE_CONTAINER_PARAMETER</code> is used
* to retrive the HTTP request parameter <b>"container"</b> used by the servlet
* to know if the action must be done through a Session Bean Container.
*/
public final static String TYPE_CONTAINER_PARAMETER = "container";
public final static String LOCAL_SESSION_BEAN_PARAMETER = "localsession";
/**
* The constant <code>WITH_GETPM_PARAMETER</code> is used
* to retrive the HTTP request parameter <b>"withGetPM"</b> used by the servlet
* to know if the persistence manager must be get by the servelt.
*/
public final static String WITH_GETPM_PARAMETER = "withGetPM";
private final static String PMF_JNDI_NAME = "speedo";
protected static Logger logger = null;
protected PersistenceManagerFactory persistenceManagerFactory = null;
protected StoreServicesLocalHome lstoreServicesLH;
protected StoreServicesRemoteHome lstoreServicesRH;
/**
* This servlet executes current request:<ul>
* <li>Gets the Persistence manager when required (false by default),</li>
* <li>Starts a local transaction when requested (false by default),</li>
* <li>Calls the dedicated action directly or through a Session Bean Container
* (direct call by default),</li>
* <li>Close the PM when initialized at the servlet level.</li>
* </ul>
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
public void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
boolean withTransaction = getParameterValue(
req, MainServlet.WITH_TRANSACTION_PARAMETER, false);
boolean withGetPM = getParameterValue(
req, MainServlet.WITH_GETPM_PARAMETER, withTransaction);
boolean useSessionBean = getParameterValue(
req, MainServlet.TYPE_CONTAINER_PARAMETER, false);
boolean localSessionBean = getParameterValue(
req, MainServlet.LOCAL_SESSION_BEAN_PARAMETER, false);
if (logger.isLoggable(BasicLevel.DEBUG)) {
logger.log(BasicLevel.DEBUG, "Invoke Servlet: "
+" \n\t-withGetPM=" + withGetPM
+ "\n\t-withTransaction=" + withTransaction
+ "\n\t-useSessionBean=" + useSessionBean
+ "\n\t-localSessionBean=" + localSessionBean
);
}
// check sequence of parameters
if (useSessionBean && withTransaction) {
withTransaction = false;
logger.log(BasicLevel.WARN,
"Use local transaction is forbiden when using an ejb session");
}
if (withTransaction && !withGetPM) {
// to begin and close an transaction the pm is required
withGetPM = true;
logger.log(BasicLevel.WARN,
"Use of the persistence manager is required when using transaction");
}
PMHolder pmh = new PMHolder(persistenceManagerFactory);
PersistenceManager pm = null;
javax.jdo.Transaction utx = null;
try {
if ((!useSessionBean || localSessionBean) && withGetPM) {
logger.log(BasicLevel.DEBUG, "GetPM");
pm = pmh.getPersistenceManager();
}
if ((!useSessionBean || localSessionBean) && withTransaction) {
utx = pm.currentTransaction();
utx.begin();
logger.log(BasicLevel.DEBUG, "Begin local JDOTransactionItf");
}
if (useSessionBean) {
//The action will be done by the Session bean
if (localSessionBean) {
//Invoke the session bean through the local interface
logger.log(BasicLevel.DEBUG, "Use local session bean");
StoreServicesLocal lstoreServices = null;
try {
lstoreServices = lstoreServicesLH.create();
} catch (CreateException e) {
logger.log(BasicLevel.ERROR, "Error during the creation of Local Session", e);
throw new ServletException(e);
}
try {
executeSessionBean(req, resp, lstoreServices, pmh);
} finally {
//release the session bean from the pool
lstoreServices.remove();
}
} else {
//Invoke the session bean through the Remote interface
logger.log(BasicLevel.DEBUG, "Use remote session bean");
StoreServicesRemote lstoreServices = null;
try {
lstoreServices = lstoreServicesRH.create();
} catch (CreateException e) {
logger.log(BasicLevel.ERROR, "Error during the creation of Local Session", e);
throw new ServletException(e);
}
try {
executeSessionBean(req, resp, lstoreServices);
} finally {
//release the session bean from the pool
lstoreServices.remove();
}
}
} else {
logger.log(BasicLevel.DEBUG, "Use direct call");
executeDirectCall(req, resp, pmh);
}
} catch (Exception e) {
if (utx != null && utx.isActive()) {
logger.log(BasicLevel.DEBUG, "Rollback the local JDOTransactionItf due to an error: ", e);
utx.rollback();
} else {
logger.log(BasicLevel.ERROR, "An error has occured: ", e);
}
throw new ServletException(e);
} finally {
if (utx != null && utx.isActive()) {
logger.log(BasicLevel.DEBUG, "Commit the local JDOTransactionItf");
utx.commit();
}
if (pm != null && !pm.isClosed()) {
logger.log(BasicLevel.DEBUG, "Close local PM");
pmh.closePersistenceManager();
}
}
}
public void init() throws ServletException {
super.init();
// get the logger
logger = Monolog.initialize().getLogger(getClass().getName());
//get the PersistenceManagerFactory
persistenceManagerFactory = (PersistenceManagerFactory)
getObjectFromContext(null, PMF_JNDI_NAME);
try {
getStoreServicesRemoteHome();
} catch (ServletException e) {
logger.log(BasicLevel.WARN, "No StoreServicesRemoteHome found: " + e.getMessage());
}
try {
getStoreServicesLocalHome();
} catch (ServletException e) {
logger.log(BasicLevel.WARN, "No StoreServicesLocalHome found: " + e.getMessage());
}
}
/**
* get the StoreServicesLocalHome.
*/
private StoreServicesLocalHome getStoreServicesLocalHome() throws ServletException {
if (lstoreServicesLH == null) {
lstoreServicesLH = (StoreServicesLocalHome)
getObjectFromContext(null, "java:comp/env/ejb/StoreServicesHomeLocal");
}
return lstoreServicesLH;
}
/**
* get the StoreServicesRemoteHome.
*/
private StoreServicesRemoteHome getStoreServicesRemoteHome() throws ServletException {
if (lstoreServicesRH == null) {
lstoreServicesRH = (StoreServicesRemoteHome)
getObjectFromContext(null, "ejb/storeService");
}
return lstoreServicesRH;
}
/**
* Get an object from JNDI
* @param ictx is the InitialContext to use. If this parameter is null
* a new context is created and closed
* @param name is the JNDI name of the searched object
* @return the object (never null)
* @throws ServletException if the object cannot be found.
*/
private static Object getObjectFromContext(InitialContext ictx, String name) throws ServletException {
boolean hasToCloseContext = false;
if (ictx == null) {
try {
ictx = new InitialContext();
hasToCloseContext = true;
} catch (NamingException e) {
logger.log(BasicLevel.ERROR,
"Impossible to get the InitialContext: ", e);
throw new ServletException(
"Impossible to get the InitialContext: " + e.getMessage());
}
}
try {
Object o = ictx.lookup(name);
if (o == null) {
throw new ServletException("'" + name + "' has not been found from JNDI");
}
return o;
} catch (ServletException e) {
throw e;
} catch (NameNotFoundException e) {
logger.log(BasicLevel.WARN, "Impossible to find " + name +": " + e.getMessage());
return null;
} catch (Exception e) {
logger.log(BasicLevel.ERROR, "Impossible to find " + name +": ", e);
return null;
} finally {
if (hasToCloseContext && ictx != null) {
try {
ictx.close();
} catch (NamingException ne) {
}
}
}
}
/**
* Get the value of a prameter from a HttpServletRequest instance
* @param req is the HttpServletRequest
* @param paramName is the name of the parameter
* @param defaultValue is the default value to return if the parameter
* is not defined in the HttpServletRequest
*/
private static boolean getParameterValue(HttpServletRequest req,
String paramName,
boolean defaultValue) {
try {
String val = req.getParameter(paramName);
return val != null && Boolean.valueOf(val).booleanValue();
} catch (Exception e) {
return defaultValue;
}
}
/**
* Empty threatment call for a ejb session
*
* @param lstoreServices
* @param persistenceManagerHolder
* @param out
* @throws JDOException
* @throws RemoteException
* @throws Exception
* @throws IOException
*/
protected abstract void executeSessionBean(
HttpServletRequest req,
HttpServletResponse resp,
StoreServicesRemote storeServices)
throws JDOException, RemoteException, Exception, IOException;
protected abstract void executeSessionBean(
HttpServletRequest req,
HttpServletResponse resp,
StoreServicesLocal storeServices,
PMHolder persistenceManagerHolder)
throws JDOException, RemoteException, Exception, IOException;
/**
* Empty threatment call for a jdo direct call
*
* @param persistenceManagerHolder
* @param out
* @throws JDOException
* @throws Exception
* @throws IOException
*/
protected abstract void executeDirectCall(
HttpServletRequest req,
HttpServletResponse resp,
PMHolder persistenceManagerHolder)
throws JDOException, Exception, IOException ;
}