1 /*
2 * SSHTools - Java SSH2 API
3 *
4 * Copyright (C) 2002-2003 Lee David Painter and Contributors.
5 *
6 * Contributions made by:
7 *
8 * Brett Smith
9 * Richard Pernavas
10 * Erwin Bolwidt
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26 package com.sshtools.j2ssh.transport;
27
28 import com.sshtools.j2ssh.SshThread;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 import java.io.IOException;
34
35
36 /**
37 * <p>
38 * Extends the simple <code>Service</code> class to provide an asyncronous
39 * messaging service for the transport protocol.
40 * </p>
41 *
42 * @author Lee David Painter
43 * @version $Revision: 1.28 $
44 *
45 * @since 0.2.0
46 */
47 public abstract class AsyncService extends Service implements Runnable {
48 private static Log log = LogFactory.getLog(Service.class);
49
50 /** */
51 protected SshThread thread;
52
53 /**
54 * <p>
55 * Constructs an asyncronous service.
56 * </p>
57 *
58 * @param serviceName the name of the service
59 *
60 * @since 0.2.0
61 */
62 public AsyncService(String serviceName) {
63 super(serviceName);
64 }
65
66 /**
67 * <p>
68 * Implements the abstract <code>Service</code> method and starts the
69 * service thread.
70 * </p>
71 *
72 * @throws IOException if an IO error occurs
73 *
74 * @since 0.2.0
75 */
76 protected void onStart() throws IOException {
77 if (Thread.currentThread() instanceof SshThread) {
78 thread = ((SshThread) Thread.currentThread()).cloneThread(this,
79 getServiceName());
80 } else {
81 thread = new SshThread(this, getServiceName(), true);
82 }
83
84 log.info("Starting " + getServiceName() + " service thread");
85 thread.start();
86 }
87
88 /**
89 * <p>
90 * Implements the asyncronous services message loop.
91 * </p>
92 *
93 * @since 0.2.0
94 */
95 public final void run() {
96 int[] messageFilter = getAsyncMessageFilter();
97 state.setValue(ServiceState.SERVICE_STARTED);
98
99 SshMessage msg = null;
100
101 while ((state.getValue() == ServiceState.SERVICE_STARTED) &&
102 transport.isConnected()) {
103 try {
104 // Get the next message from the message store
105 msg = messageStore.getMessage(messageFilter);
106
107 if (state.getValue() == ServiceState.SERVICE_STOPPED) {
108 break;
109 }
110
111 if (log.isDebugEnabled()) {
112 log.debug("Routing " + msg.getMessageName());
113 }
114
115 onMessageReceived(msg);
116
117 if (log.isDebugEnabled()) {
118 log.debug("Finished processing " + 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 }