package org.opennaas.core.protocols.sessionmanager.shell;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;
import org.apache.felix.gogo.commands.Argument;
import org.apache.felix.gogo.commands.Command;
import org.apache.felix.gogo.commands.Option;
import org.opennaas.core.protocols.sessionmanager.ProtocolSessionManager;
import org.opennaas.core.resources.IResourceIdentifier;
import org.opennaas.core.resources.IResourceManager;
import org.opennaas.core.resources.protocol.IProtocolManager;
import org.opennaas.core.resources.protocol.ProtocolSessionContext;
import org.opennaas.core.resources.shell.GenericKarafCommand;
/**
* List the device ids registered to the protocol manager
*
* @author Pau Minoves
*
*/
@Command(scope = "protocols", name = "Context", description = "Manipulates protocol contexts for used to create new sessions. Call without protocol to list.")
public class ContextCommand extends GenericKarafCommand {
@Argument(name = "resourceType:resourceName", index = 0, required = true, description = "The resource owning the context.")
String resourceId;
@Argument(name = "protocol", required = false, index = 1, description = "The protocol of the context")
String protocol; // user and password are inside PROTOCOL_URI
@Argument(name = "authType", required = true, index = 2, description = "Type of authType to use.")
String authType;
@Argument(name = "uri", index = 3, required = false, description = "The URI passed to the protocol implementation of the context")
String uri; // user and password are inside PROTOCOL_URI
@Option(name = "--privateKeyPath", aliases = { "-PKpath" }, required = false, description = "The path where the private key is stored.")
String keyPath;
@Option(name = "--keyPassphrase", aliases = { "-PKpwd" }, required = false, description = "Passphrase to unlock the private key.")
String keyPassphrase;
@Option(name = "--remove", aliases = { "-r" }, required = false, description = "Instead of adding a context, remove it for the named protocol. ")
boolean optionRemove;
@Option(name = "--interactive", aliases = { "-i" }, required = false, description = "Tells command to ask for passwords interactively")
boolean interactive;
@Option(name = "--params", aliases = { "-p" }, required = false, description = "Allows the user to specify a coma separated list of extra parameters (name=value).")
String parametersList;
private static final String PASSWORD = "password";
private static final String PUBLICKEY = "publickey";
private static final String NOAUTH = "noauth";
@Override
protected Object doExecute() throws Exception {
IResourceManager manager = getResourceManager();
if (optionRemove) {
printInitCommand("Remove context");
} else {
printInitCommand("Adding context");
}
String[] argsRouterName = new String[2];
try {
argsRouterName = splitResourceName(resourceId);
} catch (Exception e) {
printError(e.getMessage());
printEndCommand();
return -1;
}
IResourceIdentifier resourceIdentifier = manager.getIdentifierFromResourceName(argsRouterName[0], argsRouterName[1]);
IProtocolManager protocolManager = getProtocolManager();
ProtocolSessionManager sessionManager = (ProtocolSessionManager) protocolManager.getProtocolSessionManager(resourceIdentifier.getId());
if (optionRemove) {
ProtocolSessionContext context = new ProtocolSessionContext();
context.addParameter(ProtocolSessionContext.PROTOCOL, protocol);
sessionManager.unregisterContext(protocol);
printEndCommand();
return null;
}
if (protocol == null || protocol.contentEquals("")) {
printError("You must specify a [protocol] and [uri] to register.");
for (ProtocolSessionContext context : sessionManager.getRegisteredProtocolSessionContexts().values()) {
printInfo("protocol = " + context.getSessionParameters().get(ProtocolSessionContext.PROTOCOL)
+ ", uri = " + context.getSessionParameters().get(ProtocolSessionContext.PROTOCOL_URI));
}
printEndCommand();
return null;
}
if (uri == null || uri.contentEquals("")) {
printError("You must specify a [uri] to register.");
printEndCommand();
return null;
}
ProtocolSessionContext context = new ProtocolSessionContext();
context.addParameter(ProtocolSessionContext.PROTOCOL, protocol);
context.addParameter(ProtocolSessionContext.PROTOCOL_URI, uri);
try {
context = checkAndSetAuthentication(context);
} catch (Exception e) {
printError(e.getLocalizedMessage());
printEndCommand();
return null;
}
context = fillExtraParams(context, parametersList);
sessionManager.registerContext(context);
printInfo("Context registered for resource " + resourceId);
printEndCommand();
return null;
}
private ProtocolSessionContext fillExtraParams(
ProtocolSessionContext context, String parametersList) {
if (parametersList == null || parametersList.isEmpty())
return context;
Set<String> reservedParameters = context.getSessionParameters().keySet();
String[] parametersArray = parametersList.split(",");
for (int i = 0; i < parametersArray.length; i++) {
String[] keyValuePair = parametersArray[i].split("=");
if (keyValuePair.length > 0) {
if (keyValuePair.length > 1) {
String parameterName = keyValuePair[0];
String parameterValue = keyValuePair[1];
if (reservedParameters.contains(parameterName)) {
printInfo("Ignoring parameter " + parameterName + ". It is reserved.");
} else {
context.addParameter(parameterName, parameterValue);
}
} else {
printInfo("Ignoring parameter " + keyValuePair[0] + " with no value");
}
}
}
return context;
}
/**
*
* @param context
* @return
* @throws Exception
*/
private ProtocolSessionContext checkAndSetAuthentication(ProtocolSessionContext context) throws Exception {
if (!authType.equals(PUBLICKEY) && !authType.equals(PASSWORD) && !authType.equals(NOAUTH)) {
throw new Exception("You must specify a valid authType type. Possible options are: \"password\", \"publickey\", \"noauth\".");
}
if (authType.equals(PASSWORD)) {
String userName = getUsername();
String password = getPassword();
if (userName == null || password == null) {
throw new Exception("You must specify a userName and password for password authentication.");
}
// UPDATE CONTEXT
context.addParameter(ProtocolSessionContext.AUTH_TYPE, PASSWORD);
context.addParameter(ProtocolSessionContext.USERNAME, userName);
context.addParameter(ProtocolSessionContext.PASSWORD, password);
} else if (authType.equals(PUBLICKEY)) {
String userName = getKeyUsername();
String keyPassphrase = getKeyPassphrase();
if (userName == null) {
throw new Exception("You must specify a userName for key authentication.");
}
if ((keyPath == null) || (keyPath.contentEquals(""))) {
throw new Exception("You must specify a private key file path for key authentication.");
}
// UPDATE CONTEXT
context.addParameter(ProtocolSessionContext.AUTH_TYPE, PUBLICKEY);
context.addParameter(ProtocolSessionContext.KEY_USERNAME, userName);
context.addParameter(ProtocolSessionContext.KEY_PATH, keyPath);
context.addParameter(ProtocolSessionContext.KEY_PASSPHRASE, keyPassphrase);
} else {
context.addParameter(ProtocolSessionContext.AUTH_TYPE, authType);
}
return context;
}
private String getUsername() throws URISyntaxException {
return getUserNameFromUri();
}
private String getPassword() throws IOException, URISyntaxException {
String password;
if (interactive) {
String askPasswordMsg = "password:";
password = askPasswordInteractively(askPasswordMsg);
} else {
password = getPasswordFromURI();
}
return password;
}
private String getKeyUsername() throws URISyntaxException {
return getUserNameFromUri();
}
private String getKeyPassphrase() throws IOException {
String passphrase;
if (interactive) {
String usrMsg = "Private key passphare:";
passphrase = askPasswordInteractively(usrMsg);
} else {
passphrase = keyPassphrase;
}
return passphrase;
}
private String getUserNameFromUri() throws URISyntaxException {
URI uRI = new URI(uri);
String userInfo = uRI.getUserInfo();
if (userInfo == null)
return null;
String userName = userInfo.split(":")[0];
return userName;
}
private String getPasswordFromURI() throws URISyntaxException {
URI uRI = new URI(uri);
String userInfo = uRI.getUserInfo();
if (userInfo == null)
return null;
if (userInfo.split(":").length > 1) {
String password = userInfo.split(":")[1];
return password;
} else {
return null;
}
}
}