%@ page contentType="application/json; charset=utf-8" pageEncoding="UTF-8" %>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ page import="javax.servlet.jsp.JspWriter" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.zookeeper.*" %>
<%@ page import="org.apache.zookeeper.data.Stat" %>
<%@ page import="org.apache.solr.core.*" %>
<%@ page import="org.apache.solr.cloud.*" %>
<%@ page import="org.apache.solr.common.cloud.*" %>
<%@ page import="org.apache.solr.common.util.*" %>
<%@ page import="java.util.concurrent.TimeoutException" %>
<%@ page import="java.io.*" %>
<%@ page import="java.util.*" %>
<%@ page import="java.net.URLEncoder" %>
<% SolrCore core = (SolrCore)request.getAttribute( "org.apache.solr.SolrCore" ); %>
<%!
static class ZKPrinter
{
static boolean FULLPATH_DEFAULT = false;
boolean indent = true;
boolean fullpath = FULLPATH_DEFAULT;
boolean detail = false;
String addr; // the address passed to us
String keeperAddr; // the address we're connected to
boolean doClose; // close the client after done if we opened it
HttpServletResponse response;
JspWriter out;
SolrZkClient zkClient;
private boolean levelchange;
int level;
int maxData = 95;
public ZKPrinter(HttpServletResponse response, JspWriter out, SolrCore core, String addr)
throws IOException
{
this.response = response;
this.out = out;
this.addr = addr;
if (addr == null)
{
ZkController controller = core.getCoreDescriptor().getCoreContainer().getZkController();
if (controller != null)
{
// this core is zk enabled
keeperAddr = controller.getZkServerAddress();
zkClient = controller.getZkClient();
if (zkClient != null && zkClient.isConnected())
{
return;
}
else
{
// try a different client with this address
addr = keeperAddr;
}
}
}
keeperAddr = addr;
if (addr == null)
{
response.setStatus(404);
out.println
(
"{" +
"\"status\": 404" +
", \"error\" : \"Zookeeper is not configured for this Solr Core. Please try connecting to an alternate zookeeper address.\"" +
"}"
);
return;
}
try
{
zkClient = new SolrZkClient(addr, 10000);
doClose = true;
}
catch (TimeoutException e)
{
response.setStatus(503);
out.println
(
"{" +
"\"status\": 503" +
", \"error\" : \"Could not connect to zookeeper at '" + addr + "'\"" +
"}"
);
zkClient = null;
return;
}
catch (InterruptedException e)
{
// Restore the interrupted status
Thread.currentThread().interrupt();
response.setStatus(503);
out.println
(
"{" +
"\"status\": 503" +
", \"error\" : \"Could not connect to zookeeper at '" + addr + "'\"" +
"}"
);
zkClient = null;
return;
}
}
public void close()
{
try
{
if (doClose)
{
zkClient.close();
}
} catch (InterruptedException e)
{
// ignore exception on close
}
}
// main entry point
void print(String path) throws IOException
{
if (zkClient == null)
{
return;
}
// normalize path
if (path == null)
{
path = "/";
}
else
{
path.trim();
if (path.length() == 0)
{
path = "/";
}
}
if (path.endsWith("/") && path.length() > 1)
{
path = path.substring(0, path.length() - 1);
}
int idx = path.lastIndexOf('/');
String parent = idx >= 0 ? path.substring(0, idx) : path;
if (parent.length() == 0)
{
parent = "/";
}
out.println("{");
if (detail)
{
printZnode(path);
out.println(", ");
}
out.println("\"tree\" : [");
printTree(path);
out.println("]");
out.println("}");
}
void exception(Exception e)
{
try
{
response.setStatus(500);
out.println
(
"{" +
"\"status\": 500" +
", \"error\" : \"" + e.toString() + "\"" +
"}"
);
}
catch (IOException e1)
{
// nothing we can do
}
}
void xmlescape(String s)
{
try
{
XML.escapeCharData(s, out);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
// collapse all whitespace to a single space or escaped newline
String compress(String str) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
boolean whitespace = false;
boolean newline = false;
while (Character.isWhitespace(ch)) {
whitespace = true;
if (ch == '\n')
newline = true;
if (++i >= str.length())
return sb.toString();
ch = str.charAt(i);
}
if (newline) {
// sb.append("\\n");
sb.append(" "); // collapse newline to two spaces
} else if (whitespace) {
sb.append(' ');
}
// TODO: handle non-printable chars
sb.append(ch);
if (sb.length() >= maxData)
return sb.toString() + " ...";
}
return sb.toString();
}
void url(String label, String path, boolean detail) throws IOException {
try {
out.print("");
xmlescape(label);
out.print("");
} catch (UnsupportedEncodingException e) {
exception(e);
}
}
void printTree(String path) throws IOException
{
String label = path;
if (!fullpath)
{
int idx = path.lastIndexOf('/');
label = idx > 0 ? path.substring(idx + 1) : path;
}
//url(label, path, true);
out.println("{");
out.println("\"data\" : \"" + label + "\"");
Stat stat = new Stat();
try
{
byte[] data = zkClient.getData(path, null, stat, true);
if( stat.getEphemeralOwner() != 0 )
{
out.println(", \"ephemeral\" : true");
out.println(", \"version\" : \"" + stat.getVersion() + "\"");
}
/*
if (stat.getNumChildren() != 0)
{
out.println(", \"children_count\" : \"" + stat.getNumChildren() + "\"");
}
*/
//if (data != null)
if( stat.getDataLength() != 0 )
{
String str;
try
{
str = new String(data, "UTF-8");
str = str.replaceAll("\\\"", "\\\\\"");
out.print(", \"content\" : \"");
//xmlescape(compress(str));
out.print(compress(str));
out.println("\"");
}
catch (UnsupportedEncodingException e)
{
// not UTF8
StringBuilder sb = new StringBuilder("BIN(");
sb.append("len=" + data.length);
sb.append("hex=");
int limit = Math.min(data.length, maxData / 2);
for (int i = 0; i < limit; i++)
{
byte b = data[i];
sb.append(StrUtils.HEX_DIGITS[(b >> 4) & 0xf]);
sb.append(StrUtils.HEX_DIGITS[b & 0xf]);
}
if (limit != data.length)
{
sb.append("...");
}
sb.append(")");
str = sb.toString();
//out.print(str);
}
}
}
catch (IllegalArgumentException e)
{
// path doesn't exist (must have been removed)
out.println("(path gone)");
}
catch (KeeperException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
if( stat.getNumChildren() > 0 )
{
out.print(", \"children\" : [");
List children = null;
try
{
children = zkClient.getChildren(path, null, true);
}
catch (KeeperException e)
{
exception(e);
return;
}
catch (InterruptedException e)
{
exception(e);
}
catch (IllegalArgumentException e)
{
// path doesn't exist (must have been removed)
out.println("(children gone)");
}
Integer i = 0;
for( String child : children )
{
if( 0 != i )
{
out.print(", ");
}
String childPath = path + (path.endsWith("/") ? "" : "/") + child;
printTree( childPath );
i++;
}
out.println("]");
}
out.println("}");
}
String time(long ms) {
return (new Date(ms)).toString() + " (" + ms + ")";
}
void printZnode(String path) throws IOException
{
try
{
Stat stat = new Stat();
byte[] data = zkClient.getData(path, null, stat, true);
out.println("\"znode\" : {");
out.print("\"path\" : \"");
xmlescape(path);
out.println("\"");
out.println(", \"version\" : \"" + stat.getVersion() + "\"");
out.println(", \"aversion\" : \"" + stat.getAversion() + "\"");
out.println(", \"cversion\" : \"" + stat.getCversion() + "\"");
out.println(", \"ctime\" : \"" + time(stat.getCtime()) + "\"");
out.println(", \"mtime\" : \"" + time(stat.getMtime()) + "\"");
out.println(", \"czxid\" : \"" + stat.getCzxid() + "\"");
out.println(", \"mzxid\" : \"" + stat.getMzxid() + "\"");
out.println(", \"pzxid\" : \"" + stat.getPzxid() + "\"");
out.println(", \"children_count\" : \"" + stat.getNumChildren() + "\"");
out.println(", \"ephemeralOwner\" : \"" + stat.getEphemeralOwner() + "\"");
out.println(", \"dataLength\" : \"" + stat.getDataLength() + "\"");
if( stat.getDataLength() != 0 )
{
boolean isBinary = false;
String str;
try
{
str = new String(data, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
// The results are unspecified
// when the bytes are not properly encoded.
// not UTF8
StringBuilder sb = new StringBuilder(data.length * 2);
for (int i = 0; i < data.length; i++)
{
byte b = data[i];
sb.append(StrUtils.HEX_DIGITS[(b >> 4) & 0xf]);
sb.append(StrUtils.HEX_DIGITS[b & 0xf]);
if ((i & 0x3f) == 0x3f)
{
sb.append("\n");
}
}
str = sb.toString();
}
str = str.replaceAll("\\\"", "\\\\\"");
out.print(", \"data\" : \"");
//xmlescape(str);
out.print(str);
out.println("\"");
}
out.println("}");
}
catch (KeeperException e)
{
exception(e);
return;
}
catch (InterruptedException e)
{
exception(e);
}
}
}
%>
<%
String path = request.getParameter("path");
String addr = request.getParameter("addr");
if (addr != null && addr.length() == 0)
{
addr = null;
}
String detailS = request.getParameter("detail");
boolean detail = detailS != null && detailS.equals("true");
ZKPrinter printer = new ZKPrinter(response, out, core, addr);
printer.detail = detail;
String tryAddr = printer.keeperAddr != null ? printer.keeperAddr : "localhost:2181";
try {
printer.print(path);
} finally {
printer.close();
}
%>