KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > internal > core > FrameworkConsole


1 /*******************************************************************************
2  * Copyright (c) 2003, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.framework.internal.core;
13
14 import java.io.*;
15 import java.net.*;
16 import org.eclipse.osgi.framework.console.CommandInterpreter;
17 import org.eclipse.osgi.framework.console.CommandProvider;
18 import org.eclipse.osgi.util.NLS;
19 import org.osgi.framework.ServiceReference;
20 import org.osgi.util.tracker.ServiceTracker;
21
22 /**
23  * This class starts OSGi with a console for development use.
24  *
25  * FrameworkConsole provides a printStackTrace method to print Exceptions and their
26  * nested Exceptions.
27  */

28 public class FrameworkConsole implements Runnable JavaDoc {
29     /** The stream to receive commands on */
30     protected BufferedReader in;
31     /** The stream to write command results to */
32     protected PrintWriter out;
33     /** The current bundle context */
34     protected final org.osgi.framework.BundleContext context;
35     /** The current osgi instance */
36     protected final OSGi osgi;
37     /** The command line arguments passed at launch time*/
38     protected final String JavaDoc[] args;
39     /** The OSGi Command Provider */
40     protected final CommandProvider osgicp;
41     /** A tracker containing the service object of all registered command providers */
42     protected final ServiceTracker cptracker;
43
44     /** Default code page which must be supported by all JVMs */
45     static final String JavaDoc defaultEncoding = "iso8859-1"; //$NON-NLS-1$
46
/** The current setting for code page */
47     static final String JavaDoc encoding = FrameworkProperties.getProperty("osgi.console.encoding", FrameworkProperties.getProperty("file.encoding", defaultEncoding)); //$NON-NLS-1$ //$NON-NLS-2$
48

49     /** set to true if accepting commands from port */
50     protected final boolean useSocketStream;
51     protected boolean disconnect = false;
52     protected final int port;
53     protected ConsoleSocketGetter scsg = null;
54     protected Socket s;
55     boolean blockOnready = FrameworkProperties.getProperty("osgi.dev") != null || FrameworkProperties.getProperty("osgi.console.blockOnReady") != null; //$NON-NLS-1$ //$NON-NLS-2$
56
volatile boolean shutdown = false;
57
58     /**
59      Constructor for FrameworkConsole.
60      It creates a service tracker to track CommandProvider registrations.
61      The console InputStream is set to System.in and the console PrintStream is set to System.out.
62      @param osgi - an instance of an osgi framework
63      @param args - any arguments passed on the command line when Launcher is started.
64      */

65     public FrameworkConsole(OSGi osgi, String JavaDoc[] args) {
66         this(osgi, args, 0, false);
67     }
68
69     /**
70      Constructor for FrameworkConsole.
71      It creates a service tracker to track CommandProvider registrations.
72      The console InputStream is set to System.in and the console PrintStream is set to System.out.
73      @param osgi - an instance of an osgi framework
74      @param args - any arguments passed on the command line when Launcher is started.
75      */

76     public FrameworkConsole(OSGi osgi, int port, String JavaDoc[] args) {
77         this(osgi, args, port, true);
78     }
79
80     private FrameworkConsole(OSGi osgi, String JavaDoc[] args, int port, boolean useSocketStream) {
81         this.args = args;
82         this.osgi = osgi;
83         this.useSocketStream = useSocketStream;
84         this.port = port;
85         this.context = osgi.getBundleContext();
86
87         // set up a service tracker to track CommandProvider registrations
88
this.cptracker = new ServiceTracker(context, CommandProvider.class.getName(), null);
89         this.cptracker.open();
90
91         // register the OSGi command provider
92
this.osgicp = new FrameworkCommandProvider(osgi).intialize();
93     }
94
95     /**
96      * Open streams for system.in and system.out
97      */

98     private void getDefaultStreams() {
99         InputStream is = new FilterInputStream(System.in) {
100             public void close() throws IOException {
101                 // We don't want to close System.in
102
}
103         };
104         in = createBufferedReader(is);
105
106         OutputStream os = new FilterOutputStream(System.out) {
107             public void close() throws IOException {
108                 // We don't want to close System.out
109
}
110         };
111         out = createPrintWriter(os);
112         disconnect = false;
113     }
114
115     /**
116      * Open a socket and create input and output streams
117      *
118      * @param port number to listen on
119      */

120     private void getSocketStream() {
121         try {
122             System.out.println(NLS.bind(ConsoleMsg.CONSOLE_LISTENING_ON_PORT, String.valueOf(port)));
123             synchronized (this) {
124                 if (scsg == null)
125                     scsg = new ConsoleSocketGetter(new ServerSocket(port));
126                 scsg.setAcceptConnections(true);
127             }
128             // get socket outside of sync block
129
Socket temp = scsg.getSocket();
130             if (temp == null)
131                 return;
132             synchronized (this) {
133                 s = temp;
134                 in = createBufferedReader(s.getInputStream());
135                 out = createPrintWriter(s.getOutputStream());
136                 disconnect = false;
137             }
138         } catch (UnknownHostException uhe) {
139             uhe.printStackTrace();
140         } catch (Exception JavaDoc e) {
141             e.printStackTrace();
142         }
143     }
144
145     /**
146      * Return a BufferedReader from an InputStream. Handle encoding.
147      *
148      * @param _in An InputStream to wrap with a BufferedReader
149      * @return a BufferedReader
150      */

151     private BufferedReader createBufferedReader(InputStream _in) {
152         BufferedReader reader;
153         try {
154             reader = new BufferedReader(new InputStreamReader(_in, encoding));
155         } catch (UnsupportedEncodingException uee) {
156             // if the encoding is not supported by the jvm, punt and use whatever encodiing there is
157
reader = new BufferedReader(new InputStreamReader(_in));
158         }
159         return reader;
160     }
161
162     /**
163      * Return a PrintWriter from an OutputStream. Handle encoding.
164      *
165      * @param _out An OutputStream to wrap with a PrintWriter
166      * @return a PrintWriter
167      */

168     PrintWriter createPrintWriter(OutputStream _out) {
169         PrintWriter writer;
170         try {
171             writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(_out, encoding)), true);
172         } catch (UnsupportedEncodingException uee) {
173             // if the encoding is not supported by the jvm, punt and use whatever encodiing there is
174
writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(_out)), true);
175         }
176         return writer;
177     }
178
179     /**
180      * Return the current output PrintWriter
181      * @return The currently active PrintWriter
182      */

