blob: cd86ce4f18df44f0a5a10eae857c0a659c5a9ae1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.vinci.transport.vns.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Random;
import java.util.StringTokenizer;
import org.apache.vinci.transport.BaseClient;
import org.apache.vinci.transport.FrameLeaf;
import org.apache.vinci.transport.KeyValuePair;
import org.apache.vinci.transport.QueryableFrame;
import org.apache.vinci.transport.Transportable;
import org.apache.vinci.transport.VinciFrame;
import org.apache.vinci.transport.context.VinciContext;
import org.apache.vinci.transport.vns.VNSConstants;
/**
* Provides a command-line interface for querying VNS.
*/
public class NameClient {
String vnsHost;
int vnsPort = 9000;
static class HitsList {
public HitsList() {
}
String[] types;
int[] hits;
int totalhits;
String starttime;
};
static Random R = new Random();
public NameClient() {
configure(VinciContext.getGlobalContext().getVNSHost(), VinciContext.getGlobalContext()
.getVNSPort());
}
public NameClient(String host, int port) {
configure(host, port);
}
// Configure the VNS host / port
public void configure(String host, int port) {
if (host != null) {
vnsHost = host;
}
if (port > -1) {
vnsPort = port;
}
}
// Method to parse a fully qualified name into sub-parts
public static ServiceInfo parseQName(String qname) {
String[] result = new String[5];
int i = qname.indexOf("/");
if (i > -1)
result[0] = qname.substring(0, i);
i++;
qname = qname.substring(i);
i = qname.indexOf("[");
String lhi;
if (i > -1) {
lhi = qname.substring(i + 1, qname.length() - 1);
StringTokenizer str = new StringTokenizer(lhi, ",");
int j = 2;
while (str.hasMoreTokens())
result[j++] = str.nextToken().trim();
} else
i = qname.length();
result[1] = qname.substring(0, i);
return new ServiceInfo(result);
}
// Methods to perform service lookup
public ServiceInfo[] lookup(String name, int level, String host, String instance, String ws) {
VinciFrame req = new VinciFrame();
req.fadd("vinci:COMMAND", VNSConstants.RESOLVE_COMMAND).fadd("SERVICE", name).fadd("LEVEL",
level).fadd("HOST", host).fadd("INSTANCE", instance).fadd("WORKSPACE", ws);
System.out.println(req.toXML());
VinciFrame resp = (VinciFrame) transmit(req);
checkError(resp);
return constructServiceInfo(resp.fget("SERVER"), resp.fgetString("LEVEL"), name);
}
public ServiceInfo[] lookup(String name) {
return lookup(name, -1, null, null, null);
}
public ServiceInfo[] lookup(String name, int level) {
return lookup(name, level, null, null, null);
}
public ServiceInfo[] lookup(String name, int level, String host) {
return lookup(name, level, host, null, null);
}
public ServiceInfo[] lookup(String name, int level, String host, String instance) {
return lookup(name, level, host, instance, null);
}
public ServiceInfo[] lookup(String name, String host) {
return lookup(name, -1, host, null, null);
}
public ServiceInfo[] lookup(String name, String host, String instance) {
return lookup(name, -1, host, instance, null);
}
public ServiceInfo[] lookup(String name, String host, String instance, String ws) {
return lookup(name, -1, host, instance, ws);
}
// Method to perform service resolve
public ServiceInfo resolve(String name, String host, String ip, String ws, int level, int inst) {
VinciFrame req = new VinciFrame();
req.fadd("vinci:COMMAND", VNSConstants.RESOLVE_COMMAND).fadd("SERVICE", name);
smFrameAdd(req, "HOST", host);
smFrameAdd(req, "IP", ip);
smFrameAdd(req, "WORKSPACE", ws);
req.fadd("LEVEL", level);
if (inst > 0) {
req.fadd("INSTANCE", inst);
}
VinciFrame resp = (VinciFrame) transmit(req);
checkError(resp);
ServiceInfo[] S = constructServiceInfo(resp.fget("SERVER"), resp.fgetString("LEVEL"), name);
return ((S.length > 0) ? S[R.nextInt(S.length)] : null);
}
public static void smFrameAdd(VinciFrame v, String tag, String val) {
if (val != null && tag != null)
v.fadd(tag, val);
}
public ServiceInfo resolve(String name, int level) {
VinciFrame req = (VinciFrame) new VinciFrame().fadd("vinci:COMMAND",
VNSConstants.RESOLVE_COMMAND).fadd("SERVICE", name).fadd("LEVEL", level);
VinciFrame resp = (VinciFrame) transmit(req);
checkError(resp);
ServiceInfo[] S = constructServiceInfo(resp.fget("SERVER"), resp.fgetString("LEVEL"), name);
return ((S.length > 0) ? S[R.nextInt(S.length)] : null);
}
public ServiceInfo resolve(String name) {
return resolve(name, -1);
}
// Method to get the list of services that are registered
public ServiceInterface[] getList(String prefix, String level) {
VinciFrame req = new VinciFrame();
req.fadd("vinci:COMMAND", VNS.dirCmdGetList);
req.fadd("LEVEL", level);
smartAdd(req, "PREFIX", prefix);
VinciFrame resp = (VinciFrame) transmit(req);
checkError(resp);
ArrayList A = resp.fget("SERVICE");
Hashtable H;
QueryableFrame Q;
ServiceInterface[] S = new ServiceInterface[A.size()];
for (int i = 0; i < A.size(); i++) {
Q = (QueryableFrame) A.get(i);
// Check if it is a Service or a ServiceAlias and parse accordingly
if (Q.fgetString("TARGET") == null) {
H = new Hashtable();
int total = Q.getKeyValuePairCount();
KeyValuePair P = null;
for (int j = 0; j < total; j++) {
P = Q.getKeyValuePair(j);
if (P.isValueALeaf()) {
H.put(P.getKey(), P.getValueAsString());
} else {
H.put(P.getKey(), P.getValue());
}
}
S[i] = new Service(H);
} else {
S[i] = new ServiceAlias(Q.fgetString("NAME"), Q.fgetString("TARGET"));
}
}
return S;
}
public ServiceInterface[] getList(String prefix, int level) {
return getList(prefix, "" + level);
}
public ServiceInterface[] getList() {
return getList(null, -1);
}
public ServiceInterface[] getList(String prefix) {
return getList(prefix, -1);
}
public ServiceInterface[] getList(int level) {
return getList(null, level);
}
// Method to get the registered service names
public String[] getNames(String prefix, String level) {
VinciFrame req = new VinciFrame();
req.fadd("vinci:COMMAND", VNS.dirCmdGetNames);
req.fadd("LEVEL", level);
smartAdd(req, "PREFIX", prefix);
VinciFrame resp = (VinciFrame) transmit(req);
checkError(resp);
ArrayList A = resp.fget("SERVICE");
String[] S = new String[A.size()];
for (int i = 0; i < A.size(); i++) {
S[i] = ((FrameLeaf) A.get(i)).toString().trim();
}
return S;
}
public String[] getNames(String prefix, int level) {
return getNames(prefix, "" + level);
}
public String[] getNames() {
return getNames(null, -1);
}
public String[] getNames(String prefix) {
return getNames(prefix, -1);
}
public String[] getNames(int level) {
return getNames(null, level);
}
// Method to get the hits for a particular service
public int getHits(String type) {
VinciFrame out = new VinciFrame();
out.fadd("vinci:COMMAND", VNS.dirCmdGetHits);
smartAdd(out, "TYPE", type);
VinciFrame resp = (VinciFrame) transmit(out);
checkError(resp);
return (resp.fgetInt("HITS"));
}
public int getHits() {
return getHits(null);
}
// Method to get all the hits
public HitsList getAllHits() {
VinciFrame out = new VinciFrame();
out.fadd("vinci:COMMAND", VNS.dirCmdGetHits);
out.fadd("TYPE", "all");
VinciFrame resp = (VinciFrame) transmit(out);
checkError(resp);
HitsList H = new HitsList();
H.totalhits = resp.fgetInt("TOTAL");
H.starttime = resp.fgetString("STARTED");
ArrayList A = resp.fget("HITS");
H.hits = new int[A.size()];
H.types = new String[A.size()];
QueryableFrame Q;
for (int i = 0; i < H.hits.length; i++) {
Q = (QueryableFrame) A.get(i);
H.hits[i] = Q.fgetInt("COUNT");
H.types[i] = Q.fgetString("TYPE");
}
return H;
}
// Method to delete a service
public boolean delService(Service S) {
return modifyService(S, VNS.dirCmdDelService);
}
// Method to add a service
public boolean addService(Service S) {
return modifyService(S, VNS.dirCmdAddService);
}
// Method to update a service
public boolean updateService(Service S) {
return modifyService(S, VNS.dirCmdUpdateService);
}
// Generic service interaction method
public boolean modifyService(Service S, String type) {
VinciFrame out = new VinciFrame();
out.fadd("vinci:COMMAND", type);
out.fadd("SERVICE", S.toFrame());
VinciFrame resp = (VinciFrame) transmit(out);
checkError(resp);
return (resp.fgetString("STATUS").toLowerCase().trim().equals("ok"));
}
// Method to add an alias
public boolean addAlias(String name, String target) {
return modifyAlias(VNS.dirCmdAddAlias, name, target);
}
// Method to del an alias
public boolean delAlias(String name) {
return modifyAlias(VNS.dirCmdAddAlias, name, null);
}
// Generic alias interaction method
public boolean modifyAlias(String type, String name, String target) {
VinciFrame out = new VinciFrame();
out.fadd("vinci:COMMAND", type);
VinciFrame srv = new VinciFrame();
smartAdd(srv, "NAME", name);
smartAdd(srv, "TARGET", target);
out.fadd("SERVICE", srv);
VinciFrame resp = (VinciFrame) transmit(out);
checkError(resp);
return (resp.fgetString("STATUS").toLowerCase().trim().equals("ok"));
}
// Method to find out the port to serve on
public int[] serveon(String name, String host, int level, int instance) {
if (strip(host) == null || host.trim().toLowerCase().equals("localhost")) {
try {
host = InetAddress.getLocalHost().getHostName();
} catch (Exception e) {
throw new RuntimeException("Could not resolve local host");
}
}
VinciFrame out = (VinciFrame) new VinciFrame().fadd("vinci:COMMAND",
VNSConstants.SERVEON_COMMAND).fadd("SERVICE", name).fadd("HOST", host).fadd("LEVEL",
level).fadd("INSTANCE", instance);
VinciFrame resp = (VinciFrame) transmit(out);
checkError(resp);
int[] result = new int[3];
result[0] = resp.fgetInt("PORT");
result[1] = resp.fgetInt("LEVEL");
result[2] = resp.fgetInt("INSTANCE");
return result;
}
public int[] serveon(String name) {
return serveon(name, null, -1, 0);
}
// Helper methods
private void smartAdd(VinciFrame req, String tag, String val) {
if (val != null)
req.fadd(tag, val);
}
private ServiceInfo[] constructServiceInfo(ArrayList A, String level, String name) {
if (level == null)
level = "-1";
ServiceInfo[] S = new ServiceInfo[A.size()];
QueryableFrame L;
for (int i = 0; i < S.length; i++) {
L = (QueryableFrame) A.get(i);
S[i] = new ServiceInfo(name, L.fgetString("HOST"), L.fgetString("PORT"), level, L
.fgetString("INSTANCE"));
}
return S;
}
private Transportable transmit(Transportable T) {
try {
return BaseClient.rpc(T, vnsHost, vnsPort);
} catch (Exception e) {
VinciFrame F = new VinciFrame();
F.fadd("vinci:ERROR", e.toString());
return F;
}
}
private void checkError(VinciFrame in) {
String s = in.fgetString("vinci:ERROR");
if (s != null)
throw new RuntimeException(s);
}
// Main method for testing
public static void main(String[] args) {
NameClient nc = new NameClient();
if (args.length > 1) {
nc.configure(args[0], Integer.parseInt(args[1]));
}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s;
while (true) {
prMainMenu();
s = getLine(br).trim();
if (s.equals("q"))
break;
try {
switch (parseMainOption(s)) {
case 0:
handleParseQName(br, nc);
break;
case 1:
handleLookup(br, nc);
break;
case 2:
handleResolve(br, nc);
break;
case 3:
handleGetList(br, nc);
break;
case 4:
handleGetNames(br, nc);
break;
case 5:
handleGetHits(br, nc);
break;
case 6:
handleGetAllHits(br, nc);
break;
case 7:
handleServeon(br, nc);
break;
case 8:
handleAddService(br, nc);
break;
default:
pr("Unknown option");
}
} catch (RuntimeException e) {
pr("" + e);
}
}
}
private static void handleParseQName(BufferedReader br, NameClient nc) {
pr("Enter the qname to parse : ", false);
ServiceInfo S = NameClient.parseQName(getLine(br));
pr(S.toString());
}
private static void handleLookup(BufferedReader br, NameClient nc) {
pr("Enter the service name : ", false);
String name = getLine(br);
pr("Enter the level : ", false);
String level = strip(getLine(br));
int l = -1;
try {
l = Integer.parseInt(level);
} catch (Exception e) {
l = -1;
}
pr("Enter the host : ", false);
String host = strip(getLine(br));
pr("Enter the instance : ", false);
String instance = strip(getLine(br));
pr("Enter the workspace : ", false);
String ws = strip(getLine(br));
ServiceInfo[] S = nc.lookup(name, l, host, instance, ws);
for (int i = 0; i < S.length; i++)
pr("Service " + i + ":\n" + S[i]);
}
private static void handleResolve(BufferedReader br, NameClient nc) {
pr("Enter the service name : ", false);
String name = getLine(br);
pr("Enter the service host : ", false);
String host = getLine(br);
pr("Enter the service IP : ", false);
String ip = getLine(br);
pr("Enter the service workspace : ", false);
String ws = getLine(br);
pr("Enter the level : ", false);
String level = strip(getLine(br));
int l = -1;
try {
l = Integer.parseInt(level);
} catch (Exception e) {
l = -1;
}
ServiceInfo S = nc.resolve(strip(name), strip(host), strip(ip), strip(ws), l, -1);
pr("Service : \n" + S);
}
private static void handleServeon(BufferedReader br, NameClient nc) {
pr("Enter the service name : ", false);
String name = getLine(br);
pr("Enter the host : ", false);
String host = strip(getLine(br));
pr("Enter the level : ", false);
String level = strip(getLine(br));
int l = -1;
try {
l = Integer.parseInt(level);
} catch (Exception e) {
l = -1;
}
pr("Enter the instance : ", false);
String instance = strip(getLine(br));
int inst = 0;
try {
inst = Integer.parseInt(instance);
} catch (Exception e) {
inst = 0;
}
int[] temp = nc.serveon(name, host, l, inst);
pr("PORT: " + temp[0]);
}
private static void handleGetList(BufferedReader br, NameClient nc) {
pr("Enter the prefix : ", false);
String name = getLine(br);
pr("Enter the level : ", false);
String level = strip(getLine(br));
// int l = -1;
// try {
// l = Integer.parseInt(level);
// } catch (Exception e) {
// l = -1;
// }
Object[] S = nc.getList(name, level);
for (int i = 0; i < S.length; i++)
if (ServiceAlias.isAlias(S[i]))
pr("Service alias " + i + ":\n" + ((ServiceAlias) S[i]).toXML());
else
pr("Service " + i + ":\n" + ((Service) S[i]).toXML());
}
private static void handleGetNames(BufferedReader br, NameClient nc) {
pr("Enter the prefix : ", false);
String name = getLine(br);
pr("Enter the level : ", false);
String level = strip(getLine(br));
// int l = -1;
// try {
// l = Integer.parseInt(level);
// } catch (Exception e) {
// l = -1;
// }
String[] S = nc.getNames(name, level);
for (int i = 0; i < S.length; i++)
pr("Service " + i + ": " + S[i]);
}
private static void handleGetHits(BufferedReader br, NameClient nc) {
pr("Enter the type : ", false);
String type = getLine(br);
pr("Result : " + nc.getHits(type));
}
private static void handleGetAllHits(BufferedReader br, NameClient nc) {
HitsList H = nc.getAllHits();
for (int i = 0; i < H.hits.length; i++) {
pr("[" + i + "] " + H.types[i].trim() + " : " + H.hits[i]);
}
pr("Total : " + H.totalhits);
pr("Starttime : " + H.starttime);
}
private static void handleAddService(BufferedReader br, NameClient nc) {
pr("Enter the service name : ", false);
String name = getLine(br);
pr("Enter the service host : ", false);
String host = getLine(br);
pr("Enter the service level : ", false);
String level = getLine(br);
pr("Enter the service minport : ", false);
String minport = getLine(br);
pr("Enter the service maxport : ", false);
String maxport = getLine(br);
pr("Enter the service port : ", false);
String port = getLine(br);
Hashtable H = new Hashtable();
smAddHT(H, "NAME", name);
smAddHT(H, "HOST", host);
smAddHT(H, "LEVEL", level);
smAddHT(H, "MINPORT", minport);
smAddHT(H, "MAXPORT", maxport);
smAddHT(H, "PORT", port);
Service S = new Service(H);
if (nc.addService(S))
System.out.println("Successfully added service.\n" + S);
else
System.out.println("Could not add the service");
}
private static String[] options = { "parseqname", "lookup", "resolve", "getlist", "getnames",
"gethits", "getallhits", "serveon", "addservice" };
private static void prMainMenu() {
pr("\nMenu \n");
for (int i = 0; i < options.length; i++) {
pr("" + i + " : " + options[i]);
}
pr("\nq : quit\n");
pr("Enter your selection : ", false);
}
private static void smAddHT(Hashtable H, String key, String val) {
if (key != null && val != null)
H.put(key, val);
}
private static int parseMainOption(String s) {
s = s.toLowerCase().trim();
for (int i = 0; i < options.length; i++)
if (s.equals(options[i]))
return i;
try {
return Integer.parseInt(s);
} catch (Exception e) {
}
return -1;
}
public static String pr(String s) {
System.out.println(s);
return s;
}
public static String pr(String s, boolean newline) {
System.out.print(s + ((newline) ? "\n" : ""));
return s;
}
private static String strip(String s) {
if (s == null || s.trim().equals(""))
return null;
return s.trim();
}
private static String getLine(BufferedReader br) {
try {
return br.readLine();
} catch (IOException e) {
return null;
}
}
}