001: // Copyright (c) 2004-2005 Sun Microsystems Inc., All Rights Reserved.
002:
003: /*
004: * WorkThread.java
005: *
006: * SUN PROPRIETARY/CONFIDENTIAL
007: * This software is the proprietary information of Sun Microsystems, Inc.
008: * Use is subject to license terms
009: */
010: package com.sun.jbi.binding.file.framework;
011:
012: import com.sun.jbi.binding.file.FileBindingContext;
013: import com.sun.jbi.binding.file.FileBindingResources;
014: import com.sun.jbi.binding.file.util.StringTranslator;
015:
016: import java.util.logging.Logger;
017:
018: /**
019: * This class executes the command in its thread. The class is always a part of
020: * a threadpool and cannot exist on its own.
021: *
022: * @author Sun Microsystems, Inc.
023: */
024: class WorkThread implements Runnable, FileBindingResources {
025: /**
026: * Default Thread sleep time in milliseconds.
027: */
028: private static final int DEFAULT_THREAD_SLEEP_TIME = 100;
029:
030: /**
031: * Thread sleep time in milliseconds.
032: */
033: private static int sThreadSleeptime = DEFAULT_THREAD_SLEEP_TIME;
034:
035: /**
036: * Container for holding the command to be executed in this thread.
037: */
038: private Command mCurrentCommand;
039:
040: /**
041: * Internal handle to the logger instance.
042: */
043: private Logger mLog;
044:
045: /**
046: * Helper class for i18n.
047: */
048: private StringTranslator mTranslator;
049:
050: /**
051: * Internal handle to the thread in which this runnable object is running.
052: */
053: private Thread mThread;
054:
055: /**
056: * Internal handle to WorkThreadPool.
057: */
058: private WorkThreadPool mThreadPool;
059:
060: /**
061: * A flag which indicates whether the thread should continue processing or
062: * not.
063: */
064: private boolean mContinue;
065:
066: /**
067: * Creates a new instance of WorkThread.
068: *
069: * @param workThreadPool - worker thread pool parent
070: */
071: WorkThread(WorkThreadPool workThreadPool) {
072: mThreadPool = workThreadPool;
073: mLog = FileBindingContext.getInstance().getLogger();
074: mTranslator = new StringTranslator();
075: }
076:
077: /**
078: * Sets the log file.
079: *
080: * @param logFile log file.
081: */
082: public void setLogger(String logFile) {
083: mLog = mLog.getLogger(logFile);
084: }
085:
086: /**
087: * Gets the thread name
088: *
089: * @return thread name.
090: */
091: public String getName() {
092: return mThread.getName();
093: }
094:
095: /**
096: * Sets the sleep time for the thread.
097: *
098: * @param time in millieseconds
099: */
100: public void setSleepTime(int time) {
101: sThreadSleeptime = time;
102: }
103:
104: /**
105: * The method polls the container for a new work when the thread is ready
106: * to do work. This is indicated by the method doWork(). If there is new
107: * work, it processes the command in its thread. Once the command has been
108: * processed, it clears its work container and notifies the thread pool
109: * that it is now free. The method will clean up the thread and shut
110: * itself down when its state is set to "STOP".
111: */
112: public void run() {
113: mThread = Thread.currentThread();
114: mLog.info(mTranslator.getString(FBC_RUNNING_THREAD, mThread
115: .getName()));
116: mContinue = true;
117:
118: while (mContinue) {
119: if (isWorkAssigned()) {
120: try {
121: processCommand();
122: } catch (Throwable th) {
123: mLog.severe(mTranslator
124: .getString(FBC_THREADS_COMMAND_FAILED));
125: th.printStackTrace();
126: }
127:
128: clearCommand();
129: mThreadPool.releaseThread(this );
130: }
131:
132: try {
133: Thread.sleep(sThreadSleeptime);
134: } catch (InterruptedException interruptException) {
135: mLog.info(mTranslator.getString(
136: FBC_THREADS_INTERUPPTED, mThread.getName()));
137: }
138: }
139:
140: try {
141: mLog.fine(mTranslator.getString(FBC_THREADS_STOPPED,
142: mThread.getName()));
143: } catch (Exception e) {
144: ;
145: }
146: }
147:
148: /**
149: * Assigns the command to this thread.
150: *
151: * @param command - command instance.
152: */
153: synchronized void setCommand(Command command) {
154: if (mCurrentCommand == null) {
155: mCurrentCommand = command;
156: }
157: }
158:
159: /**
160: * Gets the command associated with this thread.
161: *
162: * @return the command associated with the thread
163: */
164: synchronized Command getCommand() {
165: return mCurrentCommand;
166: }
167:
168: /**
169: * Returns a boolean indicating if work has been assigned to this thread.
170: *
171: * @return true if work has been allocated to this thread; otherwise false.
172: */
173: synchronized boolean isWorkAssigned() {
174: return (mCurrentCommand != null);
175: }
176:
177: /**
178: * Clears the command associated with the thread.
179: */
180: void clearCommand() {
181: mCurrentCommand = null;
182: }
183:
184: /**
185: * Processes the command in this thread.
186: */
187: void processCommand() {
188: mCurrentCommand.execute();
189: }
190:
191: /**
192: * Stops the worker thread.
193: *
194: * @throws IllegalStateException
195: */
196: void stop() {
197: if (mContinue) {
198: mLog.fine(mTranslator.getString(FBC_THREADS_SHUTDOWN,
199: getName()));
200: mContinue = false;
201:
202: try {
203: mThread.interrupt();
204: } catch (SecurityException securityException) {
205: mLog.warning(mTranslator.getString(
206: FBC_THREADS_CANNOT_INTERRUPT, securityException
207: .toString()));
208: }
209:
210: try {
211: mThread.join();
212: } catch (InterruptedException exp) {
213: ;
214: }
215:
216: mThread = null;
217: } else {
218: throw new IllegalStateException("Thread is not running");
219: }
220: }
221: }
|