183     public PrintWriter getWriter() {
184         return out;
185     }
186
187     /**
188      * Return the current input BufferedReader
189      * @return The currently active BufferedReader
190      */

191     public BufferedReader getReader() {
192         return in;
193     }
194
195     /**
196      * Return if the SocketSteam (telnet to the console) is being used
197      * @return Return if the SocketSteam is being used
198      */

199     public boolean getUseSocketStream() {
200         return useSocketStream;
201     }
202
203     /**
204      * Begin doing the active part of the class' code. Starts up the console.
205      */

206     public void run() {
207         // always grap the default streams
208
getDefaultStreams();
209         try {
210             console(args);
211         } catch (IOException e) {
212             e.printStackTrace(out);
213         }
214         while (!shutdown) {
215             if (useSocketStream)
216                 getSocketStream();
217             try {
218                 console();
219             } catch (IOException e) {
220                 if (!shutdown)
221                     e.printStackTrace(out);
222             }
223         }
224     }
225
226     /**
227      * Command Line Interface for OSGi. The method processes the initial commands
228      * and then reads and processes commands from the console InputStream.
229      * Command output is written to the console PrintStream. The method will
230      * loop reading commands from the console InputStream until end-of-file
231      * is reached. This method will then return.
232      *
233      * @param args Initial set of commands to execute.
234      * @throws IOException
235      */

236     public void console(String JavaDoc args[]) throws IOException {
237         // first handle any args passed in from launch
238
if (args != null) {
239             for (int i = 0; i < args.length; i++) {
240                 docommand(args[i]);
241             }
242         }
243     }
244
245     /**
246      * Command Line Interface for OSGi. The method processes the initial commands
247      * and then reads and processes commands from the console InputStream.
248      * Command output is written to the console PrintStream. The method will
249      * loop reading commands from the console InputStream until end-of-file
250      * is reached. This method will then return.
251      * @throws IOException
252      */

253     protected void console() throws IOException {
254         // wait to receive commands from console and handle them
255
BufferedReader br = in;
256         //cache the console prompt String
257
String JavaDoc consolePrompt = "\r\n" + ConsoleMsg.CONSOLE_PROMPT; //$NON-NLS-1$
258
while (!disconnected()) {
259             out.print(consolePrompt);
260             out.flush();
261
262             String JavaDoc cmdline = null;
263             if (blockOnready && !useSocketStream) {
264                 // bug 40066: avoid waiting on input stream - apparently generates contention with other native calls
265
try {
266                     while (!br.ready())
267                         Thread.sleep(300);
268                     cmdline = br.readLine();
269                 } catch (InterruptedException JavaDoc e) {
270                     // do nothing; probably got disconnected
271
}
272             } else
273                 cmdline = br.readLine();
274
275             if (cmdline != null && !shutdown)
276                 docommand(cmdline);
277         }
278     }
279
280     /**
281      * Process the args on the command line.
282      * This method invokes a CommandInterpreter to do the actual work.
283      *
284      * @param cmdline a string containing the command line arguments
285      */

286     protected void docommand(String JavaDoc cmdline) {
287         if (cmdline != null && cmdline.length() > 0) {
288             CommandInterpreter intcp = new FrameworkCommandInterpreter(cmdline, getServices(), this);
289             String JavaDoc command = intcp.nextArgument();
290             if (command != null) {
291                 intcp.execute(command);
292             }
293         }
294     }
295
296     /**
297      * Disconnects from console if useSocketStream is set to true. This
298      * will cause the console to close from a telnet session.
299      */

