blob: c4875099c243b837717d1915d8cd75001357cf8f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.framework.internal.core;
import java.io.*;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.eclipse.osgi.framework.console.ConsoleSession;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class ConsoleManager implements ServiceTrackerCustomizer {
/**
* ConsoleSocketGetter - provides a Thread that listens on the port
* for FrameworkConsole.
*/
class ConsoleSocketGetter implements Runnable {
/** The ServerSocket to accept connections from */
private final ServerSocket server;
private volatile boolean shutdown = false;
/**
* Constructor - sets the server and starts the thread to
* listen for connections.
*
* @param server a ServerSocket to accept connections from
*/
ConsoleSocketGetter(ServerSocket server) {
this.server = server;
try {
Method reuseAddress = server.getClass().getMethod("setReuseAddress", new Class[] {boolean.class}); //$NON-NLS-1$
reuseAddress.invoke(server, new Object[] {Boolean.TRUE});
} catch (Exception ex) {
// try to set the socket re-use property, it isn't a problem if it can't be set
}
Thread t = new Thread(this, "ConsoleSocketGetter"); //$NON-NLS-1$
t.setDaemon(false);
t.start();
}
public void run() {
// Print message containing port console actually bound to..
System.out.println(NLS.bind(ConsoleMsg.CONSOLE_LISTENING_ON_PORT, Integer.toString(server.getLocalPort())));
while (!shutdown) {
try {
Socket socket = server.accept();
if (socket == null)
throw new IOException("No socket available. Probably caused by a shutdown."); //$NON-NLS-1$
FrameworkConsoleSession session = new FrameworkConsoleSession(socket.getInputStream(), socket.getOutputStream(), socket);
framework.getSystemBundleContext().registerService(ConsoleSession.class.getName(), session, null);
} catch (Exception e) {
if (!shutdown)
e.printStackTrace();
}
}
}
public void shutdown() {
if (shutdown)
return;
shutdown = true;
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static final String PROP_CONSOLE = "osgi.console"; //$NON-NLS-1$
private static final String PROP_SYSTEM_IN_OUT = "console.systemInOut"; //$NON-NLS-1$
private static final String CONSOLE_NAME = "OSGi Console"; //$NON-NLS-1$
private final Framework framework;
private final ServiceTracker cpTracker;
private final ServiceTracker sessions;
private final String consolePort;
private FrameworkCommandProvider fwkCommands;
private ServiceRegistration builtinSession;
private ConsoleSocketGetter scsg;
public ConsoleManager(Framework framework, String consolePort) {
this.framework = framework;
this.consolePort = consolePort != null ? consolePort.trim() : consolePort;
this.cpTracker = new ServiceTracker(framework.getSystemBundleContext(), CommandProvider.class.getName(), null);
this.sessions = new ServiceTracker(framework.getSystemBundleContext(), ConsoleSession.class.getName(), this);
}
public static ConsoleManager startConsole(Framework framework) {
ConsoleManager consoleManager = new ConsoleManager(framework, FrameworkProperties.getProperty(PROP_CONSOLE));
consoleManager.startConsole();
return consoleManager;
}
private void startConsole() {
if ("none".equals(consolePort)) //$NON-NLS-1$
return; // disables all console sessions
this.cpTracker.open();
this.sessions.open();
fwkCommands = new FrameworkCommandProvider(framework);
fwkCommands.start();
if (consolePort == null)
return;
int port = -1;
try {
if (consolePort.length() > 0)
port = Integer.parseInt(consolePort);
} catch (NumberFormatException e) {
// do nothing;
}
if (port < 0) {
InputStream in = new FilterInputStream(System.in) {
public void close() throws IOException {
// We don't want to close System.in
}
};
OutputStream out = new FilterOutputStream(System.out) {
public void close() throws IOException {
// We don't want to close System.out
}
public void write(byte[] var0, int var1, int var2) throws IOException {
this.out.write(var0, var1, var2);
}
};
FrameworkConsoleSession session = new FrameworkConsoleSession(in, out, null);
Hashtable props = null;
props = new Hashtable(1);
props.put(PROP_SYSTEM_IN_OUT, Boolean.TRUE);
builtinSession = framework.getSystemBundleContext().registerService(ConsoleSession.class.getName(), session, props);
} else {
try {
scsg = new ConsoleManager.ConsoleSocketGetter(new ServerSocket(port));
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Stops the OSGi Command console
*
*/
public void stopConsole() {
if (builtinSession != null)
try {
builtinSession.unregister();
} catch (IllegalStateException e) {
// ignore; this can happen if the session was closed manually (bug 314343)
}
sessions.close();
cpTracker.close();
if (scsg != null)
scsg.shutdown();
if (fwkCommands != null)
fwkCommands.stop();
}
public Object addingService(ServiceReference reference) {
FrameworkConsole console = null;
Boolean isSystemInOut = (Boolean) reference.getProperty(PROP_SYSTEM_IN_OUT);
if (isSystemInOut == null)
isSystemInOut = Boolean.FALSE;
ConsoleSession session = (ConsoleSession) framework.getSystemBundleContext().getService(reference);
console = new FrameworkConsole(framework.getSystemBundleContext(), session, isSystemInOut.booleanValue(), cpTracker);
Thread t = new Thread(console, CONSOLE_NAME);
t.setDaemon(false);
t.start();
return console;
}
public void modifiedService(ServiceReference reference, Object service) {
// nothing
}
public void removedService(ServiceReference reference, Object service) {
((FrameworkConsole) service).shutdown();
}
}