001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)WorkThread.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.engine.sequencing.framework.threads;
030:
031: import com.sun.jbi.engine.sequencing.SequencingEngineContext;
032:
033: import java.util.logging.Logger;
034:
035: /**
036: * This class executes the command in its thread. The class is always a part of
037: * a threadpool and cannot exist on its own.
038: *
039: * @author Sun Microsystems, Inc.
040: */
041: class WorkThread implements Runnable {
042: /**
043: * Default Thread sleep time in milliseconds.
044: */
045: private static final int DEFAULT_THREAD_SLEEP_TIME = 100;
046:
047: /**
048: * Thread sleep time in milliseconds.
049: */
050: private static int sThreadSleeptime = DEFAULT_THREAD_SLEEP_TIME;
051:
052: /**
053: * Container for holding the command to be executed in this thread.
054: */
055: private Command mCurrentCommand;
056:
057: /**
058: * Internal handle to the logger instance.
059: */
060: private Logger mLog;
061:
062: /**
063: * Flag to hold the state of the Thread. Valid states are "INIT", "READY",
064: * "PROCESS" and "STOP"
065: */
066: private String mState;
067:
068: /**
069: * Internal handle to the thread in which this runnable object is running.
070: */
071: private Thread mThread;
072:
073: /**
074: * Internal handle to WorkThreadPool.
075: */
076: private WorkThreadPool mThreadPool;
077:
078: /**
079: * A flag which indicates whether the thread should continue processing or
080: * not.
081: */
082: private boolean mContinue;
083:
084: /**
085: * Creates a new instance of WorkThread.
086: *
087: * @param workThreadPool - worker thread pool parent
088: */
089: WorkThread(WorkThreadPool workThreadPool) {
090: mThreadPool = workThreadPool;
091: mLog = SequencingEngineContext.getInstance().getLogger();
092: setState("INIT");
093: }
094:
095: /**
096: * Sets the log file.
097: *
098: * @param logFile log file.
099: */
100: public void setLogger(String logFile) {
101: mLog = mLog.getLogger(logFile);
102: }
103:
104: /**
105: * Gets the thread name
106: *
107: * @return thread name.
108: */
109: public String getName() {
110: return mThread.getName();
111: }
112:
113: /**
114: * Sets the sleep time for the thread.
115: *
116: * @param time in millieseconds
117: */
118: public void setSleepTime(int time) {
119: sThreadSleeptime = time;
120: }
121:
122: /**
123: * The method polls the container for a new work when the thread is ready
124: * to do work. This is indicated by the method doWork(). If there is new
125: * work, it processes the command in its thread. Once the command has been
126: * processed, it clears its work container and notifies the thread pool
127: * that it is now free. The method will clean up the thread and shut
128: * itself down when its state is set to "STOP".
129: */
130: public void run() {
131: mThread = Thread.currentThread();
132: mLog.info("Running thread " + mThread.getName());
133: mContinue = true;
134:
135: while (mContinue) {
136: if (isWorkAssigned()) {
137: try {
138: processCommand();
139: } catch (Throwable th) {
140: mLog.info("The command failed to execute");
141: th.printStackTrace();
142: }
143:
144: clearCommand();
145: mThreadPool.releaseThread(this );
146: }
147:
148: try {
149: Thread.sleep(sThreadSleeptime);
150: } catch (InterruptedException interruptException) {
151: // someone must have interrupted this thread
152: // do nothing
153: mLog.info("Received an interrupt signal in "
154: + mThread.getName());
155: }
156: }
157:
158: try {
159: mLog.info("Thread " + mThread.getName()
160: + " has been stopped");
161: } catch (Exception e) {
162: ;
163: }
164: }
165:
166: /**
167: * Assigns the command to this thread.
168: *
169: * @param command - command instance.
170: */
171: synchronized void setCommand(Command command) {
172: if (mCurrentCommand == null) {
173: mCurrentCommand = command;
174: }
175: }
176:
177: /**
178: * Gets the command associated with this thread.
179: *
180: * @return the command associated with the thread
181: */
182: synchronized Command getCommand() {
183: return mCurrentCommand;
184: }
185:
186: /**
187: * Sets the State of the Worker Thread.
188: *
189: * @param state - worker thread state.
190: */
191: void setState(String state) {
192: mState = state;
193: }
194:
195: /**
196: * Returns a boolean indicating if work has been assigned to this thread.
197: *
198: * @return true if work has been allocated to this thread; otherwise false.
199: */
200: synchronized boolean isWorkAssigned() {
201: return (mCurrentCommand != null);
202: }
203:
204: /**
205: * Clears the command associated with the thread.
206: */
207: void clearCommand() {
208: mCurrentCommand = null;
209: }
210:
211: /**
212: * Processes the command in this thread.
213: */
214: void processCommand() {
215: mCurrentCommand.execute();
216: }
217:
218: /**
219: * Stops the worker thread.
220: *
221: * @throws IllegalStateException exception.
222: */
223: void stop() {
224: if (mContinue) {
225: mLog.fine("Shutting down thread " + getName());
226: mContinue = false;
227:
228: try {
229: // Interrupt the thread so that it can shutdown quickly
230: // This will also enable the command implementation to cleanup quickly.
231: mThread.interrupt();
232: } catch (SecurityException securityException) {
233: mLog.warning("Could not interrupt thread");
234: mLog.warning("Details : "
235: + securityException.toString());
236: }
237:
238: try {
239: //Wait for the thread to stop
240: mThread.join();
241: } catch (InterruptedException exp) {
242: ; // do nothing
243: }
244:
245: mThread = null;
246: } else {
247: throw new IllegalStateException("Thread is not running");
248: }
249: }
250: }
|