001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.spi.service;
046:
047: import org.obe.OBEException;
048: import org.obe.client.api.model.MIMETypes;
049: import org.obe.spi.WMLocalClient;
050: import org.obe.spi.event.ApplicationEventListener;
051: import org.obe.util.CommonConfig;
052:
053: import javax.mail.Session;
054: import javax.naming.Context;
055: import javax.naming.InitialContext;
056: import javax.naming.NamingException;
057: import java.net.InetAddress;
058: import java.net.UnknownHostException;
059:
060: /**
061: * Provides access to OBE server configuration information. OBE is configured
062: * by several XML and properties files, which can either be located in the OBE
063: * configuration directory or in the <code>META-INF/services</code> directory in
064: * obeconfig.jar. Resources in the latter location are accessed via this
065: * class's ClassLoader. The OBE configuration directory can be specified by the
066: * system property <code>"obe.config.dir"</code>, and it defaults to the current
067: * directory. Loose files take precedence over resources in obeconfig.jar.
068: * <p/>
069: * The <code>obe.properties</code> file contains the main OBE configuration,
070: * and the <code>ServiceManager.properties</code> file contains the OBE
071: * ServiceManager configuration.
072: *
073: * @author Adrian Price
074: */
075: public final class ServerConfig extends CommonConfig {
076: /**
077: * Property key for audit trail transactionality.
078: *
079: * @see #isAuditNonTransactional()
080: */
081: public static final String AUDIT_NON_TXN_PROP = "obe.audit.nontransactional";
082: /**
083: * Property key for auditing domain.
084: *
085: * @see #getDomain()
086: */
087: public static final String DOMAIN_PROP = "obe.domain";
088: /**
089: * Property key for mail session.
090: *
091: * @see #getMailSession()
092: */
093: public static final String MAIL_SESSION_PROP = "obe.mail.session";
094: /**
095: * Property key for auditing node.
096: *
097: * @see #getNodeId()
098: */
099: public static final String NODE_PROP = "obe.node";
100: /**
101: * Property key for workitem reuse.
102: *
103: * @see #reuseWorkItems()
104: */
105: public static final String REUSE_WORKITEMS_PROP = "obe.reuse.workitems";
106: /**
107: * Property key for default script type.
108: *
109: * @see #getScriptType()
110: */
111: public static final String SCRIPT_PROP = "obe.script";
112: /**
113: * Property key for internal event API usage.
114: *
115: * @see #useEventAPI()
116: */
117: public static final String USE_EVENT_API_PROP = "obe.events.use.api";
118: /**
119: * Property key for key-based event subscription usage.
120: *
121: * @see #supportsKeyBasedEventSubscriptions()
122: */
123: public static final String EVENT_KEY_BASED_SUBSCRIPTIONS_PROP = "obe.events.key.based.subscriptions";
124: /**
125: * Property key for temporal event validity.
126: *
127: * @see #getMaximumTemporalEventTardiness()
128: */
129: public static final String EVENT_MAX_TARDINESS_PROP = "obe.events.max.tardiness";
130: /**
131: * Property key for initialization servlet usage.
132: *
133: * @see #useInitServlet()
134: */
135: public static final String USE_INIT_SERVLET_PROP = "obe.init.use.servlet";
136: /**
137: * Property key for debug verbosity.
138: *
139: * @see #isVerbose()
140: */
141: public static final String VERBOSE_PROP = "obe.debug.verbose";
142: /**
143: * Property key for async manager thread pool size.
144: *
145: * @see #getAsyncThreadpoolSize()
146: */
147: public static final String ASYNC_THREADPOOL_SIZE_PROP = "obe.async.threadpool.size";
148: /**
149: * Property key for processes directory polling interval.
150: *
151: * @see #getDirectoryPollInterval()
152: */
153: public static final String DIRECTORY_POLL_INTERVAL_PROP = "obe.directory.poll.interval";
154:
155: private static final String LOCALHOST = "localhost";
156:
157: /**
158: * JavaMail mail session defaults.
159: */
160: private static final String[][] MAIL_DEFAULTS = {
161: { "mail.debug", "false" },
162: { "mail.from", "obe@localhost" },
163: { "mail.mime.address.strict", "true" },
164: { "mail.host", LOCALHOST },
165: { "mail.store.protocol", "pop3" },
166: { "mail.transport.protocol", "smtp" },
167: { "mail.user", "obe" }, };
168:
169: private static final int DEFAULT_POLL_MILLIS = 5000;
170: private static final int DEFAULT_POOL_SIZE = 20;
171: private static final int DEFAULT_MAX_TARDINESS = 300000;
172:
173: private static final InetAddress LOCAL_HOST;
174: private static final String HOST;
175: private static final String DOMAIN;
176: private static final String ADDRESS;
177:
178: static {
179: InetAddress addr = null;
180: try {
181: addr = InetAddress.getLocalHost();
182: } catch (UnknownHostException e) {
183: // Fine, we can't resolve our host name.
184: }
185: LOCAL_HOST = addr;
186: ADDRESS = LOCAL_HOST == null ? "127.0.0.1" : LOCAL_HOST
187: .getHostAddress();
188: HOST = LOCAL_HOST == null ? LOCALHOST : LOCAL_HOST
189: .getHostName();
190: DOMAIN = "OBE";
191:
192: for (int i = 0; i < MAIL_DEFAULTS.length; i++)
193: _props
194: .setProperty(MAIL_DEFAULTS[i][0],
195: MAIL_DEFAULTS[i][1]);
196: }
197:
198: /**
199: * Returns the local host's InetAddress, if known.
200: *
201: * @return The local host.
202: */
203: public static InetAddress getLocalHost() {
204: return LOCAL_HOST;
205: }
206:
207: /**
208: * Returns the local host's IP address.
209: *
210: * @return The local host address.
211: */
212: public static String getHostAddress() {
213: return ADDRESS;
214: }
215:
216: /**
217: * Returns the local host's DNS host name.
218: *
219: * @return The DNS host name.
220: */
221: public static String getHostName() {
222: return HOST;
223: }
224:
225: /**
226: * Returns the server's management domain. Currently, this returns the
227: * hard-coded string <code>"OBE"</code>. In a future release,
228: * this will be changed to return the name of the management domain to which
229: * the server belongs.
230: * <p/>
231: * The setting reflects the string value of the configuration property
232: * <code>obe.domain</code>.
233: *
234: * @return The management domain name, defaulting to <code>"OBE"</code>.
235: * @see #DOMAIN_PROP
236: */
237: public static String getDomain() {
238: return getStringProperty(DOMAIN_PROP, DOMAIN);
239: }
240:
241: /**
242: * Returns the server's node ID. Currently, this returns the server's
243: * DNS host name. In a future release, this will be changed to return a
244: * node ID that is unique within the management domain to which the server
245: * belongs.
246: * <p/>
247: * The setting reflects the string value of the configuration property
248: * <code>obe.node</code>.
249: *
250: * @return The server's node ID, defaulting to the primary DNS host name.
251: * @see #NODE_PROP
252: */
253: public static String getNodeId() {
254: return getStringProperty(NODE_PROP, HOST);
255: }
256:
257: /**
258: * Returns the default script type to use if one is not specified in XPDL.
259: * <p/>
260: * The setting reflects the boolean value of the configuration property
261: * <code>obe.script</code>.
262: *
263: * @return Script type, defaulting to <code>"text/x-xpath"</code>.
264: * @see #SCRIPT_PROP
265: */
266: public static String getScriptType() {
267: return getStringProperty(SCRIPT_PROP, MIMETypes.XPATH);
268: }
269:
270: /**
271: * Returns whether debug output should be verbose.
272: * <p/>
273: * The setting reflects the boolean value of the configuration property
274: * <code>obe.debug.verbose</code>.
275: *
276: * @return <code>true</code> if verbose debugging is enabled, defaulting to
277: * <code>false</code>.
278: * @see #VERBOSE_PROP
279: */
280: public static boolean isVerbose() {
281: return getBooleanProperty(VERBOSE_PROP, false);
282: }
283:
284: /**
285: * Returns whether work items should be re-used.
286: * <p/>
287: * The setting reflects the boolean value of the configuration property
288: * <code>obe.reuse.workitems</code>.
289: *
290: * @return <code>true</code> if work item re-use is enabled.
291: * @see #REUSE_WORKITEMS_PROP
292: */
293: public static boolean reuseWorkItems() {
294: return getBooleanProperty(REUSE_WORKITEMS_PROP, true);
295: }
296:
297: /**
298: * Returns whether to inject application events via the
299: * {@link WMLocalClient local client API}. The engine creates
300: * an {@link ApplicationEventListener application event
301: * listener}, with which it subscribes for workflow-relevant application
302: * events. Injecting application events via the API allows them to be
303: * handled in a transactional context under an authenticated identity if the
304: * ApplicationEventBroker implementation does not provide these
305: * characteristics.
306: * <p/>
307: * The setting reflects the boolean value of the configuration property
308: * <code>obe.events.use.api</code>.
309: *
310: * @return <code>true</code> if events are to be injected via the API,
311: * <code>false</code> for direct injection into the workflow engine.
312: * @see #USE_EVENT_API_PROP
313: */
314: public static boolean useEventAPI() {
315: return getBooleanProperty(USE_EVENT_API_PROP, false);
316: }
317:
318: /**
319: * Returns whether to defer initialization to the J2EEInitServlet.
320: *
321: * @return <code>true</code> to defer initialization, <code>false</code> to
322: * initialize immediately.
323: * @see #USE_INIT_SERVLET_PROP
324: */
325: public static boolean useInitServlet() {
326: return getBooleanProperty(USE_INIT_SERVLET_PROP, false);
327: }
328:
329: /**
330: * Returns whether auditing should be performed non-transactionally. If
331: * auditing is transactional, audit entries are enlisted in the transaction
332: * and will be lost in the event of a rollback. Otherwise, audit entries
333: * will be always logged regardless of the outcome of the transaction to
334: * which they relate.
335: * <p/>
336: * <em>N.B. Non-transactional auditing is very much more expensive than
337: * transactional auditing, and should only be used if absolutely
338: * necessary. In addition, interpreting the audit log is less
339: * straightforward, because the transactional context must be taken into
340: * account to determine whether an audit entry relates to a committed change
341: * or one which was rolled back. At the time of writing, non-transactional
342: * auditing support is incomplete, in that the transaction ID is not
343: * currently included in the logged information.</em>
344: * <p/>
345: * The setting reflects the value of the configuration property
346: * <code>obe.audit.nontransactional</code>:
347: * <br/>
348: * <table border="1"><tr><th>Type</th><th>Default</th><th>Purpose</th></tr>
349: * <tr valign="top"><td>boolean</td><td>false</td><td>
350: * The property name that specifies whether to log audit entries
351: * non-transactionally.
352: * </td></tr></table>
353: *
354: * @return <code>true</code> for non-transactional auditing.
355: * @see #AUDIT_NON_TXN_PROP
356: */
357: public static boolean isAuditNonTransactional() {
358: return getBooleanProperty(AUDIT_NON_TXN_PROP, false);
359: }
360:
361: /**
362: * Returns the size of the thread pool used to service asynchronous
363: * execution requests.
364: * <p/>
365: * The setting reflects the value of the configuration property
366: * <code>obe.async.threadpool.size</code>.
367: *
368: * @return Async thread pool size, defaulting to <code>20</code>.
369: * @see #ASYNC_THREADPOOL_SIZE_PROP
370: */
371: public static int getAsyncThreadpoolSize() {
372: return getIntProperty(ASYNC_THREADPOOL_SIZE_PROP,
373: DEFAULT_POOL_SIZE);
374: }
375:
376: /**
377: * Returns the polling interval for the
378: * <code>${obe.config.dir}/processes</code> and
379: * <code>${obe.config.dir}/events</code> directories. Only used by the
380: * BasicProcessRepository and BasicApplicationEventBroker.
381: * <p/>
382: * The setting reflects the value of the configuration property
383: * <code>obe.directory.poll.interval</code>.
384: *
385: * @return Polling interval in milliseconds, defaulting to <code>5000</code>
386: * (5 seconds).
387: * @see #DIRECTORY_POLL_INTERVAL_PROP
388: */
389: public static int getDirectoryPollInterval() {
390: return getIntProperty(DIRECTORY_POLL_INTERVAL_PROP,
391: DEFAULT_POLL_MILLIS);
392: }
393:
394: /**
395: * Returns the maximum acceptable delay for processing a non-recoverable
396: * temporal event. Non-recoverable temporal events older than this are
397: * discarded unprocessed.
398: * <p/>
399: * The setting reflects the value of the configuration property
400: * <code>obe.events.max.tardiness</code>.
401: *
402: * @return Maximum temporal event processing delay, defaulting to
403: * <code>30000</code> (5 minutes).
404: * @see #EVENT_MAX_TARDINESS_PROP
405: */
406: public static int getMaximumTemporalEventTardiness() {
407: return getIntProperty(EVENT_MAX_TARDINESS_PROP,
408: DEFAULT_MAX_TARDINESS);
409: }
410:
411: /**
412: * Returns whether the event manager should accept key-based event
413: * subscriptions.
414: * <p/>
415: * The setting reflects the value of the configuration property
416: * <code>obe.events.key.based.subscriptions</code>.
417: *
418: * @return <code>true</code> to accept key-based subscriptions,
419: * <code>false</code> to reject, defaulting to <code>true</code>.
420: * @see #EVENT_KEY_BASED_SUBSCRIPTIONS_PROP
421: */
422: public static boolean supportsKeyBasedEventSubscriptions() {
423: return getBooleanProperty(EVENT_KEY_BASED_SUBSCRIPTIONS_PROP,
424: true);
425: }
426:
427: /**
428: * Returns the default mail session.
429: *
430: * @return Mail session.
431: */
432: public static Session getMailSession() throws OBEException {
433: Session mailSession;
434: String jndiName = getStringProperty(MAIL_SESSION_PROP, null);
435: if (jndiName == null) {
436: mailSession = Session.getDefaultInstance(_props);
437: } else {
438: Context ctx = null;
439: try {
440: ctx = new InitialContext();
441: mailSession = (Session) ctx.lookup(jndiName);
442: } catch (NamingException e) {
443: throw new OBEException(e);
444: } finally {
445: if (ctx != null) {
446: try {
447: ctx.close();
448: } catch (NamingException e) {
449: _logger.error("Error closing JNDI Context", e);
450: }
451: }
452: }
453: }
454: return mailSession;
455: }
456:
457: private ServerConfig() {
458: }
459: }
|