package net.matrix_rad.zen; import java.lang.*; import java.awt.TextArea; import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.util.Calendar; import java.util.Date; import java.util.Enumeration; import java.util.Locale; import java.util.Properties; import java.util.TimeZone; import net.matrix_rad.NAWS.*; import net.matrix_rad.security.Who; import net.matrix_rad.skang.*; /* Developer mode (Middle click) - developer pane ONLY shown during developer mode. make main pane widgets dragable and resizable. allow add / del widget. allow editing widget "extra skin commands"[1]. allow add / edit / del modules, panes, commands, parameters. Do some general "edit Thing" stuff. [1] widget extra skin commands are commands in the skang file that relate to a widget - action, look, method calls, etc. When writing the new skang file, add them after the widget creation command. */ /* User mode (Right click, or from Right click popup) - Like developer mode, but only widget add / del / move / resize / edit look allowed. No developer pane needed. Allow "Save skin" and "Revert skin". Allow "Add module", after modules can add to the classpath. MAYBE - Right click and drag widget. Right click and drag widget border (three pixels around widget). Right click popup - "Add widget", "Copy widget", "Delete widget", "Edit look", "Add module", "Revert to old skin", "Save skin". New SkangAWT command "menu name,text,action" adds to popup menu. */ /** * Developer is the development system for Skang. * Unlike every other module, the skin details are * hard coded into the source. This is to avoid * trying to edit the skin editor, and other problems. * * @.requires Java 1.1 at least. * @author David Seikel * @.copyright 2002 David Seikel * @version 0.13 prototype 2002-12-12 14:56:00 */ public final class Developer extends Skang { public static void main(String someArguments[]) { Skang.main(someArguments); } public void initGUI() { ERRLN("zen.Developer.initGUI()"); super.initGUI(); try {Widget.getPane("developer");} catch (ThingNotFoundException e) { doThing("pane developer "+ developerX + ", " + developerY + ", 350, 600, 'Zen developer'"); pendingDoThing("developmenu"); } } private static void addLocalDevelopFiles(Tree aTree, String aDir) { int len = System.getProperty("user.dir").length(); try { File root = new File(aDir); String files[] = root.list(); for (int i = 0; i < files.length; i++) { File file = new File(root, files[i]); if (file.isFile()) { if (files[i].lastIndexOf('.') != -1) { String type = files[i].substring(files[i].lastIndexOf('.')); if (type.equals(".class")) continue; if (type.equals(".jar")) continue; if (type.equals(".png")) continue; if (type.equals(".jpg")) continue; if (type.equals(".jpeg")) continue; if (type.equals(".gif")) continue; if (type.equals(".gz")) continue; if (type.equals(".zip")) continue; } // Use absolute path here for the external editor. aTree.addRow("editfile" + aDir.substring(len).replace(What.separator, '.') + "." + files[i].replace('.', '_'), files[i], "editfile \"" + file.getPath() + "\"", 0); } else { aTree.addRow("editfile" + aDir.substring(len).replace(What.separator, '.') + "." + files[i] + ".", files[i], "+", 0); addLocalDevelopFiles(aTree, aDir + What.separator + file.getName()); } } } catch (NullPointerException e) {;} catch (SecurityException e) {;} } private static void addWebDevelopFiles(Tree aTree) { boolean first = true; String tag = "editfile."; Enumeration things = Thing.elements(What.root, ThingSpace.CLASSES); while (things.hasMoreElements()) { tag = "editfile.CLASS."; Leaf leaf = (Leaf) things.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Thing) { Thing thing = (Thing) leaf.getValue(); if (!thing.text.startsWith("java")) { if (first) { aTree.addRow(tag, "Widgets", "+", 0); first = false; } addClassSourceFiles(aTree, tag, ("src." + thing.text).replace('.', What.separator), thing.text); } } } } first = true; Enumeration modules = Thing.elements(What.root, ThingSpace.MODULE); while (modules.hasMoreElements()) { tag = "editfile.MODULE."; Leaf leaf = (Leaf) modules.nextElement(); if (leaf != null) { if (leaf.getValue() instanceof Module) { Module thing = (Module) leaf.getValue(); Skang module = thing.module; if (first) { aTree.addRow(tag, "Modules", "+", 0); first = false; } tag += thing.name.replace('.', '_') + "."; aTree.addRow(tag, thing.name, "+", 0); String file = ("docs." + thing.name).replace('.', What.separator); aTree.addRow(tag + "html", file + ".html", "editfile \"" + file + ".html\"", 0); file = ("src." + thing.name).replace('.', What.separator); aTree.addRow(tag + "skang", file + ".skang", "editfile \"" + file + ".skang\"", 0); aTree.addRow(tag + "prop", file + ".properties", "editfile \"" + file + ".properties\"", 0); addClassSourceFiles(aTree, tag, file, thing.name); } } } Leaf leaf = What.root; while (leaf != null) { if (leaf.up() != null) { String name = "" + leaf.getKey().charAt(0) + leaf.getKey().substring(1).toLowerCase(); String aClass = "net.matrix_rad.skang." + name; try { // Check if it exists. Class.forName(aClass); addClassSourceFiles(aTree, "editfile.", ("src." + aClass).replace('.', What.separator), aClass); } catch (Exception e) {;} } leaf = leaf.next(); } } private static void addClassSourceFiles(Tree aTree, String aTag, String aFile, String aClass) { aFile += ".java"; //ERRLN("ADDING " + aTag + aFile.replace('.', '_')); aTree.addRow(aTag + aFile.replace('.', '_'), aFile, "editfile \"" + aFile + "\"", 0); try { // Should use an interface to find CLASS_SOURCE_FILES. Object us = Class.forName(aClass).newInstance(); String files[] = (String[]) us.getClass().getDeclaredField("CLASS_SOURCE_FILES").get(us); aClass = aClass.substring(0, aClass.lastIndexOf('.')).replace('.', What.separator); for (int i = 0; i < files.length; i++) { files[i] = files[i].replace('/', What.separator); String file = "src" + What.separator + aClass; // Do "../" resolving. while (files[i].startsWith(".." + What.separator)) { files[i] = files[i].substring(3); file = file.substring(0, file.lastIndexOf(What.separator)); } file += What.separator + files[i]; // If this is a .java file, do it recursively. if (file.endsWith(".java")) { file = file.substring(0, file.lastIndexOf('.')); addClassSourceFiles(aTree, aTag, file, file.substring(4).replace(What.separator, '.')); } else aTree.addRow(aTag + file.replace('.', '_'), file, "editfile \"" + file + "\"", 0); } } catch (Exception e) {;} } public static void fillDevelTree(Tree aTree, String aModule) { aTree.removeAll(); aTree.addRow("level.", What.root.user.getLevelNoun() + " experience level.", "+", 0); for (int i = 0; i < Who.LEVELS.length; i++) { aTree.addRow("level." + Who.LEVELS[i][0], "Change to " + Who.LEVELS[i][0] + " who can " + Who.LEVELS[i][1].toLowerCase() + ".", "setuserlevel " + i, 0); } if (What.useSecurity) aTree.addRow("login", "Show login window", "showloginwindow", 0); if (What.root.user.getLevel() >= Who.OPERATOR) { String skin = aModule.replace('.', What.separator) + ".skang"; aTree.addRow("skinEdit", "Edit " + skin, "editfile \"" + skin + "\"", 0); aTree.addRow("skinReload", "Reload skin", "skang", 0); } if (What.root.user.getLevel() >= Who.EXPERT) { aTree.addRow("debug.", "Debug", "-", 0); aTree.addRow("debug.dump", "Dump debugging information", "dump", 0); aTree.addRow("debug.check", "Check the system status", "check", 0); aTree.addRow("debug.bug", "Toggle Browser Button Bug", "togglebug", 0); aTree.addRow("debug.output", "Toggle output", "toggleout", 0); aTree.addRow("debug.error", "Toggle error output", "toggleerr", 0); } if (What.root.user.getLevel() == Who.GURU) { aTree.addRow("editfile.", "Edit", "+", 0); if (areWe.standAlone) addLocalDevelopFiles(aTree, System.getProperty("user.dir")); else addWebDevelopFiles(aTree); aTree.addRow("build.", "Build", "-", 0); aTree.addRow("build.build", "Rebuild " + aModule, "rebuild", 0); aTree.addRow("build.dist", "Distribute " + aModule, "distribute", 0); aTree.addRow("threads.", "Threads", "+", 0); try { ThreadGroup tg = Thread.currentThread().getThreadGroup(); while (tg.getParent() != null) tg = tg.getParent(); ThreadGroup tgs[] = new ThreadGroup[tg.activeGroupCount()]; int count = tg.enumerate(tgs); for (int i = 0; i < count; i++) { aTree.addRow("threads." + tgs[i].toString().replace('.', '_') + ".", tgs[i].toString(), "+", 0); Thread ts[] = new Thread[tgs[i].activeCount()]; int threads = tgs[i].enumerate(ts); for (int j = 0; j < threads; j++) aTree.addRow("threads." + tgs[i].toString().replace('.', '_') + "." + ts[j].toString().replace('.', '_'), "" + (ts[j].isAlive() ? " Alive" : " Dead ") + (ts[j].isInterrupted() ? " Interrupted" : " Running ") + (ts[j].isDaemon() ? " Daemon" : " ") + " " + ts[j].getPriority() + " " + ts[j].getName() , null, 0); } } catch (Exception e) {aTree.addRow("threads.error", e.getMessage(), null, 0);} aTree.addRow("health", What.modulesDisplay, null, 0); aTree.addTree("ThingSpace", What.root); } aTree.addRow("system.", "System", "-", 0); try { aTree.addRow("system.os", System.getProperty("os.name") + " OS " + System.getProperty("os.version") + " - " + System.getProperty("os.arch") + ".", null, 0); aTree.addRow("system.jvm", "Java " + System.getProperty("java.version") + "-" + System.getProperty("java.class.version") + ", " + System.getProperty("java.vendor") + ".", null, 0); } catch (Exception e) {;} if (areWe.fuckedJava) { aTree.addRow("system.braindead", "This version of Java is brain dead!", null, 0); aTree.addRow("system.limping", "Don't expect things to work well!", null, 0); } if (!areWe.useJava1_1) { aTree.addRow("system.dead", "Java 1.1 at least is required!", null, 0); aTree.addRow("system.broken", "Don't expect things to work at all!", null, 0); } Runtime rt = Runtime.getRuntime(); aTree.addRow("system.memory", "Java memory total : " + (rt.totalMemory() / (1024)) + "KB, free : " + (rt.freeMemory() / (1024)) + " KB", null, 0); if (What.root.user.getLevel() >= Who.EXPERT) { aTree.addRow("system.properties.", "System properties", "+", 0); Properties properties = null; try {properties = System.getProperties();} catch (Exception e) {;} if (properties != null) { for (Enumeration props = properties.propertyNames(); props.hasMoreElements(); ) { String prop = (String) props.nextElement(); aTree.addRow("system.properties." + prop.replace('.', '_'), prop + " : " + System.getProperty(prop), null, 0); } } else aTree.addRow("system.properties.none", "Your browser thinks that all properties are a security risk.", null, 0); } What.isNewTree = false; aTree.invalidate(); } private void testJVM() { Calendar rightNow = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault()); ERRLN(getClassName() + ".class version " + this.skanglet.VERSION); ERRLN(""); // prop.list(System.out); // OUTLN(); ERRLN("OS = " + System.getProperty("os.name") + ", " + System.getProperty("os.arch") + ", " + System.getProperty("os.version") + "."); ERRLN("JRE = " + System.getProperty("java.vendor") + ", " + System.getProperty("java.vendor.url") + ", " + System.getProperty("java.version") + "."); ERRLN("JREs = " + System.getProperty("java.specification.vendor") + ", " + System.getProperty("java.specification.name") + ", " + System.getProperty("java.specification.version") + "."); ERRLN("JVM = " + System.getProperty("java.vm.vendor") + ", " + System.getProperty("java.vm.name") + ", " + System.getProperty("java.vm.version") + "."); ERRLN("JVMs = " + System.getProperty("java.vm.specification.vendor") + ", " + System.getProperty("java.vm.specification.name") + ", " + System.getProperty("java.vm.specification.version") + "."); ERRLN("Class = " + System.getProperty("java.class.version") + ", " + System.getProperty("java.class.path") + "."); ERRLN("Compiler = " + System.getProperty("java.compiler") + ", " + System.getProperty("java.home") + ", " + System.getProperty("java.library.path") + "."); ERRLN(""); Runtime rt = Runtime.getRuntime(); ERRLN("Total memory " + rt.totalMemory() + " Free " + rt.freeMemory()); ERRLN(""); ERRLN("1 - " + (rightNow.toString()) + "\n2 - " + TimeZone.getDefault() + "\n3 - " + Locale.getDefault() + "\n4 - " + System.getProperty("user.timezone", "AET")); ERRLN((rightNow.getTime().toString()) + " [" + rightNow.get(Calendar.YEAR) + "-" + (rightNow.get(Calendar.MONTH) + 1) + "-" + rightNow.get(Calendar.DATE) + " " + rightNow.get(Calendar.HOUR_OF_DAY) + ":" + rightNow.get(Calendar.MINUTE) + ":" + rightNow.get(Calendar.SECOND) + "]"); rightNow.setTime(new Date()); // rightNow.add(Calendar.HOUR_OF_DAY, (new Integer(tz)).intValue() + 5); ERRLN((rightNow.getTime().toString()) + " [" + rightNow.get(Calendar.YEAR) + "-" + (rightNow.get(Calendar.MONTH) + 1) + "-" + rightNow.get(Calendar.DATE) + " " + rightNow.get(Calendar.HOUR_OF_DAY) + ":" + rightNow.get(Calendar.MINUTE) + ":" + rightNow.get(Calendar.SECOND) + "]"); ERRLN((new Date().toString()) + " [" + getClassName() + ".class] "); ERRLN(""); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getFamily() = " + What.ourFont.getFamily()); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getLeading() = " + What.metrics.getLeading()); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getAscent() = " + What.metrics.getAscent()); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getDescent() = " + What.metrics.getDescent()); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getMaxAscent() = " + What.metrics.getMaxAscent()); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getMaxDescent() = " + What.metrics.getMaxDescent()); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getHeight() = " + What.metrics.getHeight()); ERRLN("(" + What.ourFont.getName() + ", " + What.ourFont.getStyle() + ", " + What.ourFont.getSize() + ") getMaxAdvance() = " + What.metrics.getMaxAdvance()); ERRLN(""); } /** Check to see if everything is still working. * * @.skang check */ public void check() { testJVM(); } /** Fill the tree with developer stuff. * * @.skang developmenu */ public void developMenu() { try { Widget widget = Widget.getWidget("developer.DevMenu"); fillDevelTree((Tree) widget.widget, module); if (What.root.user.getLevel() >= Who.EXPERT) { pendingDoThing("show developer.lTester"); pendingDoThing("show developer.Tester"); } else { pendingDoThing("hide developer.lTester"); pendingDoThing("hide developer.Tester"); } pendingDoThing("show developer"); } catch (ThingNotFoundException e) { ERRLN("Menu not found, creating it."); pendingDoThing("widget developer.DevMenu Tree 0, _1, 0, _16, ''"); pendingDoThing("action developer.DevMenu 'nada \"internal\"'"); pendingDoThing("sethelp developer.DevMenu 'Click on a red item to perform a function.'"); pendingDoThing("widget developer.Help Button -20, _0, 20, 0, '?'"); pendingDoThing("action developer.Help 'help'"); pendingDoThing("widget developer.lTester Label 0, _0, 40, 0, 'Skang'"); pendingDoThing("widget developer.Tester TextField 45, _0, -65, 0, ''"); pendingDoThing("action developer.Tester '%d'"); pendingDoThing("sethelp developer.Tester 'Type in Skang commands here.'"); pendingDoThing("developmenu"); } } /** Make a distribution of the current system. * * @.skang distribute */ public void distribute() { runProgram("DISTRIBUTE", distributer); } /** Edit a text file (usually source code). * * @.skang editfile file */ public void editFile(String aFile) { boolean done = false; String args[] = new String[2]; args[0] = editor; args[1] = aFile; Runtime rt = Runtime.getRuntime(); try { rt.exec(args); done = true; } catch (Exception e) {;} if (!done) // Either this is an applet, or the specified editor doesn't exist / work. { try // our own editor. { String name = aFile.replace('.', 'E').replace('/', 'E').replace('\\', 'E').replace('-', 'E').replace('_', 'E'); try {Widget.getPane(name);} catch (ThingNotFoundException e) {doThing("pane " + name + " "+ developerX + " " + developerY + " 630 450 '" + aFile + "'");} doThing("widget " + name + ".Edit TextArea 0 _0 0 _15 ''"); pendingDoThing("widget " + name + ".Save Button 0 _-1 50 0 'Save'"); pendingDoThing("action " + name + ".Save 'savefile \"" + aFile + "\"'"); Widget widget = Widget.getWidget(name + ".Edit"); BufferedReader in = new BufferedReader(new InputStreamReader(What.me.openResource(aFile))); String line = null; while ((line = in.readLine()) != null) { widget.appendText(line + "\n"); What.UBER(line); } pendingDoThing("show developer"); } catch (Exception e) {ERRLN(e.getMessage());} } } /** Rebuild the current system. * * @.skang rebuild * @.todo Convert this to a servlet that can do the build on the web server. * @.todo Keep a stable version around for bootstrapping, and when the new version crashes. */ public void rebuild() { if (runProgram("REBUILD", rebuilder) == 0) { // Rebuilt ourselves, so do the jesus thing. What.resetErrOut(); String command = runner + " "; command += System.getProperty("java.class.path") + " " + What.me.getClass().getName(); for (int i = 0; i < arguments.length; i++) command += " " + arguments[i]; System.out.println("\n" + command); // Fake typing the command. What.toggleOut(); try { startQuit(); // Suicide is fun when you know you're coming back. Runtime.getRuntime().exec(command); // Start the resurection. } catch (Exception e) {System.err.println(e.toString());} } } /** Save the current file. * * @.skang savefile data */ public void saveFile(String aFile) { OUTLN("Saving " + aFile + "..."); String notSaved = aFile + " not saved."; String name = aFile.replace('.', 'E').replace('/', 'E').replace('\\', 'E').replace('-', 'E').replace('_', 'E'); try { Widget widget = Widget.getWidget(name + ".Edit"); String text = ((TextArea) widget.widget).getText(); if (areWe.standAlone) // Either write to the file, { File in = new File(aFile); File backup = new File(aFile + "~"); if (backup.exists()) if (!backup.delete()) { OUTLN(notSaved); ERRLN("Backup not deleted."); return; } if (in.exists()) if (!in.renameTo(backup)) { OUTLN(notSaved); ERRLN("Backup not created."); return; } FileWriter out = new FileWriter(aFile); out.write(text); out.flush(); OUTLN("Saved " + aFile + "."); } else // or do an HTTP auth'ed PUT. { // Or is that POST, I can never remember. // Later, PUT should do the subversion thing instead, // or at least a WEB_DAV delete backup, move file to backup, save new file. pause(1000); OUTLN(notSaved); ERRLN("Not authorized."); } } catch (ThingNotFoundException e) { OUTLN(notSaved); ERRLN("Nothing to save."); } catch (IOException e) { OUTLN(notSaved); ERRLN(e.getClass().getName() + " " + e.getMessage()); } } /** Switch to new experience level. * * @.skang setuserlevel int */ public void setUserLevel(Integer aLevel) { setUserLevel(aLevel.intValue()); } public void setUserLevel(int aLevel) { What.root.user.setLevel(aLevel); developMenu(); } /** Switch error output between status line and console. * * @.skang toggleerr */ public void toggleErr() throws SecurityException { What.toggleErr(); } /** Switch output between status line and console. * * @.skang toggleout */ public void toggleOut() throws SecurityException { What.toggleOut(); } //********************************************************************** /** Develop X coordinate. * * @.skangarg developerx * @.default "0" */ public static String developerX = null; /** Develop Y coordinate. * * @.skangarg developery * @.default "100" */ public static String developerY = null; /** Distributer to run. * * @.skangarg distributer * @.default "ant dist" */ public static String distributer = null; /** Editor to run. * * @.skangarg editor * @.default "jedit" */ public static String editor = null; /** Module to develop. * * @.skangarg module * @.default "net.matrix_rad.matrix.Matrix" */ public static String module = null; /** Java executable to execute during restart. * * @.skangarg runner * @.default "java -classpath" */ public static String runner = null; /** Rebuilder to run. * * @.skangarg rebuilder * @.default "ant" */ public static String rebuilder = null; }