/*
* Copyright 2011 Future Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.araqne.logdb.impl;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import org.araqne.api.PathAutoCompleter;
import org.araqne.api.Script;
import org.araqne.api.ScriptArgument;
import org.araqne.api.ScriptContext;
import org.araqne.api.ScriptUsage;
import org.araqne.logdb.Account;
import org.araqne.logdb.AccountService;
import org.araqne.logdb.CsvLookupRegistry;
import org.araqne.logdb.ExternalAuthService;
import org.araqne.logdb.LookupHandlerRegistry;
import org.araqne.logdb.Permission;
import org.araqne.logdb.Procedure;
import org.araqne.logdb.ProcedureParameter;
import org.araqne.logdb.ProcedureRegistry;
import org.araqne.logdb.Query;
import org.araqne.logdb.QueryScriptFactory;
import org.araqne.logdb.QueryScriptRegistry;
import org.araqne.logdb.QueryService;
import org.araqne.logdb.SavedResult;
import org.araqne.logdb.SavedResultManager;
import org.araqne.logdb.SecurityGroup;
import org.araqne.logdb.Session;
import org.araqne.logdb.Strings;
import org.araqne.logstorage.LogTableRegistry;
public class LogDBScript implements Script {
private QueryService qs;
private QueryScriptRegistry scriptRegistry;
private CsvLookupRegistry csvRegistry;
private ScriptContext context;
private LookupHandlerRegistry lookup;
private AccountService accountService;
private SavedResultManager savedResultManager;
private ProcedureRegistry procedureRegistry;
private LogTableRegistry tableRegistry;
public LogDBScript(QueryService qs, QueryScriptRegistry scriptRegistry, LookupHandlerRegistry lookup,
CsvLookupRegistry csvRegistry, AccountService accountService, SavedResultManager savedResultManager,
ProcedureRegistry procedureRegistry, LogTableRegistry tableRegistry) {
this.qs = qs;
this.scriptRegistry = scriptRegistry;
this.lookup = lookup;
this.csvRegistry = csvRegistry;
this.accountService = accountService;
this.savedResultManager = savedResultManager;
this.procedureRegistry = procedureRegistry;
this.tableRegistry = tableRegistry;
}
@Override
public void setScriptContext(ScriptContext context) {
this.context = context;
}
public void authServices(String[] args) {
context.println("External Auth Services");
context.println("------------------------");
ExternalAuthService using = accountService.getUsingAuthService();
for (ExternalAuthService s : accountService.getAuthServices()) {
context.print(using == s ? "[*] " : "[ ] ");
context.println(s.getName() + " - " + s);
}
}
public void useAuthService(String[] args) {
accountService.useAuthService(args.length > 0 ? args[0] : null);
context.println(args.length > 0 ? "set" : "unset");
}
public void sessions(String[] args) {
context.println("Current Sessions");
context.println("------------------");
for (Session session : accountService.getSessions()) {
context.println(session);
}
}
public void accounts(String[] args) {
context.println("Accounts");
context.println("----------");
for (String loginName : accountService.getAccountNames()) {
Account account = accountService.getAccount(loginName);
String admin = "";
if (account.isAdmin())
admin = " (admin)";
context.println(loginName + admin);
}
}
@ScriptUsage(description = "open console", arguments = { @ScriptArgument(name = "login name", type = "string", description = "db account name") })
public void console(String[] args) {
new Console(context, accountService, qs, savedResultManager).run(args[0]);
}
public void csvLookups(String[] args) {
context.println("CSV Mapping Files");
context.println("-------------------");
for (File f : csvRegistry.getCsvFiles()) {
context.println(f.getAbsolutePath());
}
}
@ScriptUsage(description = "create new query script workspace", arguments = { @ScriptArgument(name = "workspace name", type = "string", description = "query script workspace name") })
public void createScriptWorkspace(String[] args) {
scriptRegistry.createWorkspace(args[0]);
context.println("created");
}
@ScriptUsage(description = "remove query script workspace", arguments = { @ScriptArgument(name = "workspace name", type = "string", description = "query script workspace name") })
public void dropScriptWorkspace(String[] args) {
scriptRegistry.dropWorkspace(args[0]);
context.println("dropped");
}
@ScriptUsage(description = "load csv lookup mapping file", arguments = { @ScriptArgument(name = "path", type = "string", description = "csv (comma separated value) file path. first line should be column headers.", autocompletion = PathAutoCompleter.class) })
public void loadCsvLookup(String[] args) throws IOException {
try {
File f = new File(args[0]);
csvRegistry.loadCsvFile(f);
context.println("loaded " + f.getAbsolutePath());
} catch (IllegalStateException e) {
context.println(e);
}
}
@ScriptUsage(description = "reload csv lookup mapping file", arguments = { @ScriptArgument(name = "path", type = "string", description = "csv (comma separated value) file path. first line should be column headers.", autocompletion = PathAutoCompleter.class) })
public void reloadCsvLookup(String[] args) throws IOException {
try {
File f = new File(args[0]);
csvRegistry.unloadCsvFile(f);
csvRegistry.loadCsvFile(f);
context.println("reloaded");
} catch (IllegalStateException e) {
context.println(e);
}
}
@ScriptUsage(description = "unload csv lookup mapping file", arguments = { @ScriptArgument(name = "path", type = "string", description = "registered csv file path", autocompletion = PathAutoCompleter.class) })
public void unloadCsvLookup(String[] args) {
File f = new File(args[0]);
csvRegistry.unloadCsvFile(f);
context.println("unloaded" + f.getAbsolutePath());
}
public void scripts(String[] args) {
context.println("Log Scripts");
context.println("--------------");
for (String workspace : scriptRegistry.getWorkspaceNames()) {
context.println("Workspace: " + workspace);
for (String name : scriptRegistry.getScriptFactoryNames(workspace)) {
QueryScriptFactory factory = scriptRegistry.getScriptFactory(workspace, name);
context.println(" " + name + " - " + factory);
}
}
}
public void lookupHandlers(String[] args) {
context.println("Lookup Handlers");
context.println("---------------------");
for (String name : lookup.getLookupHandlerNames())
context.println(name);
}
/**
* @since 0.14.0
*/
public void queries(String[] args) {
String queryFilter = null;
if (args.length > 0)
queryFilter = args[0];
QueryPrintHelper.printQueries(context, qs.getQueries(), queryFilter);
}
/**
* @since 0.16.2
*/
@ScriptUsage(description = "print specific query status", arguments = { @ScriptArgument(name = "query id", type = "int", description = "query id") })
public void queryStatus(String[] args) {
Integer id = Integer.valueOf(args[0]);
Query q = qs.getQuery(id);
if (q == null) {
context.println("query " + id + " not found");
return;
}
context.println("Query Status");
context.println("------------------");
context.println(QueryPrintHelper.getQueryStatus(q));
}
/**
* @since 0.14.0
*/
@ScriptUsage(description = "remove query", arguments = { @ScriptArgument(name = "query id", type = "int", description = "query id") })
public void removeQuery(String[] args) {
for (String arg : args) {
Integer id = Integer.valueOf(arg);
if (qs.getQuery(id) != null) {
qs.removeQuery(id);
context.println("removed query " + arg);
} else {
context.println("query " + id + " not found");
}
}
}
/**
* @since 0.16.2
*/
public void removeAllQueries(String[] args) {
for (Query q : qs.getQueries()) {
qs.removeQuery(q.getId());
context.println("removed query " + q.getId());
}
}
/**
* @since 2.0.3
*/
@ScriptUsage(description = "delete saved query result", arguments = { @ScriptArgument(name = "guid", type = "string", description = "the guid of saved query result") })
public void deleteSavedResult(String[] args) throws IOException {
String guid = args[0];
SavedResult sr = savedResultManager.getResult(guid);
if (sr == null) {
context.println("query result not found");
return;
}
savedResultManager.deleteResult(guid);
context.println("deleted '" + sr.getTitle() + "', " + sr.getFileSize() + " bytes, " + sr.getRowCount() + " rows");
}
/**
* @since 2.0.3
*/
@ScriptUsage(description = "list all saved query results", arguments = { @ScriptArgument(name = "owner", type = "string", description = "login name", optional = true) })
public void savedResults(String[] args) {
String owner = args.length > 0 ? args[0] : null;
List<SavedResult> savedResults = savedResultManager.getResultList(owner);
context.println("Saved Query Results");
context.println("---------------------");
for (SavedResult sr : savedResults) {
context.println(sr);
}
context.println("total " + savedResults.size() + " results");
}
public void instanceGuid(String[] args) {
context.println(accountService.getInstanceGuid());
}
public void setInstanceGuid(String[] args) {
accountService.setInstanceGuid(args[0]);
}
public void procedures(String[] args) {
context.println("Procedures");
context.println("------------");
for (Procedure p : procedureRegistry.getProcedures()) {
int i = 0;
String signature = p.getName() + "(";
for (ProcedureParameter param : p.getParameters()) {
if (i++ != 0)
signature += ", ";
signature += param;
}
signature += ")";
context.println(signature + ", owner=" + p.getOwner());
}
}
@ScriptUsage(description = "print procedure details", arguments = { @ScriptArgument(name = "name", type = "string", description = "procedure name") })
public void procedure(String[] args) {
Procedure p = procedureRegistry.getProcedure(args[0]);
if (p == null) {
context.println("procedure not found");
return;
}
context.println(p);
}
public void createProcedure(String[] args) {
try {
Procedure proc = inputProcedure(null);
procedureRegistry.createProcedure(proc);
context.println("created");
} catch (InterruptedException e) {
context.println("");
context.println("interrupted");
}
}
public void updateProcedure(String[] args) {
try {
String name = readLine("name", null);
Procedure old = procedureRegistry.getProcedure(name);
if (old == null) {
context.println("procedure not found: " + name);
return;
}
Procedure proc = inputProcedure(old);
proc.setCreated(old.getCreated());
procedureRegistry.updateProcedure(proc);
context.println("updated");
} catch (InterruptedException e) {
context.println("");
context.println("interrupted");
}
}
@ScriptUsage(description = "grant procedure", arguments = {
@ScriptArgument(name = "procedure name", type = "string", description = "procedure name"),
@ScriptArgument(name = "type", type = "string", description = "'user' or 'group'"),
@ScriptArgument(name = "login name", type = "string", description = "login name") })
public void grantProcedure(String[] args) {
String procName = args[0];
String type = args[1];
String target = args[2];
Procedure p = procedureRegistry.getProcedure(procName);
if (p == null) {
context.println("procedure not found");
return;
}
if (type.equals("user")) {
if (!p.getGrants().contains(target)) {
p.getGrants().add(target);
procedureRegistry.updateProcedure(p);
}
} else if (type.equals("group")) {
Map<String, SecurityGroup> groupMap = getSecurityGroupMap();
SecurityGroup old = groupMap.get(target);
if (old != null) {
p.getGrantGroups().add(old.getGuid());
procedureRegistry.updateProcedure(p);
}
} else {
context.println("invalid type. use 'user' or 'group'");
return;
}
context.println("granted");
}
@ScriptUsage(description = "revoke procedure", arguments = {
@ScriptArgument(name = "procedure name", type = "string", description = "procedure name"),
@ScriptArgument(name = "type", type = "string", description = "user or group"),
@ScriptArgument(name = "login name", type = "string", description = "login name") })
public void revokeProcedure(String[] args) {
String procName = args[0];
String type = args[1];
String target = args[2];
Procedure p = procedureRegistry.getProcedure(procName);
if (p == null) {
context.println("procedure not found");
return;
}
if (type.equals("user")) {
p.getGrants().remove(target);
procedureRegistry.updateProcedure(p);
} else if (type.equals("group")) {
Map<String, SecurityGroup> groupMap = getSecurityGroupMap();
SecurityGroup old = groupMap.get(target);
if (old != null) {
p.getGrantGroups().remove(old.getGuid());
procedureRegistry.updateProcedure(p);
}
} else {
context.println("invalid type. use 'user' or 'group'");
return;
}
context.println("revoked");
}
private Procedure inputProcedure(Procedure old) throws InterruptedException {
Procedure proc = new Procedure();
if (old == null)
proc.setName(readLine("name", null));
else
proc.setName(old.getName());
proc.setOwner(readLine("owner", old != null ? old.getOwner() : null));
proc.setGrants(new HashSet<String>(Strings.tokenize(
readLine("grants", old != null ? Strings.join(old.getGrants(), ", ") : null), ",")));
proc.setQueryString(readLine("query", old != null ? old.getQueryString() : null));
List<ProcedureParameter> parameters = new ArrayList<ProcedureParameter>();
context.println("Type parameter definitions in \"type name\" format. e.g. \"string opt\", press enter to end.");
int idx = 0;
while (true) {
ProcedureParameter oldParam = null;
if (old != null && idx < old.getParameters().size()) {
oldParam = old.getParameters().get(idx);
}
context.print("parameter? ");
String line = context.readLine(oldParam != null ? oldParam.toString() : null);
if (line.isEmpty())
break;
int p = line.indexOf(" ");
String type = line.substring(0, p).trim();
String key = line.substring(p + 1).trim();
parameters.add(new ProcedureParameter(key, type));
idx++;
}
proc.setParameters(parameters);
return proc;
}
private String readLine(String prompt, String old) throws InterruptedException {
context.print(prompt + "? ");
return context.readLine(old);
}
@ScriptUsage(description = "remove procedure", arguments = { @ScriptArgument(name = "procedure name", type = "string", description = "procedure name") })
public void removeProcedure(String[] args) {
String name = args[0];
Procedure p = procedureRegistry.getProcedure(name);
if (p == null) {
context.println("procedure not found: " + name);
return;
}
procedureRegistry.removeProcedure(name);
context.println("removed");
}
@ScriptUsage(description = "set hash join threshold", arguments = { @ScriptArgument(name = "threshold", type = "int", description = "hash join threshold") })
public void setHashJoinThreshold(String[] args) {
System.setProperty("araqne.hashjointhreshold", args[0]);
context.println("set hash join threshold");
}
@ScriptUsage(description = "get hash join threshold")
public void getHashJoinThreshold(String[] args) {
context.println("hash join threshold :" + System.getProperty("araqne.hashjointhreshold", "100000"));
}
public void securityGroups(String[] args) {
context.println("Security Groups");
context.println("-----------------");
for (SecurityGroup group : accountService.getSecurityGroups()) {
context.println(group);
}
}
@ScriptUsage(description = "create security group", arguments = {
@ScriptArgument(name = "group name", type = "string", description = "name of security group"),
@ScriptArgument(name = "description", type = "string", description = "description", optional = true) })
public void createSecurityGroup(String[] args) {
SecurityGroup group = new SecurityGroup();
group.setName(args[0]);
if (args.length > 1)
group.setDescription(args[1]);
accountService.createSecurityGroup(null, group);
context.println("created");
}
@ScriptUsage(description = "remove security group", arguments = { @ScriptArgument(name = "group name", type = "string", description = "name of security group") })
public void removeSecurityGroup(String[] args) {
SecurityGroup found = findSecurityGroupByName(args[0]);
if (found == null) {
context.println("security group not found");
return;
}
accountService.removeSecurityGroup(null, found.getGuid());
context.println("removed");
}
@ScriptUsage(description = "join security group", arguments = {
@ScriptArgument(name = "group name", type = "string", description = "name of security group"),
@ScriptArgument(name = "login name", type = "string", description = "account login name") })
public void joinSecurityGroup(String[] args) {
SecurityGroup group = findSecurityGroupByName(args[0]);
if (group == null) {
context.println("security group not found");
return;
}
for (int i = 1; i < args.length; i++) {
String loginName = args[i];
Account account = accountService.getAccount(loginName);
if (account == null) {
context.println("account [" + loginName + "] not found. skipping.");
continue;
}
group.getAccounts().add(account.getLoginName());
}
accountService.updateSecurityGroup(null, group);
context.println("updated");
}
@ScriptUsage(description = "leave security group", arguments = {
@ScriptArgument(name = "group name", type = "string", description = "name of security group"),
@ScriptArgument(name = "login name", type = "string", description = "account login name") })
public void leaveSecurityGroup(String[] args) {
SecurityGroup group = findSecurityGroupByName(args[0]);
if (group == null) {
context.println("security group not found");
return;
}
for (int i = 1; i < args.length; i++)
group.getAccounts().remove(args[i]);
accountService.updateSecurityGroup(null, group);
context.println("updated");
}
@ScriptUsage(description = "grant table access", arguments = {
@ScriptArgument(name = "table name", type = "string", description = "table name"),
@ScriptArgument(name = "type", type = "string", description = "user or group"),
@ScriptArgument(name = "login name or group name", type = "string", description = "name of user or security group") })
public void grantTable(String[] args) {
String tableName = args[0];
String type = args[1];
if (!tableRegistry.exists(tableName)) {
context.println("table not found: " + tableName);
return;
}
if (!type.equals("user") && !type.equals("group")) {
context.println("invalid type, use 'user' or 'group'");
return;
}
if (type.equals("user")) {
for (int i = 2; i < args.length; i++) {
String loginName = args[i];
if (accountService.getAccount(loginName) == null) {
context.println("account [" + loginName + "] not found, skipping");
continue;
}
accountService.grantPrivilege(null, loginName, tableName, Permission.READ);
}
} else if (type.equals("group")) {
Map<String, SecurityGroup> groupMap = getSecurityGroupMap();
for (int i = 2; i < args.length; i++) {
String groupName = args[i];
SecurityGroup group = groupMap.get(groupName);
if (group == null) {
context.println("security group [" + groupName + "] not found, skipping");
continue;
}
group.getReadableTables().add(tableName);
accountService.updateSecurityGroup(null, group);
}
}
context.println("granted");
}
@ScriptUsage(description = "revoke table access from group", arguments = {
@ScriptArgument(name = "table name", type = "string", description = "table name"),
@ScriptArgument(name = "type", type = "string", description = "user or group"),
@ScriptArgument(name = "login name or group name", type = "string", description = "name of user or security group") })
public void revokeTable(String[] args) {
String tableName = args[0];
String type = args[1];
if (!tableRegistry.exists(tableName)) {
context.println("table not found: " + tableName);
return;
}
if (!type.equals("user") && !type.equals("group")) {
context.println("invalid type, use 'user' or 'group'");
return;
}
if (type.equals("user")) {
for (int i = 2; i < args.length; i++) {
String loginName = args[i];
if (accountService.getAccount(loginName) == null) {
context.println("account [" + loginName + "] not found, skipping");
continue;
}
accountService.revokePrivilege(null, loginName, tableName, Permission.READ);
}
} else if (type.equals("group")) {
Map<String, SecurityGroup> groupMap = getSecurityGroupMap();
for (int i = 2; i < args.length; i++) {
String groupName = args[i];
SecurityGroup group = groupMap.get(groupName);
if (group == null) {
context.println("security group [" + groupName + "] not found, skipping");
continue;
}
group.getReadableTables().remove(tableName);
accountService.updateSecurityGroup(null, group);
}
}
context.println("revoked");
}
// name to security group map
private Map<String, SecurityGroup> getSecurityGroupMap() {
Map<String, SecurityGroup> m = new HashMap<String, SecurityGroup>();
for (SecurityGroup group : accountService.getSecurityGroups()) {
m.put(group.getName(), group);
}
return m;
}
private SecurityGroup findSecurityGroupByName(String name) {
SecurityGroup found = null;
for (SecurityGroup group : accountService.getSecurityGroups()) {
if (group.getName().equals(name)) {
found = group;
break;
}
}
return found;
}
}