001: /*
002: * SSHTools - Java SSH2 API
003: *
004: * Copyright (C) 2002-2003 Lee David Painter and Contributors.
005: *
006: * Contributions made by:
007: *
008: * Brett Smith
009: * Richard Pernavas
010: * Erwin Bolwidt
011: *
012: * This program is free software; you can redistribute it and/or
013: * modify it under the terms of the GNU General Public License
014: * as published by the Free Software Foundation; either version 2
015: * of the License, or (at your option) any later version.
016: *
017: * This program is distributed in the hope that it will be useful,
018: * but WITHOUT ANY WARRANTY; without even the implied warranty of
019: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: * GNU General Public License for more details.
021: *
022: * You should have received a copy of the GNU General Public License
023: * along with this program; if not, write to the Free Software
024: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
025: */
026: package com.sshtools.j2ssh.transport;
027:
028: import com.sshtools.j2ssh.SshThread;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032:
033: import java.io.IOException;
034:
035: /**
036: * <p>
037: * Extends the simple <code>Service</code> class to provide an asyncronous
038: * messaging service for the transport protocol.
039: * </p>
040: *
041: * @author Lee David Painter
042: * @version $Revision: 1.28 $
043: *
044: * @since 0.2.0
045: */
046: public abstract class AsyncService extends Service implements Runnable {
047: private static Log log = LogFactory.getLog(Service.class);
048:
049: /** */
050: protected SshThread thread;
051:
052: /**
053: * <p>
054: * Constructs an asyncronous service.
055: * </p>
056: *
057: * @param serviceName the name of the service
058: *
059: * @since 0.2.0
060: */
061: public AsyncService(String serviceName) {
062: super (serviceName);
063: }
064:
065: /**
066: * <p>
067: * Implements the abstract <code>Service</code> method and starts the
068: * service thread.
069: * </p>
070: *
071: * @throws IOException if an IO error occurs
072: *
073: * @since 0.2.0
074: */
075: protected void onStart() throws IOException {
076: if (Thread.currentThread() instanceof SshThread) {
077: thread = ((SshThread) Thread.currentThread()).cloneThread(
078: this , getServiceName());
079: } else {
080: thread = new SshThread(this , getServiceName(), true);
081: }
082:
083: log.info("Starting " + getServiceName() + " service thread");
084: thread.start();
085: }
086:
087: /**
088: * <p>
089: * Implements the asyncronous services message loop.
090: * </p>
091: *
092: * @since 0.2.0
093: */
094: public final void run() {
095: int[] messageFilter = getAsyncMessageFilter();
096: state.setValue(ServiceState.SERVICE_STARTED);
097:
098: SshMessage msg = null;
099:
100: while ((state.getValue() == ServiceState.SERVICE_STARTED)
101: && transport.isConnected()) {
102: try {
103: // Get the next message from the message store
104: msg = messageStore.getMessage(messageFilter);
105:
106: if (state.getValue() == ServiceState.SERVICE_STOPPED) {
107: break;
108: }
109:
110: if (log.isDebugEnabled()) {
111: log.debug("Routing " + msg.getMessageName());
112: }
113:
114: onMessageReceived(msg);
115:
116: if (log.isDebugEnabled()) {
117: log.debug("Finished processing "
118: + msg.getMessageName());
119: }
120: } catch (MessageStoreEOFException eof) {
121: stop();
122: } catch (Exception ex) {
123: if ((state.getValue() != ServiceState.SERVICE_STOPPED)
124: && transport.isConnected()) {
125: log.fatal("Service message loop failed!", ex);
126: stop();
127: }
128: }
129: }
130:
131: onStop();
132: log.info(getServiceName() + " thread is exiting");
133: thread = null;
134: }
135:
136: /**
137: * <p>
138: * The service thread calls this method when the thread is exiting.
139: * </p>
140: *
141: * @since 0.2.0
142: */
143: protected abstract void onStop();
144:
145: /**
146: * <p>
147: * Implement this method by returning the message ids of the asyncrounous
148: * messages your implementation wants to receive.
149: * </p>
150: *
151: * @return an int array of message ids
152: *
153: * @since 0.2.0
154: */
155: protected abstract int[] getAsyncMessageFilter();
156:
157: /**
158: * <p>
159: * Called by the service thread when an asyncronous message is received.
160: * </p>
161: *
162: * @param msg the message received
163: *
164: * @throws IOException if an IO error occurs
165: *
166: * @since 0.2.0
167: */
168: protected abstract void onMessageReceived(SshMessage msg)
169: throws IOException;
170: }
|