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 }