Author: sshafroi
Date: 2008-06-05 17:41:34 +0200 (Thu, 05 Jun 2008)
New Revision: 6676
Added:
trunk/util/
trunk/util/pom.xml
trunk/util/src/
trunk/util/src/main/
trunk/util/src/main/java/
trunk/util/src/main/java/no/
trunk/util/src/main/java/no/sesat/
trunk/util/src/main/java/no/sesat/Interpreter.java
Modified:
trunk/pom.xml
trunk/search-command-config-spi/pom.xml
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/SearchModeFactory.java
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/config/AbstractSearchConfiguration.java
Log:
Issue SKER4768: (Interpreter for debuging and inspection help)
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2008-06-05 13:15:27 UTC (rev 6675)
+++ trunk/pom.xml 2008-06-05 15:41:34 UTC (rev 6676)
@@ -136,6 +136,7 @@
<!-- sitemap-generator must be after
generic.sesam-search-command-control because they both use assembly -->
<module>sitemap-generator</module>
<module>war</module>
+ <module>util</module>
</modules>
<build>
Modified: trunk/search-command-config-spi/pom.xml
===================================================================
--- trunk/search-command-config-spi/pom.xml 2008-06-05 13:15:27 UTC (rev
6675)
+++ trunk/search-command-config-spi/pom.xml 2008-06-05 15:41:34 UTC (rev
6676)
@@ -65,6 +65,11 @@
<artifactId>sesat-run-transform-config-spi</artifactId>
<version>${sesat.version}</version>
</dependency>
+ <dependency>
+ <groupId>sesat</groupId>
+ <artifactId>sesat-util</artifactId>
+ <version>${sesat.version}</version>
+ </dependency>
</dependencies>
-</project>
\ No newline at end of file
+</project>
Modified:
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/SearchModeFactory.java
===================================================================
---
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/SearchModeFactory.java
2008-06-05 13:15:27 UTC (rev 6675)
+++
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/SearchModeFactory.java
2008-06-05 15:41:34 UTC (rev 6676)
@@ -18,6 +18,7 @@
package no.sesat.search.mode;
+import no.sesat.Interpreter;
import no.sesat.search.run.transform.RunTransformerConfig;
import no.sesat.search.site.config.AbstractConfigFactory;
import no.schibstedsok.commons.ioc.ContextWrapper;
@@ -622,4 +623,31 @@
return clazz;
}
}
+
+
+ static {
+ Interpreter.addFunction("commands", new Interpreter.Function() {
+ public String execute(Interpreter.Context ctx) {
+ String res = "";
+ COMMANDS_LOCK.readLock().lock();
+ try {
+ for (SearchMode c : COMMANDS.keySet()) {
+ res += "Mode: " + c + "\n";
+ for (String s : COMMANDS.get(c).keySet()) {
+ res += " " + COMMANDS.get(c).get(s).toString() +
"\n";
+ }
+ res += "\n";
+ }
+ }
+ finally {
+ COMMANDS_LOCK.readLock().unlock();
+ }
+ return res;
+
+ }
+ public String describe() {
+ return "Print out the SearchModes in COMMANDS.";
+ }
+ });
+ }
}
Modified:
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/config/AbstractSearchConfiguration.java
===================================================================
---
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/config/AbstractSearchConfiguration.java
2008-06-05 13:15:27 UTC (rev 6675)
+++
trunk/search-command-config-spi/src/main/java/no/sesat/search/mode/config/AbstractSearchConfiguration.java
2008-06-05 15:41:34 UTC (rev 6676)
@@ -20,6 +20,9 @@
import java.lang.reflect.Method;
import java.util.*;
+import no.sesat.Interpreter;
+import no.sesat.Interpreter.Context;
+
import org.apache.log4j.Logger;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
@@ -33,33 +36,38 @@
private static final String[] setters = {"set", "add"};
/**
- * This method will be called before settings from the modes.xml files
will be applied.
- * Default implementation is empty.
+ * This method will be called before settings from the modes.xml files will
+ * be applied. Default implementation is empty.
*
- * @param element The xml element where the attribues are found.
- * @param inherit The configuration that we inherit from.
+ * @param element
+ * The xml element where the attribues are found.
+ * @param inherit
+ * The configuration that we inherit from.
*/
protected void readSearchConfigurationBefore(final Element element, final
SearchConfiguration inherit) {
}
/**
- * This method will be called after settings from the modes.xml files will
be applied.
- * Default implementation is empty.
+ * This method will be called after settings from the modes.xml files will
+ * be applied. Default implementation is empty.
*
- * @param element The xml element where the attribues are found.
- * @param inherit The configuration that we inherit from.
+ * @param element
+ * The xml element where the attribues are found.
+ * @param inherit
+ * The configuration that we inherit from.
*/
protected void readSearchConfigurationAfter(final Element element, final
SearchConfiguration inherit) {
}
-
/**
* This method will apply the attributes found in element.
*
- * @param element The xml element where the attribues are found.
- * @param inherit The configuration that we inherit from.
+ * @param element
+ * The xml element where the attribues are found.
+ * @param inherit
+ * The configuration that we inherit from.
*/
public final void readSearchConfiguration(final Element element, final
SearchConfiguration inherit) {
readSearchConfigurationBefore(element, inherit);
@@ -98,7 +106,7 @@
}
private static boolean startsWith(String string, String[] prefixes) {
- for( String p : prefixes) {
+ for (String p : prefixes) {
if (string.startsWith(p))
return true;
}
@@ -131,7 +139,9 @@
if (paramTypes.length == 1) {
MethodWrapper.Type type =
MethodWrapper.getType(paramTypes[0]);
if (type == MethodWrapper.Type.Unsupported) {
- LOG.trace("Unsupported type for: " + name + " " +
method.getParameterTypes()[0].getSimpleName());
+ LOG
+ .trace("Unsupported type for: " + name + " "
+ +
method.getParameterTypes()[0].getSimpleName());
} else {
if (!methodMap.containsKey(name)) {
@@ -188,8 +198,7 @@
if (method != null) {
if (!method.setValue(this, value)) {
- LOG.error("Setting value on " + getClass().getSimpleName() + "
" + name + "==" + value
- + " failed.");
+ LOG.error("Setting value on " + getClass().getSimpleName() + "
" + name + "==" + value + " failed.");
}
} else {
LOG.error("Setting value on " + getClass().getSimpleName() + " " +
name + "==" + value
@@ -207,7 +216,7 @@
private static MethodWrapper getMethodWrapper(Class klass, final String
name, final String[] pre) {
Map<String, MethodWrapper> map = getMethodMap(klass);
while (map != null) {
- for(String s : pre) {
+ for (String s : pre) {
String g = s + name.substring(0, 1).toUpperCase() +
name.substring(1);
if (map.containsKey(g)) {
return map.get(g);
@@ -223,11 +232,11 @@
String res = getClass().getSimpleName() + " ";
Set<String> methods = getMethodNames(getters);
for (String s : methods) {
- res += s + " == ";
+ res += s + "==";
Object o = getAttribute(this, s);
if (o instanceof String[]) {
res += "[";
- for (String a : (String[])o) {
+ for (String a : (String[]) o) {
res += "\"" + a + "\" ";
}
res += "] ";
@@ -240,8 +249,6 @@
return res;
}
-
-
/**
* Helper class to encapsulate a method.
*/
@@ -263,33 +270,33 @@
if (value instanceof String) {
String valueString = (String) value;
switch (type) {
- case String:
- break;
- case StringArray:
- value = valueString.split(",");
- break;
- case Integer:
- value = Integer.parseInt(valueString);
- break;
- case Boolean:
- value = Boolean.parseBoolean(valueString);
- break;
- case Char:
- value = valueString.charAt(0);
- if (valueString.length() > 1)
- LOG.error("Setting char attribute where input was
more then a character long");
- break;
- default:
- LOG.error("Failed to set attribute " +
method.getName() + ", unnsuported type.");
- return false;
- }
- }
- try {
- method.invoke(obj, value);
- } catch (Exception e) {
- LOG.info("Failed to set attribute with name: " +
method.getName() + "(" + type + ").");
+ case String:
+ break;
+ case StringArray:
+ value = valueString.split(",");
+ break;
+ case Integer:
+ value = Integer.parseInt(valueString);
+ break;
+ case Boolean:
+ value = Boolean.parseBoolean(valueString);
+ break;
+ case Char:
+ value = valueString.charAt(0);
+ if (valueString.length() > 1)
+ LOG.error("Setting char attribute where input was more
then a character long");
+ break;
+ default:
+ LOG.error("Failed to set attribute " + method.getName() +
", unnsuported type.");
return false;
}
+ }
+ try {
+ method.invoke(obj, value);
+ } catch (Exception e) {
+ LOG.info("Failed to set attribute with name: " +
method.getName() + "(" + type + ").");
+ return false;
+ }
return true;
}
@@ -297,7 +304,8 @@
try {
return method.invoke(obj);
} catch (Exception e) {
- LOG.error("Failed to get attribute with name: " + type + " " +
method.getName() + "(). " + e.getMessage(), e);
+ LOG.error("Failed to get attribute with name: " + type + " " +
method.getName() + "(). "
+ + e.getMessage(), e);
}
return null;
}
@@ -320,6 +328,33 @@
type = MethodWrapper.Type.Unsupported;
return type;
}
+
+ public String toString() {
+ return method.getName() + " Type: " + type;
+ }
}
+
+ /**
+ * Add some debug function to the interpreter.
+ */
+ static {
+ Interpreter.addFunction("scmap", new Interpreter.Function() {
+ public String execute(Context ctx) {
+ String res = "";
+ for (Class c : ClassMethodMap.keySet()) {
+ res += "CLASS: " + c.getSimpleName() + "\n";
+ for (String s : ClassMethodMap.get(c).keySet()) {
+ res += " " + ClassMethodMap.get(c).get(s).toString()
+ "\n";
+ }
+ res += "\n";
+ }
+ return res;
+ }
+
+ public String describe() {
+ return "Print out the ClassMethodMap cache in
AbstractSearchConfiguration.";
+ }
+
+ });
+ }
}
-
Added: trunk/util/pom.xml
===================================================================
--- trunk/util/pom.xml (rev 0)
+++ trunk/util/pom.xml 2008-06-05 15:41:34 UTC (rev 6676)
@@ -0,0 +1,22 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>sesat</groupId>
+ <artifactId>sesat-kernel</artifactId>
+ <version>2.18-SNAPSHOT</version>
+ </parent>
+ <artifactId>sesat-util</artifactId>
+ <packaging>jar</packaging>
+ <name>Sesat Util</name>
+ <description>
+ This is the Sesam Search Application Toolkit. Aka Sesat.
+ Read http://sesat.no/development-guidelines.html for developing help.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ </dependencies>
+</project>
Added: trunk/util/src/main/java/no/sesat/Interpreter.java
===================================================================
--- trunk/util/src/main/java/no/sesat/Interpreter.java
(rev 0)
+++ trunk/util/src/main/java/no/sesat/Interpreter.java 2008-06-05 15:41:34 UTC
(rev 6676)
@@ -0,0 +1,211 @@
+/**
+ * Copyright (2008) Schibsted Søk AS
+ * This file is part of SESAT.
+ *
+ * SESAT is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * SESAT is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with SESAT. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package no.sesat;
+
+import java.io.Console;
+import java.util.*;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LoggerRepository;
+
+/**
+ * Simple interpreter that will start if a console is available. You can add
+ * functions to it by using addFunction(String, Function).
+ *
+ */
+public class Interpreter {
+ private static Map<String, Function> functions = new HashMap<String,
Function>();
+ private static boolean run = true;
+
+ /**
+ * Add a function to this Interpreter.
+ *
+ * @param name
+ * Name of function
+ * @param fun
+ * The function
+ */
+ public static void addFunction(String name, Function fun) {
+ if (functions != null) {
+ functions.put(name, fun);
+ }
+ }
+
+ /**
+ * Remove function from interpreter.
+ *
+ * @param name
+ * Named function
+ */
+ public static void removeFunction(String name) {
+ if (functions != null) {
+ functions.remove(name);
+ }
+ }
+
+ private static interface FunctionInterface {
+ public String execute(Context ctx);
+ }
+
+ /**
+ * Function that you can implement if you want to add a function to this
+ * Interpreter.
+ */
+ public abstract static class Function implements FunctionInterface {
+ /**
+ * One line that describes the function.
+ *
+ * @return Description
+ */
+ protected String describe() {
+ return "";
+ }
+
+ /**
+ * If there is need for a longer description then what you can write in
+ * description then write it here.
+ *
+ * @return Help text
+ */
+ protected String help() {
+ return describe();
+ }
+ }
+
+ /**
+ * Context for a function
+ */
+ public static class Context {
+ protected String[] args;
+
+ private Context(String[] args) {
+ this.args = args;
+ }
+
+ protected int length() {
+ return args.length;
+ }
+ }
+
+ static {
+ addFunction("help", new Function() {
+ public String execute(Context ctx) {
+ if (ctx.length() == 1) {
+ String res = "Help for " + ctx.args[0] + "\n";
+ Function fun = functions.get(ctx.args[0].trim());
+ if (fun != null) {
+ res += " " + fun.help();
+ } else {
+ res += " Not found!\n";
+ }
+ return res;
+ } else {
+ String res = "Functions available: \n";
+ for (String name : functions.keySet()) {
+ res += " " + name + "\n";
+ res += " " + functions.get(name).describe() +
"\n";
+ }
+ return res;
+ }
+ }
+
+ public String describe() {
+ return "Print this help message";
+ }
+ });
+
+ addFunction("loggers", new Function() {
+ public String execute(Context ctx) {
+ String res = "Active loggers:\n";
+ LoggerRepository repo =
Logger.getRootLogger().getLoggerRepository();
+
+ Enumeration e = repo.getCurrentCategories();
+ while (e.hasMoreElements()) {
+ Logger logger = (Logger) e.nextElement();
+ if (ctx.length() == 0 || (ctx.length() > 0 &&
logger.getName().matches(ctx.args[0]))) {
+ res += logger.getName() + " " + logger.getLevel();
+ if (ctx.length() == 2) {
+ Level level = Level.toLevel(ctx.args[1]);
+ if
(level.toString().equalsIgnoreCase(ctx.args[1])) {
+ res += " (Setting level to " + level + ")";
+ logger.setLevel(level);
+ } else {
+ res += " (unknown debug level: " + ctx.args[1]
+ ")";
+ }
+ }
+ res += "\n";
+ }
+ }
+ return res;
+ }
+
+ public String describe() {
+ return "Print active loggers, and set level if specified.
'loggers [regexp] [level]'";
+ }
+ });
+
+ addFunction("quit", new Function() {
+ public String execute(Context ctx) {
+ run = false;
+ return "Bye!";
+ }
+
+ public String describe() {
+ return "Stop this interpreter.";
+ }
+ });
+
+ Thread replThread = new Thread("REPL") {
+ Console console = System.console();
+
+ public void run() {
+ if (console != null) {
+ while (run) {
+ console.printf("$ ");
+ String line = console.readLine();
+ if (line != null) { // check for null, this will
happen on shutdown
+ String[] input = line.split("\\s");
+ if (input.length > 0) {
+ String name = input[0].trim();
+ if (name.length() > 0) {
+ if (functions.containsKey(input[0])) {
+ try {
+ console.printf("%s\n",
functions.get(name).execute(
+ new
Context(Arrays.copyOfRange(input, 1, input.length))));
+ } catch (Throwable e) {
+ console.printf("Error: %s\n",
e.toString());
+ }
+
+ } else {
+ console.printf("Unknown function:
%s\n", name);
+ }
+ }
+ }
+ }
+ }
+ }
+ functions = null;
+ }
+ };
+ replThread.setDaemon(true);
+ replThread.start();
+ }
+}
_______________________________________________
Kernel-commits mailing list
[email protected]
http://sesat.no/mailman/listinfo/kernel-commits