001: /*
002: * The contents of this file are subject to the Sapient Public License
003: * Version 1.0 (the "License"); you may not use this file except in compliance
004: * with the License. You may obtain a copy of the License at
005: * http://carbon.sf.net/License.html.
006: *
007: * Software distributed under the License is distributed on an "AS IS" basis,
008: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
009: * the specific language governing rights and limitations under the License.
010: *
011: * The Original Code is The Carbon Component Framework.
012: *
013: * The Initial Developer of the Original Code is Sapient Corporation
014: *
015: * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
016: */
017:
018: package org.sape.carbon.services.threadpool;
019:
020: import org.apache.commons.logging.Log;
021: import org.apache.commons.logging.LogFactory;
022:
023: import org.sape.carbon.core.exception.ExceptionUtility;
024:
025: /**
026: * Besides supplying the functionality described by the TaskInfo interface,
027: * this implementation also is responsible for making callbacks using the
028: * TaskCallback interface if a callback has been specified.
029: *
030: * Copyright 2003 Sapient
031: * @since carbon 2.1
032: * @author Douglas Voet, Nov 20, 2003
033: * @version $Revision: 1.6 $($Author: dvoet $ / $Date: 2003/11/20 18:49:59 $)
034: */
035: public class TaskInfoImpl implements TaskInfo {
036: private Log log = LogFactory.getLog(this .getClass());
037:
038: private Runnable task;
039: private TaskStatusEnum status = TaskStatusEnum.PENDING;
040: private Throwable taskFailureCause = null;
041: private String taskName;
042: private String threadPoolName;
043: private TaskCallback callback;
044:
045: protected TaskInfoImpl(Runnable task, String taskName,
046: TaskCallback callback, String threadPoolName) {
047:
048: this .task = task;
049: this .taskName = taskName;
050: this .callback = callback;
051: this .threadPoolName = threadPoolName;
052:
053: if (log.isTraceEnabled()) {
054: log.trace("Queuing task, thread pool ["
055: + this .threadPoolName + "], task [" + this .taskName
056: + "]");
057: }
058: }
059:
060: public synchronized Throwable getFailureCause() {
061: return this .taskFailureCause;
062: }
063:
064: public synchronized TaskStatusEnum getStatus() {
065: return this .status;
066: }
067:
068: public String getTaskName() {
069: return this .taskName;
070: }
071:
072: public synchronized void waitUntilExecuted()
073: throws InterruptedException {
074:
075: waitUntilExecuted(0);
076: }
077:
078: public synchronized void waitUntilExecuted(long timeout)
079: throws InterruptedException {
080:
081: if (this .status == TaskStatusEnum.PENDING
082: || this .status == TaskStatusEnum.EXECUTING) {
083:
084: this .wait(timeout);
085: }
086: }
087:
088: /**
089: * This method is called when a task fails. The status is set to
090: * TaskStatusEnum.FAILED, all listeners are notified and the callback
091: * is called.
092: *
093: * @param cause
094: */
095: public void setFailure(Throwable cause) {
096: if (log.isInfoEnabled()) {
097: log.info("Task failed, thread pool [" + this .threadPoolName
098: + "], task [" + this .taskName
099: + "], failure cause ["
100: + ExceptionUtility.printStackTracesToString(cause)
101: + "]");
102: }
103:
104: synchronized (this ) {
105: this .status = TaskStatusEnum.FAILED;
106: this .taskFailureCause = cause;
107: this .notifyAll();
108: }
109:
110: callCallback(false);
111: }
112:
113: /**
114: * This method is called when a task succeeds. The status is set to
115: * TaskStatusEnum.SUCCESS, all listeners are notified and the callback
116: * is called.
117: */
118: public void setSuccess() {
119: if (log.isTraceEnabled()) {
120: log.trace("Task executed successfully, thread pool ["
121: + this .threadPoolName + "], task [" + this .taskName
122: + "]");
123: }
124:
125: synchronized (this ) {
126: this .status = TaskStatusEnum.SUCCESS;
127: this .notifyAll();
128: }
129:
130: callCallback(true);
131: }
132:
133: /**
134: * This method is called when a task begins execution. The status is set to
135: * TaskStatusEnum.EXECUTING.
136: */
137: public synchronized void setExecuting() {
138: if (log.isTraceEnabled()) {
139: log.trace("Executing task, thread pool ["
140: + this .threadPoolName + "], task [" + this .taskName
141: + "]");
142: }
143:
144: this .status = TaskStatusEnum.EXECUTING;
145: }
146:
147: /** called by the DefaultThreadPoolImpl to get the task to execute */
148: public Runnable getTask() {
149: return this .task;
150: }
151:
152: public synchronized String toString() {
153: StringBuffer buf = new StringBuffer();
154:
155: buf.append("Task [");
156: buf.append(this .taskName == null ? "Unnamed Task"
157: : this .taskName);
158: buf.append("], current state [");
159: buf.append(this .status);
160: buf.append("]");
161:
162: if (this .taskFailureCause != null) {
163: buf.append(", failure cause: ");
164: buf.append(ExceptionUtility
165: .printStackTracesToString(this .taskFailureCause));
166: }
167: return buf.toString();
168: }
169:
170: /** helper method that calls the callback */
171: private void callCallback(boolean success) {
172: if (this .callback != null) {
173:
174: if (log.isTraceEnabled()) {
175: log.trace("Notifying callback, thread pool ["
176: + this .threadPoolName + "], task ["
177: + this .taskName + "]");
178: }
179:
180: try {
181: if (success) {
182: this .callback.taskSucceeded(this );
183: } else {
184: this .callback.taskFailed(this );
185: }
186: } catch (RuntimeException re) {
187: if (log.isErrorEnabled()) {
188: log.error(
189: "Caught RuntimeException in callback, thread pool ["
190: + this .threadPoolName + "], task ["
191: + this .taskName + "]", re);
192: }
193: }
194: }
195: }
196:
197: }
|