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 }