300     public synchronized void disconnect() {
301         if (!disconnect) {
302             disconnect = true;
303             // We don't want to close System.in and System.out
304
if (useSocketStream) {
305                 if (s != null)
306                     try {
307                         s.close();
308                     } catch (IOException ioe) {
309                         // do nothing
310
}
311                 if (out != null)
312                     out.close();
313                 if (in != null)
314                     try {
315                         in.close();
316                     } catch (IOException ioe) {
317                         // do nothing
318
}
319             }
320         }
321     }
322
323     /**
324      * @return are we still connected?
325      */

326     private synchronized boolean disconnected() {
327         return disconnect;
328     }
329
330     /**
331      * Reads a string from standard input until user hits the Enter key.
332      *
333      * @return The string read from the standard input without the newline character.
334      */

335     public String JavaDoc getInput() {
336         String JavaDoc input;
337         try {
338             /** The buffered input reader on standard in. */
339             input = in.readLine();
340             System.out.println("<" + input + ">"); //$NON-NLS-1$//$NON-NLS-2$
341
} catch (IOException e) {
342             input = ""; //$NON-NLS-1$
343
}
344         return input;
345     }
346
347     /**
348      * Return an array of service objects for all services
349      * being tracked by this <tt>ServiceTracker</tt> object.
350      *
351      * The array is sorted primarily by descending Service Ranking and
352      * secondarily by ascending Service ID.
353      *
354      * @return Array of service objects or <tt>null</tt> if no service
355      * are being tracked.
356      */

357     public Object JavaDoc[] getServices() {
358         ServiceReference[] serviceRefs = cptracker.getServiceReferences();
359         Util.dsort(serviceRefs, 0, serviceRefs.length);
360
361         Object JavaDoc[] serviceObjects = new Object JavaDoc[serviceRefs.length];
362         for (int i = 0; i < serviceRefs.length; i++)
363             serviceObjects[i] = FrameworkConsole.this.context.getService(serviceRefs[i]);
364         return serviceObjects;
365     }
366
367     /**
368      * Stops the console so the thread can be GC'ed
369      * @throws IOException
370      *
371      */

372     public synchronized void shutdown() {
373         shutdown = true;
374         cptracker.close();
375         disconnect();
376         if (scsg != null)
377             try {
378                 scsg.shutdown();
379             } catch (IOException e) {
380                 System.err.println(e.getMessage());
381             }
382     }
383
384     /**
385      * ConsoleSocketGetter - provides a Thread that listens on the port
386      * for FrameworkConsole. If acceptConnections is set to true then
387      * the thread will notify the getSocket method to return the socket.
388      * If acceptConnections is set to false then the client is notified
389      * that connections are not currently accepted and closes the socket.
390      */

391     class ConsoleSocketGetter implements Runnable JavaDoc {
392
393         /** The ServerSocket to accept connections from */
394         private final ServerSocket server;
395         /** The current socket to be returned by getSocket */
396         private Socket socket;
397         /** if set to true then allow the socket to be returned by getSocket */
398         private boolean acceptConnections = true;
399         /** Lock object to synchronize returning of the socket */
400         private final Object JavaDoc lock = new Object JavaDoc();
401
402         /**
403          * Constructor - sets the server and starts the thread to
404          * listen for connections.
405          *
406          * @param server a ServerSocket to accept connections from
407          */

408         ConsoleSocketGetter(ServerSocket server) {
409             this.server = server;
410             Thread JavaDoc t = new Thread JavaDoc(this, "ConsoleSocketGetter"); //$NON-NLS-1$
411
t.setDaemon(true);
412             t.start();
413         }
414
415         public void run() {
416             while (!shutdown) {
417                 try {
418                     socket = server.accept();
419                     if (!acceptConnections) {
420                         PrintWriter o = createPrintWriter(socket.getOutputStream());
421                         o.println(ConsoleMsg.CONSOLE_TELNET_CONNECTION_REFUSED);
422                         o.println(ConsoleMsg.CONSOLE_TELNET_CURRENTLY_USED);
423                         o.println(ConsoleMsg.CONSOLE_TELNET_ONE_CLIENT_ONLY);
424                         o.close();
425                         socket.close();
426                     } else {
427                         synchronized (lock) {
428                             lock.notify();
429                         }
430                     }
431                 } catch (Exception JavaDoc e) {
432                     if (!shutdown)
433                         e.printStackTrace();
434                 }
435
436             }
437         }
438
439         /**
440          * Method to get a socket connection from a client.
441          *
442          * @return - Socket from a connected client
443          */

444         public Socket getSocket() throws InterruptedException JavaDoc {
445             // wait for a socket to get assigned from the accepter thread
446
synchronized (lock) {
447                 lock.wait(); //TODO spurious wakeup not handled
448
}
449             setAcceptConnections(false);
450             return socket;
451         }
452
453         /**
454          * Method to indicate if connections are accepted or not. If set
455          * to false then the clients will be notified that connections
456          * are not accepted.
457          */

458         public void setAcceptConnections(boolean acceptConnections) {
459             this.acceptConnections = acceptConnections;
460         }
461
462         public void shutdown() throws IOException {
463             server.close();
464         }
465     }
466
467 }
468
Popular Tags