/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.debug.daemon;
import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.php.debug.daemon.communication.ICommunicationDaemon;
import org.eclipse.php.internal.debug.daemon.communication.DaemonsRegistry;
import org.osgi.framework.BundleContext;
/**
* The main plug-in class to be used in the desktop. Note that since PDT 1.0 the
* daemon plug-in waits for an outside invocation to start the daemons listening
* (See startDaemons()).
*
* @author Shalom Gibly
*/
public class DaemonPlugin extends Plugin {
public static final String ID = "org.eclipse.php.debug.daemon"; //$NON-NLS-1$
/**
* Disable deamon startup via -Dorg.eclipse.php.debug.disableDaemonStartup
*/
private static final String DISABLE_PROPERTY = "org.eclipse.php.debug.disableDaemonStartup"; //$NON-NLS-1$
private static final int INTERNAL_ERROR = 10001;
public static final boolean isDebugMode;
static {
String value = Platform.getDebugOption("org.eclipse.php.debug.daemon/debug"); //$NON-NLS-1$
isDebugMode = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$
}
// The shared instance.
private static DaemonPlugin plugin;
// Hold an array of possible daemons.
private ICommunicationDaemon[] daemons;
/**
* The constructor.
*/
public DaemonPlugin() {
plugin = this;
}
/**
* This method is called upon plug-in activation
*/
public void start(BundleContext context) throws Exception {
super.start(context);
initializeAfterStart(context);
}
/**
* This method is used for later initialization. This trick should release
* plug-in start-up.
*
* @param context
*/
void initializeAfterStart(final BundleContext context) {
if (System.getProperty(DISABLE_PROPERTY, null) != null) {
return;
}
Job job = new Job("") { //$NON-NLS-1$
protected IStatus run(IProgressMonitor monitor) {
startDaemons(null);
return Status.OK_STATUS;
}
};
job.schedule(Job.LONG);
}
/**
* Initializes and starts the daemons that has the given daemonID. In case
* that the give id is null, starts all the registered daemons.
*
* @param debuggerID
* The debugger id, or null.
* @since PDT 1.0
*/
public void startDaemons(String debuggerID) {
if (daemons == null) {
List<ICommunicationDaemon> loaded = DaemonsRegistry.getDaemons();
daemons = loaded.toArray(new ICommunicationDaemon[loaded.size()]);
}
if (daemons != null) {
for (int i = 0; i < daemons.length; i++) {
if (debuggerID == null
|| (daemons[i].isDebuggerDaemon() && debuggerID.equals(daemons[i].getDebuggerID()))) {
daemons[i].init();
daemons[i].startListen();
}
}
}
}
public boolean isInitialized(String debuggerID) {
if (daemons != null) {
for (int i = 0; i < daemons.length; i++) {
if (debuggerID == null
|| (daemons[i].isDebuggerDaemon() && debuggerID.equals(daemons[i].getDebuggerID()))) {
if (!daemons[i].isInitialized()) {
return false;
}
}
}
return true;
}
return false;
}
public void makeSureDebuggerInitialized(String debuggerID) {
while (true) {
if (!isInitialized(debuggerID)) {
if (System.getProperty(DISABLE_PROPERTY, null) != null) {
startDaemons(debuggerID);
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
} else {
break;
}
}
}
/**
* Stop the daemons that has the given daemonID. In case that the give id is
* null, stop all the registered daemons.
*
* @param debuggerID
* The debugger id, or null.
* @since PDT 1.0
*/
public void stopDaemons(String debuggerID) {
if (daemons != null) {
for (int i = 0; i < daemons.length; i++) {
if (debuggerID == null
|| (daemons[i].isDebuggerDaemon() && debuggerID.equals(daemons[i].getDebuggerID()))) {
daemons[i].stopListen();
}
}
}
}
/**
* This method is called when the plug-in is stopped
*/
public void stop(BundleContext context) throws Exception {
super.stop(context);
plugin = null;
stopDaemons(null);
daemons = null;
}
/**
* Make sure that the communication daemons are alive and listening. This
* method can be called before a communication session is requested in order
* to make sure that the requested communication daemon is up and running.
*
* The method goes over the registered daemons and reset the socket for any
* communication daemon that is not listening.
*
* The validation will be made on the daemons that have the given debuggerID
* or on all the daemons in case the id is null.
*
* @param debuggerID
* The debugger id, or null.
* @return True, if all the communication daemons passed the validation;
* False, otherwise.
* @since PDT 1.0
*/
public boolean validateCommunicationDaemons(String debuggerID, int port) {
boolean validated = true;
if (daemons != null) {
for (int i = 0; i < daemons.length; i++) {
if (debuggerID == null
|| (daemons[i].isDebuggerDaemon() && debuggerID.equals(daemons[i].getDebuggerID()))) {
if (!daemons[i].isListening(port)) {
// Try to restart daemons
daemons[i].resetSocket();
validated = daemons[i].isListening(port);
}
}
}
}
return validated;
}
/**
* Returns the DaemonPlugin ID string (e.g. org.eclipse.php.debug.daemon).
*/
public static String getID() {
return ID;
}
/**
* Returns the shared instance.
*/
public static DaemonPlugin getDefault() {
return plugin;
}
public static void log(IStatus status) {
getDefault().getLog().log(status);
}
public static void log(Throwable e) {
log(new Status(IStatus.ERROR, ID, INTERNAL_ERROR, "Debug Daemon plugin internal error", e)); //$NON-NLS-1$
}
public static void logErrorMessage(String message) {
log(new Status(IStatus.ERROR, ID, INTERNAL_ERROR, message, null));
}
}