package org.zend.php.zendserver.deployment.debug.core;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.php.internal.debug.core.PHPDebugPlugin;
import org.eclipse.php.internal.debug.core.debugger.AbstractDebuggerConfiguration;
import org.eclipse.php.internal.debug.core.preferences.PHPDebugCorePreferenceNames;
import org.eclipse.php.internal.debug.core.preferences.PHPDebuggersRegistry;
import org.eclipse.php.internal.debug.core.zend.communication.DebuggerCommunicationDaemon;
import org.eclipse.php.internal.debug.core.zend.debugger.ZendDebuggerSettingsUtil;
import org.eclipse.php.internal.server.core.Server;
import org.zend.php.server.core.utils.ServerUtils;
import org.zend.sdklib.SdkException;
import org.zend.sdklib.application.ZendDebugMode;
import org.zend.sdklib.application.ZendDebugMode.State;
import org.zend.sdklib.manager.TargetsManager;
import org.zend.sdklib.target.IZendTarget;
@SuppressWarnings("restriction")
public class DebugModeManager {
public static final int[] prohibitedPorts = new int[] { 10081, 10082 };
public static final String SERVER_ATTRIBUTE = "debugModeFilters"; //$NON-NLS-1$
private static final String DEBUG_STOP = "debug_stop"; //$NON-NLS-1$
private static final String DEBUG_HOST = "debug_host"; //$NON-NLS-1$
private static final String DEBUG_PORT = "debug_port"; //$NON-NLS-1$
private static final String LOCALHOST = "localhost"; //$NON-NLS-1$
public static final String DEBUG_MODE_NODE = Activator.PLUGIN_ID
+ "/debugMode"; //$NON-NLS-1$
public static final String FILTER_SEPARATOR = ","; //$NON-NLS-1$
private static DebugModeManager manager;
private Map<IZendTarget, Boolean> targets;
private DebugModeManager() {
this.targets = new HashMap<IZendTarget, Boolean>();
}
public static DebugModeManager getManager() {
if (manager == null) {
manager = new DebugModeManager();
}
return manager;
}
public IStatus startDebugMode(IZendTarget target) {
ZendDebugMode debugMode = new ZendDebugMode(target.getId());
Map<String, String> options = new HashMap<String, String>();
debugMode.setFilters(getFilters(target));
options.put(DEBUG_PORT, String.valueOf(getDebugPort(target)));
options.put(DEBUG_HOST, getDebugHosts(target));
Server server = ServerUtils.getServer(target);
if (server != null) {
if (shouldStopAtFirstLine()) {
options.put(DEBUG_STOP, "1"); //$NON-NLS-1$
}
} else {
options.put(DEBUG_STOP, "1"); //$NON-NLS-1$
}
debugMode.setOptions(options);
State result = State.ERROR;
try {
result = debugMode.start();
} catch (SdkException e) {
Activator.log(e);
}
if (result == State.STARTING) {
targets.put(target, true);
return new Status(IStatus.OK, Activator.PLUGIN_ID,
Messages.DebugModeManager_StartSuccess);
}
if (result == State.STARTED) {
return new Status(IStatus.WARNING, Activator.PLUGIN_ID,
Messages.DebugModeManager_AlreadyStartedWarning);
}
return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
Messages.DebugModeManager_CannotStartError);
}
public IStatus stopDebugMode(IZendTarget target) {
ZendDebugMode debugMode = new ZendDebugMode(target.getId());
State result = State.ERROR;
try {
result = debugMode.stop();
} catch (SdkException e) {
Activator.log(e);
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getCause()
.getMessage());
}
if (result == State.STOPPING) {
targets.put(target, false);
return new Status(IStatus.OK, Activator.PLUGIN_ID,
Messages.DebugModeManager_StopSuccess);
}
if (result == State.STOPPED) {
if (isInDebugMode(target)) {
targets.put(target, false);
}
return new Status(IStatus.WARNING, Activator.PLUGIN_ID,
Messages.DebugModeManager_AlreadyStoppedWarning);
}
return new Status(IStatus.ERROR, Activator.PLUGIN_ID,
Messages.DebugModeManager_CannotStopError);
}
public IStatus restartDebugMode(IZendTarget target) {
IStatus stopStatus = stopDebugMode(target);
if (stopStatus.getSeverity() != IStatus.ERROR) {
return startDebugMode(target);
} else {
return stopStatus;
}
}
public boolean isInDebugMode(IZendTarget target) {
Boolean value = targets.get(target);
if (value == null || !value) {
return false;
}
return true;
}
public static void stopAll() {
DebugModeManager manager = getManager();
Set<IZendTarget> keys = manager.targets.keySet();
for (IZendTarget target : keys) {
if (manager.isInDebugMode(target)) {
manager.stopDebugMode(target);
}
}
}
private String getDebugHosts(IZendTarget target) {
String host = target.getHost().getHost();
if (host.equals(LOCALHOST)) {
return LOCALHOST;
}
IEclipsePreferences prefs = InstanceScope.INSTANCE
.getNode(PHPDebugPlugin.ID);
String clientHosts = prefs.get(PHPDebugCorePreferenceNames.CLIENT_IP,
(String) null);
if (clientHosts == null) {
IEclipsePreferences defaultPrefs = DefaultScope.INSTANCE
.getNode(PHPDebugPlugin.ID);
clientHosts = defaultPrefs.get(
PHPDebugCorePreferenceNames.CLIENT_IP, (String) null);
}
Server server = ServerUtils.getServer(target);
// Get server individual hosts list if any
String customHosts = ZendDebuggerSettingsUtil.getDebugHosts(server.getUniqueId());
if (customHosts != null)
clientHosts = customHosts;
return clientHosts;
}
private int getDebugPort(IZendTarget target) {
IEclipsePreferences prefs = InstanceScope.INSTANCE
.getNode(PHPDebugPlugin.ID);
int clientHosts = prefs.getInt(
PHPDebugCorePreferenceNames.ZEND_DEBUG_PORT, -1);
if (clientHosts == -1) {
IEclipsePreferences defaultPrefs = DefaultScope.INSTANCE
.getNode(PHPDebugPlugin.ID);
clientHosts = defaultPrefs.getInt(
PHPDebugCorePreferenceNames.ZEND_DEBUG_PORT, -1);
}
Server server = ServerUtils.getServer(target);
// Get server individual hosts list if any
int customPort = ZendDebuggerSettingsUtil.getDebugPort(server.getUniqueId());
if (customPort != -1)
clientHosts = customPort;
return clientHosts;
}
/**
* Get Debug Mode filters. Firstly, it tries to read them from PHP server
* configuration. If they are not defined in it, then reads them from
* preferences.
*
* @param target
* @return list of Debug Mode filters; it may be empty
*/
private String[] getFilters(IZendTarget target) {
Server server = ServerUtils.getServer(target);
String value = server.getAttribute(SERVER_ATTRIBUTE, null);
if (value == null) {
IEclipsePreferences prefs = InstanceScope.INSTANCE
.getNode(DEBUG_MODE_NODE);
value = prefs.get(target.getId(), null);
}
List<String> filters = null;
if (value != null && value.length() > 0) {
filters = new ArrayList<String>(Arrays.asList(value
.split(FILTER_SEPARATOR)));
} else {
filters = new ArrayList<String>();
}
return filters.toArray(new String[0]);
}
private boolean shouldStopAtFirstLine() {
IEclipsePreferences prefs = InstanceScope.INSTANCE
.getNode(PHPDebugPlugin.ID);
return prefs.getBoolean(PHPDebugCorePreferenceNames.STOP_AT_FIRST_LINE,
true);
}
}