/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.debugger.server;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.debugger.server.exceptions.DebuggerException;
import org.eclipse.che.api.debugger.server.exceptions.DebuggerNotFoundException;
import org.eclipse.che.api.debug.shared.model.event.DebuggerEvent;
import org.eclipse.che.commons.lang.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import static java.lang.Long.parseLong;
/**
* @author Anatoliy Bazko
*/
@Singleton
public class DebuggerManager {
private static final Logger LOG = LoggerFactory.getLogger(DebuggerManager.class);
private final EventService eventService;
/**
* Registered factories by debug type.
*/
private final Map<String, DebuggerFactory> factories;
/**
* Active debug sessions.
*/
private final Map<Long, Pair<String, Debugger>> debuggers;
private final AtomicLong sessionId;
@Inject
public DebuggerManager(Set<DebuggerFactory> factories, EventService eventService) {
this.eventService = eventService;
this.factories = new ConcurrentHashMap<>();
this.debuggers = new ConcurrentHashMap<>();
this.sessionId = new AtomicLong();
factories.stream().forEach(factory -> this.factories.put(factory.getType(), factory));
}
/**
* Instantiates a new debugger of given type.
* @see DebuggerFactory#create(Map, Debugger.DebuggerCallback)
* @return session identifier
*/
public String create(String debuggerType, Map<String, String> properties) throws DebuggerException {
DebuggerFactory factory = factories.get(debuggerType);
if (factory == null) {
throw new DebuggerNotFoundException("Debugger factory type '" + debuggerType + "' is not registered");
}
final long id = sessionId.incrementAndGet();
Debugger debugger = factory.create(properties, event -> {
if (DebuggerEvent.TYPE.DISCONNECT == event.getType()) {
debuggers.remove(id);
}
eventService.publish(new DebuggerMessage(event, debuggerType));
});
debuggers.put(id, Pair.of(debuggerType, debugger));
return String.valueOf(id);
}
/**
* @return active debugger by session id
* @throws DebuggerNotFoundException
* if no debugger found
*/
public Debugger getDebugger(String sessionId) throws DebuggerNotFoundException {
try {
Pair<String, Debugger> debugger = debuggers.get(parseLong(sessionId));
if (debugger == null) {
throw new DebuggerNotFoundException("Debug session " + sessionId + " not found");
}
return debugger.second;
} catch (NumberFormatException e) {
throw new DebuggerNotFoundException("Illegal session id " + sessionId);
}
}
/**
* @return debugger type by session id
* @throws DebuggerNotFoundException
* if no debugger found
*/
public String getDebuggerType(String sessionId) throws DebuggerNotFoundException {
try {
Pair<String, Debugger> debugger = debuggers.get(parseLong(sessionId));
if (debugger == null) {
throw new DebuggerNotFoundException("Debug session " + sessionId + " not found");
}
return debugger.first;
} catch (NumberFormatException e) {
throw new DebuggerNotFoundException("Illegal session id " + sessionId);
}
}
}