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