blob: fa64d4ad34c90addb24688f5105a6a4d317d2dc1 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2015, 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ecommons.debug.core.model;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.ecommons.debug.core.ECommonsDebugCore;
@NonNullByDefault
public abstract class AbstractProcess extends PlatformObject implements IProcess {
private final ILaunch launch;
private final String name;
private volatile @Nullable Map<String, String> attributes;
private int exitValue;
public AbstractProcess(final ILaunch launch, final String label) {
this.launch= launch;
this.name= label;
}
@Override
public ILaunch getLaunch() {
return this.launch;
}
@Override
public String getLabel() {
return this.name;
}
@Override
public @Nullable IStreamsProxy getStreamsProxy() {
return null;
}
protected void fireEvent(final DebugEvent event) {
final DebugPlugin manager= DebugPlugin.getDefault();
if (manager != null) {
manager.fireDebugEventSet(new DebugEvent[] { event });
}
}
protected void fireEvents(final DebugEvent[] events) {
final DebugPlugin manager= DebugPlugin.getDefault();
if (manager != null) {
manager.fireDebugEventSet(events);
}
}
protected final Map<String, String> getAttributes() {
Map<String, String> map= this.attributes;
if (map == null) {
synchronized (this) {
map= this.attributes;
if (map == null) {
this.attributes= map= new HashMap<>();
}
}
}
return map;
}
protected final @Nullable Map<String, String> getAttributesIfPresent() {
return this.attributes;
}
protected final @Nullable DebugEvent doSet(final Map<String, String> map,
final String key, final @Nullable String value) {
final String oldValue= map.put(key, value);
if (Objects.equals(oldValue, value)) {
return null;
}
final DebugEvent event= new DebugEvent(this, DebugEvent.CHANGE);
event.setData(new String[] { key, oldValue, value });
return event;
}
@Override
public void setAttribute(final String key, final @Nullable String value) {
final Map<String, String> attributes= getAttributes();
final DebugEvent event;
synchronized (attributes) {
event= doSet(attributes, key, value);
}
if (event != null) {
fireEvent(event);
}
}
@Override
public @Nullable String getAttribute(final String key) {
final Map<String, String> attributes= getAttributesIfPresent();
if (attributes != null) {
synchronized (attributes) {
return attributes.get(key);
}
}
return null;
}
protected void created() {
getLaunch().addProcess(this);
fireEvent(new DebugEvent(this, DebugEvent.CREATE));
}
protected void terminated() {
fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
}
protected void doSetExitValue(final int value) {
this.exitValue= value;
}
protected int doGetExitValue() {
return this.exitValue;
}
@Override
public int getExitValue() throws DebugException {
if (!isTerminated()) {
throw new DebugException(new Status(IStatus.ERROR, ECommonsDebugCore.BUNDLE_ID,
DebugException.TARGET_REQUEST_FAILED,
"Exit value is not available until process is terminated.", null));
}
return doGetExitValue();
}
@Override
@SuppressWarnings("unchecked")
public <T> @Nullable T getAdapter(final Class<T> adapterType) {
if (adapterType == IProcess.class) {
return (T) this;
}
if (adapterType == ILaunch.class) {
return (T) getLaunch();
}
if (adapterType == IDebugTarget.class) {
final ILaunch launch= getLaunch();
final IDebugTarget[] targets= launch.getDebugTargets();
for (int i= 0; i < targets.length; i++) {
if (equals(targets[i].getProcess())) {
return (T) targets[i];
}
}
return null;
}
return super.getAdapter(adapterType);
}
}