001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * Release: 1.0
021: *
022: *@author fmillevi@yahoo.com
023: *
024: */package org.objectweb.speedo.j2eedo.web;
025:
026: import java.io.IOException;
027: import java.rmi.RemoteException;
028:
029: import javax.ejb.CreateException;
030: import javax.jdo.JDOException;
031: import javax.jdo.PersistenceManager;
032: import javax.jdo.PersistenceManagerFactory;
033: import javax.naming.InitialContext;
034: import javax.naming.NameNotFoundException;
035: import javax.naming.NamingException;
036:
037: import javax.servlet.ServletException;
038: import javax.servlet.http.HttpServlet;
039: import javax.servlet.http.HttpServletRequest;
040: import javax.servlet.http.HttpServletResponse;
041:
042: import org.objectweb.speedo.j2eedo.common.PMHolder;
043: import org.objectweb.speedo.j2eedo.ejb.StoreServicesLocal;
044: import org.objectweb.speedo.j2eedo.ejb.StoreServicesLocalHome;
045: import org.objectweb.speedo.j2eedo.ejb.StoreServicesRemote;
046: import org.objectweb.speedo.j2eedo.ejb.StoreServicesRemoteHome;
047: import org.objectweb.util.monolog.Monolog;
048: import org.objectweb.util.monolog.api.BasicLevel;
049: import org.objectweb.util.monolog.api.Logger;
050:
051: abstract class MainServlet extends HttpServlet {
052: // define the class name parameter
053: /**
054: * The constant <code>WITHOUT_TRANSACTION_PARAMETER</code> is used
055: * to retrive the HTTP request parameter <b>"withoutTrans"</b> used by the servlet
056: * to know if a transaction must be start at the servlet level.
057: */
058: public final static String WITH_TRANSACTION_PARAMETER = "withTrans";
059: /**
060: * The constant <code>TYPE_CONTAINER_PARAMETER</code> is used
061: * to retrive the HTTP request parameter <b>"container"</b> used by the servlet
062: * to know if the action must be done through a Session Bean Container.
063: */
064: public final static String TYPE_CONTAINER_PARAMETER = "container";
065:
066: public final static String LOCAL_SESSION_BEAN_PARAMETER = "localsession";
067:
068: /**
069: * The constant <code>WITH_GETPM_PARAMETER</code> is used
070: * to retrive the HTTP request parameter <b>"withGetPM"</b> used by the servlet
071: * to know if the persistence manager must be get by the servelt.
072: */
073: public final static String WITH_GETPM_PARAMETER = "withGetPM";
074:
075: private final static String PMF_JNDI_NAME = "speedo";
076:
077: protected static Logger logger = null;
078:
079: protected PersistenceManagerFactory persistenceManagerFactory = null;
080:
081: protected StoreServicesLocalHome lstoreServicesLH;
082: protected StoreServicesRemoteHome lstoreServicesRH;
083:
084: /**
085: * This servlet executes current request:<ul>
086: * <li>Gets the Persistence manager when required (false by default),</li>
087: * <li>Starts a local transaction when requested (false by default),</li>
088: * <li>Calls the dedicated action directly or through a Session Bean Container
089: * (direct call by default),</li>
090: * <li>Close the PM when initialized at the servlet level.</li>
091: * </ul>
092: * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
093: * javax.servlet.http.HttpServletResponse)
094: */
095: public void service(HttpServletRequest req, HttpServletResponse resp)
096: throws ServletException, IOException {
097: boolean withTransaction = getParameterValue(req,
098: MainServlet.WITH_TRANSACTION_PARAMETER, false);
099: boolean withGetPM = getParameterValue(req,
100: MainServlet.WITH_GETPM_PARAMETER, withTransaction);
101: boolean useSessionBean = getParameterValue(req,
102: MainServlet.TYPE_CONTAINER_PARAMETER, false);
103: boolean localSessionBean = getParameterValue(req,
104: MainServlet.LOCAL_SESSION_BEAN_PARAMETER, false);
105: if (logger.isLoggable(BasicLevel.DEBUG)) {
106: logger.log(BasicLevel.DEBUG, "Invoke Servlet: "
107: + " \n\t-withGetPM=" + withGetPM
108: + "\n\t-withTransaction=" + withTransaction
109: + "\n\t-useSessionBean=" + useSessionBean
110: + "\n\t-localSessionBean=" + localSessionBean);
111: }
112: // check sequence of parameters
113: if (useSessionBean && withTransaction) {
114: withTransaction = false;
115: logger
116: .log(BasicLevel.WARN,
117: "Use local transaction is forbiden when using an ejb session");
118: }
119: if (withTransaction && !withGetPM) {
120: // to begin and close an transaction the pm is required
121: withGetPM = true;
122: logger
123: .log(BasicLevel.WARN,
124: "Use of the persistence manager is required when using transaction");
125: }
126: PMHolder pmh = new PMHolder(persistenceManagerFactory);
127: PersistenceManager pm = null;
128: javax.jdo.Transaction utx = null;
129: try {
130: if ((!useSessionBean || localSessionBean) && withGetPM) {
131: logger.log(BasicLevel.DEBUG, "GetPM");
132: pm = pmh.getPersistenceManager();
133: }
134: if ((!useSessionBean || localSessionBean)
135: && withTransaction) {
136: utx = pm.currentTransaction();
137: utx.begin();
138: logger.log(BasicLevel.DEBUG,
139: "Begin local JDOTransactionItf");
140: }
141: if (useSessionBean) {
142: //The action will be done by the Session bean
143: if (localSessionBean) {
144: //Invoke the session bean through the local interface
145: logger.log(BasicLevel.DEBUG,
146: "Use local session bean");
147: StoreServicesLocal lstoreServices = null;
148: try {
149: lstoreServices = lstoreServicesLH.create();
150: } catch (CreateException e) {
151: logger
152: .log(
153: BasicLevel.ERROR,
154: "Error during the creation of Local Session",
155: e);
156: throw new ServletException(e);
157: }
158: try {
159: executeSessionBean(req, resp, lstoreServices,
160: pmh);
161: } finally {
162: //release the session bean from the pool
163: lstoreServices.remove();
164: }
165: } else {
166: //Invoke the session bean through the Remote interface
167: logger.log(BasicLevel.DEBUG,
168: "Use remote session bean");
169: StoreServicesRemote lstoreServices = null;
170: try {
171: lstoreServices = lstoreServicesRH.create();
172: } catch (CreateException e) {
173: logger
174: .log(
175: BasicLevel.ERROR,
176: "Error during the creation of Local Session",
177: e);
178: throw new ServletException(e);
179: }
180: try {
181: executeSessionBean(req, resp, lstoreServices);
182: } finally {
183: //release the session bean from the pool
184: lstoreServices.remove();
185: }
186: }
187: } else {
188: logger.log(BasicLevel.DEBUG, "Use direct call");
189: executeDirectCall(req, resp, pmh);
190: }
191: } catch (Exception e) {
192: if (utx != null && utx.isActive()) {
193: logger
194: .log(
195: BasicLevel.DEBUG,
196: "Rollback the local JDOTransactionItf due to an error: ",
197: e);
198: utx.rollback();
199: } else {
200: logger.log(BasicLevel.ERROR, "An error has occured: ",
201: e);
202: }
203: throw new ServletException(e);
204: } finally {
205: if (utx != null && utx.isActive()) {
206: logger.log(BasicLevel.DEBUG,
207: "Commit the local JDOTransactionItf");
208: utx.commit();
209: }
210: if (pm != null && !pm.isClosed()) {
211: logger.log(BasicLevel.DEBUG, "Close local PM");
212: pmh.closePersistenceManager();
213: }
214: }
215: }
216:
217: public void init() throws ServletException {
218: super .init();
219:
220: // get the logger
221: logger = Monolog.initialize().getLogger(getClass().getName());
222:
223: //get the PersistenceManagerFactory
224: persistenceManagerFactory = (PersistenceManagerFactory) getObjectFromContext(
225: null, PMF_JNDI_NAME);
226:
227: try {
228: getStoreServicesRemoteHome();
229: } catch (ServletException e) {
230: logger.log(BasicLevel.WARN,
231: "No StoreServicesRemoteHome found: "
232: + e.getMessage());
233: }
234:
235: try {
236: getStoreServicesLocalHome();
237: } catch (ServletException e) {
238: logger.log(BasicLevel.WARN,
239: "No StoreServicesLocalHome found: "
240: + e.getMessage());
241: }
242: }
243:
244: /**
245: * get the StoreServicesLocalHome.
246: */
247: private StoreServicesLocalHome getStoreServicesLocalHome()
248: throws ServletException {
249: if (lstoreServicesLH == null) {
250: lstoreServicesLH = (StoreServicesLocalHome) getObjectFromContext(
251: null, "java:comp/env/ejb/StoreServicesHomeLocal");
252: }
253: return lstoreServicesLH;
254: }
255:
256: /**
257: * get the StoreServicesRemoteHome.
258: */
259: private StoreServicesRemoteHome getStoreServicesRemoteHome()
260: throws ServletException {
261: if (lstoreServicesRH == null) {
262: lstoreServicesRH = (StoreServicesRemoteHome) getObjectFromContext(
263: null, "ejb/storeService");
264: }
265: return lstoreServicesRH;
266: }
267:
268: /**
269: * Get an object from JNDI
270: * @param ictx is the InitialContext to use. If this parameter is null
271: * a new context is created and closed
272: * @param name is the JNDI name of the searched object
273: * @return the object (never null)
274: * @throws ServletException if the object cannot be found.
275: */
276: private static Object getObjectFromContext(InitialContext ictx,
277: String name) throws ServletException {
278: boolean hasToCloseContext = false;
279: if (ictx == null) {
280: try {
281: ictx = new InitialContext();
282: hasToCloseContext = true;
283: } catch (NamingException e) {
284: logger.log(BasicLevel.ERROR,
285: "Impossible to get the InitialContext: ", e);
286: throw new ServletException(
287: "Impossible to get the InitialContext: "
288: + e.getMessage());
289: }
290: }
291: try {
292: Object o = ictx.lookup(name);
293: if (o == null) {
294: throw new ServletException("'" + name
295: + "' has not been found from JNDI");
296: }
297: return o;
298: } catch (ServletException e) {
299: throw e;
300: } catch (NameNotFoundException e) {
301: logger.log(BasicLevel.WARN, "Impossible to find " + name
302: + ": " + e.getMessage());
303: return null;
304: } catch (Exception e) {
305: logger.log(BasicLevel.ERROR, "Impossible to find " + name
306: + ": ", e);
307: return null;
308: } finally {
309: if (hasToCloseContext && ictx != null) {
310: try {
311: ictx.close();
312: } catch (NamingException ne) {
313: }
314: }
315: }
316: }
317:
318: /**
319: * Get the value of a prameter from a HttpServletRequest instance
320: * @param req is the HttpServletRequest
321: * @param paramName is the name of the parameter
322: * @param defaultValue is the default value to return if the parameter
323: * is not defined in the HttpServletRequest
324: */
325: private static boolean getParameterValue(HttpServletRequest req,
326: String paramName, boolean defaultValue) {
327: try {
328: String val = req.getParameter(paramName);
329: return val != null && Boolean.valueOf(val).booleanValue();
330: } catch (Exception e) {
331: return defaultValue;
332: }
333: }
334:
335: /**
336: * Empty threatment call for a ejb session
337: *
338: * @param lstoreServices
339: * @param persistenceManagerHolder
340: * @param out
341: * @throws JDOException
342: * @throws RemoteException
343: * @throws Exception
344: * @throws IOException
345: */
346: protected abstract void executeSessionBean(HttpServletRequest req,
347: HttpServletResponse resp, StoreServicesRemote storeServices)
348: throws JDOException, RemoteException, Exception,
349: IOException;
350:
351: protected abstract void executeSessionBean(HttpServletRequest req,
352: HttpServletResponse resp, StoreServicesLocal storeServices,
353: PMHolder persistenceManagerHolder) throws JDOException,
354: RemoteException, Exception, IOException;
355:
356: /**
357: * Empty threatment call for a jdo direct call
358: *
359: * @param persistenceManagerHolder
360: * @param out
361: * @throws JDOException
362: * @throws Exception
363: * @throws IOException
364: */
365: protected abstract void executeDirectCall(HttpServletRequest req,
366: HttpServletResponse resp, PMHolder persistenceManagerHolder)
367: throws JDOException, Exception, IOException;
368: }
|