/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.
*
* CVS $Id: UglyBrowser.java,v 1.13 2004/02/11 14:03:09 vgritsenko Exp $
*/
package org.apache.xindice.server;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.Collection;
import org.apache.xindice.core.DBException;
import org.apache.xindice.core.Database;
import org.apache.xindice.xml.TextWriter;
import org.w3c.dom.Document;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.StringTokenizer;
/**
* Moved out of XindiceServlet for separation of display and server bootstrapping.
*
* @author Kevin Ross
* @version CVS $Revision: 1.13 $, $Date: 2004/02/11 14:03:09 $
*/
public class UglyBrowser {
private static final Log log = LogFactory.getLog(UglyBrowser.class);
/**
*
*/
public UglyBrowser() {
super();
}
/**
* Get handling to provide simple HTTP access to the Xindice instance.
*/
public static void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
try {
String contextPath = request.getContextPath();
StringBuffer sb = new StringBuffer();
String path = request.getQueryString();
sb.append("<html><body><center>");
if (path == null) {
sb.append("<h2>THIS IS AN UGLY DEBUG TOOL!</h2><p>");
sb.append("To browse the database, follow the link: ");
String [] databases = Database.listDatabases();
for (int i = 0; i < databases.length; i++) {
String db = databases[i];
sb.append("<a href=\"" + contextPath + "/?/" + db + "\">" + db + "</a> ");
}
} else {
// we have something to chew on
XPathPseudoParser parser = new XPathPseudoParser(path);
Database db = Database.getDatabase(parser.getDatabase());
/* building the page once we have all the information */
sb.append("<table border=\"1\" width=\"90%\">\n");
sb.append("<tr><td rowspan=\"1\" colspan=\"2\">" + getPathNavigation(parser, contextPath) + "</td></tr>\n");
sb.append("<tr><td valign=\"top\">" + getHierarchy(parser, contextPath, db) + "</td>");
sb.append("<td valign=\"top\">" + getDetailView(parser, db) + "</td></tr>\n");
sb.append("</table>\n");
}
sb.append("</center>");
sb.append("<p><font size=\"-1\">Ugly Browser version: $Revision: 1.13 $ </font>\n</p>");
sb.append("</body></html>");
response.setContentType("text/html; charset=utf-8");
byte[] resultBytes = sb.toString().getBytes("utf-8");
response.setContentLength(resultBytes.length);
OutputStream output = response.getOutputStream();
output.write(resultBytes);
output.flush();
} catch (Exception e) {
throw new ServletException("argh!", e);
//response.setStatus(HttpServletResponse.SC_NOT_FOUND);
// TODO: need intelligent error handling.
// throw new ServletException("Error while doGet method", e);
}
}
protected static String getPathNavigation(XPathPseudoParser parser, String contextPath) {
String path = parser.getQuery();
StringBuffer result = new StringBuffer();
StringTokenizer st = new StringTokenizer(path, "/");
String currentPath = "<a href=\"" + contextPath + "/?";
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (token.indexOf("&") > 0) {
token = token.substring(0, token.indexOf("&"));
}
currentPath = currentPath + "/" + token;
result.append(currentPath + "\">" + token + "</a> - ");
}
return result.toString();
}
protected static String getHierarchy(XPathPseudoParser parser, String contextPath, Database db) throws DBException, Exception {
StringBuffer result = new StringBuffer();
String path = parser.getPath();
Collection col;
if (!path.equals("")) {
col = db.getCollection(parser.getPath());
} else {
col = db;
}
if (col == null) {
result.append("Collection not found! " + parser.getPath());
return result.toString();
}
String[] cols = col.listCollections();
String dbLoc = parser.getDatabase();
String parserPath = parser.getPath();
StringBuffer baseHref = new StringBuffer();
baseHref.append("<a href=\"" + contextPath + "/?/" + dbLoc);
if(parserPath.startsWith("/") || dbLoc.endsWith("/")) {
baseHref.append(parserPath);
} else {
baseHref.append("/" + parserPath);
}
for (int i = 0; i < cols.length; i++) {
result.append(baseHref);
if(!baseHref.toString().endsWith("/")) {
result.append("/");
}
result.append(cols[i]);
result.append("\">");
result.append(cols[i]);
result.append("</a><br>");
}
try {
String[] docs = col.listDocuments();
for (int i = 0; i < docs.length; i++) {
result.append(baseHref);
result.append("&");
result.append(docs[i]);
result.append("\">");
result.append(docs[i]);
result.append("</a><br>");
}
} catch (DBException e) {
// do nothing but this collection cannot store documents.
if (log.isWarnEnabled()) {
log.warn("ignored exception", e);
}
}
return result.toString();
}
protected static String getDetailView(XPathPseudoParser parser, Database db) throws Exception {
Collection col = db.getCollection(parser.getPath());
String document = parser.getDocument();
if (document == null) {
return "";
}
Document doc = col.getDocument(document);
if (doc == null) {
return "Document '" + document + "' not found";
}
return "Document '" + document + "'<p>\n"
+ escapeHtml(TextWriter.toString(doc));
}
/* simple function to escape the xml stuff that'll
* not be displayed correctly in html.
*/
static public String escapeHtml(String value) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
switch (c) {
case '<' :
buf.append("<");
break;
case '>' :
buf.append(">");
break;
case '\'' :
buf.append("'");
break;
case '\"' :
buf.append(""");
break;
case '&' :
buf.append("&");
break;
default :
if (isLegalCharacter(c)) {
buf.append(c);
} else {
buf.append("&#");
buf.append(String.valueOf(c));
buf.append(";");
}
break;
}
}
return buf.toString();
}
/**
* Is the given character allowed inside an HTML document?
*/
static public boolean isLegalCharacter(char c) {
return (c > 0x07) && (c < 0x80);
}
public static class XPathPseudoParser {
private String query;
public XPathPseudoParser(String query) throws Exception {
this.query = query;
}
public String getQuery() {
return this.query;
}
public String getDatabase() {
String db;
int max = query.indexOf("/", 1);
if (max > 1) {
db = query.substring(0, max);
} else {
db = query;
}
if (db.startsWith("/")) {
db = db.substring(1);
}
return db;
}
public String getPath() {
int min = query.indexOf("/", 1);
if (min <= 0) {
return "";
}
int max = query.indexOf("&");
if (max > 1) {
return query.substring(min + 1, max);
} else {
return query.substring(min + 1);
}
/*
int pos = query.indexOf("&");
if (pos > 0) {
return query.substring(0, pos);
} else {
return query;
}
*/
}
public String getDocument() {
int pos = query.indexOf("&");
if (pos > 0) {
return query.substring(pos + 1);
} else {
return null;
}
}
}
}