001 package com.mockrunner.mock.ejb; 002 003 import javax.naming.Context; 004 import javax.naming.NameNotFoundException; 005 import javax.naming.NamingException; 006 import javax.transaction.UserTransaction; 007 008 import org.mockejb.MockContainer; 009 010 import com.mockrunner.ejb.Configuration; 011 import com.mockrunner.ejb.JNDIUtil; 012 013 /** 014 * Used to create all types of EJB mock objects. 015 * Maintains the necessary dependencies between the mock objects. 016 * If you use the mock objects returned by this factory in your tests 017 * you can be sure that they are all up to date. 018 * This factory takes the <code>UserTransaction</code> from the JNDI context. 019 * If there's no transaction bound to the context, the factory will create a 020 * {@link com.mockrunner.mock.ejb.MockUserTransaction} and bind it to the context. 021 * If the bound transaction is no 022 * {@link com.mockrunner.mock.ejb.MockUserTransaction}, 023 * the method {@link #getMockUserTransaction} returns <code>null</code>. 024 * Use {@link #getUserTransaction} instead in this case. 025 * You can configure the JNDI name of the <code>UserTransaction</code> and 026 * the JNDI <code>Context</code> with the class 027 * {@link com.mockrunner.ejb.Configuration}. 028 */ 029 public class EJBMockObjectFactory 030 { 031 private Configuration configuration; 032 private UserTransaction transaction; 033 private MockContainer container; 034 private Context context; 035 036 /** 037 * Creates a new set of mock objects. 038 */ 039 public EJBMockObjectFactory() 040 { 041 this(new Configuration()); 042 } 043 044 /** 045 * Creates a new set of mock objects based on the specified configuration. 046 */ 047 public EJBMockObjectFactory(Configuration configuration) 048 { 049 this.configuration = configuration; 050 initializeContext(); 051 initializeEJBContainer(); 052 initializeUserTransaction(); 053 } 054 055 private void initializeContext() 056 { 057 context = JNDIUtil.getContext(configuration); 058 } 059 060 private void initializeUserTransaction() 061 { 062 try 063 { 064 try 065 { 066 transaction = (UserTransaction)context.lookup(configuration.getUserTransactionJNDIName()); 067 } 068 catch(NameNotFoundException nameExc) 069 { 070 transaction = createMockUserTransaction(); 071 JNDIUtil.bindUserTransaction(configuration, context, transaction); 072 } 073 } 074 catch(Exception exc) 075 { 076 transaction = createMockUserTransaction(); 077 } 078 if(transaction instanceof MockUserTransaction) 079 { 080 ((MockUserTransaction)transaction).reset(); 081 } 082 } 083 084 private void initializeEJBContainer() 085 { 086 container = new MockContainer(context); 087 } 088 089 /** 090 * Creates the {@link com.mockrunner.mock.ejb.MockUserTransaction} using <code>new</code>. 091 * This method can be overridden to return a subclass of {@link com.mockrunner.mock.ejb.MockUserTransaction}. 092 * @return the {@link com.mockrunner.mock.ejb.MockUserTransaction} 093 */ 094 public MockUserTransaction createMockUserTransaction() 095 { 096 return new MockUserTransaction(); 097 } 098 099 /** 100 * Calls <code>MockContextFactory.setAsInitial()</code>, if 101 * <code>MockContextFactory</code> is not already the current 102 * context factory. 103 */ 104 public void initMockContextFactory() throws NamingException 105 { 106 JNDIUtil.initMockContextFactory(); 107 } 108 109 /** 110 * Calls <code>MockContextFactory.revertSetAsInitial()</code>, if 111 * <code>MockContextFactory</code> is the current context factory. 112 */ 113 public void resetMockContextFactory() 114 { 115 JNDIUtil.resetMockContextFactory(); 116 } 117 118 /** 119 * Returns the {@link com.mockrunner.mock.ejb.MockUserTransaction}. 120 * If the bound transaction is no {@link com.mockrunner.mock.ejb.MockUserTransaction}, 121 * this method returns <code>null</code>. 122 * @return the {@link com.mockrunner.mock.ejb.MockUserTransaction} 123 */ 124 public MockUserTransaction getMockUserTransaction() 125 { 126 if(!(transaction instanceof MockUserTransaction)) return null; 127 return (MockUserTransaction)transaction; 128 } 129 130 /** 131 * Returns the <code>UserTransaction</code>. 132 * @return the <code>UserTransaction</code> 133 */ 134 public UserTransaction getUserTransaction() 135 { 136 return transaction; 137 } 138 139 /** 140 * Returns the MockEJB <code>MockContainer</code>. 141 * @return the <code>MockContainer</code> 142 */ 143 public MockContainer getMockContainer() 144 { 145 return container; 146 } 147 148 /** 149 * Returns the JNDI context that is used by this factory. If you do not set 150 * a <code>Context</code> using {@link com.mockrunner.ejb.Configuration#setContext}}, 151 * the JNDI implementation of MockEJB is used. 152 * @return the JNDI context 153 */ 154 public Context getContext() 155 { 156 return context; 157 } 158 }