001: /*
002: * Bossa Workflow System
003: *
004: * $Id: BossaFactory.java,v 1.9 2004/03/12 19:44:38 gdvieira Exp $
005: *
006: * Copyright (C) 2003,2004 OpenBR Sistemas S/C Ltda.
007: *
008: * This file is part of Bossa.
009: *
010: * Bossa is free software; you can redistribute it and/or modify it
011: * under the terms of version 2 of the GNU General Public License as
012: * published by the Free Software Foundation.
013: *
014: * This program is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * General Public License for more details.
018: *
019: * You should have received a copy of the GNU General Public
020: * License along with this program; if not, write to the
021: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
022: * Boston, MA 02111-1307, USA.
023: */
024:
025: package com.bigbross.bossa;
026:
027: import java.io.IOException;
028: import java.util.ArrayList;
029: import java.util.List;
030:
031: import org.prevayler.Prevayler;
032: import org.prevayler.PrevaylerFactory;
033:
034: import com.bigbross.bossa.history.HistoryListener;
035: import com.bigbross.bossa.notify.NotificationBus;
036:
037: /**
038: * This class handles the creation of a Bossa instance. <p>
039: *
040: * To use it, create an instance of this factory class, configure the
041: * available Bossa options by calling methods of this instance and create
042: * the Bossa instance using the <code>createBossa()</code> method. <p>
043: *
044: * Alternatively, use one of the provided static methods to get a preconfigured
045: * Bossa instance. <p>
046: *
047: * @author <a href="http://www.bigbross.com">BigBross Team</a>
048: */
049: public class BossaFactory {
050:
051: private boolean transientBossa;
052:
053: private TimeSource timeSource;
054:
055: private String stateDir;
056:
057: private boolean activeHistorian;
058:
059: /**
060: * Creates a new Bossa factory with default configuration values. <p>
061: */
062: public BossaFactory() {
063: transientBossa = false;
064: timeSource = null;
065: stateDir = "BossaState";
066: activeHistorian = true;
067: }
068:
069: /**
070: * Configures if the created Bossa is transient or not. <p>
071: *
072: * A transient Bossa won't save its state, all operations
073: * will be lost in case of system shutdown. However, it is still
074: * serializable, so it can be included in a larger prevalent system
075: * (if this is the case, look the <code>setTimeSource</code> method). <p>
076: *
077: * Default: <code>false</code>. <p>
078: *
079: * @param transientBossa <code>true</code> to create a transient Bossa,
080: * <code>false</code> to create a persistent Bossa.
081: * @see BossaFactory#setTimeSource(TimeSource)
082: */
083: public void setTransientBossa(boolean transientBossa) {
084: this .transientBossa = transientBossa;
085: }
086:
087: /**
088: * Configures the time source of a transient Bossa engine. See the
089: * documentation of the <code>TimeSource</code> interface for more
090: * information on time sources. <p>
091: *
092: * If you don't care about how time is handled by the Bossa engine,
093: * usa an instance of the <code>RealTimeSource</code> class. <p>
094: *
095: * If you are trying to embed a transient Bossa engine in a larger
096: * prevalent system, use an instance of the
097: * <code>DeterministicTimeSource</code> class. Keep a reference to the
098: * time source and set the time in it every time a transaction is
099: * executed, all Bossa actions will happen using the time set. <p>
100: *
101: * Default: <code>new RealTimeSource()</code>. <p>
102: *
103: * @param timeSource the time source.
104: * @see BossaFactory#setTransientBossa(boolean)
105: * @see TimeSource
106: * @see RealTimeSource
107: * @see DeterministicTimeSource
108: */
109: public void setTimeSource(TimeSource timeSource) {
110: this .timeSource = timeSource;
111: }
112:
113: /**
114: * Configures the directory where Bossa will save its state. <p>
115: *
116: * If the provided directory is empty, a new Bossa engine will be created.
117: * If the provided directory contains data of an already running Bossa
118: * engine, it will be restarted using this data. <p>
119: *
120: * Default: <code>"BossaState"</code>
121: *
122: * @param dir the directory where Bossa will save its state.
123: */
124: public void setStateDir(String dir) {
125: if (dir != null) {
126: stateDir = dir;
127: } else {
128: throw new NullPointerException();
129: }
130: }
131:
132: /**
133: * Configures if the created Bossa will log its events in the historian
134: * or not. <p>
135: *
136: * Default: <code>true</code>. <p>
137: *
138: * @param activeHistorian <code>true</code> for the historian to log
139: * events, <code>false</code> for the historian
140: * to ignore events.
141: */
142: public void setActiveHistorian(boolean activeHistorian) {
143: this .activeHistorian = activeHistorian;
144: }
145:
146: /**
147: * Creates a Bossa engine instance using the current configuration
148: * of the Bossa factory. <p>
149: *
150: * @return the newly created bossa engine.
151: * @exception PersistenceException if an error occours starting the
152: * persistence mechanism.
153: */
154: public Bossa createBossa() throws PersistenceException {
155: Bossa newBossa = new Bossa();
156:
157: List internalListners = new ArrayList();
158: if (activeHistorian) {
159: internalListners.add(new HistoryListener(newBossa
160: .getHistorian()));
161: }
162: newBossa.setNotificationBus(new NotificationBus(newBossa,
163: internalListners));
164:
165: if (this .transientBossa) {
166: if (this .timeSource != null) {
167: newBossa.setTimeSource(this .timeSource);
168: } else {
169: newBossa.setTimeSource(new RealTimeSource());
170: }
171: } else if (this .stateDir != null) {
172: try {
173: PrevaylerFactory factory = new PrevaylerFactory();
174: factory.configurePrevalentSystem(newBossa);
175: factory.configurePrevalenceBase(this .stateDir);
176: factory.configureTransactionFiltering(false);
177: Prevayler prevayler = factory.create();
178: newBossa = (Bossa) prevayler.prevalentSystem();
179: newBossa.setPrevayler(prevayler);
180: } catch (IOException e) {
181: throw new PersistenceException(
182: "I/O error starting prevayler.", e);
183: } catch (ClassNotFoundException e) {
184: throw new PersistenceException(
185: "Reflection error in prevayler.", e);
186: }
187: }
188:
189: return newBossa;
190: }
191:
192: /**
193: * Creates a Bossa engine instance with the default configuration
194: * values. <p>
195: *
196: * @return the newly created bossa engine.
197: * @exception PersistenceException if an error occours starting the
198: * persistence mechanism.
199: */
200: public static Bossa defaultBossa() throws PersistenceException {
201: return new BossaFactory().createBossa();
202: }
203:
204: /**
205: * Creates a transient Bossa engine instance, keeping all other default
206: * configuration values. <p>
207: *
208: * @return the newly created bossa engine.
209: * @exception PersistenceException if an error occours starting the
210: * persistence mechanism.
211: */
212: public static Bossa transientBossa() throws PersistenceException {
213: BossaFactory factory = new BossaFactory();
214: factory.setTransientBossa(true);
215: return factory.createBossa();
216: }
217: }
|