Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/altara/mars/engine/SendExpectClient.java


1   /* MARS Network Monitoring Engine
2      Copyright (C) 1999 Brian H. Trammell
3      Copyright (C) 2002 Leapfrog Research & Development, LLC
4   
5     This program is free software; you can redistribute it and/or
6     modify it under the terms of the GNU General Public License
7     as published by the Free Software Foundation; either version 2
8     of the License, or (at your option) any later version.
9   
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14    
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, it is available at 
17    http:///www.gnu.org/copyleft/gpl.html, or by writing to the
18    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA  02111-1307, USA.
20  */
21  
22  package org.altara.mars.engine;
23  
24  import org.apache.oro.text.regex.*;
25  import org.altara.mars.*;
26  import java.util.*;
27  import java.net.*;
28  import java.io.*;
29  
30  public class SendExpectClient implements Serializable {
31    // for numbering child threads
32    private static int nctid = 0;
33    // maximum expect length in bytes; this is a hack used to keep
34    // a garbage-spewing service (like SSH) from causing problems.
35    private static final int MAXRECV_LEN = 512;
36  
37    private static final char ENDSTREAM = (char)0xFFFF;
38  
39    private transient InetAddress host;
40    private transient int port;
41    private transient long timeout;
42    private List script;
43  
44    private transient Socket sock;    
45    private transient Writer writer;  
46    private transient Reader reader;
47    private transient StringBuffer buffer;  
48    private transient int bufptr;
49  
50    private transient Perl5Matcher matcher;
51  
52    private transient boolean didTimeout;
53    private transient boolean didClose;
54    private transient boolean didFail;
55  
56    public SendExpectClient() {
57      this(null,0,0);
58    }
59  
60    public SendExpectClient(InetAddress host, int port, long timeout) {
61      // store all instance variables for script run
62      setServer(host,port,timeout);
63      // prepare an empty script
64      this.script = new LinkedList();
65    }
66  
67    public void setServer(InetAddress host, int port, long timeout) {
68      this.host = host;
69      this.port = port;
70      this.timeout = timeout;
71    }
72  
73    public void clear() {
74      script.clear();
75    }
76  
77    public void send(Object out) {
78      script.add(new SendStep(out));
79    }
80  
81    public void expect(Object in) {
82      script.add(new ExpectStep(in));
83    }
84  
85    public void expect(Object pass, Object fail) {
86      script.add(new ExpectStep(pass,fail));
87    }
88  
89    public synchronized Status runScript() {
90      // do nothing if no server
91      if (host == null) return new Status(Status.PROBEFAIL);
92      try {
93        // open a socket
94        try {
95          sock = new Socket(host, port);
96        } catch (IOException ex) {
97          return new Status(Status.DOWN);
98        }
99    
100       // set up I/O on the socket
101       try {
102         writer = new OutputStreamWriter(sock.getOutputStream());
103         reader = new InputStreamReader(sock.getInputStream());
104         buffer = new StringBuffer();
105         bufptr = 0;
106       } catch (IOException ex) {
107         return new Status(Status.FASTCLOSE);
108       }
109   
110       // start the helper threads
111       didTimeout = false;
112       didClose = false;
113       didFail = false;
114       new ReaderThread().start();
115       new ReaperThread().start();
116       // get the time for response time logging
117       long startTime = System.currentTimeMillis();
118       // run through the script
119       ListIterator scriptIter = script.listIterator();
120       while (scriptIter.hasNext()) {
121         // run the step
122         ((Step)scriptIter.next()).run();
123         // check for timeout
124         if (didTimeout) {
125           Status out = new Status(Status.TIMEOUT);
126           out.setProperty("received",buffer.toString());
127           return out;
128         }
129         // check for premature closing
130         if (didClose) {
131           Status out = new Status(Status.FASTCLOSE);
132           out.setProperty("received",buffer.toString());
133           return out;
134         }
135         // check for overrun or expect failure
136         if (didFail) {
137           Status out = new Status(Status.UNEXPECTED);
138           out.setProperty("received",buffer.toString());
139           return out;
140         }
141       }
142       // we made it to the end of the script, so we must be up
143       Status out =
144         new Status(Status.UP,System.currentTimeMillis() - startTime);
145       out.setProperty("received",buffer.toString());
146       return out;
147     } finally {
148       // close the socket no matter what
149       try {
150         sock.close();
151       } catch (Exception ignored) {}
152     }
153   }
154 
155   public String dumpScript() {
156     StringBuffer out = new StringBuffer();
157     String hostName = "[prototype]";
158     if (host != null) hostName = host.getHostName();
159     out.append("SEC "+hostName+":"+port+" {\n");
160     ListIterator scriptIter = script.listIterator();
161     while (scriptIter.hasNext()) {
162       // print the step
163       Step nextStep = (Step)scriptIter.next();
164       if (nextStep instanceof SendStep) {
165         Object toSend = ((SendStep)nextStep).toSend;
166         out.append("\t> "+getShortClassName(toSend.getClass())+
167           " "+toSend.toString()+"\n");
168       } else if (nextStep instanceof ExpectStep) {
169         Object pass = ((ExpectStep)nextStep).pass;
170         Object fail = ((ExpectStep)nextStep).fail;
171         if (pass instanceof Perl5Pattern) {
172           out.append("\t< "+getShortClassName(pass.getClass())+
173             " "+((Perl5Pattern)pass).getPattern()+"\n");
174         } else {
175           out.append("\t< "+getShortClassName(pass.getClass())+
176             " "+pass.toString()+"\n");
177         }
178         if (fail != null) {
179           if (fail instanceof Perl5Pattern) {
180             out.append("\tX "+getShortClassName(pass.getClass())+
181               " "+((Perl5Pattern)fail).getPattern()+"\n");
182           } else {
183             out.append("\tX "+getShortClassName(fail.getClass())+
184               " "+fail.toString()+"\n");
185           }
186         }
187       } else {
188         out.append("\tBAD STEP "+nextStep.getClass()+"\n");
189       }
190     }
191     out.append("}\n");
192     return out.toString();
193   }
194 
195   private static String getShortClassName(Class clazz) {
196     String longname = clazz.getName();
197     return longname.substring(longname.lastIndexOf(".")+1);
198   }
199 
200   private class ReaderThread extends Thread {
201     private ReaderThread() {
202       super ("SECReader "+(nctid++));
203     }
204 
205     public void run() {
206       try {
207         while(true) {
208           int c = reader.read();
209           synchronized (buffer) {
210             if (c == -1) {
211               buffer.append(ENDSTREAM);
212               buffer.notify();
213               break;
214             } else if (buffer.length() - bufptr > MAXRECV_LEN) {
215               didFail = true;
216             } else {
217               buffer.append((char)c);
218             }
219             buffer.notify();
220           }
221         }
222       } catch (IOException ex) {
223         didClose = true;
224         synchronized (buffer) {
225           buffer.notify();
226         }
227       }
228     }
229   }
230 
231   private class ReaperThread extends Thread {
232     private ReaperThread() {
233       super ("SECReaper "+(nctid++));
234     }
235 
236     public void run() {  
237       try {
238         Thread.sleep(timeout);
239       } catch (InterruptedException ignored) {}
240       didTimeout = true;
241       synchronized(buffer) {
242         buffer.notify();
243       }
244     }
245   }
246 
247   public class SendLocalHostname implements Serializable {
248     public String toString() {
249       return sock.getLocalAddress().getHostName();
250     }
251   }
252 
253   public static class SendRemoteHostname implements Serializable {
254     private SendExpectProbe sep;
255 
256     public SendRemoteHostname(SendExpectProbe sep) {
257       this.sep = sep;
258     }
259 
260     public String toString() {
261       if (sep.getService() == null) return "[no svc]";
262       return sep.getService().getHost()
263         .getAddress().getHostName();
264     }
265   }
266 
267   public static class SendParameter implements Serializable {
268     private SendExpectProbe sep;
269     private String name;
270 
271     public SendParameter(SendExpectProbe sep, String name) {
272       this.sep = sep;
273       this.name = name;
274     }
275 
276     public String toString() {
277       Service svc = sep.getService();
278       if (svc == null) return "[no svc]";
279       String param = svc.getParameter(name);
280       if (param == null || param.length() == 0)
281         param = svc.getProbeFactory().getServiceParamDefault(svc,name);
282       return param;
283     }
284   }
285 
286   private abstract class Step implements Serializable {
287     public abstract void run();
288   }
289 
290   private class SendStep extends Step {
291     private Object toSend;
292 
293     public SendStep(Object toSend) {
294       this.toSend = toSend;
295     }
296 
297     public void run() {
298       // convert to string
299       String out = toSend.toString();
300       // do nothing for null sends
301       if (out.length() == 0) return;
302       // set the buffer pointer to the current buffer end
303       bufptr = buffer.length();
304       // send the string
305       try {
306         writer.write(out);
307         //System.out.println("> "+out);
308         writer.flush();
309       } catch (IOException ex) {
310         didClose = true;
311       }
312     }
313   }
314 
315   private class ExpectStep extends Step {
316     private Object pass, fail;
317 
318     public ExpectStep(Object pass) {
319       this(pass,null);
320     }
321 
322     public ExpectStep(Object pass, Object fail) {
323       this.pass = pass;
324       this.fail = fail;
325     }
326 
327     public void run() {
328       while (true) {
329         synchronized (buffer) {
330           String bufarea = buffer.substring(bufptr);
331           // Check for pass match
332           if (checkMatch(bufarea, pass)) {
333             return;
334           }
335           // Check for fail match
336           if (fail != null && checkMatch(bufarea, fail)) {
337             didFail = true;
338             return;
339           }
340           // check for EOS
341           if (bufarea.indexOf(ENDSTREAM) >= 0) {
342             // end of stream found before expected string
343             // set didClose flag.
344             didClose = true;
345             return;
346           }
347           if (didClose || didTimeout || didFail) return;
348           try {
349             buffer.wait();
350           } catch (InterruptedException ex) {
351             return;
352           }
353         }
354       }
355     }
356 
357     private boolean checkMatch (String bufarea, Object match) {
358       // Check for pattern match
359       if (match instanceof Perl5Pattern) {
360         if (matcher == null)
361           matcher = new Perl5Matcher();
362         if (matcher.contains(bufarea,((Perl5Pattern)match)))
363           return true;
364       // Check for string match
365       } else {
366         if (bufarea.indexOf(match.toString()) >= 0) return true;
367       }
368       // No match found if we made it here.
369       return false;
370     }
371   }
372 }