001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.test.util.ejb;
023:
024: import java.lang.reflect.Constructor;
025: import java.util.Properties;
026: import javax.ejb.EJBException;
027: import javax.ejb.SessionBean;
028: import javax.ejb.SessionContext;
029: import javax.naming.Binding;
030: import javax.naming.InitialContext;
031: import javax.naming.NamingException;
032: import javax.naming.NamingEnumeration;
033: import javax.transaction.Status;
034: import javax.transaction.SystemException;
035:
036: /**
037: * Implementation of the ejb test runner.
038: *
039: * @see EJBTestRunner
040: *
041: * @author <a href="mailto:dain@daingroup.com">Dain Sundstrom</a>
042: * @author Scott.Stark@jboss.org
043: * @version $Revision: 57211 $
044: */
045: public class EJBTestRunnerBean implements SessionBean {
046: transient private SessionContext ctx;
047: private String runnerJndiName;
048:
049: /** Run the specified test method on the given class name using a Properties
050: * map built from all java:comp/env entries.
051: *
052: * @param className the name of the test class
053: * @param methodName the name of the test method
054: * @throws RemoteTestException If any throwable is thrown during
055: * execution of the method, it is wrapped with a RemoteTestException and
056: * rethrown.
057: */
058: public void run(String className, String methodName)
059: throws RemoteTestException {
060: Properties props = new Properties();
061: try {
062: InitialContext ctx = new InitialContext();
063: NamingEnumeration bindings = ctx
064: .listBindings("java:comp/env");
065: while (bindings.hasMore()) {
066: Binding binding = (Binding) bindings.next();
067: String name = binding.getName();
068: String value = binding.getObject().toString();
069: props.setProperty(name, value);
070: }
071: } catch (NamingException e) {
072: throw new RemoteTestException(e);
073: }
074: run(className, methodName, props);
075: }
076:
077: /** Run the specified test method on the given class name
078: *
079: * @param className the name of the test class
080: * @param methodName the name of the test method
081: * @param props
082: * @throws RemoteTestException If any throwable is thrown during
083: * execution of the method, it is wrapped with a RemoteTestException and
084: * rethrown.
085: */
086: public void run(String className, String methodName,
087: Properties props) throws RemoteTestException {
088: EJBTestCase testCase = getTestInstance(className, methodName);
089:
090: setUpEJB(testCase, props);
091:
092: RemoteTestException exception = null;
093: try {
094: runTestCase(testCase);
095: } catch (RemoteTestException e) {
096: exception = e;
097: } finally {
098: try {
099: tearDownEJB(testCase, props);
100: } catch (RemoteTestException e) {
101: // favor the run exception if one was thrown
102: if (exception != null) {
103: exception = e;
104: }
105: }
106: if (exception != null) {
107: throw exception;
108: }
109: }
110: }
111:
112: /**
113: * Runs the setUpEJB method on the specified test case
114: * @param testCase the actual test case that will be run
115: * @throws RemoteTestException If any throwable is thrown during execution
116: * of the method, it is wrapped with a RemoteTestException and rethrown.
117: */
118: private void setUpEJB(EJBTestCase testCase, Properties props)
119: throws RemoteTestException {
120: try {
121: ctx.getUserTransaction().begin();
122: try {
123: testCase.setUpEJB(props);
124: } catch (Throwable e) {
125: throw new RemoteTestException(e);
126: }
127: if (ctx.getUserTransaction().getStatus() == Status.STATUS_ACTIVE) {
128: ctx.getUserTransaction().commit();
129: }
130: } catch (Throwable e) {
131: try {
132: ctx.getUserTransaction().rollback();
133: } catch (SystemException unused) {
134: // eat the exception we are exceptioning out anyway
135: }
136: if (e instanceof RemoteTestException) {
137: throw (RemoteTestException) e;
138: }
139: throw new RemoteTestException(e);
140: }
141: }
142:
143: /**
144: * Runs the test method on the specified test case
145: * @param testCase the actual test case that will be run
146: * @throws RemoteTestException If any throwable is thrown during execution
147: * of the method, it is wrapped with a RemoteTestException and rethrown.
148: */
149: private void runTestCase(EJBTestCase testCase)
150: throws RemoteTestException {
151: try {
152: ctx.getUserTransaction().begin();
153: try {
154: testCase.runBare();
155: } catch (Throwable e) {
156: throw new RemoteTestException(e);
157: }
158: if (ctx.getUserTransaction().getStatus() == Status.STATUS_ACTIVE) {
159: ctx.getUserTransaction().commit();
160: }
161: } catch (Throwable e) {
162: try {
163: ctx.getUserTransaction().rollback();
164: } catch (SystemException unused) {
165: // eat the exception we are exceptioning out anyway
166: }
167: if (e instanceof RemoteTestException) {
168: throw (RemoteTestException) e;
169: }
170: throw new RemoteTestException(e);
171: }
172: }
173:
174: /**
175: * Runs the tearDownEJB method on the specified test case
176: * @param testCase the actual test case that will be run
177: * @throws RemoteTestException If any throwable is thrown during execution
178: * of the method, it is wrapped with a RemoteTestException and rethrown.
179: */
180: private void tearDownEJB(EJBTestCase testCase, Properties props)
181: throws RemoteTestException {
182:
183: try {
184: ctx.getUserTransaction().begin();
185: try {
186: testCase.tearDownEJB(props);
187: } catch (Throwable e) {
188: throw new RemoteTestException(e);
189: }
190: if (ctx.getUserTransaction().getStatus() == Status.STATUS_ACTIVE) {
191: ctx.getUserTransaction().commit();
192: }
193: } catch (Throwable e) {
194: try {
195: ctx.getUserTransaction().rollback();
196: } catch (SystemException unused) {
197: // eat the exception we are exceptioning out anyway
198: }
199: if (e instanceof RemoteTestException) {
200: throw (RemoteTestException) e;
201: }
202: throw new RemoteTestException(e);
203: }
204: }
205:
206: /**
207: * Gets a instance of the test class with the specified class name and
208: * initialized to execute the specified method.
209: *
210: * @param className the name of the test class
211: * @param methodName the name of the test method
212: * @return a new instance of the test class with the specified class name and
213: * initialized to execute the specified method.
214: */
215: private EJBTestCase getTestInstance(String className,
216: String methodName) {
217: Class testClass = null;
218: try {
219: ClassLoader loader = Thread.currentThread()
220: .getContextClassLoader();
221: testClass = loader.loadClass(className);
222: } catch (ClassNotFoundException e) {
223: throw new EJBException("Test class not found : "
224: + className);
225: }
226:
227: Constructor constructor = null;
228: try {
229: constructor = testClass
230: .getConstructor(new Class[] { String.class });
231: } catch (Exception e) {
232: throw new EJBException(
233: "Test class does not have a constructor "
234: + "which has a single String argument.", e);
235: }
236:
237: try {
238: EJBTestCase testCase = (EJBTestCase) constructor
239: .newInstance(new Object[] { methodName });
240: testCase.setServerSide(true);
241: return testCase;
242: } catch (Exception e) {
243: throw new EJBException("Cannot instantiate test class: "
244: + testClass.getName(), e);
245: }
246: }
247:
248: public void ejbCreate() {
249: }
250:
251: public void ejbRemove() {
252: }
253:
254: public void ejbActivate() {
255: }
256:
257: public void ejbPassivate() {
258: }
259:
260: public void setSessionContext(SessionContext ctx) {
261: this.ctx = ctx;
262: }
263: }
|