001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: DefaultAuditEvent.java,v 1.5 2006/09/29 12:32:08 drmlipp Exp $
021: *
022: * $Log: DefaultAuditEvent.java,v $
023: * Revision 1.5 2006/09/29 12:32:08 drmlipp
024: * Consistently using WfMOpen as projct name now.
025: *
026: * Revision 1.4 2006/09/06 09:30:25 drmlipp
027: * Further improved serialization.
028: *
029: * Revision 1.3 2006/09/05 15:55:25 drmlipp
030: * Added deferred deserialization of source as a workaround for a
031: * classloader problem.
032: *
033: * Revision 1.2 2005/04/22 15:11:02 drmlipp
034: * Merged changes from 1.3 branch up to 1.3p15.
035: *
036: * Revision 1.1.1.2.6.2 2005/04/18 11:11:21 drmlipp
037: * More event handling optimization.
038: *
039: * Revision 1.1.1.2.6.1 2005/04/16 21:18:30 drmlipp
040: * Made audit event filtering more flexible and added possibility to turn
041: * off audit log.
042: *
043: * Revision 1.1.1.2 2004/08/18 15:17:38 drmlipp
044: * Update to 1.2
045: *
046: * Revision 1.18 2004/07/04 17:34:19 lipp
047: * Fixed problem with event source.
048: *
049: * Revision 1.17 2003/06/27 08:51:45 lipp
050: * Fixed copyright/license information.
051: *
052: * Revision 1.16 2003/05/28 15:11:03 lipp
053: * Updated toString.
054: *
055: * Revision 1.15 2003/05/07 10:46:06 lipp
056: * Renamed some classes/methods to imply both tool and sub-process
057: * implementations.
058: *
059: * Revision 1.14 2003/04/26 16:11:15 lipp
060: * Moved some classes to reduce package dependencies.
061: *
062: * Revision 1.13 2003/03/31 16:50:28 huaiyang
063: * Logging using common-logging.
064: *
065: * Revision 1.12 2003/02/11 08:49:55 lipp
066: * Shortened toString repr.
067: *
068: * Revision 1.11 2003/02/06 16:39:51 lipp
069: * Fixed a state handling bug (must not expose running state for manually
070: * started activity).
071: *
072: * Revision 1.10 2002/10/22 15:48:21 lipp
073: * Keep audit event base information as local info to avoid unnecessary
074: * container() calls.
075: *
076: * Revision 1.9 2002/10/16 08:40:19 barzik
077: * new constructors to allow recreation by history
078: *
079: * Revision 1.8 2002/10/07 12:04:38 barzik
080: * toString now displays the event type, too.
081: *
082: * Revision 1.7 2002/10/03 19:01:00 lipp
083: * New constructor.
084: *
085: * Revision 1.6 2002/10/02 20:54:40 lipp
086: * Event handling partially reorganized.
087: *
088: * Revision 1.5 2002/10/02 15:07:43 lipp
089: * Support eventType null.
090: *
091: * Revision 1.4 2002/10/02 11:27:07 barzik
092: * bug fixes and more ...
093: *
094: * Revision 1.3 2002/10/01 16:06:00 lipp
095: * Event queue activated.
096: *
097: * Revision 1.2 2002/10/01 11:03:14 barzik
098: * add toString()
099: *
100: * Revision 1.1 2002/10/01 09:10:38 lipp
101: * AuditEvent handling restructured.
102: *
103: * Revision 1.9 2002/10/01 06:45:23 barzik
104: * no message
105: *
106: * Revision 1.8 2002/09/30 15:04:46 lipp
107: * Added implements Serializable.
108: *
109: * Revision 1.7 2002/09/30 12:42:05 barzik
110: * audit event handling using base event information
111: *
112: * Revision 1.6 2002/09/26 09:53:00 huaiyang
113: * In readresolve method use text representation to compare.
114: *
115: * Revision 1.5 2002/09/26 08:02:31 barzik
116: * Moved EventType to WfAuditEvent.java
117: *
118: * Revision 1.4 2002/09/24 12:23:36 barzik
119: * Extended ...
120: *
121: * Revision 1.3 2002/07/24 08:04:42 huaiyang
122: * doccheck.
123: *
124: * Revision 1.2 2001/08/24 12:58:30 lipp
125: * CR/NL fixes
126: *
127: * Revision 1.1 2001/07/06 08:51:48 lipp
128: * Moved from domain to omgcore
129: *
130: * Revision 1.1 2001/07/05 14:15:09 lipp
131: * Rather complete version.
132: *
133: */
134: package de.danet.an.workflow.domain;
135:
136: import java.io.ByteArrayInputStream;
137: import java.io.ByteArrayOutputStream;
138: import java.io.IOException;
139: import java.io.ObjectInputStream;
140: import java.io.ObjectOutputStream;
141: import java.io.Serializable;
142:
143: import java.util.Date;
144: import java.util.EventObject;
145:
146: import de.danet.an.workflow.omgcore.SourceNotAvailableException;
147: import de.danet.an.workflow.omgcore.WfActivity;
148: import de.danet.an.workflow.omgcore.WfAuditEvent;
149: import de.danet.an.workflow.omgcore.WfExecutionObject;
150: import de.danet.an.workflow.omgcore.WfProcess;
151: import de.danet.an.workflow.api.ProcessDefinition;
152:
153: /**
154: * <P>A <code>DefaultAuditEvent</code> implements an audit record of
155: * workflow event information.</P>
156: *
157: * <P>It provides information on the source of the event and contains
158: * specific event data. Workflow events include state changes, change
159: * of a resource assignment, and data changes. Workflow events are
160: * persistent and can be accessed navigating the history relationship
161: * of a <code>WfExecutionObject</code>.</P>
162: *
163: * <P>Workflow audit event objects are not part of the persistent state of
164: * their source workflow object.</P>
165: */
166: public class DefaultAuditEvent extends EventObject implements
167: WfAuditEvent, Serializable {
168:
169: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
170: .getLog(DefaultAuditEvent.class);
171:
172: private byte[] marshalledSource = null;
173:
174: /**
175: * The attribute <code>timeStamp</code>. It identifies
176: * the timestamp as supplied at trigger time of the event.
177: */
178: private Date timeStamp = null;
179:
180: /**
181: * The attribute <code>eventType</code>. It identifies
182: * the type of the event. The type is supplied either
183: * implicit in case of a unique definition or must be supplied at trigger
184: * time.
185: */
186: private String eventType = null;
187:
188: /**
189: * The attribute <code>activityKey</code>. It identifies
190: * the activity associated with the event.
191: */
192: private String activityKey = null;
193:
194: /**
195: * The attribute <code>processKey</code>. It identifies
196: * the name of the activity associated with the event.
197: * If the event is associated to a process, the attribute is expected
198: * being <code>null</code>.
199: */
200: private String activityName = null;
201:
202: /**
203: * The attribute <code><processKey/code>. It identifies
204: * the process associated with the event.
205: * If the event is associated to a process, the attribute is expected
206: * being <code>null</code>.
207: */
208: private String processKey = null;
209:
210: /**
211: * The attribute <code>processName</code>. It identifies
212: * the name of the process associated with the event.
213: */
214: private String processName = null;
215:
216: /**
217: * The attribute <code>processMgrName</code>. It identifies
218: * the name of the process manager associated with the event.
219: * If the event is associated to a process, this is the manager of the
220: * process. If the event is associated to an activity, it is the manager
221: * of the process that contains the activity.
222: */
223: private String processMgrName = null;
224:
225: /**
226: * The attribute <code>processMgrVersion</code>. It identifies
227: * the version of the process manager associated with the event.
228: * If the event is associated to a process, this is the manager of the
229: * process. If the event is associated to an activity, it is the manager
230: * of the process that contains the activity.
231: */
232: private String processMgrVersion = null;
233:
234: /**
235: * If <code>true</code> the event will not be processed
236: * (i.e. fed back to the engine) when retrieved from the event queue.
237: */
238: private boolean skip = false;
239:
240: /**
241: * The audit event selection of the event source.
242: */
243: private int auditEventSelection = ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS;
244:
245: /**
246: * If <code>true</code> the event will be stored.
247: */
248: private boolean store = false;
249:
250: /**
251: * Create a <code>DefaultAuditEvent</code> related to the given
252: * <code>WfExecutionObject</code>.
253: * @param source the related object.
254: */
255: protected DefaultAuditEvent(Object source) {
256: super ((source == null) ? ((Object) "(no source)")
257: : ((Object) source));
258: }
259:
260: /**
261: * Create a <code>DefaultAuditEvent</code> triggered by a given
262: * <code>WfExecutionObject</code>.
263: * @param baseInfo a <code>WfAuditEvent</code> containing further
264: * information for the event.
265: */
266: protected DefaultAuditEvent(WfAuditEvent baseInfo) {
267: this (baseInfo, false);
268: }
269:
270: /**
271: * Create a <code>DefaultAuditEvent</code> triggered by a given
272: * <code>WfExecutionObject</code>.
273: * @param baseInfo a <code>WfAuditEvent</code> containing further
274: * information for the event.
275: * @param skip if <code>true</code> the event will not be processed
276: * (i.e. fed back to the engine) when retrieved from the event queue.
277: */
278: protected DefaultAuditEvent(WfAuditEvent baseInfo, boolean skip) {
279: this (((DefaultAuditEvent) baseInfo).source,
280: (DefaultAuditEvent) baseInfo);
281: this .skip = skip;
282: }
283:
284: /**
285: * Create a <code>DefaultAuditEvent</code> with the given
286: * <code>WfExecutionObject</code> as source and all other
287: * attributes copied from the given event.
288: * @param source the value for the source attribute.
289: * @param baseInfo a <code>WfAuditEvent</code> containing further
290: * information for the event.
291: */
292: protected DefaultAuditEvent(Object source,
293: DefaultAuditEvent baseInfo) {
294: this (source);
295:
296: // assign data not depending on event type
297: timeStamp = baseInfo.timeStamp;
298: auditEventSelection = baseInfo.auditEventSelection;
299: store = baseInfo.store;
300: skip = baseInfo.skip;
301:
302: // assign attributes
303: eventType = baseInfo.eventType;
304: activityKey = baseInfo.activityKey;
305: activityName = baseInfo.activityName;
306: assignProcessRelatedAttributes(baseInfo.processKey(), baseInfo
307: .processName(), baseInfo.processMgrName(), baseInfo
308: .processMgrVersion());
309: }
310:
311: /**
312: * Creates a new <code>DefaultAuditEvent</code> containing process-related
313: * and activity-related information, only.
314: * @param source the activity which is the originator of the audit event.
315: * @param eventType the event's type identifier.
316: * @param actKey the attribute <code>activityKey</code>.
317: * @param actName the attribute <code>activityName</code>.
318: * @param processInfo a <code>WfAuditEvent</code> containing
319: * process-related information about the process that contains the
320: * activity.
321: */
322: public DefaultAuditEvent(WfActivity source, String eventType,
323: String actKey, String actName, WfAuditEvent processInfo) {
324: this (
325: source,
326: eventType,
327: new Date(),
328: processInfo.processKey(),
329: processInfo.processName(),
330: processInfo.processMgrName(),
331: processInfo.processMgrVersion(),
332: ((DefaultAuditEvent) processInfo).auditEventSelection(),
333: ((DefaultAuditEvent) processInfo).store(), true);
334:
335: // validate event type
336: if (eventType != null
337: && (!eventType.equals(ACTIVITY_STATE_CHANGED))
338: && (!eventType.equals(ACTIVITY_ASSIGNMENT_CHANGED))
339: && (!eventType.equals(ACTIVITY_RESULT_CHANGED))
340: && (!eventType.equals(ACTIVITY_CONTEXT_CHANGED))
341: && (!eventType
342: .equals(ImplCompleteAuditEvent.TOOL_COMPLETE))) {
343: throw new IllegalArgumentException(
344: "Invalid 'eventType' supplied.");
345: }
346:
347: // assign attributes
348: activityKey = actKey;
349: activityName = actName;
350: }
351:
352: /**
353: * Creates a new <code>DefaultAuditEvent</code> containing process-related
354: * and activity-related information.
355: * This descriptor's intention is for re-creation usage, only.
356: * @param source the activity which is the originator of the audit event.
357: * @param eventType the event's type identifier.
358: * @param timestamp the event time.
359: * @param actKey the attribute <code>activityKey</code>.
360: * @param actName the attribute <code>activityName</code>.
361: * @param processKey the attribute <code>processKey</code>.
362: * @param processName the attribute <code>processName</code>.
363: * @param processMgrName the attribute <code>processMgrName</code>.
364: * @param processMgrVersion the attribute <code>processMgrVersion</code>.
365: * @param auditEventSelection the audit event selection of source
366: * @param store if <code>true</code> the event will be stored in
367: * the database
368: */
369: public DefaultAuditEvent(WfActivity source, String eventType,
370: Date timestamp, String actKey, String actName,
371: String processKey, String processName,
372: String processMgrName, String processMgrVersion,
373: int auditEventSelection, boolean store) {
374: this (source, eventType, timestamp, processKey, processName,
375: processMgrName, processMgrVersion, auditEventSelection,
376: store, false);
377:
378: // validate event type
379: if (eventType != null
380: && (!eventType.equals(ACTIVITY_STATE_CHANGED))
381: && (!eventType.equals(ACTIVITY_ASSIGNMENT_CHANGED))
382: && (!eventType.equals(ACTIVITY_RESULT_CHANGED))
383: && (!eventType.equals(ACTIVITY_CONTEXT_CHANGED))
384: && (!eventType
385: .equals(ImplCompleteAuditEvent.TOOL_COMPLETE))) {
386: throw new IllegalArgumentException(
387: "Invalid 'eventType' supplied.");
388: }
389:
390: // assign attributes
391: activityKey = actKey;
392: activityName = actName;
393: }
394:
395: /**
396: * Creates a new <code>DefaultAuditEvent</code> containing process-related
397: * information, only.
398: * @param source the process which is the originator of the audit event
399: * @param eventType the event's type identifier
400: * @param processKey the attribute <code>processKey</code>.
401: * @param processName the attribute <code>processName</code>.
402: * @param processMgrName the attribute <code>processMgrName</code>.
403: * @param processMgrVersion the attribute <code>processMgrVersion</code>.
404: * @param auditEventSelection the audit event selection of source
405: * @param store if <code>true</code> the event will be stored in
406: * the database
407: */
408:
409: public DefaultAuditEvent(WfProcess source, String eventType,
410: String processKey, String processName,
411: String processMgrName, String processMgrVersion,
412: int auditEventSelection, boolean store) {
413: this (source, eventType, new Date(), processKey, processName,
414: processMgrName, processMgrVersion, auditEventSelection,
415: store);
416: }
417:
418: /**
419: * Creates a new <code>DefaultAuditEvent</code> containing process-related
420: * information, only.
421: * @param source the process which is the originator of the audit event
422: * @param eventType the event's type identifier
423: * @param timestamp the event's timestamp
424: * @param processKey the attribute <code>processKey</code>.
425: * @param processName the attribute <code>processName</code>.
426: * @param processMgrName the attribute <code>processMgrName</code>.
427: * @param processMgrVersion the attribute <code>processMgrVersion</code>.
428: * @param auditEventSelection the audit event selection of source
429: * @param store if <code>true</code> the event will be stored in
430: * the database
431: */
432:
433: public DefaultAuditEvent(WfProcess source, String eventType,
434: Date timestamp, String processKey, String processName,
435: String processMgrName, String processMgrVersion,
436: int auditEventSelection, boolean store) {
437: this (source, eventType, timestamp, processKey, processName,
438: processMgrName, processMgrVersion, auditEventSelection,
439: store, false);
440:
441: // validate event type
442: if (eventType != null
443: && (!eventType.equals(PROCESS_STATE_CHANGED))
444: && (!eventType.equals(PROCESS_CREATED))
445: && (!eventType.equals(PROCESS_CONTEXT_CHANGED))) {
446: throw new IllegalArgumentException(
447: "Invalid 'eventType' supplied.");
448: }
449: }
450:
451: /**
452: * Create a <code>DefaultAuditEvent</code> triggered by a given
453: * <code>WfExecutionObject</code>.
454: * @param source the process which is the originator of the audit event
455: * @param et the event's type identifier
456: * @param ts the event's timestamp
457: * @param processKey the attribute <code>processKey</code>.
458: * @param processName the attribute <code>processName</code>.
459: * @param processMgrName the attribute <code>processMgrName</code>.
460: * @param processMgrVersion the attribute <code>processMgrVersion</code>.
461: * @param auditEventSelection the audit event selection of source
462: * @param store if <code>true</code> the event will be stored in
463: * the database
464: * @param verifySource if <code>true</code> <code>source</code> may not be
465: * <code>null</code>.
466: */
467: private DefaultAuditEvent(WfExecutionObject source, String et,
468: Date ts, String processKey, String processName,
469: String processMgrName, String processMgrVersion,
470: int auditEventSelection, boolean store, boolean verifySource) {
471: this (source);
472:
473: // check mandatory parameters
474: if (verifySource && source == null) {
475: throw new IllegalArgumentException(
476: "The argument 'source' MUST be supplied.");
477: }
478:
479: // assign data not depending on event type
480: timeStamp = ts;
481:
482: // assign attributes
483: eventType = et;
484: assignProcessRelatedAttributes(processKey, processName,
485: processMgrName, processMgrVersion);
486: this .auditEventSelection = auditEventSelection;
487: this .store = store;
488: }
489:
490: private void writeObject(ObjectOutputStream stream)
491: throws IOException {
492: // "source" is transient. So we have to save it explicitly.
493: // The additional wrapper for deferred deserialization is a
494: // workaround for a classloader problem.
495: if (source != null) {
496: ByteArrayOutputStream bos = new ByteArrayOutputStream();
497: ObjectOutputStream oos = new ObjectOutputStream(bos);
498: oos.writeObject(source);
499: marshalledSource = bos.toByteArray();
500: }
501: stream.defaultWriteObject();
502: }
503:
504: private void readObject(ObjectInputStream stream)
505: throws IOException, ClassNotFoundException {
506: stream.defaultReadObject();
507: }
508:
509: /**
510: * Override <code>getSource</code> to do deferred unmarshalling
511: * if required.
512: */
513: public Object getSource() {
514: if (source != null) {
515: return source;
516: }
517: if (marshalledSource != null) {
518: try {
519: ObjectInputStream ois = new ObjectInputStream(
520: new ByteArrayInputStream(marshalledSource));
521: source = ois.readObject();
522: marshalledSource = null;
523: return source;
524: } catch (IOException e) {
525: throw (IllegalStateException) (new IllegalStateException(
526: "Cannot deserialize source: " + e.getMessage())
527: .initCause(e));
528: } catch (ClassNotFoundException e) {
529: throw (IllegalStateException) (new IllegalStateException(
530: "Cannot deserialize source: " + e.getMessage())
531: .initCause(e));
532: }
533: }
534: return null;
535: }
536:
537: /**
538: * Assigns the given attribute values.
539: * @param processKey the attribute <code>processKey</code>.
540: * @param processName the attribute <code>processName</code>.
541: * @param processMgrName the attribute <code>processMgrName</code>.
542: * @param processMgrVersion the attribute <code>processMgrVersion</code>.
543: */
544: private void assignProcessRelatedAttributes(String processKey,
545: String processName, String processMgrName,
546: String processMgrVersion) {
547: this .processKey = processKey;
548: this .processName = processName;
549: this .processMgrName = processMgrName;
550: this .processMgrVersion = processMgrVersion;
551: }
552:
553: /**
554: * Return a new audit event object with the source attribute
555: * replaced with the given object. Derived classes must override
556: * this method and return an object of the derived type.
557: * @param source the new source attribute.
558: * @return the new audit event.
559: */
560: public DefaultAuditEvent replaceSource(Object source) {
561: return new DefaultAuditEvent(source, this );
562: }
563:
564: /**
565: * Returns the current value of the attribute <code>source</code>.
566: * The source of the event is the <code>WfExceutionObject</code>
567: * associated to the event, i.e. that triggered the event.
568: * @return the current value of the attribute.
569: * @throws SourceNotAvailableException if the source is not available.
570: */
571: public WfExecutionObject source()
572: throws SourceNotAvailableException {
573: Object source = getSource();
574: if (source == null || !(source instanceof WfExecutionObject)) {
575: throw new SourceNotAvailableException();
576: }
577: return (WfExecutionObject) source;
578: }
579:
580: /**
581: * Returns the audit event selection of the source of this event.
582: * @return the audit event selection
583: */
584: public int auditEventSelection() {
585: return auditEventSelection;
586: }
587:
588: /**
589: * Indicates if the event is to be stored in the database.
590: * @return <code>true</code> if the event is not to be processed.
591: */
592: public boolean store() {
593: return store;
594: }
595:
596: /**
597: * Indicates if the event is to be processed (i.e. fed back to the
598: * event queue).
599: * @return <code>true</code> if the event is not to be processed.
600: */
601: public boolean skip() {
602: return skip;
603: }
604:
605: /**
606: * Returns the current value of the attribute <code>timeStamp</code>.
607: * @return the current value of the attribute.
608: */
609: public Date timeStamp() {
610: return timeStamp;
611: }
612:
613: /**
614: * Returns the current value of the attribute <code>eventType</code>.
615: * @return the current value of the attribute.
616: */
617: public String eventType() {
618: return eventType;
619: }
620:
621: /**
622: * Returns the current value of the attribute <code>activityKey</code>.
623: * @return the current value of the attribute.
624: */
625: public String activityKey() {
626: return activityKey;
627: }
628:
629: /**
630: * Returns the current value of the attribute <code>activityName</code>.
631: * @return the current value of the attribute.
632: */
633: public String activityName() {
634: return activityName;
635: }
636:
637: /**
638: * Returns the current value of the attribute <code>processKey</code>.
639: * @return the current value of the attribute.
640: */
641: public String processKey() {
642: return processKey;
643: }
644:
645: /**
646: * Returns the current value of the attribute <code>processName</code>.
647: * @return the current value of the attribute.
648: */
649: public String processName() {
650: return processName;
651: }
652:
653: /**
654: * Returns the current value of the attribute
655: * <code>processMgrName</code>.
656: * @return the current value of the attribute.
657: */
658: public String processMgrName() {
659: return processMgrName;
660: }
661:
662: /**
663: * Returns the current value of the attribute
664: * <code>processMgrVersion</code>.
665: * @return the current value of the attribute.
666: */
667: public String processMgrVersion() {
668: return processMgrVersion;
669: }
670:
671: /**
672: * Returns a textual representation of the event.
673: * @return the textual representation
674: */
675: public String toString() {
676: return "eventType=" + eventType + ", activityKey="
677: + activityKey + ", activityName=" + activityName
678: + ", processKey=" + processKey + ", processName="
679: + processName + ", processManagerName="
680: + processMgrName + ", processManagerVersion="
681: + processMgrVersion + ", auditEventSelection="
682: + auditEventSelection + ", store=" + store + ", skip="
683: + skip;
684: }
685: }
|