package org.yamcs.commanding;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.ErrorInCommand;
import org.yamcs.NoPermissionException;
import org.yamcs.Processor;
import org.yamcs.YamcsException;
import org.yamcs.management.ManagementService;
import org.yamcs.protobuf.Commanding.CommandId;
import org.yamcs.security.AuthenticationToken;
import org.yamcs.security.InvalidAuthenticationToken;
import org.yamcs.security.Privilege;
import org.yamcs.xtce.ArgumentAssignment;
import org.yamcs.xtce.MetaCommand;
import org.yamcs.xtceproc.MetaCommandProcessor;
import org.yamcs.xtceproc.MetaCommandProcessor.CommandBuildResult;
import com.google.common.util.concurrent.AbstractService;
/**
* Responsible for parsing and tc packet composition.
* @author nm
*
*/
public class CommandingManager extends AbstractService {
Logger log=LoggerFactory.getLogger(this.getClass().getName());
private Processor processor;
private CommandQueueManager commandQueueManager;
/**
* Keeps a reference to the channel and creates the queue manager
* @param proc
*/
public CommandingManager(Processor proc) {
this.processor=proc;
this.commandQueueManager=new CommandQueueManager(this);
ManagementService.getInstance().registerCommandQueueManager(proc.getInstance(), proc.getName(), commandQueueManager);
}
public CommandQueueManager getCommandQueueManager() {
return commandQueueManager;
}
/**
* pc is a command whose source is included.
* parse the source populate the binary part and the definition.
*/
public PreparedCommand buildCommand(MetaCommand mc, List<ArgumentAssignment> argAssignmentList, String origin, int seq, AuthenticationToken authToken) throws ErrorInCommand, NoPermissionException, YamcsException {
log.debug("building command {} with arguments {}", mc.getName(), argAssignmentList);
if(!Privilege.getInstance().hasPrivilege1(authToken, Privilege.Type.TC, mc.getName())) {
throw new NoPermissionException("User has no privilege on command " + mc.getName());
}
if(origin == null)
origin = "anonymous";
CommandBuildResult cbr = MetaCommandProcessor.buildCommand(mc, argAssignmentList);
CommandId cmdId = CommandId.newBuilder().setCommandName(mc.getQualifiedName()).setOrigin(origin).setSequenceNumber(seq).setGenerationTime(processor.getCurrentTime()).build();
PreparedCommand pc = new PreparedCommand(cmdId);
pc.setMetaCommand(mc);
pc.setBinary(cbr.getCmdPacket());
pc.setArgAssignment(cbr.getArgs());
String username;
if (authToken !=null && authToken.getPrincipal() != null) {
username = authToken.getPrincipal().toString();
} else {
username = Privilege.getDefaultUser();
}
pc.setUsername(username);
return pc;
}
/**
* @return the queue that the command was sent to
* @throws InvalidAuthenticationToken
*/
public CommandQueue sendCommand(AuthenticationToken authToken, PreparedCommand pc) throws InvalidAuthenticationToken {
log.debug("sendCommand commandSource={}", pc.getSource());
return commandQueueManager.addCommand(authToken, pc);
}
public void addToCommandHistory(CommandId commandId, String key, String value, AuthenticationToken authToken) throws NoPermissionException {
if(!Privilege.getInstance().hasPrivilege1(authToken, Privilege.Type.SYSTEM, Privilege.SystemPrivilege.MayModifyCommandHistory.name())) {
log.warn("Throwing InsufficientPrivileges for lack of COMMANDING privilege for user "+authToken);
throw new NoPermissionException("User has no privilege to update command history ");
}
commandQueueManager.addToCommandHistory(commandId, key, value);
}
public Processor getChannel() {
return processor;
}
@Override
protected void doStart() {
notifyStarted();
}
@Override
protected void doStop() {
notifyStopped();
}
}