diff --git a/Holmes/.classpath b/Holmes/.classpath new file mode 100644 index 0000000..78abb61 --- /dev/null +++ b/Holmes/.classpath @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Holmes/.metadata/.lock b/Holmes/.metadata/.lock new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/.metadata/.log b/Holmes/.metadata/.log new file mode 100644 index 0000000..2cfbf7a --- /dev/null +++ b/Holmes/.metadata/.log @@ -0,0 +1,339 @@ +!SESSION 2018-05-17 13:38:08.042 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-17 13:38:16.702 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-17 13:38:16.702 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@333e01c6, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@4f70b659, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) + +!ENTRY org.eclipse.oomph.setup.ui 1 0 2018-05-17 13:38:45.476 +!MESSAGE Setup tasks were performed during startup updating 4 preferences. See '/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/org.eclipse.oomph.setup/setup.log' for details +!SESSION 2018-05-17 19:52:29.901 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-17 19:52:44.473 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-17 19:52:44.473 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@7479cdf7, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@71852f76, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-17 20:22:26.524 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-17 20:22:35.243 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-17 20:22:35.243 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@27f43664, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@234adbe2, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-17 20:27:19.185 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-17 20:27:27.695 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-17 20:27:27.695 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@d640fe6, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@14f08a97, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 16:59:13.504 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 16:59:31.293 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 16:59:31.293 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@7d8c264, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@19993ed, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 17:03:26.571 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 17:03:35.204 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 17:03:35.205 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@2f154d9b, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@7d8c264, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 17:11:23.910 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 17:11:32.842 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 17:11:32.843 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@2f154d9b, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@7d8c264, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 17:13:28.328 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 17:13:36.941 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 17:13:36.941 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@3ce71bbb, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@661d49d1, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 17:15:18.315 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 17:15:26.867 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 17:15:26.868 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@71852f76, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@308f18c0, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 17:17:36.360 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 17:17:45.081 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 17:17:45.082 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@2f154d9b, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@7d8c264, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 17:45:25.938 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 17:45:34.899 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 17:45:34.899 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@6c7bc8ac, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@25131637, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) +!SESSION 2018-05-18 19:37:41.004 ----------------------------------------------- +eclipse.buildId=4.7.2.M20171130-0510 +java.version=1.8.0_144 +java.vendor=Oracle Corporation +BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=en_US +Framework arguments: -product org.eclipse.platform.ide +Command-line arguments: -product org.eclipse.platform.ide -data /Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin -dev file:/Users/bjohnson/eclipse-workspace/.metadata/.plugins/org.eclipse.pde.core/Eclipse Application/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -clean + +!ENTRY org.eclipse.jface 2 0 2018-05-18 19:37:49.818 +!MESSAGE Keybinding conflicts occurred. They may interfere with normal accelerator operation. +!SUBENTRY 1 org.eclipse.jface 2 0 2018-05-18 19:37:49.818 +!MESSAGE A conflict occurred for ALT+COMMAND+R: +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.python.pydev.debug.setnext,Set Next Statement, + , + Category(org.python.pydev.ui.category.run,PyDev - Run,Python run category,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@206a465f, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,,system) +Binding(ALT+COMMAND+R, + ParameterizedCommand(Command(org.eclipse.jdt.ui.edit.text.java.rename.element,Rename - Refactoring , + Rename the selected element, + Category(org.eclipse.jdt.ui.category.refactoring,Refactor - Java,Java Refactoring Actions,true), + org.eclipse.ui.internal.WorkbenchHandlerServiceHandler@c509742, + ,,true),null), + org.eclipse.ui.defaultAcceleratorConfiguration, + org.eclipse.ui.contexts.window,,cocoa,system) diff --git a/Holmes/.metadata/.mylyn/repositories.xml.zip b/Holmes/.metadata/.mylyn/repositories.xml.zip new file mode 100644 index 0000000..45519e5 Binary files /dev/null and b/Holmes/.metadata/.mylyn/repositories.xml.zip differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.indexes/properties.index b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.indexes/properties.index new file mode 100644 index 0000000..07ba7b2 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.indexes/properties.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.location b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.location new file mode 100644 index 0000000..5c21a6a Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.location differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.markers b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.markers new file mode 100644 index 0000000..0f6e76f Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/.markers differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/org.eclipse.egit.core/GitProjectData.properties b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/org.eclipse.egit.core/GitProjectData.properties new file mode 100644 index 0000000..fa16ac8 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/org.eclipse.egit.core/GitProjectData.properties @@ -0,0 +1,3 @@ +#GitProjectData +#Thu May 17 13:39:25 EDT 2018 +.gitdir=.git diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/org.eclipse.jdt.core/state.dat b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/org.eclipse.jdt.core/state.dat new file mode 100644 index 0000000..45de052 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.projects/lang_16_buggy/org.eclipse.jdt.core/state.dat differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version new file mode 100644 index 0000000..25cb955 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index new file mode 100644 index 0000000..39d70aa Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/1.tree b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/1.tree new file mode 100644 index 0000000..1f30969 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.root/1.tree differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources new file mode 100644 index 0000000..1fda514 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ajdt.ui.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ajdt.ui.prefs new file mode 100644 index 0000000..830e84f --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ajdt.ui.prefs @@ -0,0 +1,2 @@ +ajde.version.at.previous.startup=2.2.4.201703272045 +eclipse.preferences.version=1 diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..dffc6b5 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +version=1 diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.core.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.core.prefs new file mode 100644 index 0000000..9cbc3a1 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.debug.core.PREF_DELETE_CONFIGS_ON_PROJECT_DELETE=false diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.ui.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.ui.prefs new file mode 100644 index 0000000..616c304 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.debug.ui.prefs @@ -0,0 +1,4 @@ +Console.highWaterMark=88000 +StringVariablePreferencePage=164,136,136,109, +eclipse.preferences.version=1 +org.eclipse.debug.ui.save_dirty_editors_before_launch=always diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.egit.core.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.egit.core.prefs new file mode 100644 index 0000000..a4cd66f --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.egit.core.prefs @@ -0,0 +1,3 @@ +GitRepositoriesView.GitDirectories=/Users/bjohnson/eclipse-workspace/lang_16_buggy/.git\: +GitRepositoriesView.GitDirectories.relative=/Users/bjohnson/eclipse-workspace/lang_16_buggy/.git\: +eclipse.preferences.version=1 diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.logging.aeri.ide.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.logging.aeri.ide.prefs new file mode 100644 index 0000000..c186df8 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.epp.logging.aeri.ide.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +resetSendMode=KEEP +resetSendModeOn=0 +sendMode=NOTIFY diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..5bcbdd5 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.classpathVariable.JRE_LIB=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/rt.jar +org.eclipse.jdt.core.classpathVariable.JRE_SRC=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/src.zip +org.eclipse.jdt.core.classpathVariable.JRE_SRCROOT=src +org.eclipse.jdt.core.codeComplete.visibilityCheck=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs new file mode 100644 index 0000000..57cf1e4 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.launching.PREF_VM_XML=\n\n\n\n\n\n\n diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..679bb40 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,12 @@ +content_assist_number_of_computers=21 +content_assist_proposals_background=255,255,255 +content_assist_proposals_foreground=0,0,0 +eclipse.preferences.version=1 +org.eclipse.jdt.internal.ui.navigator.layout=2 +org.eclipse.jdt.internal.ui.navigator.librariesnode=true +org.eclipse.jdt.ui.formatterprofiles.version=13 +org.eclipse.jdt.ui.text.custom_templates= +org.eclipse.jdt.ui.text.templates_migrated=true +spelling_locale_initialized=true +useAnnotationsPrefPage=true +useQuickDiffPrefPage=true diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.m2e.discovery.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.m2e.discovery.prefs new file mode 100644 index 0000000..67b1d96 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.m2e.discovery.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.m2e.discovery.pref.projects= diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs new file mode 100644 index 0000000..43e97e4 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +mylyn.attention.migrated=true diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.monitor.ui.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.monitor.ui.prefs new file mode 100644 index 0000000..8d462a6 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.monitor.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.mylyn.monitor.activity.tracking.enabled.checked=true diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.tasks.ui.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.tasks.ui.prefs new file mode 100644 index 0000000..5330e43 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.tasks.ui.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +migrated.task.repositories.secure.store=true +org.eclipse.mylyn.tasks.ui.filters.nonmatching=true +org.eclipse.mylyn.tasks.ui.filters.nonmatching.encouraged=true diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.pde.api.tools.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.pde.api.tools.prefs new file mode 100644 index 0000000..d2ed603 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.pde.api.tools.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +knownEEFragments= diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs new file mode 100644 index 0000000..56cd496 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.team.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.team.ui.first_time=false diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs new file mode 100644 index 0000000..61f3bb8 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.editors.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +overviewRuler_migration=migrated_3.1 diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs new file mode 100644 index 0000000..bc74de6 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs @@ -0,0 +1,5 @@ +TASKS_FILTERS_MIGRATE=true +eclipse.preferences.version=1 +platformState=1526578689007 +quickStart=false +tipsAndTricks=false diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs new file mode 100644 index 0000000..08076f2 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +showIntro=false diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs new file mode 100644 index 0000000..aa3dc02 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs @@ -0,0 +1,3 @@ +//org.eclipse.ui.commands/state/org.eclipse.ui.navigator.resources.nested.changeProjectPresentation/org.eclipse.ui.commands.radioState=false +PLUGINS_NOT_ACTIVATED_ON_STARTUP=;org.eclipse.m2e.discovery; +eclipse.preferences.version=1 diff --git a/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs new file mode 100644 index 0000000..656dde0 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs @@ -0,0 +1,2 @@ +INTERPRETERS_CHECKED_ONCE=true +eclipse.preferences.version=1 diff --git a/Holmes/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi b/Holmes/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi new file mode 100644 index 0000000..4566534 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi @@ -0,0 +1,2878 @@ + + + + activeSchemeId:org.eclipse.ui.defaultAcceleratorConfiguration + ModelMigrationProcessor.001 + + + + + + + + topLevel + + + + + persp.actionSet:ajrefactoring + persp.actionSet:org.eclipse.contribution.xref.ui.XRefActionSet + persp.actionSet:org.eclipse.mylyn.doc.actionSet + persp.actionSet:org.eclipse.mylyn.tasks.ui.navigation + persp.actionSet:org.eclipse.ui.cheatsheets.actionSet + persp.actionSet:org.eclipse.search.searchActionSet + persp.actionSet:org.eclipse.ui.edit.text.actionSet.annotationNavigation + persp.actionSet:org.eclipse.ui.edit.text.actionSet.navigation + persp.actionSet:org.eclipse.ui.edit.text.actionSet.convertLineDelimitersTo + persp.actionSet:org.eclipse.ui.externaltools.ExternalToolsSet + persp.actionSet:org.eclipse.ui.actionSet.keyBindings + persp.actionSet:org.eclipse.ui.actionSet.openFiles + persp.newWizSC:org.eclipse.ui.wizards.new.folder + persp.newWizSC:org.eclipse.ui.wizards.new.file + persp.viewSC:org.eclipse.ui.navigator.ProjectExplorer + persp.viewSC:org.eclipse.ui.views.BookmarkView + persp.viewSC:org.eclipse.ui.views.ContentOutline + persp.viewSC:org.eclipse.ui.views.PropertySheet + persp.viewSC:org.eclipse.ui.views.ProblemView + persp.viewSC:org.eclipse.ui.views.ProgressView + persp.viewSC:org.eclipse.ui.views.TaskList + persp.actionSet:org.eclipse.ui.NavigateActionSet + persp.viewSC:org.eclipse.pde.runtime.LogView + persp.newWizSC:org.eclipse.ui.editors.wizards.UntitledTextFileWizard + persp.showIn:org.eclipse.ui.navigator.ProjectExplorer + persp.perspSC:org.eclipse.team.ui.TeamSynchronizingPerspective + persp.showIn:org.eclipse.team.ui.GenericHistoryView + persp.perspSC:org.eclipse.jdt.ui.JavaPerspective + persp.perspSC:org.eclipse.jdt.ui.JavaBrowsingPerspective + persp.viewSC:org.eclipse.mylyn.tasks.ui.views.tasks + persp.newWizSC:org.eclipse.mylyn.tasks.ui.wizards.new.repository.task + persp.perspSC:org.eclipse.wst.xml.ui.perspective + persp.showIn:org.eclipse.egit.ui.RepositoriesView + persp.viewSC:org.eclipse.ant.ui.views.AntView + + + + org.eclipse.e4.primaryNavigationStack + + + + + + org.eclipse.e4.secondaryNavigationStack + + + + + + + + + + + + + + + org.eclipse.e4.secondaryDataStack + + + + + + + + + + + + + + + + + + + + View + categoryTag:Help + + + + + View + categoryTag:General + + ViewMenu + menuContribution:menu + + + + + + + View + categoryTag:Help + + + + org.eclipse.e4.primaryDataStack + EditorStack + active + + + Editor + org.eclipse.jdt.ui.CompilationUnitEditor + removeOnHide + active + + menuContribution:popup + popup:#CompilationUnitEditorContext + popup:org.eclipse.jdt.ui.CompilationUnitEditor.EditorContext + popup:#AbstractTextEditorContext + + + menuContribution:popup + popup:#CompilationUnitRulerContext + popup:org.eclipse.jdt.ui.CompilationUnitEditor.RulerContext + popup:#AbstractTextEditorRulerContext + + + menuContribution:popup + popup:#OverviewRulerContext + + + + + + + + + View + categoryTag:General + + ViewMenu + menuContribution:menu + + + menuContribution:popup + popup:org.eclipse.ui.navigator.ProjectExplorer#PopupMenu + + + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + + View + categoryTag:General + + ViewMenu + menuContribution:menu + + + menuContribution:popup + popup:org.eclipse.jdt.ui.outline + + + + + + + + View + categoryTag:General + + ViewMenu + menuContribution:menu + + + menuContribution:popup + popup:org.eclipse.ui.views.TaskList + popup:org.eclipse.ui.ide.MarkersView + + + + + + + View + categoryTag:General + + + + + View + categoryTag:Java + + ViewMenu + menuContribution:menu + + + + + + + View + categoryTag:Mylyn + + + + + View + categoryTag:Ant + + + + toolbarSeparator + + + + Draggable + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + + toolbarSeparator + + + + Draggable + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + + Draggable + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + + Draggable + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + + toolbarSeparator + + + + Draggable + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + Opaque + + + + Opaque + + + Opaque + + + Opaque + + + + Draggable + + + toolbarSeparator + + + + toolbarSeparator + + + + Draggable + + Opaque + + + Opaque + + + + stretch + SHOW_RESTORE_MENU + + + Draggable + HIDEABLE + SHOW_RESTORE_MENU + + + + + stretch + + + Draggable + + + Draggable + + + + + + TrimStack + Draggable + + + + + + + + + + + + + platform:cocoa + + + + + + + + + platform:cocoa + + + + + + + + + + + + + + + + + + platform:cocoa + + + + + + + platform:cocoa + + + platform:cocoa + + + + platform:cocoa + + + platform:cocoa + + + + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + platform:cocoa + + + + + + + + + + + + + platform:cocoa + + + platform:cocoa + + + + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + + + + + + + platform:cocoa + + + + + platform:cocoa + + + + + + + + + + + + + + + + + + + + + platform:cocoa + + + + + + platform:cocoa + + + platform:cocoa + + + + + + + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + platform:cocoa + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + + platform:cocoa + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + + + + + + platform:cocoa + + + + + + + + + + + platform:cocoa + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + + + platform:cocoa + + + + platform:cocoa + + + + + + platform:cocoa + + + + platform:cocoa + + + platform:cocoa + + + + + + + platform:cocoa + + + + platform:cocoa + + + platform:cocoa + + + + + platform:cocoa + + + platform:cocoa + + + + platform:cocoa + + + + + + platform:cocoa + + + + + + + + + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + + + + platform:cocoa + + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + platform:cocoa + + + + + + + + + + platform:cocoa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + platform:cocoa + + + + platform:cocoa + + + + + + + + + + + + + platform:cocoa + + + + + + + + + platform:cocoa + + + + + platform:cocoa + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + + + + + platform:cocoa + + + + + + + platform:cocoa + + + + + platform:cocoa + + + platform:cocoa + + + + + + platform:cocoa + + + + + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + platform:cocoa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + platform:cocoa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Editor + + + + + View + categoryTag:AspectJ + + + + + View + categoryTag:Ant + + + + + View + categoryTag:Gradle + + + + + View + categoryTag:Gradle + + + + + View + categoryTag:Visualiser + + + + + View + categoryTag:Visualiser + + + + + View + categoryTag:AspectJ + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Java + + + + + View + categoryTag:Git + + + + + View + categoryTag:Git + + + + + View + categoryTag:Git + + + + + View + categoryTag:Git + + + + + View + categoryTag:Git + + + + + View + categoryTag:General + + + + + View + categoryTag:Help + + + + + View + categoryTag:Java + + + + + View + categoryTag:Debug + + + + + View + categoryTag:Java + + + + + View + categoryTag:Java + + + + + View + categoryTag:Java + + + + + View + categoryTag:Java + + + + + View + categoryTag:Java Browsing + + + + + View + categoryTag:Java Browsing + + + + + View + categoryTag:Java Browsing + + + + + View + categoryTag:Java Browsing + + + + + View + categoryTag:Java + + + + + View + categoryTag:General + + + + + View + categoryTag:Java + + + + + View + categoryTag:Java + + + + + View + categoryTag:Maven + + + + + View + categoryTag:Maven + + + + + View + categoryTag:Mylyn + + + + + View + categoryTag:Mylyn + + + + + View + categoryTag:Mylyn + + + + + View + categoryTag:Mylyn + + + + + View + categoryTag:Oomph + + + + + View + categoryTag:API Tools + + + + + View + categoryTag:Plug-in Development + + + + + View + categoryTag:Plug-in Development + + + + + View + categoryTag:Plug-in Development + + + + + View + categoryTag:Plug-in Development + + + + + View + categoryTag:Plug-in Development + + + + + View + categoryTag:Code Recommenders + + + + + View + categoryTag:Code Recommenders + + + + + View + categoryTag:Code Recommenders + + + + + View + categoryTag:Code Recommenders + + + + + View + categoryTag:Code Recommenders + + + + + View + categoryTag:Java + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:Team + + + + + View + categoryTag:Team + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:Help + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:General + + + + + View + categoryTag:XML + + + + + View + categoryTag:XML + + + + + View + categoryTag:PyDev + + + + + View + categoryTag:PyDev + + + + + View + categoryTag:PyDev + + + + + View + categoryTag:PyDev + + + + + View + categoryTag:PyDev + + + + + View + categoryTag:PyDev + + + + + View + categoryTag:PyDev + + + + + View + categoryTag:PyDev + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/http-cache.lucene60/segments_1 b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/http-cache.lucene60/segments_1 new file mode 100644 index 0000000..72b3730 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/http-cache.lucene60/segments_1 differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/http-cache.lucene60/write.lock b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/http-cache.lucene60/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.cfe b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.cfe new file mode 100644 index 0000000..89eaf3c Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.cfe differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.cfs b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.cfs new file mode 100644 index 0000000..a297d0b Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.si b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.si new file mode 100644 index 0000000..5d33e8c Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/_0.si differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/segments_1 b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/segments_1 new file mode 100644 index 0000000..b6402db Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/segments_1 differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/write.lock b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/local-history.lucene60/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/server-config.json b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/server-config.json new file mode 100644 index 0000000..ed4aa44 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.epp.logging.aeri.ide/org.eclipse.epp.logging.aeri.ide.server/server-config.json @@ -0,0 +1,72 @@ +{ + "version": "v1", + "title": "Eclipse", + "timestamp": 1526578724042, + "ttl": 10080, + "helpUrl": "https://dev.eclipse.org/recommenders/community/aeri/v2/help/", + "feedbackUrl": "https://www.codetrails.com/error-analytics/", + "aboutUrl": "https://wiki.eclipse.org/EPP/Logging", + "submitUrl": "https://dev.eclipse.org/recommenders/community/confess/0.6/reports/", + "maxReportSize": 262144, + "problemsUrl": "https://www.eclipse.org/downloads/download.php?r\u003d1\u0026file\u003d/technology/epp/logging/problems.zip", + "problemsTtl": 20160, + "interestUrl": "https://dev.eclipse.org/recommenders/community/confess/v2/interest", + "connectTimeout": 10, + "socketTimeout": 10, + "acceptedProducts": [ + "org.eclipse.*", + "org.fordiac.*" + ], + "acceptedPlugins": [ + "org.apache.log4j.*", + "org.eclipse.*", + "org.fordiac.*" + ], + "acceptedPackages": [ + "ch.qos.*", + "com.cforcoding.*", + "com.google.*", + "com.gradleware.tooling.*", + "com.mountainminds.eclemma.*", + "com.naef.*", + "com.sun.*", + "java.*", + "javafx.*", + "javax.*", + "org.apache.*", + "org.eclipse.*", + "org.fordiac.*", + "org.gradle.*", + "org.jacoco.*", + "org.osgi.*", + "org.slf4j.*", + "sun.*" + ], + "requiredPackages": [ + "com.cforcoding.*", + "com.gradleware.tooling.*", + "com.mountainminds.eclemma.*", + "com.naef.*", + "org.eclipse.*", + "org.fordiac.*", + "org.gradle.*", + "org.jacoco.*" + ], + "acceptOtherPackages": false, + "acceptUiFreezes": true, + "ignoredStatuses": [ + ":java.io.IOException:There is not enough space on the disk", + ":java.net.*:", + "org.eclipse.core.filesystem::Could not delete*", + "org.eclipse.core.filesystem::Could not move*", + "org.eclipse.core.resources:org.eclipse.core.internal.resources.ResourceException:Resource is out of sync with the file system*", + "org.eclipse.core.runtime::Invalid input url*", + "org.eclipse.epp.mpc.ui:java.io.IOException:", + "org.eclipse.equinox.p2.*::", + "org.eclipse.jface:java.io.IOException:Unable to resolve plug-in*", + "org.eclipse.oomph.setup.core:$org.apache.http.ConnectionClosedException:", + "org.eclipse.pde.core::The current target platform contains errors*", + "org.eclipse.ui::Conflicting handlers for*" + ], + "problemsZipLastDownloadTimestamp": 0 +} \ No newline at end of file diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1097848872.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1097848872.index new file mode 100644 index 0000000..65608da Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1097848872.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1180484879.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1180484879.index new file mode 100644 index 0000000..cbaa2cb Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1180484879.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1271342938.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1271342938.index new file mode 100644 index 0000000..30237d5 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1271342938.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1384487945.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1384487945.index new file mode 100644 index 0000000..2b24690 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1384487945.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/145268399.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/145268399.index new file mode 100644 index 0000000..c9c7a33 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/145268399.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/156905802.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/156905802.index new file mode 100644 index 0000000..16b9af8 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/156905802.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1690311816.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1690311816.index new file mode 100644 index 0000000..98c0932 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1690311816.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1699738662.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1699738662.index new file mode 100644 index 0000000..9e716fc Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1699738662.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1819685514.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1819685514.index new file mode 100644 index 0000000..da97360 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1819685514.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1833648217.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1833648217.index new file mode 100644 index 0000000..7ad3506 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/1833648217.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2056418733.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2056418733.index new file mode 100644 index 0000000..f777408 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2056418733.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/206535591.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/206535591.index new file mode 100644 index 0000000..ce9a98d Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/206535591.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2137341644.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2137341644.index new file mode 100644 index 0000000..e3d095a Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2137341644.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2345560674.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2345560674.index new file mode 100644 index 0000000..23573ff Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2345560674.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2362891960.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2362891960.index new file mode 100644 index 0000000..a4b3912 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2362891960.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2545238116.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2545238116.index new file mode 100644 index 0000000..ce35156 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2545238116.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2575165415.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2575165415.index new file mode 100644 index 0000000..3819005 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2575165415.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2789758058.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2789758058.index new file mode 100644 index 0000000..8b73a0c Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2789758058.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2842472240.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2842472240.index new file mode 100644 index 0000000..911d26b Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/2842472240.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3045154579.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3045154579.index new file mode 100644 index 0000000..47ea2d7 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3045154579.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3126888922.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3126888922.index new file mode 100644 index 0000000..217f7e6 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3126888922.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3175304630.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3175304630.index new file mode 100644 index 0000000..feb4007 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3175304630.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3266567714.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3266567714.index new file mode 100644 index 0000000..3d7fa94 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3266567714.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3273049893.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3273049893.index new file mode 100644 index 0000000..7907489 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3273049893.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3277980169.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3277980169.index new file mode 100644 index 0000000..9add4c7 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3277980169.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3302703152.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3302703152.index new file mode 100644 index 0000000..74c505b Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3302703152.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3321539481.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3321539481.index new file mode 100644 index 0000000..dcc1e2b Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3321539481.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3360226141.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3360226141.index new file mode 100644 index 0000000..070be3a Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3360226141.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3619427458.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3619427458.index new file mode 100644 index 0000000..3191fe3 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3619427458.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3712507179.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3712507179.index new file mode 100644 index 0000000..31a08f0 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/3712507179.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/43572380.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/43572380.index new file mode 100644 index 0000000..f796022 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/43572380.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/648288460.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/648288460.index new file mode 100644 index 0000000..88e40b7 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/648288460.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/676043254.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/676043254.index new file mode 100644 index 0000000..0baad03 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/676043254.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/853707784.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/853707784.index new file mode 100644 index 0000000..ade04c1 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/853707784.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/88183214.index b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/88183214.index new file mode 100644 index 0000000..ef3d09d Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/88183214.index differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache new file mode 100644 index 0000000..593f470 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache new file mode 100644 index 0000000..8b3fa76 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps new file mode 100644 index 0000000..d3c6fb1 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/index.db b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/index.db new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/indexNamesMap.txt b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/indexNamesMap.txt new file mode 100644 index 0000000..0295c3b --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/indexNamesMap.txt @@ -0,0 +1 @@ +INDEX VERSION 1.130 diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt new file mode 100644 index 0000000..4644f71 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt @@ -0,0 +1,2 @@ +aj +java \ No newline at end of file diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache new file mode 100644 index 0000000..1bd4bbe Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt new file mode 100644 index 0000000..6581a04 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt @@ -0,0 +1,36 @@ +INDEX VERSION 1.130+/Users/bjohnson/eclipse-workspace/org.fuzzydriver.plugin/.metadata/.plugins/org.eclipse.jdt.core +1384487945.index +1833648217.index +1699738662.index +2137341644.index +3266567714.index +2545238116.index +648288460.index +1690311816.index +3302703152.index +3277980169.index +206535591.index +2789758058.index +1097848872.index +3175304630.index +3045154579.index +676043254.index +2056418733.index +145268399.index +1180484879.index +853707784.index +1819685514.index +2362891960.index +2575165415.index +2345560674.index +1271342938.index +43572380.index +3619427458.index +3712507179.index +2842472240.index +88183214.index +3360226141.index +3126888922.index +3273049893.index +156905802.index +3321539481.index diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat new file mode 100644 index 0000000..5f51125 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.launching/.install.xml b/Holmes/.metadata/.plugins/org.eclipse.jdt.launching/.install.xml new file mode 100644 index 0000000..b22c51d --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.launching/.install.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.launching/libraryInfos.xml b/Holmes/.metadata/.plugins/org.eclipse.jdt.launching/libraryInfos.xml new file mode 100644 index 0000000..b569d3c --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.launching/libraryInfos.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml b/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml new file mode 100644 index 0000000..a4ee3cb --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml @@ -0,0 +1,2 @@ + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml b/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml new file mode 100644 index 0000000..9e390f5 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml @@ -0,0 +1,2 @@ + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml b/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml new file mode 100644 index 0000000..e74a85b --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml @@ -0,0 +1,9 @@ + +
+
+
+
+
+
+
+
diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_a.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_a.cfs new file mode 100644 index 0000000..df588c2 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_a.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_a_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_a_1.del new file mode 100644 index 0000000..1b473bd Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_a_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_b.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_b.cfs new file mode 100644 index 0000000..bf1657d Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_b.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_b_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_b_1.del new file mode 100644 index 0000000..1b473bd Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_b_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_c.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_c.cfs new file mode 100644 index 0000000..21c08b6 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/_c.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments.gen b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments.gen new file mode 100644 index 0000000..534ee70 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments.gen differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments_d b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments_d new file mode 100644 index 0000000..575e23f Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/segments_d differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/write.lock b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/05b0fe8524860bd73cbb07ef30fb34cc/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_a.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_a.cfs new file mode 100644 index 0000000..9405764 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_a.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_a_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_a_1.del new file mode 100644 index 0000000..1b473bd Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_a_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_b.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_b.cfs new file mode 100644 index 0000000..92d2f5a Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_b.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_b_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_b_1.del new file mode 100644 index 0000000..1b473bd Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_b_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_c.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_c.cfs new file mode 100644 index 0000000..84be3ee Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/_c.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/segments.gen b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/segments.gen new file mode 100644 index 0000000..534ee70 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/segments.gen differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/segments_d b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/segments_d new file mode 100644 index 0000000..0bb273d Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/segments_d differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/write.lock b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/3d21adf56b1238ae93fc0cbf6d7b59a0/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_a.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_a.cfs new file mode 100644 index 0000000..4bd086e Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_a.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_a_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_a_1.del new file mode 100644 index 0000000..6ad5fba Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_a_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_b.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_b.cfs new file mode 100644 index 0000000..3f2df2b Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_b.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_b_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_b_1.del new file mode 100644 index 0000000..1b473bd Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_b_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_c.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_c.cfs new file mode 100644 index 0000000..7c48236 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_c.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_c_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_c_1.del new file mode 100644 index 0000000..1b473bd Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_c_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_d.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_d.cfs new file mode 100644 index 0000000..832dc18 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_d.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_d_1.del b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_d_1.del new file mode 100644 index 0000000..1b473bd Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_d_1.del differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_e.cfs b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_e.cfs new file mode 100644 index 0000000..217cf16 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/_e.cfs differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen new file mode 100644 index 0000000..026de2b Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments_f b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments_f new file mode 100644 index 0000000..7d82d79 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments_f differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/write.lock b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/write.lock new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser new file mode 100644 index 0000000..918e042 Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.core/workspacestate.properties b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/workspacestate.properties new file mode 100644 index 0000000..be62be4 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.m2e.core/workspacestate.properties @@ -0,0 +1,4 @@ +#Thu May 17 13:39:35 EDT 2018 +org.apache.commons\:commons-lang3\:jar\:\:3.0.2-SNAPSHOT=/Users/bjohnson/eclipse-workspace/lang_16_buggy/target/classes +org.apache.commons\:commons-lang3\:pom\:\:3.0.2-SNAPSHOT=/Users/bjohnson/eclipse-workspace/lang_16_buggy/pom.xml +org.apache.commons\:commons-lang3\:jar\:tests\:3.0.2-SNAPSHOT=/Users/bjohnson/eclipse-workspace/lang_16_buggy/target/test-classes diff --git a/Holmes/.metadata/.plugins/org.eclipse.m2e.jdt/lang_16_buggy.container b/Holmes/.metadata/.plugins/org.eclipse.m2e.jdt/lang_16_buggy.container new file mode 100644 index 0000000..76559ff Binary files /dev/null and b/Holmes/.metadata/.plugins/org.eclipse.m2e.jdt/lang_16_buggy.container differ diff --git a/Holmes/.metadata/.plugins/org.eclipse.oomph.setup.ui/dialog_settings.xml b/Holmes/.metadata/.plugins/org.eclipse.oomph.setup.ui/dialog_settings.xml new file mode 100644 index 0000000..9444160 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.oomph.setup.ui/dialog_settings.xml @@ -0,0 +1,11 @@ + +
+
+
+
+
+
+
+
+
+
diff --git a/Holmes/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup b/Holmes/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup new file mode 100644 index 0000000..1f73e14 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup @@ -0,0 +1,6 @@ + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.pde.core/.cache/clean-cache.properties b/Holmes/.metadata/.plugins/org.eclipse.pde.core/.cache/clean-cache.properties new file mode 100644 index 0000000..52ef57e --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.pde.core/.cache/clean-cache.properties @@ -0,0 +1,2 @@ +#Cached timestamps +#Thu May 17 19:51:51 EDT 2018 diff --git a/Holmes/.metadata/.plugins/org.eclipse.recommenders.news.impl/downloads/http%3A%2F%2Fwww.eclipse.org%2Fhome%2Feclipsenews.rss b/Holmes/.metadata/.plugins/org.eclipse.recommenders.news.impl/downloads/http%3A%2F%2Fwww.eclipse.org%2Fhome%2Feclipsenews.rss new file mode 100644 index 0000000..e7e6d3f --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.recommenders.news.impl/downloads/http%3A%2F%2Fwww.eclipse.org%2Fhome%2Feclipsenews.rss @@ -0,0 +1,541 @@ + + + + Eclipse News + http://www.eclipse.org + Eclipse News + + http://eclipse.org/eclipse.org-common/themes/Nova/images/eclipse.png + eclipse.org + http://www.eclipse.org + + + <![CDATA[EclipseCon Europe 2018 Call for Papers]]> + + + Mon, 14 May 2018 13:00:00 EST + news + 0 + + + <![CDATA[New Proposed Charter for OS.bea Working Group]]> + + + Mon, 14 May 2018 13:00:00 EST + news + 0 + + + <![CDATA[Eclipse Common Build Infrastructure: Upcoming Changes]]> + + + Thu, 10 May 2018 09:00:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter - Java Tools and Runtimes]]> + + + Fri, 04 May 2018 05:00:00 EST + news + 0 + + + <![CDATA[EclipseCon France 2018: Register Early!]]> + + + Wed, 25 Apr 2018 08:30:00 EST + news + 0 + + + <![CDATA[Survey of 1800+ developers now released on new Jakarta EE website]]> + + + Tue, 24 Apr 2018 09:00:00 EST + news + 0 + + + <![CDATA[IoT Developer Survey 2018 | Results are in!]]> + + + Tue, 17 Apr 2018 09:00:00 EST + news + 0 + + + <![CDATA[Eclipse Oxygen 3A has been released!]]> + + + Thu, 12 Apr 2018 09:00:00 EST + news + 0 + + + <![CDATA[Winners of Open IoT Challenge 4.0 Demonstrate How Open Source Accelerates Innovation]]> + + + Wed, 04 Apr 2018 09:00:00 EST + news + 1 + + + <![CDATA[EclipseCon France 2018 Program Announced]]> + + + Tue, 03 Apr 2018 09:00:00 EST + news + 0 + + + <![CDATA[Voting for the Jakarta EE logo is now open!]]> + + + Thu, 29 Mar 2018 17:45:00 EST + news + 0 + + + <![CDATA[Three days left to complete the Jakarta EE Survey!]]> + + + Tue, 27 Mar 2018 07:10:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Code in Different Languages]]> + + + Thu, 22 Mar 2018 04:13:00 EST + news + 0 + + + <![CDATA[Complete the Jakarta EE Developer Survey]]> + + + Thu, 16 Mar 2018 06:45:00 EST + news + 0 + + + <![CDATA[Eclipse IoT Day Santa Clara | Speakers Announced]]> + + + Thu, 15 Mar 2018 07:00:00 EST + news + 0 + + + <![CDATA[Last call for EclipseCon France submissions]]> + + + Mon, 12 Mar 2018 16:00:00 EST + news + 0 + + + <![CDATA[Eclipse Foundation supports EU funded Brain-IoT Project]]> + + + Mon, 12 Mar 2018 09:00:00 EST + news + 1 + + + <![CDATA[Eclipse Foundation Announces 2018 Board Member Election Results]]> + + + Wed, 07 Mar 2018 18:00:00 EST + news + 1 + + + <![CDATA[From Java EE to Jakarta EE]]> + + + Mon, 26 Feb 2018 14:50:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Boot & Build Eclipse Projects]]> + + + Thu, 22 Feb 2018 3:51:00 EST + news + 0 + + + <![CDATA[Countdown: 2 weeks | Complete IoT Developer Survey]]> + + + Tue, 20 Feb 2018 4:27:00 EST + news + 0 + + + <![CDATA[EclipseCon France 2018 | Call for Papers]]> + + + Mon, 12 Feb 2018 09:15:00 EST + news + 0 + + + <![CDATA[EE.next working group | Community review process]]> + + + Wed, 06 Feb 2018 08:00:00 EST + news + 0 + + + <![CDATA[Last Week to Submit for FOSS4G NA 2018!]]> + + + Fri, 02 Feb 2018 08:30:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Coming in 2018]]> + + + Wed, 25 Jan 2018 10:30:00 EST + news + 0 + + + <![CDATA[Launching IoT Developer Survey 2018]]> + + + Wed, 24 Jan 2018 4:27:00 EST + news + 1 + + + <![CDATA[Eclipse IoT Day Santa Clara 2018 | Call for Papers]]> + + + Mon, 15 Jan 2018 9:15:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Capella: open source MBSE solution]]> + + + Thu, 14 Dec 2017 10:10:00 EST + news + 0 + + + <![CDATA[Open Source Community Accelerates Big Data Analytics for Geospatial Solutions]]> + + + Thu, 14 Dec 2017 08:00:00 EST + news + 1 + + + <![CDATA[Announcing Open IoT Challenge 4.0 Scholars]]> + + + Wed, 13 Dec 2017 09:45:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Location Matters]]> + + + Wed, 22 Nov 2017 06:23:00 EST + news + 0 + + + <![CDATA[Open IoT Challenge 4.0 | Extended Deadline Nov 20]]> + + + Wed, 15 Nov 2017 05:30:00 EST + news + 0 + + + <![CDATA[EclipseCon + Ludwigsburg = Great Partners]]> + + + Sun, 22 Oct 2017 08:00:00 EST + news + 0 + + + <![CDATA[New Industry 4.0 Open Testbed Addresses Performance Monitoring and Management in Manufacturing]]> + + + Thu, 19 Oct 2017 11:00:00 EST + news + 1 + + + <![CDATA[Eclipse Science Advances Open Source Technology for Scientific Research]]> + + + Wed, 18 Oct 2017 09:00:00 EST + news + 1 + + + <![CDATA[Eclipse Newsletter | Utility Belt: Projects and Tools]]> + + + Wed, 18 Oct 2017 05:02:00 EST + news + 0 + + + <![CDATA[On Naming Eclipse Enterprise for Java (EE4J)]]> + + + Wed, 04 Oct 2017 08:48:00 EST + news + 0 + + + <![CDATA[EclipseCon Europe: Last Chance for the Early Price]]> + + + Tue, 03 Oct 2017 11:30:00 EST + news + 0 + + + <![CDATA[Annual Donation Campaign: End User Support for the Eclipse Foundation]]> + + + Fri, 29 Sep 2017 11:00:00 EST + news + 0 + + + <![CDATA[Eclipse IoT Announces Fourth Edition of the Open IoT Challenge]]> + + + Thu, 28 Sep 2017 09:10:00 EST + news + 1 + + + <![CDATA[Eclipse IDE Now Supports Java 9]]> + + + Tue, 26 Sep 2017 14:30:00 EST + news + 0 + + + <![CDATA[Special Notice for Eclipse IDE Users on macOS 10.13 in non-English mode]]> + + + Mon, 25 Sep 2017 08:30:00 EST + news + 0 + + + <![CDATA[Get the Early Price for EclipseCon Europe]]> + + + Thu, 21 Sep 2017 08:30:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Eclipse MicroProfile]]> + + + Wed, 20 Sep 2017 10:30:00 EST + news + 0 + + + <![CDATA[Java EE Moves to the Eclipse Foundation]]> + + + Tue, 12 Sep 2017 17:00:00 EST + news + 0 + + + <![CDATA[First Release of Eclipse Papyrus for Real Time: Modeling Tool for UML-RT]]> + + + Thu, 07 Sep 2017 09:00:00 EST + news + 1 + + + <![CDATA[Eclipse Public License Version 2.0 Approved By OSI and Eclipse Foundation Board of Directors]]> + + + Tue, 29 Aug 2017 14:20:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Exciting New Eclipse Projects]]> + + + Tue, 22 Aug 2017 09:00:00 EST + news + 0 + + + <![CDATA[EclipseCon Europe: Schedule and Keynotes]]> + + + Mon, 21 Aug 2017 10:10:00 EST + news + 0 + + + <![CDATA[Launching Eclipse IoT Newsletter]]> + + + Fri, 18 Aug 2017 05:40:00 EST + news + 0 + + + <![CDATA[Eclipse IoT Day @ ThingMonk]]> + + + Thu, 17 Aug 2017 08:55:00 EST + news + 0 + + + <![CDATA[Potential adware plugin on Eclipse Marketplace - Eclipse Class Decompiler]]> + + + Mon, 14 Aug 2017 10:40:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Summer Issue]]> + + + Tue, 25 Jul 2017 10:05:00 EST + news + 0 + + + <![CDATA[EclipseCon Europe 2017 | Submissions Close in One Week]]> + + + Mon, 10 Jul 2017 09:05:00 EST + news + 0 + + + <![CDATA[Eclipse Oxygen Now Available]]> + + + Wed, 28 Jun 2017 10:05:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter | Eclipse Oxygen]]> + + + Wed, 28 Jun 2017 10:26:00 EST + news + 0 + + + <![CDATA[Early Submission Deadline for EclipseCon Europe 2017]]> + + + Mon, 26 Jun 2017 22:00:00 EST + news + 0 + + + <![CDATA[Capella Industry Consortium (IC) Announced at PolarSys]]> + + + Tue, 20 Jun 2017 04:00:00 EST + news + 0 + + + <![CDATA[RC3 Available for Eclipse Oxygen | Download Now]]> + + + Mon, 12 Jun 2017 15:45:00 EST + news + 0 + + + <![CDATA[Last Chance to Register for EclipseCon France 2017]]> + + + Thu, 08 Jun 2017 10:45:00 EST + news + 0 + + + <![CDATA[Eclipse Newsletter - Language Server Protocol 101]]> + + + Wed, 24 May 2017 05:35:00 EST + news + 0 + + + <![CDATA[It’s time to organise Eclipse Oxygen DemoCamps]]> + + + Tue, 23 May 2017 04:35:00 EST + news + 0 + + + <![CDATA[Case Study: Deploying Eclipse IoT on Germany's DB Railway System]]> + + + Thu, 18 May 2017 04:55:00 EST + news + 0 + + + <![CDATA[EclipseCon Europe 2017 | Call for Papers Open]]> + + + Wed, 17 May 2017 09:29:00 EST + news + 0 + + + <![CDATA[Program Ready for EclipseCon France 2017]]> + + + Thu, 27 Apr 2017 17:10:00 EST + news + 0 + + + <![CDATA[New Eclipse IoT Open Testbeds]]> + + + Thu, 27 Apr 2017 09:05:00 EST + news + 1 + + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.recommenders.news.impl/downloads/http%3A%2F%2Fwww.eclipse.org%2Frecommenders%2Ffeeds%2Fide.rss b/Holmes/.metadata/.plugins/org.eclipse.recommenders.news.impl/downloads/http%3A%2F%2Fwww.eclipse.org%2Frecommenders%2Ffeeds%2Fide.rss new file mode 100644 index 0000000..b6219a4 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.recommenders.news.impl/downloads/http%3A%2F%2Fwww.eclipse.org%2Frecommenders%2Ffeeds%2Fide.rss @@ -0,0 +1,13 @@ + + + + Code Recommenders In-IDE News + https://www.eclipse.org/recommenders/ + The latest news about Code Recommenders, delivered to your Eclipse IDE + + Insert Knowledge Here - A Guide to Intelligent Code Completion Using Eclipse Code Recommenders + https://medium.com/codetrails/insert-knowledge-here-a2f71c2862d2?utm_source=rss-eclipse&utm_medium=eclipse&utm_campaign=cc + Tue, 10 Oct 2017 16:00:00 GMT + + + diff --git a/Holmes/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/Holmes/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml new file mode 100644 index 0000000..7b64e3f --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml @@ -0,0 +1,28 @@ + +
+
+ + + + + + + + + +
+
+ + + + + +
+ + + + + +
+
+
diff --git a/Holmes/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/Holmes/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml new file mode 100644 index 0000000..5593325 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml @@ -0,0 +1,21 @@ + +
+
+ + + + + + + + + + +
+
+ + + + +
+
diff --git a/Holmes/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/Holmes/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml new file mode 100644 index 0000000..9ca4bfa --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Holmes/.metadata/.plugins/org.eclipse.ui/dialog_settings.xml b/Holmes/.metadata/.plugins/org.eclipse.ui/dialog_settings.xml new file mode 100644 index 0000000..5ca0b77 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.ui/dialog_settings.xml @@ -0,0 +1,3 @@ + +
+
diff --git a/Holmes/.metadata/.plugins/org.eclipse.wst.sse.core/task-tags.properties b/Holmes/.metadata/.plugins/org.eclipse.wst.sse.core/task-tags.properties new file mode 100644 index 0000000..70f4429 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.eclipse.wst.sse.core/task-tags.properties @@ -0,0 +1,3 @@ +# +#Thu May 17 13:39:30 EDT 2018 +task-tag-projects-already-scanned=lang_16_buggy diff --git a/Holmes/.metadata/.plugins/org.python.pydev/pyunit_tests/test_run_pin_info.txt b/Holmes/.metadata/.plugins/org.python.pydev/pyunit_tests/test_run_pin_info.txt new file mode 100644 index 0000000..27cc728 --- /dev/null +++ b/Holmes/.metadata/.plugins/org.python.pydev/pyunit_tests/test_run_pin_info.txt @@ -0,0 +1 @@ +|| \ No newline at end of file diff --git a/Holmes/.metadata/version.ini b/Holmes/.metadata/version.ini new file mode 100644 index 0000000..b46dcde --- /dev/null +++ b/Holmes/.metadata/version.ini @@ -0,0 +1,3 @@ +#Fri May 18 19:37:45 EDT 2018 +org.eclipse.core.runtime=2 +org.eclipse.platform=4.7.2.v20171130-0510 diff --git a/Holmes/.project b/Holmes/.project new file mode 100644 index 0000000..80076dc --- /dev/null +++ b/Holmes/.project @@ -0,0 +1,28 @@ + + + Holmes + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/Holmes/.settings/org.eclipse.jdt.core.prefs b/Holmes/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..a698e59 --- /dev/null +++ b/Holmes/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/Holmes/META-INF/MANIFEST.MF b/Holmes/META-INF/MANIFEST.MF new file mode 100644 index 0000000..a54f452 --- /dev/null +++ b/Holmes/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Holmes_1.0 +Bundle-SymbolicName: org.holmes.plugin;singleton:=true +Bundle-Version: 1.0.0.qualifier +Require-Bundle: org.eclipse.core.resources;bundle-version="3.12.0", + org.eclipse.core.runtime;bundle-version="3.13.0", + org.eclipse.jdt.core;bundle-version="3.13.100", + org.eclipse.ui;bundle-version="3.109.0", + org.eclipse.ui.ide;bundle-version="3.13.1", + org.eclipse.jface.text;bundle-version="3.12.1", + org.junit;bundle-version="4.12.0", + org.eclipse.jdt.ui;bundle-version="3.13.51" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ClassPath: ., + lib/commons-exec-1.3/commons-exec-1.3.jar, + lib/org.eclipse.jdt.ui_3.5.2.r352_v20100106-0800.jar, + lib/commons-text-1.0.jar, + lib/org.eclipse.ui.workbench.texteditor-3.3.2.jar, + lib/roaster-api-2.20.8.Final.jar, + lib/commons-io-2.6.jar, + lib/aspectjweaver.jar, + lib/MaintainJAspect.jar diff --git a/Holmes/bin-javah/javah b/Holmes/bin-javah/javah new file mode 100755 index 0000000..1503336 Binary files /dev/null and b/Holmes/bin-javah/javah differ diff --git a/Holmes/bin/org/holmes/plugin/actions/RunHolmes.class b/Holmes/bin/org/holmes/plugin/actions/RunHolmes.class new file mode 100644 index 0000000..49b726c Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/actions/RunHolmes.class differ diff --git a/Holmes/bin/org/holmes/plugin/nodevisitor/GeneratedTestVisitor.class b/Holmes/bin/org/holmes/plugin/nodevisitor/GeneratedTestVisitor.class new file mode 100644 index 0000000..0b6b6ce Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/nodevisitor/GeneratedTestVisitor.class differ diff --git a/Holmes/bin/org/holmes/plugin/nodevisitor/TestMethodVisitor.class b/Holmes/bin/org/holmes/plugin/nodevisitor/TestMethodVisitor.class new file mode 100644 index 0000000..406629b Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/nodevisitor/TestMethodVisitor.class differ diff --git a/Holmes/bin/org/holmes/plugin/util/Test.class b/Holmes/bin/org/holmes/plugin/util/Test.class new file mode 100644 index 0000000..9f006de Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/util/Test.class differ diff --git a/Holmes/bin/org/holmes/plugin/util/Util.class b/Holmes/bin/org/holmes/plugin/util/Util.class new file mode 100644 index 0000000..d3d2542 Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/util/Util.class differ diff --git a/Holmes/bin/org/holmes/plugin/views/HolmesView$1.class b/Holmes/bin/org/holmes/plugin/views/HolmesView$1.class new file mode 100644 index 0000000..4502518 Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/views/HolmesView$1.class differ diff --git a/Holmes/bin/org/holmes/plugin/views/HolmesView$2.class b/Holmes/bin/org/holmes/plugin/views/HolmesView$2.class new file mode 100644 index 0000000..22ef141 Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/views/HolmesView$2.class differ diff --git a/Holmes/bin/org/holmes/plugin/views/HolmesView$ViewLabelProvider.class b/Holmes/bin/org/holmes/plugin/views/HolmesView$ViewLabelProvider.class new file mode 100644 index 0000000..d7347c5 Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/views/HolmesView$ViewLabelProvider.class differ diff --git a/Holmes/bin/org/holmes/plugin/views/HolmesView.class b/Holmes/bin/org/holmes/plugin/views/HolmesView.class new file mode 100644 index 0000000..c5d1087 Binary files /dev/null and b/Holmes/bin/org/holmes/plugin/views/HolmesView.class differ diff --git a/Holmes/build.properties b/Holmes/build.properties new file mode 100644 index 0000000..6c97728 --- /dev/null +++ b/Holmes/build.properties @@ -0,0 +1,36 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + icons/,\ + lib/commons-exec-1.3/commons-exec-1.3.jar,\ + lib/org.eclipse.jdt.ui_3.5.2.r352_v20100106-0800.jar,\ + lib/commons-text-1.0.jar,\ + build.properties,\ + lib/org.eclipse.ui.workbench.texteditor-3.3.2.jar,\ + lib/roaster-api-2.20.8.Final.jar,\ + lib/commons-io-2.6.jar,\ + lib/aspectjweaver.jar,\ + lib/MaintainJAspect.jar +jars.compile.order = .,\ + lib/kelinci.jar,\ + lib/fuzzino.jar,\ + lib/jython-standalone-2.7.0.jar,\ + lib/wrapper.jar,\ + lib/wrapperdemo.jar,\ + lib/wrappertest.jar,\ + lib/commons-exec-1.3/commons-exec-1.3.jar,\ + lib/commons-text-1.0.jar,\ + lib/google-collect-0.5.jar,\ + lib/lang_16.jar,\ + projects/lang_16_buggy/,\ + lib/lang_16_buggy.jar,\ + lib/org.eclipse.jdt.ui-3.12.2.jar,\ + lib/org.eclipse.jdt.ui_3.5.2.r352_v20100106-0800.jar,\ + lib/roaster-api-2.20.8.Final.jar,\ + lib/commons-io-2.6.jar,\ + lib/aspectjweaver.jar,\ + lib/MaintainJAspect.jar + + diff --git a/Holmes/icons/holmes.png b/Holmes/icons/holmes.png new file mode 100644 index 0000000..3ca07b7 Binary files /dev/null and b/Holmes/icons/holmes.png differ diff --git a/Holmes/icons/holmes_2.png b/Holmes/icons/holmes_2.png new file mode 100644 index 0000000..01e86a5 Binary files /dev/null and b/Holmes/icons/holmes_2.png differ diff --git a/Holmes/icons/sample.png b/Holmes/icons/sample.png new file mode 100644 index 0000000..02c4b79 Binary files /dev/null and b/Holmes/icons/sample.png differ diff --git a/Holmes/icons/sample@2x.png b/Holmes/icons/sample@2x.png new file mode 100644 index 0000000..c1224d1 Binary files /dev/null and b/Holmes/icons/sample@2x.png differ diff --git a/Holmes/in_dir/testInput.txt b/Holmes/in_dir/testInput.txt new file mode 100644 index 0000000..a8ff560 --- /dev/null +++ b/Holmes/in_dir/testInput.txt @@ -0,0 +1 @@ +0Xfade \ No newline at end of file diff --git a/Holmes/lib/MaintainJAspect.jar b/Holmes/lib/MaintainJAspect.jar new file mode 100644 index 0000000..8f9b688 Binary files /dev/null and b/Holmes/lib/MaintainJAspect.jar differ diff --git a/Holmes/lib/MaintainJAspect14.jar b/Holmes/lib/MaintainJAspect14.jar new file mode 100644 index 0000000..856770c Binary files /dev/null and b/Holmes/lib/MaintainJAspect14.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/META-INF/MANIFEST.MF b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/META-INF/MANIFEST.MF new file mode 100644 index 0000000..b6cd232 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: com.maintainj.core +Bundle-SymbolicName: com.maintainj.core;singleton:=true +Bundle-Version: 4.2.0 +Bundle-Vendor: MaintainJ Inc. +Bundle-Localization: plugin +Bundle-Activator: com.maintainj.core.MaintainJCorePlugin +Eclipse-LazyStart: true +Export-Package: com.maintainj.aspect, + com.maintainj.core, + com.maintainj.traces.db, + com.maintainj.traces.db.search +Bundle-ClassPath: MaintainJCore.jar, + derby.jar, + MaintainJAspect.jar, + MaintainJDatabase.jar +Require-Bundle: org.eclipse.core.runtime diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/MaintainJCore.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/MaintainJCore.jar new file mode 100644 index 0000000..970998b Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/MaintainJCore.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/MaintainJDatabase.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/MaintainJDatabase.jar new file mode 100644 index 0000000..5454d7e Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/MaintainJDatabase.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/derby.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/derby.jar new file mode 100644 index 0000000..33a84e9 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/derby.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/plugin.xml b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/plugin.xml new file mode 100644 index 0000000..30f3884 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.core_4.2.0/plugin.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/META-INF/MANIFEST.MF b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/META-INF/MANIFEST.MF new file mode 100644 index 0000000..d8b7877 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: MaintainJ Wizards +Bundle-SymbolicName: com.maintainj.inst.wizard;singleton:=true +Bundle-Version: 4.2.0 +Bundle-Activator: com.maintainj.wizard.MJWizardPlugin +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.ui.ide, + org.eclipse.core.resources, + org.eclipse.core.runtime, + org.eclipse.jdt.core, + org.eclipse.jdt.ui, + com.maintainj.core +Eclipse-LazyStart: true +Bundle-ClassPath: MaintainJWizard.jar +Bundle-Vendor: MaintainJ Inc. diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/MaintainJAspect.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/MaintainJAspect.jar new file mode 100644 index 0000000..856770c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/MaintainJAspect.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/MaintainJWizard.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/MaintainJWizard.jar new file mode 100644 index 0000000..2649aff Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/MaintainJWizard.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/RSADemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/RSADemo.html new file mode 100644 index 0000000..9bf502a --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/RSADemo.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + +
+Download as PDF + + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/aboutus.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/aboutus.html new file mode 100644 index 0000000..efa3b3f --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/aboutus.html @@ -0,0 +1,80 @@ + + + +

MaintainJ Blog

+

+Check the blog for MaintainJ related issues and thoughts.

+

Contact Us

+

+ MaintainJ Inc.
+ 2611, 5 Massey Square, Toronto, ON, Canada - M4C 5L6
+ Ph: 416 686 7494
+ email: support@maintainj.com

+ +

MaintainJ Story

+

+ The story behind + MaintainJ as told by its founder, Choudary Kothapalli:

+

+ + I have been working on Java since 1997. In the first 6 years I was mostly + doing design and development and in the last 8 years I was mostly into + maintaining large Java applications. In the last 8 years MaintainJ provided + maintenance services to 7 different organizations for applications of + different scale and complexity.

+

+At each company, the applications are mainly Java, J2EE based - +Struts/Servlets/ JSP/EJB/ Spring/ Hibernate/iBatis/SOAP/AJAX/ Portals etc. +Nothing very fancy there. Still, with all my experience in Java, +I find it very time consuming to track down even simple defects. I usually end up +spending lot of time in the debugger. +

+

It would definitely be better to thoroughly understand the code and minimize +the time spent in +debugger, but it does not happen. Most of the time there is little useful +documentation. The core developers who could explain the design are always +busy. Good developers always tend to be too busy to have enough time to coach +new developers.

+ +

+ Different + applications are complex (and difficult to understand) in different ways.

+

+ + Some applications are + just messy. They start as small applications and because they are successful, + they evolve into larger applications. As the original design was not intended + for large applications, after 3-4 releases, the design becomes messy enough + that a new developer would find it hard to understand and maintain. +

+ +

+ At one very successful product company, the design was very generic in nature + because the primary design requirement was flexibility. That design seemed + to work for them. But it was chaos for any new developer. There were good engineers + at that company but few were able to crunch down the design to some basic + and consistent principles and make it easier to follow.

+ +

At another large + automobile company, it was complexity arising from huge code base. The original + design was good and one result of that was lot of code reuse. Three +years after the initial release, it would take many months to make simple changes to +the core modules. +

+The fact is, it is impossible to design the core modules for +all the future requirements. And when the core modules are good, applications +grow very fast around them. In an enterprise setting, it is impossible to review +each line of code and maintain a clean design over the years.

+ +

The time and skills will remain a constraint in the software industry for the +foreseeable future. Given those constraints, without proper tools, developers will +end up taking lot more time than really necessary to understand and maintain code. + +

+MaintainJ is the result of my thinking that there has to be a better way to understand +complex Java applications. It is built for and tested on large real-world applications; +not some academic or 'Hello World' applications. +

+ + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/appletRuntimeDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/appletRuntimeDemo.html new file mode 100644 index 0000000..4f08786 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/appletRuntimeDemo.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/buy.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/buy.html new file mode 100644 index 0000000..177c384 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/buy.html @@ -0,0 +1,91 @@ + + + + + + +
+ + + + + + + + +

Buy MaintainJ License

+ +

There are two types of licensing for MaintainJ - floating and node locked. +Both types of licenses are valid for all future updates of MaintainJ. The licenses include email support. +Support questions from customers will be answered in under 12 hours.

+ +

1. Floating license: This type of license is suitable for development teams. +Floating license is not locked to a computer. The license can be +reassigned among developers as needed. Anyone in the network can use MaintainJ. Floating license is valid forever.

+Cost of floating license: US $299/user
+Contact us at support@maintainj.com to purchase +

2. Node locked license: Node locked license is tied to a single computer and is valid for one year. It can be +used in multiple Eclipse installations as long as they are running on the same +computer. This is suitable for individual users.

+ + + + + + + + + + + + +
Number of LicensesPrice 
US $99/user/yearBuy
+

The Buy link leads to SWREG.org (our payment +gateway), where you can complete the transaction. After payment, you will +receive a MaintainJ Key and instructions to install the license.

+ +

Evaluation License: You can get a 7 day evaluation license +here. + + +

+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/demoVideos.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/demoVideos.html new file mode 100644 index 0000000..5c3b31e --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/demoVideos.html @@ -0,0 +1,153 @@ + + + +

1. MaintainJ Overview Demo

+
+The following Flash video gives an overview of MaintainJ, +taking a large Web application as a sample. The demo starts with the installation +of MaintainJ and showcases the important features relevant to the web applications.

+MaintainJ Overview Demo Video (3 minutes) +

+ +

2. MaintainJ Screenshots

+ +

Check the sample sequence and class diagram +screenshots +that explain the important features of MaintainJ. +

+
+ + + + + + + + + + + + + + + +
+

3. Installation Wizard Demos

+ +
We provide many wizards to install MaintainJ on +different types of applications. The following slideshows +show the steps involved in installing MaintainJ on core Java, web and JUnit applications.

+We also provide the sample applications (JFreeChart) used to record the slideshows. +The sample applications are about 1000 classes, big enough to give you an idea of +how MaintainJ scales. +

+ +

3.1 For web applications

+ +

+ + +3.1.1 +MaintainJ for Tomcat and JBoss: + +Check this if your application runs on Tomcat or JBoss and you deploy and start +the server from Eclipse 'Servers' view. + +

+Sample Application: +This is an Eclipse web project that can be imported into Eclipse. Add it to Tomcat or +JBoss and open http://localhost:8080/jfreechart-sample/ +
+

+ +

+ +3.1.2 +MaintainJ for other Application Servers: + Check this for any other application server or when + you cannot use the above approach for Tomcat or JBoss. +

+ Sample Application: +Deploy the war to the application server of your choice and open +http://localhost:8080/jfreechart-sample/ +

+

+

3.2 For core Java / Applet / JUnit applications run from Eclipse

+ +MaintainJ for Swing Applications

+MaintainJ for Applets +

+ +MaintainJ for JUnit: +MaintainJ seamlessly integrates with JUnit to + generate UML diagrams for each test case. + +

+Sample Application: + The zip is an Eclipse workspace projects that can directly be imported into Eclipse. + The main class and the Applet class used are + org.jfree.chart.demo.TimeSeriesChartDemo1 and +demo.applet.TimeSeriesChartApplet respectively. + +
+

+ +

3.3 For core Java applications run from command prompt

+ +

+ If your application is started from + command prompt, check these.

+

+ + + + For core Java + Applications run from command prompt

+ + + +
+

4. UML Diagram Feature Demos

+ +

4.1 Predefined Filters

+

+ Check how you can define and apply the filters + to view the same diagram at different levels of details.

+

+Predefined Filters Demo   +(Download as PDF)

+

4.2 Exporting the diagrams to RSA (UML2 format)

+

+ The MaintainJ diagrams can be exported as UML2 models + and then be imported into other UML2 compliant tools like + Rational Software Architect (RSA).

+

RSA Integration Demo    +(Download PDF)

+ +

4.3 Runtime Impact Analysis

+

+ + You can search for a class / method or database table / field across trace files. + This feature can be used to find the impacted use cases after a change to a + Java class or method or changing a database table or field. Check the slides below to + find out how. + +

+

+Runtime Impact Analysis Demo +  (Download PDF)

+ +
+ + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/editorIntro.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/editorIntro.html new file mode 100644 index 0000000..04f7bc6 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/editorIntro.html @@ -0,0 +1,557 @@ + + +

4. MaintainJ UML Diagram Editor

+

+MaintainJ UML Diagram Editor renders sequence and class diagrams from +the call trace files. To view the UML diagrams, add the trace files to +a MaintainJ Trace Files Project in Eclipse and open. MaintainJ Trace Files Project +can be created by by following +File->New->Project->MaintainJ->MaintainJ Trace Files Project.

+ +

+All menu options in MaintainJ UML Diagram Editor are provided in context menus, +which can be seen by right clicking anywhere in the diagram or the Eclipse Outline View. Depending on the +selected figure, relevant options are displayed in the context menu. You can 'Undo' and 'Redo' +most of the operations in the editor. + +

+
+

4.1 Sequence Diagram Features

+ +
    +
  • Color Coded Calls: Calls are color + coded. Public calls are shown in + green, private calls are shown in red and protected calls are shown in yellow.
  • +
    +
  • Collapse/Expand Calls: + + icon beside a call name indicates a collapsed call. + + icon + beside a call name indicates an expanded call. All calls are + collapsed initially to present an easy to read diagram. You can expand + and collapse the calls as you explore the diagram. Click on + + to expand a call and on + + to collapse a call.
  • +
    +
  • Collapse All Calls: + Collapses all calls in the diagram.
  • +
    +
  • Expand All Calls: Expands + all calls in the diagram. For trace files with thousands of calls, + expanding all calls will make editing the diagram slow. You should either + explore the diagram by expanding calls of interest or + browse the diagram using the Eclipse 'Outline view'.
  • + +
    + +
  • Search Diagram: + This feature allows to quickly search the sequence digram for a class or method + or database table. Partial names can be entered. Use * as a wild card. Wild card(*) + is automatically added at the beginning and end of the search string. Wild card + can be used in the middle of a string. To search BeanProxyFilter use search + string bean*filter. When 'Table' is the search criteria, the entire SQL statement + is searched for. So, this can be used to search for database tables, fields and + runtime parameters too. +  
  • + +
    +
  • Call Response Time: + Sequence diagram shows the response time for each call in milliseconds. + You can see the response time beside the method call in parentheses. If you + want to use the sequence diagram for finding the calls that are taking the + maximum response time, use the 'Switch to Response Time View' feature + described below. +  
  • +
    + +
  • Switch to Response Time View: + When this option is clicked, the sequence diagram and the 'Outline view' are + refreshed to present them in a way to help you to quickly find the maximum time taking methods. + In the sequence diagram, the response time is shown at the beginning of method + name label. Usually the first level calls displayed when the diagram is + opened take the maximum amount of time. User can drill down into the calls of + interest to identify the calls that can be improved for a better response time. + The 'Outline view' by default sorts the calls by response time in descending order. + There may be some methods + that are repeatedly called in a use case. Optimizing such methods could improve + response time of the use case. In the 'Outline view', use the menu option + 'Sort Calls by Aggregate Response Time' to sort the calls by the aggregate + response time. The Outline view also shows the total number of times a method + is called in the use case. +  
  • +
    +
  • Switch to Normal View: + Use this option to switch back to the regular view from the Response Time view.
  • +
    +
  • Filter Calls By Response Time: + This feature allows you to filter out all the calls whose response time is less + than the specified time.
  • +
    + +
  • Delete All Classes Except: + Use this feature to quickly delete all classes from the diagram except the + ones that are important to you. You can specify multiple class names separated + by comma and using * as a wild card. For example, to delete all classes + except the 'Controller' and 'DAO' classes, enter the filter string as + '*controller,*dao*'. The class names are case insensitive and you don't need + to specify the package names. The above filter string will show how the Controller + classes in the use case are calling the DAO classes.
  • +
    +
  • Delete getter/setter Calls: + Often the simple get() and set() methods clutter the diagram. You can delete all + of them in one go using this action.
  • +
    +
  • Delete Constructor Calls: + You can delete all the constructor calls using this option. +
  • +
    + + + +
  • Keyboard Navigation: + Sequence diagram can be navigated using keyboard keys. Up and Down + arrow keys move focus to previous and next method calls. Left arrow + collapses an expanded call and right + arrow expands a collapsed call. Delete button deletes a call.
  • +
    +
  • Show Activations: Clicking this option + draws an activation box for the duration a method is active.
  • +
    + +
  • Show Thread Information: + MaintainJ generates one trace file for each active thread while tracing is + turned on. These trace files can be merged using Merge Trace Files wizard + (at File->New->Other->MaintainJ->Merge Trace Files) to view them in a + single sequence diagram. Clicking 'Show Thread Information' displays each + thread in a different color. The thread name is also displayed before the + method name. You can also merge trace files generated in different JVMs for a + single use case and see different threads in different colors. + +
  • + + +
    + +
  • No Loop or Recursive Calls: + If the same method is repeatedly called in a loop, only the first call is shown + to avoid cluttered diagrams. Similarly, the recursive calls are also shown only once. + But, the number of times the same method is called is displayed beside the method name. + A loop icon is also displayed before the call label to highlight the fact that + it is a loop or recursive call.
  • + +
    +
  • No Immediate Return Calls: Immediate + return calls are deleted to avoid diagram clutter.
  • +
    + +
  • Web Sequence Diagrams: Use + this option to export the current diagram as a web sequence diagram + rendered by websequencediagrams.com. The call trace information is exported as + a HTML file and a web service call to websequencediagrams.com displays the + sequence diagram in a browser. +
    + Security Note:This feature is disabled by default because of security concerns. + By default, the call trace information in the sequence diagram is passed over the + internet to the websequencediagrams.com web site to generate the diagram displayed + in the browser. You will have to purchase the license from them to install the diagram + rendering web service in your company. You can enable this feature + by changing the 'EnableWebSequenceDiagrams' property to 'true' + in plugins/com.maintainj.umlDiagram_x.x.x/DiagramConfiguration.properties file. + After you have the diagram rendering web service installed in your intranet, + you can change the url by changing the 'WSDLastLine' property in the same file.
  • + +
+ +
+

4.2 Class Diagram Features

+

The class diagram is a class dependency + diagram that shows the dependencies between + the classes involved based on the call sequence.

+
    +
  • Show Class Hierarchy: + To view the hierarchy of a class, select a class, right click and + choose 'Show Class Hierarchy'. For this feature to work, the + hierarchy classes should be available in workspace when the diagram + was opened.
  • +
    +
  • Classes can be resized and rearranged: + Classes can be resized if a long class name is not fully displayed in the + box. Classes can be rearranged to make the diagram + more readable. Class relations can be bent by selecting a relation + and dragging the centre point.
  • +
    +
  • Shows class fields and methods in tool tip: + When you hover the mouse over a class, the class fields and methods are + shown in the tool tip. For this feature to work, the class file should + be present in the workspace either as a source file or .class file. +
  • +
+ +
+

4.3 Common Features in both Class and Sequence Diagrams

+The following features are available to both + class and sequence diagrams.

+
    +
  • Both diagrams are in sync: + The class diagram always shows the classes currently shown + in the sequence diagram. If a class is deleted from sequence diagram, + the same class is deleted from class diagram and vice versa.
  • +
    +
  • Runtime Classes: All + classes shown in the diagram are concrete runtime classes. No + abstract base classes or interfaces are shown.
  • +
    +
  • + Save and Save As: Trace + files are initially saved as *.ser files. These files + hold the original call trace of the use case. The changes done to the + diagram generated from a *.ser file cannot be saved back to the *.ser + file. The changes have to + be saved to a *.mnj file, which can also be opened in MaintainJ editor. + Choose 'File-->Save As' to save the + diagram to a file with extension *.mnj. You can change the diagram generated from + *.mnj + file and save the changes back to the same file.
  • +
    +
  • Delete: Calls and classes + can be deleted with Delete key or 'Delete' option in the context menu. + When a collapsed call is deleted, all hidden enclosed calls are deleted too. + When an expanded call is deleted, only that call is deleted. When a class is + deleted, all calls to that class and calls going out from that class are + deleted. You might want to delete classes that do not make any further calls + (like Value Objects with only get/set methods). You might also delete classes + that you want to ignore for now, though they make further calls. + You can 'Undo' all the delete operations.
  • +
    + +
  • Outline View: Eclipse 'Outline + View' lists all undeleted classes and calls whether they + are shown or hidden in the diagram. You can right click a class/call + and choose 'Select In Diagram' to select the corresponding figure. + If the corresponding figure is not currently displayed, the sequence + diagram will expanded minimally to open the breadcrumb trail of the + selected call or class. Outline View serves two important + purposes.
    + i) For a large diagram, it gives an overview of all packages, + classes and calls in the diagram without expanding all the calls in the diagram.
    + ii) It helps to filter out unwanted packages/classes/calls without having to + expand the calls to show those classes/calls. You can select all + unwanted packages/classes/calls and delete them in one go. +
  • +
    + + +
  • Exclude Class: + This feature allows you to delete a class without deleting the calls + this class is making on other classes (Deleting a class deletes all + calls from and to that class). + Assume you have 3 classes - MyServlet, SessionFacade and MyDAO. Typically, in a + J2EE application all calls to the DAO's are routed through a facade class + (MyServlet calls SessionFacade, which in turn calls MyDAO). + If you exclude the SessionFacade class from the diagram, this is what happens:
    + a) SessionFacade class is deleted from the diagram
    + b) The calls from SessionFacade to MyDAO are rearranged to show as if + MyServlet is calling MyDAO directly.

    + This behavior is same as what happens when a class is excluded from the instrumentation + scope in aop.xml. This feature is useful when you want to capture all calls + in the trace file, but would like to exclude some class(es) or package(s) from + the diagram. From the 'Outline View', you can select class(es) or package(s) and + exclude all of them in one go. +
  • +
    + +
  • Predefined filters: + Demo
    + Using the + predefined filters, you can filter out the unwanted details from the diagrams. The + filters are defined in simple properties file format. These files can be shared among + the developers. You can apply the filters defined in multiple filters files at the + same time. For example, there can be a global filters file where you might delete + all 'Logger' and such classes and another filters file that deletes all 'DAO' classes. +

    + + You can either hand code the filters files or let the tool create them for you. A sample + filters file (sampleFilters.filter) is created when you create the + 'MaintainJ Trace Files Project'. You can either edit this file or create new filter + files using this file as a sample. +

    + + Or you can create the filters files from the Outline view. In the Outline view context menu, + you will find two options: 'Create Delete Classes/Packages Filter' and + 'Create Exclude Classes/Packages Filter'. Select the packages and/or classes that you + want to delete or exclude and use one of the above menu options to create the filters + file. +

    + The 'Delete' filter deletes all the calls to and from a class. When you add a package + to the 'delete filter', all classes under that package will be deleted. +

    + The 'Exclude' filter deletes all the calls to the excluded class, but retains the calls + that the excluded class is making. This behavior is same as the 'Exclude Class' feature + described above. +

    + To apply the filters to the diagram, use the context menu 'Apply Predefined Filters'. + This will prompt you to select one or more predefined filters files, which will be + applied to the diagram. The 'delete' filters can be undone whereas the the + 'exclude' filters cannot be undone. To undo the exclude filters, do not save the + diagram after the exclude filters are applied. +

    + Note: Because of a bug in the current implementation, the filter files must be + present in the root folder of the Trace Files Project. +
  • +
    + +
  • Tooltips: Tooltips + for a class show the complete class name. Tooltips for a method call show + the values of parameters and return value if call context data was captured. + Method call tooltips always show the response time of the call and where + this method is declared. If a method is defined in the superclass + and is called on the subclass instance, the tooltip shows the superclass name.
  • +
    + +
  • Print: + 'Print' option prints the active diagram.
  • +
    + +
  • Export As  JPG/BMP Image: This + option is used to export the diagram as a jpg or bmp image. Large images + take lot of system resources and cannot be exported. Use the filtering + features to delete unimportant classes and calls. Try to reduce the + diagram to about 400 calls before exporting as a diagram. BMP images + take greater resources than a jpg image.
  • +
    + +
  • Double click to open source file: + Double clicking a call opens the source file where this + call is defined. All Java projects in workspace are searched for the + source file and the file is opened with the corresponding line is + selected. Double clicking a Class figure opens the class file.
  • +
+ + +
+

4.4 To Perform Impact Analysis

+

+Demo +

+After changing the application to fix a defect or to add a new feature, you may want to +find all the existing use cases impacted by the change. It is necessary to find the +impacted use cases, so that proper regression testing can be conducted before +the new code is put into production. Static time source code searching does not +enable us to determine the use cases that depend on a class or database table. + +

The 'MaintainJ Search' feature allows you find out all the use cases that +depend on a Java class or method or on a database table or field. + +

Click the menu option 'Search' (Control+H) in Eclipse. In the search dialog box +opened, you will notice a 'MaintainJ Search' tab, where you can search for a +trace file or class or a method across multiple trace file projects. +This gets even better by allowing you to search for a particular method parameter value. +Let us explain these powerful capabilities using two concrete examples. + +

+1. Java class or method search: Consider the simple code snippet below, +a very common pattern used in Java applications. +

+interface DataSource{
+    String loadData();
+} +

+class FileDataSource implements DataSource{
+     String loadData(){
+         //Read from file and return the data
+     }
+}
+

+class NetworkDataSource implements DataSource{
+     String loadData(){
+         //Read from network and return the data
+     }
+}
+

+class DataLoader{
+     private DataSource dataSource;

+ +     DataLoader(DataSource ds){
+         dataSource=ds;
+     }

+ +     String loadData(){
+         return dataSource.loadData();
+     }
+} +

+By analyzing the source code above, it is impossible to tell whether DataLoader +uses FileDataSource or NetworkDataSource at runtime when a use case is executed. +Using the static time source code analysis tools, it is impossible to +precisely tell if a use case depends on FileDataSource or NetworkDataSource. +

+Because MaintainJ captures the classes, method calls and their parameters +as the use cases are executed, it can precisely identify whether a use case +calls FileDataSource or NetworkDataSource. +

+Once the trace files are captured for all use cases in the application, +you simply need to search for FileDataSource to find out all the use cases +that depend on it. Armed with this information, you can conduct +focused and comprehensive regression testing and put the code +back into production with more confidence. + +

+ +2. SQL Search: Most Java applications use databases. Consider that we +need to identify all the test cases impacted by a change to a table structure. +This is not an easy task in an enterprise setting where many applications +depend on the same database. There are many database frameworks for Java +and each of them embeds the SQL differently in XML or source code or both. +For code analysis tools, it is difficult to map a Java class to a +SQL statement and impossible to map a use case to a set of tables used. +

+Because MaintainJ captures all the runtime SQL statements sent to database +when a use case is executed, it can precisely identify the use cases that +depend on a database table(s) or field(s). +

+To find all the use cases that use a table, use the following search criteria +in the 'MaintainJ Search' tab:

+Class name: '*Statement' (searches both Statement and PreparedStatement)
+Method name: 'execute*'
+Method parameter name: 'sqlStatment'
+Method parameter value: <<Table name or field name as referred to in the SQL>> + +

+The search results show all the use cases that depend on the table/field and +show the SQL statements using those tables/fields. + +

A Powerful Feature

+ +

This is a very powerful feature that no available static time dependency analysis +tools can offer. However, take note of the assumption and current limitations +of the feature: +

The assumption is that you have already captured the trace files for all use cases of +the application. If this is a considerable effort during a release cycle, it can be +started on more important modules of the application and expanded to other modules later. +

+The limitations are:
+a) Assume that class ConcreteUser extends AbstractUser. If you change AbstractUser, +there is a chance that use cases depending on ConcreteUser will be impacted though +you did not change ConcreteUser. +In the current release users will have to use their discretion when analyzing +the impact of changes to classes in a class hierarchy.
+b) Only the impact of changes to Java classes, JSP's and database resources +can be identified currently. Impact of changes to HTML, CSS or Javascript cannot be +predicted.
+ +

+ + +
+

4.5 Export the Diagrams to UML2 (and import into UML compliant tools like RSA)

+ +

+Demo +

+You can export the MaintainJ sequence and class diagrams into UML2 model files +and then import those model files into other UML2 compliant tools like +Rational Software Architect(RSA) 8. Using these model files, RSA can display the +sequence and class diagrams.

+ +If the generated trace files are large, you can apply filters on the diagrams or +delete the unwanted packages/classes/methods from the 'Outline view' and save +the diagram as .mnj file. Open the .mnj file using the +'MaintainJ Editor to Save As UML2 Model' editor (select the .mnj file and right +click to see this editor in the context menu). When you click 'Save As' (File->Save As), +you will be prompted to enter the model file name. The UML2 model file will be saved in +the same folder as the .mnj file. +

+You can choose if you want to export all class attributes, methods and/or class +hierarchy of the classes called in the sequence diagram. The source code of the +called classes must be in the workspace to export attributes/methods/hierarchy +to the UML2 model. By default only the methods called in a class are exported. +

+The classes and calls currently +visible in the diagram will only be exported to the model file. In other words, if a call +is collapsed, just that call will be exported into the model file and none of the +nested calls will be exported.

+ +If you are going to import the model files into RSA, name the model files as .emx files. +You have two options to view the class and sequence diagrams in RSA. +

+1. Install the 'MaintainJ UML2 Diagram Creator For RSA' plug-in (download link provided below). +Copy the .emx file to any +project and from any view like the Navigator view where you can see the file +name with the .emx extension, right click the mouse. In the context menu, +you will find 'Create MaintainJ UML2 Diagrams' option. +When you click this option, the sequence and class diagrams will be opened in RSA. +

+2. You do not really need the above MaintainJ plug-in to generate the UML diagrams +from the UML2 model file in RSA. Copy the .emx files into any project in RSA, open +the 'Modeling perspective' and then open the .emx file using the 'Rational Model Editor'. +

+To open the model file as a sequence diagram, expand the model (in Model perspective, +Project Explorer view) and follow 'Collaboration -> Interaction -> Right click +the mouse ->Add Diagram->Sequence Diagram'.
+To create the class diagram, expand the model, select all domain classes (or the classes +you want to include in the class diagram), right click the mouse and follow +'Add to New Diagram File ->Class Diagram'. +

+ +Note when viewing the diagrams in RSA: Sequence diagrams with more than 50 calls +take some time to open in RSA. Because it really depends on your computer's +processing power, start with less number of calls and increase the diagram size +depending on how it scales. You may use the 'predefined filters' to reduce the +MaintainJ diagram size by removing redundant calls. +

+Installation Links and Notes:
+The feature to export the diagrams as UML2 model files is implemented in a separate +Eclipse plug-in called 'MaintainJ UML2 Model Creator', which is not packaged in the +core 'MaintainJ Feature'. So, you need to install this +plug-in separately. Below are relevant url's to install this plugin. +

+Eclipse Update url: http://maintainj.com/updates/4.0.0/uml2 +
+Zip file: MaintainJ_UML2_Converter_4.0.0.zip +The zip file contents should be placed in the 'eclipse/plugins' folder. +

+To install the 'MaintainJ UML2 Diagram Creator For RSA' plug-in (to follow the first +approach above to view the diagrams in RSA), download +MaintainJ_UML2_Diagram_Creator_4.0.0.zip +file and unzip to 'eclipse/plugins' folder. Please note that this plug-in works only in RSA. +

+This feature is tested in Eclipse 3.5 and above, RSA 8 and RAD 7.5 and above. +When installing in RSA or RAD, you can use either the 'update url' or the zip file. +But when installing in Eclipse, use the update url because Eclipse would automatically +fetch and install the other plug-ins that this plug-in depends on. If you cannot +use the update url, make sure that you have both 'UML2 Extender SDK' and +'EMF Model Transaction SDK' plug-ins installed before installing this plug-in. +In RSA and RAD these 2 plug-ins are pre-installed. +

+ +License Note: This feature is not included in the current licensing. Please contact us to +use this feature on your application. However, you can try this feature using the +sample trace file copied to the 'MaintainJ Trace Files Project'. + +
+

+ + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/faq.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/faq.html new file mode 100644 index 0000000..bad1886 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/faq.html @@ -0,0 +1,279 @@ + + +

6. Frequently Asked Questions

+ + +1. Do I need Eclipse to use MaintainJ? +

2. How does MaintainJ scale? +

3. I get a ClassNotfoundException for com.maintainj.inst.J2EEAspect. Where is that class? +

4. Trace file is not generated +

5. Where is the aop.xml file (the trace configuration file)? How can I edit it? +

6. I do not see the UML diagrams when I open the trace file +

7. My diagrams are too big and cluttered. How can I filter out the unnecessary classes and calls? +

8. I get java.lang.OutOfMemoryError:PermGen space +

9. Can I import the diagrams into Rational tools like RAD or RSA? +

10. How can I use MaintainJ for documentation and share the MaintainJ diagrams with others? +

11. What are the license terms? + +
+ +

+

+

+ + + +

1. Do I need Eclipse to use MaintainJ?

+

MaintainJ needs Eclipse to view the diagrams. As Eclipse and GEF (API used to render the diagrams) +are open source projects, you can use them for free.

+ +

You don't need Eclipse to generate the trace files. While some wizards are provided in +Eclipse to generate the trace files, one can do the same outside Eclipse. + +

For example, MaintainJ.war can be used outside Eclipse to generate the trace files +for J2EE applications. You can also follow these +steps to manually +generate the trace files. + +

+ +

2. How does MaintainJ scale?

+

+ MaintainJ scales very well for large scale applications. Large applications can + potentially slow down MaintainJ at two stages : a) during instrumentation and + b) during diagram rendering.  +

Instrumented applications take longer time to service the first +request. Just like JSPs that get compiled at the first request, the classes get +runtime instrumented at the first request. For subsequent  requests, there +is little overhead. Capturing call context also adds some overhead.

+ +

Rendering the diagram is typically very quick and does not take much memory. +As loop calls and return calls are not logged to the trace files, number of +calls to render are kept low. That said, users should limit the trace file +to a single user action to make the diagrams focused and easier to understand. +Also, avoid using 'Expand All' to expand all calls in the diagram as a large +diagram of 5,000+ calls will make navigating the diagram slow. You should either +explore the diagram or use the 'Select In Diagram' feature in Outline view to +open the call trail to a particular call. +

+

+ +3. I get a ClassNotfoundException for com.maintainj.inst.J2EEAspect. Where is that class?

+ +

com.maintainj.inst.J2EEAspect is not a class file. It is specified in META-INF/aop.xml. +The aop.xml file is generated in 'Step 2' of MaintainJ.war installation (or if the Tomcat/JBoss +servers are started using MaintainJ J2EE Server plug-in, the aop.xml file is generated +when the server is started). The J2EEAspect class is generated at runtime by AspectJ. +For this to work, the META-INF/aop.xml should be in application server classpath. +For example, if the path of aop.xml is c:\maintainj\META-INF\aop.xml, c:\maintainj +should be added to the classpath. +

+META-INF/aop.xml is automatically added to the server classpath in the MaintainJ generated +startup scripts. However, if you are seeing the ClassNotfoundException, there may be a +problem with your server classpath. Check the classpath setting with which your +server was started.

+ +

+4. Trace file is not generated

+

The use case that you ran may not have called any of the instrumented +classes. If this is not the case, ensure that the instrumentation scope is +properly defined. + +

+5. Where is the aop.xml file (the trace configuration file)? How can I edit it?

+

+The details like the Java packages that you want to capture, whether you want to capture +the call context, etc. are stored in aop.xml file. This is a special file used by +AspectJ Load Time Weaving mechanism that is used to capture the call trace. +This file is always created under META-INF folder and META-INF/aop.xml should +be added to the JVM classpath. The out of the box MaintainJ wizards +create this file for you and add it to the JVM classpath. + +

5.1 Where is the aop.xml file located? +

Different MaintainJ wizards place this file under different folders. + +
a) The J2SE, JUnit, Applet applications launched from Eclipse using the +MaintainJ run configurations create a 'maintainj' folder under the main project and +place META-INF/aop.xml under that folder.
+b) The MaintainJ J2EE Server plugin for Tomcat and JBoss puts the file under +<TomcatRoot>/maintainj and <JBossRoot>/bin/maintainj folders respectively.
+c) The MaintainJ.war shows the location of this file after Step 2: Configure Instrumentation Scope.
+d) The MaintainJSwingWizard.jar also shows the location of this file after the second step. + +

5.2 How can I edit the aop.xml file? +

You may edit it manually to define more fine-grained configuration. +Change the weaver options section to include or +exclude more packages. There can be any number of includes or excludes. This +sample below includes all classes and sub-packages under +org.jfree.chart and excludes sub-packages and classes under +org.jfree.chart.ui package. +It also excludes org.jfree.chart.JFreeChart +class. Note the difference in syntax when excluding a class.

+ + +

<weaver options="-proceedOnError -nowarn -XaddSerialVersionUID">
+    <include within="org.jfree.chart..*"/>
+ +    <exclude within="org.jfree.chart.ui..*"/>
+    <exclude within="org.jfree.chart.JFreeChart"/>

+</weaver>

+ +

5.3 After editing the file make sure that it is not overwritten by the wizards +

If you are using any of the Eclipse launch configurations, the aop.xml is +regenerated every time the application or server is launched. Select the +'Do not regenerate aop.xml' checkbox at the bottom of the +MaintainJ tab to not overwrite your changes. If you are using MaintainJ.war +or MaintainJSwingWizard.jar, the aop.xml is regenerated only if you +repeat Step 2 to configure the instrumentation scope. + +

+6. I do not see the UML diagrams when I open the trace file

+

The MaintainJ UML Diagram Editor plug-in is not installed properly. If it is +installed correctly, you should see MaintainJ icon + beside the trace file +in Eclipse.  + + + +

+7. My diagrams are too big and cluttered. How can I filter out the unnecessary classes and calls?

+

MaintainJ offers two options to +get focused diagrams by removing the unimportant calls that clutter the diagrams. +The first option is not capturing unimportant calls while tracing the application. +The second option is to remove the unimportant calls from the diagram +after the diagram is rendered.

+

7.1 Do not capture the unimportant calls

+

MaintainJ has a number of options to follow this +approach. 

+

7.1.1 MaintainJ automatically removes all +repeating calls in a loop except the first call. If a method is called 100 times +in a loop, only the first call is shown in the diagram. Recursive calls are also +removed in a similar manner.

+

7.1.2 You can limit the packages and projects +that will be instrumented. As only the instrumented classes and methods are +logged to the trace file, this is another way to avoid unwanted packages or +projects from the diagrams.

+ + +

7.1.3 You can also limit the scope of instrumentation at a finer level by +editing the generated META-INF/aop.xml file. Check the above +faq entry +'Where is the aop.xml file (the trace configuration file)? How can I edit it?' +for details. +

+ +

7.2 To remove unnecessary calls from the +diagrams

Besides loop and recursive +calls, there may be number of calls that just clutter the sequence diagram and +add little to our understanding. Often, it is hard to know such unnecessary +calls before hand. MaintainJ UML Editor plug-in offers a number of options to +remove them from diagrams. + +

+7.2.1 Predefined Filters +is the first thing you should check to filter out unwanted details from the +diagrams. +

+ +

7.2.2 You can simply delete the unnecessary classes or packages (from Outline view). +The deleted class and all the calls to and from that class will be deleted. +

+ +

+7.2.3 Excluding a class +or classes is another great way to get focused diagrams. +

+ +

+7.2.4 You can also use the Outline view to select and delete +multiple packages, classes or calls at once. +

+ +

+7.2.5 You can use 'Delete getter/setter Calls' in the +sequence diagram to delete the simple get/set method calls. +

+ +

+7.2.6 You can use 'Delete Constructor Calls' in the +sequence diagram to delete all constructor calls. +

+ +

+7.2.7 +There can be a method in a particular class that is called multiple times in the +sequence diagram but adds little to our understanding. To remove all repeating +calls except the selected call, select a call in the Outline view and +choose Delete Duplicate Calls to this Method. This can be used to remove +all unnecessary get/set methods, repeating calls to boolean equals(Object obj) method, etc.

+ + + + +

7.3 +Use 'Save As' feature to split the diagrams

+When the trace file is opened, all calls are +initially collapsed into a few top level calls. If you delete a top level call, +it will delete all the calls inside that call as well. Then, the 'Save As' +feature can be used to save the smaller diagram. This way a trace file of 5000 +calls can be split into two trace files of 2000 and 3000 calls, for example. + +

+8. I get java.lang.OutOfMemoryError:PermGen space

+

MaintainJ changes the instrumented class files while they are loaded into the memory. +If you are instrumenting thousands of classes, the default memory size allocated for +class definition may not be sufficient. You need to add '-XX:MaxPermSize=256m' +to the JVM arguments to set the maximum memory available for class definition to 256MB. +You may search the web to find more about this error.

+ +

+9. Can I import the diagrams into Rational tools like RAD and RSA?

+

Yes, you can starting from MaintainJ V3.5! MaintainJ generated diagrams +can be exported as UML2 models. These models can be imported into any UML2 +compliant tools like RSA to view the UML2 class and sequence diagrams. + +

+ + +

+ +10. How can I use MaintainJ for documentation and share +the MaintainJ diagrams with others?

+

+You can use MaintainJ for documenting and sharing the application knowledge with your team members.

+1. You can export the sequence and class diagrams as bmp or jpg images after +filtering out the unimportant calls in the diagram. You can also export the +diagrams as UML2 models and import into UML2 compliant tools like RSA.
+2. After filtering out the unimportant calls, you can save the original .ser files +as .mnj files and open them in the same exact state they were in when the +diagrams were saved. To share the mnj files with others, you need to provide the +entire MaintainJ Trace Files project that contains the ser and mnj files.p +

+ + +

+11. What are the license terms?

+

MaintainJ is a free to use software during the evaluation period. Once the +evaluation period ends, users need to buy the license to use MaintainJ. Read the complete +License Agreement.

+
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/filtersDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/filtersDemo.html new file mode 100644 index 0000000..ae93bd2 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/filtersDemo.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + +
+Download as PDF + + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/floatingLicense.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/floatingLicense.html new file mode 100644 index 0000000..022b175 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/floatingLicense.html @@ -0,0 +1,36 @@ + + +

Instructions to obtain and install floating +license

+

+ +

1. Download +FloatingServer.jar
+2. Copy the file to the computer where you intend to run MaintainJ floating license +server. This computer should be accessible to the computers running MaintainJ +Eclipse plug-in. Please choose the server computer carefully because the license +will be locked to this computer (more precisely, to its host name).
+3. Run java -jar FloatingServer.jar -HostKey . This will generate the +License Server Host Key and print to console.
+4. Go to +download +license page. Enter the MaintainJ Key you received earlier and Host Key and +click 'Download License'. You can save the license file to your computer. The +license is emailed to you as well.
+5. Type java -jar FloatingServer.jar 7773 <<AbsolutePathToLicenseFile>> to start the server. 7773 is +the port number, which you may change. Provide the absolute path to the license.lic file as the second argument. (Ex: c:\maintainj\license.lic)
+6. The license server starts with the following messages to console:
+MaintainJ floating license server starting on port:7773
+Number of licenses allowed: <<Number of Licenses Purchased>>
+7. Enter the license server name and port number in Eclipse following +File->New->Other->MaintainJ->Get License->License Server Settings. +Repeat this on each computer using MaintainJ plug-in.
+

+ +

+ +


+
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/EclipseAwardsLogo.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/EclipseAwardsLogo.png new file mode 100644 index 0000000..37b2182 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/EclipseAwardsLogo.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/about-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/about-off.gif new file mode 100644 index 0000000..c29f8bf Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/about-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/about-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/about-on.gif new file mode 100644 index 0000000..99c4d5d Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/about-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/around_advice.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/around_advice.gif new file mode 100644 index 0000000..e13ad57 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/around_advice.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow.gif new file mode 100644 index 0000000..df8b6c2 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow1.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow1.gif new file mode 100644 index 0000000..23466d2 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow1.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow2.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow2.gif new file mode 100644 index 0000000..e51b117 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/arrow2.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg.jpg new file mode 100644 index 0000000..7e78bf3 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottom.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottom.gif new file mode 100644 index 0000000..3cd895c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottom.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottomleft.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottomleft.gif new file mode 100644 index 0000000..26a59b1 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottomleft.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottomright.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottomright.gif new file mode 100644 index 0000000..16eace5 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_bottomright.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_left.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_left.gif new file mode 100644 index 0000000..ac19f17 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_left.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_right.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_right.gif new file mode 100644 index 0000000..a9e2f41 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_right.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_top.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_top.gif new file mode 100644 index 0000000..74b673d Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_top.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_topleft.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_topleft.gif new file mode 100644 index 0000000..f1aef27 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_topleft.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_topright.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_topright.gif new file mode 100644 index 0000000..a1fe29b Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/bg_topright.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/big-arrow1.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/big-arrow1.gif new file mode 100644 index 0000000..23b7f28 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/big-arrow1.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/box-bg.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/box-bg.jpg new file mode 100644 index 0000000..c4edcdc Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/box-bg.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/buy-licence.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/buy-licence.gif new file mode 100644 index 0000000..baafa82 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/buy-licence.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/collapsed.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/collapsed.gif new file mode 100644 index 0000000..252d7eb Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/collapsed.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/contact-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/contact-off.gif new file mode 100644 index 0000000..87c1315 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/contact-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/contact-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/contact-on.gif new file mode 100644 index 0000000..a0f7a0c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/contact-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demo.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demo.jpg new file mode 100644 index 0000000..57981ec Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demo.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demoVideo1.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demoVideo1.jpg new file mode 100644 index 0000000..11ac8b1 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demoVideo1.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demos-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demos-off.gif new file mode 100644 index 0000000..b32c4f9 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demos-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demos-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demos-on.gif new file mode 100644 index 0000000..7af32ca Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/demos-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/dot.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/dot.gif new file mode 100644 index 0000000..4b38a59 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/dot.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/download.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/download.gif new file mode 100644 index 0000000..d9afcc9 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/download.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/expanded.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/expanded.gif new file mode 100644 index 0000000..ae09139 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/expanded.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/fl1.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/fl1.png new file mode 100644 index 0000000..d22e116 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/fl1.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/fl2.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/fl2.png new file mode 100644 index 0000000..8cabaf0 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/fl2.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/home-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/home-off.gif new file mode 100644 index 0000000..cdb8030 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/home-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/home-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/home-on.gif new file mode 100644 index 0000000..b409b54 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/home-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/launchConfig1.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/launchConfig1.png new file mode 100644 index 0000000..ce3ffe1 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/launchConfig1.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/left-box.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/left-box.jpg new file mode 100644 index 0000000..311ddf0 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/left-box.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/licence-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/licence-off.gif new file mode 100644 index 0000000..2363d9c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/licence-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/licence-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/licence-on.gif new file mode 100644 index 0000000..828a259 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/licence-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/logo.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/logo.gif new file mode 100644 index 0000000..0443699 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/logo.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/methodProperties.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/methodProperties.png new file mode 100644 index 0000000..091f017 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/methodProperties.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/seqDiagWithData.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/seqDiagWithData.png new file mode 100644 index 0000000..de5fcff Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/seqDiagWithData.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/tooltipProperties.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/tooltipProperties.png new file mode 100644 index 0000000..f6cbe60 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/milestones/tooltipProperties.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj.gif new file mode 100644 index 0000000..3555eba Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj110By30.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj110By30.jpg new file mode 100644 index 0000000..adb0a43 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj110By30.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj4.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj4.gif new file mode 100644 index 0000000..e4cbace Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj4.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj4.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj4.jpg new file mode 100644 index 0000000..6547b52 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnj4.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnjIntro.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnjIntro.gif new file mode 100644 index 0000000..5c7b271 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnjIntro.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnjIntro.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnjIntro.png new file mode 100644 index 0000000..c8a64d4 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/mnjIntro.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/pixel.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/pixel.gif new file mode 100644 index 0000000..9935f82 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/pixel.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/readmore.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/readmore.gif new file mode 100644 index 0000000..83f9905 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/readmore.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/reguster.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/reguster.gif new file mode 100644 index 0000000..d015d14 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/reguster.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/reverse1.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/reverse1.gif new file mode 100644 index 0000000..6eda852 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/reverse1.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/right-box.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/right-box.jpg new file mode 100644 index 0000000..f9032cc Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/right-box.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/Thumbs.db b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/Thumbs.db new file mode 100644 index 0000000..804b8f0 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/Thumbs.db differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/j2seLauncher1.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/j2seLauncher1.png new file mode 100644 index 0000000..9b65902 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/j2seLauncher1.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/nodeManagerWindow.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/nodeManagerWindow.png new file mode 100644 index 0000000..f0bcd43 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/nodeManagerWindow.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeEclipse1.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeEclipse1.png new file mode 100644 index 0000000..17d55dc Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeEclipse1.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeEclipse2.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeEclipse2.png new file mode 100644 index 0000000..034416e Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeEclipse2.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeSwing1.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeSwing1.png new file mode 100644 index 0000000..2691f8f Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeSwing1.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeSwing2.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeSwing2.png new file mode 100644 index 0000000..b993af6 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/runtimeSwing2.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWindow.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWindow.png new file mode 100644 index 0000000..1be3b6d Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWindow.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWizard1.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWizard1.png new file mode 100644 index 0000000..2809b5c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWizard1.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWizard2.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWizard2.png new file mode 100644 index 0000000..9fa99e8 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime/swingWizard2.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime1.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime1.jpg new file mode 100644 index 0000000..1c8ee38 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime1.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime2.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime2.jpg new file mode 100644 index 0000000..c021fbf Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime2.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime3.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime3.jpg new file mode 100644 index 0000000..ce303c2 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime3.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime4.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime4.jpg new file mode 100644 index 0000000..0240594 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/runtime4.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/screenshot1.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/screenshot1.jpg new file mode 100644 index 0000000..0db4795 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/screenshot1.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/selectInstWizard.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/selectInstWizard.jpg new file mode 100644 index 0000000..59f7d92 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/selectInstWizard.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/send.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/send.gif new file mode 100644 index 0000000..e4fa248 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/send.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/sepa.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/sepa.jpg new file mode 100644 index 0000000..0713e51 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/sepa.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/spacer.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/spacer.gif new file mode 100644 index 0000000..35d42e8 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/spacer.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/star.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/star.gif new file mode 100644 index 0000000..9e49d7d Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/star.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/support-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/support-off.gif new file mode 100644 index 0000000..8fa0eab Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/support-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/support-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/support-on.gif new file mode 100644 index 0000000..1a2fbfc Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/support-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/swingStartStop.jpg b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/swingStartStop.jpg new file mode 100644 index 0000000..91580d2 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/swingStartStop.jpg differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/testimonials-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/testimonials-off.gif new file mode 100644 index 0000000..ac62815 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/testimonials-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/testimonials-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/testimonials-on.gif new file mode 100644 index 0000000..733eb46 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/testimonials-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/try-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/try-off.gif new file mode 100644 index 0000000..3f01229 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/try-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/try-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/try-on.gif new file mode 100644 index 0000000..b1d1139 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/try-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/twister.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/twister.png new file mode 100644 index 0000000..1a8ffe5 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/twister.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/user-off.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/user-off.gif new file mode 100644 index 0000000..994b6c9 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/user-off.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/user-on.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/user-on.gif new file mode 100644 index 0000000..261d7ed Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/user-on.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/vote-us.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/vote-us.gif new file mode 100644 index 0000000..400b2a7 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/images/vote-us.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/impactAnalysisDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/impactAnalysisDemo.html new file mode 100644 index 0000000..cfa5429 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/impactAnalysisDemo.html @@ -0,0 +1,14 @@ + + +
+ + + + + + + +
+Download as PDF + + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/index.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/index.html new file mode 100644 index 0000000..daf3c36 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/index.html @@ -0,0 +1,425 @@ + + + +MaintainJ - Reverse Engineer Java Like Never Before + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + + + + +
MaintainJProduct Downloads:
+ 117,600
+
+ + + + + + + + + + +
HomeDemosdownload.htmlUser GuideSupportTestimonialsBuy LicenseAbout Us
+ + + + + + +
+ + + + + + + + + + + + + + + + + +
  
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Reverse Engineer Java Like Never Before
MaintainJ is the tool to + turn to when you want to:
MaintainJ + Find out what exactly happens when you run a use case +
+ Generate interactive sequence diagram from call trace +
+ Reduce the bug fix and release cycle time of your applications +
MaintainJ + Document your applications in minutes + + Read More...
 
+ Download
+ + View Demo +
+
+ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Testimonials
+ + + Awesome Tool : This tool came as a blessing!! It + gives immense pleasure to see the sequence diagram for a + use case at click of a button... + + +
Satish Rao, EDS
+ + + A Must Tool To Have :  + ...creates sequence and class + diagrams at runtime. Makes debugging really easy... + + +
Nasser Alizadeh,  Ericsson
MaintainJ
  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Latest News
+ + + +
+
  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Clients
+ + + Governments : + USA, + Canada, + Australia + + + +
+
+
+
+ + + Corporations : + IBM, + HP, + Verizon, + VMware, + Infosys, + Informatica, + Cisco, + Wells Fargo, + Disney, + T-Systems, + British Telecom, + GE, + eBay, + HCL, + Digital River, + TietoEnator, + SAIC, + QFS, + Verient, + FIS, + Nimbus, + Ross, + Logica, + Booz Allen, + TracFone, + Newpark, + Cash Edge, + Confirma, + Zinc, + CCL + and many more... + + +
+
+
+ + + Universities : + Texas A & M, + University of Southern Denmark + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/installWizard.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/installWizard.html new file mode 100644 index 0000000..decc0e0 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/installWizard.html @@ -0,0 +1,196 @@ + + + + + + + + + +The following wizard will present the download links and demo video relevant to your application.

+What is the type of your application?   + J2EE + J2SE +Applet +JUnit +Eclipse Plug-in +None of these + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2eeLauncherDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2eeLauncherDemo.html new file mode 100644 index 0000000..2ea51d0 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2eeLauncherDemo.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2eeRuntimeDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2eeRuntimeDemo.html new file mode 100644 index 0000000..d7bc7a7 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2eeRuntimeDemo.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + + +
+ + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2seRuntimeDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2seRuntimeDemo.html new file mode 100644 index 0000000..1e41eb1 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/j2seRuntimeDemo.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/junitRuntimeDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/junitRuntimeDemo.html new file mode 100644 index 0000000..d5c71a8 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/junitRuntimeDemo.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/license.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/license.html new file mode 100644 index 0000000..98357b0 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/license.html @@ -0,0 +1,75 @@ + + +

License Agreement

+

+ +

PLEASE READ THIS LICENSE CAREFULLY BEFORE USING OR EVALUATING +THE SOFTWARE. USING THE SOFTWARE SHALL INDICATE YOUR ACCEPTANCE +OF THE TERMS AND CONDITIONS CONTAINED IN THIS AGREEMENT. IF YOU +DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT, DO +NOT DOWNLOAD, INSTALL, EVALUATE OR USE THE SOFTWARE.

+ +

This is a legal agreement between you, the end user, and MaintainJ +Inc. (the "Licensor"). MaintainJ set of Eclipse plug-ins (the +"Software") is owned by the Licensor and is protected by copyright +law. Upon acceptance of the terms of this License Agreement, +your rights and obligations with respect to use of the Software +are as follows. + +

+ +

Licensor grants you a non-exclusive right to use the Software. +Evaluators of the Software are granted the right to use it themselves +on one computer as long as the license is valid. License purchasers +are granted the right to use the Software on multiple computers as +long as the license is valid, but should ensure that the Software is +not used by other users. No other license is given unless explicitly +stated in the license agreement issued at the time of purchasing the license. +

+ +

You may not reverse engineer, decompile or disassemble the Software. Reverse +engineering third-party software may be illegal. The Licensor is not liable for +any damages arising from the evaluator or end user reverse engineering any +software using MaintainJ.

+ +

RUNTIME RIGHTS AND LIMITATIONS: You agree to indemnify, hold +harmless and defend the Licensor from and against any claims +or lawsuits, including attorneys' fees, that arise or result +from the use or distribution of the Software. + +

+ +

The Software is built using Eclipse and related plug-ins, which +are distributed under the following license. + +

+ +

Eclipse Public License (EPL) 1.0 available at +http://www.eclipse.org/legal/epl-v10.html

+ +

IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS OF THE +ABOVE LICENSES PRIOR TO USE OF THE SOFTWARE.

+ +

COPYRIGHT: The Software and Documentation are copyrighted by the Licensor and +are protected by Canadian and international copyright laws and treaties. The +product contains copyrighted software of the Licensor. All rights reserved.

+ +

IN NO EVENT SHALL THE LICENSOR BE LIABLE FOR ANY LOSS OF PROFIT OR ANY OTHER +DAMAGE, INCLUDING BUT NOT LIMITED TO SPECIAL, INCIDENTAL, CONSEQUENTIAL OR OTHER +DAMAGES. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. LICENSOR +SPECIFICALLY DISCLAIMS ALL OTHER WARRANTIES, EXPRESS OR IMPLIED, INCLUDING +WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A +PARTICULAR USE. LICENSOR DOES NOT WARRANT THAT THE SOFTWARE WILL MEET YOUR +REQUIREMENTS OR THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR +ERROR-FREE.

+ +

GOVERNING LAW: This Agreement shall be governed by and construed in accordance +with the laws of Canada. You agree not to use, ship, or export the Software in +violation of law.

+ +

ENTIRE AGREEMENT: You agree that this Agreement expresses the entire +understanding between you and the Licensor, and supersedes all other +communications, oral or written, relating to the Software.

+
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/maintainjnew3.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/maintainjnew3.html new file mode 100644 index 0000000..b5dc3e6 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/maintainjnew3.html @@ -0,0 +1,194 @@ + + + + +MaintainJ Inc. + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + +
Home  |  + Demos  |  + User Guide  |  + Downloads  |  + Forums  |  + Contact Us
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Eclipse Plug-in to generate sequence and class diagrams

+
+ MaintainJ, an Eclipse plug-in, generates sequence and class diagrams for + a use case, helping the users to quickly understand a complex Java or J2EE + application.

MaintainJ logs runtime method execution sequence to a + file and uses that trace file to render sequence and class diagrams. + MaintainJ Instrumentation Wizard instruments a Java/J2EE application and + MaintainJ UML Editor renders sequence and class diagram from the trace + file.

+

+ + The + following features make MaintainJ a unique and useful tool for Java + developers.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
Source Untouched
The application code is not changed in anyway; + application is rebuilt using AspectJ compiler to capture the method + execution sequence at runtime.
Collapsible Calls
Method calls in sequence diagram are collapsible. + Developers can easily explore a complex sequence diagram by + collapsing and expanding calls as necessary.
Focused Diagrams
Only application classes are shown in the diagrams + and API classes are filtered out. The classes in the diagram can + further be narrowed by instrumenting only the packages of interest. +
Runtime Diagrams
All classes shown in the diagrams are concrete + runtime classes.
No Loop Calls
All repeat calls occurring in a loop except the + first call are removed. Recursive calls also are removed.
Eclipse Integration
Double clicking a method call or class opens + matching method or class in Eclipse.
Outline Views
Outline views in both diagrams make navigating a + complex diagram simpler.
Print or Export
Diagrams can be printed or exported as JPEG + images.
+ +
+ + + + + + + +
Demo Videos

Screenshots
+
+
+ + + + + + + +
Copyright © 2007 MaintainJ Inc. Canada. All rights reserved.
+ + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/milestones.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/milestones.html new file mode 100644 index 0000000..922dd6c --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/milestones.html @@ -0,0 +1,187 @@ + + + + + +April 07, 2012 +

MaintainJ for Android applications

+ +

The current release version of MaintainJ does not work for Android applications. This is because MaintainJ instruments the class files as they are loaded into the memory, but the Android VM does not allow this.

+ +

To avoid this problem, the Android code needs to be instrumented at compile time rather than at load time. Following this method, MaintainJ can be used on Android apps to generate the runtime sequence and class diagrams.

+ +

The instructions work for the Android apps developed in Eclipse. I assume that you are already familiar with the Android application development in Eclipse and MaintainJ plugins are already installed in your Eclipse.

+ +

1. Install the correct version of AJDT from the AJDT download page.

+ +

2. In Eclipse, follow Window, Preferences, AspectJ Compiler, Possible Optimizations. Check 'No inline' option if it is not already selected.

+ +

3. Under your Android app project, create 'libs' folder if it is not already created. Copy MaintainJAspect.jar and aspectjrt.jar files to this folder. Get MaintainJAspect.jar from eclipse\plugins\com.maintainj.launcher.core_3.6.x . Get aspectjrt.jar from eclipse\plugins\org.aspectj.runtime_1.6.12.20110613132200

+ +

4.Take a backup of the .project file of your Android app project and do the following changes to add AspectJ builder to your project.
+Add the following node in buildSpec node.

+ +

+ + <buildCommand>
+ <name>org.eclipse.ajdt.core.ajbuilder</name>
+ <arguments></arguments>
+ </buildCommand>
+

+ +

Remove the following node if it is already present.

+ +

+<buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments></arguments>
+</buildCommand>
+

+ +

5. Add both libs/MaintainJAspect.jar and libs/aspectjrt.jar to the project classpath. +The steps to add the jars to classpath are, right click the project, Properties, Java Build Path, Libraries, Add Jars, select libs/MaintainJAspect.jar

+

After adding, your .classpath file should look like below:

+

6. In your Android app project, create package com.maintainj.androidaspect . Copy MaintainJTracer.aj to this package.

+

7. In the following line of MaintainJTracer.aj, change the com.msi to your package name.
+public pointcut anyExecution(): execution(* com.msi..*(..)) || execution(com.msi..*.new(..));

+

In the following line, change com.msi.manning.restaurant.RestaurantFinderApplication to your class name.
+public pointcut beforeMain(): execution(public void com.msi.manning.restaurant.RestaurantFinderApplication.onCreate());

+

8. Build the project and run it. It should run as it was running before the changes.
+9.Download MaintainJAndroidTraceManager.zip and import the project into your Eclipse workspace. Build and deply it to the emulator. This application helps you to start and stop tracing. You will see this app with the name 'MaintainJ Trace Controller'. When this app is launched, you should see 'Stop Tracing' button and a text box to enter the trace file name.
+10.Run a use case in your android application.

+

11. Go back to the 'MaintainJ Trace Controller' app, enter a trace file name like 'sampleTraceFile' and click 'Stop Tracing'. The trace file(s) will be written to sdcard/Download folder.

+

12. Pull the trace files from that folder into your Eclipse project created by following File, New, Project, MaintainJ, MaintainJ Trace Files Project.

+

13. Open the trace files to see the sequence and class diagrams.

+

14. You might use the sample app RestaurantFinder.zip to try this.

+ +
+ +

+September 07, 2010 +

MaintainJ V3.0 Beta

+ +

1. New features

+The major enhancement in this milestone is to show the context of each method call. It shows the method +call arguments, return value, source  instances of the call. These values are shown in the +properties view when the call is selected in the sequence diagram. +The values of basic data types like String, int are shown in tool tip when mouse +is hovered over a method call.

+ +The other change in this version is that the trace file must be placed in a +special project created by the wizard at +File->New->Project->MaintainJ->MaintainJ Trace File Project. This project +creates an embedded derby database to store the trace file information. Having +the trace file data in database serves two purposes. + +

+a) It reduces the memory usage as the entire trace file data need not be loaded +into memory. +
+b) It helps to search for a method or data like a specific value of a parameter. +This search can operate on a trace file or across trace files. The search +feature will be added in V3.1.

+There is no need to manually change the aop.xml as in the first milestone +release. + +

2. Screenshots

+When an invocation line is selected, in the Properties view, the method call arguments, return value, +source  instances of the call are displayed. +

+ +The values of basic data types like String, int are shown in tool tip when mouse +is hovered over a method call.

+ +  + + +

 

+ +

3.The download links

+

The installation procedure is same as it is for the release version. Check the +quick start guide for detailed installation instructions. +

+

MaintainJ Feature Update url for Eclipse 3.3 and above: http://www.maintainj.com/updates/3.0.1 +
MaintainJ Feature Update url for Eclipse 3.2: http://www.maintainj.com/updates/3.0.1/3.2 + +
MaintainJ J2EE Server Feature Update url: http://www.maintainj.com/updates/3.0.1/server +

MaintainJ Feature Zip (for Eclipse 3.3 and above): MaintainJ_3.0.1.zip +
MaintainJ Feature Zip (for Eclipse 3.2): MaintainJ_3.0.1_ForEclipse_3.2.zip + +
MaintainJ J2EE Server Feature: MaintainJ_J2EE_Launcher_3.0.1.zip +

MaintainJ.war to instrument J2EE applications: MaintainJ.war +

 


+

November 4, 2009 +

MaintainJ V3.0 Milestone 1

+ +

1. New features

+The major enhancement in this milestone is to show the context of each method call. It shows the method call arguments, return value, source and target instances of the call. These values are shown in the properties view when the call is selected in the sequence diagram. + +

2. Screenshot

+If the data is primitive, String or single dimension arrays of primitive or String, they are displayed. If the data is an object, only the first level primitive +attributes of that object are shown.

+ + +
+ +

3. How it works

+This version works the same as the release version in every other way except showing the context data. By default it does not log the context of a calls to the trace file. +You need to do a small change to the generated aop.xml to log context data. The location of the aop.xml can be found here. +Remember to select the 'Do not regerate aop.xml' checkbox at the bottom of the Aspect tab not to overwrite your changes.

+ +3.1 For J2SE applications or any application that you start with main() method, the third line in the generated aop.xml looks as below.
+<concrete-aspect name="com.maintainj.inst.J2SEAspect" extends="com.maintainj.aspect.J2SEExecutionAspect">

+You need to change the super aspect name to J2SEExecutionDataAspect as below.
+<concrete-aspect name="com.maintainj.inst.J2SEAspect" extends="com.maintainj.aspect.J2SEExecutionDataAspect">

+ +3.2 For J2EE applications,
+
1. Change the super aspect name from ExecutionAspect to ServletDataAspect
+2. Add -Xset:weaveJavaxPackages=true to 'weaver options'
+3. Include 'javax.servlet.http.HttpServlet' to instrumentation scope.

+Here is a sample aop.xml after the change: + +

+<aspectj>
+  +<aspects>
+     + <concrete-aspect name="com.maintainj.inst.J2EEAspect" extends="com.maintainj.aspect.ServletDataAspect">
+       <pointcut name="anyExecution" expression="execution( * *.*(..)) || execution( *.new(..))"/>
+     + </concrete-aspect>
+   + </aspects>
+  +<weaver options="-proceedOnError -Xset:weaveJavaxPackages=true">
+    <include within="org.jfree.chart..*"/>
+    <include within="javax.servlet.http.HttpServlet"/>
+    <include within="com.maintainj..*"/>
+  +</weaver>
+</aspectj> + +

For J2EE applications, the HttpServletRequest parameter of the service method shows the request parameters. + +

4.The download links

+The installation procedure is same as it is for the release version. Check the user guide for detailed installation instructions. +

MaintainJ Feature Update url: http://www.maintainj.com/updates/3.0
+MaintainJ J2EE Server Feature Update url: http://www.maintainj.com/updates/3.0/server
+MaintainJ Feature Zip: MaintainJ_3.0.0.zip
+MaintainJ J2EE Server Feature: MaintainJ_J2EE_Launcher_3.0.0.zip
+MaintainJ.war to instrument J2EE applications: MaintainJ.war
+ +

5. What's coming?

+ +Below is a summary of enhancements you can expect in near future.

+ +1.In this release context data is shown in the properties view. This will also be shown in the diagram itself - either below the call or in the tooltip popup.
+2. For large diagrams of say 6000 calls, lot of memory is taken up because all +context data is loaded into memory when the diagram is rendered. This has to be better managed.
+3. The data for JDBC calls - the sql statement itself and the data will be added. +The HttpServletRequest parameters in the service() method are shown in this +release.
+4. The other major enhancement for V3 is search capability.
+5. And finally the important impact analysis capability will be added.

+ +Keep checking for these exciting new features of MaintainJ! + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/missing.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/missing.html new file mode 100644 index 0000000..c060f57 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/missing.html @@ -0,0 +1,11 @@ + + + +MaintainJ Inc. + + + + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/mnjInstall.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/mnjInstall.html new file mode 100644 index 0000000..c66ff4c --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/mnjInstall.html @@ -0,0 +1,643 @@ + + + + + + + + +

3. MaintainJ Quick Start

+ +We strongly suggest you to watch this +demo video first to understand MaintainJ's potential. +

For detailed installation instructions, check the following sections. This +wizard shows the download links and demo video relevant to your application.

+ +What is the type of your application? +Web App +Core Java App +Applet +JUnit + +None of these + + + + + + + + + + + + + + + + + + + + + + + + + +
+
  +

3.1 MaintainJ Eclipse Plug-ins Installation

+

+MaintainJ has two Eclipse features:
+a) MaintainJ Feature (always required)
+b) MaintainJ J2EE Server Feature (required only for Tomcat and JBoss applications). +

MaintainJ requires Eclipse 3.2 or newer versions. The following sections help you to install the plug-ins. + + + + + +

3.1.1. MaintainJ Update URL's

+ +

MaintainJ Feature: http://www.maintainj.com/updates/4.1.0
+MaintainJ J2EE Server Feature: http://www.maintainj.com/updates/4.1.0/server

+ +

+ +Follow these steps to install using the update URL's: +

    +
  • In Eclipse, click 'Help-->Install New Software'.
  • +
  • Click 'Add' and in the dialog box opened, enter one of the URL's above.
  • +
  • Select the just added site in the 'Available Software Sites' + dropdown list and follow the wizard steps.
  • +
+ + +

3.1.2. MaintainJ Plug-in Zip Files

+ +We strongly recommend you to use the Update URL's to install, but +if you cannot for any reason, you may install using the following zip files. +

MaintainJ Feature: +MaintainJ_4.1.0.zip
+MaintainJ J2EE Server Feature: +MaintainJ_J2EE_Launcher_4.1.0.zip +

+Unzip the zip files to <EclipseRoot>>/eclipse/plugins folder and restart Eclipse. + +
+GEF (Graphical Editing Framework) plug-in +is required for MaintainJ. Install it if you do not already have it installed. +Ensure that you install the GEF version that works with your Eclipse version. + +

3.1.3. Verify Installation

+

+MaintainJ UML Diagram and MaintainJ Wizards: +Create a MaintainJ Trace Files Project by following +File-->New-->Project-->MaintainJ-->MaintainJ Trace Files Project. You should +see a sample trace file Alfresco_Login.ser in the project. +When you open the trace file, sequence and class diagrams should show. + +

MaintainJ Run Configurations : Click +'Run-->Run Configurations' in Eclipse to open the run configurations dialog. +On the left hand side, you should see Java Application with MaintainJ +

+ +

Tomcat/JBoss Server Configurations: Open 'Servers' view in Eclipse and create a +new Server (right click, New->Server). Under Apache and JBoss, you +should see 'Tomcat with MaintainJ' and 'JBoss with MaintainJ'. + +

+ +

3.1.4. Get Evaluation License

+Get the free evaluation license. + + +
  +

3.2 MaintainJ.war - To generate call trace files for Web Applications

+

+MaintainJ.war +web application is the wizard to install and configure MaintainJ on application servers. +Deploy MaintainJ.war directly to the application server or from an Eclipse based IDE +(after importing the war as a project). +Open http://server/MaintainJ/index.jsp and follow the instructions.

+ +

Check the demo video. + +
  +

+

3.3 MaintainJ Aspect Wizard

+MaintainJSwingWizard.jar  - +Start as 'java -jar MaintainJSwingWizard.jar'

+

Use this wizard for core Java applications launched +from outside Eclipse. Check the demo video. +If you are launching your application from inside Eclipse, +use MaintainJ Launcher plug-in. + +
  +

3.4 Release Notes

+ +

+ +MaintainJ 4.1.0 +(September 1, 2014)

+This release contains several enhancements as below: +
    +
  1. Search Diagram - + Using this feature, the sequence diagram can be searched for a class or method or + any text (like tables or fields) in database SQL calls. +
  2. +
  3. + AspectJ library used is upgraded to the latest 1.8.2 from the older 1.6.11 +
  4. +
  5. + In MaintainJ Server feature, support is added for Tomcat 8. +
  6. +
+

+ +MaintainJ 4.0.0 +(April 30, 2013)

+This release adds the response time tuning capability in a single user environment. +
    +
  1. Response Time View - + The sequence diagram and the corresponding 'Outline view' are + redesigned to allow the user to quickly find the methods that are taking the + maximum response time in a use case. +
  2. +
  3. Filter Calls by Response Time - + This feature allows the user to filter out all the calls whose response time is less + than the specified time. +
  4. +
  5. Delete All Classes Except - + This feature can be used to quickly see the interactions between the important + classes in the use case. +
  6. + +
  7. Shows the number of times a method is called in a loop - + MaintainJ always removed the loop and recursive calls to avoid cluttered sequence + diagrams. This version adds the feature to show the number of times a method is + called in a loop. +
  8. + +
  9. Opening trace files generated using older versions - To open the trace files + generated using the older versions of MaintainJ, copy them to the + 'MaintainJ Trace Files Project' created using this release. + This project can be created by following File->New->Project->MaintainJ->MaintainJ Trace Files Project. + Please note that the trace files from older verisons do not have information + about the number of times a method is called in a loop. +
  10. + +
+

+ +MaintainJ 3.6.1 +(March 12, 2013)

+This is mainly a minor enhancement and bug fix release. +
    +
  1. Export the diagrams to UML2 - + The package name of the return type of a call was not shown in the last release. + This release fixes the issue. If the method parameters (or the return type) are + of an array type, they were not shown properly in the last release. This issue is fixed as well. +
  2. +
  3. When call context is captured, the previous release did not generate a merged + trace file of all the threads. This release generates the merged trace file for all threads. +
  4. + +
  5. MaintainJ removes the loop and recursive calls by default. A system property is + introduced to turn this off if necessary. +
  6. +
+ + +

+MaintainJ 3.6.0 +(February 16, 2013)

+
    +
  1. Export the diagrams to UML2 - + This feature is enhanced to export the UML 2 model with the class hierarchy, + class methods and attributes. Before exporting the UML 2 model, user can choose + to export one or all of these options. +
  2. +
  3. A new plugin is created to render the class and sequence diagrams in RSA + from the UML 2 model exported using the above feature. +
  4. + +
  5. Web Sequence Diagrams - This + feature allows to generate the web sequence diagrams as at websequencediagrams.com. +
  6. +
  7. Response times for each call is displayed in the Outline view. +
  8. +
  9. Support is added for JRE 1.7 and Tomcat 7. +
  10. +
+ +

MaintainJ 3.5.0 +(January 27, 2013)

+
    +
  1. Export the diagrams to UML2 - + Now you can export the MaintainJ generated class and + sequence diagrams into a UML2 model file. This UML2 model file can be imported into any + UML2 compliant tool like Rational Software Architect (RSA) to view the UML2 class and sequence diagrams. +
  2. +
  3. Predefined Filters - The prior releases of MaintainJ allow defining class and/or package + filters before generating the trace files. Now, similar filters can be applied + on the diagrams after generating the trace files. You can capture the trace + files with all the classes and then apply different filters to the diagram to + view the diagrams at different levels of abstraction. +
  4. +
  5. Delete Constructor Calls - All constructor calls can be deleted at once using this + option in the sequence diagram. +
  6. +
+ +

MaintainJ 3.3.0 +(October 26, 2012)

+
    +
  1. Introduces Impact Analysis capability - User can search for trace files, classes, + methods, SQL statements in multiple trace files across many 'MaintainJ Trace File Projects'. + Check the section on Impact Analysis + in the user guide for more details. +
  2. +
  3. The class diagram is improved to show the fields and methods in a class when + the mouse is hovered over a class.
  4. +
+

MaintainJ 3.2.0 +(September 7, 2012)

+
    +
  1. Major release with multiple enhancements to the product.
  2. +
  3. Shows call context - The context of each call is shown in the sequence diagram. + The context includes the call parameters, return value and the state of the called object.
  4. +
  5. Displays runtime SQL - The actual runtime SQL statements (with populated parameters) + going to the database regardless of the JDBC frameworks used are shown in the sequence diagram.
  6. +
  7. JSP calls - The calls to JSP(s) in a use case are shown in the sequence + diagrams. If one JSP includes multiple JSPs, the runtime calls to the inner JSPs are + displayed as well.
  8. +
  9. + Supports multi-JVM applications - Users can trace applications running on multiple + JVMs and see the end-to-end call flow in a single sequence diagram. For example, + when an application calls a web service running in a different JVM, the call flow + across JVMs is shown in a single sequence diagram. The calls in each JVM can be seen + in a different color on the same diagram. +
  10. +
  11. Enhanced Outline View - The sequence diagram's 'Outline View' shows all the + classes and calls in the use case. It is enhanced to select and delete multiple + packages, classes or calls at one go. An option to filter out all getter and + setter methods has been added to the sequence diagram. +
  12. +
  13. By using 'Select In Diagram' feature in 'Outline View', + the breadcrumb trail of the call can be seen in sequence diagram. This feature helps to + quickly browse the diagram without expanding all calls.
  14. +
  15. The new 'Exclude Class' feature allows to exclude some + classes or packages from the diagram. This is similar + to excluding classes or packages from instrumentation scope so that those classes + or packages will not be captured in the trace file. This new feature + allows us to first capture all calls and then exclude those we do not want from the diagram.
  16. +
+ + +

MaintainJ 2.9.0 +(March 29, 2011)

+
    +
  1. Major revamp of UML Diagram Editor to + increase the performance.
  2. +
  3. The tooltips for calls and classes are + enhanced. The call tooltip shows the javadoc information if the source file is + available in the workspace. In the class diagram the class tooltip shows all + the methods of that class called in the use case. The tooltips behave exactly + as they do in java source editor.
  4. +
  5. The sequence and class diagrams are always + in sync now. In the previous releases, when a class is deleted in the sequence + diagram, it is deleted in class diagram but when a class is deleted from class + diagram, it is not deleted in sequence diagram. In this release they are + always in sync.
  6. +
  7. When a class or call is selected in the + Outline view, the corresponding class or call is not automatically selected in + the diagram. User needs to right click and choose 'Select In Diagram' to + select the corresponding class or call in the diagram. This change is to avoid + unnecessary scrolling of the diagram, which is very slow in large diagrams.
  8. +
  9. For Tomcat and JBoss applications deployed + in Eclipse using MaintainJ J2EE server feature, the JSPs are automatically + added to the instrumentation scope and are shown in the diagrams.
  10. +
  11. The trace files saved as .mnj files in + previous releases cannot be opened in this release. A conversion tool for this + purpose will be released soon.
  12. +
+

MaintainJ 2.8.0 +(September 10, 2009)

+
    +
  1. MaintainJ J2EE Server Plug-in is released. + This plug-in is used to instrument applications running on Tomcat or JBoss.
  2. +
  3. MaintainJ Launcher plug-in is enhanced to + seamlessly support JUnit and + Applets.
  4. +
  5. 'MaintainJ Start and Stop Tracing' Swing + window is updated with more information.
  6. +
  7. AspectJ weaver used is upgraded to more + efficient version 1.6.4.
  8. +
+

MaintainJ 2.5.3 +(January 17, 2009)

+
    +
  1. Added floating license option.
  2. +
  3. Classes in class diagrams can be resized now.
  4. +
  5. In + MaintainJ Launcher plug-in, + stopping users from selecting com package as it includes packages like + com.sun into the instrumentation scope.
  6. +
+

MaintainJ 2.5.1 +(October 27, 2008)

+
    +
  1. Bug fix release. Fixed a defect in MaintainJ + Launcher plug-in.
  2. +
+

MaintainJ 2.5 +(July 07, 2008)

+
    +
  1. Dependency on AJDT plug-in is removed. Now + GEF is the only required plug-in.
  2. +
  3. Build-time instrumentation wizard is + retired.
  4. +
+

MaintainJ 2.4 +(July 01, 2008)

+
    +
  1. UML class diagrams show methods called in + each class in a scenario.
  2. +
  3. In UML sequence diagrams, 'Delete Duplicate + Calls to a Method' menu option deletes all calls expect the selected call.
  4. +
+

MaintainJ 2.1 +(December 08, 2007)

+
    +
  1. MaintainJ.war updates - Updated to work on + UNIX. Updated to work with J2EE applications deployed from Eclipse.
  2. +
  3. MaintainJ Launcher is supported on all + flavors of JREs of version 1.4 and above.
  4. +
  5. UML sequence diagrams show the response time + for every method call. Select a call and open the Eclipse properties view to + view the response time.
  6. +
+

MaintainJ 2.0 +(October 24, 2007)

+
    +
  1. Runtime instrumentation support is added for + J2SE and J2EE applications. Applications running on supported configurations + are instrumented at runtime to generate the call trace files. No changes done + to the source code. No need to build the source code using AspectJ; the + deployed application is instrumented at runtime to generate the call trace + files. UML diagrams are generated from trace files.
  2. +
  3. A new Eclipse plug-in, MaintainJ Launcher, is + added. This plug-in instruments J2SE applications at runtime and generates + call trace files when the application is launched from Eclipse.
  4. +
  5. A new web application MaintainJ.war is + developed for runtime instrumenting J2EE applications. MaintainJ.war installs MaintainJ related jars on the server, + generates the aspect and prepares the application for runtime instrumentation.
  6. +
  7. UML diagrams can also be exported as BMP + images. BMP images offer better quality.
  8. +
+

MaintainJ 1.3 +(September 1, 2007)

+
    +
  1. UML Editor's performance has been increased + drastically. Now large diagrams can be opened and edited much faster than + before. While in the last release a sequence diagram with 6000 calls took + around 75 seconds to open, it now takes about 13 seconds.
  2. +
  3. More features to better understand + multi-threaded applications. In this release trace files of different threads + can be merged using a wizard. Follow File-->New-->Other-->MaintainJ-->Merge + Trace Files to access the wizard. When the trace file logging is stopped, a + trace file that contains joinpoints of all threads is written with name <<TraceFileName>>_AllThreads.ser + . However, if this file is too large (say 20,000+ calls), it may take a while + to render the diagram. In such a case, it is better to work with trace files + of each thread separately and merge them as necessary.
  4. +
  5. Instrumentation Wizard enhanced to work on + Solaris. The browser widget, which was giving problems on Solaris is not used + on platforms that do not support browser.
  6. +
  7. License is locked to the computer name. Users + need to supply the Host Key (encoded computer name + user name for evaluation + and just machine name when bought) to get the license file.
  8. +
  9. Bug fixes. When a trace file outside the + workspace is opened, a message is shown to add to add the trace file to a + project in workspace.
  10. +
+

MaintainJ 1.2.2 (July 19, 2007)

+
    +
  1. Bug fixes to work with Eclipse 3.3.
  2. +
+

MaintainJ 1.2.1 (July 13, 2007)

+
    +
  1. The downloaded version of the plug-in works in + a limited evaluation mode, in which  one can expand or collapse calls + in the sequence diagrams for a limited number of times. Users need to + install the license file to get the full evaluation license.
  2. +
+

MaintainJ 1.2 (June 26, 2007)

+

The following is a list of the major changes in +this version:

+
    +
  1. Support for Eclipse plug-ins is added. Now, + Eclipse plug-ins can be instrumented using Instrumentation Wizard and diagrams + can be generated in a couple of minutes.
  2. +
  3. Support for pure web applications is added. In + the previous version, the Instrumentation Wizard did not support pure web + applications that don't have an EAR file. Now users can instrument such + applications and deploy to servers like Tomcat to generate UML diagrams.
  4. +
  5. Support for non-GUI J2SE applications is + added. Instrumentation Wizard can instrument any Java code. Once the code is + instrumented, user can add a few lines of code to log the trace files. 
  6. +
  7. Demos are added for J2SE and Plug-in + instrumentation.
  8. +
  9. Bug fixes.
  10. +
+ \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/mnjIntro.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/mnjIntro.html new file mode 100644 index 0000000..18726a2 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/mnjIntro.html @@ -0,0 +1,169 @@ + + + + + + + +MaintainJ generates UML sequence and class diagram at runtime + + + + +

1. MaintainJ Introduction

+ +

+MaintainJ reduces the time needed to understand complex enterprise Java +applications from days to minutes. It also helps to document Java applications +using sequence and class diagrams. +

+MaintainJ generates runtime sequence diagrams using the call +trace captured for a single use case while you run the application. +The captured information includes data at each method call, any sql calls to +the database and the response time of each call. You can trace +applications running on a single JVM or on multiple JVM's and view the +end-to-end call trace in a single sequence diagram.
+
You may want to check the sample +screenshots of +the generated sequence and class diagrams.

+

+The following are the three steps to generate the diagrams: +

+ +

+ +

1.1. Instrument Code

+

This step changes class files at runtime. +No changes are done to the source files nor any changes are +persisted to file system. You can choose the packages to be instrumented. +Instrumented applications are slow to service the first request but perform with +little overhead later.

+Below are the types of Java applications supported out-of-the box by +MaintainJ. In fact, any non-J2ME Java applications can use MaintainJ by +following these steps. +The JRE versions currently supported are 1.4, 1.5, 1.6 and 1.7. +

+ + +

a) J2SE applications/Applets/JUnit - Tracing J2SE applications (Swing or +non-GUI), Applets and JUnit is supported.

+
+ +

+ +b) J2EE applications - The following J2EE application server are supported - +Tomcat 4, 5, 6 & 7, JBoss 3, 4, 5 & 6, WebLogic 8, 9 & 10, WebSphere 5, 6 & 7. +Glassfish and +Jetty servers are also supported. +If your server is not supported, +follow these steps to generate +the trace files. We would add support to your server on request. + + +

+ +c) Databases - MaintainJ captures the actual runtime sql calls sent to the +database regardless of the JDBC frameworks used by the application. MaintainJ +supports Oracle, DB2, MySQL, PostgreSQL and Derby out of the box. Microsoft SQL +Server also is supported. Contact support if you are using MS SQL Server or any +other databases. + + + + +

1.2. Generate Trace Files

+

Next, run the instrumented application and +demarcate the +start and end points of a use case. Call trace for the use case will be logged +to the given trace file (.ser file).

+

a) J2EE Applications - A JSP is provided +to demarcate the start and end points. You need to click a 'Start Tracing' button before a use +case starts and click 'Stop Tracing' at the end of the use case. The call trace +will be logged to the given file when 'Stop Tracing' is clicked.

+

b) J2SE/Applet/JUnit - A +Swing window in which you can start and stop tracing opens when your instrumented +application starts. Click 'Start Tracing' button before a use case starts and +'Stop Tracing' at the end of the use case. The call trace will be logged to the +given file when 'Stop Tracing' is clicked.

+

1.3. View the Diagrams

+

Create a MaintainJ Trace Files Project by following +File->New->Project->MaintainJ->MaintainJ Trace Files Project. Copy the trace files to this +project and open to view the diagrams in +MaintainJ UML Editor.

+ +

1.4. How does MaintainJ help users?

+ +

+1. Using MaintainJ, Java developers can quickly analyze, understand, document and +enhance large Java code bases. +The MaintainJ demo video +is recorded on a Java application +that has 8000+ classes, runs on Tomcat and MySQL and uses Spring and Hibernate frameworks. +

+2. MaintainJ generates detailed runtime sequence and class diagrams for a single use case. +The arguments and return value of the call are shown in the sequence diagram. The runtime +SQL calls made during a use case, regardless of the database frameworks used, are shown. +All these details help developers to quickly troubleshoot a problem or to analyze and +enhance the application. +

+3. MaintainJ supports + +tracing applications deployed across multiple JVM's. The call trace +captured on different JVM’s can be merged to view the end-to-end call flow across JVM’s. +For example, when an application calls a web service running in a different JVM, the call +flow across the JVMs is shown in a single sequence diagram. The calls in each JVM are +shown in a different color. +

+4. MaintainJ supports +runtime impact analysis - +Users can capture the runtime call +trace for all the use cases of the application and use that information to exactly +determine the use cases impacted by a change to a Java class, method or database +table or field. +

+5. Users can filter out the unwanted details from the MaintainJ generated diagrams +and then export the diagrams as UML2 +model files. These models can be imported into +other UML2 compliant tools like Rational Software Architect (RSA) where they can +be edited for enhancing the application. +

+6. Any UML diagrams generated at runtime can be verbose and difficult to read. +MaintainJ provides simple user interface to dynamically explore the sequence +diagrams. Users can also search for a class, method or database table or field used in the use case. +

+7. MaintainJ offers various options to filter out unwanted details from the +generated diagrams and to view them at the level of abstraction that the user +wants. For example, a use case in a web application typically spans the +web tier, business tier and data access tier. Users can apply +predefined filters +on the diagram to view just the business tier classes. In addition, +MaintainJ shows the interactions between the application classes +only (no framework or library classes are shown). +

+8. Users can easily troubleshoot multi-threaded applications using +MaintainJ - The sequence diagram shows the runtime interactions +between threads in different colors. This helps developers to quickly +troubleshoot a multi-threaded application, which would be hard to +do using a traditional debugger. +

+9. MaintainJ integrates seamlessly with JUnit +- Users can generate a +sequence diagram for every test case and check the sequence diagram +for any troubleshooting later. +

+10. MaintainJ saves lot of effort for teams that maintain large +Java applications - Different developers in a team repeatedly spend time +to understand the same use cases because there are no tools to quickly +document and share that knowledge. By facilitating documentation and +sharing of the "Maintenance Experience" within the team using the generated +UML diagrams, MaintainJ exponentially reduces the total maintenance effort. +

+ + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/newIntro.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/newIntro.html new file mode 100644 index 0000000..9f16515 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/newIntro.html @@ -0,0 +1,130 @@ + + + + + + + +MaintainJ generates UML sequence and class diagram at runtime + + + + +

MaintainJ Introduction

+ +

MaintainJ generates UML sequence and class diagram at +runtime for a use case. This happens in three steps:

+

1. Instrument Code

+

This step, inserts log statements before every +method call in the class files. Source code is unchanged. You can choose the +packages that will be instrumented. All classes and sub-packages under the +chosen packages will be instrumented. This can be done either at runtime or +build-time.

+

a) Runtime Instrumentation - Runtime instrumentation +is easy and very quick to get started. The following table lists the application +server and JRE configurations on which MaintainJ runtime instrumentation is supported. +J2SE applications (Swing or non-GUI) are supported on almost all JREs.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Server

JRE Sun's JREBEA's JRockitIBM JRE
J2SE Apps1.4, 1.5 , 1.61.4 and 1.51.5
Tomcat 41.4  
Tomcat 5 & 61.5, 1.6  
JBoss 31.4  
JBoss 41.5, 1.6  
WebLogic 81.4JRockit 1.4 
WebLogic 91.5JRockit 1.5 
WebSphere 51.4 1.4
WebSphere 6  1.5
+

Runtime instrumented applications are slow to +service the first request but perform with little overhead after that.

+

b) Build-time Instrumentation - Use +build-time instrumentation if runtime instrumentation is not supported for your +configuration. MaintainJ Instrumentation +Wizard supports build-time instrumentation for J2SE, J2EE and Eclipse +applications. Instrumentation Wizard supports J2EE applications when they are +deployed directly from Eclipse WTP (Web Tools Platform) based IDEs or RAD 6. If +the J2EE applications are built and deployed using Ant scripts, the Ant scripts +need to be changed.

+ +

2. Generate Trace Files

+

Run the instrumented Java code. Define the +start and end points of a use case. Call trace for the use case will be logged +to the given trace file (.ser file).

+

a) J2EE Applications - A JSP is provided +to Start and Tracing. You need to click a 'Start Tracing' button before a use +case starts and click 'Stop Tracing' at the end of the use case. The call trace +will be logged to the given file name when 'Stop Tracing' is clicked.

+

b) J2SE and Eclipse Applications - A +Swing window where you can start and stop tracing opens when your instrumented +application starts. Click a 'Start Tracing' button before a use case starts and +'Stop Tracing' at the end of the use case. The call trace will be logged to the +given file name when 'Stop Tracing' is clicked.

+

3. View the Diagrams +

+

Just copy or move the trace files to any +project in Eclipse workspace to view the diagrams.

+

 

+ + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/overviewDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/overviewDemo.html new file mode 100644 index 0000000..9cac7b9 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/overviewDemo.html @@ -0,0 +1,17 @@ + + + + +
+ + + + + + + +
+Length of video - 3 minutes. Use the green bar above to pause or move back. +
If the text is not clear, the browser font size might have been changed. Reset the font size.
+ + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/pluginRuntimeDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/pluginRuntimeDemo.html new file mode 100644 index 0000000..3577c2b --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/pluginRuntimeDemo.html @@ -0,0 +1,16 @@ + + + +
+ + + + + + + + + +
+ + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/runtimeInst.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/runtimeInst.html new file mode 100644 index 0000000..8c2ba35 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/runtimeInst.html @@ -0,0 +1,295 @@ + + + + + + + +MaintainJ generates UML sequence and class diagram at runtime + + + + +

5. Generating Call Trace Files

+ +

Java applications run in different runtime +configurations like Applets, Swing/SWT based GUI applications, non-GUI +applications (batch/socket server apps, etc), J2EE server applications etc. +MaintainJ supports many of these configurations out of the box with the help +of wizards. Check the +Introduction page for +the supported configurations and related demo videos. The following sections explain +generating the call trace files using these wizards and even without using the +wizards. +

+ +

5.1 Generating call trace for J2EE Applications
+5.2 Generating call trace for J2SE (Swing or non-GUI), Applets and JUnit  
+5.3 Generating call trace for Java Applications run from command prompt
+5.4 Generating call trace files on Multiple JVMs and merging the trace files  
+5.5 Generating call trace files without a MaintainJ wizard
 
+ + + +

5.1 Generating call trace for J2EE Applications

+

If you use Tomcat or JBoss and deploy and start +the server from Eclipse Servers view, the MaintainJ J2EE Server Launcher plug-in +should be used. Check the Demo Video.

+

For all other cases use +MaintainJ.war. MaintainJ.war installs +MaintainJ related jar files to the application server and configures your J2EE +application for instrumentation. Deploy MaintainJ.war to the same server instance +where you are running your application. +Open http://server/MaintainJ/index.jsp for installation and configuration page +and follow the instructions. Check the +Demo Video.

+

+

5.2 Generating call trace for J2SE (Swing or non-GUI), Applet and JUnit +Applications

+

Demo Videos - +MaintainJ for Swing, +Applet, +JUnit

+

Use this if you are currently running your application +in Eclipse using Java Application / Java Applet / JUnit run configurations. +

+

1) Click Run-->Run Configurations in Eclipse +to open the run configurations dialog.
+2) On the +left hand side, you will see three MaintainJ configurations for Java +Applets, Java Applications and JUnit as highlighted in the screenshot +below. MaintainJ run configurations are the same as normal configurations +except for the MaintainJ tab, which is the second from left. + +

+ + +

3) Create a new configuration for your type of application just as +you would when running without MaintainJ. In the MaintainJ tab, +choose the packages that you want to capture. Choose only the packages of +interest and avoid very high level packages. +If you want to capture the values of parameters and return value for each call, +select 'Capture method call context data'. You can also capture the actual runtime sql statements +your application is sending to the database server by selecting 'Capture SQL' and +then choosing your database.
+4) Run the application or Applet or JUnit test cases. +This will create 'maintainj/META-INF/aop.xml' file in your main project's root +folder. If you would like to manually edit aop.xml and do not want the wizard to +overwrite your changes, select 'Do not regenerate aop.xml' checkbox. +
5 a) For JUnit test cases, this will also create 'maintainj\JUnitTraceFiles' +folder under which the trace files will be written for each test case. This is the +last step if you are using MaintainJ with JUnit test cases. +
5 b) For J2SE +applications and applets, a Swing window will open along with your +application/applet. Enter a file name with full path and without extension +and click 'Stop Tracing' to log the call trace up +to the point of starting the application. The generated trace file names, +locations and number of calls in each file will be displayed. One trace file +for each active thread will be generated. The thread name +is appended to the given trace file name. Trace files have +the extension 'ser'.

+

+

+

6) Once 'Stop Tracing' is clicked, the button is reset +to 'Start Tracing' as above. Before performing an action for which a trace file is needed, click +'Start Tracing', perform the action and click 'Stop Tracing' to generate a new trace +file. +
7) Copy the trace files to a MaintainJ Trace Files Project in Eclipse +and open to view the UML diagrams. MaintainJ Trace Files Project +can be created by by following +File->New->Project->MaintainJ->MaintainJ Trace Files Project.

+ +

5.3 Generating call trace for Java Applications run from +command prompt

+ +

Demo Videos - + + +MaintainJ for + Applications run from command prompt

+This Swing based Wizard supports generating +trace files for any Java application that is run from the command prompt +(instead of running from Eclipse). The following +steps explain how this wizard is used.

+1) Download MaintainJSwingWizard.jar and +start the Wizard using 'java -jar MaintainJSwingWizard.jar' +
2) Select Application Type +as J2SE Application. Select a folder to copy the MaintainJ +related files. Provide the +absolute name of the main class (the class with public static void main(String[]) +method).

+

+3) Choose the package(s) in the application +or plug-in. Limit the instrumentation scope to your application or plug-in +classes. You may also exclude the package(s) that are not of interest. +The other options are same as explained above in section 5.2

+ +
+
4) The wizard copies MaintainJ jar files, +META-INF/aop.xml (the aspect) and start_with_maintainj.bat + to the installation +folder. Edit start_with_maintainj.bat to +set application classpath. + +
+5) When the Java application, +a 'MaintainJ - Start and +Stop Tracing' Swing window pops up. This is the same window as shown in the last section. +Enter a file name with full path and without extension and click 'Stop Tracing' to +log the call trace up to the point of starting the +plug-in. One or more trace files with the given file name with thread name +appended (Ex: EclipseShapeDropped_main.ser) are generated. One trace file for +each active thread is generated. +
6) Once 'Stop Tracing' is clicked, the button +is reset to 'Start Tracing'. Before performing an action for which a trace file is +needed, click 'Start Tracing', perform the action and click 'Stop Tracing' to +generate a new trace file.

+ +

5.4 Generating call trace files on multiple JVMs and merging the trace files

+MaintainJ supports tracing applications running on multiple JVMs simultaneously +and merging the trace files for a end-to-end call flow. For example, consider a scenario where +a J2EE application calls a web service running on a different J2EE server. +You may be interested in seeing the end-to-end call flow of a request +going from the J2EE application to the web service and coming back. +You can do this by following the steps below. This feature is supported +only for JRE 1.5 and above. + +

+1) Start MaintainJ Node Manager window using +
'java -classpath <pathTo>/MaintainJAspect.jar com.maintainj.swing.NodeManagerWindow' . +You will find MaintainJAspect.jar under eclipse\plugins\com.maintainj.launcher.core_x.x.x. +A Swing window similar to the screenshot below opens. Do not do anything yet in this window. +

+ +

+2) While starting the applications with MaintainJ, select the option to +trace multiple JVMs and provide a port number to start the MaintainJ Node Agent. +You will see this option on all MaintainJ wizards. In the Eclipse run configuration +MaintainJ tab, +select 'Capturing call trace on multiple Java VMs'. Select the +same option if you are using MaintainJSwingWizard explained in section 5.3. +If you are tracing a J2EE application using MaintainJ.war, you will see the +same option in 'Step 5: Capture call trace'. +
+3) You may trace any combination of Java applications running on different +JVMs - multiple J2EE applications or a socket server application and a +J2EE application, etc. Once all the applications are started with MaintainJ, +go back to the MaintainJ Node Manager window opened in step 1. +
+4) Enter the IP addresses of the machines where you are running your applications +and the port numbers you gave in step 2. Click 'Test Connection'. Make sure that the +status changes to 'Tested'. +
+5) Click 'Synchronize Nodes' button. +
+6) Enter the name of the scenario. This will be used to as an identifier for the +generated trace files. +
+7) Click 'Start Tracing' when you are ready to trace. +
+8) Run the scenario in your application and click 'Stop Tracing'. +
+9) You will see the list of generated trace files. Click +'Download trace files from all nodes' if you want to copy all the trace files to +a local folder. +
+10) You can merge these trace files using Merge Trace Files wizard +(at File->New->Other->MaintainJ->Merge Trace Files) to view them in a single +sequence diagram. + +

5.5 Generating call trace files without a MaintainJ wizard

+ +If the wizards that come with MaintainJ do not work for your application, you can +still generate the trace files using the procedure below.

+There are 4 steps to instrument your application and generate the trace files. The first three steps will instrument the application. The last step will set the start and end points of the use case and will write the call trace to a file. +

+1. Prepare the aspect. + +

The aspect should be in aop.xml file. Below is a sample file.

+ +<aspectj>
+ <aspects>
+   <concrete-aspect name="com.maintainj.inst.J2EEAspect" extends="com.maintainj.aspect.ExecutionAspect">
+     <pointcut name="anyExecution" expression="execution(* *.*(..)) || execution(*.new(..))"/>
+   </concrete-aspect>
+ </aspects>
+  <weaver options="-proceedOnError -showWeaveInfo -verbose ">
+   <include within="com.test..*"/>
+  </weaver>
+</aspectj>

+ +The only line that must be changed is the one within 'weaver options' section in blue. +Replace 'com.test' package with a package in your application. Only the classes under +the included packages and their sub-packages will be captured in the diagrams. +You may include as many packages as you want. If +you want to include a class, simply replace 'com.test..*' with the class name. You +can also exclude some classes or packages similarly using the 'exclude' keyword. + +

+ +The above aop.xml file does not capture method call context data, JSP's and the SQL statements. +If you want to add those options, either contact MaintainJ customer support or use one +of the wizards to first generate the aop.xml and then edit it as necessary. + +

+2. Update you application classpath.

+ +In case of J2EE applications, update the server classpath so that it will apply to +all applications running on the server. For J2SE, JUnit or Applets, just put them +under application classpath. All the jar files mentioned below can be found in +eclipse/plugins/com.maintainj.launcher.core_x.x.x folder for J2SE applications +and in MaintainJ.war for J2EE applications. + +

The instructions here apply for +applications running using JRE 1.5 or above. If you are using JRE 1.4, please contact +MaintainJ customer support or use one of the wizards on a sample application to +check the jar files added to classpath.

+ +The aop.xml created in last step needs to be under META-INF +folder and that folder needs to be in classpath. Assuming that the location of aop.xml +is c:\maintainj\META-INF\aop.xml, below are the jar files and the folder that is added +to the classpath for applications using JRE 1.5 or above. +

+MaintainJAspect.jar;aspectweaver.jar;c:\maintainj + +

+3. Update JVM arguments

+ +Again, the instructions below are for JRE 1.5 or above.

+ +-javaagent:<<PathTo>>\aspectjweaver.jar

+ +

+ +4. Generate trace file

+ +The challenge here is to find a way to turn on and turn off tracing. In the wizards that +come with MaintainJ, this is done using a Swing window for J2SE applications. For J2EE +applications, this is done using a JSP. But you are free to devise your own method.

+ +a) To turn on tracing, call the following method. JoinPointMap class is present in MaintainJAspect.jar.

+ +JoinPointMap.setAddJoinPoint(true);

+
+b) To write the call trace to a file and turn off tracing use the following statements.

+ +JoinPointMap.setAddJoinPoint(false);
+String[][] serFiles = JoinPointMap.writeToFile("c:\\TraceFile");
+JoinPointMap.clear();

+
+The input to JoinPointMap.writeToFile() is the trace file name, which is given without +any extension. This method returns a String[][] where String[][0] is the generated trace +file name and String[][1] is the number of calls in that trace file. + +The extension .ser is automatically added to the file name. One trace file for each thread +in the use case is generated. + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/screenshots.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/screenshots.html new file mode 100644 index 0000000..51fa9f2 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/screenshots.html @@ -0,0 +1,47 @@ + + +MaintainJ Inc. + + + + + + + +

MaintainJ Screenshots

+ +
    +
  1. Sequence Diagram Screenshots
  2. +
  3. Class Diagram Screenshot
  4. +
+
+

1. Sequence Diagram Screenshot 1

+

The screenshot below shows the following features of the sequence diagram:

+ +1. The runtime interactions between the concrete Java classes for a login use case.
+2. That you can explore the sequence diagram by expanding and collapsing the calls.
+3. The 'Properties view' below the sequence diagram showing the context of the selected call. +The call context includes:
+    a) The call parameters and return value.
+    b) The state of the called object when the method is invoked.
+    c) The response time of the call in milliseconds.
+

+ +

Sequence Diagram Screenshot 2

+

The screenshot below shows the following features of the sequence diagram:

+1. The sequence diagram 'Outline View' shows all packages, classes and calls in the use case.
+2. When mouse is hovered over a call, the call context shows in a popup.
+3. MaintainJ captures the actual runtime SQL sent to the database regardless +of the JDBC framework used by the application.
+

+ + +

2. Class Diagram

+The class diagram shows the same classes currently shown in the sequence diagram and +their dependencies based on their runtime interactions. For example, based on the class +diagram below, one can quickly infer that in this use case AuthenticationComponentImpl +class calls RepositoryAuthenticationDao. +

+ + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/support.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/support.html new file mode 100644 index 0000000..063ddf0 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/support.html @@ -0,0 +1,58 @@ + + + +

MaintainJ Support Channels

+

1. Free Evaluation License and Support

+We offer free evaluation licenses and support so that you can try MaintainJ on your +applications. We request you to confirm that in addition to generating the diagrams, +MaintainJ actually saves debugging and documentation effort for your Java teams. +Please feel free to ask us for license extensions if you need more time to evaluate +the product. + +

2. MaintainJ Installation Wizards

+

We provide many out-of-the-box wizards for quick installation of MaintainJ. +Usually one of these wizards would work for you. Use the +MaintainJ Quick Start +to download the relevant Eclipse plug-ins and wizards for your application. You will also +find slideshows of the steps involved in installing MaintainJ using the wizards. + + +

3. MaintainJ User Guide, FAQ and Forum

+ +MaintainJ User Guide - The user guide +has all the details on how to set up and use MaintainJ. +

+MaintainJ FAQ - The FAQ section is +constantly updated with the most frequently asked questions about MaintainJ. +Check the FAQ first to see if your questions are answered. +

+Support Forums - +The support forums are used to discuss any issues you have and to search through +the related discussions for solutions to your issues. Please provide the version +numbers of Eclipse, JDK, application server and any exception stack trace to help +us identify the problem quicker. +

+ +

4. Live Demos

+We offer 30 minute live demonstrations of MaintainJ using online presentation tools. +Live Demos give a chance for your entire team to see MaintainJ working on real +applications and also provide an opportunity to discuss any questions they might have. + +

5. Phone and email support

+

+You are always welcome to email us at support@maintainj.com. +

+ +We also encourage you to call us at 416 686 7494. We are in Toronto, Canada in EST time zone. +

+We promise that you will not greeted by a robot. You get to talk directly with +the MaintainJ developers. We see many instances where many hours are lost on +issues that could be resolved with a 2 minute chat with us. So, do not hesitate +to pick up the phone. + +

+ + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/swingCommandPromptDemo.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/swingCommandPromptDemo.html new file mode 100644 index 0000000..847d879 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/swingCommandPromptDemo.html @@ -0,0 +1,16 @@ + + + +
+ + + + + + + + + +
+ + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/testimonials.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/testimonials.html new file mode 100644 index 0000000..102fee3 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/testimonials.html @@ -0,0 +1,317 @@ + + + + +

Testimonials

+ +

Incredibly Useful Tool

+ +

As an IntelliJ user, I thought of sharing my experiences with MaintainJ. +First let me say, this is the fifth tool I evaluated and it will be the +last. Why, because this one works! The other tools cost several thousand +dollars and only create sequence diagrams from static source code, which +is completely useless for complex code. If you want to learn what is really +happening in your code, this is the product to use. Not only does the +MaintainJ work very well, but all of my questions were answered by +technical experts. I am very happy to recommend such a useful product. +Great Job to all those at MaintainJ. Keep up the good work.

+ +

Don Steger
+President
+Next Wave Mobile, LLC +

+
+

+

A very useful tool for a challenging problem!

+ +

MaintainJ +has proved to be a very useful tool for a challenging problem. Our team was +assigned the glamorous task of identifying business rules from Java code, +developed and evolved over a period of 10 years. The initial attempt at doing +this by just viewing the code did not yield the optimal results plus the task +quickly lost its appeal. :-).

+ +

The +MaintainJ trace capability enabled the team to identify specific paths within +the code base, and use the sequence diagrams to navigate the code to identify +and document rules. Version 3.0 provided the additional context data, that added +further value to what we were doing.

+ +

MaintainJ +support was very responsive and helped us with issues we faced getting the tool +to work with a non compliant J2EE app and any other questions we had. +Overall, this is a very useful tool that can provide great value at a nominal +price.

+ +

Ajay Chaudhari

+
+

The tool works very well for me

+ +

The tool works very well for me :

+
    +
  • to discover the actual call trace in a graphical manner.
  • +
  • to generate real documentation that I can pass around (especially for + black box testing).
  • +
+

I have advised my outsourcers to use it and will start getting more licenses +for my team members.

+ + + +

Jean Safar
+Chief Technology Officer
+Quartet Financial Systems

+
+

Awesome!!

+

I am part of a Java/J2EE maintenance project spanning 6000+ classes + from past 3 years. Having 6+ years of experience in Java it was always + difficult and more challenging because the code had very less + documentation, complex business rules, strict deadlines, growing + expectation from customers. There are still certain areas which still + baffles us as a team.
+
+ This tool came as a blessing !! It gives immense pleasure to see the + sequence diagram generated for a use case at click of a button.
+
+ Initially when trying this tool, the time it was taking to instrument a + package of 600 classes was not so encouraging, but thanks to you + Choudary for coming up with new version which instruments the classes + involved at runtime, yes at RUNTIME !!
+
+ Now there is a big leap in terms of performance and also the diagrams are + so user friendly. This tool made my life much easier, especially for the + new guys in the team, they can just play around the application and + figure out the flow just like that !!
+
+ Many thanks to you Choudary. Keep up the good work.
+ +
+

Satish S Rao +
Delivery Manager +
HP
+

+


+

With 32 years of this stuff behind me maybe MaintainJ will allow me a few +more

+

Some tools work well enough to use. Some tools work more or less as they are +represented. This tool is better than some which I have paid huge amounts of +money for because it just works. In attempting to understand massive systems +which are written in event driven languages and are almost always "self +documenting" (I always loved that one) it is nice to have a tool which cuts +through the trash and provides real sequence diagrams. THANK YOU, REALLY THANK +YOU

+

Marshall Dewitt +
Application/Systems Engineer, Principle
+

+


+

+ +

Amazing Tool!

+

+ I work for a .com company that releases a new version of our software every 2 weeks. The software has different styles of architecture and is a large and complex application. When we are implementing new features, most of the time, we have to follow the design decisions that was made for that particular module. All the documentation become obsolete quickly. Thanks for MaintainJ that generates the artifacts dynamically! When I reading a diagram I can be sure that is reflecting the actual code. Your tool is AMAZING!!! + +

+Joao Bentes
+Planet Discover

+ +
+ +

A boon for developers

+ A boon for developers working on top of an existing java application with very +little documentation w.r.t. code (as in most of the cases). Also for people, who +want to document the existing code with very little effort, which generally +stops them from doing it.

I got to this great tool thru TSS when i was looking for a UML plug-in for + Eclipse. I was excited by looking at the capabilities. As i evaluated it, + there was no disappointment whatsoever, and the tool worked as great as it + claims to be. There was nothing that I wanted to be improved. (of course I do + have some enhancement requests now + Smiley)
+
+ Why I think the tool is cool? Here are the answers:
+
+ Ease of use
+ - Amazingly easy to instrument your application, to apply the filters and get + going (thanks to the nice demos)
+ - Know AspectJ? You are ready to use this tool at once..
+ - If you understand how it works, you don't even need eclipse to instrument + your application. You can instrument it thru' your ant build script. Later use + Eclipse to view the generated diagrams.
+
+ Neat UI
+ - Neat and simple UI for sequence diagrams
+ - Easy to remove redundancy in diagrams
+ - Easy to filter out unnecessary
+
+ Performance
+ - Decent performance for an instrumented application (who cares anyways - this + is not in production)
+ - I used it with a quite big standalone application. Even big sequence + diagrams are not cluttered and thanks to the simplicity, there are no perf + issues in loading/rendering big diagrams
+ +
+ I have used TogetherJ to create static sequence diagrams from code - and was + disappointed because of the cluttered UI (even after lots of filtering, even + with just static analysis) and some fancy stuff.
+ Though I do not want to compare TogetherJ and MaintainJ as they are + functionally different (TogetherJ has lot more features than you can imagine), + from a developer's point of view (in a practical scenario) MaintainJ takes the + prize, thanks to
+ - runtime generation of sequence diagrams
+ - neat UI (come on, since when did developers need fancy UI??)
+
+ Congrats to Choudary for a really good job. I look forward to recommend + MaintainJ to my colleagues and friends.
+ +
+ Cheers,
+ Krishna Rajappa

+

+ +


+ +

+

A must tool to have

+ +I really like the idea behind MaintainJ. MaintainJ is using Aspect-oriented +programming, what it does mean is that there are no need for code changes, +MaintainJ will do the work for you.
+
+MaintainJ is easy to use, just add the AspectJ & MaintainJ plug-ins to your +eclipse, and create a MaintainJ project, then you are ready to go.
+
+MaintainJ creates sequence diagrams and class diagrams for all JAVA and J2EE +applications at the runtime, it is really easy to see the use case, it also +makes debugging easy.

+ +Nasser Alizadeh
+Ericsson Inc.
+

+ +


+

+

Nice and useful tool

+ +This is a very good tool, easy to setup and quickly get going. In a few minutes +I was able to get a sequence diagram to unravel a standalone app. + +

Javed Sujala +
eBay
+

+ +


+

+

A useful tool

+

I found MaintainJ by mistake and I hope I'll continue to make this kind of +mistakes. MaintainJ is a powerful tool that helps me in my work. It easy to +generate sequence diagram to understand a working application. It's not always +easy to modify an existing application without breaking something; with +MaintainJ you can accelerate the development if used correctly. +

+ +Good work!

+ +

+ +Sebastien Dionne
+Financiere Banque Nationale
+ +
+ +

+ +


+

A very neat tool

+

+I joined a new company recently. The code base is large but documentation is +sparse. I use the MaintainJ plug-in along with custom changes to the ant build +file (to weave the aspects using AspectJ ant task into the code) and lo behold +.... I had the sequence diagram for the particular workflow. Its nice to follow +the workflow from the ser file than stepping through via debugging.
+
+This is a splendid tool and keep up the good work.
+ +

Harjit Singh +
Barclays
+ +

+


+

+

A good find

+

+I looked to MaintainJ for use in an academic project, and found it very useful +for explaining the "magic happens" parts of a multi-threaded multi-hosted +application, to relatively inexperienced developers. I'd tried a few other +products that claimed to produce sequence diagrams, but this was the only one +that Just Works. It really made my day to find it. +

+Richard Barrington +


+

+ +

Very Useful Tool

+

I have used this tool recently on a J2EE project and found it to be very +useful, in particular the Sequence Diagrams. I look forward to downloading and +trying out the new version.

+

Thanks,
+Nasser Alhawash
+ +
+ +


+ +

The whole idea is really marvellous...

+

My manager has thrown me an assignment to customize a standalone Java +application which was developed in dirty and messy way. To make the things +worst, there is no documentation at all! I was having difficulties to understand +the code... and luckily, I found MaintainJ and it really help me a lot in +tracing and debugging the application. Many thanks to MaintainJ and Choudary!
+
+Among all the issues we discussed in MaintainJ forum, I'm very interested to see +if I'm able to export the diagrams to image files one day (which I'm still +encounter the OutOfMemoryException).
+
+I'm very interested to see MaintainJ evolves and becomes a stable product and I +hope to try out the next release very soon!

+ + +

wolverine.my

+ + +


+

Good work!

+

The whole idea is really marvelous, capturing runtime trace by AspectJ +without touching the source code. I especially like the idea of expanding and +collapsing the sequence, which can avoid messy diagrams.
+
+I have tried it under Eclipse 3.2 with AspectJ 1.5.2. I worked perfectly for +both standard Java application and Web Application.
+
+However, it cannot work under IBM's RAD (Rational Application Developer 6.0), +where eclipse is 3.0. That's not end of the world. Here is a word around. I +installed 1.2.2 AspectJ plug-in in RAD to be able to capture the runtime trace, +review and study the generate sequence diagrams and class diagrams under eclipse +3.2. Of course you gotta put AspectJ runtime and MaintainJAspect.jar in your web +project. It sounds inconvenience, but it really helps me in my work, maintaining +a quite complicated project.
+
+Good work, Choudary
+

+Charlie Liu
+on The Server Side +
+


+ +

A good plugin

+

+Recently, I found this plug-in and learnt to use it in my work. +It is ease to use and the runtime sequence diagram is very useful to me. +I use it with JADclipse. It helps me to read the source code quickly. +I think it is a great tool. I will spend time to try it in my another work. +I look forward to downloading and trying out the new version. +

+Chen Bin + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/userGuide.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/userGuide.html new file mode 100644 index 0000000..9080657 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/userGuide.html @@ -0,0 +1,11 @@ + + + +MaintainJ Inc. + + + + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/why.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/why.html new file mode 100644 index 0000000..b79da9a --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/why.html @@ -0,0 +1,11 @@ + + + +MaintainJ Inc. + + + + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/whyMaintainJ.html b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/whyMaintainJ.html new file mode 100644 index 0000000..53467b5 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/help/whyMaintainJ.html @@ -0,0 +1,117 @@ + + + +

2. Why should I use MaintainJ?

+ + + +Costs of software maintenance are well documented. + This compilation + puts maintenance cost at more than 90% of total software + cost. The same paper puts the cost of understanding the code at 50% of + maintenance cost.

+

+ + Currently there are no good tools to understand + enterprise scale Java applications. Most of the reverse engineering tools + generate the class diagrams, a static time view of the system. But when a + developer is changing code, he/she is more interested in knowing how + classes + interact at runtime for a single use case. + MaintainJ generates runtime sequence and class diagrams for a single use + case.

+ + + +

2.1 Why should managers be interested?

+ + + +

+ +Change is constant and everywhere - business + changes, development teams change, enhancements and bug fixes involve changes, interfacing with new applications need changes, etc.

+

Change involves risk. Understanding reduces risk. + MaintainJ significantly reduces the effort spent in understanding large + Java applications.

+

Typically, developers depend on debuggers to analyze + runtime interactions. Debuggers definitely help but diagrams are better + for the same reason that managers prefer graphs to numbers.

+ +
+

Most of the currently available reverse engineering + tools generate class diagrams and a static sequence diagrams. Generally, + the class diagrams generated are not for a single use case. They are more + for the entire system and are too cluttered to understand. Static sequence diagrams are generated from code and show the possible + call flows starting from a method. This helps to understand the code + structure to certain extent but do not help to understand the runtime + behavior.

+

MaintainJ generates runtime diagrams for a use case and that is what + developers crave for while debugging a complex Java application. + + + + + +

+In agile development environments, MaintainJ can also be used to generate always +up-to-date +UML documentation from code.

+

MaintainJ is based on open source +Eclipse project and works on any IDE that is built on Eclipse platform. + + + +

2.2 Why should developers be interested?

+ + + +Any developer who has ever tried to change a large + Java application should not need much persuasion. For the remaining few, +here are a few reasons :

Dynamic Binding - Dynamic or runtime binding +in Java makes understanding code more difficult. Developers often need to +understand the runtime object interactions for a specific use case either to +debug or enhance the application. Dynamic binding helps in building very +flexible systems but, at the same time it increases the time to understand the +system. It is also common to employ multiple levels of dynamic binding, like a +Vector containing another Vector, which further complicates the issue.

+

Observer Pattern - Many enterprise applications follow Observer +Pattern for flexibility, where 'listener' (or observer) objects change model +state besides 'listening' (or observing) for the state changes. When many +such listener objects, which are often determined at runtime, change the model, +it becomes hard to understand and debug a large application.

+

Multi-threaded Applications - Multi-threaded +applications are always difficult to code and debug. Using MaintainJ, one can +see the sequence of method calls happening in each thread in a neat sequence +diagram. This makes debugging multi-threaded applications much easier.

+

Externalized Data and Rules - Externalizing configuration data as well +as rule based logic to XML files is very commonly found in the present day Java +applications. Very often, the logic to determine the runtime classes is +soft-coded in xml files. In a not so well documented large-scale system, it is +very hard to understand how the xml file drive the system.

+

Poor Design - Designing robust and flexible systems at the same + time is hard. Maintaining them as the systems evolve is harder. If + poor design slips into this equation, it becomes very hard to understand a + system after 2-3 years from initial launch. +

+

Here are some other scenarios where + MaintainJ helps developers.

+

Complements Debugger - MaintainJ complements debugger rather than replacing it. By generating + the class and sequence diagrams for a use case, it reduces the time spent + in debugger. Unlike other reverse engineering tools, MaintainJ offers + uncluttered and focused UML  diagrams. For sequence diagrams, which + get cluttered very easily, MaintainJ offers features like call + folding to generate crisp diagrams.

+

During Code reviews - MaintainJ can also be used during code reviews. + Rather than reviewing the entire source code, one can review the diagrams + to find deviations from the design standards. Class diagrams + showing the dependencies help to weed out unwanted dependencies. + +

+

For Agile Teams - For agile programming teams, + MaintainJ provides always up-to-date documentation of the system. Useful + UML diagrams + can be generated whenever one needs them. + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/collapsed.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/collapsed.gif new file mode 100644 index 0000000..252d7eb Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/collapsed.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/expanded.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/expanded.gif new file mode 100644 index 0000000..ae09139 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/expanded.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/mnj.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/mnj.gif new file mode 100644 index 0000000..3555eba Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/icons/mnj.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/plugin.xml b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/plugin.xml new file mode 100644 index 0000000..faad4ff --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/plugin.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/properties/registration.properties b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/properties/registration.properties new file mode 100644 index 0000000..45f8bfe --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/properties/registration.properties @@ -0,0 +1,3 @@ +MergeWizard.1=Merge Failed +MergeWizard.2=Merge failed. Check the Eclipse error log for more information. +MaintainJRegnUrl= http://maintainj.com/license/register.jsp diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/samples/Alfresco_Login.ser b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/samples/Alfresco_Login.ser new file mode 100644 index 0000000..4cd53d2 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/samples/Alfresco_Login.ser differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/toc.xml b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/toc.xml new file mode 100644 index 0000000..bbb7859 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.inst.wizard_4.2.0/toc.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/AjPreProcessor.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/AjPreProcessor.jar new file mode 100644 index 0000000..fb1c3e5 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/AjPreProcessor.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/META-INF/MANIFEST.MF b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/META-INF/MANIFEST.MF new file mode 100644 index 0000000..f3a314f --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/META-INF/MANIFEST.MF @@ -0,0 +1,17 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: com.maintainj.launcher.core +Bundle-SymbolicName: com.maintainj.launcher.core;singleton:=true +Bundle-Version: 4.2.0 +Bundle-Vendor: MaintainJ Inc. +Bundle-Localization: plugin +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.debug.core, + org.eclipse.debug.ui, + org.eclipse.jdt.core, + org.eclipse.jface, + org.eclipse.jdt.launching +Bundle-Activator: com.maintainj.launching.core.MaintainJLauncherCorePlugin +Eclipse-LazyStart: true +Export-Package: com.maintainj.launching.core +Bundle-ClassPath: MaintainJLauncherCore.jar diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJAspect.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJAspect.jar new file mode 100644 index 0000000..8f9b688 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJAspect.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJAspect14.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJAspect14.jar new file mode 100644 index 0000000..856770c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJAspect14.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJLauncherCore.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJLauncherCore.jar new file mode 100644 index 0000000..9b1d749 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/MaintainJLauncherCore.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/aspectjweaver164.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/aspectjweaver164.jar new file mode 100644 index 0000000..51d24a5 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/aspectjweaver164.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/aspectwerkz-core-2.0.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/aspectwerkz-core-2.0.jar new file mode 100644 index 0000000..19ab01e Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/aspectwerkz-core-2.0.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/awaj-boot.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/awaj-boot.jar new file mode 100644 index 0000000..ae21b6a Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/awaj-boot.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/icons/mnj.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/icons/mnj.gif new file mode 100644 index 0000000..3555eba Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/icons/mnj.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/java14Adapter.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/java14Adapter.jar new file mode 100644 index 0000000..bfed59c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/java14Adapter.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/plugin.xml b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/plugin.xml new file mode 100644 index 0000000..30f3884 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.core_4.2.0/plugin.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/META-INF/MANIFEST.MF b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/META-INF/MANIFEST.MF new file mode 100644 index 0000000..404bb99 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: MaintainJ Launcher for J2SE and JUnit +Bundle-SymbolicName: com.maintainj.launcher.j2se;singleton:=true +Bundle-Version: 4.2.0 +Bundle-Activator: com.maintainj.launching.j2se.J2SELauncherPlugin +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.jdt.debug.ui, + org.eclipse.jdt.launching, + org.eclipse.debug.ui, + org.eclipse.debug.core, + org.eclipse.jdt.core, + org.eclipse.core.resources, + org.eclipse.jdt.junit, + com.maintainj.launcher.core +Eclipse-LazyStart: true +Bundle-ClassPath: MaintainJLauncher.jar +Bundle-Vendor: MaintainJ Inc. diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/MaintainJLauncher.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/MaintainJLauncher.jar new file mode 100644 index 0000000..3107857 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/MaintainJLauncher.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/icons/mnj.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/icons/mnj.gif new file mode 100644 index 0000000..3555eba Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/icons/mnj.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/plugin.properties b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/plugin.properties new file mode 100644 index 0000000..e69de29 diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/plugin.xml b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/plugin.xml new file mode 100644 index 0000000..f2c47c4 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.launcher.j2se_4.2.0/plugin.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/DiagramConfiguration.properties b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/DiagramConfiguration.properties new file mode 100644 index 0000000..3826181 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/DiagramConfiguration.properties @@ -0,0 +1,25 @@ +#Color properties of various lines, boxes +#The value must be in R,G,B format. Eclipse must be restarted for changes to take effect +ClassBoxColor=0,0,255 +ClassDiagramRelationColor=0,0,0 +PrivateCallColor=255,0,0 +ProtectedCallColor=255,215,0 +PublicCallColor=0,127,0 +MethodNameColor=0,0,255 +ThreadColors=255,0,0|0,0,255|0,127,0|153,51,255|255,0,255|0,0,0|153,204,0|150,50,0 + + +#For integration with Web Sequence Diagrams at http://www.websequencediagrams.com/ +EnableWebSequenceDiagrams=false +#The wsd_style may be changed to one of +#default,earth,modern-blue,mscgen,omegapple,qsd,rose,roundgreen,napkin +WSDFirstLine=

+WSDLastLine=
+ + +#Floating License Server Name(or IP adress) and Port values. +#These values can either be specified here or in Eclipse +#at File-> New-> Other-> MaintainJ-> Get License-> License Server Settings +MaintainJFloatingServerName= +MaintainJFloatingServerPort= + \ No newline at end of file diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/META-INF/MANIFEST.MF b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/META-INF/MANIFEST.MF new file mode 100644 index 0000000..1fb9102 --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/META-INF/MANIFEST.MF @@ -0,0 +1,25 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: com.maintainj.umlDiagram;singleton:=true +Bundle-Version: 4.2.0 +Bundle-Name: MaintainJ UML Diagram Editor Plug-in +Bundle-Activator: UMLDiagramPlugin +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Require-Bundle: org.eclipse.ui, + org.eclipse.ui.views, + org.eclipse.ui.ide, + org.eclipse.ui.editors, + org.eclipse.ui.workbench.texteditor, + org.eclipse.core.resources, + org.eclipse.core.runtime, + org.eclipse.search, + org.eclipse.gef, + org.eclipse.jdt.core, + org.eclipse.jdt.ui, + org.eclipse.jdt.launching, + org.eclipse.jface.text, + com.maintainj.core +Bundle-ClassPath: MaintainJEditor.jar +Bundle-Vendor: MaintainJ Inc. +Eclipse-LazyStart: true diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/MaintainJEditor.jar b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/MaintainJEditor.jar new file mode 100644 index 0000000..36d8bf4 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/MaintainJEditor.jar differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/allthreecollpase.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/allthreecollpase.png new file mode 100644 index 0000000..ed14706 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/allthreecollpase.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/allthreeexpand.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/allthreeexpand.png new file mode 100644 index 0000000..719446e Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/allthreeexpand.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/breadcrumb.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/breadcrumb.gif new file mode 100644 index 0000000..06b75a4 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/breadcrumb.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapseAll.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapseAll.gif new file mode 100644 index 0000000..0bae56c Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapseAll.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsed.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsed.gif new file mode 100644 index 0000000..252d7eb Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsed.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedarrow.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedarrow.png new file mode 100644 index 0000000..eda40a9 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedarrow.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedloop.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedloop.gif new file mode 100644 index 0000000..4ea95c9 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedloop.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedloop.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedloop.png new file mode 100644 index 0000000..6c6da98 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/collapsedloop.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/deletedAbove.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/deletedAbove.gif new file mode 100644 index 0000000..f0b0073 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/deletedAbove.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/deletedAbove.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/deletedAbove.png new file mode 100644 index 0000000..4fb48ec Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/deletedAbove.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandAll.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandAll.gif new file mode 100644 index 0000000..0205b29 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandAll.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expanded.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expanded.gif new file mode 100644 index 0000000..ae09139 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expanded.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandedarrow.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandedarrow.png new file mode 100644 index 0000000..7e4bda3 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandedarrow.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandedloop.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandedloop.gif new file mode 100644 index 0000000..19c8801 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/expandedloop.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/exportImage.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/exportImage.gif new file mode 100644 index 0000000..830be0e Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/exportImage.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/filter.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/filter.gif new file mode 100644 index 0000000..36f5b71 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/filter.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/loop.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/loop.gif new file mode 100644 index 0000000..0213bf2 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/loop.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/looparrow.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/looparrow.png new file mode 100644 index 0000000..3feed2d Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/looparrow.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/mnj.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/mnj.gif new file mode 100644 index 0000000..3555eba Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/mnj.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/pin.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/pin.gif new file mode 100644 index 0000000..381c4a9 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/pin.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/print.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/print.gif new file mode 100644 index 0000000..0c213c3 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/print.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/search.png b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/search.png new file mode 100644 index 0000000..f05bec8 Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/search.png differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/selectGetterSetter.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/selectGetterSetter.gif new file mode 100644 index 0000000..252d7eb Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/selectGetterSetter.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/threads.gif b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/threads.gif new file mode 100644 index 0000000..9ac596d Binary files /dev/null and b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/icons/threads.gif differ diff --git a/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/plugin.xml b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/plugin.xml new file mode 100644 index 0000000..aedcade --- /dev/null +++ b/Holmes/lib/MaintainJ_4.2.0/com.maintainj.umlDiagram_4.2.0/plugin.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Holmes/lib/aspectjweaver.jar b/Holmes/lib/aspectjweaver.jar new file mode 100644 index 0000000..db86336 Binary files /dev/null and b/Holmes/lib/aspectjweaver.jar differ diff --git a/Holmes/lib/aspectjweaver164.jar b/Holmes/lib/aspectjweaver164.jar new file mode 100644 index 0000000..51d24a5 Binary files /dev/null and b/Holmes/lib/aspectjweaver164.jar differ diff --git a/Holmes/lib/commons-exec-1.3/LICENSE.txt b/Holmes/lib/commons-exec-1.3/LICENSE.txt new file mode 100644 index 0000000..8b5861d --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/LICENSE.txt @@ -0,0 +1,203 @@ +/* + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright [yyyy] [name of copyright owner] + * + * 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. + */ diff --git a/Holmes/lib/commons-exec-1.3/NOTICE.txt b/Holmes/lib/commons-exec-1.3/NOTICE.txt new file mode 100644 index 0000000..129ce2d --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/NOTICE.txt @@ -0,0 +1,5 @@ +Apache Commons Exec +Copyright 2005-2014 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/Holmes/lib/commons-exec-1.3/RELEASE-NOTES.txt b/Holmes/lib/commons-exec-1.3/RELEASE-NOTES.txt new file mode 100644 index 0000000..ad8b480 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/RELEASE-NOTES.txt @@ -0,0 +1,87 @@ + Apache Commons Exec 1.3 RELEASE NOTES + +The Apache Commons Exec team is pleased to announce the commons-exec-1.3 release! + +Apache Commons Exec is a library to reliably execute external processes from within the JVM. + +Changes in this version include: + +New features: +o DefaultExecutor async execute prevents shutdown hooks running. + Issue: EXEC-69. Thanks to Richard Atkins, Michael Vorburger. + +Fixed Bugs: +o Remove remaining raw types, unchecked conversions + Issue: EXEC-81. Thanks to Stephen Compall. + +o NPE in EnvironmentUtils.toString(map) + Issue: EXEC-80. + +Changes: +o No need to use System.class.getMethod("getenv",...) any more + Issue: EXEC-78. + +o Update JUnit dependency to 4.11 + Issue: EXEC-77. + +o Update to Java 5 + Issue: EXEC-76. + + +Have fun! +-Apache Commons Exec team + + +------------------------------------------------------------------------------- + Apache Commons Exec 1.2 RELEASE NOTES + +The Apache Commons Exec team is pleased to announce the Apache commons-exec-1.2 release! + +Apache Commons Exec is a library to reliably execute external processes from within the JVM. + +Feature and fix release. Requires a minimum of Java 1.3. + +Changes in this version include: + +New features: + +o Set names for started threads. Issue: EXEC-55. Thanks to Dominik Stadler. + +Fixed Bugs: + +o Issue: EXEC-68. + Watchdog kills process immediately if timeout is too large. + Thanks to Joel McCance. + +o Issue: EXEC-57. + Applied the patch from Nickolay Martinov but the timeout disguises the fact that the process might be still running. + Therefore added a sanity check in order to throw an exception if the the timeout for join() was exceeded. + Thanks to Nickolay Martinov. + +o Issue: EXEC-60. + Fixed deadlock by calling the timeout observers outside of the synchronized block thereby removing a prerequisite of a deadlock. + Also added a test case to demonstrate that this problem is fixed (which of course can not guarantee the absence of a dead lock). + Thanks to Peter Kofler. + +o Issue: EXEC-52. + Tests fail on HP-UX, because it uses a different syntax for the ping command. + Thanks to Nickolay Martinov. + +o Issue: EXEC-49. + "Write dead end" IOException when using Piped streams w/PumpStreamHandler. + When encountering a PipedOutputStream we will automatically close it to avoid the exception. + Thanks to Kevin Telford. + +o Issue: EXEC-34. + Race condition prevent watchdog working using ExecuteStreamHandler. + Patch submittd by Kristian Rosenvold. + Thanks to Marco Ferrante. + +For complete information on Apache Commons Exec, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Commons Exec website: + +http://commons.apache.org/proper/commons-exec/ + + +Have fun! +-Apache Commons Exec team + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/allclasses-frame.html b/Holmes/lib/commons-exec-1.3/apidocs/allclasses-frame.html new file mode 100644 index 0000000..308790a --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/allclasses-frame.html @@ -0,0 +1,48 @@ + + + + + +All Classes (Apache Commons Exec 1.3 API) + + + +

All Classes

+ + + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/allclasses-noframe.html b/Holmes/lib/commons-exec-1.3/apidocs/allclasses-noframe.html new file mode 100644 index 0000000..ce60f66 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/allclasses-noframe.html @@ -0,0 +1,48 @@ + + + + + +All Classes (Apache Commons Exec 1.3 API) + + + +

All Classes

+ + + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/constant-values.html b/Holmes/lib/commons-exec-1.3/apidocs/constant-values.html new file mode 100644 index 0000000..f133e66 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/constant-values.html @@ -0,0 +1,210 @@ + + + + + +Constant Field Values (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Constant Field Values

+

Contents

+ +
+
+ + +

org.apache.*

+ + +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/deprecated-list.html b/Holmes/lib/commons-exec-1.3/apidocs/deprecated-list.html new file mode 100644 index 0000000..4a6d667 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/deprecated-list.html @@ -0,0 +1,165 @@ + + + + + +Deprecated List (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Deprecated API

+

Contents

+ +
+
+ + + + + + + +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/help-doc.html b/Holmes/lib/commons-exec-1.3/apidocs/help-doc.html new file mode 100644 index 0000000..d609faa --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/help-doc.html @@ -0,0 +1,220 @@ + + + + + +API Help (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

How This API Document Is Organized

+
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
+
+
+
    +
  • +

    Overview

    +

    The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.

    +
  • +
  • +

    Package

    +

    Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:

    +
      +
    • Interfaces (italic)
    • +
    • Classes
    • +
    • Enums
    • +
    • Exceptions
    • +
    • Errors
    • +
    • Annotation Types
    • +
    +
  • +
  • +

    Class/Interface

    +

    Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:

    +
      +
    • Class inheritance diagram
    • +
    • Direct Subclasses
    • +
    • All Known Subinterfaces
    • +
    • All Known Implementing Classes
    • +
    • Class/interface declaration
    • +
    • Class/interface description
    • +
    +
      +
    • Nested Class Summary
    • +
    • Field Summary
    • +
    • Constructor Summary
    • +
    • Method Summary
    • +
    +
      +
    • Field Detail
    • +
    • Constructor Detail
    • +
    • Method Detail
    • +
    +

    Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.

    +
  • +
  • +

    Annotation Type

    +

    Each annotation type has its own separate page with the following sections:

    +
      +
    • Annotation Type declaration
    • +
    • Annotation Type description
    • +
    • Required Element Summary
    • +
    • Optional Element Summary
    • +
    • Element Detail
    • +
    +
  • +
  • +

    Enum

    +

    Each enum has its own separate page with the following sections:

    +
      +
    • Enum declaration
    • +
    • Enum description
    • +
    • Enum Constant Summary
    • +
    • Enum Constant Detail
    • +
    +
  • +
  • +

    Use

    +

    Each documented package, class and interface has its own Use page. This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A. You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.

    +
  • +
  • +

    Tree (Class Hierarchy)

    +

    There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.

    +
      +
    • When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
    • +
    • When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
    • +
    +
  • +
  • +

    Deprecated API

    +

    The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.

    +
  • +
  • +

    Index

    +

    The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.

    +
  • +
  • +

    Prev/Next

    +

    These links take you to the next or previous class, interface, package, or related page.

    +
  • +
  • +

    Frames/No Frames

    +

    These links show and hide the HTML frames. All pages are available with or without frames.

    +
  • +
  • +

    All Classes

    +

    The All Classes link shows all classes and interfaces except non-static nested types.

    +
  • +
  • +

    Serialized Form

    +

    Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.

    +
  • +
  • +

    Constant Field Values

    +

    The Constant Field Values page lists the static final fields and their values.

    +
  • +
+This help file applies to API documentation generated using the standard doclet.
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/index-all.html b/Holmes/lib/commons-exec-1.3/apidocs/index-all.html new file mode 100644 index 0000000..0a075e9 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/index-all.html @@ -0,0 +1,1124 @@ + + + + + +Index (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
A C D E F G H I J K L M O P Q R S T V W  + + +

A

+
+
add(Process) - Method in interface org.apache.commons.exec.ProcessDestroyer
+
+
Returns true if the specified + Process was + successfully added to the list of processes to be destroy.
+
+
add(Process) - Method in class org.apache.commons.exec.ShutdownHookProcessDestroyer
+
+
Returns true if the specified Process was + successfully added to the list of processes to destroy upon VM exit.
+
+
addArgument(String) - Method in class org.apache.commons.exec.CommandLine
+
+
Add a single argument.
+
+
addArgument(String, boolean) - Method in class org.apache.commons.exec.CommandLine
+
+
Add a single argument.
+
+
addArguments(String[]) - Method in class org.apache.commons.exec.CommandLine
+
+
Add multiple arguments.
+
+
addArguments(String[], boolean) - Method in class org.apache.commons.exec.CommandLine
+
+
Add multiple arguments.
+
+
addArguments(String) - Method in class org.apache.commons.exec.CommandLine
+
+
Add multiple arguments.
+
+
addArguments(String, boolean) - Method in class org.apache.commons.exec.CommandLine
+
+
Add multiple arguments.
+
+
addTimeoutObserver(TimeoutObserver) - Method in class org.apache.commons.exec.Watchdog
+
 
+
addVariableToEnvironment(Map<String, String>, String) - Static method in class org.apache.commons.exec.environment.EnvironmentUtils
+
+
Add a key/value pair to the given environment.
+
+
+ + + +

C

+
+
checkException() - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
This method will rethrow the exception that was possibly caught during + the run of the process.
+
+
cleanUp() - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
reset the monitor flag and the process.
+
+
close() - Method in class org.apache.commons.exec.LogOutputStream
+
+
Writes all remaining data from the buffer.
+
+
CommandLauncher - Interface in org.apache.commons.exec.launcher
+
+
Interface to shield the caller from the various platform-dependent + implementations.
+
+
CommandLauncherFactory - Class in org.apache.commons.exec.launcher
+
+
Builds a command launcher for the OS and JVM we are running under.
+
+
CommandLauncherImpl - Class in org.apache.commons.exec.launcher
+
+
A command launcher for a particular JVM/OS platform.
+
+
CommandLauncherImpl() - Constructor for class org.apache.commons.exec.launcher.CommandLauncherImpl
+
 
+
CommandLauncherProxy - Class in org.apache.commons.exec.launcher
+
+
A command launcher that proxies another command launcher.
+
+
CommandLauncherProxy(CommandLauncher) - Constructor for class org.apache.commons.exec.launcher.CommandLauncherProxy
+
 
+
CommandLine - Class in org.apache.commons.exec
+
+
CommandLine objects help handling command lines specifying processes to + execute.
+
+
CommandLine(String) - Constructor for class org.apache.commons.exec.CommandLine
+
+
Create a command line without any arguments.
+
+
CommandLine(File) - Constructor for class org.apache.commons.exec.CommandLine
+
+
Create a command line without any arguments.
+
+
CommandLine(CommandLine) - Constructor for class org.apache.commons.exec.CommandLine
+
+
Copy constructor.
+
+
COMMONS_EXEC_DEBUG - Static variable in class org.apache.commons.exec.util.DebugUtils
+
+
System property to determine how to dump an exception.
+
+
COMMONS_EXEC_LENIENT - Static variable in class org.apache.commons.exec.util.DebugUtils
+
+
System property to determine how to handle exceptions.
+
+
copy(Map<K, V>) - Static method in class org.apache.commons.exec.util.MapUtils
+
+
Clones a map.
+
+
createProcEnvironment() - Method in class org.apache.commons.exec.environment.DefaultProcessingEnvironment
+
+
Find the list of environment variables for this process.
+
+
createProcessErrorPump(InputStream, OutputStream) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Create the pump to handle error output.
+
+
createProcessOutputPump(InputStream, OutputStream) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Create the pump to handle process output.
+
+
createPump(InputStream, OutputStream) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Creates a stream pumper to copy the given input stream to the given + output stream.
+
+
createPump(InputStream, OutputStream, boolean) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Creates a stream pumper to copy the given input stream to the given + output stream.
+
+
createThread(Runnable, String) - Method in class org.apache.commons.exec.DaemonExecutor
+
+
Factory method to create a thread waiting for the result of an asynchronous execution.
+
+
createThread(Runnable, String) - Method in class org.apache.commons.exec.DefaultExecutor
+
+
Factory method to create a thread waiting for the result of an + asynchronous execution.
+
+
createVMLauncher() - Static method in class org.apache.commons.exec.launcher.CommandLauncherFactory
+
+
Factory method to create an appropriate launcher.
+
+
+ + + +

D

+
+
DaemonExecutor - Class in org.apache.commons.exec
+
+
Runs daemon processes asynchronously.
+
+
DaemonExecutor() - Constructor for class org.apache.commons.exec.DaemonExecutor
+
 
+
DebugUtils - Class in org.apache.commons.exec.util
+
+
Provides debugging support.
+
+
DebugUtils() - Constructor for class org.apache.commons.exec.util.DebugUtils
+
 
+
DefaultExecuteResultHandler - Class in org.apache.commons.exec
+
+
A default implementation of 'ExecuteResultHandler' used for asynchronous + process handling.
+
+
DefaultExecuteResultHandler() - Constructor for class org.apache.commons.exec.DefaultExecuteResultHandler
+
+
Constructor.
+
+
DefaultExecutor - Class in org.apache.commons.exec
+
+
The default class to start a subprocess.
+
+
DefaultExecutor() - Constructor for class org.apache.commons.exec.DefaultExecutor
+
+
Default constructor creating a default PumpStreamHandler + and sets the working directory of the subprocess to the current + working directory.
+
+
DefaultProcessingEnvironment - Class in org.apache.commons.exec.environment
+
+
Helper class to determine the environment variable + for the OS.
+
+
DefaultProcessingEnvironment() - Constructor for class org.apache.commons.exec.environment.DefaultProcessingEnvironment
+
 
+
destroyProcess() - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
Destroys the running process manually.
+
+
+ + + +

E

+
+
EnvironmentUtils - Class in org.apache.commons.exec.environment
+
+
Wrapper for environment variables.
+
+
exec(CommandLine, Map<String, String>) - Method in interface org.apache.commons.exec.launcher.CommandLauncher
+
+
Launches the given command in a new process.
+
+
exec(CommandLine, Map<String, String>, File) - Method in interface org.apache.commons.exec.launcher.CommandLauncher
+
+
Launches the given command in a new process, in the given working + directory.
+
+
exec(CommandLine, Map<String, String>) - Method in class org.apache.commons.exec.launcher.CommandLauncherImpl
+
 
+
exec(CommandLine, Map<String, String>, File) - Method in class org.apache.commons.exec.launcher.CommandLauncherImpl
+
 
+
exec(CommandLine, Map<String, String>) - Method in class org.apache.commons.exec.launcher.CommandLauncherProxy
+
+
Launches the given command in a new process.
+
+
exec(CommandLine, Map<String, String>, File) - Method in class org.apache.commons.exec.launcher.Java13CommandLauncher
+
+
Launches the given command in a new process, in the given working + directory
+
+
exec(CommandLine, Map<String, String>, File) - Method in class org.apache.commons.exec.launcher.OS2CommandLauncher
+
+
Launches the given command in a new process, in the given working + directory.
+
+
exec(CommandLine, Map<String, String>) - Method in class org.apache.commons.exec.launcher.VmsCommandLauncher
+
+
Launches the given command in a new process.
+
+
exec(CommandLine, Map<String, String>, File) - Method in class org.apache.commons.exec.launcher.VmsCommandLauncher
+
+
Launches the given command in a new process, in the given working + directory.
+
+
exec(CommandLine, Map<String, String>, File) - Method in class org.apache.commons.exec.launcher.WinNTCommandLauncher
+
+
Launches the given command in a new process, in the given working + directory.
+
+
execute(CommandLine) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
execute(CommandLine, Map<String, String>) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
execute(CommandLine, ExecuteResultHandler) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
execute(CommandLine, Map<String, String>, ExecuteResultHandler) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
execute(CommandLine) - Method in interface org.apache.commons.exec.Executor
+
+
Methods for starting synchronous execution.
+
+
execute(CommandLine, Map<String, String>) - Method in interface org.apache.commons.exec.Executor
+
+
Methods for starting synchronous execution.
+
+
execute(CommandLine, ExecuteResultHandler) - Method in interface org.apache.commons.exec.Executor
+
+
Methods for starting asynchronous execution.
+
+
execute(CommandLine, Map<String, String>, ExecuteResultHandler) - Method in interface org.apache.commons.exec.Executor
+
+
Methods for starting asynchronous execution.
+
+
ExecuteException - Exception in org.apache.commons.exec
+
+
An exception indicating that the executing a subprocesses failed.
+
+
ExecuteException(String, int) - Constructor for exception org.apache.commons.exec.ExecuteException
+
+
Construct a new exception with the specified detail message.
+
+
ExecuteException(String, int, Throwable) - Constructor for exception org.apache.commons.exec.ExecuteException
+
+
Construct a new exception with the specified detail message and cause.
+
+
ExecuteResultHandler - Interface in org.apache.commons.exec
+
+
The callback handlers for the result of asynchronous process execution.
+
+
ExecuteStreamHandler - Interface in org.apache.commons.exec
+
+
Used by Execute to handle input and output stream of + subprocesses.
+
+
ExecuteWatchdog - Class in org.apache.commons.exec
+
+
Destroys a process running for too long.
+
+
ExecuteWatchdog(long) - Constructor for class org.apache.commons.exec.ExecuteWatchdog
+
+
Creates a new watchdog with a given timeout.
+
+
Executor - Interface in org.apache.commons.exec
+
+
The main abstraction to start an external process.
+
+
+ + + +

F

+
+
fireTimeoutOccured() - Method in class org.apache.commons.exec.Watchdog
+
 
+
fixFileSeparatorChar(String) - Static method in class org.apache.commons.exec.util.StringUtils
+
+
Fixes the file separator char for the target platform + using the following replacement.
+
+
flush() - Method in class org.apache.commons.exec.LogOutputStream
+
+
Flush this log stream.
+
+
+ + + +

G

+
+
getArguments() - Method in class org.apache.commons.exec.CommandLine
+
+
Returns the expanded and quoted command line arguments.
+
+
getCause() - Method in exception org.apache.commons.exec.ExecuteException
+
+
Return the underlying cause of this exception (if any).
+
+
getErr() - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Get the error stream.
+
+
getException() - Method in class org.apache.commons.exec.DefaultExecuteResultHandler
+
+
Get the exception causing the process execution to fail.
+
+
getExecutable() - Method in class org.apache.commons.exec.CommandLine
+
+
Returns the executable.
+
+
getExecutorThread() - Method in class org.apache.commons.exec.DefaultExecutor
+
+
Get the worker thread being used for asynchronous execution.
+
+
getExitValue() - Method in class org.apache.commons.exec.DefaultExecuteResultHandler
+
+
Get the exitValue of the process.
+
+
getExitValue() - Method in exception org.apache.commons.exec.ExecuteException
+
+
Gets the exit value returned by the failed process
+
+
getMessageLevel() - Method in class org.apache.commons.exec.LogOutputStream
+
 
+
getOut() - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Get the output stream.
+
+
getProcEnvCommand() - Method in class org.apache.commons.exec.environment.DefaultProcessingEnvironment
+
+
Deprecated. +
No longer needed
+
+
+
getProcEnvironment() - Method in class org.apache.commons.exec.environment.DefaultProcessingEnvironment
+
+
Find the list of environment variables for this process.
+
+
getProcEnvironment() - Static method in class org.apache.commons.exec.environment.EnvironmentUtils
+
+
Find the list of environment variables for this process.
+
+
getProcessDestroyer() - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
getProcessDestroyer() - Method in interface org.apache.commons.exec.Executor
+
+
Set the handler for cleanup of started processes if the main process + is going to terminate.
+
+
getStreamHandler() - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
getStreamHandler() - Method in interface org.apache.commons.exec.Executor
+
+
Get the StreamHandler used for providing input and + retrieving the output.
+
+
getSubstitutionMap() - Method in class org.apache.commons.exec.CommandLine
+
 
+
getWatchdog() - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
getWatchdog() - Method in interface org.apache.commons.exec.Executor
+
+
Get the watchdog used to kill of processes running, + typically, too long time.
+
+
getWorkingDirectory() - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
getWorkingDirectory() - Method in interface org.apache.commons.exec.Executor
+
+
Get the working directory of the created process.
+
+
+ + + +

H

+
+
handleException(String, Exception) - Static method in class org.apache.commons.exec.util.DebugUtils
+
+
Handles an exception based on the system properties.
+
+
hasResult() - Method in class org.apache.commons.exec.DefaultExecuteResultHandler
+
+
Has the process exited and a result is available, i.e.
+
+
+ + + +

I

+
+
INFINITE_TIMEOUT - Static variable in class org.apache.commons.exec.ExecuteWatchdog
+
+
The marker for an infinite timeout
+
+
InputStreamPumper - Class in org.apache.commons.exec
+
+
Copies all data from an System.input stream to an output stream of the executed process.
+
+
InputStreamPumper(InputStream, OutputStream) - Constructor for class org.apache.commons.exec.InputStreamPumper
+
+
Create a new stream pumper.
+
+
INVALID_EXITVALUE - Static variable in interface org.apache.commons.exec.Executor
+
+
Invalid exit code.
+
+
isAddedAsShutdownHook() - Method in class org.apache.commons.exec.ShutdownHookProcessDestroyer
+
+
Returns whether or not the ProcessDestroyer is registered as as shutdown + hook
+
+
isArch(String) - Static method in class org.apache.commons.exec.OS
+
+
Determines if the OS on which Ant is executing matches the given OS + architecture.
+
+
isDebugEnabled() - Static method in class org.apache.commons.exec.util.DebugUtils
+
+
Determines if debugging is enabled based on the + system property "COMMONS_EXEC_DEBUG".
+
+
isFailure(int) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
isFailure(int) - Method in interface org.apache.commons.exec.Executor
+
+
Checks whether exitValue signals a failure.
+
+
isFailure(int) - Method in interface org.apache.commons.exec.launcher.CommandLauncher
+
+
Checks whether exitValue signals a failure on the current + system (OS specific).
+
+
isFailure(int) - Method in class org.apache.commons.exec.launcher.CommandLauncherImpl
+
 
+
isFailure(int) - Method in class org.apache.commons.exec.launcher.VmsCommandLauncher
+
 
+
isFamilyDOS() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyMac() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyNetware() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyOpenVms() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyOS2() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyOS400() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyTandem() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyUnix() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyWin9x() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyWindows() - Static method in class org.apache.commons.exec.OS
+
 
+
isFamilyZOS() - Static method in class org.apache.commons.exec.OS
+
 
+
isFile() - Method in class org.apache.commons.exec.CommandLine
+
+
Was a file being used to set the executable?
+
+
isFinished() - Method in class org.apache.commons.exec.StreamPumper
+
+
Tells whether the end of the stream has been reached.
+
+
isLenientEnabled() - Static method in class org.apache.commons.exec.util.DebugUtils
+
+
Determines if lenient mode is enabled.
+
+
isName(String) - Static method in class org.apache.commons.exec.OS
+
+
Determines if the OS on which Ant is executing matches the given OS name.
+
+
isOs(String, String, String, String) - Static method in class org.apache.commons.exec.OS
+
+
Determines if the OS on which Ant is executing matches the given OS + family, name, architecture and version
+
+
isQuoted(String) - Static method in class org.apache.commons.exec.util.StringUtils
+
+
Determines if this is a quoted argument - either single or + double quoted.
+
+
isVersion(String) - Static method in class org.apache.commons.exec.OS
+
+
Determines if the OS on which Ant is executing matches the given OS + version.
+
+
isWatching() - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
Indicates whether or not the watchdog is still monitoring the process.
+
+
+ + + +

J

+
+
Java13CommandLauncher - Class in org.apache.commons.exec.launcher
+
+
A command launcher for JDK/JRE 1.3 (and higher).
+
+
Java13CommandLauncher() - Constructor for class org.apache.commons.exec.launcher.Java13CommandLauncher
+
+
Constructor
+
+
+ + + +

K

+
+
killedProcess() - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
Indicates whether the last process run was killed.
+
+
+ + + +

L

+
+
launch(CommandLine, Map<String, String>, File) - Method in class org.apache.commons.exec.DefaultExecutor
+
+
Creates a process that runs a command.
+
+
LogOutputStream - Class in org.apache.commons.exec
+
+
Base class to connect a logging system to the output and/or + error stream of then external process.
+
+
LogOutputStream() - Constructor for class org.apache.commons.exec.LogOutputStream
+
+
Creates a new instance of this class.
+
+
LogOutputStream(int) - Constructor for class org.apache.commons.exec.LogOutputStream
+
+
Creates a new instance of this class.
+
+
+ + + +

M

+
+
MapUtils - Class in org.apache.commons.exec.util
+
+
Helper classes to manipulate maps to pass substition map to the CommandLine.
+
+
MapUtils() - Constructor for class org.apache.commons.exec.util.MapUtils
+
 
+
merge(Map<K, V>, Map<K, V>) - Static method in class org.apache.commons.exec.util.MapUtils
+
+
Clones the lhs map and add all things from the rhs map.
+
+
+ + + +

O

+
+
onProcessComplete(int) - Method in class org.apache.commons.exec.DefaultExecuteResultHandler
+
 
+
onProcessComplete(int) - Method in interface org.apache.commons.exec.ExecuteResultHandler
+
+
The asynchronous execution completed.
+
+
onProcessFailed(ExecuteException) - Method in class org.apache.commons.exec.DefaultExecuteResultHandler
+
 
+
onProcessFailed(ExecuteException) - Method in interface org.apache.commons.exec.ExecuteResultHandler
+
+
The asynchronous execution failed.
+
+
OpenVmsProcessingEnvironment - Class in org.apache.commons.exec.environment
+
+
Deprecated. +
No longer needed
+
+
+
OpenVmsProcessingEnvironment() - Constructor for class org.apache.commons.exec.environment.OpenVmsProcessingEnvironment
+
+
Deprecated.
+
org.apache.commons.exec - package org.apache.commons.exec
+
 
+
org.apache.commons.exec.environment - package org.apache.commons.exec.environment
+
 
+
org.apache.commons.exec.launcher - package org.apache.commons.exec.launcher
+
 
+
org.apache.commons.exec.util - package org.apache.commons.exec.util
+
 
+
OS - Class in org.apache.commons.exec
+
+
Condition that tests the OS type.
+
+
OS2CommandLauncher - Class in org.apache.commons.exec.launcher
+
+
A command launcher for OS/2 that uses 'cmd.exe' when launching commands in + directories other than the current working directory.
+
+
OS2CommandLauncher(CommandLauncher) - Constructor for class org.apache.commons.exec.launcher.OS2CommandLauncher
+
 
+
+ + + +

P

+
+
parse(String) - Static method in class org.apache.commons.exec.CommandLine
+
+
Create a command line from a string.
+
+
parse(String, Map<String, ?>) - Static method in class org.apache.commons.exec.CommandLine
+
+
Create a command line from a string.
+
+
prefix(Map<K, V>, String) - Static method in class org.apache.commons.exec.util.MapUtils
+
+
Clones a map and prefixes the keys in the clone, e.g.
+
+
procEnvironment - Variable in class org.apache.commons.exec.environment.DefaultProcessingEnvironment
+
+
the environment variables of the process
+
+
processBuffer() - Method in class org.apache.commons.exec.LogOutputStream
+
+
Converts the buffer to a string and sends it to processLine.
+
+
ProcessDestroyer - Interface in org.apache.commons.exec
+
+
Destroys all registered Process after a certain event, + typically when the VM exits
+
+
processLine(String) - Method in class org.apache.commons.exec.LogOutputStream
+
+
Logs a line to the log system of the user.
+
+
processLine(String, int) - Method in class org.apache.commons.exec.LogOutputStream
+
+
Logs a line to the log system of the user.
+
+
PumpStreamHandler - Class in org.apache.commons.exec
+
+
Copies standard output and error of sub-processes to standard output and error + of the parent process.
+
+
PumpStreamHandler() - Constructor for class org.apache.commons.exec.PumpStreamHandler
+
+
Construct a new PumpStreamHandler.
+
+
PumpStreamHandler(OutputStream) - Constructor for class org.apache.commons.exec.PumpStreamHandler
+
+
Construct a new PumpStreamHandler.
+
+
PumpStreamHandler(OutputStream, OutputStream) - Constructor for class org.apache.commons.exec.PumpStreamHandler
+
+
Construct a new PumpStreamHandler.
+
+
PumpStreamHandler(OutputStream, OutputStream, InputStream) - Constructor for class org.apache.commons.exec.PumpStreamHandler
+
+
Construct a new PumpStreamHandler.
+
+
+ + + +

Q

+
+
quoteArgument(String) - Static method in class org.apache.commons.exec.util.StringUtils
+
+
Put quotes around the given String if necessary.
+
+
+ + + +

R

+
+
remove(Process) - Method in interface org.apache.commons.exec.ProcessDestroyer
+
+
Returns true if the specified + Process was + successfully removed from the list of processes to be destroy.
+
+
remove(Process) - Method in class org.apache.commons.exec.ShutdownHookProcessDestroyer
+
+
Returns true if the specified Process was + successfully removed from the list of processes to destroy upon VM exit.
+
+
removeTimeoutObserver(TimeoutObserver) - Method in class org.apache.commons.exec.Watchdog
+
 
+
run() - Method in class org.apache.commons.exec.InputStreamPumper
+
+
Copies data from the input stream to the output stream.
+
+
run() - Method in class org.apache.commons.exec.ShutdownHookProcessDestroyer
+
+
Invoked by the VM when it is exiting.
+
+
run() - Method in class org.apache.commons.exec.StreamPumper
+
+
Copies data from the input stream to the output stream.
+
+
run() - Method in class org.apache.commons.exec.Watchdog
+
 
+
runProcEnvCommand() - Method in class org.apache.commons.exec.environment.DefaultProcessingEnvironment
+
+
Deprecated. +
No longer needed
+
+
+
+ + + +

S

+
+
setExitValue(int) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
setExitValue(int) - Method in interface org.apache.commons.exec.Executor
+
+
Define the exitValue of the process to be considered + successful.
+
+
setExitValues(int[]) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
setExitValues(int[]) - Method in interface org.apache.commons.exec.Executor
+
+
Define a list of exitValue of the process to be considered + successful.
+
+
setProcessDestroyer(ProcessDestroyer) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
setProcessDestroyer(ProcessDestroyer) - Method in interface org.apache.commons.exec.Executor
+
+
Get the handler for cleanup of started processes if the main process + is going to terminate.
+
+
setProcessErrorStream(InputStream) - Method in interface org.apache.commons.exec.ExecuteStreamHandler
+
+
Install a handler for the error stream of the subprocess.
+
+
setProcessErrorStream(InputStream) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Set the InputStream from which to read the standard error + of the process.
+
+
setProcessInputStream(OutputStream) - Method in interface org.apache.commons.exec.ExecuteStreamHandler
+
+
Install a handler for the input stream of the subprocess.
+
+
setProcessInputStream(OutputStream) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Set the OutputStream by means of which input can be sent + to the process.
+
+
setProcessOutputStream(InputStream) - Method in interface org.apache.commons.exec.ExecuteStreamHandler
+
+
Install a handler for the output stream of the subprocess.
+
+
setProcessOutputStream(InputStream) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Set the InputStream from which to read the standard output + of the process.
+
+
setStopTimeout(long) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Set maximum time to wait until output streams are exchausted + when PumpStreamHandler.stop() was called.
+
+
setStreamHandler(ExecuteStreamHandler) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
setStreamHandler(ExecuteStreamHandler) - Method in interface org.apache.commons.exec.Executor
+
+
Set a custom the StreamHandler used for providing + input and retrieving the output.
+
+
setSubstitutionMap(Map<String, ?>) - Method in class org.apache.commons.exec.CommandLine
+
+
Set the substitutionMap to expand variables in the + command line.
+
+
setWatchdog(ExecuteWatchdog) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
setWatchdog(ExecuteWatchdog) - Method in interface org.apache.commons.exec.Executor
+
+
Set the watchdog used to kill of processes running, + typically, too long time.
+
+
setWorkingDirectory(File) - Method in class org.apache.commons.exec.DefaultExecutor
+
 
+
setWorkingDirectory(File) - Method in interface org.apache.commons.exec.Executor
+
+
Set the working directory of the created process.
+
+
ShutdownHookProcessDestroyer - Class in org.apache.commons.exec
+
+
Destroys all registered Processes when the VM exits.
+
+
ShutdownHookProcessDestroyer() - Constructor for class org.apache.commons.exec.ShutdownHookProcessDestroyer
+
+
Constructs a ProcessDestroyer and obtains + Runtime.addShutdownHook() and + Runtime.removeShutdownHook() through reflection.
+
+
size() - Method in interface org.apache.commons.exec.ProcessDestroyer
+
+
Returns the number of registered processes.
+
+
size() - Method in class org.apache.commons.exec.ShutdownHookProcessDestroyer
+
+
Returns the number of registered processes.
+
+
SLEEPING_TIME - Static variable in class org.apache.commons.exec.InputStreamPumper
+
 
+
split(String, String) - Static method in class org.apache.commons.exec.util.StringUtils
+
+
Split a string into an array of strings based + on a separator.
+
+
start() - Method in interface org.apache.commons.exec.ExecuteStreamHandler
+
+
Start handling of the streams.
+
+
start(Process) - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
Watches the given process and terminates it, if it runs for too long.
+
+
start() - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Start the Threads.
+
+
start() - Method in class org.apache.commons.exec.Watchdog
+
 
+
stop() - Method in interface org.apache.commons.exec.ExecuteStreamHandler
+
+
Stop handling of the streams - will not be restarted.
+
+
stop() - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
Stops the watcher.
+
+
stop() - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Stop pumping the streams.
+
+
stop() - Method in class org.apache.commons.exec.Watchdog
+
 
+
stopProcessing() - Method in class org.apache.commons.exec.InputStreamPumper
+
 
+
stopThread(Thread, long) - Method in class org.apache.commons.exec.PumpStreamHandler
+
+
Stopping a pumper thread.
+
+
StreamPumper - Class in org.apache.commons.exec
+
+
Copies all data from an input stream to an output stream.
+
+
StreamPumper(InputStream, OutputStream, boolean) - Constructor for class org.apache.commons.exec.StreamPumper
+
+
Create a new stream pumper.
+
+
StreamPumper(InputStream, OutputStream, boolean, int) - Constructor for class org.apache.commons.exec.StreamPumper
+
+
Create a new stream pumper.
+
+
StreamPumper(InputStream, OutputStream) - Constructor for class org.apache.commons.exec.StreamPumper
+
+
Create a new stream pumper.
+
+
stringSubstitution(String, Map<? super String, ?>, boolean) - Static method in class org.apache.commons.exec.util.StringUtils
+
+
Perform a series of substitutions.
+
+
StringUtils - Class in org.apache.commons.exec.util
+
+
Supplement of commons-lang, the stringSubstitution() was in a simpler + implementation available in an older commons-lang implementation.
+
+
StringUtils() - Constructor for class org.apache.commons.exec.util.StringUtils
+
 
+
+ + + +

T

+
+
TimeoutObserver - Interface in org.apache.commons.exec
+
+
Interface for classes that want to be notified by Watchdog.
+
+
timeoutOccured(Watchdog) - Method in class org.apache.commons.exec.ExecuteWatchdog
+
+
Called after watchdog has finished.
+
+
timeoutOccured(Watchdog) - Method in interface org.apache.commons.exec.TimeoutObserver
+
+
Called when the watchdog times out.
+
+
toString() - Method in class org.apache.commons.exec.CommandLine
+
+
Stringify operator returns the command line as a string.
+
+
toString(String[], String) - Static method in class org.apache.commons.exec.util.StringUtils
+
+
Concatenates an array of string using a separator.
+
+
toStrings() - Method in class org.apache.commons.exec.CommandLine
+
+
Returns the command line as an array of strings.
+
+
toStrings(Map<String, String>) - Static method in class org.apache.commons.exec.environment.EnvironmentUtils
+
+
Get the variable list as an array.
+
+
+ + + +

V

+
+
VmsCommandLauncher - Class in org.apache.commons.exec.launcher
+
+
A command launcher for VMS that writes the command to a temporary DCL script + before launching commands.
+
+
VmsCommandLauncher() - Constructor for class org.apache.commons.exec.launcher.VmsCommandLauncher
+
 
+
+ + + +

W

+
+
waitFor() - Method in class org.apache.commons.exec.DefaultExecuteResultHandler
+
+
Causes the current thread to wait, if necessary, until the + process has terminated.
+
+
waitFor(long) - Method in class org.apache.commons.exec.DefaultExecuteResultHandler
+
+
Causes the current thread to wait, if necessary, until the + process has terminated.
+
+
waitFor() - Method in class org.apache.commons.exec.StreamPumper
+
+
This method blocks until the stream pumper finishes.
+
+
Watchdog - Class in org.apache.commons.exec
+
+
Generalization of ExecuteWatchdog
+
+
Watchdog(long) - Constructor for class org.apache.commons.exec.Watchdog
+
 
+
WinNTCommandLauncher - Class in org.apache.commons.exec.launcher
+
+
A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when launching + commands in directories other than the current working directory.
+
+
WinNTCommandLauncher(CommandLauncher) - Constructor for class org.apache.commons.exec.launcher.WinNTCommandLauncher
+
 
+
write(int) - Method in class org.apache.commons.exec.LogOutputStream
+
+
Write the data to the buffer and flush the buffer, if a line separator is + detected.
+
+
write(byte[], int, int) - Method in class org.apache.commons.exec.LogOutputStream
+
+
Write a block of characters to the output stream
+
+
+A C D E F G H I J K L M O P Q R S T V W 
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/index.html b/Holmes/lib/commons-exec-1.3/apidocs/index.html new file mode 100644 index 0000000..14ce661 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/index.html @@ -0,0 +1,74 @@ + + + + + +Apache Commons Exec 1.3 API + + + + + + + + + +<noscript> +<div>JavaScript is disabled on your browser.</div> +</noscript> +<h2>Frame Alert</h2> +<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> + + + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/CommandLine.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/CommandLine.html new file mode 100644 index 0000000..4966247 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/CommandLine.html @@ -0,0 +1,568 @@ + + + + + +CommandLine (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class CommandLine

+
+
+ +
+
    +
  • +
    +
    +
    public class CommandLine
    +extends Object
    +
    CommandLine objects help handling command lines specifying processes to + execute. The class can be used to a command line by an application.
    +
    Version:
    +
    $Id: CommandLine.java 1613094 2014-07-24 12:20:14Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        CommandLine

        +
        public CommandLine(String executable)
        +
        Create a command line without any arguments.
        +
        Parameters:
        executable - the executable
        +
      • +
      + + + +
        +
      • +

        CommandLine

        +
        public CommandLine(File executable)
        +
        Create a command line without any arguments.
        +
        Parameters:
        executable - the executable file
        +
      • +
      + + + +
        +
      • +

        CommandLine

        +
        public CommandLine(CommandLine other)
        +
        Copy constructor.
        +
        Parameters:
        other - the instance to copy
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        parse

        +
        public static CommandLine parse(String line)
        +
        Create a command line from a string.
        +
        Parameters:
        line - the first element becomes the executable, the rest the arguments
        +
        Returns:
        the parsed command line
        +
        Throws:
        +
        IllegalArgumentException - If line is null or all whitespace
        +
      • +
      + + + +
        +
      • +

        parse

        +
        public static CommandLine parse(String line,
        +                Map<String,?> substitutionMap)
        +
        Create a command line from a string.
        +
        Parameters:
        line - the first element becomes the executable, the rest the arguments
        substitutionMap - the name/value pairs used for substitution
        +
        Returns:
        the parsed command line
        +
        Throws:
        +
        IllegalArgumentException - If line is null or all whitespace
        +
      • +
      + + + +
        +
      • +

        getExecutable

        +
        public String getExecutable()
        +
        Returns the executable.
        +
        Returns:
        The executable
        +
      • +
      + + + +
        +
      • +

        isFile

        +
        public boolean isFile()
        +
        Was a file being used to set the executable?
        +
        Returns:
        true if a file was used for setting the executable
        +
      • +
      + + + +
        +
      • +

        addArguments

        +
        public CommandLine addArguments(String[] addArguments)
        +
        Add multiple arguments. Handles parsing of quotes and whitespace.
        +
        Parameters:
        addArguments - An array of arguments
        +
        Returns:
        The command line itself
        +
      • +
      + + + +
        +
      • +

        addArguments

        +
        public CommandLine addArguments(String[] addArguments,
        +                       boolean handleQuoting)
        +
        Add multiple arguments.
        +
        Parameters:
        addArguments - An array of arguments
        handleQuoting - Add the argument with/without handling quoting
        +
        Returns:
        The command line itself
        +
      • +
      + + + +
        +
      • +

        addArguments

        +
        public CommandLine addArguments(String addArguments)
        +
        Add multiple arguments. Handles parsing of quotes and whitespace. + Please note that the parsing can have undesired side-effects therefore + it is recommended to build the command line incrementally.
        +
        Parameters:
        addArguments - An string containing multiple arguments.
        +
        Returns:
        The command line itself
        +
      • +
      + + + +
        +
      • +

        addArguments

        +
        public CommandLine addArguments(String addArguments,
        +                       boolean handleQuoting)
        +
        Add multiple arguments. Handles parsing of quotes and whitespace. + Please note that the parsing can have undesired side-effects therefore + it is recommended to build the command line incrementally.
        +
        Parameters:
        addArguments - An string containing multiple arguments.
        handleQuoting - Add the argument with/without handling quoting
        +
        Returns:
        The command line itself
        +
      • +
      + + + +
        +
      • +

        addArgument

        +
        public CommandLine addArgument(String argument)
        +
        Add a single argument. Handles quoting.
        +
        Parameters:
        argument - The argument to add
        +
        Returns:
        The command line itself
        +
        Throws:
        +
        IllegalArgumentException - If argument contains both single and double quotes
        +
      • +
      + + + +
        +
      • +

        addArgument

        +
        public CommandLine addArgument(String argument,
        +                      boolean handleQuoting)
        +
        Add a single argument.
        +
        Parameters:
        argument - The argument to add
        handleQuoting - Add the argument with/without handling quoting
        +
        Returns:
        The command line itself
        +
      • +
      + + + +
        +
      • +

        getArguments

        +
        public String[] getArguments()
        +
        Returns the expanded and quoted command line arguments.
        +
        Returns:
        The quoted arguments
        +
      • +
      + + + +
        +
      • +

        getSubstitutionMap

        +
        public Map<String,?> getSubstitutionMap()
        +
        Returns:
        the substitution map
        +
      • +
      + + + +
        +
      • +

        setSubstitutionMap

        +
        public void setSubstitutionMap(Map<String,?> substitutionMap)
        +
        Set the substitutionMap to expand variables in the + command line.
        +
        Parameters:
        substitutionMap - the map
        +
      • +
      + + + +
        +
      • +

        toStrings

        +
        public String[] toStrings()
        +
        Returns the command line as an array of strings.
        +
        Returns:
        The command line as an string array
        +
      • +
      + + + +
        +
      • +

        toString

        +
        public String toString()
        +
        Stringify operator returns the command line as a string. + Parameters are correctly quoted when containing a space or + left untouched if the are already quoted.
        +
        +
        Overrides:
        +
        toString in class Object
        +
        Returns:
        the command line as single string
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DaemonExecutor.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DaemonExecutor.html new file mode 100644 index 0000000..022414a --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DaemonExecutor.html @@ -0,0 +1,301 @@ + + + + + +DaemonExecutor (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class DaemonExecutor

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Executor
    +
    +
    +
    +
    public class DaemonExecutor
    +extends DefaultExecutor
    +
    Runs daemon processes asynchronously. Callers are expected to register a ProcessDestroyer before executing + any processes.
    +
    Since:
    +
    1.3
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        DaemonExecutor

        +
        public DaemonExecutor()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        createThread

        +
        protected Thread createThread(Runnable runnable,
        +                  String name)
        +
        Factory method to create a thread waiting for the result of an asynchronous execution.
        +
        +
        Overrides:
        +
        createThread in class DefaultExecutor
        +
        Parameters:
        runnable - the runnable passed to the thread
        name - the name of the thread
        +
        Returns:
        the thread
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DefaultExecuteResultHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DefaultExecuteResultHandler.html new file mode 100644 index 0000000..c2fd78d --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DefaultExecuteResultHandler.html @@ -0,0 +1,407 @@ + + + + + +DefaultExecuteResultHandler (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class DefaultExecuteResultHandler

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • org.apache.commons.exec.DefaultExecuteResultHandler
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    ExecuteResultHandler
    +
    +
    +
    +
    public class DefaultExecuteResultHandler
    +extends Object
    +implements ExecuteResultHandler
    +
    A default implementation of 'ExecuteResultHandler' used for asynchronous + process handling.
    +
    Version:
    +
    $Id: DefaultExecuteResultHandler.java 1636057 2014-11-01 21:14:00Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        DefaultExecuteResultHandler

        +
        public DefaultExecuteResultHandler()
        +
        Constructor.
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + + + + + + + + + +
        +
      • +

        getException

        +
        public ExecuteException getException()
        +
        Get the exception causing the process execution to fail.
        +
        Returns:
        Returns the exception.
        +
        Throws:
        +
        IllegalStateException - if the process has not exited yet
        +
      • +
      + + + +
        +
      • +

        getExitValue

        +
        public int getExitValue()
        +
        Get the exitValue of the process.
        +
        Returns:
        Returns the exitValue.
        +
        Throws:
        +
        IllegalStateException - if the process has not exited yet
        +
      • +
      + + + +
        +
      • +

        hasResult

        +
        public boolean hasResult()
        +
        Has the process exited and a result is available, i.e. exitCode or exception?
        +
        Returns:
        true if a result of the execution is available
        +
      • +
      + + + +
        +
      • +

        waitFor

        +
        public void waitFor()
        +             throws InterruptedException
        +
        Causes the current thread to wait, if necessary, until the + process has terminated. This method returns immediately if + the process has already terminated. If the process has + not yet terminated, the calling thread will be blocked until the + process exits.
        +
        Throws:
        +
        InterruptedException - if the current thread is + interrupted by another + thread while it is waiting, then the wait is ended and + an InterruptedException is thrown.
        +
      • +
      + + + +
        +
      • +

        waitFor

        +
        public void waitFor(long timeout)
        +             throws InterruptedException
        +
        Causes the current thread to wait, if necessary, until the + process has terminated. This method returns immediately if + the process has already terminated. If the process has + not yet terminated, the calling thread will be blocked until the + process exits.
        +
        Parameters:
        timeout - the maximum time to wait in milliseconds
        +
        Throws:
        +
        InterruptedException - if the current thread is + interrupted by another + thread while it is waiting, then the wait is ended and + an InterruptedException is thrown.
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DefaultExecutor.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DefaultExecutor.html new file mode 100644 index 0000000..b080a43 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/DefaultExecutor.html @@ -0,0 +1,756 @@ + + + + + +DefaultExecutor (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class DefaultExecutor

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Executor
    +
    +
    +
    Direct Known Subclasses:
    +
    DaemonExecutor
    +
    +
    +
    +
    public class DefaultExecutor
    +extends Object
    +implements Executor
    +
    The default class to start a subprocess. The implementation + allows to +
      +
    • set a current working directory for the subprocess
    • +
    • provide a set of environment variables passed to the subprocess
    • +
    • capture the subprocess output of stdout and stderr using an ExecuteStreamHandler
    • +
    • kill long-running processes using an ExecuteWatchdog
    • +
    • define a set of expected exit values
    • +
    • terminate any started processes when the main process is terminating using a ProcessDestroyer
    • +
    + + The following example shows the basic usage: + +
    + Executor exec = new DefaultExecutor();
    + CommandLine cl = new CommandLine("ls -l");
    + int exitvalue = exec.execute(cl);
    + 
    +
    Version:
    +
    $Id: DefaultExecutor.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+ +
+
+ +
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteException.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteException.html new file mode 100644 index 0000000..9212e9b --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteException.html @@ -0,0 +1,336 @@ + + + + + +ExecuteException (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class ExecuteException

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Serializable
    +
    +
    +
    +
    public class ExecuteException
    +extends IOException
    +
    An exception indicating that the executing a subprocesses failed.
    +
    Version:
    +
    $Id: ExecuteException.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
    See Also:
    Serialized Form
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        ExecuteException

        +
        public ExecuteException(String message,
        +                int exitValue)
        +
        Construct a new exception with the specified detail message.
        +
        Parameters:
        message - The detail message
        exitValue - The exit value
        +
      • +
      + + + +
        +
      • +

        ExecuteException

        +
        public ExecuteException(String message,
        +                int exitValue,
        +                Throwable cause)
        +
        Construct a new exception with the specified detail message and cause.
        +
        Parameters:
        message - The detail message
        exitValue - The exit value
        cause - The underlying cause
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        getCause

        +
        public Throwable getCause()
        +
        Return the underlying cause of this exception (if any).
        +
        +
        Overrides:
        +
        getCause in class Throwable
        +
        +
      • +
      + + + +
        +
      • +

        getExitValue

        +
        public int getExitValue()
        +
        Gets the exit value returned by the failed process
        +
        Returns:
        The exit value
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteResultHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteResultHandler.html new file mode 100644 index 0000000..0ab3393 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteResultHandler.html @@ -0,0 +1,237 @@ + + + + + +ExecuteResultHandler (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Interface ExecuteResultHandler

+
+
+
+
    +
  • +
    +
    All Known Implementing Classes:
    +
    DefaultExecuteResultHandler
    +
    +
    +
    +
    public interface ExecuteResultHandler
    +
    The callback handlers for the result of asynchronous process execution. When a + process is started asynchronously the callback provides you with the result of + the executed process, i.e. the exit value or an exception.
    +
    Version:
    +
    $Id: ExecuteResultHandler.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
    See Also:
    Executor.execute(CommandLine, java.util.Map, ExecuteResultHandler)
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + +
      Methods 
      Modifier and TypeMethod and Description
      voidonProcessComplete(int exitValue) +
      The asynchronous execution completed.
      +
      voidonProcessFailed(ExecuteException e) +
      The asynchronous execution failed.
      +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        onProcessComplete

        +
        void onProcessComplete(int exitValue)
        +
        The asynchronous execution completed.
        +
        Parameters:
        exitValue - the exit value of the sub-process
        +
      • +
      + + + +
        +
      • +

        onProcessFailed

        +
        void onProcessFailed(ExecuteException e)
        +
        The asynchronous execution failed.
        +
        Parameters:
        e - the ExecuteException containing the root cause
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteStreamHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteStreamHandler.html new file mode 100644 index 0000000..d59b1c9 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteStreamHandler.html @@ -0,0 +1,299 @@ + + + + + +ExecuteStreamHandler (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Interface ExecuteStreamHandler

+
+
+
+
    +
  • +
    +
    All Known Implementing Classes:
    +
    PumpStreamHandler
    +
    +
    +
    +
    public interface ExecuteStreamHandler
    +
    Used by Execute to handle input and output stream of + subprocesses.
    +
    Version:
    +
    $Id: ExecuteStreamHandler.java 1636064 2014-11-01 22:01:19Z ggregory $
    +
  • +
+
+
+
    +
  • + + +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        setProcessInputStream

        +
        void setProcessInputStream(OutputStream os)
        +                           throws IOException
        +
        Install a handler for the input stream of the subprocess.
        +
        Parameters:
        os - output stream to write to the standard input stream of the subprocess
        +
        Throws:
        +
        IOException - thrown when an I/O exception occurs.
        +
      • +
      + + + +
        +
      • +

        setProcessErrorStream

        +
        void setProcessErrorStream(InputStream is)
        +                           throws IOException
        +
        Install a handler for the error stream of the subprocess.
        +
        Parameters:
        is - input stream to read from the error stream from the subprocess
        +
        Throws:
        +
        IOException - thrown when an I/O exception occurs.
        +
      • +
      + + + +
        +
      • +

        setProcessOutputStream

        +
        void setProcessOutputStream(InputStream is)
        +                            throws IOException
        +
        Install a handler for the output stream of the subprocess.
        +
        Parameters:
        is - input stream to read from the error stream from the subprocess
        +
        Throws:
        +
        IOException - thrown when an I/O exception occurs.
        +
      • +
      + + + +
        +
      • +

        start

        +
        void start()
        +           throws IOException
        +
        Start handling of the streams.
        +
        Throws:
        +
        IOException - thrown when an I/O exception occurs.
        +
      • +
      + + + +
        +
      • +

        stop

        +
        void stop()
        +          throws IOException
        +
        Stop handling of the streams - will not be restarted. Will wait for pump threads to complete.
        +
        Throws:
        +
        IOException - thrown when an I/O exception occurs.
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteWatchdog.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteWatchdog.html new file mode 100644 index 0000000..b750d18 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ExecuteWatchdog.html @@ -0,0 +1,466 @@ + + + + + +ExecuteWatchdog (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class ExecuteWatchdog

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    TimeoutObserver
    +
    +
    +
    +
    public class ExecuteWatchdog
    +extends Object
    +implements TimeoutObserver
    +
    Destroys a process running for too long. For example: + +
    + ExecuteWatchdog watchdog = new ExecuteWatchdog(30000);
    + Executer exec = new Executer(myloghandler, watchdog);
    + exec.setCommandLine(mycmdline);
    + int exitvalue = exec.execute();
    + if (Execute.isFailure(exitvalue) && watchdog.killedProcess()) {
    +     // it was killed on purpose by the watchdog
    + }
    + 
    + + When starting an asynchronous process than 'ExecuteWatchdog' is the + keeper of the process handle. In some cases it is useful not to define + a timeout (and pass 'INFINITE_TIMEOUT') and to kill the process explicitly + using 'destroyProcess()'. +

    + Please note that ExecuteWatchdog is processed asynchronously, e.g. it might + be still attached to a process even after the DefaultExecutor.execute + has returned.

    +
    Version:
    +
    $Id: ExecuteWatchdog.java 1612032 2014-07-20 06:30:44Z ggregory $
    +
    See Also:
    Executor, +Watchdog
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Field Summary

      + + + + + + + + + + +
      Fields 
      Modifier and TypeField and Description
      static longINFINITE_TIMEOUT +
      The marker for an infinite timeout
      +
      +
    • +
    + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      ExecuteWatchdog(long timeout) +
      Creates a new watchdog with a given timeout.
      +
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Methods 
      Modifier and TypeMethod and Description
      voidcheckException() +
      This method will rethrow the exception that was possibly caught during + the run of the process.
      +
      protected voidcleanUp() +
      reset the monitor flag and the process.
      +
      voiddestroyProcess() +
      Destroys the running process manually.
      +
      booleanisWatching() +
      Indicates whether or not the watchdog is still monitoring the process.
      +
      booleankilledProcess() +
      Indicates whether the last process run was killed.
      +
      voidstart(Process processToMonitor) +
      Watches the given process and terminates it, if it runs for too long.
      +
      voidstop() +
      Stops the watcher.
      +
      voidtimeoutOccured(Watchdog w) +
      Called after watchdog has finished.
      +
      + +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Field Detail

      + + + +
        +
      • +

        INFINITE_TIMEOUT

        +
        public static final long INFINITE_TIMEOUT
        +
        The marker for an infinite timeout
        +
        See Also:
        Constant Field Values
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        ExecuteWatchdog

        +
        public ExecuteWatchdog(long timeout)
        +
        Creates a new watchdog with a given timeout.
        +
        Parameters:
        timeout - the timeout for the process in milliseconds. It must be + greater than 0 or 'INFINITE_TIMEOUT'
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        start

        +
        public void start(Process processToMonitor)
        +
        Watches the given process and terminates it, if it runs for too long. All + information from the previous run are reset.
        +
        Parameters:
        processToMonitor - the process to monitor. It cannot be null
        +
        Throws:
        +
        IllegalStateException - if a process is still being monitored.
        +
      • +
      + + + +
        +
      • +

        stop

        +
        public void stop()
        +
        Stops the watcher. It will notify all threads possibly waiting on this + object.
        +
      • +
      + + + +
        +
      • +

        destroyProcess

        +
        public void destroyProcess()
        +
        Destroys the running process manually.
        +
      • +
      + + + +
        +
      • +

        timeoutOccured

        +
        public void timeoutOccured(Watchdog w)
        +
        Called after watchdog has finished.
        +
        +
        Specified by:
        +
        timeoutOccured in interface TimeoutObserver
        +
        Parameters:
        w - the watchdog that timed out.
        +
      • +
      + + + +
        +
      • +

        checkException

        +
        public void checkException()
        +                    throws Exception
        +
        This method will rethrow the exception that was possibly caught during + the run of the process. It will only remains valid once the process has + been terminated either by 'error', timeout or manual intervention. + Information will be discarded once a new process is ran.
        +
        Throws:
        +
        Exception - a wrapped exception over the one that was silently swallowed + and stored during the process run.
        +
      • +
      + + + +
        +
      • +

        isWatching

        +
        public boolean isWatching()
        +
        Indicates whether or not the watchdog is still monitoring the process.
        +
        Returns:
        true if the process is still running, otherwise + false.
        +
      • +
      + + + +
        +
      • +

        killedProcess

        +
        public boolean killedProcess()
        +
        Indicates whether the last process run was killed.
        +
        Returns:
        true if the process was killed + false.
        +
      • +
      + + + +
        +
      • +

        cleanUp

        +
        protected void cleanUp()
        +
        reset the monitor flag and the process.
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/Executor.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/Executor.html new file mode 100644 index 0000000..a34cfed --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/Executor.html @@ -0,0 +1,589 @@ + + + + + +Executor (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Interface Executor

+
+
+
+
    +
  • +
    +
    All Known Implementing Classes:
    +
    DaemonExecutor, DefaultExecutor
    +
    +
    +
    +
    public interface Executor
    +
    The main abstraction to start an external process. + + The interface allows to +
      +
    • set a current working directory for the subprocess
    • +
    • provide a set of environment variables passed to the subprocess
    • +
    • capture the subprocess output of stdout and stderr using an ExecuteStreamHandler
    • +
    • kill long-running processes using an ExecuteWatchdog
    • +
    • define a set of expected exit values
    • +
    • terminate any started processes when the main process is terminating using a ProcessDestroyer
    • +
    + + The following example shows the basic usage: + +
    + Executor exec = new DefaultExecutor();
    + CommandLine cl = new CommandLine("ls -l");
    + int exitvalue = exec.execute(cl);
    + 
    +
    Version:
    +
    $Id: Executor.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Field Detail

      + + + +
        +
      • +

        INVALID_EXITVALUE

        +
        static final int INVALID_EXITVALUE
        +
        Invalid exit code.
        +
        See Also:
        Constant Field Values
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        setExitValue

        +
        void setExitValue(int value)
        +
        Define the exitValue of the process to be considered + successful. If a different exit value is returned by + the process then execute(CommandLine) + will throw an ExecuteException
        +
        Parameters:
        value - the exit code representing successful execution
        +
      • +
      + + + +
        +
      • +

        setExitValues

        +
        void setExitValues(int[] values)
        +
        Define a list of exitValue of the process to be considered + successful. The caller can pass one of the following values +
          +
        • an array of exit values to be considered successful
        • +
        • an empty array for auto-detect of successful exit codes relying on isFailure(int)
        • +
        • null to indicate to skip checking of exit codes
        • +
        + + If an undefined exit value is returned by the process then + execute(CommandLine) will + throw an ExecuteException.
        +
        Parameters:
        values - a list of the exit codes
        +
      • +
      + + + +
        +
      • +

        isFailure

        +
        boolean isFailure(int exitValue)
        +
        Checks whether exitValue signals a failure. If no + exit values are set than the default conventions of the OS is + used. e.g. most OS regard an exit code of '0' as successful + execution and everything else as failure.
        +
        Parameters:
        exitValue - the exit value (return code) to be checked
        +
        Returns:
        true if exitValue signals a failure
        +
      • +
      + + + +
        +
      • +

        getStreamHandler

        +
        ExecuteStreamHandler getStreamHandler()
        +
        Get the StreamHandler used for providing input and + retrieving the output.
        +
        Returns:
        the StreamHandler
        +
      • +
      + + + +
        +
      • +

        setStreamHandler

        +
        void setStreamHandler(ExecuteStreamHandler streamHandler)
        +
        Set a custom the StreamHandler used for providing + input and retrieving the output. If you don't provide + a proper stream handler the executed process might block + when writing to stdout and/or stderr (see + Process).
        +
        Parameters:
        streamHandler - the stream handler
        +
      • +
      + + + +
        +
      • +

        getWatchdog

        +
        ExecuteWatchdog getWatchdog()
        +
        Get the watchdog used to kill of processes running, + typically, too long time.
        +
        Returns:
        the watchdog
        +
      • +
      + + + +
        +
      • +

        setWatchdog

        +
        void setWatchdog(ExecuteWatchdog watchDog)
        +
        Set the watchdog used to kill of processes running, + typically, too long time.
        +
        Parameters:
        watchDog - the watchdog
        +
      • +
      + + + +
        +
      • +

        getProcessDestroyer

        +
        ProcessDestroyer getProcessDestroyer()
        +
        Set the handler for cleanup of started processes if the main process + is going to terminate.
        +
        Returns:
        the ProcessDestroyer
        +
      • +
      + + + +
        +
      • +

        setProcessDestroyer

        +
        void setProcessDestroyer(ProcessDestroyer processDestroyer)
        +
        Get the handler for cleanup of started processes if the main process + is going to terminate.
        +
        Parameters:
        processDestroyer - the ProcessDestroyer
        +
      • +
      + + + +
        +
      • +

        getWorkingDirectory

        +
        File getWorkingDirectory()
        +
        Get the working directory of the created process.
        +
        Returns:
        the working directory
        +
      • +
      + + + +
        +
      • +

        setWorkingDirectory

        +
        void setWorkingDirectory(File dir)
        +
        Set the working directory of the created process. The + working directory must exist when you start the process.
        +
        Parameters:
        dir - the working directory
        +
      • +
      + + + +
        +
      • +

        execute

        +
        int execute(CommandLine command)
        +            throws ExecuteException,
        +                   IOException
        +
        Methods for starting synchronous execution. The child process inherits + all environment variables of the parent process.
        +
        Parameters:
        command - the command to execute
        +
        Returns:
        process exit value
        +
        Throws:
        +
        ExecuteException - execution of subprocess failed or the + subprocess returned a exit value indicating a failure + setExitValue(int).
        +
        IOException
        +
      • +
      + + + +
        +
      • +

        execute

        +
        int execute(CommandLine command,
        +          Map<String,String> environment)
        +            throws ExecuteException,
        +                   IOException
        +
        Methods for starting synchronous execution.
        +
        Parameters:
        command - the command to execute
        environment - The environment for the new process. If null, the + environment of the current process is used.
        +
        Returns:
        process exit value
        +
        Throws:
        +
        ExecuteException - execution of subprocess failed or the + subprocess returned a exit value indicating a failure + setExitValue(int).
        +
        IOException
        +
      • +
      + + + +
        +
      • +

        execute

        +
        void execute(CommandLine command,
        +           ExecuteResultHandler handler)
        +             throws ExecuteException,
        +                    IOException
        +
        Methods for starting asynchronous execution. The child process inherits + all environment variables of the parent process. Result provided to + callback handler.
        +
        Parameters:
        command - the command to execute
        handler - capture process termination and exit code
        +
        Throws:
        +
        ExecuteException - execution of subprocess failed
        +
        IOException
        +
      • +
      + + + +
        +
      • +

        execute

        +
        void execute(CommandLine command,
        +           Map<String,String> environment,
        +           ExecuteResultHandler handler)
        +             throws ExecuteException,
        +                    IOException
        +
        Methods for starting asynchronous execution. The child process inherits + all environment variables of the parent process. Result provided to + callback handler.
        +
        Parameters:
        command - the command to execute
        environment - The environment for the new process. If null, the + environment of the current process is used.
        handler - capture process termination and exit code
        +
        Throws:
        +
        ExecuteException - execution of subprocess failed
        +
        IOException
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/InputStreamPumper.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/InputStreamPumper.html new file mode 100644 index 0000000..c3f2151 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/InputStreamPumper.html @@ -0,0 +1,328 @@ + + + + + +InputStreamPumper (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class InputStreamPumper

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Runnable
    +
    +
    +
    +
    public class InputStreamPumper
    +extends Object
    +implements Runnable
    +
    Copies all data from an System.input stream to an output stream of the executed process.
    +
    Version:
    +
    $Id: InputStreamPumper.java 1557263 2014-01-10 21:18:09Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + + + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        InputStreamPumper

        +
        public InputStreamPumper(InputStream is,
        +                 OutputStream os)
        +
        Create a new stream pumper.
        +
        Parameters:
        is - input stream to read data from
        os - output stream to write data to.
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        run

        +
        public void run()
        +
        Copies data from the input stream to the output stream. Terminates as + soon as the input stream is closed or an error occurs.
        +
        +
        Specified by:
        +
        run in interface Runnable
        +
        +
      • +
      + + + +
        +
      • +

        stopProcessing

        +
        public void stopProcessing()
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/LogOutputStream.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/LogOutputStream.html new file mode 100644 index 0000000..0fe6427 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/LogOutputStream.html @@ -0,0 +1,451 @@ + + + + + +LogOutputStream (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class LogOutputStream

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Closeable, Flushable, AutoCloseable
    +
    +
    +
    +
    public abstract class LogOutputStream
    +extends OutputStream
    +
    Base class to connect a logging system to the output and/or + error stream of then external process. The implementation + parses the incoming data to construct a line and passes + the complete line to an user-defined implementation.
    +
    Version:
    +
    $Id: LogOutputStream.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + + + + +
      Constructors 
      Constructor and Description
      LogOutputStream() +
      Creates a new instance of this class.
      +
      LogOutputStream(int level) +
      Creates a new instance of this class.
      +
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Methods 
      Modifier and TypeMethod and Description
      voidclose() +
      Writes all remaining data from the buffer.
      +
      voidflush() +
      Flush this log stream.
      +
      intgetMessageLevel() 
      protected voidprocessBuffer() +
      Converts the buffer to a string and sends it to processLine.
      +
      protected voidprocessLine(String line) +
      Logs a line to the log system of the user.
      +
      protected abstract voidprocessLine(String line, + int logLevel) +
      Logs a line to the log system of the user.
      +
      voidwrite(byte[] b, + int off, + int len) +
      Write a block of characters to the output stream
      +
      voidwrite(int cc) +
      Write the data to the buffer and flush the buffer, if a line separator is + detected.
      +
      + + +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        LogOutputStream

        +
        public LogOutputStream()
        +
        Creates a new instance of this class. + Uses the default level of 999.
        +
      • +
      + + + +
        +
      • +

        LogOutputStream

        +
        public LogOutputStream(int level)
        +
        Creates a new instance of this class.
        +
        Parameters:
        level - loglevel used to log data written to this stream.
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + + + + + + + + + + + + + +
        +
      • +

        getMessageLevel

        +
        public int getMessageLevel()
        +
        Returns:
        the trace level of the log system
        +
      • +
      + + + +
        +
      • +

        write

        +
        public void write(byte[] b,
        +         int off,
        +         int len)
        +           throws IOException
        +
        Write a block of characters to the output stream
        +
        +
        Overrides:
        +
        write in class OutputStream
        +
        Parameters:
        b - the array containing the data
        off - the offset into the array where data starts
        len - the length of block
        +
        Throws:
        +
        IOException - if the data cannot be written into the stream.
        See Also:
        OutputStream.write(byte[], int, int)
        +
      • +
      + + + +
        +
      • +

        processBuffer

        +
        protected void processBuffer()
        +
        Converts the buffer to a string and sends it to processLine.
        +
      • +
      + + + +
        +
      • +

        processLine

        +
        protected void processLine(String line)
        +
        Logs a line to the log system of the user.
        +
        Parameters:
        line - the line to log.
        +
      • +
      + + + +
        +
      • +

        processLine

        +
        protected abstract void processLine(String line,
        +               int logLevel)
        +
        Logs a line to the log system of the user.
        +
        Parameters:
        line - the line to log.
        logLevel - the log level to use
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/OS.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/OS.html new file mode 100644 index 0000000..fbac760 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/OS.html @@ -0,0 +1,439 @@ + + + + + +OS (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class OS

+
+
+ +
+
    +
  • +
    +
    +
    public final class OS
    +extends Object
    +
    Condition that tests the OS type.
    +
    Version:
    +
    $Id: OS.java 1556869 2014-01-09 16:51:11Z britter $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        isFamilyDOS

        +
        public static boolean isFamilyDOS()
        +
      • +
      + + + +
        +
      • +

        isFamilyMac

        +
        public static boolean isFamilyMac()
        +
      • +
      + + + +
        +
      • +

        isFamilyNetware

        +
        public static boolean isFamilyNetware()
        +
      • +
      + + + +
        +
      • +

        isFamilyOS2

        +
        public static boolean isFamilyOS2()
        +
      • +
      + + + +
        +
      • +

        isFamilyTandem

        +
        public static boolean isFamilyTandem()
        +
      • +
      + + + +
        +
      • +

        isFamilyUnix

        +
        public static boolean isFamilyUnix()
        +
      • +
      + + + +
        +
      • +

        isFamilyWindows

        +
        public static boolean isFamilyWindows()
        +
      • +
      + + + +
        +
      • +

        isFamilyWin9x

        +
        public static boolean isFamilyWin9x()
        +
      • +
      + + + +
        +
      • +

        isFamilyZOS

        +
        public static boolean isFamilyZOS()
        +
      • +
      + + + +
        +
      • +

        isFamilyOS400

        +
        public static boolean isFamilyOS400()
        +
      • +
      + + + +
        +
      • +

        isFamilyOpenVms

        +
        public static boolean isFamilyOpenVms()
        +
      • +
      + + + +
        +
      • +

        isName

        +
        public static boolean isName(String name)
        +
        Determines if the OS on which Ant is executing matches the given OS name.
        +
        Parameters:
        name - the OS name to check for
        +
        Returns:
        true if the OS matches
        +
      • +
      + + + +
        +
      • +

        isArch

        +
        public static boolean isArch(String arch)
        +
        Determines if the OS on which Ant is executing matches the given OS + architecture.
        +
        Parameters:
        arch - the OS architecture to check for
        +
        Returns:
        true if the OS matches
        +
      • +
      + + + +
        +
      • +

        isVersion

        +
        public static boolean isVersion(String version)
        +
        Determines if the OS on which Ant is executing matches the given OS + version.
        +
        Parameters:
        version - the OS version to check for
        +
        Returns:
        true if the OS matches
        +
      • +
      + + + +
        +
      • +

        isOs

        +
        public static boolean isOs(String family,
        +           String name,
        +           String arch,
        +           String version)
        +
        Determines if the OS on which Ant is executing matches the given OS + family, name, architecture and version
        +
        Parameters:
        family - The OS family
        name - The OS name
        arch - The OS architecture
        version - The OS version
        +
        Returns:
        true if the OS matches
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ProcessDestroyer.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ProcessDestroyer.html new file mode 100644 index 0000000..cdd7682 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ProcessDestroyer.html @@ -0,0 +1,267 @@ + + + + + +ProcessDestroyer (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Interface ProcessDestroyer

+
+
+
+
    +
  • +
    +
    All Known Implementing Classes:
    +
    ShutdownHookProcessDestroyer
    +
    +
    +
    +
    public interface ProcessDestroyer
    +
    Destroys all registered Process after a certain event, + typically when the VM exits
    +
    Version:
    +
    $Id: ProcessDestroyer.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
    See Also:
    ShutdownHookProcessDestroyer
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + +
      Methods 
      Modifier and TypeMethod and Description
      booleanadd(Process process) +
      Returns true if the specified + Process was + successfully added to the list of processes to be destroy.
      +
      booleanremove(Process process) +
      Returns true if the specified + Process was + successfully removed from the list of processes to be destroy.
      +
      intsize() +
      Returns the number of registered processes.
      +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        add

        +
        boolean add(Process process)
        +
        Returns true if the specified + Process was + successfully added to the list of processes to be destroy.
        +
        Parameters:
        process - the process to add
        +
        Returns:
        true if the specified + Process was + successfully added
        +
      • +
      + + + +
        +
      • +

        remove

        +
        boolean remove(Process process)
        +
        Returns true if the specified + Process was + successfully removed from the list of processes to be destroy.
        +
        Parameters:
        process - the process to remove
        +
        Returns:
        true if the specified + Process was + successfully removed
        +
      • +
      + + + +
        +
      • +

        size

        +
        int size()
        +
        Returns the number of registered processes.
        +
        Returns:
        the number of register process
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/PumpStreamHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/PumpStreamHandler.html new file mode 100644 index 0000000..18486c7 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/PumpStreamHandler.html @@ -0,0 +1,579 @@ + + + + + +PumpStreamHandler (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class PumpStreamHandler

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    ExecuteStreamHandler
    +
    +
    +
    +
    public class PumpStreamHandler
    +extends Object
    +implements ExecuteStreamHandler
    +
    Copies standard output and error of sub-processes to standard output and error + of the parent process. If output or error stream are set to null, any feedback + from that stream will be lost.
    +
    Version:
    +
    $Id: PumpStreamHandler.java 1557263 2014-01-10 21:18:09Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        PumpStreamHandler

        +
        public PumpStreamHandler()
        +
        Construct a new PumpStreamHandler.
        +
      • +
      + + + +
        +
      • +

        PumpStreamHandler

        +
        public PumpStreamHandler(OutputStream outAndErr)
        +
        Construct a new PumpStreamHandler.
        +
        Parameters:
        outAndErr - the output/error OutputStream.
        +
      • +
      + + + +
        +
      • +

        PumpStreamHandler

        +
        public PumpStreamHandler(OutputStream out,
        +                 OutputStream err)
        +
        Construct a new PumpStreamHandler.
        +
        Parameters:
        out - the output OutputStream.
        err - the error OutputStream.
        +
      • +
      + + + +
        +
      • +

        PumpStreamHandler

        +
        public PumpStreamHandler(OutputStream out,
        +                 OutputStream err,
        +                 InputStream input)
        +
        Construct a new PumpStreamHandler.
        +
        Parameters:
        out - the output OutputStream.
        err - the error OutputStream.
        input - the input InputStream.
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        setStopTimeout

        +
        public void setStopTimeout(long timeout)
        +
        Set maximum time to wait until output streams are exchausted + when stop() was called.
        +
        Parameters:
        timeout - timeout in milliseconds or zero to wait forever (default)
        +
      • +
      + + + +
        +
      • +

        setProcessOutputStream

        +
        public void setProcessOutputStream(InputStream is)
        +
        Set the InputStream from which to read the standard output + of the process.
        +
        +
        Specified by:
        +
        setProcessOutputStream in interface ExecuteStreamHandler
        +
        Parameters:
        is - the InputStream.
        +
      • +
      + + + +
        +
      • +

        setProcessErrorStream

        +
        public void setProcessErrorStream(InputStream is)
        +
        Set the InputStream from which to read the standard error + of the process.
        +
        +
        Specified by:
        +
        setProcessErrorStream in interface ExecuteStreamHandler
        +
        Parameters:
        is - the InputStream.
        +
      • +
      + + + +
        +
      • +

        setProcessInputStream

        +
        public void setProcessInputStream(OutputStream os)
        +
        Set the OutputStream by means of which input can be sent + to the process.
        +
        +
        Specified by:
        +
        setProcessInputStream in interface ExecuteStreamHandler
        +
        Parameters:
        os - the OutputStream.
        +
      • +
      + + + + + + + +
        +
      • +

        stop

        +
        public void stop()
        +          throws IOException
        +
        Stop pumping the streams. When a timeout is specified it it is not guaranteed that the + pumper threads are cleanly terminated.
        +
        +
        Specified by:
        +
        stop in interface ExecuteStreamHandler
        +
        Throws:
        +
        IOException - thrown when an I/O exception occurs.
        +
      • +
      + + + +
        +
      • +

        getErr

        +
        protected OutputStream getErr()
        +
        Get the error stream.
        +
        Returns:
        OutputStream.
        +
      • +
      + + + +
        +
      • +

        getOut

        +
        protected OutputStream getOut()
        +
        Get the output stream.
        +
        Returns:
        OutputStream.
        +
      • +
      + + + +
        +
      • +

        createProcessOutputPump

        +
        protected void createProcessOutputPump(InputStream is,
        +                           OutputStream os)
        +
        Create the pump to handle process output.
        +
        Parameters:
        is - the InputStream.
        os - the OutputStream.
        +
      • +
      + + + +
        +
      • +

        createProcessErrorPump

        +
        protected void createProcessErrorPump(InputStream is,
        +                          OutputStream os)
        +
        Create the pump to handle error output.
        +
        Parameters:
        is - the InputStream.
        os - the OutputStream.
        +
      • +
      + + + +
        +
      • +

        createPump

        +
        protected Thread createPump(InputStream is,
        +                OutputStream os)
        +
        Creates a stream pumper to copy the given input stream to the given + output stream. When the 'os' is an PipedOutputStream we are closing + 'os' afterwards to avoid an IOException ("Write end dead").
        +
        Parameters:
        is - the input stream to copy from
        os - the output stream to copy into
        +
        Returns:
        the stream pumper thread
        +
      • +
      + + + +
        +
      • +

        createPump

        +
        protected Thread createPump(InputStream is,
        +                OutputStream os,
        +                boolean closeWhenExhausted)
        +
        Creates a stream pumper to copy the given input stream to the given + output stream.
        +
        Parameters:
        is - the input stream to copy from
        os - the output stream to copy into
        closeWhenExhausted - close the output stream when the input stream is exhausted
        +
        Returns:
        the stream pumper thread
        +
      • +
      + + + +
        +
      • +

        stopThread

        +
        protected void stopThread(Thread thread,
        +              long timeout)
        +
        Stopping a pumper thread. The implementation actually waits + longer than specified in 'timeout' to detect if the timeout + was indeed exceeded. If the timeout was exceeded an IOException + is created to be thrown to the caller.
        +
        Parameters:
        thread - the thread to be stopped
        timeout - the time in ms to wait to join
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ShutdownHookProcessDestroyer.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ShutdownHookProcessDestroyer.html new file mode 100644 index 0000000..e109024 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/ShutdownHookProcessDestroyer.html @@ -0,0 +1,370 @@ + + + + + +ShutdownHookProcessDestroyer (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class ShutdownHookProcessDestroyer

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • org.apache.commons.exec.ShutdownHookProcessDestroyer
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Runnable, ProcessDestroyer
    +
    +
    +
    +
    public class ShutdownHookProcessDestroyer
    +extends Object
    +implements ProcessDestroyer, Runnable
    +
    Destroys all registered Processes when the VM exits.
    +
    Version:
    +
    $Id: ShutdownHookProcessDestroyer.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Summary

      + + + + + + + + +
      Constructors 
      Constructor and Description
      ShutdownHookProcessDestroyer() +
      Constructs a ProcessDestroyer and obtains + Runtime.addShutdownHook() and + Runtime.removeShutdownHook() through reflection.
      +
      +
    • +
    + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Methods 
      Modifier and TypeMethod and Description
      booleanadd(Process process) +
      Returns true if the specified Process was + successfully added to the list of processes to destroy upon VM exit.
      +
      booleanisAddedAsShutdownHook() +
      Returns whether or not the ProcessDestroyer is registered as as shutdown + hook
      +
      booleanremove(Process process) +
      Returns true if the specified Process was + successfully removed from the list of processes to destroy upon VM exit.
      +
      voidrun() +
      Invoked by the VM when it is exiting.
      +
      intsize() +
      Returns the number of registered processes.
      +
      + +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        ShutdownHookProcessDestroyer

        +
        public ShutdownHookProcessDestroyer()
        +
        Constructs a ProcessDestroyer and obtains + Runtime.addShutdownHook() and + Runtime.removeShutdownHook() through reflection. The + ProcessDestroyer manages a list of processes to be destroyed when the VM + exits. If a process is added when the list is empty, this + ProcessDestroyer is registered as a shutdown hook. If + removing a process results in an empty list, the + ProcessDestroyer is removed as a shutdown hook.
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        isAddedAsShutdownHook

        +
        public boolean isAddedAsShutdownHook()
        +
        Returns whether or not the ProcessDestroyer is registered as as shutdown + hook
        +
        Returns:
        true if this is currently added as shutdown hook
        +
      • +
      + + + +
        +
      • +

        add

        +
        public boolean add(Process process)
        +
        Returns true if the specified Process was + successfully added to the list of processes to destroy upon VM exit.
        +
        +
        Specified by:
        +
        add in interface ProcessDestroyer
        +
        Parameters:
        process - the process to add
        +
        Returns:
        true if the specified Process was + successfully added
        +
      • +
      + + + +
        +
      • +

        remove

        +
        public boolean remove(Process process)
        +
        Returns true if the specified Process was + successfully removed from the list of processes to destroy upon VM exit.
        +
        +
        Specified by:
        +
        remove in interface ProcessDestroyer
        +
        Parameters:
        process - the process to remove
        +
        Returns:
        true if the specified Process was + successfully removed
        +
      • +
      + + + +
        +
      • +

        size

        +
        public int size()
        +
        Returns the number of registered processes.
        +
        +
        Specified by:
        +
        size in interface ProcessDestroyer
        +
        Returns:
        the number of register process
        +
      • +
      + + + +
        +
      • +

        run

        +
        public void run()
        +
        Invoked by the VM when it is exiting.
        +
        +
        Specified by:
        +
        run in interface Runnable
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/StreamPumper.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/StreamPumper.html new file mode 100644 index 0000000..d93bc87 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/StreamPumper.html @@ -0,0 +1,357 @@ + + + + + +StreamPumper (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class StreamPumper

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Runnable
    +
    +
    +
    +
    public class StreamPumper
    +extends Object
    +implements Runnable
    +
    Copies all data from an input stream to an output stream.
    +
    Version:
    +
    $Id: StreamPumper.java 1557263 2014-01-10 21:18:09Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        StreamPumper

        +
        public StreamPumper(InputStream is,
        +            OutputStream os,
        +            boolean closeWhenExhausted)
        +
        Create a new stream pumper.
        +
        Parameters:
        is - input stream to read data from
        os - output stream to write data to.
        closeWhenExhausted - if true, the output stream will be closed when the input is exhausted.
        +
      • +
      + + + +
        +
      • +

        StreamPumper

        +
        public StreamPumper(InputStream is,
        +            OutputStream os,
        +            boolean closeWhenExhausted,
        +            int size)
        +
        Create a new stream pumper.
        +
        Parameters:
        is - input stream to read data from
        os - output stream to write data to.
        closeWhenExhausted - if true, the output stream will be closed when the input is exhausted.
        size - the size of the internal buffer for copying the streams
        +
      • +
      + + + +
        +
      • +

        StreamPumper

        +
        public StreamPumper(InputStream is,
        +            OutputStream os)
        +
        Create a new stream pumper.
        +
        Parameters:
        is - input stream to read data from
        os - output stream to write data to.
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        run

        +
        public void run()
        +
        Copies data from the input stream to the output stream. Terminates as + soon as the input stream is closed or an error occurs.
        +
        +
        Specified by:
        +
        run in interface Runnable
        +
        +
      • +
      + + + +
        +
      • +

        isFinished

        +
        public boolean isFinished()
        +
        Tells whether the end of the stream has been reached.
        +
        Returns:
        true is the stream has been exhausted.
        +
      • +
      + + + +
        +
      • +

        waitFor

        +
        public void waitFor()
        +             throws InterruptedException
        +
        This method blocks until the stream pumper finishes.
        +
        Throws:
        +
        InterruptedException - if any thread interrupted the current thread before or while the current thread was waiting for a + notification.
        See Also:
        isFinished()
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/TimeoutObserver.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/TimeoutObserver.html new file mode 100644 index 0000000..de3ac7e --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/TimeoutObserver.html @@ -0,0 +1,218 @@ + + + + + +TimeoutObserver (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Interface TimeoutObserver

+
+
+
+
    +
  • +
    +
    All Known Implementing Classes:
    +
    ExecuteWatchdog
    +
    +
    +
    +
    public interface TimeoutObserver
    +
    Interface for classes that want to be notified by Watchdog.
    +
    Version:
    +
    $Id: TimeoutObserver.java 1556869 2014-01-09 16:51:11Z britter $
    +
    See Also:
    Watchdog
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + +
      Methods 
      Modifier and TypeMethod and Description
      voidtimeoutOccured(Watchdog w) +
      Called when the watchdog times out.
      +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        timeoutOccured

        +
        void timeoutOccured(Watchdog w)
        +
        Called when the watchdog times out.
        +
        Parameters:
        w - the watchdog that timed out.
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/Watchdog.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/Watchdog.html new file mode 100644 index 0000000..aaa3e06 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/Watchdog.html @@ -0,0 +1,334 @@ + + + + + +Watchdog (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec
+

Class Watchdog

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    Runnable
    +
    +
    +
    +
    public class Watchdog
    +extends Object
    +implements Runnable
    +
    Generalization of ExecuteWatchdog
    +
    Version:
    +
    $Id: Watchdog.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
    See Also:
    ExecuteWatchdog
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        Watchdog

        +
        public Watchdog(long timeout)
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        addTimeoutObserver

        +
        public void addTimeoutObserver(TimeoutObserver to)
        +
      • +
      + + + +
        +
      • +

        removeTimeoutObserver

        +
        public void removeTimeoutObserver(TimeoutObserver to)
        +
      • +
      + + + +
        +
      • +

        fireTimeoutOccured

        +
        protected final void fireTimeoutOccured()
        +
      • +
      + + + +
        +
      • +

        start

        +
        public void start()
        +
      • +
      + + + +
        +
      • +

        stop

        +
        public void stop()
        +
      • +
      + + + +
        +
      • +

        run

        +
        public void run()
        +
        +
        Specified by:
        +
        run in interface Runnable
        +
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/CommandLine.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/CommandLine.html new file mode 100644 index 0000000..d3b36ea --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/CommandLine.html @@ -0,0 +1,402 @@ + + + + + +Uses of Class org.apache.commons.exec.CommandLine (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.CommandLine

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DaemonExecutor.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DaemonExecutor.html new file mode 100644 index 0000000..7763d01 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DaemonExecutor.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.DaemonExecutor (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.DaemonExecutor

+
+
No usage of org.apache.commons.exec.DaemonExecutor
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DefaultExecuteResultHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DefaultExecuteResultHandler.html new file mode 100644 index 0000000..af8c304 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DefaultExecuteResultHandler.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.DefaultExecuteResultHandler (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.DefaultExecuteResultHandler

+
+
No usage of org.apache.commons.exec.DefaultExecuteResultHandler
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DefaultExecutor.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DefaultExecutor.html new file mode 100644 index 0000000..9d742d4 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/DefaultExecutor.html @@ -0,0 +1,157 @@ + + + + + +Uses of Class org.apache.commons.exec.DefaultExecutor (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.DefaultExecutor

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteException.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteException.html new file mode 100644 index 0000000..6d816e4 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteException.html @@ -0,0 +1,233 @@ + + + + + +Uses of Class org.apache.commons.exec.ExecuteException (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.ExecuteException

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteResultHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteResultHandler.html new file mode 100644 index 0000000..17353f3 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteResultHandler.html @@ -0,0 +1,193 @@ + + + + + +Uses of Interface org.apache.commons.exec.ExecuteResultHandler (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Interface
org.apache.commons.exec.ExecuteResultHandler

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteStreamHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteStreamHandler.html new file mode 100644 index 0000000..22a6a2a --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteStreamHandler.html @@ -0,0 +1,198 @@ + + + + + +Uses of Interface org.apache.commons.exec.ExecuteStreamHandler (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Interface
org.apache.commons.exec.ExecuteStreamHandler

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteWatchdog.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteWatchdog.html new file mode 100644 index 0000000..daf532f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ExecuteWatchdog.html @@ -0,0 +1,182 @@ + + + + + +Uses of Class org.apache.commons.exec.ExecuteWatchdog (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.ExecuteWatchdog

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/Executor.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/Executor.html new file mode 100644 index 0000000..46f8007 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/Executor.html @@ -0,0 +1,163 @@ + + + + + +Uses of Interface org.apache.commons.exec.Executor (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Interface
org.apache.commons.exec.Executor

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/InputStreamPumper.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/InputStreamPumper.html new file mode 100644 index 0000000..fb560ce --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/InputStreamPumper.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.InputStreamPumper (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.InputStreamPumper

+
+
No usage of org.apache.commons.exec.InputStreamPumper
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/LogOutputStream.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/LogOutputStream.html new file mode 100644 index 0000000..906c158 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/LogOutputStream.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.LogOutputStream (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.LogOutputStream

+
+
No usage of org.apache.commons.exec.LogOutputStream
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/OS.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/OS.html new file mode 100644 index 0000000..841b5a6 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/OS.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.OS (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.OS

+
+
No usage of org.apache.commons.exec.OS
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ProcessDestroyer.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ProcessDestroyer.html new file mode 100644 index 0000000..b0811c0 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ProcessDestroyer.html @@ -0,0 +1,197 @@ + + + + + +Uses of Interface org.apache.commons.exec.ProcessDestroyer (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Interface
org.apache.commons.exec.ProcessDestroyer

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/PumpStreamHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/PumpStreamHandler.html new file mode 100644 index 0000000..fc2e710 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/PumpStreamHandler.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.PumpStreamHandler (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.PumpStreamHandler

+
+
No usage of org.apache.commons.exec.PumpStreamHandler
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ShutdownHookProcessDestroyer.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ShutdownHookProcessDestroyer.html new file mode 100644 index 0000000..1ae1f98 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/ShutdownHookProcessDestroyer.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.ShutdownHookProcessDestroyer (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.ShutdownHookProcessDestroyer

+
+
No usage of org.apache.commons.exec.ShutdownHookProcessDestroyer
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/StreamPumper.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/StreamPumper.html new file mode 100644 index 0000000..0e84651 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/StreamPumper.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.StreamPumper (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.StreamPumper

+
+
No usage of org.apache.commons.exec.StreamPumper
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/TimeoutObserver.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/TimeoutObserver.html new file mode 100644 index 0000000..297a797 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/TimeoutObserver.html @@ -0,0 +1,174 @@ + + + + + +Uses of Interface org.apache.commons.exec.TimeoutObserver (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Interface
org.apache.commons.exec.TimeoutObserver

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/Watchdog.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/Watchdog.html new file mode 100644 index 0000000..d656935 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/class-use/Watchdog.html @@ -0,0 +1,163 @@ + + + + + +Uses of Class org.apache.commons.exec.Watchdog (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.Watchdog

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/DefaultProcessingEnvironment.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/DefaultProcessingEnvironment.html new file mode 100644 index 0000000..b73b116 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/DefaultProcessingEnvironment.html @@ -0,0 +1,379 @@ + + + + + +DefaultProcessingEnvironment (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.environment
+

Class DefaultProcessingEnvironment

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • org.apache.commons.exec.environment.DefaultProcessingEnvironment
    • +
    +
  • +
+
+
    +
  • +
    +
    Direct Known Subclasses:
    +
    OpenVmsProcessingEnvironment
    +
    +
    +
    +
    public class DefaultProcessingEnvironment
    +extends Object
    +
    Helper class to determine the environment variable + for the OS. Depending on the JDK the environment + variables can be either retrieved directly from the + JVM or requires starting a process to get them running + an OS command line.
    +
    Version:
    +
    $Id: DefaultProcessingEnvironment.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Field Detail

      + + + +
        +
      • +

        procEnvironment

        +
        protected Map<String,String> procEnvironment
        +
        the environment variables of the process
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        DefaultProcessingEnvironment

        +
        public DefaultProcessingEnvironment()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        getProcEnvironment

        +
        public Map<String,String> getProcEnvironment()
        +                                      throws IOException
        +
        Find the list of environment variables for this process.
        +
        Returns:
        a map containing the environment variables
        +
        Throws:
        +
        IOException - obtaining the environment variables failed
        +
      • +
      + + + +
        +
      • +

        createProcEnvironment

        +
        protected Map<String,String> createProcEnvironment()
        +                                            throws IOException
        +
        Find the list of environment variables for this process.
        +
        Returns:
        a amp containing the environment variables
        +
        Throws:
        +
        IOException - the operation failed
        +
      • +
      + + + +
        +
      • +

        runProcEnvCommand

        +
        @Deprecated
        +protected BufferedReader runProcEnvCommand()
        +                                    throws IOException
        +
        Deprecated. No longer needed
        +
        Start a process to list the environment variables.
        +
        Returns:
        a reader containing the output of the process
        +
        Throws:
        +
        IOException - starting the process failed
        +
      • +
      + + + +
        +
      • +

        getProcEnvCommand

        +
        @Deprecated
        +protected CommandLine getProcEnvCommand()
        +
        Deprecated. No longer needed
        +
        Determine the OS specific command line to get a list of environment + variables.
        +
        Returns:
        the command line
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/EnvironmentUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/EnvironmentUtils.html new file mode 100644 index 0000000..434d6d3 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/EnvironmentUtils.html @@ -0,0 +1,274 @@ + + + + + +EnvironmentUtils (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.environment
+

Class EnvironmentUtils

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • org.apache.commons.exec.environment.EnvironmentUtils
    • +
    +
  • +
+
+
    +
  • +
    +
    +
    public class EnvironmentUtils
    +extends Object
    +
    Wrapper for environment variables.
    +
    Version:
    +
    $Id: EnvironmentUtils.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        toStrings

        +
        public static String[] toStrings(Map<String,String> environment)
        +
        Get the variable list as an array.
        +
        Parameters:
        environment - the environment to use, may be null
        +
        Returns:
        array of key=value assignment strings or null if and only if + the input map was null
        +
      • +
      + + + +
        +
      • +

        getProcEnvironment

        +
        public static Map<String,String> getProcEnvironment()
        +                                             throws IOException
        +
        Find the list of environment variables for this process. The returned map preserves + the casing of a variable's name on all platforms but obeys the casing rules of the + current platform during lookup, e.g. key names will be case-insensitive on Windows + platforms.
        +
        Returns:
        a map containing the environment variables, may be empty but never null
        +
        Throws:
        +
        IOException - the operation failed
        +
      • +
      + + + +
        +
      • +

        addVariableToEnvironment

        +
        public static void addVariableToEnvironment(Map<String,String> environment,
        +                            String keyAndValue)
        +
        Add a key/value pair to the given environment. + If the key matches an existing key, the previous setting is replaced.
        +
        Parameters:
        environment - the current environment
        keyAndValue - the key/value pair
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/OpenVmsProcessingEnvironment.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/OpenVmsProcessingEnvironment.html new file mode 100644 index 0000000..ed9f216 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/OpenVmsProcessingEnvironment.html @@ -0,0 +1,266 @@ + + + + + +OpenVmsProcessingEnvironment (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.environment
+

Class OpenVmsProcessingEnvironment

+
+
+ +
+
    +
  • +
    +
    Deprecated.  +
    No longer needed
    +
    +
    +
    @Deprecated
    +public class OpenVmsProcessingEnvironment
    +extends DefaultProcessingEnvironment
    +
    Helper class to determine the environment variable + for VMS.
    +
    Version:
    +
    $Id: OpenVmsProcessingEnvironment.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        OpenVmsProcessingEnvironment

        +
        public OpenVmsProcessingEnvironment()
        +
        Deprecated. 
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/DefaultProcessingEnvironment.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/DefaultProcessingEnvironment.html new file mode 100644 index 0000000..53a766d --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/DefaultProcessingEnvironment.html @@ -0,0 +1,159 @@ + + + + + +Uses of Class org.apache.commons.exec.environment.DefaultProcessingEnvironment (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.environment.DefaultProcessingEnvironment

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/EnvironmentUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/EnvironmentUtils.html new file mode 100644 index 0000000..dab3e7f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/EnvironmentUtils.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.environment.EnvironmentUtils (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.environment.EnvironmentUtils

+
+
No usage of org.apache.commons.exec.environment.EnvironmentUtils
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/OpenVmsProcessingEnvironment.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/OpenVmsProcessingEnvironment.html new file mode 100644 index 0000000..190a82f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/class-use/OpenVmsProcessingEnvironment.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.environment.OpenVmsProcessingEnvironment (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.environment.OpenVmsProcessingEnvironment

+
+
No usage of org.apache.commons.exec.environment.OpenVmsProcessingEnvironment
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-frame.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-frame.html new file mode 100644 index 0000000..c0118ae --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-frame.html @@ -0,0 +1,20 @@ + + + + + +org.apache.commons.exec.environment (Apache Commons Exec 1.3 API) + + + +

org.apache.commons.exec.environment

+ + + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-summary.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-summary.html new file mode 100644 index 0000000..ed1d9dc --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-summary.html @@ -0,0 +1,148 @@ + + + + + +org.apache.commons.exec.environment (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Package org.apache.commons.exec.environment

+
+
+ +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-tree.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-tree.html new file mode 100644 index 0000000..14adc18 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-tree.html @@ -0,0 +1,133 @@ + + + + + +org.apache.commons.exec.environment Class Hierarchy (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Hierarchy For Package org.apache.commons.exec.environment

+Package Hierarchies: + +
+
+

Class Hierarchy

+ +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-use.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-use.html new file mode 100644 index 0000000..690078c --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/environment/package-use.html @@ -0,0 +1,151 @@ + + + + + +Uses of Package org.apache.commons.exec.environment (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Package
org.apache.commons.exec.environment

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncher.html new file mode 100644 index 0000000..94a9c7a --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncher.html @@ -0,0 +1,282 @@ + + + + + +CommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Interface CommandLauncher

+
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + +
      Methods 
      Modifier and TypeMethod and Description
      Processexec(CommandLine cmd, + Map<String,String> env) +
      Launches the given command in a new process.
      +
      Processexec(CommandLine cmd, + Map<String,String> env, + File workingDir) +
      Launches the given command in a new process, in the given working + directory.
      +
      booleanisFailure(int exitValue) +
      Checks whether exitValue signals a failure on the current + system (OS specific).
      +
      +
    • +
    +
  • +
+
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        exec

        +
        Process exec(CommandLine cmd,
        +           Map<String,String> env)
        +             throws IOException
        +
        Launches the given command in a new process.
        +
        Parameters:
        cmd - The command to execute
        env - The environment for the new process. If null, the environment + of the current process is used.
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - if attempting to run a command in a specific directory
        +
      • +
      + + + +
        +
      • +

        exec

        +
        Process exec(CommandLine cmd,
        +           Map<String,String> env,
        +           File workingDir)
        +             throws IOException
        +
        Launches the given command in a new process, in the given working + directory.
        +
        Parameters:
        cmd - The command to execute
        env - The environment for the new process. If null, the environment + of the current process is used.
        workingDir - The directory to start the command in. If null, the current + directory is used
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - if trying to change directory
        +
      • +
      + + + +
        +
      • +

        isFailure

        +
        boolean isFailure(int exitValue)
        +
        Checks whether exitValue signals a failure on the current + system (OS specific). +

        + Note that this method relies on the conventions of the OS, it + will return false results if the application you are running doesn't + follow these conventions. One notable exception is the Java VM provided + by HP for OpenVMS - it will return 0 if successful (like on any other + platform), but this signals a failure on OpenVMS. So if you execute a new + Java VM on OpenVMS, you cannot trust this method. +

        +
        Parameters:
        exitValue - the exit value (return code) to be checked
        +
        Returns:
        true if exitValue signals a failure
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherFactory.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherFactory.html new file mode 100644 index 0000000..86dc393 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherFactory.html @@ -0,0 +1,229 @@ + + + + + +CommandLauncherFactory (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Class CommandLauncherFactory

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • org.apache.commons.exec.launcher.CommandLauncherFactory
    • +
    +
  • +
+
+
    +
  • +
    +
    +
    public final class CommandLauncherFactory
    +extends Object
    +
    Builds a command launcher for the OS and JVM we are running under.
    +
    Version:
    +
    $Id: CommandLauncherFactory.java 1556869 2014-01-09 16:51:11Z britter $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        createVMLauncher

        +
        public static CommandLauncher createVMLauncher()
        +
        Factory method to create an appropriate launcher.
        +
        Returns:
        the command launcher
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherImpl.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherImpl.html new file mode 100644 index 0000000..b17dd0f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherImpl.html @@ -0,0 +1,350 @@ + + + + + +CommandLauncherImpl (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Class CommandLauncherImpl

+
+
+
    +
  • java.lang.Object
  • +
  • +
      +
    • org.apache.commons.exec.launcher.CommandLauncherImpl
    • +
    +
  • +
+
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    CommandLauncher
    +
    +
    +
    Direct Known Subclasses:
    +
    CommandLauncherProxy, Java13CommandLauncher
    +
    +
    +
    +
    public abstract class CommandLauncherImpl
    +extends Object
    +implements CommandLauncher
    +
    A command launcher for a particular JVM/OS platform. This class is a general + purpose command launcher which can only launch commands in the current + working directory.
    +
    Version:
    +
    $Id: CommandLauncherImpl.java 1557338 2014-01-11 10:34:22Z sebb $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        CommandLauncherImpl

        +
        public CommandLauncherImpl()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        exec

        +
        public Process exec(CommandLine cmd,
        +           Map<String,String> env)
        +             throws IOException
        +
        Description copied from interface: CommandLauncher
        +
        Launches the given command in a new process.
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Parameters:
        cmd - The command to execute
        env - The environment for the new process. If null, the environment + of the current process is used.
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - if attempting to run a command in a specific directory
        +
      • +
      + + + +
        +
      • +

        exec

        +
        public abstract Process exec(CommandLine cmd,
        +           Map<String,String> env,
        +           File workingDir)
        +                      throws IOException
        +
        Description copied from interface: CommandLauncher
        +
        Launches the given command in a new process, in the given working + directory.
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Parameters:
        cmd - The command to execute
        env - The environment for the new process. If null, the environment + of the current process is used.
        workingDir - The directory to start the command in. If null, the current + directory is used
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - if trying to change directory
        +
      • +
      + + + +
        +
      • +

        isFailure

        +
        public boolean isFailure(int exitValue)
        +
        Description copied from interface: CommandLauncher
        +
        Checks whether exitValue signals a failure on the current + system (OS specific). +

        + Note that this method relies on the conventions of the OS, it + will return false results if the application you are running doesn't + follow these conventions. One notable exception is the Java VM provided + by HP for OpenVMS - it will return 0 if successful (like on any other + platform), but this signals a failure on OpenVMS. So if you execute a new + Java VM on OpenVMS, you cannot trust this method. +

        +
        +
        Specified by:
        +
        isFailure in interface CommandLauncher
        +
        Parameters:
        exitValue - the exit value (return code) to be checked
        +
        Returns:
        true if exitValue signals a failure
        See Also:
        CommandLauncher.isFailure(int)
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherProxy.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherProxy.html new file mode 100644 index 0000000..dc9de7d --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/CommandLauncherProxy.html @@ -0,0 +1,296 @@ + + + + + +CommandLauncherProxy (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Class CommandLauncherProxy

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    CommandLauncher
    +
    +
    +
    Direct Known Subclasses:
    +
    OS2CommandLauncher, WinNTCommandLauncher
    +
    +
    +
    +
    public abstract class CommandLauncherProxy
    +extends CommandLauncherImpl
    +
    A command launcher that proxies another command launcher. Sub-classes + override exec(args, env, workdir)
    +
    Version:
    +
    $Id: CommandLauncherProxy.java 1557338 2014-01-11 10:34:22Z sebb $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        CommandLauncherProxy

        +
        public CommandLauncherProxy(CommandLauncher launcher)
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        exec

        +
        public Process exec(CommandLine cmd,
        +           Map<String,String> env)
        +             throws IOException
        +
        Launches the given command in a new process. Delegates this method to the + proxied launcher
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Overrides:
        +
        exec in class CommandLauncherImpl
        +
        Parameters:
        cmd - the command line to execute as an array of strings
        env - the environment to set as an array of strings
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - forwarded from the exec method of the command launcher
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/Java13CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/Java13CommandLauncher.html new file mode 100644 index 0000000..787b3cf --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/Java13CommandLauncher.html @@ -0,0 +1,302 @@ + + + + + +Java13CommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Class Java13CommandLauncher

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    CommandLauncher
    +
    +
    +
    Direct Known Subclasses:
    +
    VmsCommandLauncher
    +
    +
    +
    +
    public class Java13CommandLauncher
    +extends CommandLauncherImpl
    +
    A command launcher for JDK/JRE 1.3 (and higher). Uses the built-in + Runtime.exec() command
    +
    Version:
    +
    $Id: Java13CommandLauncher.java 1557338 2014-01-11 10:34:22Z sebb $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        Java13CommandLauncher

        +
        public Java13CommandLauncher()
        +
        Constructor
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        exec

        +
        public Process exec(CommandLine cmd,
        +           Map<String,String> env,
        +           File workingDir)
        +             throws IOException
        +
        Launches the given command in a new process, in the given working + directory
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Specified by:
        +
        exec in class CommandLauncherImpl
        +
        Parameters:
        cmd - the command line to execute as an array of strings
        env - the environment to set as an array of strings
        workingDir - the working directory where the command should run
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - probably forwarded from Runtime#exec
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/OS2CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/OS2CommandLauncher.html new file mode 100644 index 0000000..fc3870e --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/OS2CommandLauncher.html @@ -0,0 +1,313 @@ + + + + + +OS2CommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Class OS2CommandLauncher

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    CommandLauncher
    +
    +
    +
    +
    public class OS2CommandLauncher
    +extends CommandLauncherProxy
    +
    A command launcher for OS/2 that uses 'cmd.exe' when launching commands in + directories other than the current working directory. +

    + Unlike Windows NT and friends, OS/2's cd doesn't support the /d switch to + change drives and directories in one go. +

    + Please not that this class is currently unused because the Java13CommandLauncher + is used for 0S/2
    +
    Version:
    +
    $Id: OS2CommandLauncher.java 1557338 2014-01-11 10:34:22Z sebb $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        OS2CommandLauncher

        +
        public OS2CommandLauncher(CommandLauncher launcher)
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        exec

        +
        public Process exec(CommandLine cmd,
        +           Map<String,String> env,
        +           File workingDir)
        +             throws IOException
        +
        Launches the given command in a new process, in the given working + directory.
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Specified by:
        +
        exec in class CommandLauncherImpl
        +
        Parameters:
        cmd - the command line to execute as an array of strings
        env - the environment to set as an array of strings
        workingDir - working directory where the command should run
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - forwarded from the exec method of the command launcher
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/VmsCommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/VmsCommandLauncher.html new file mode 100644 index 0000000..39e7081 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/VmsCommandLauncher.html @@ -0,0 +1,359 @@ + + + + + +VmsCommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Class VmsCommandLauncher

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    CommandLauncher
    +
    +
    +
    +
    public class VmsCommandLauncher
    +extends Java13CommandLauncher
    +
    A command launcher for VMS that writes the command to a temporary DCL script + before launching commands. This is due to limitations of both the DCL + interpreter and the Java VM implementation.
    +
    Version:
    +
    $Id: VmsCommandLauncher.java 1636056 2014-11-01 21:12:52Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        VmsCommandLauncher

        +
        public VmsCommandLauncher()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        exec

        +
        public Process exec(CommandLine cmd,
        +           Map<String,String> env)
        +             throws IOException
        +
        Launches the given command in a new process.
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Overrides:
        +
        exec in class CommandLauncherImpl
        +
        Parameters:
        cmd - The command to execute
        env - The environment for the new process. If null, the environment + of the current process is used.
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - if attempting to run a command in a specific directory
        +
      • +
      + + + +
        +
      • +

        exec

        +
        public Process exec(CommandLine cmd,
        +           Map<String,String> env,
        +           File workingDir)
        +             throws IOException
        +
        Launches the given command in a new process, in the given working + directory. Note that under Java 1.3.1, 1.4.0 and 1.4.1 on VMS this method + only works if workingDir is null or the logical + JAVA$FORK_SUPPORT_CHDIR needs to be set to TRUE.
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Overrides:
        +
        exec in class Java13CommandLauncher
        +
        Parameters:
        cmd - the command line to execute as an array of strings
        env - the environment to set as an array of strings
        workingDir - the working directory where the command should run
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - probably forwarded from Runtime#exec
        +
      • +
      + + + +
        +
      • +

        isFailure

        +
        public boolean isFailure(int exitValue)
        +
        Description copied from interface: CommandLauncher
        +
        Checks whether exitValue signals a failure on the current + system (OS specific). +

        + Note that this method relies on the conventions of the OS, it + will return false results if the application you are running doesn't + follow these conventions. One notable exception is the Java VM provided + by HP for OpenVMS - it will return 0 if successful (like on any other + platform), but this signals a failure on OpenVMS. So if you execute a new + Java VM on OpenVMS, you cannot trust this method. +

        +
        +
        Specified by:
        +
        isFailure in interface CommandLauncher
        +
        Overrides:
        +
        isFailure in class CommandLauncherImpl
        +
        Parameters:
        exitValue - the exit value (return code) to be checked
        +
        Returns:
        true if exitValue signals a failure
        See Also:
        CommandLauncher.isFailure(int)
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/WinNTCommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/WinNTCommandLauncher.html new file mode 100644 index 0000000..fb730f1 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/WinNTCommandLauncher.html @@ -0,0 +1,307 @@ + + + + + +WinNTCommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.launcher
+

Class WinNTCommandLauncher

+
+
+ +
+
    +
  • +
    +
    All Implemented Interfaces:
    +
    CommandLauncher
    +
    +
    +
    +
    public class WinNTCommandLauncher
    +extends CommandLauncherProxy
    +
    A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when launching + commands in directories other than the current working directory.
    +
    Version:
    +
    $Id: WinNTCommandLauncher.java 1557338 2014-01-11 10:34:22Z sebb $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        WinNTCommandLauncher

        +
        public WinNTCommandLauncher(CommandLauncher launcher)
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        exec

        +
        public Process exec(CommandLine cmd,
        +           Map<String,String> env,
        +           File workingDir)
        +             throws IOException
        +
        Launches the given command in a new process, in the given working + directory.
        +
        +
        Specified by:
        +
        exec in interface CommandLauncher
        +
        Specified by:
        +
        exec in class CommandLauncherImpl
        +
        Parameters:
        cmd - the command line to execute as an array of strings
        env - the environment to set as an array of strings
        workingDir - working directory where the command should run
        +
        Returns:
        the newly created process
        +
        Throws:
        +
        IOException - forwarded from the exec method of the command launcher
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncher.html new file mode 100644 index 0000000..e378567 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncher.html @@ -0,0 +1,222 @@ + + + + + +Uses of Interface org.apache.commons.exec.launcher.CommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Interface
org.apache.commons.exec.launcher.CommandLauncher

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherFactory.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherFactory.html new file mode 100644 index 0000000..06137f0 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherFactory.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.launcher.CommandLauncherFactory (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.launcher.CommandLauncherFactory

+
+
No usage of org.apache.commons.exec.launcher.CommandLauncherFactory
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherImpl.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherImpl.html new file mode 100644 index 0000000..f8e2d06 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherImpl.html @@ -0,0 +1,184 @@ + + + + + +Uses of Class org.apache.commons.exec.launcher.CommandLauncherImpl (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.launcher.CommandLauncherImpl

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherProxy.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherProxy.html new file mode 100644 index 0000000..ec3b2ad --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/CommandLauncherProxy.html @@ -0,0 +1,165 @@ + + + + + +Uses of Class org.apache.commons.exec.launcher.CommandLauncherProxy (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.launcher.CommandLauncherProxy

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/Java13CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/Java13CommandLauncher.html new file mode 100644 index 0000000..3f22531 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/Java13CommandLauncher.html @@ -0,0 +1,158 @@ + + + + + +Uses of Class org.apache.commons.exec.launcher.Java13CommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.launcher.Java13CommandLauncher

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/OS2CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/OS2CommandLauncher.html new file mode 100644 index 0000000..e2017d6 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/OS2CommandLauncher.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.launcher.OS2CommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.launcher.OS2CommandLauncher

+
+
No usage of org.apache.commons.exec.launcher.OS2CommandLauncher
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/VmsCommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/VmsCommandLauncher.html new file mode 100644 index 0000000..34bd4bb --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/VmsCommandLauncher.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.launcher.VmsCommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.launcher.VmsCommandLauncher

+
+
No usage of org.apache.commons.exec.launcher.VmsCommandLauncher
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/WinNTCommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/WinNTCommandLauncher.html new file mode 100644 index 0000000..92d692f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/class-use/WinNTCommandLauncher.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.launcher.WinNTCommandLauncher (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.launcher.WinNTCommandLauncher

+
+
No usage of org.apache.commons.exec.launcher.WinNTCommandLauncher
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-frame.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-frame.html new file mode 100644 index 0000000..427d4d8 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-frame.html @@ -0,0 +1,28 @@ + + + + + +org.apache.commons.exec.launcher (Apache Commons Exec 1.3 API) + + + +

org.apache.commons.exec.launcher

+ + + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-summary.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-summary.html new file mode 100644 index 0000000..39a1766 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-summary.html @@ -0,0 +1,192 @@ + + + + + +org.apache.commons.exec.launcher (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Package org.apache.commons.exec.launcher

+
+
+
    +
  • + + + + + + + + + + + + +
    Interface Summary 
    InterfaceDescription
    CommandLauncher +
    Interface to shield the caller from the various platform-dependent + implementations.
    +
    +
  • +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Class Summary 
    ClassDescription
    CommandLauncherFactory +
    Builds a command launcher for the OS and JVM we are running under.
    +
    CommandLauncherImpl +
    A command launcher for a particular JVM/OS platform.
    +
    CommandLauncherProxy +
    A command launcher that proxies another command launcher.
    +
    Java13CommandLauncher +
    A command launcher for JDK/JRE 1.3 (and higher).
    +
    OS2CommandLauncher +
    A command launcher for OS/2 that uses 'cmd.exe' when launching commands in + directories other than the current working directory.
    +
    VmsCommandLauncher +
    A command launcher for VMS that writes the command to a temporary DCL script + before launching commands.
    +
    WinNTCommandLauncher +
    A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when launching + commands in directories other than the current working directory.
    +
    +
  • +
+
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-tree.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-tree.html new file mode 100644 index 0000000..0e08d55 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-tree.html @@ -0,0 +1,147 @@ + + + + + +org.apache.commons.exec.launcher Class Hierarchy (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Hierarchy For Package org.apache.commons.exec.launcher

+Package Hierarchies: + +
+
+

Class Hierarchy

+ +

Interface Hierarchy

+ +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-use.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-use.html new file mode 100644 index 0000000..18cc41f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/launcher/package-use.html @@ -0,0 +1,166 @@ + + + + + +Uses of Package org.apache.commons.exec.launcher (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Package
org.apache.commons.exec.launcher

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-frame.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-frame.html new file mode 100644 index 0000000..8bc7350 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-frame.html @@ -0,0 +1,41 @@ + + + + + +org.apache.commons.exec (Apache Commons Exec 1.3 API) + + + +

org.apache.commons.exec

+ + + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-summary.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-summary.html new file mode 100644 index 0000000..3d55d50 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-summary.html @@ -0,0 +1,265 @@ + + + + + +org.apache.commons.exec (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Package org.apache.commons.exec

+
+
+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Interface Summary 
    InterfaceDescription
    ExecuteResultHandler +
    The callback handlers for the result of asynchronous process execution.
    +
    ExecuteStreamHandler +
    Used by Execute to handle input and output stream of + subprocesses.
    +
    Executor +
    The main abstraction to start an external process.
    +
    ProcessDestroyer +
    Destroys all registered Process after a certain event, + typically when the VM exits
    +
    TimeoutObserver +
    Interface for classes that want to be notified by Watchdog.
    +
    +
  • +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Class Summary 
    ClassDescription
    CommandLine +
    CommandLine objects help handling command lines specifying processes to + execute.
    +
    DaemonExecutor +
    Runs daemon processes asynchronously.
    +
    DefaultExecuteResultHandler +
    A default implementation of 'ExecuteResultHandler' used for asynchronous + process handling.
    +
    DefaultExecutor +
    The default class to start a subprocess.
    +
    ExecuteWatchdog +
    Destroys a process running for too long.
    +
    InputStreamPumper +
    Copies all data from an System.input stream to an output stream of the executed process.
    +
    LogOutputStream +
    Base class to connect a logging system to the output and/or + error stream of then external process.
    +
    OS +
    Condition that tests the OS type.
    +
    PumpStreamHandler +
    Copies standard output and error of sub-processes to standard output and error + of the parent process.
    +
    ShutdownHookProcessDestroyer +
    Destroys all registered Processes when the VM exits.
    +
    StreamPumper +
    Copies all data from an input stream to an output stream.
    +
    Watchdog +
    Generalization of ExecuteWatchdog
    +
    +
  • +
  • + + + + + + + + + + + + +
    Exception Summary 
    ExceptionDescription
    ExecuteException +
    An exception indicating that the executing a subprocesses failed.
    +
    +
  • +
+
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-tree.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-tree.html new file mode 100644 index 0000000..707f9fe --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-tree.html @@ -0,0 +1,167 @@ + + + + + +org.apache.commons.exec Class Hierarchy (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Hierarchy For Package org.apache.commons.exec

+Package Hierarchies: + +
+
+

Class Hierarchy

+ +

Interface Hierarchy

+ +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-use.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-use.html new file mode 100644 index 0000000..3176519 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/package-use.html @@ -0,0 +1,242 @@ + + + + + +Uses of Package org.apache.commons.exec (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Package
org.apache.commons.exec

+
+
+ +
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/DebugUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/DebugUtils.html new file mode 100644 index 0000000..7e9bd6d --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/DebugUtils.html @@ -0,0 +1,363 @@ + + + + + +DebugUtils (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.util
+

Class DebugUtils

+
+
+ +
+
    +
  • +
    +
    +
    public class DebugUtils
    +extends Object
    +
    Provides debugging support.
    +
    Version:
    +
    $Id: DebugUtils.java 1636203 2014-11-02 22:26:31Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Field Detail

      + + + +
        +
      • +

        COMMONS_EXEC_LENIENT

        +
        public static final String COMMONS_EXEC_LENIENT
        +
        System property to determine how to handle exceptions. When + set to "false" we rethrow the otherwise silently catched + exceptions found in the original code. The default value + is "true"
        +
        See Also:
        Constant Field Values
        +
      • +
      + + + +
        +
      • +

        COMMONS_EXEC_DEBUG

        +
        public static final String COMMONS_EXEC_DEBUG
        +
        System property to determine how to dump an exception. When + set to "true" we print any exception to stderr. The default + value is "false"
        +
        See Also:
        Constant Field Values
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        DebugUtils

        +
        public DebugUtils()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        handleException

        +
        public static void handleException(String msg,
        +                   Exception e)
        +
        Handles an exception based on the system properties.
        +
        Parameters:
        msg - message describing the problem
        e - an exception being handled
        +
      • +
      + + + +
        +
      • +

        isDebugEnabled

        +
        public static boolean isDebugEnabled()
        +
        Determines if debugging is enabled based on the + system property "COMMONS_EXEC_DEBUG".
        +
        Returns:
        true if debug mode is enabled
        +
      • +
      + + + +
        +
      • +

        isLenientEnabled

        +
        public static boolean isLenientEnabled()
        +
        Determines if lenient mode is enabled.
        +
        Returns:
        true if lenient mode is enabled
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/MapUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/MapUtils.html new file mode 100644 index 0000000..33177ea --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/MapUtils.html @@ -0,0 +1,306 @@ + + + + + +MapUtils (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.util
+

Class MapUtils

+
+
+ +
+
    +
  • +
    +
    +
    public class MapUtils
    +extends Object
    +
    Helper classes to manipulate maps to pass substition map to the CommandLine. This class is not part of the public API + and could change without warning.
    +
    Version:
    +
    $Id: MapUtils.java 1636205 2014-11-02 22:32:33Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        MapUtils

        +
        public MapUtils()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        copy

        +
        public static <K,V> Map<K,V> copy(Map<K,V> source)
        +
        Clones a map.
        +
        Type Parameters:
        K - the map key type
        V - the map value type
        Parameters:
        source - the Map to clone
        +
        Returns:
        the cloned map
        +
      • +
      + + + +
        +
      • +

        prefix

        +
        public static <K,V> Map<String,V> prefix(Map<K,V> source,
        +                         String prefix)
        +
        Clones a map and prefixes the keys in the clone, e.g. for mapping "JAVA_HOME" to "env.JAVA_HOME" to simulate the + behaviour of Ant.
        +
        Type Parameters:
        K - the map key type
        V - the map value type
        Parameters:
        source - the source map
        prefix - the prefix used for all names
        +
        Returns:
        the clone of the source map
        +
      • +
      + + + +
        +
      • +

        merge

        +
        public static <K,V> Map<K,V> merge(Map<K,V> lhs,
        +                   Map<K,V> rhs)
        +
        Clones the lhs map and add all things from the rhs map.
        +
        Type Parameters:
        K - the map key type
        V - the map value type
        Parameters:
        lhs - the first map
        rhs - the second map
        +
        Returns:
        the merged map
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/StringUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/StringUtils.html new file mode 100644 index 0000000..3a6cb61 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/StringUtils.html @@ -0,0 +1,399 @@ + + + + + +StringUtils (Apache Commons Exec 1.3 API) + + + + + + + + + + +
+
org.apache.commons.exec.util
+

Class StringUtils

+
+
+ +
+
    +
  • +
    +
    +
    public class StringUtils
    +extends Object
    +
    Supplement of commons-lang, the stringSubstitution() was in a simpler + implementation available in an older commons-lang implementation. + + This class is not part of the public API and could change without + warning.
    +
    Version:
    +
    $Id: StringUtils.java 1636204 2014-11-02 22:30:31Z ggregory $
    +
  • +
+
+
+ +
+
+
    +
  • + +
      +
    • + + +

      Constructor Detail

      + + + +
        +
      • +

        StringUtils

        +
        public StringUtils()
        +
      • +
      +
    • +
    + +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        stringSubstitution

        +
        public static StringBuffer stringSubstitution(String argStr,
        +                              Map<? super String,?> vars,
        +                              boolean isLenient)
        +
        Perform a series of substitutions. +

        + The substitutions are performed by replacing ${variable} in the target string with the value of provided by the + key "variable" in the provided hash table. +

        +

        + A key consists of the following characters: +

        +
          +
        • letter +
        • digit +
        • dot character +
        • hyphen character +
        • plus character +
        • underscore character +
        +
        Parameters:
        argStr - the argument string to be processed
        vars - name/value pairs used for substitution
        isLenient - ignore a key not found in vars or throw a RuntimeException?
        +
        Returns:
        String target string with replacements.
        +
      • +
      + + + +
        +
      • +

        split

        +
        public static String[] split(String input,
        +             String splitChar)
        +
        Split a string into an array of strings based + on a separator.
        +
        Parameters:
        input - what to split
        splitChar - what to split on
        +
        Returns:
        the array of strings
        +
      • +
      + + + +
        +
      • +

        fixFileSeparatorChar

        +
        public static String fixFileSeparatorChar(String arg)
        +
        Fixes the file separator char for the target platform + using the following replacement. + +
          +
        • '/' → File.separatorChar
        • +
        • '\\' → File.separatorChar
        • +
        +
        Parameters:
        arg - the argument to fix
        +
        Returns:
        the transformed argument
        +
      • +
      + + + +
        +
      • +

        toString

        +
        public static String toString(String[] strings,
        +              String separator)
        +
        Concatenates an array of string using a separator.
        +
        Parameters:
        strings - the strings to concatenate
        separator - the separator between two strings
        +
        Returns:
        the concatenated strings
        +
      • +
      + + + +
        +
      • +

        quoteArgument

        +
        public static String quoteArgument(String argument)
        +
        Put quotes around the given String if necessary. +

        + If the argument doesn't include spaces or quotes, return it as is. If it + contains double quotes, use single quotes - else surround the argument by + double quotes. +

        +
        Parameters:
        argument - the argument to be quoted
        +
        Returns:
        the quoted argument
        +
        Throws:
        +
        IllegalArgumentException - If argument contains both types of quotes
        +
      • +
      + + + +
        +
      • +

        isQuoted

        +
        public static boolean isQuoted(String argument)
        +
        Determines if this is a quoted argument - either single or + double quoted.
        +
        Parameters:
        argument - the argument to check
        +
        Returns:
        true when the argument is quoted
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/DebugUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/DebugUtils.html new file mode 100644 index 0000000..f383250 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/DebugUtils.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.util.DebugUtils (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.util.DebugUtils

+
+
No usage of org.apache.commons.exec.util.DebugUtils
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/MapUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/MapUtils.html new file mode 100644 index 0000000..a949142 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/MapUtils.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.util.MapUtils (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.util.MapUtils

+
+
No usage of org.apache.commons.exec.util.MapUtils
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/StringUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/StringUtils.html new file mode 100644 index 0000000..cfeda3f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/class-use/StringUtils.html @@ -0,0 +1,115 @@ + + + + + +Uses of Class org.apache.commons.exec.util.StringUtils (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Class
org.apache.commons.exec.util.StringUtils

+
+
No usage of org.apache.commons.exec.util.StringUtils
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-frame.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-frame.html new file mode 100644 index 0000000..7f72adf --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-frame.html @@ -0,0 +1,20 @@ + + + + + +org.apache.commons.exec.util (Apache Commons Exec 1.3 API) + + + +

org.apache.commons.exec.util

+
+

Classes

+ +
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-summary.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-summary.html new file mode 100644 index 0000000..01d34c4 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-summary.html @@ -0,0 +1,148 @@ + + + + + +org.apache.commons.exec.util (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Package org.apache.commons.exec.util

+
+
+
    +
  • + + + + + + + + + + + + + + + + + + + + +
    Class Summary 
    ClassDescription
    DebugUtils +
    Provides debugging support.
    +
    MapUtils +
    Helper classes to manipulate maps to pass substition map to the CommandLine.
    +
    StringUtils +
    Supplement of commons-lang, the stringSubstitution() was in a simpler + implementation available in an older commons-lang implementation.
    +
    +
  • +
+
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-tree.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-tree.html new file mode 100644 index 0000000..9d3aa26 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-tree.html @@ -0,0 +1,130 @@ + + + + + +org.apache.commons.exec.util Class Hierarchy (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Hierarchy For Package org.apache.commons.exec.util

+Package Hierarchies: + +
+
+

Class Hierarchy

+ +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-use.html b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-use.html new file mode 100644 index 0000000..a774b5b --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/org/apache/commons/exec/util/package-use.html @@ -0,0 +1,115 @@ + + + + + +Uses of Package org.apache.commons.exec.util (Apache Commons Exec 1.3 API) + + + + + + + + + +
+

Uses of Package
org.apache.commons.exec.util

+
+
No usage of org.apache.commons.exec.util
+ + + + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/overview-frame.html b/Holmes/lib/commons-exec-1.3/apidocs/overview-frame.html new file mode 100644 index 0000000..50c86d4 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/overview-frame.html @@ -0,0 +1,22 @@ + + + + + +Overview List (Apache Commons Exec 1.3 API) + + + + + +

 

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/overview-summary.html b/Holmes/lib/commons-exec-1.3/apidocs/overview-summary.html new file mode 100644 index 0000000..394810b --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/overview-summary.html @@ -0,0 +1,141 @@ + + + + + +Overview (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Apache Commons Exec 1.3 API

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
Packages 
PackageDescription
org.apache.commons.exec 
org.apache.commons.exec.environment 
org.apache.commons.exec.launcher 
org.apache.commons.exec.util 
+
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/overview-tree.html b/Holmes/lib/commons-exec-1.3/apidocs/overview-tree.html new file mode 100644 index 0000000..3bd0d7a --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/overview-tree.html @@ -0,0 +1,196 @@ + + + + + +Class Hierarchy (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + + +
+

Class Hierarchy

+ +

Interface Hierarchy

+ +
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/package-list b/Holmes/lib/commons-exec-1.3/apidocs/package-list new file mode 100644 index 0000000..a23be21 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/package-list @@ -0,0 +1,4 @@ +org.apache.commons.exec +org.apache.commons.exec.environment +org.apache.commons.exec.launcher +org.apache.commons.exec.util diff --git a/Holmes/lib/commons-exec-1.3/apidocs/resources/background.gif b/Holmes/lib/commons-exec-1.3/apidocs/resources/background.gif new file mode 100644 index 0000000..f471940 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/apidocs/resources/background.gif differ diff --git a/Holmes/lib/commons-exec-1.3/apidocs/resources/tab.gif b/Holmes/lib/commons-exec-1.3/apidocs/resources/tab.gif new file mode 100644 index 0000000..1a73a83 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/apidocs/resources/tab.gif differ diff --git a/Holmes/lib/commons-exec-1.3/apidocs/resources/titlebar.gif b/Holmes/lib/commons-exec-1.3/apidocs/resources/titlebar.gif new file mode 100644 index 0000000..17443b3 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/apidocs/resources/titlebar.gif differ diff --git a/Holmes/lib/commons-exec-1.3/apidocs/resources/titlebar_end.gif b/Holmes/lib/commons-exec-1.3/apidocs/resources/titlebar_end.gif new file mode 100644 index 0000000..3ad78d4 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/apidocs/resources/titlebar_end.gif differ diff --git a/Holmes/lib/commons-exec-1.3/apidocs/serialized-form.html b/Holmes/lib/commons-exec-1.3/apidocs/serialized-form.html new file mode 100644 index 0000000..a777aa6 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/serialized-form.html @@ -0,0 +1,151 @@ + + + + + +Serialized Form (Apache Commons Exec 1.3 API) + + + + + + +
+ + + + + +
+ + +
+

Serialized Form

+
+
+
    +
  • +

    Package org.apache.commons.exec

    + +
  • +
+
+ +
+ + + + + +
+ + +

Copyright © 2014 The Apache Software Foundation. All rights reserved.

+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/CommandLine.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/CommandLine.html new file mode 100644 index 0000000..357c7e9 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/CommandLine.html @@ -0,0 +1,517 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.File;
+022import java.util.ArrayList;
+023import java.util.HashMap;
+024import java.util.Iterator;
+025import java.util.Map;
+026import java.util.StringTokenizer;
+027import java.util.Vector;
+028
+029import org.apache.commons.exec.util.StringUtils;
+030
+031/**
+032 * CommandLine objects help handling command lines specifying processes to
+033 * execute. The class can be used to a command line by an application.
+034 *
+035 * @version $Id: CommandLine.java 1613094 2014-07-24 12:20:14Z ggregory $
+036 */
+037public class CommandLine {
+038
+039    /**
+040     * The arguments of the command.
+041     */
+042    private final Vector<Argument> arguments = new Vector<Argument>();
+043
+044    /**
+045     * The program to execute.
+046     */
+047    private final String executable;
+048
+049    /**
+050     * A map of name value pairs used to expand command line arguments
+051     */
+052    private Map<String, ?> substitutionMap; // N.B. This can contain values other than Strings
+053
+054    /**
+055     * Was a file being used to set the executable?
+056     */
+057    private final boolean isFile;
+058
+059    /**
+060     * Create a command line from a string.
+061     * 
+062     * @param line the first element becomes the executable, the rest the arguments
+063     * @return the parsed command line
+064     * @throws IllegalArgumentException If line is null or all whitespace
+065     */
+066    public static CommandLine parse(final String line) {
+067        return parse(line, null);
+068    }
+069
+070    /**
+071     * Create a command line from a string.
+072     *
+073     * @param line the first element becomes the executable, the rest the arguments
+074     * @param substitutionMap the name/value pairs used for substitution
+075     * @return the parsed command line
+076     * @throws IllegalArgumentException If line is null or all whitespace
+077     */
+078    public static CommandLine parse(final String line, final Map<String, ?> substitutionMap) {
+079                
+080        if (line == null) {
+081            throw new IllegalArgumentException("Command line can not be null");
+082        } else if (line.trim().length() == 0) {
+083            throw new IllegalArgumentException("Command line can not be empty");
+084        } else {
+085            final String[] tmp = translateCommandline(line);
+086
+087            final CommandLine cl = new CommandLine(tmp[0]);
+088            cl.setSubstitutionMap(substitutionMap);
+089            for (int i = 1; i < tmp.length; i++) {
+090                cl.addArgument(tmp[i]);
+091            }
+092
+093            return cl;
+094        }
+095    }
+096
+097    /**
+098     * Create a command line without any arguments.
+099     *
+100     * @param executable the executable
+101     */
+102    public CommandLine(final String executable) {
+103        this.isFile=false;
+104        this.executable=toCleanExecutable(executable);
+105    }
+106
+107    /**
+108     * Create a command line without any arguments.
+109     *
+110     * @param  executable the executable file
+111     */
+112    public CommandLine(final File executable) {
+113        this.isFile=true;
+114        this.executable=toCleanExecutable(executable.getAbsolutePath());
+115    }
+116
+117    /**
+118     * Copy constructor.
+119     *
+120     * @param other the instance to copy
+121     */
+122    public CommandLine(final CommandLine other)
+123    {
+124        this.executable = other.getExecutable();
+125        this.isFile = other.isFile();
+126        this.arguments.addAll(other.arguments);
+127
+128        if (other.getSubstitutionMap() != null)
+129        {
+130            final Map<String, Object> omap = new HashMap<String, Object>();
+131            this.substitutionMap = omap;
+132            final Iterator<String> iterator = other.substitutionMap.keySet().iterator();
+133            while (iterator.hasNext())
+134            {
+135                final String key = iterator.next();
+136                omap.put(key, other.getSubstitutionMap().get(key));
+137            }
+138        }
+139    }
+140
+141    /**
+142     * Returns the executable.
+143     * 
+144     * @return The executable
+145     */
+146    public String getExecutable() {
+147        // Expand the executable and replace '/' and '\\' with the platform
+148        // specific file separator char. This is safe here since we know
+149        // that this is a platform specific command.
+150        return StringUtils.fixFileSeparatorChar(expandArgument(executable));
+151    }
+152
+153    /**
+154     * Was a file being used to set the executable?
+155     *
+156     * @return true if a file was used for setting the executable 
+157     */
+158    public boolean isFile() {
+159        return isFile;
+160    }
+161
+162    /**
+163     * Add multiple arguments. Handles parsing of quotes and whitespace.
+164     * 
+165     * @param addArguments An array of arguments
+166     * @return The command line itself
+167     */
+168    public CommandLine addArguments(final String[] addArguments) {
+169        return this.addArguments(addArguments, true);
+170    }
+171
+172    /**
+173     * Add multiple arguments.
+174     *
+175     * @param addArguments An array of arguments
+176     * @param handleQuoting Add the argument with/without handling quoting
+177     * @return The command line itself
+178     */
+179    public CommandLine addArguments(final String[] addArguments, final boolean handleQuoting) {
+180        if (addArguments != null) {
+181            for (final String addArgument : addArguments) {
+182                addArgument(addArgument, handleQuoting);
+183            }
+184        }
+185
+186        return this;
+187    }
+188
+189    /**
+190     * Add multiple arguments. Handles parsing of quotes and whitespace.
+191     * Please note that the parsing can have undesired side-effects therefore
+192     * it is recommended to build the command line incrementally.
+193     * 
+194     * @param addArguments An string containing multiple arguments. 
+195     * @return The command line itself
+196     */
+197    public CommandLine addArguments(final String addArguments) {
+198        return this.addArguments(addArguments, true);
+199    }
+200
+201    /**
+202     * Add multiple arguments. Handles parsing of quotes and whitespace.
+203     * Please note that the parsing can have undesired side-effects therefore
+204     * it is recommended to build the command line incrementally.
+205     *
+206     * @param addArguments An string containing multiple arguments.
+207     * @param handleQuoting Add the argument with/without handling quoting
+208     * @return The command line itself
+209     */
+210    public CommandLine addArguments(final String addArguments, final boolean handleQuoting) {
+211        if (addArguments != null) {
+212            final String[] argumentsArray = translateCommandline(addArguments);
+213            addArguments(argumentsArray, handleQuoting);
+214        }
+215
+216        return this;
+217    }
+218
+219    /**
+220     * Add a single argument. Handles quoting.
+221     *
+222     * @param argument The argument to add
+223     * @return The command line itself
+224     * @throws IllegalArgumentException If argument contains both single and double quotes
+225     */
+226    public CommandLine addArgument(final String argument) {
+227        return this.addArgument(argument, true);
+228    }
+229
+230   /**
+231    * Add a single argument.
+232    *
+233    * @param argument The argument to add
+234    * @param handleQuoting Add the argument with/without handling quoting
+235    * @return The command line itself
+236    */
+237   public CommandLine addArgument(final String argument, final boolean handleQuoting) {
+238
+239       if (argument == null)
+240       {
+241           return this;
+242       }
+243
+244       // check if we can really quote the argument - if not throw an
+245       // IllegalArgumentException
+246       if (handleQuoting)
+247       {
+248           StringUtils.quoteArgument(argument);
+249       }
+250
+251       arguments.add(new Argument(argument, handleQuoting));
+252       return this;
+253   }
+254
+255    /**
+256     * Returns the expanded and quoted command line arguments.
+257     *  
+258     * @return The quoted arguments
+259     */
+260    public String[] getArguments() {
+261
+262        Argument currArgument;
+263        String expandedArgument;
+264        final String[] result = new String[arguments.size()];
+265
+266        for (int i=0; i<result.length; i++) {
+267            currArgument = arguments.get(i);
+268            expandedArgument = expandArgument(currArgument.getValue());
+269            result[i] = currArgument.isHandleQuoting() ? StringUtils.quoteArgument(expandedArgument) : expandedArgument;
+270        }
+271
+272        return result;
+273    }
+274
+275    /**
+276     * @return the substitution map
+277     */
+278    public Map<String, ?> getSubstitutionMap() {
+279        return substitutionMap;
+280    }
+281
+282    /**
+283     * Set the substitutionMap to expand variables in the
+284     * command line.
+285     * 
+286     * @param substitutionMap the map
+287     */
+288    public void setSubstitutionMap(final Map<String, ?> substitutionMap) {
+289        this.substitutionMap = substitutionMap;
+290    }
+291
+292    /**
+293     * Returns the command line as an array of strings.
+294     *
+295     * @return The command line as an string array
+296     */
+297    public String[] toStrings() {
+298        final String[] result = new String[arguments.size() + 1];
+299        result[0] = this.getExecutable();
+300        System.arraycopy(getArguments(), 0, result, 1, result.length-1);
+301        return result;
+302    }
+303
+304    /**
+305     * Stringify operator returns the command line as a string.
+306     * Parameters are correctly quoted when containing a space or
+307     * left untouched if the are already quoted. 
+308     *
+309     * @return the command line as single string
+310     */
+311    @Override
+312    public String toString() {
+313        return "[" + StringUtils.toString(toStrings(), ", ") + "]";
+314    }
+315
+316    // --- Implementation ---------------------------------------------------
+317
+318    /**
+319     * Expand variables in a command line argument.
+320     *
+321     * @param argument the argument
+322     * @return the expanded string
+323     */
+324    private String expandArgument(final String argument) {
+325        final StringBuffer stringBuffer = StringUtils.stringSubstitution(argument, this.getSubstitutionMap(), true);
+326        return stringBuffer.toString();
+327    }
+328
+329    /**
+330     * Crack a command line.
+331     *
+332     * @param toProcess
+333     *            the command line to process
+334     * @return the command line broken into strings. An empty or null toProcess
+335     *         parameter results in a zero sized array
+336     */
+337    private static String[] translateCommandline(final String toProcess) {
+338        if (toProcess == null || toProcess.length() == 0) {
+339            // no command? no string
+340            return new String[0];
+341        }
+342
+343        // parse with a simple finite state machine
+344
+345        final int normal = 0;
+346        final int inQuote = 1;
+347        final int inDoubleQuote = 2;
+348        int state = normal;
+349        final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
+350        final ArrayList<String> list = new ArrayList<String>();
+351        StringBuilder current = new StringBuilder();
+352        boolean lastTokenHasBeenQuoted = false;
+353
+354        while (tok.hasMoreTokens()) {
+355            final String nextTok = tok.nextToken();
+356            switch (state) {
+357            case inQuote:
+358                if ("\'".equals(nextTok)) {
+359                    lastTokenHasBeenQuoted = true;
+360                    state = normal;
+361                } else {
+362                    current.append(nextTok);
+363                }
+364                break;
+365            case inDoubleQuote:
+366                if ("\"".equals(nextTok)) {
+367                    lastTokenHasBeenQuoted = true;
+368                    state = normal;
+369                } else {
+370                    current.append(nextTok);
+371                }
+372                break;
+373            default:
+374                if ("\'".equals(nextTok)) {
+375                    state = inQuote;
+376                } else if ("\"".equals(nextTok)) {
+377                    state = inDoubleQuote;
+378                } else if (" ".equals(nextTok)) {
+379                    if (lastTokenHasBeenQuoted || current.length() != 0) {
+380                        list.add(current.toString());
+381                        current = new StringBuilder();
+382                    }
+383                } else {
+384                    current.append(nextTok);
+385                }
+386                lastTokenHasBeenQuoted = false;
+387                break;
+388            }
+389        }
+390
+391        if (lastTokenHasBeenQuoted || current.length() != 0) {
+392            list.add(current.toString());
+393        }
+394
+395        if (state == inQuote || state == inDoubleQuote) {
+396            throw new IllegalArgumentException("Unbalanced quotes in "
+397                    + toProcess);
+398        }
+399
+400        final String[] args = new String[list.size()];
+401        return list.toArray(args);
+402    }
+403
+404    /**
+405     * Cleans the executable string. The argument is trimmed and '/' and '\\' are
+406     * replaced with the platform specific file separator char
+407     *
+408     * @param dirtyExecutable the executable
+409     * @return the platform-specific executable string
+410     */
+411    private String toCleanExecutable(final String dirtyExecutable) {
+412        if (dirtyExecutable == null) {
+413            throw new IllegalArgumentException("Executable can not be null");
+414        } else if (dirtyExecutable.trim().length() == 0) {
+415            throw new IllegalArgumentException("Executable can not be empty");
+416        } else {
+417            return StringUtils.fixFileSeparatorChar(dirtyExecutable);
+418        }
+419    }
+420
+421    /**
+422     * Encapsulates a command line argument.
+423     */
+424    class Argument {
+425
+426        private final String value;
+427        private final boolean handleQuoting;
+428
+429        private Argument(final String value, final boolean handleQuoting)
+430        {
+431            this.value = value.trim();
+432            this.handleQuoting = handleQuoting;
+433        }
+434
+435        private String getValue()
+436        {
+437            return value;
+438        }
+439
+440        private boolean isHandleQuoting()
+441        {
+442            return handleQuoting;
+443        }
+444    }
+445}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DaemonExecutor.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DaemonExecutor.html new file mode 100644 index 0000000..13e0fc5 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DaemonExecutor.html @@ -0,0 +1,114 @@ + + + +Source code + + + +
+
001/*
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 * contributor license agreements.  See the NOTICE file distributed with
+004 * this work for additional information regarding copyright ownership.
+005 * The ASF licenses this file to You under the Apache License, Version 2.0
+006 * (the "License"); you may not use this file except in compliance with
+007 * the License.  You may obtain a copy of the License at
+008 *
+009 *     http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 * Unless required by applicable law or agreed to in writing, software
+012 * distributed under the License is distributed on an "AS IS" BASIS,
+013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 * See the License for the specific language governing permissions and
+015 * limitations under the License.
+016 */
+017package org.apache.commons.exec;
+018
+019/**
+020 * Runs daemon processes asynchronously. Callers are expected to register a {@link ProcessDestroyer} before executing
+021 * any processes.
+022 * 
+023 * @since 1.3
+024 */
+025public class DaemonExecutor extends DefaultExecutor {
+026
+027    /**
+028     * Factory method to create a thread waiting for the result of an asynchronous execution.
+029     *
+030     * @param runnable
+031     *            the runnable passed to the thread
+032     * @param name
+033     *            the name of the thread
+034     * @return the thread
+035     */
+036    @Override
+037    protected Thread createThread(final Runnable runnable, final String name) {
+038        final Thread t = super.createThread(runnable, name);
+039        t.setDaemon(true);
+040        return t;
+041    }
+042}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DefaultExecuteResultHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DefaultExecuteResultHandler.html new file mode 100644 index 0000000..fd8be62 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DefaultExecuteResultHandler.html @@ -0,0 +1,218 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021/**
+022 * A default implementation of 'ExecuteResultHandler' used for asynchronous
+023 * process handling.
+024 *
+025 * @version $Id: DefaultExecuteResultHandler.java 1636057 2014-11-01 21:14:00Z ggregory $
+026 */
+027public class DefaultExecuteResultHandler implements ExecuteResultHandler {
+028
+029    /** the interval polling the result */
+030    private static final int SLEEP_TIME_MS = 50;
+031
+032    /** Keep track if the process is still running */
+033    private volatile boolean hasResult;
+034
+035    /** The exit value of the finished process */
+036    private volatile int exitValue;
+037
+038    /** Any offending exception */
+039    private volatile ExecuteException exception;
+040
+041    /**
+042     * Constructor.
+043     */
+044    public DefaultExecuteResultHandler() {
+045        this.hasResult = false;
+046        this.exitValue = Executor.INVALID_EXITVALUE;
+047    }
+048
+049    /**
+050     * @see org.apache.commons.exec.ExecuteResultHandler#onProcessComplete(int)
+051     */
+052    public void onProcessComplete(final int exitValue) {
+053        this.exitValue = exitValue;
+054        this.exception = null;
+055        this.hasResult = true;
+056    }
+057
+058    /**
+059     * @see org.apache.commons.exec.ExecuteResultHandler#onProcessFailed(org.apache.commons.exec.ExecuteException)
+060     */
+061    public void onProcessFailed(final ExecuteException e) {
+062        this.exitValue = e.getExitValue();            
+063        this.exception = e;
+064        this.hasResult = true;
+065    }
+066
+067    /**
+068     * Get the {@code exception} causing the process execution to fail.
+069     *
+070     * @return Returns the exception.
+071     * @throws IllegalStateException if the process has not exited yet
+072     */
+073    public ExecuteException getException() {
+074
+075        if (!hasResult) {
+076            throw new IllegalStateException("The process has not exited yet therefore no result is available ...");
+077        }
+078
+079        return exception;
+080    }
+081
+082    /**
+083     * Get the {@code exitValue} of the process.
+084     *
+085     * @return Returns the exitValue.
+086     * @throws IllegalStateException if the process has not exited yet
+087     */
+088    public int getExitValue() {
+089
+090        if (!hasResult) {
+091            throw new IllegalStateException("The process has not exited yet therefore no result is available ...");
+092        }
+093
+094        return exitValue;
+095    }
+096
+097    /**
+098     * Has the process exited and a result is available, i.e. exitCode or exception?
+099     *
+100     * @return true if a result of the execution is available
+101     */
+102    public boolean hasResult() {
+103        return hasResult;
+104    }
+105
+106    /**
+107     * Causes the current thread to wait, if necessary, until the
+108     * process has terminated. This method returns immediately if
+109     * the process has already terminated. If the process has
+110     * not yet terminated, the calling thread will be blocked until the
+111     * process exits.
+112     *
+113     * @exception  InterruptedException if the current thread is
+114     *             {@linkplain Thread#interrupt() interrupted} by another
+115     *             thread while it is waiting, then the wait is ended and
+116     *             an {@link InterruptedException} is thrown.
+117     */
+118    public void waitFor() throws InterruptedException {
+119
+120        while (!hasResult()) {
+121            Thread.sleep(SLEEP_TIME_MS);
+122        }
+123    }
+124
+125    /**
+126     * Causes the current thread to wait, if necessary, until the
+127     * process has terminated. This method returns immediately if
+128     * the process has already terminated. If the process has
+129     * not yet terminated, the calling thread will be blocked until the
+130     * process exits.
+131     *
+132     * @param timeout the maximum time to wait in milliseconds
+133     * @exception  InterruptedException if the current thread is
+134     *             {@linkplain Thread#interrupt() interrupted} by another
+135     *             thread while it is waiting, then the wait is ended and
+136     *             an {@link InterruptedException} is thrown.
+137     */
+138    public void waitFor(final long timeout) throws InterruptedException {
+139
+140        final long until = System.currentTimeMillis() + timeout;
+141
+142        while (!hasResult() && System.currentTimeMillis() < until) {
+143            Thread.sleep(SLEEP_TIME_MS);
+144        }
+145    }
+146}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DefaultExecutor.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DefaultExecutor.html new file mode 100644 index 0000000..e175115 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/DefaultExecutor.html @@ -0,0 +1,508 @@ + + + +Source code + + + +
+
001/*
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 * contributor license agreements.  See the NOTICE file distributed with
+004 * this work for additional information regarding copyright ownership.
+005 * The ASF licenses this file to You under the Apache License, Version 2.0
+006 * (the "License"); you may not use this file except in compliance with
+007 * the License.  You may obtain a copy of the License at
+008 *
+009 *     http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 * Unless required by applicable law or agreed to in writing, software
+012 * distributed under the License is distributed on an "AS IS" BASIS,
+013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 * See the License for the specific language governing permissions and
+015 * limitations under the License.
+016 */
+017package org.apache.commons.exec;
+018
+019import java.io.File;
+020import java.io.IOException;
+021import java.util.Map;
+022
+023import org.apache.commons.exec.launcher.CommandLauncher;
+024import org.apache.commons.exec.launcher.CommandLauncherFactory;
+025
+026/**
+027 * The default class to start a subprocess. The implementation
+028 * allows to
+029 * <ul>
+030 *  <li>set a current working directory for the subprocess</li>
+031 *  <li>provide a set of environment variables passed to the subprocess</li>
+032 *  <li>capture the subprocess output of stdout and stderr using an ExecuteStreamHandler</li>
+033 *  <li>kill long-running processes using an ExecuteWatchdog</li>
+034 *  <li>define a set of expected exit values</li>
+035 *  <li>terminate any started processes when the main process is terminating using a ProcessDestroyer</li>
+036 * </ul>
+037 *
+038 * The following example shows the basic usage:
+039 *
+040 * <pre>
+041 * Executor exec = new DefaultExecutor();
+042 * CommandLine cl = new CommandLine("ls -l");
+043 * int exitvalue = exec.execute(cl);
+044 * </pre>
+045 *
+046 * @version $Id: DefaultExecutor.java 1636056 2014-11-01 21:12:52Z ggregory $
+047 */
+048public class DefaultExecutor implements Executor {
+049
+050    /** taking care of output and error stream */
+051    private ExecuteStreamHandler streamHandler;
+052
+053    /** the working directory of the process */
+054    private File workingDirectory;
+055
+056    /** monitoring of long running processes */
+057    private ExecuteWatchdog watchdog;
+058
+059    /** the exit values considered to be successful */
+060    private int[] exitValues;
+061
+062    /** launches the command in a new process */
+063    private final CommandLauncher launcher;
+064
+065    /** optional cleanup of started processes */ 
+066    private ProcessDestroyer processDestroyer;
+067
+068    /** worker thread for asynchronous execution */
+069    private Thread executorThread;
+070
+071    /** the first exception being caught to be thrown to the caller */
+072    private IOException exceptionCaught;
+073
+074    /**
+075     * Default constructor creating a default {@code PumpStreamHandler}
+076     * and sets the working directory of the subprocess to the current
+077     * working directory.
+078     *
+079     * The {@code PumpStreamHandler} pumps the output of the subprocess
+080     * into our {@code System.out} and {@code System.err} to avoid
+081     * into our {@code System.out} and {@code System.err} to avoid
+082     * a blocked or deadlocked subprocess (see{@link java.lang.Process Process}).
+083     */
+084    public DefaultExecutor() {
+085        this.streamHandler = new PumpStreamHandler();
+086        this.launcher = CommandLauncherFactory.createVMLauncher();
+087        this.exitValues = new int[0];
+088        this.workingDirectory = new File(".");
+089        this.exceptionCaught = null;
+090    }
+091
+092    /**
+093     * @see org.apache.commons.exec.Executor#getStreamHandler()
+094     */
+095    public ExecuteStreamHandler getStreamHandler() {
+096        return streamHandler;
+097    }
+098
+099    /**
+100     * @see org.apache.commons.exec.Executor#setStreamHandler(org.apache.commons.exec.ExecuteStreamHandler)
+101     */
+102    public void setStreamHandler(final ExecuteStreamHandler streamHandler) {
+103        this.streamHandler = streamHandler;
+104    }
+105
+106    /**
+107     * @see org.apache.commons.exec.Executor#getWatchdog()
+108     */
+109    public ExecuteWatchdog getWatchdog() {
+110        return watchdog;
+111    }
+112
+113    /**
+114     * @see org.apache.commons.exec.Executor#setWatchdog(org.apache.commons.exec.ExecuteWatchdog)
+115     */
+116    public void setWatchdog(final ExecuteWatchdog watchDog) {
+117        this.watchdog = watchDog;
+118    }
+119
+120    /**
+121     * @see org.apache.commons.exec.Executor#getProcessDestroyer()
+122     */
+123    public ProcessDestroyer getProcessDestroyer() {
+124      return this.processDestroyer;
+125    }
+126
+127    /**
+128     * @see org.apache.commons.exec.Executor#setProcessDestroyer(ProcessDestroyer)
+129     */
+130    public void setProcessDestroyer(final ProcessDestroyer processDestroyer) {
+131      this.processDestroyer = processDestroyer;
+132    }
+133
+134    /**
+135     * @see org.apache.commons.exec.Executor#getWorkingDirectory()
+136     */
+137    public File getWorkingDirectory() {
+138        return workingDirectory;
+139    }
+140
+141    /**
+142     * @see org.apache.commons.exec.Executor#setWorkingDirectory(java.io.File)
+143     */
+144    public void setWorkingDirectory(final File dir) {
+145        this.workingDirectory = dir;
+146    }
+147
+148    /**
+149     * @see org.apache.commons.exec.Executor#execute(CommandLine)
+150     */
+151    public int execute(final CommandLine command) throws ExecuteException,
+152            IOException {
+153        return execute(command, (Map<String, String>) null);
+154    }
+155
+156    /**
+157     * @see org.apache.commons.exec.Executor#execute(CommandLine, java.util.Map)
+158     */
+159    public int execute(final CommandLine command, final Map<String, String> environment)
+160            throws ExecuteException, IOException {
+161
+162        if (workingDirectory != null && !workingDirectory.exists()) {
+163            throw new IOException(workingDirectory + " doesn't exist.");
+164        }
+165        
+166        return executeInternal(command, environment, workingDirectory, streamHandler);
+167
+168    }
+169
+170    /**
+171     * @see org.apache.commons.exec.Executor#execute(CommandLine,
+172     *      org.apache.commons.exec.ExecuteResultHandler)
+173     */
+174    public void execute(final CommandLine command, final ExecuteResultHandler handler)
+175            throws ExecuteException, IOException {
+176        execute(command, null, handler);
+177    }
+178
+179    /**
+180     * @see org.apache.commons.exec.Executor#execute(CommandLine,
+181     *      java.util.Map, org.apache.commons.exec.ExecuteResultHandler)
+182     */
+183    public void execute(final CommandLine command, final Map<String, String> environment,
+184            final ExecuteResultHandler handler) throws ExecuteException, IOException {
+185
+186        if (workingDirectory != null && !workingDirectory.exists()) {
+187            throw new IOException(workingDirectory + " doesn't exist.");
+188        }
+189
+190        if (watchdog != null) {
+191            watchdog.setProcessNotStarted();
+192        }
+193
+194        final Runnable runnable = new Runnable()
+195        {
+196            public void run()
+197            {
+198                int exitValue = Executor.INVALID_EXITVALUE;
+199                try {
+200                    exitValue = executeInternal(command, environment, workingDirectory, streamHandler);
+201                    handler.onProcessComplete(exitValue);
+202                } catch (final ExecuteException e) {
+203                    handler.onProcessFailed(e);
+204                } catch (final Exception e) {
+205                    handler.onProcessFailed(new ExecuteException("Execution failed", exitValue, e));
+206                }
+207            }
+208        };
+209
+210        this.executorThread = createThread(runnable, "Exec Default Executor");
+211        getExecutorThread().start();
+212    }
+213
+214    /** @see org.apache.commons.exec.Executor#setExitValue(int) */
+215    public void setExitValue(final int value) {
+216        this.setExitValues(new int[] {value});
+217    }
+218
+219
+220    /** @see org.apache.commons.exec.Executor#setExitValues(int[]) */
+221    public void setExitValues(final int[] values) {
+222        this.exitValues = values == null ? null : (int[]) values.clone();
+223    }
+224
+225    /** @see org.apache.commons.exec.Executor#isFailure(int) */
+226    public boolean isFailure(final int exitValue) {
+227
+228        if (this.exitValues == null) {
+229            return false;
+230        }
+231        else if (this.exitValues.length == 0) {
+232            return this.launcher.isFailure(exitValue);
+233        }
+234        else {
+235            for (final int exitValue2 : this.exitValues) {
+236                if (exitValue2 == exitValue) {
+237                    return false;
+238                }
+239            }
+240        }
+241        return true;
+242    }
+243
+244    /**
+245     * Factory method to create a thread waiting for the result of an
+246     * asynchronous execution.
+247     *
+248     * @param runnable the runnable passed to the thread
+249     * @param name the name of the thread
+250     * @return the thread
+251     */
+252    protected Thread createThread(final Runnable runnable, final String name) {
+253        return new Thread(runnable, name);
+254    }
+255
+256    /**
+257     * Creates a process that runs a command.
+258     *
+259     * @param command
+260     *            the command to run
+261     * @param env
+262     *            the environment for the command
+263     * @param dir
+264     *            the working directory for the command
+265     * @return the process started
+266     * @throws IOException
+267     *             forwarded from the particular launcher used
+268     */
+269    protected Process launch(final CommandLine command, final Map<String, String> env,
+270            final File dir) throws IOException {
+271
+272        if (this.launcher == null) {
+273            throw new IllegalStateException("CommandLauncher can not be null");
+274        }
+275
+276        if (dir != null && !dir.exists()) {
+277            throw new IOException(dir + " doesn't exist.");
+278        }
+279        return this.launcher.exec(command, env, dir);
+280    }
+281
+282    /**
+283     * Get the worker thread being used for asynchronous execution.
+284     *
+285     * @return the worker thread
+286     */
+287    protected Thread getExecutorThread() {
+288        return executorThread;
+289    }
+290    
+291    /**
+292     * Close the streams belonging to the given Process.
+293     *
+294     * @param process the <CODE>Process</CODE>.
+295     */
+296    private void closeProcessStreams(final Process process) {
+297
+298        try {
+299            process.getInputStream().close();
+300        }
+301        catch (final IOException e) {
+302            setExceptionCaught(e);
+303        }
+304
+305        try {
+306            process.getOutputStream().close();
+307        }
+308        catch (final IOException e) {
+309            setExceptionCaught(e);
+310        }
+311
+312        try {
+313            process.getErrorStream().close();
+314        }
+315        catch (final IOException e) {
+316            setExceptionCaught(e);
+317        }
+318    }
+319
+320    /**
+321     * Execute an internal process. If the executing thread is interrupted while waiting for the
+322     * child process to return the child process will be killed.
+323     *
+324     * @param command the command to execute
+325     * @param environment the execution environment
+326     * @param dir the working directory
+327     * @param streams process the streams (in, out, err) of the process
+328     * @return the exit code of the process
+329     * @throws IOException executing the process failed
+330     */
+331    private int executeInternal(final CommandLine command, final Map<String, String> environment,
+332            final File dir, final ExecuteStreamHandler streams) throws IOException {
+333
+334        setExceptionCaught(null);
+335
+336        final Process process = this.launch(command, environment, dir);
+337
+338        try {
+339            streams.setProcessInputStream(process.getOutputStream());
+340            streams.setProcessOutputStream(process.getInputStream());
+341            streams.setProcessErrorStream(process.getErrorStream());
+342        } catch (final IOException e) {
+343            process.destroy();
+344            throw e;
+345        }
+346
+347        streams.start();
+348
+349        try {
+350
+351            // add the process to the list of those to destroy if the VM exits
+352            if (this.getProcessDestroyer() != null) {
+353              this.getProcessDestroyer().add(process);
+354            }
+355
+356            // associate the watchdog with the newly created process
+357            if (watchdog != null) {
+358                watchdog.start(process);
+359            }
+360
+361            int exitValue = Executor.INVALID_EXITVALUE;
+362
+363            try {
+364                exitValue = process.waitFor();
+365            } catch (final InterruptedException e) {
+366                process.destroy();
+367            }
+368            finally {
+369                // see http://bugs.sun.com/view_bug.do?bug_id=6420270
+370                // see https://issues.apache.org/jira/browse/EXEC-46
+371                // Process.waitFor should clear interrupt status when throwing InterruptedException
+372                // but we have to do that manually
+373                Thread.interrupted();
+374            }            
+375
+376            if (watchdog != null) {
+377                watchdog.stop();
+378            }
+379
+380            try {
+381                streams.stop();
+382            }
+383            catch (final IOException e) {
+384                setExceptionCaught(e);
+385            }
+386
+387            closeProcessStreams(process);
+388
+389            if (getExceptionCaught() != null) {
+390                throw getExceptionCaught();
+391            }
+392
+393            if (watchdog != null) {
+394                try {
+395                    watchdog.checkException();
+396                } catch (final IOException e) {
+397                    throw e;
+398                } catch (final Exception e) {
+399                    throw new IOException(e.getMessage());
+400                }
+401            }
+402
+403            if (this.isFailure(exitValue)) {
+404                throw new ExecuteException("Process exited with an error: " + exitValue, exitValue);
+405            }
+406
+407            return exitValue;
+408        } finally {
+409            // remove the process to the list of those to destroy if the VM exits
+410            if (this.getProcessDestroyer() != null) {
+411              this.getProcessDestroyer().remove(process);
+412            }
+413        }
+414    }
+415
+416    /**
+417     * Keep track of the first IOException being thrown.
+418     *
+419     * @param e the IOException
+420     */
+421    private void setExceptionCaught(final IOException e) {
+422        if (this.exceptionCaught == null) {
+423            this.exceptionCaught = e;
+424        }
+425    }
+426
+427    /**
+428     * Get the first IOException being thrown.
+429     *
+430     * @return the first IOException being caught
+431     */
+432    private IOException getExceptionCaught() {
+433        return this.exceptionCaught;
+434    }
+435
+436}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteException.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteException.html new file mode 100644 index 0000000..62faee4 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteException.html @@ -0,0 +1,160 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.IOException;
+022
+023/**
+024 * An exception indicating that the executing a subprocesses failed.
+025 *
+026 * @version $Id: ExecuteException.java 1636056 2014-11-01 21:12:52Z ggregory $
+027 */
+028public class ExecuteException extends IOException {
+029
+030    /**
+031     * Comment for {@code serialVersionUID}.
+032     */
+033    private static final long serialVersionUID = 3256443620654331699L;
+034
+035    /**
+036     * The underlying cause of this exception.
+037     */
+038    private final Throwable cause;
+039
+040    /**
+041     * The exit value returned by the failed process
+042     */
+043    private final int exitValue;
+044    
+045    /**
+046     * Construct a new exception with the specified detail message.
+047     * 
+048     * @param message
+049     *            The detail message
+050     * @param exitValue The exit value
+051     */
+052    public ExecuteException(final String message, final int exitValue) {
+053        super(message + " (Exit value: " + exitValue + ")");
+054        this.cause = null;
+055        this.exitValue = exitValue;
+056    }
+057
+058    /**
+059     * Construct a new exception with the specified detail message and cause.
+060     * 
+061     * @param message
+062     *            The detail message
+063     * @param exitValue The exit value
+064     * @param cause
+065     *            The underlying cause
+066     */
+067    public ExecuteException(final String message, final int exitValue, final Throwable cause) {
+068        super(message + " (Exit value: " + exitValue + ". Caused by " + cause + ")");
+069        this.cause = cause; // Two-argument version requires JDK 1.4 or later
+070        this.exitValue = exitValue;
+071    }
+072
+073    /**
+074     * Return the underlying cause of this exception (if any).
+075     */
+076    @Override
+077    public Throwable getCause() {
+078        return this.cause;
+079    }
+080
+081    /**
+082     * Gets the exit value returned by the failed process
+083     * @return The exit value
+084     */
+085    public int getExitValue() {
+086        return exitValue;
+087    }
+088}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteResultHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteResultHandler.html new file mode 100644 index 0000000..f38dd91 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteResultHandler.html @@ -0,0 +1,117 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021/**
+022 * The callback handlers for the result of asynchronous process execution. When a
+023 * process is started asynchronously the callback provides you with the result of
+024 * the executed process, i.e. the exit value or an exception. 
+025 *
+026 * @see org.apache.commons.exec.Executor#execute(CommandLine, java.util.Map, ExecuteResultHandler)
+027 *
+028 * @version $Id: ExecuteResultHandler.java 1636056 2014-11-01 21:12:52Z ggregory $
+029 */
+030public interface ExecuteResultHandler {
+031
+032  /**
+033   * The asynchronous execution completed.
+034   *
+035   * @param exitValue the exit value of the sub-process
+036   */
+037    void onProcessComplete(int exitValue);
+038
+039  /**
+040   * The asynchronous execution failed.
+041   *
+042   * @param e the {@code ExecuteException} containing the root cause
+043   */
+044    void onProcessFailed(ExecuteException e);
+045}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteStreamHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteStreamHandler.html new file mode 100644 index 0000000..f04d1d0 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteStreamHandler.html @@ -0,0 +1,150 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.IOException;
+022import java.io.InputStream;
+023import java.io.OutputStream;
+024
+025/**
+026 * Used by {@code Execute} to handle input and output stream of
+027 * subprocesses.
+028 *
+029 * @version $Id: ExecuteStreamHandler.java 1636064 2014-11-01 22:01:19Z ggregory $
+030 */
+031public interface ExecuteStreamHandler {
+032
+033    /**
+034     * Install a handler for the input stream of the subprocess.
+035     * 
+036     * @param os
+037     *            output stream to write to the standard input stream of the subprocess
+038     * @throws IOException
+039     *             thrown when an I/O exception occurs.
+040     */
+041    void setProcessInputStream(OutputStream os) throws IOException;
+042
+043    /**
+044     * Install a handler for the error stream of the subprocess.
+045     * 
+046     * @param is
+047     *            input stream to read from the error stream from the subprocess
+048     * @throws IOException
+049     *             thrown when an I/O exception occurs.
+050     */
+051    void setProcessErrorStream(InputStream is) throws IOException;
+052
+053    /**
+054     * Install a handler for the output stream of the subprocess.
+055     * 
+056     * @param is
+057     *            input stream to read from the error stream from the subprocess
+058     * @throws IOException
+059     *             thrown when an I/O exception occurs.
+060     */
+061    void setProcessOutputStream(InputStream is) throws IOException;
+062
+063    /**
+064     * Start handling of the streams.
+065     * 
+066     * @throws IOException
+067     *             thrown when an I/O exception occurs.
+068     */
+069    void start() throws IOException;
+070
+071    /**
+072     * Stop handling of the streams - will not be restarted. Will wait for pump threads to complete.
+073     * 
+074     * @throws IOException
+075     *             thrown when an I/O exception occurs.
+076     */
+077    void stop() throws IOException;
+078}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteWatchdog.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteWatchdog.html new file mode 100644 index 0000000..2343df1 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ExecuteWatchdog.html @@ -0,0 +1,307 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import org.apache.commons.exec.util.DebugUtils;
+022
+023/**
+024 * Destroys a process running for too long. For example:
+025 *
+026 * <pre>
+027 * ExecuteWatchdog watchdog = new ExecuteWatchdog(30000);
+028 * Executer exec = new Executer(myloghandler, watchdog);
+029 * exec.setCommandLine(mycmdline);
+030 * int exitvalue = exec.execute();
+031 * if (Execute.isFailure(exitvalue) &amp;&amp; watchdog.killedProcess()) {
+032 *     // it was killed on purpose by the watchdog
+033 * }
+034 * </pre>
+035 *
+036 * When starting an asynchronous process than 'ExecuteWatchdog' is the
+037 * keeper of the process handle. In some cases it is useful not to define
+038 * a timeout (and pass 'INFINITE_TIMEOUT') and to kill the process explicitly
+039 * using 'destroyProcess()'.
+040 * <p>
+041 * Please note that ExecuteWatchdog is processed asynchronously, e.g. it might
+042 * be still attached to a process even after the DefaultExecutor.execute 
+043 * has returned.
+044 *
+045 * @see org.apache.commons.exec.Executor
+046 * @see org.apache.commons.exec.Watchdog
+047 *
+048 * @version $Id: ExecuteWatchdog.java 1612032 2014-07-20 06:30:44Z ggregory $
+049 */
+050public class ExecuteWatchdog implements TimeoutObserver {
+051
+052    /** The marker for an infinite timeout */
+053    public static final long INFINITE_TIMEOUT = -1;
+054    
+055    /** The process to execute and watch for duration. */
+056    private Process process;
+057
+058    /** Is a user-supplied timeout in use */
+059    private final boolean hasWatchdog;
+060
+061    /** Say whether or not the watchdog is currently monitoring a process. */
+062    private boolean watch;
+063
+064    /** Exception that might be thrown during the process execution. */
+065    private Exception caught;
+066
+067    /** Say whether or not the process was killed due to running overtime. */
+068    private boolean killedProcess;
+069
+070    /** Will tell us whether timeout has occurred. */
+071    private final Watchdog watchdog;
+072
+073    /** Indicates that the process is verified as started */
+074    private volatile boolean processStarted;
+075
+076    /**
+077     * Creates a new watchdog with a given timeout.
+078     * 
+079     * @param timeout
+080     *            the timeout for the process in milliseconds. It must be
+081     *            greater than 0 or 'INFINITE_TIMEOUT'
+082     */
+083    public ExecuteWatchdog(final long timeout) {
+084        this.killedProcess = false;
+085        this.watch = false;
+086        this.hasWatchdog = timeout != INFINITE_TIMEOUT;
+087        this.processStarted = false;
+088        if (this.hasWatchdog) {
+089            this.watchdog = new Watchdog(timeout);
+090            this.watchdog.addTimeoutObserver(this);
+091        }
+092        else {
+093            this.watchdog = null;
+094        }
+095    }
+096
+097    /**
+098     * Watches the given process and terminates it, if it runs for too long. All
+099     * information from the previous run are reset.
+100     * 
+101     * @param processToMonitor
+102     *            the process to monitor. It cannot be {@code null}
+103     * @throws IllegalStateException
+104     *             if a process is still being monitored.
+105     */
+106    public synchronized void start(final Process processToMonitor) {
+107        if (processToMonitor == null) {
+108            throw new NullPointerException("process is null.");
+109        }
+110        if (this.process != null) {
+111            throw new IllegalStateException("Already running.");
+112        }
+113        this.caught = null;
+114        this.killedProcess = false;
+115        this.watch = true;
+116        this.process = processToMonitor;
+117        this.processStarted = true;
+118        this.notifyAll();
+119        if (this.hasWatchdog) {
+120            watchdog.start();
+121        }
+122    }
+123
+124    /**
+125     * Stops the watcher. It will notify all threads possibly waiting on this
+126     * object.
+127     */
+128    public synchronized void stop() {
+129        if (hasWatchdog) {
+130            watchdog.stop();
+131        }
+132        watch = false;
+133        process = null;
+134    }
+135
+136    /**
+137     * Destroys the running process manually.
+138     */
+139    public synchronized void destroyProcess() {
+140        ensureStarted();
+141        this.timeoutOccured(null);
+142        this.stop();
+143    }
+144
+145    /**
+146     * Called after watchdog has finished.
+147     */
+148    public synchronized void timeoutOccured(final Watchdog w) {
+149        try {
+150            try {
+151                // We must check if the process was not stopped
+152                // before being here
+153                if (process != null) {
+154                    process.exitValue();
+155                }
+156            } catch (final IllegalThreadStateException itse) {
+157                // the process is not terminated, if this is really
+158                // a timeout and not a manual stop then destroy it.
+159                if (watch) {
+160                    killedProcess = true;
+161                    process.destroy();
+162                }
+163            }
+164        } catch (final Exception e) {
+165            caught = e;
+166            DebugUtils.handleException("Getting the exit value of the process failed", e);
+167        } finally {
+168            cleanUp();
+169        }
+170    }
+171
+172
+173    /**
+174     * This method will rethrow the exception that was possibly caught during
+175     * the run of the process. It will only remains valid once the process has
+176     * been terminated either by 'error', timeout or manual intervention.
+177     * Information will be discarded once a new process is ran.
+178     * 
+179     * @throws Exception
+180     *             a wrapped exception over the one that was silently swallowed
+181     *             and stored during the process run.
+182     */
+183    public synchronized void checkException() throws Exception {
+184        if (caught != null) {
+185            throw caught;
+186        }
+187    }
+188
+189    /**
+190     * Indicates whether or not the watchdog is still monitoring the process.
+191     * 
+192     * @return {@code true} if the process is still running, otherwise
+193     *         {@code false}.
+194     */
+195    public synchronized boolean isWatching() {
+196        ensureStarted();
+197        return watch;
+198    }
+199
+200    /**
+201     * Indicates whether the last process run was killed.
+202     * 
+203     * @return {@code true} if the process was killed
+204     *         {@code false}.
+205     */
+206    public synchronized boolean killedProcess() {
+207        return killedProcess;
+208    }
+209
+210    /**
+211     * reset the monitor flag and the process.
+212     */
+213    protected synchronized void cleanUp() {
+214        watch = false;
+215        process = null;
+216    }
+217
+218    void setProcessNotStarted() {
+219        processStarted = false;
+220    }
+221
+222    /**
+223     * Ensures that the process is started, so we do not race with asynch execution.
+224     * The caller of this method must be holding the lock on this
+225     */
+226    private void ensureStarted() {
+227        while (!processStarted) {
+228            try {
+229                this.wait();
+230            } catch (final InterruptedException e) {
+231                throw new RuntimeException(e.getMessage());
+232            }
+233        }
+234    }
+235}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/Executor.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/Executor.html new file mode 100644 index 0000000..f3bff22 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/Executor.html @@ -0,0 +1,282 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.File;
+022import java.io.IOException;
+023import java.util.Map;
+024
+025/**
+026 * The main abstraction to start an external process.
+027 *
+028 * The interface allows to
+029 * <ul>
+030 *  <li>set a current working directory for the subprocess</li>
+031 *  <li>provide a set of environment variables passed to the subprocess</li>
+032 *  <li>capture the subprocess output of stdout and stderr using an ExecuteStreamHandler</li>
+033 *  <li>kill long-running processes using an ExecuteWatchdog</li>
+034 *  <li>define a set of expected exit values</li>
+035 *  <li>terminate any started processes when the main process is terminating using a ProcessDestroyer</li>
+036 * </ul>
+037 *
+038 * The following example shows the basic usage:
+039 *
+040 * <pre>
+041 * Executor exec = new DefaultExecutor();
+042 * CommandLine cl = new CommandLine("ls -l");
+043 * int exitvalue = exec.execute(cl);
+044 * </pre>
+045 *
+046 * @version $Id: Executor.java 1636056 2014-11-01 21:12:52Z ggregory $
+047 */
+048
+049public interface Executor {
+050
+051    /** Invalid exit code. */
+052    int INVALID_EXITVALUE = 0xdeadbeef;
+053
+054    /**
+055     * Define the {@code exitValue} of the process to be considered
+056     * successful. If a different exit value is returned by
+057     * the process then {@link org.apache.commons.exec.Executor#execute(CommandLine)}
+058     * will throw an {@link org.apache.commons.exec.ExecuteException} 
+059     *
+060     * @param value the exit code representing successful execution
+061     */
+062    void setExitValue(final int value);
+063
+064    /**
+065     * Define a list of {@code exitValue} of the process to be considered
+066     * successful. The caller can pass one of the following values
+067     * <ul>
+068     *  <li>an array of exit values to be considered successful</li>
+069     *  <li>an empty array for auto-detect of successful exit codes relying on {@link org.apache.commons.exec.Executor#isFailure(int)}</li>
+070     *  <li>null to indicate to skip checking of exit codes</li>
+071     * </ul>
+072     *
+073     * If an undefined exit value is returned by the process then
+074     * {@link org.apache.commons.exec.Executor#execute(CommandLine)}  will
+075     * throw an {@link org.apache.commons.exec.ExecuteException}.
+076     *
+077     * @param values a list of the exit codes
+078     */
+079    void setExitValues(final int[] values);
+080
+081    /**
+082     * Checks whether {@code exitValue} signals a failure. If no
+083     * exit values are set than the default conventions of the OS is
+084     * used. e.g. most OS regard an exit code of '0' as successful
+085     * execution and everything else as failure.
+086     *
+087     * @param exitValue the exit value (return code) to be checked
+088     * @return {@code true} if {@code exitValue} signals a failure
+089     */
+090    boolean isFailure(final int exitValue);
+091
+092    /**
+093     * Get the StreamHandler used for providing input and
+094     * retrieving the output.
+095     * 
+096     * @return the StreamHandler 
+097     */
+098    ExecuteStreamHandler getStreamHandler();
+099
+100    /**
+101     * Set a custom the StreamHandler used for providing
+102     * input and retrieving the output. If you don't provide
+103     * a proper stream handler the executed process might block
+104     * when writing to stdout and/or stderr (see
+105     * {@link java.lang.Process Process}).
+106     *
+107     * @param streamHandler the stream handler
+108     */
+109    void setStreamHandler(ExecuteStreamHandler streamHandler);
+110
+111    /**
+112     * Get the watchdog used to kill of processes running,
+113     * typically, too long time.
+114     *
+115     * @return the watchdog
+116     */
+117    ExecuteWatchdog getWatchdog();
+118
+119    /**
+120     * Set the watchdog used to kill of processes running, 
+121     * typically, too long time.
+122     *
+123     * @param watchDog the watchdog
+124     */
+125    void setWatchdog(ExecuteWatchdog watchDog);
+126
+127    /**
+128     * Set the handler for cleanup of started processes if the main process
+129     * is going to terminate.
+130     *
+131     * @return the ProcessDestroyer
+132     */
+133    ProcessDestroyer getProcessDestroyer();
+134
+135    /**
+136     * Get the handler for cleanup of started processes if the main process
+137     * is going to terminate.
+138     *
+139     * @param processDestroyer the ProcessDestroyer
+140     */
+141    void setProcessDestroyer(ProcessDestroyer processDestroyer);
+142
+143    /**
+144     * Get the working directory of the created process.
+145     *
+146     * @return the working directory
+147     */
+148    File getWorkingDirectory();
+149
+150    /**
+151     * Set the working directory of the created process. The
+152     * working directory must exist when you start the process.
+153     *
+154     * @param dir the working directory
+155     */
+156    void setWorkingDirectory(File dir);
+157
+158    /**
+159     * Methods for starting synchronous execution. The child process inherits
+160     * all environment variables of the parent process.
+161     *
+162     * @param command the command to execute
+163     * @return process exit value
+164     * @throws ExecuteException execution of subprocess failed or the
+165     *          subprocess returned a exit value indicating a failure
+166     *          {@link Executor#setExitValue(int)}.
+167     */
+168    int execute(CommandLine command)
+169        throws ExecuteException, IOException;
+170
+171    /**
+172     * Methods for starting synchronous execution.
+173     *
+174     * @param command the command to execute
+175     * @param environment The environment for the new process. If null, the
+176     *          environment of the current process is used.
+177     * @return process exit value
+178     * @throws ExecuteException execution of subprocess failed or the
+179     *          subprocess returned a exit value indicating a failure
+180     *          {@link Executor#setExitValue(int)}.
+181     */
+182    int execute(CommandLine command, Map<String, String> environment)
+183        throws ExecuteException, IOException;
+184    
+185    /**
+186     * Methods for starting asynchronous execution. The child process inherits
+187     * all environment variables of the parent process. Result provided to
+188     * callback handler.
+189     *
+190     * @param command the command to execute
+191     * @param handler capture process termination and exit code
+192     * @throws ExecuteException execution of subprocess failed
+193     */
+194    void execute(CommandLine command, ExecuteResultHandler handler)
+195        throws ExecuteException, IOException;
+196
+197    /**
+198     * Methods for starting asynchronous execution. The child process inherits
+199     * all environment variables of the parent process. Result provided to
+200     * callback handler.
+201     *
+202     * @param command the command to execute
+203     * @param environment The environment for the new process. If null, the
+204     *          environment of the current process is used.
+205     * @param handler capture process termination and exit code 
+206     * @throws ExecuteException execution of subprocess failed     
+207     */
+208    void execute(CommandLine command, Map<String, String> environment, ExecuteResultHandler handler)
+209        throws ExecuteException, IOException;
+210}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/InputStreamPumper.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/InputStreamPumper.html new file mode 100644 index 0000000..008d808 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/InputStreamPumper.html @@ -0,0 +1,155 @@ + + + +Source code + + + +
+
001/*
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.InputStream;
+022import java.io.OutputStream;
+023
+024import org.apache.commons.exec.util.DebugUtils;
+025
+026/**
+027 * Copies all data from an System.input stream to an output stream of the executed process.
+028 *
+029 * @version $Id: InputStreamPumper.java 1557263 2014-01-10 21:18:09Z ggregory $
+030 */
+031public class InputStreamPumper implements Runnable {
+032
+033    public static final int SLEEPING_TIME = 100;
+034
+035    /** the input stream to pump from */
+036    private final InputStream is;
+037
+038    /** the output stream to pmp into */
+039    private final OutputStream os;
+040
+041    /** flag to stop the stream pumping */
+042    private volatile boolean stop;
+043
+044
+045    /**
+046     * Create a new stream pumper.
+047     *
+048     * @param is input stream to read data from
+049     * @param os output stream to write data to.
+050     */
+051    public InputStreamPumper(final InputStream is, final OutputStream os) {
+052        this.is = is;
+053        this.os = os;
+054        this.stop = false;
+055    }
+056
+057
+058    /**
+059     * Copies data from the input stream to the output stream. Terminates as
+060     * soon as the input stream is closed or an error occurs.
+061     */
+062    public void run() {
+063        try {
+064            while (!stop) {
+065                while (is.available() > 0 && !stop) {
+066                    os.write(is.read());
+067                }
+068                os.flush();
+069                Thread.sleep(SLEEPING_TIME);
+070            }
+071        } catch (final Exception e) {
+072            final String msg = "Got exception while reading/writing the stream";
+073            DebugUtils.handleException(msg ,e);
+074        } finally {
+075        }
+076    }
+077
+078
+079    public void stopProcessing() {
+080        stop = true;
+081    }
+082
+083}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/LogOutputStream.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/LogOutputStream.html new file mode 100644 index 0000000..18d23a8 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/LogOutputStream.html @@ -0,0 +1,254 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.ByteArrayOutputStream;
+022import java.io.IOException;
+023import java.io.OutputStream;
+024
+025/**
+026 * Base class to connect a logging system to the output and/or
+027 * error stream of then external process. The implementation
+028 * parses the incoming data to construct a line and passes
+029 * the complete line to an user-defined implementation.
+030 *
+031 * @version $Id: LogOutputStream.java 1636056 2014-11-01 21:12:52Z ggregory $
+032 */
+033public abstract class LogOutputStream
+034  extends OutputStream {
+035
+036    /** Initial buffer size. */
+037    private static final int INTIAL_SIZE = 132;
+038
+039    /** Carriage return */
+040    private static final int CR = 0x0d;
+041
+042    /** Linefeed */
+043    private static final int LF = 0x0a;
+044
+045    /** the internal buffer */
+046    private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(
+047      INTIAL_SIZE);
+048
+049    private boolean skip = false;
+050
+051    private final int level;
+052
+053    /**
+054     * Creates a new instance of this class.
+055     * Uses the default level of 999.
+056     */
+057    public LogOutputStream() {
+058        this(999);
+059    }
+060
+061    /**
+062     * Creates a new instance of this class.
+063     *
+064     * @param level loglevel used to log data written to this stream.
+065     */
+066    public LogOutputStream(final int level) {
+067        this.level = level;
+068    }
+069
+070    /**
+071     * Write the data to the buffer and flush the buffer, if a line separator is
+072     * detected.
+073     *
+074     * @param cc data to log (byte).
+075     * @see java.io.OutputStream#write(int)
+076     */
+077    @Override
+078    public void write(final int cc) throws IOException {
+079        final byte c = (byte) cc;
+080        if (c == '\n' || c == '\r') {
+081            if (!skip) {
+082                processBuffer();
+083            }
+084        } else {
+085            buffer.write(cc);
+086        }
+087        skip = c == '\r';
+088    }
+089
+090    /**
+091     * Flush this log stream.
+092     *
+093     * @see java.io.OutputStream#flush()
+094     */
+095    @Override
+096    public void flush() {
+097        if (buffer.size() > 0) {
+098            processBuffer();
+099        }
+100    }
+101
+102    /**
+103     * Writes all remaining data from the buffer.
+104     *
+105     * @see java.io.OutputStream#close()
+106     */
+107    @Override
+108    public void close() throws IOException {
+109        if (buffer.size() > 0) {
+110            processBuffer();
+111        }
+112        super.close();
+113    }
+114
+115    /**
+116     * @return the trace level of the log system
+117     */
+118    public int getMessageLevel() {
+119        return level;
+120    }
+121
+122    /**
+123     * Write a block of characters to the output stream
+124     *
+125     * @param b the array containing the data
+126     * @param off the offset into the array where data starts
+127     * @param len the length of block
+128     * @throws java.io.IOException if the data cannot be written into the stream.
+129     * @see java.io.OutputStream#write(byte[], int, int)
+130     */
+131    @Override
+132    public void write(final byte[] b, final int off, final int len)
+133            throws IOException {
+134        // find the line breaks and pass other chars through in blocks
+135        int offset = off;
+136        int blockStartOffset = offset;
+137        int remaining = len;
+138        while (remaining > 0) {
+139            while (remaining > 0 && b[offset] != LF && b[offset] != CR) {
+140                offset++;
+141                remaining--;
+142            }
+143            // either end of buffer or a line separator char
+144            final int blockLength = offset - blockStartOffset;
+145            if (blockLength > 0) {
+146                buffer.write(b, blockStartOffset, blockLength);
+147            }
+148            while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) {
+149                write(b[offset]);
+150                offset++;
+151                remaining--;
+152            }
+153            blockStartOffset = offset;
+154        }
+155    }
+156
+157    /**
+158     * Converts the buffer to a string and sends it to {@code processLine}.
+159     */
+160    protected void processBuffer() {
+161        processLine(buffer.toString());
+162        buffer.reset();
+163    }
+164
+165    /**
+166     * Logs a line to the log system of the user.
+167     *
+168     * @param line
+169     *            the line to log.
+170     */
+171    protected void processLine(final String line) {
+172        processLine(line, level);
+173    }
+174
+175    /**
+176     * Logs a line to the log system of the user.
+177     *
+178     * @param line the line to log.
+179     * @param logLevel the log level to use
+180     */
+181    protected abstract void processLine(final String line, final int logLevel);
+182}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/OS.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/OS.html new file mode 100644 index 0000000..c614254 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/OS.html @@ -0,0 +1,318 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.util.Locale;
+022
+023/**
+024 * Condition that tests the OS type.
+025 *
+026 * @version $Id: OS.java 1556869 2014-01-09 16:51:11Z britter $
+027 */
+028public final class OS {
+029    private static final String FAMILY_OS_400 = "os/400";
+030
+031    private static final String FAMILY_Z_OS = "z/os";
+032
+033    private static final String FAMILY_WIN9X = "win9x";
+034
+035    private static final String FAMILY_OPENVMS = "openvms";
+036
+037    private static final String FAMILY_UNIX = "unix";
+038
+039    private static final String FAMILY_TANDEM = "tandem";
+040
+041    private static final String FAMILY_MAC = "mac";
+042
+043    private static final String FAMILY_DOS = "dos";
+044
+045    private static final String FAMILY_NETWARE = "netware";
+046
+047    private static final String FAMILY_OS_2 = "os/2";
+048
+049    private static final String FAMILY_WINDOWS = "windows";
+050
+051    private static final String OS_NAME = System.getProperty("os.name")
+052            .toLowerCase(Locale.US);
+053
+054    private static final String OS_ARCH = System.getProperty("os.arch")
+055            .toLowerCase(Locale.US);
+056
+057    private static final String OS_VERSION = System.getProperty("os.version")
+058            .toLowerCase(Locale.US);
+059
+060    private static final String PATH_SEP = System.getProperty("path.separator");
+061
+062    /**
+063     * Default constructor
+064     */
+065    private OS() {
+066    }
+067
+068    /**
+069     * Determines if the OS on which Ant is executing matches the given OS
+070     * family. * Possible values:<br />
+071     * <ul>
+072     * <li>dos</li>
+073     * <li>mac</li>
+074     * <li>netware</li>
+075     * <li>os/2</li>
+076     * <li>tandem</li>
+077     * <li>unix</li>
+078     * <li>windows</li>
+079     * <li>win9x</li>
+080     * <li>z/os</li>
+081     * <li>os/400</li>
+082     * </ul>
+083     * 
+084     * @param family
+085     *            the family to check for
+086     * @return true if the OS matches
+087     */
+088    private static boolean isFamily(final String family) {
+089        return isOs(family, null, null, null);
+090    }
+091
+092    public static boolean isFamilyDOS() {
+093        return isFamily(FAMILY_DOS);
+094    }
+095
+096    public static boolean isFamilyMac() {
+097        return isFamily(FAMILY_MAC);
+098    }
+099
+100    public static boolean isFamilyNetware() {
+101        return isFamily(FAMILY_NETWARE);
+102    }
+103
+104    public static boolean isFamilyOS2() {
+105        return isFamily(FAMILY_OS_2);
+106    }
+107
+108    public static boolean isFamilyTandem() {
+109        return isFamily(FAMILY_TANDEM);
+110    }
+111
+112    public static boolean isFamilyUnix() {
+113        return isFamily(FAMILY_UNIX);
+114    }
+115
+116    public static boolean isFamilyWindows() {
+117        return isFamily(FAMILY_WINDOWS);
+118    }
+119
+120    public static boolean isFamilyWin9x() {
+121        return isFamily(FAMILY_WIN9X);
+122    }
+123
+124    public static boolean isFamilyZOS() {
+125        return isFamily(FAMILY_Z_OS);
+126    }
+127
+128    public static boolean isFamilyOS400() {
+129        return isFamily(FAMILY_OS_400);
+130    }
+131
+132    public static boolean isFamilyOpenVms() {
+133        return isFamily(FAMILY_OPENVMS);
+134    }
+135
+136    /**
+137     * Determines if the OS on which Ant is executing matches the given OS name.
+138     * 
+139     * @param name
+140     *            the OS name to check for
+141     * @return true if the OS matches
+142     */
+143    public static boolean isName(final String name) {
+144        return isOs(null, name, null, null);
+145    }
+146
+147    /**
+148     * Determines if the OS on which Ant is executing matches the given OS
+149     * architecture.
+150     * 
+151     * @param arch
+152     *            the OS architecture to check for
+153     * @return true if the OS matches
+154     */
+155    public static boolean isArch(final String arch) {
+156        return isOs(null, null, arch, null);
+157    }
+158
+159    /**
+160     * Determines if the OS on which Ant is executing matches the given OS
+161     * version.
+162     * 
+163     * @param version
+164     *            the OS version to check for
+165     * @return true if the OS matches
+166     */
+167    public static boolean isVersion(final String version) {
+168        return isOs(null, null, null, version);
+169    }
+170
+171    /**
+172     * Determines if the OS on which Ant is executing matches the given OS
+173     * family, name, architecture and version
+174     * 
+175     * @param family
+176     *            The OS family
+177     * @param name
+178     *            The OS name
+179     * @param arch
+180     *            The OS architecture
+181     * @param version
+182     *            The OS version
+183     * @return true if the OS matches
+184     */
+185    public static boolean isOs(final String family, final String name,
+186            final String arch, final String version) {
+187        boolean retValue = false;
+188
+189        if (family != null || name != null || arch != null || version != null) {
+190
+191            boolean isFamily = true;
+192            boolean isName = true;
+193            boolean isArch = true;
+194            boolean isVersion = true;
+195
+196            if (family != null) {
+197                if (family.equals(FAMILY_WINDOWS)) {
+198                    isFamily = OS_NAME.indexOf(FAMILY_WINDOWS) > -1;
+199                } else if (family.equals(FAMILY_OS_2)) {
+200                    isFamily = OS_NAME.indexOf(FAMILY_OS_2) > -1;
+201                } else if (family.equals(FAMILY_NETWARE)) {
+202                    isFamily = OS_NAME.indexOf(FAMILY_NETWARE) > -1;
+203                } else if (family.equals(FAMILY_DOS)) {
+204                    isFamily = PATH_SEP.equals(";")
+205                            && !isFamily(FAMILY_NETWARE);
+206                } else if (family.equals(FAMILY_MAC)) {
+207                    isFamily = OS_NAME.indexOf(FAMILY_MAC) > -1;
+208                } else if (family.equals(FAMILY_TANDEM)) {
+209                    isFamily = OS_NAME.indexOf("nonstop_kernel") > -1;
+210                } else if (family.equals(FAMILY_UNIX)) {
+211                    isFamily = PATH_SEP.equals(":")
+212                            && !isFamily(FAMILY_OPENVMS)
+213                            && (!isFamily(FAMILY_MAC) || OS_NAME.endsWith("x"));
+214                } else if (family.equals(FAMILY_WIN9X)) {
+215                    isFamily = isFamily(FAMILY_WINDOWS)
+216                            && (OS_NAME.indexOf("95") >= 0
+217                                    || OS_NAME.indexOf("98") >= 0
+218                                    || OS_NAME.indexOf("me") >= 0 || OS_NAME
+219                                    .indexOf("ce") >= 0);
+220                } else if (family.equals(FAMILY_Z_OS)) {
+221                    isFamily = OS_NAME.indexOf(FAMILY_Z_OS) > -1
+222                            || OS_NAME.indexOf("os/390") > -1;
+223                } else if (family.equals(FAMILY_OS_400)) {
+224                    isFamily = OS_NAME.indexOf(FAMILY_OS_400) > -1;
+225                } else if (family.equals(FAMILY_OPENVMS)) {
+226                    isFamily = OS_NAME.indexOf(FAMILY_OPENVMS) > -1;
+227                } else {
+228                    throw new IllegalArgumentException(
+229                            "Don\'t know how to detect os family \"" + family
+230                                    + "\"");
+231                }
+232            }
+233            if (name != null) {
+234                isName = name.equals(OS_NAME);
+235            }
+236            if (arch != null) {
+237                isArch = arch.equals(OS_ARCH);
+238            }
+239            if (version != null) {
+240                isVersion = version.equals(OS_VERSION);
+241            }
+242            retValue = isFamily && isName && isArch && isVersion;
+243        }
+244        return retValue;
+245    }
+246}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ProcessDestroyer.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ProcessDestroyer.html new file mode 100644 index 0000000..d5cb924 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ProcessDestroyer.html @@ -0,0 +1,134 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021/**
+022 * Destroys all registered {@link java.lang.Process} after a certain event,
+023 * typically when the VM exits
+024 * @see org.apache.commons.exec.ShutdownHookProcessDestroyer
+025 *
+026 * @version $Id: ProcessDestroyer.java 1636056 2014-11-01 21:12:52Z ggregory $
+027 */
+028public interface ProcessDestroyer {
+029
+030    /**
+031     * Returns {@code true} if the specified
+032     * {@link java.lang.Process} was
+033     * successfully added to the list of processes to be destroy.
+034     *
+035     * @param process
+036     *      the process to add
+037     * @return {@code true} if the specified
+038     *      {@link java.lang.Process} was
+039     *      successfully added
+040     */
+041    boolean add(Process process);
+042
+043    /**
+044     * Returns {@code true} if the specified
+045     * {@link java.lang.Process} was
+046     * successfully removed from the list of processes to be destroy.
+047     *
+048     * @param process
+049     *            the process to remove
+050     * @return {@code true} if the specified
+051     *      {@link java.lang.Process} was
+052     *      successfully removed
+053     */
+054    boolean remove(Process process);
+055
+056    /**
+057     * Returns the number of registered processes.
+058     *
+059     * @return the number of register process
+060     */
+061    int size();
+062}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/PumpStreamHandler.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/PumpStreamHandler.html new file mode 100644 index 0000000..e294539 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/PumpStreamHandler.html @@ -0,0 +1,390 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.IOException;
+022import java.io.InputStream;
+023import java.io.OutputStream;
+024import java.io.PipedOutputStream;
+025
+026import org.apache.commons.exec.util.DebugUtils;
+027
+028/**
+029 * Copies standard output and error of sub-processes to standard output and error
+030 * of the parent process. If output or error stream are set to null, any feedback
+031 * from that stream will be lost.
+032 *
+033 * @version $Id: PumpStreamHandler.java 1557263 2014-01-10 21:18:09Z ggregory $
+034 */
+035public class PumpStreamHandler implements ExecuteStreamHandler {
+036
+037    private static final long STOP_TIMEOUT_ADDITION = 2000L;
+038
+039    private Thread outputThread;
+040
+041    private Thread errorThread;
+042
+043    private Thread inputThread;
+044
+045    private final OutputStream out;
+046
+047    private final OutputStream err;
+048
+049    private final InputStream input;
+050
+051    private InputStreamPumper inputStreamPumper;
+052
+053    /** the timeout in ms the implementation waits when stopping the pumper threads */
+054    private long stopTimeout;
+055
+056    /** the last exception being caught */
+057    private IOException caught = null;
+058
+059    /**
+060     * Construct a new <CODE>PumpStreamHandler</CODE>.
+061     */
+062    public PumpStreamHandler() {
+063        this(System.out, System.err);
+064    }
+065
+066    /**
+067     * Construct a new <CODE>PumpStreamHandler</CODE>.
+068     *
+069     * @param outAndErr the output/error <CODE>OutputStream</CODE>.
+070     */
+071    public PumpStreamHandler(final OutputStream outAndErr) {
+072        this(outAndErr, outAndErr);
+073    }
+074
+075    /**
+076     * Construct a new <CODE>PumpStreamHandler</CODE>.
+077     *
+078     * @param out the output <CODE>OutputStream</CODE>.
+079     * @param err the error <CODE>OutputStream</CODE>.
+080     */
+081    public PumpStreamHandler(final OutputStream out, final OutputStream err) {
+082        this(out, err, null);
+083    }
+084
+085    /**
+086     * Construct a new <CODE>PumpStreamHandler</CODE>.
+087     *
+088     * @param out   the output <CODE>OutputStream</CODE>.
+089     * @param err   the error <CODE>OutputStream</CODE>.
+090     * @param input the input <CODE>InputStream</CODE>.
+091     */
+092    public PumpStreamHandler(final OutputStream out, final OutputStream err, final InputStream input) {
+093        this.out = out;
+094        this.err = err;
+095        this.input = input;
+096    }
+097
+098    /**
+099     * Set maximum time to wait until output streams are exchausted
+100     * when {@link #stop()} was called.
+101     *
+102     * @param timeout timeout in milliseconds or zero to wait forever (default)
+103     */
+104    public void setStopTimeout(final long timeout) {
+105        this.stopTimeout = timeout;
+106    }
+107
+108    /**
+109     * Set the <CODE>InputStream</CODE> from which to read the standard output
+110     * of the process.
+111     *
+112     * @param is the <CODE>InputStream</CODE>.
+113     */
+114    public void setProcessOutputStream(final InputStream is) {
+115        if (out != null) {
+116            createProcessOutputPump(is, out);
+117        }
+118    }
+119
+120    /**
+121     * Set the <CODE>InputStream</CODE> from which to read the standard error
+122     * of the process.
+123     *
+124     * @param is the <CODE>InputStream</CODE>.
+125     */
+126    public void setProcessErrorStream(final InputStream is) {
+127        if (err != null) {
+128            createProcessErrorPump(is, err);
+129        }
+130    }
+131
+132    /**
+133     * Set the <CODE>OutputStream</CODE> by means of which input can be sent
+134     * to the process.
+135     *
+136     * @param os the <CODE>OutputStream</CODE>.
+137     */
+138    public void setProcessInputStream(final OutputStream os) {
+139        if (input != null) {
+140            if (input == System.in) {
+141                inputThread = createSystemInPump(input, os);
+142            } else {
+143                inputThread = createPump(input, os, true);
+144            }
+145        } else {
+146            try {
+147                os.close();
+148            } catch (final IOException e) {
+149                final String msg = "Got exception while closing output stream";
+150                DebugUtils.handleException(msg, e);
+151            }
+152        }
+153    }
+154
+155    /**
+156     * Start the <CODE>Thread</CODE>s.
+157     */
+158    public void start() {
+159        if (outputThread != null) {
+160            outputThread.start();
+161        }
+162        if (errorThread != null) {
+163            errorThread.start();
+164        }
+165        if (inputThread != null) {
+166            inputThread.start();
+167        }
+168    }
+169
+170    /**
+171     * Stop pumping the streams. When a timeout is specified it it is not guaranteed that the
+172     * pumper threads are cleanly terminated.
+173     */
+174    public void stop() throws IOException {
+175
+176        if (inputStreamPumper != null) {
+177            inputStreamPumper.stopProcessing();
+178        }
+179
+180        stopThread(outputThread, stopTimeout);
+181        stopThread(errorThread, stopTimeout);
+182        stopThread(inputThread, stopTimeout);
+183
+184        if (err != null && err != out) {
+185            try {
+186                err.flush();
+187            } catch (final IOException e) {
+188                final String msg = "Got exception while flushing the error stream : " + e.getMessage();
+189                DebugUtils.handleException(msg, e);
+190            }
+191        }
+192
+193        if (out != null) {
+194            try {
+195                out.flush();
+196            } catch (final IOException e) {
+197                final String msg = "Got exception while flushing the output stream";
+198                DebugUtils.handleException(msg, e);
+199            }
+200        }
+201
+202        if (caught != null) {
+203            throw caught;
+204        }
+205    }
+206
+207    /**
+208     * Get the error stream.
+209     *
+210     * @return <CODE>OutputStream</CODE>.
+211     */
+212    protected OutputStream getErr() {
+213        return err;
+214    }
+215
+216    /**
+217     * Get the output stream.
+218     *
+219     * @return <CODE>OutputStream</CODE>.
+220     */
+221    protected OutputStream getOut() {
+222        return out;
+223    }
+224
+225    /**
+226     * Create the pump to handle process output.
+227     *
+228     * @param is the <CODE>InputStream</CODE>.
+229     * @param os the <CODE>OutputStream</CODE>.
+230     */
+231    protected void createProcessOutputPump(final InputStream is, final OutputStream os) {
+232        outputThread = createPump(is, os);
+233    }
+234
+235    /**
+236     * Create the pump to handle error output.
+237     *
+238     * @param is the <CODE>InputStream</CODE>.
+239     * @param os the <CODE>OutputStream</CODE>.
+240     */
+241    protected void createProcessErrorPump(final InputStream is, final OutputStream os) {
+242        errorThread = createPump(is, os);
+243    }
+244
+245    /**
+246     * Creates a stream pumper to copy the given input stream to the given
+247     * output stream. When the 'os' is an PipedOutputStream we are closing
+248     * 'os' afterwards to avoid an IOException ("Write end dead").
+249     *
+250     * @param is the input stream to copy from
+251     * @param os the output stream to copy into
+252     * @return the stream pumper thread
+253     */
+254    protected Thread createPump(final InputStream is, final OutputStream os) {
+255        final boolean closeWhenExhausted = os instanceof PipedOutputStream ? true : false;
+256        return createPump(is, os, closeWhenExhausted);
+257    }
+258
+259    /**
+260     * Creates a stream pumper to copy the given input stream to the given
+261     * output stream.
+262     *
+263     * @param is                 the input stream to copy from
+264     * @param os                 the output stream to copy into
+265     * @param closeWhenExhausted close the output stream when the input stream is exhausted
+266     * @return the stream pumper thread
+267     */
+268    protected Thread createPump(final InputStream is, final OutputStream os, final boolean closeWhenExhausted) {
+269        final Thread result = new Thread(new StreamPumper(is, os, closeWhenExhausted), "Exec Stream Pumper");
+270        result.setDaemon(true);
+271        return result;
+272    }
+273
+274    /**
+275     * Stopping a pumper thread. The implementation actually waits
+276     * longer than specified in 'timeout' to detect if the timeout
+277     * was indeed exceeded. If the timeout was exceeded an IOException
+278     * is created to be thrown to the caller.
+279     *
+280     * @param thread  the thread to be stopped
+281     * @param timeout the time in ms to wait to join
+282     */
+283    protected void stopThread(final Thread thread, final long timeout) {
+284
+285        if (thread != null) {
+286            try {
+287                if (timeout == 0) {
+288                    thread.join();
+289                } else {
+290                    final long timeToWait = timeout + STOP_TIMEOUT_ADDITION;
+291                    final long startTime = System.currentTimeMillis();
+292                    thread.join(timeToWait);
+293                    if (!(System.currentTimeMillis() < startTime + timeToWait)) {
+294                        final String msg = "The stop timeout of " + timeout + " ms was exceeded";
+295                        caught = new ExecuteException(msg, Executor.INVALID_EXITVALUE);
+296                    }
+297                }
+298            } catch (final InterruptedException e) {
+299                thread.interrupt();
+300            }
+301        }
+302    }
+303
+304    /**
+305     * Creates a stream pumper to copy the given input stream to the given
+306     * output stream.
+307     *
+308     * @param is the System.in input stream to copy from
+309     * @param os the output stream to copy into
+310     * @return the stream pumper thread
+311     */
+312    private Thread createSystemInPump(final InputStream is, final OutputStream os) {
+313        inputStreamPumper = new InputStreamPumper(is, os);
+314        final Thread result = new Thread(inputStreamPumper, "Exec Input Stream Pumper");
+315        result.setDaemon(true);
+316        return result;
+317    }
+318}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ShutdownHookProcessDestroyer.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ShutdownHookProcessDestroyer.html new file mode 100644 index 0000000..d92d92b --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/ShutdownHookProcessDestroyer.html @@ -0,0 +1,269 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.util.Enumeration;
+022import java.util.Vector;
+023
+024/**
+025 * Destroys all registered {@code Process}es when the VM exits.
+026 *
+027 * @version $Id: ShutdownHookProcessDestroyer.java 1636056 2014-11-01 21:12:52Z ggregory $
+028 */
+029public class ShutdownHookProcessDestroyer implements ProcessDestroyer, Runnable {
+030
+031    /** the list of currently running processes */
+032    private final Vector<Process> processes = new Vector<Process>();
+033
+034    /** The thread registered at the JVM to execute the shutdown handler */
+035    private ProcessDestroyerImpl destroyProcessThread = null;
+036
+037    /** Whether or not this ProcessDestroyer has been registered as a shutdown hook */
+038    private boolean added = false;
+039
+040    /**
+041     * Whether or not this ProcessDestroyer is currently running as shutdown hook
+042     */
+043    private volatile boolean running = false;
+044
+045    private class ProcessDestroyerImpl extends Thread {
+046
+047        private boolean shouldDestroy = true;
+048
+049        public ProcessDestroyerImpl() {
+050            super("ProcessDestroyer Shutdown Hook");
+051        }
+052
+053        @Override
+054        public void run() {
+055            if (shouldDestroy) {
+056                ShutdownHookProcessDestroyer.this.run();
+057            }
+058        }
+059
+060        public void setShouldDestroy(final boolean shouldDestroy) {
+061            this.shouldDestroy = shouldDestroy;
+062        }
+063    }
+064
+065    /**
+066     * Constructs a {@code ProcessDestroyer} and obtains
+067     * {@code Runtime.addShutdownHook()} and
+068     * {@code Runtime.removeShutdownHook()} through reflection. The
+069     * ProcessDestroyer manages a list of processes to be destroyed when the VM
+070     * exits. If a process is added when the list is empty, this
+071     * {@code ProcessDestroyer} is registered as a shutdown hook. If
+072     * removing a process results in an empty list, the
+073     * {@code ProcessDestroyer} is removed as a shutdown hook.
+074     */
+075    public ShutdownHookProcessDestroyer() {
+076    }
+077
+078    /**
+079     * Registers this {@code ProcessDestroyer} as a shutdown hook, uses
+080     * reflection to ensure pre-JDK 1.3 compatibility.
+081     */
+082    private void addShutdownHook() {
+083        if (!running) {
+084            destroyProcessThread = new ProcessDestroyerImpl();
+085            Runtime.getRuntime().addShutdownHook(destroyProcessThread);
+086            added = true;
+087        }
+088    }
+089
+090    /**
+091     * Removes this {@code ProcessDestroyer} as a shutdown hook, uses
+092     * reflection to ensure pre-JDK 1.3 compatibility
+093     */
+094    private void removeShutdownHook() {
+095        if (added && !running) {
+096            final boolean removed = Runtime.getRuntime().removeShutdownHook(
+097                    destroyProcessThread);
+098            if (!removed) {
+099                System.err.println("Could not remove shutdown hook");
+100            }
+101            /*
+102             * start the hook thread, a unstarted thread may not be eligible for
+103             * garbage collection Cf.: http://developer.java.sun.com/developer/
+104             * bugParade/bugs/4533087.html
+105             */
+106
+107            destroyProcessThread.setShouldDestroy(false);
+108            destroyProcessThread.start();
+109            // this should return quickly, since it basically is a NO-OP.
+110            try {
+111                destroyProcessThread.join(20000);
+112            } catch (final InterruptedException ie) {
+113                // the thread didn't die in time
+114                // it should not kill any processes unexpectedly
+115            }
+116            destroyProcessThread = null;
+117            added = false;
+118        }
+119    }
+120
+121    /**
+122     * Returns whether or not the ProcessDestroyer is registered as as shutdown
+123     * hook
+124     *
+125     * @return true if this is currently added as shutdown hook
+126     */
+127    public boolean isAddedAsShutdownHook() {
+128        return added;
+129    }
+130
+131    /**
+132     * Returns {@code true} if the specified {@code Process} was
+133     * successfully added to the list of processes to destroy upon VM exit.
+134     *
+135     * @param process
+136     *            the process to add
+137     * @return {@code true} if the specified {@code Process} was
+138     *         successfully added
+139     */
+140    public boolean add(final Process process) {
+141        synchronized (processes) {
+142            // if this list is empty, register the shutdown hook
+143            if (processes.size() == 0) {
+144                addShutdownHook();
+145            }
+146            processes.addElement(process);
+147            return processes.contains(process);
+148        }
+149    }
+150
+151    /**
+152     * Returns {@code true} if the specified {@code Process} was
+153     * successfully removed from the list of processes to destroy upon VM exit.
+154     *
+155     * @param process
+156     *            the process to remove
+157     * @return {@code true} if the specified {@code Process} was
+158     *         successfully removed
+159     */
+160    public boolean remove(final Process process) {
+161        synchronized (processes) {
+162            final boolean processRemoved = processes.removeElement(process);
+163            if (processRemoved && processes.size() == 0) {
+164                removeShutdownHook();
+165            }
+166            return processRemoved;
+167        }
+168    }
+169
+170  /**
+171   * Returns the number of registered processes.
+172   *
+173   * @return the number of register process
+174   */
+175  public int size() {
+176    return processes.size();
+177  }
+178
+179  /**
+180     * Invoked by the VM when it is exiting.
+181     */
+182  public void run() {
+183      synchronized (processes) {
+184          running = true;
+185          final Enumeration<Process> e = processes.elements();
+186          while (e.hasMoreElements()) {
+187              final Process process = e.nextElement();
+188              try {
+189                  process.destroy();
+190              }
+191              catch (final Throwable t) {
+192                  System.err.println("Unable to terminate process during process shutdown");
+193              }
+194          }
+195      }
+196  }
+197}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/StreamPumper.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/StreamPumper.html new file mode 100644 index 0000000..4f163bb --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/StreamPumper.html @@ -0,0 +1,222 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.io.IOException;
+022import java.io.InputStream;
+023import java.io.OutputStream;
+024
+025import org.apache.commons.exec.util.DebugUtils;
+026
+027/**
+028 * Copies all data from an input stream to an output stream.
+029 *
+030 * @version $Id: StreamPumper.java 1557263 2014-01-10 21:18:09Z ggregory $
+031 */
+032public class StreamPumper implements Runnable {
+033
+034    /** the default size of the internal buffer for copying the streams */
+035    private static final int DEFAULT_SIZE = 1024;
+036
+037    /** the input stream to pump from */
+038    private final InputStream is;
+039
+040    /** the output stream to pmp into */
+041    private final OutputStream os;
+042
+043    /** the size of the internal buffer for copying the streams */ 
+044    private final int size;
+045
+046    /** was the end of the stream reached */
+047    private boolean finished;
+048
+049    /** close the output stream when exhausted */
+050    private final boolean closeWhenExhausted;
+051    
+052    /**
+053     * Create a new stream pumper.
+054     * 
+055     * @param is input stream to read data from
+056     * @param os output stream to write data to.
+057     * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted.
+058     */
+059    public StreamPumper(final InputStream is, final OutputStream os,
+060            final boolean closeWhenExhausted) {
+061        this.is = is;
+062        this.os = os;
+063        this.size = DEFAULT_SIZE;
+064        this.closeWhenExhausted = closeWhenExhausted;
+065    }
+066
+067    /**
+068     * Create a new stream pumper.
+069     *
+070     * @param is input stream to read data from
+071     * @param os output stream to write data to.
+072     * @param closeWhenExhausted if true, the output stream will be closed when the input is exhausted.
+073     * @param size the size of the internal buffer for copying the streams
+074     */
+075    public StreamPumper(final InputStream is, final OutputStream os,
+076            final boolean closeWhenExhausted, final int size) {
+077        this.is = is;
+078        this.os = os;
+079        this.size = size > 0 ? size : DEFAULT_SIZE;
+080        this.closeWhenExhausted = closeWhenExhausted;
+081    }
+082
+083    /**
+084     * Create a new stream pumper.
+085     * 
+086     * @param is input stream to read data from
+087     * @param os output stream to write data to.
+088     */
+089    public StreamPumper(final InputStream is, final OutputStream os) {
+090        this(is, os, false);
+091    }
+092
+093    /**
+094     * Copies data from the input stream to the output stream. Terminates as
+095     * soon as the input stream is closed or an error occurs.
+096     */
+097    public void run() {
+098        synchronized (this) {
+099            // Just in case this object is reused in the future
+100            finished = false;
+101        }
+102
+103        final byte[] buf = new byte[this.size];
+104
+105        int length;
+106        try {
+107            while ((length = is.read(buf)) > 0) {
+108                os.write(buf, 0, length);
+109            }
+110        } catch (final Exception e) {
+111            // nothing to do - happens quite often with watchdog
+112        } finally {
+113            if (closeWhenExhausted) {
+114                try {
+115                    os.close();
+116                } catch (final IOException e) {
+117                    final String msg = "Got exception while closing exhausted output stream";
+118                    DebugUtils.handleException(msg ,e);
+119                }
+120            }
+121            synchronized (this) {
+122                finished = true;
+123                notifyAll();
+124            }
+125        }
+126    }
+127
+128    /**
+129     * Tells whether the end of the stream has been reached.
+130     * 
+131     * @return true is the stream has been exhausted.
+132     */
+133    public synchronized boolean isFinished() {
+134        return finished;
+135    }
+136
+137    /**
+138     * This method blocks until the stream pumper finishes.
+139     * 
+140     * @exception InterruptedException
+141     *                if any thread interrupted the current thread before or while the current thread was waiting for a
+142     *                notification.
+143     * @see #isFinished()
+144     */
+145    public synchronized void waitFor() throws InterruptedException {
+146        while (!isFinished()) {
+147            wait();
+148        }
+149    }
+150}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/TimeoutObserver.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/TimeoutObserver.html new file mode 100644 index 0000000..40919b7 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/TimeoutObserver.html @@ -0,0 +1,108 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021/**
+022 * Interface for classes that want to be notified by Watchdog.
+023 * 
+024 * @see org.apache.commons.exec.Watchdog
+025 *
+026 * @version $Id: TimeoutObserver.java 1556869 2014-01-09 16:51:11Z britter $
+027 */
+028public interface TimeoutObserver {
+029
+030    /**
+031     * Called when the watchdog times out.
+032     * 
+033     * @param w the watchdog that timed out.
+034     */
+035    void timeoutOccured(Watchdog w);
+036}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/Watchdog.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/Watchdog.html new file mode 100644 index 0000000..cdd39ac --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/Watchdog.html @@ -0,0 +1,167 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec;
+020
+021import java.util.Enumeration;
+022import java.util.Vector;
+023
+024/**
+025 * Generalization of {@code ExecuteWatchdog}
+026 * 
+027 * @see org.apache.commons.exec.ExecuteWatchdog
+028 *
+029 * @version $Id: Watchdog.java 1636056 2014-11-01 21:12:52Z ggregory $
+030 */
+031public class Watchdog implements Runnable {
+032
+033    private final Vector<TimeoutObserver> observers = new Vector<TimeoutObserver>(1);
+034
+035    private final long timeout;
+036
+037    private boolean stopped = false;
+038
+039    public Watchdog(final long timeout) {
+040        if (timeout < 1) {
+041            throw new IllegalArgumentException("timeout must not be less than 1.");
+042        }
+043        this.timeout = timeout;
+044    }
+045
+046    public void addTimeoutObserver(final TimeoutObserver to) {
+047        observers.addElement(to);
+048    }
+049
+050    public void removeTimeoutObserver(final TimeoutObserver to) {
+051        observers.removeElement(to);
+052    }
+053
+054    protected final void fireTimeoutOccured() {
+055        final Enumeration<TimeoutObserver> e = observers.elements();
+056        while (e.hasMoreElements()) {
+057            e.nextElement().timeoutOccured(this);
+058        }
+059    }
+060
+061    public synchronized void start() {
+062        stopped = false;
+063        final Thread t = new Thread(this, "WATCHDOG");
+064        t.setDaemon(true);
+065        t.start();
+066    }
+067
+068    public synchronized void stop() {
+069        stopped = true;
+070        notifyAll();
+071    }
+072
+073    public void run() {
+074        final long startTime = System.currentTimeMillis();
+075        boolean isWaiting;
+076        synchronized (this) {
+077            long timeLeft = timeout - (System.currentTimeMillis() - startTime);
+078            isWaiting = timeLeft > 0;
+079            while (!stopped && isWaiting) {
+080                try {
+081                    wait(timeLeft);
+082                } catch (final InterruptedException e) {
+083                }
+084                timeLeft = timeout - (System.currentTimeMillis() - startTime);
+085                isWaiting = timeLeft > 0;
+086            }
+087        }
+088
+089        // notify the listeners outside of the synchronized block (see EXEC-60)
+090        if (!isWaiting) {
+091            fireTimeoutOccured();
+092        }
+093    }
+094    
+095}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/DefaultProcessingEnvironment.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/DefaultProcessingEnvironment.html new file mode 100644 index 0000000..3b1c53f --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/DefaultProcessingEnvironment.html @@ -0,0 +1,301 @@ + + + +Source code + + + +
+
001/*
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 * contributor license agreements.  See the NOTICE file distributed with
+004 * this work for additional information regarding copyright ownership.
+005 * The ASF licenses this file to You under the Apache License, Version 2.0
+006 * (the "License"); you may not use this file except in compliance with
+007 * the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 * Unless required by applicable law or agreed to in writing, software
+012 * distributed under the License is distributed on an "AS IS" BASIS,
+013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 * See the License for the specific language governing permissions and
+015 * limitations under the License.
+016 */
+017
+018package org.apache.commons.exec.environment;
+019
+020import java.io.BufferedReader;
+021import java.io.IOException;
+022import java.util.Comparator;
+023import java.util.HashMap;
+024import java.util.Map;
+025import java.util.TreeMap;
+026
+027import org.apache.commons.exec.CommandLine;
+028import org.apache.commons.exec.OS;
+029
+030/**
+031 * Helper class to determine the environment variable
+032 * for the OS. Depending on the JDK the environment
+033 * variables can be either retrieved directly from the
+034 * JVM or requires starting a process to get them running
+035 * an OS command line.
+036 *
+037 * @version $Id: DefaultProcessingEnvironment.java 1636056 2014-11-01 21:12:52Z ggregory $
+038 */
+039public class DefaultProcessingEnvironment {
+040
+041    /** the line separator of the system */
+042//    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+043
+044    /** the environment variables of the process */
+045    protected Map<String, String> procEnvironment;
+046
+047    /**
+048     * Find the list of environment variables for this process.
+049     *
+050     * @return a map containing the environment variables
+051     * @throws IOException obtaining the environment variables failed
+052     */
+053    public synchronized Map<String, String> getProcEnvironment() throws IOException {
+054
+055        if (procEnvironment == null) {
+056            procEnvironment = this.createProcEnvironment();
+057        }
+058
+059        // create a copy of the map just in case that
+060        // anyone is going to modifiy it, e.g. removing
+061        // or setting an evironment variable
+062        final Map<String, String> copy = createEnvironmentMap();
+063        copy.putAll(procEnvironment);
+064        return copy;
+065    }
+066
+067    /**
+068     * Find the list of environment variables for this process.
+069     *
+070     * @return a amp containing the environment variables
+071     * @throws IOException the operation failed
+072     */
+073    protected Map<String, String> createProcEnvironment() throws IOException {
+074        if (procEnvironment == null) {
+075            final Map<String, String> env = System.getenv();
+076            procEnvironment = createEnvironmentMap();
+077            procEnvironment.putAll(env);
+078        }
+079
+080// No longer needed
+081//        if (procEnvironment == null) {
+082//            procEnvironment = createEnvironmentMap();
+083//            final BufferedReader in = runProcEnvCommand();
+084//
+085//            String var = null;
+086//            String line;
+087//            while ((line = in.readLine()) != null) {
+088//                if (line.indexOf('=') == -1) {
+089//                    // Chunk part of previous env var (UNIX env vars can
+090//                    // contain embedded new lines).
+091//                    if (var == null) {
+092//                        var = LINE_SEPARATOR + line;
+093//                    } else {
+094//                        var += LINE_SEPARATOR + line;
+095//                    }
+096//                } else {
+097//                    // New env var...append the previous one if we have it.
+098//                    if (var != null) {
+099//                        EnvironmentUtils.addVariableToEnvironment(procEnvironment, var);
+100//                    }
+101//                    var = line;
+102//                }
+103//            }
+104//            // Since we "look ahead" before adding, there's one last env var.
+105//            if (var != null) {
+106//                EnvironmentUtils.addVariableToEnvironment(procEnvironment, var);
+107//            }
+108//        }
+109        return procEnvironment;
+110    }
+111
+112    /**
+113     * Start a process to list the environment variables.
+114     *
+115     * @return a reader containing the output of the process
+116     * @throws IOException starting the process failed
+117     * @deprecated No longer needed
+118     */
+119    @Deprecated
+120    protected BufferedReader runProcEnvCommand() throws IOException {
+121//        final ByteArrayOutputStream out = new ByteArrayOutputStream();
+122//        final Executor exe = new DefaultExecutor();
+123//        exe.setStreamHandler(new PumpStreamHandler(out));
+124//        // ignore the exit value - Just try to use what we got
+125//        exe.execute(getProcEnvCommand());
+126//        return new BufferedReader(new StringReader(toString(out)));
+127        return null;
+128    }
+129
+130    /**
+131     * Determine the OS specific command line to get a list of environment
+132     * variables.
+133     *
+134     * @return the command line
+135     * @deprecated No longer needed
+136     */
+137    @Deprecated
+138    protected CommandLine getProcEnvCommand() {
+139//        String executable;
+140//        String[] arguments = null;
+141//        if (OS.isFamilyOS2()) {
+142//            // OS/2 - use same mechanism as Windows 2000
+143//            executable = "cmd";
+144//
+145//            arguments = new String[] {"/c", "set"};
+146//        } else if (OS.isFamilyWindows()) {
+147//            // Determine if we're running under XP/2000/NT or 98/95
+148//            if (OS.isFamilyWin9x()) {
+149//                executable = "command.com";
+150//                // Windows 98/95
+151//            } else {
+152//                executable = "cmd";
+153//                // Windows XP/2000/NT/2003
+154//            }
+155//            arguments = new String[] {"/c", "set"};
+156//        } else if (OS.isFamilyZOS() || OS.isFamilyUnix()) {
+157//            // On most systems one could use: /bin/sh -c env
+158//
+159//            // Some systems have /bin/env, others /usr/bin/env, just try
+160//            if (new File("/bin/env").canRead()) {
+161//                executable = "/bin/env";
+162//            } else if (new File("/usr/bin/env").canRead()) {
+163//                executable = "/usr/bin/env";
+164//            } else {
+165//                // rely on PATH
+166//                executable = "env";
+167//            }
+168//        } else if (OS.isFamilyNetware() || OS.isFamilyOS400()) {
+169//            // rely on PATH
+170//            executable = "env";
+171//        } else {
+172//            // MAC OS 9 and previous
+173//            // TODO: I have no idea how to get it, someone must fix it
+174//            executable = null;
+175//        }
+176        final CommandLine commandLine = null;
+177//        if (executable != null) {
+178//            commandLine = new CommandLine(executable);
+179//            commandLine.addArguments(arguments);
+180//        }
+181        return commandLine;
+182    }
+183
+184//    /**
+185//     * ByteArrayOutputStream#toString doesn't seem to work reliably on OS/390,
+186//     * at least not the way we use it in the execution context.
+187//     *
+188//     * @param bos
+189//     *            the output stream that one wants to read
+190//     * @return the output stream as a string, read with special encodings in the
+191//     *         case of z/os and os/400
+192//     */
+193//    private String toString(final ByteArrayOutputStream bos) {
+194//        if (OS.isFamilyZOS()) {
+195//            try {
+196//                return bos.toString("Cp1047");
+197//            } catch (final java.io.UnsupportedEncodingException e) {
+198//                // noop default encoding used
+199//            }
+200//        } else if (OS.isFamilyOS400()) {
+201//            try {
+202//                return bos.toString("Cp500");
+203//            } catch (final java.io.UnsupportedEncodingException e) {
+204//                // noop default encoding used
+205//            }
+206//        }
+207//        return bos.toString();
+208//    }
+209
+210    /**
+211     * Creates a map that obeys the casing rules of the current platform for key
+212     * lookup. E.g. on a Windows platform, the map keys will be
+213     * case-insensitive.
+214     *
+215     * @return The map for storage of environment variables, never
+216     *         {@code null}.
+217     */
+218    private Map<String, String> createEnvironmentMap() {
+219        if (OS.isFamilyWindows()) {
+220            return new TreeMap<String, String>(new Comparator<String>() {
+221                public int compare(final String key0, final String key1) {
+222                    return key0.compareToIgnoreCase(key1);
+223                }
+224            });
+225        }
+226        return new HashMap<String, String>();
+227    }
+228
+229}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/EnvironmentUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/EnvironmentUtils.html new file mode 100644 index 0000000..116a438 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/EnvironmentUtils.html @@ -0,0 +1,193 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.environment;
+020
+021import java.io.IOException;
+022import java.util.Map;
+023import java.util.Map.Entry;
+024
+025//import org.apache.commons.exec.OS;
+026
+027/**
+028 * Wrapper for environment variables.
+029 *
+030 * @version $Id: EnvironmentUtils.java 1636056 2014-11-01 21:12:52Z ggregory $
+031 */
+032public class EnvironmentUtils
+033{
+034
+035    private static final DefaultProcessingEnvironment PROCESSING_ENVIRONMENT_IMPLEMENTATION;
+036    
+037    static {
+038//        if (OS.isFamilyOpenVms()) {
+039//            PROCESSING_ENVIRONMENT_IMPLEMENTATION = new OpenVmsProcessingEnvironment();
+040//        } else {
+041            PROCESSING_ENVIRONMENT_IMPLEMENTATION = new DefaultProcessingEnvironment();
+042//        }
+043    }
+044    
+045    /**
+046     * Disable constructor.
+047     */
+048    private EnvironmentUtils() {
+049
+050    }
+051
+052    /**
+053     * Get the variable list as an array.
+054     *
+055     * @param environment the environment to use, may be {@code null}
+056     * @return array of key=value assignment strings or {@code null} if and only if
+057     *     the input map was {@code null}
+058     */
+059    public static String[] toStrings(final Map<String, String> environment) {
+060        if (environment == null) {
+061            return null;
+062        }
+063        final String[] result = new String[environment.size()];
+064        int i = 0;
+065        for (final Entry<String, String> entry : environment.entrySet()) {
+066            final String key  = entry.getKey() == null ? "" : entry.getKey().toString();
+067            final String value = entry.getValue() == null ? "" : entry.getValue().toString();
+068            result[i] = key + "=" + value;
+069            i++;
+070        }
+071        return result;
+072    }
+073
+074    /**
+075     * Find the list of environment variables for this process. The returned map preserves
+076     * the casing of a variable's name on all platforms but obeys the casing rules of the
+077     * current platform during lookup, e.g. key names will be case-insensitive on Windows
+078     * platforms.
+079     *
+080     * @return a map containing the environment variables, may be empty but never {@code null}
+081     * @throws IOException the operation failed
+082     */
+083    public static Map<String, String> getProcEnvironment() throws IOException {
+084        return PROCESSING_ENVIRONMENT_IMPLEMENTATION.getProcEnvironment();
+085    }
+086
+087    /**
+088     * Add a key/value pair to the given environment.
+089     * If the key matches an existing key, the previous setting is replaced.
+090     *
+091     * @param environment the current environment
+092     * @param keyAndValue the key/value pair 
+093     */
+094    public static void addVariableToEnvironment(final Map<String, String> environment, final String keyAndValue) {
+095        final String[] parsedVariable = parseEnvironmentVariable(keyAndValue);        
+096        environment.put(parsedVariable[0], parsedVariable[1]);
+097    }
+098    
+099    /**
+100     * Split a key/value pair into a String[]. It is assumed
+101     * that the ky/value pair contains a '=' character.
+102     *
+103     * @param keyAndValue the key/value pair
+104     * @return a String[] containing the key and value
+105     */
+106    private static String[] parseEnvironmentVariable(final String keyAndValue) {
+107        final int index = keyAndValue.indexOf('=');
+108        if (index == -1) {
+109            throw new IllegalArgumentException(
+110                    "Environment variable for this platform "
+111                            + "must contain an equals sign ('=')");
+112        }
+113
+114        final String[] result = new String[2];
+115        result[0] = keyAndValue.substring(0, index);
+116        result[1] = keyAndValue.substring(index + 1);
+117
+118        return result;
+119    }
+120    
+121}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/OpenVmsProcessingEnvironment.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/OpenVmsProcessingEnvironment.html new file mode 100644 index 0000000..273dd7b --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/environment/OpenVmsProcessingEnvironment.html @@ -0,0 +1,169 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 * contributor license agreements.  See the NOTICE file distributed with
+004 * this work for additional information regarding copyright ownership.
+005 * The ASF licenses this file to You under the Apache License, Version 2.0
+006 * (the "License"); you may not use this file except in compliance with
+007 * the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 * Unless required by applicable law or agreed to in writing, software
+012 * distributed under the License is distributed on an "AS IS" BASIS,
+013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 * See the License for the specific language governing permissions and
+015 * limitations under the License.
+016 */
+017
+018package org.apache.commons.exec.environment;
+019
+020//import java.io.BufferedReader;
+021//import java.io.IOException;
+022//import java.util.HashMap;
+023//import java.util.Map;
+024//
+025//import org.apache.commons.exec.CommandLine;
+026
+027/**
+028 * Helper class to determine the environment variable
+029 * for VMS.
+030 *
+031 * @version $Id: OpenVmsProcessingEnvironment.java 1636056 2014-11-01 21:12:52Z ggregory $
+032 * @deprecated No longer needed
+033 */
+034@Deprecated
+035public class OpenVmsProcessingEnvironment extends DefaultProcessingEnvironment {
+036
+037    /*
+038     * Hopefully removing super-class overrides won't cause Clirr error.
+039     * If necessary can just delegate to super-class. 
+040     */
+041
+042//    /**
+043//     * Find the list of environment variables for this process.
+044//     *
+045//     * @return a map containing the environment variables
+046//     * @throws IOException the operation failed
+047//     */    
+048//    @Override
+049//    protected Map<String, String> createProcEnvironment() throws IOException {
+050//        if (procEnvironment == null) {
+051//            final BufferedReader in = runProcEnvCommand();
+052//            procEnvironment = addVMSenvironmentVariables(new HashMap<String, String>(), in);
+053//        }
+054//
+055//        return procEnvironment;
+056//    }
+057//
+058//    /**
+059//     * Determine the OS specific command line to get a list of environment
+060//     * variables.
+061//     *
+062//     * @return the command line
+063//     */    
+064//    @Override
+065//    protected CommandLine getProcEnvCommand() {
+066//        final CommandLine commandLine = new CommandLine("show");
+067//        commandLine.addArgument("symbol/global"); // the parser assumes symbols are global
+068//        commandLine.addArgument("*");
+069//        return commandLine;
+070//    }
+071//
+072//    /**
+073//     * This method is VMS specific and used by getProcEnvironment(). Parses VMS
+074//     * symbols from {@code in} and adds them to {@code environment}.
+075//     * {@code in} is expected to be the output of "SHOW SYMBOL/GLOBAL *".
+076//     *
+077//     * @param environment the current environment
+078//     * @param in the reader from the process to determine VMS env variables
+079//     * @return the updated environment
+080//     * @throws IOException operation failed
+081//     */
+082//    private Map<String, String> addVMSenvironmentVariables(final Map<String, String> environment,
+083//            final BufferedReader in) throws IOException {
+084//        String line;
+085//        while ((line = in.readLine()) != null) {
+086//            final String SEP = "=="; // global symbol separator
+087//            final int sepidx = line.indexOf(SEP);
+088//            if (sepidx > 0) {
+089//                final String name = line.substring(0, sepidx).trim();
+090//                String value = line.substring(sepidx+SEP.length()).trim();
+091//                value = value.substring(1,value.length()-1); // drop enclosing quotes
+092//                environment.put(name,value);
+093//            }
+094//        }
+095//        return environment;
+096//    }
+097}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncher.html new file mode 100644 index 0000000..b17c966 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncher.html @@ -0,0 +1,160 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import java.io.File;
+022import java.io.IOException;
+023import java.util.Map;
+024
+025import org.apache.commons.exec.CommandLine;
+026
+027/**
+028 * Interface to shield the caller from the various platform-dependent
+029 * implementations.
+030 *
+031 * @version $Id: CommandLauncher.java 1636056 2014-11-01 21:12:52Z ggregory $
+032 */
+033public interface CommandLauncher {
+034
+035    /**
+036     * Launches the given command in a new process.
+037     * 
+038     * @param cmd
+039     *            The command to execute
+040     * @param env
+041     *            The environment for the new process. If null, the environment
+042     *            of the current process is used.
+043     * 
+044     * @return the newly created process
+045     * @throws IOException
+046     *             if attempting to run a command in a specific directory
+047     */
+048    Process exec(final CommandLine cmd, final Map<String, String> env)
+049            throws IOException;
+050
+051    /**
+052     * Launches the given command in a new process, in the given working
+053     * directory.
+054     * 
+055     * @param cmd
+056     *            The command to execute
+057     * @param env
+058     *            The environment for the new process. If null, the environment
+059     *            of the current process is used.
+060     * @param workingDir
+061     *            The directory to start the command in. If null, the current
+062     *            directory is used
+063     *
+064     * @return the newly created process
+065     * @throws IOException
+066     *             if trying to change directory
+067     */
+068    Process exec(final CommandLine cmd, final Map<String, String> env,
+069            final File workingDir) throws IOException;
+070
+071
+072    /**
+073     * Checks whether {@code exitValue} signals a failure on the current
+074     * system (OS specific).
+075     * <p>
+076     * <b>Note</b> that this method relies on the conventions of the OS, it
+077     * will return false results if the application you are running doesn't
+078     * follow these conventions. One notable exception is the Java VM provided
+079     * by HP for OpenVMS - it will return 0 if successful (like on any other
+080     * platform), but this signals a failure on OpenVMS. So if you execute a new
+081     * Java VM on OpenVMS, you cannot trust this method.
+082     * </p>
+083     *
+084     * @param exitValue the exit value (return code) to be checked
+085     * @return {@code true} if {@code exitValue} signals a failure
+086     */
+087    boolean isFailure(final int exitValue);
+088}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherFactory.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherFactory.html new file mode 100644 index 0000000..1db7f4e --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherFactory.html @@ -0,0 +1,122 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import org.apache.commons.exec.OS;
+022
+023/**
+024 * Builds a command launcher for the OS and JVM we are running under.
+025 *
+026 * @version $Id: CommandLauncherFactory.java 1556869 2014-01-09 16:51:11Z britter $
+027 */
+028public final class CommandLauncherFactory {
+029
+030    private CommandLauncherFactory() {
+031    }
+032
+033    /**
+034     * Factory method to create an appropriate launcher.
+035     *
+036     * @return the command launcher
+037     */
+038    public static CommandLauncher createVMLauncher() {
+039        // Try using a JDK 1.3 launcher
+040        CommandLauncher launcher;
+041
+042        if (OS.isFamilyOpenVms()) {
+043            launcher = new VmsCommandLauncher();
+044        } else {
+045            launcher = new Java13CommandLauncher();
+046        }
+047
+048        return launcher;
+049    }
+050}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherImpl.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherImpl.html new file mode 100644 index 0000000..1ccacbf --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherImpl.html @@ -0,0 +1,124 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import java.io.File;
+022import java.io.IOException;
+023import java.util.Map;
+024
+025import org.apache.commons.exec.CommandLine;
+026import org.apache.commons.exec.environment.EnvironmentUtils;
+027
+028/**
+029 * A command launcher for a particular JVM/OS platform. This class is a general
+030 * purpose command launcher which can only launch commands in the current
+031 * working directory.
+032 *
+033 * @version $Id: CommandLauncherImpl.java 1557338 2014-01-11 10:34:22Z sebb $
+034 */
+035public abstract class CommandLauncherImpl implements CommandLauncher {
+036
+037    public Process exec(final CommandLine cmd, final Map<String, String> env)
+038            throws IOException {
+039        final String[] envVar = EnvironmentUtils.toStrings(env);
+040        return Runtime.getRuntime().exec(cmd.toStrings(), envVar);
+041    }
+042
+043    public abstract Process exec(final CommandLine cmd, final Map<String, String> env,
+044            final File workingDir) throws IOException;
+045
+046    /** @see org.apache.commons.exec.launcher.CommandLauncher#isFailure(int) */    
+047    public boolean isFailure(final int exitValue)
+048    {
+049        // non zero exit value signals failure
+050        return exitValue != 0;
+051    }
+052}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherProxy.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherProxy.html new file mode 100644 index 0000000..a7c01a5 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/CommandLauncherProxy.html @@ -0,0 +1,128 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import java.io.IOException;
+022import java.util.Map;
+023
+024import org.apache.commons.exec.CommandLine;
+025
+026/**
+027 * A command launcher that proxies another command launcher. Sub-classes
+028 * override exec(args, env, workdir)
+029 *
+030 * @version $Id: CommandLauncherProxy.java 1557338 2014-01-11 10:34:22Z sebb $
+031 */
+032public abstract class CommandLauncherProxy extends CommandLauncherImpl {
+033
+034    public CommandLauncherProxy(final CommandLauncher launcher) {
+035        myLauncher = launcher;
+036    }
+037
+038    private final CommandLauncher myLauncher;
+039
+040    /**
+041     * Launches the given command in a new process. Delegates this method to the
+042     * proxied launcher
+043     * 
+044     * @param cmd
+045     *            the command line to execute as an array of strings
+046     * @param env
+047     *            the environment to set as an array of strings
+048     * @throws IOException
+049     *             forwarded from the exec method of the command launcher
+050     */
+051    @Override
+052    public Process exec(final CommandLine cmd, final Map<String, String> env)
+053            throws IOException {
+054        return myLauncher.exec(cmd, env);
+055    }
+056}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/Java13CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/Java13CommandLauncher.html new file mode 100644 index 0000000..0343052 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/Java13CommandLauncher.html @@ -0,0 +1,136 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import java.io.File;
+022import java.io.IOException;
+023import java.util.Map;
+024
+025import org.apache.commons.exec.CommandLine;
+026import org.apache.commons.exec.environment.EnvironmentUtils;
+027
+028/**
+029 * A command launcher for JDK/JRE 1.3 (and higher). Uses the built-in
+030 * Runtime.exec() command
+031 *
+032 * @version $Id: Java13CommandLauncher.java 1557338 2014-01-11 10:34:22Z sebb $
+033 */
+034public class Java13CommandLauncher extends CommandLauncherImpl {
+035
+036    /**
+037     * Constructor
+038     */
+039    public Java13CommandLauncher() {
+040    }
+041
+042    /**
+043     * Launches the given command in a new process, in the given working
+044     * directory
+045     * 
+046     * @param cmd
+047     *            the command line to execute as an array of strings
+048     * @param env
+049     *            the environment to set as an array of strings
+050     * @param workingDir
+051     *            the working directory where the command should run
+052     * @throws IOException
+053     *             probably forwarded from Runtime#exec
+054     */
+055    @Override
+056    public Process exec(final CommandLine cmd, final Map<String, String> env,
+057            final File workingDir) throws IOException {
+058
+059        final String[] envVars = EnvironmentUtils.toStrings(env);
+060
+061        return Runtime.getRuntime().exec(cmd.toStrings(),
+062                envVars, workingDir);
+063    }
+064}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/OS2CommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/OS2CommandLauncher.html new file mode 100644 index 0000000..d13f0b9 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/OS2CommandLauncher.html @@ -0,0 +1,143 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import java.io.File;
+022import java.io.IOException;
+023import java.util.Map;
+024
+025import org.apache.commons.exec.CommandLine;
+026
+027/**
+028 * A command launcher for OS/2 that uses 'cmd.exe' when launching commands in
+029 * directories other than the current working directory.
+030 * <p>
+031 * Unlike Windows NT and friends, OS/2's cd doesn't support the /d switch to
+032 * change drives and directories in one go.
+033 * </p>
+034 * Please not that this class is currently unused because the Java13CommandLauncher
+035 * is used for 0S/2
+036 *
+037 * @version $Id: OS2CommandLauncher.java 1557338 2014-01-11 10:34:22Z sebb $
+038 */
+039public class OS2CommandLauncher extends CommandLauncherProxy {
+040
+041    public OS2CommandLauncher(final CommandLauncher launcher) {
+042        super(launcher);
+043    }
+044
+045    /**
+046     * Launches the given command in a new process, in the given working
+047     * directory.
+048     * 
+049     * @param cmd
+050     *            the command line to execute as an array of strings
+051     * @param env
+052     *            the environment to set as an array of strings
+053     * @param workingDir
+054     *            working directory where the command should run
+055     * @throws IOException
+056     *             forwarded from the exec method of the command launcher
+057     */
+058    @Override
+059    public Process exec(final CommandLine cmd, final Map<String, String> env,
+060            final File workingDir) throws IOException {
+061        if (workingDir == null) {
+062            return exec(cmd, env);
+063        }
+064
+065        final CommandLine newCmd = new CommandLine("cmd");
+066        newCmd.addArgument("/c");
+067        newCmd.addArguments(cmd.toStrings());
+068
+069        return exec(newCmd, env);
+070    }
+071}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/VmsCommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/VmsCommandLauncher.html new file mode 100644 index 0000000..addf317 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/VmsCommandLauncher.html @@ -0,0 +1,220 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import java.io.File;
+022import java.io.FileWriter;
+023import java.io.IOException;
+024import java.io.PrintWriter;
+025import java.util.Map;
+026import java.util.Map.Entry;
+027import java.util.Set;
+028
+029import org.apache.commons.exec.CommandLine;
+030import org.apache.commons.exec.util.StringUtils;
+031
+032/**
+033 * A command launcher for VMS that writes the command to a temporary DCL script
+034 * before launching commands. This is due to limitations of both the DCL
+035 * interpreter and the Java VM implementation.
+036 *
+037 * @version $Id: VmsCommandLauncher.java 1636056 2014-11-01 21:12:52Z ggregory $
+038 */
+039public class VmsCommandLauncher extends Java13CommandLauncher {
+040
+041    /**
+042     * Launches the given command in a new process.
+043     */
+044    @Override
+045    public Process exec(final CommandLine cmd, final Map<String, String> env)
+046            throws IOException {
+047        final CommandLine vmsCmd = new CommandLine(
+048                createCommandFile(cmd, env).getPath()
+049        );
+050
+051        return super.exec(vmsCmd, env);
+052    }
+053
+054    /**
+055     * Launches the given command in a new process, in the given working
+056     * directory. Note that under Java 1.3.1, 1.4.0 and 1.4.1 on VMS this method
+057     * only works if {@code workingDir} is null or the logical
+058     * JAVA$FORK_SUPPORT_CHDIR needs to be set to TRUE.
+059     */
+060    @Override
+061    public Process exec(final CommandLine cmd, final Map<String, String> env,
+062            final File workingDir) throws IOException {
+063        final CommandLine vmsCmd = new CommandLine(
+064                createCommandFile(cmd, env).getPath()
+065        );
+066
+067        return super.exec(vmsCmd, env, workingDir);
+068    }
+069
+070    /** @see org.apache.commons.exec.launcher.CommandLauncher#isFailure(int) */
+071    @Override
+072    public boolean isFailure(final int exitValue) {
+073        // even exit value signals failure
+074        return exitValue % 2 == 0;
+075    }
+076
+077    /*
+078     * Writes the command into a temporary DCL script and returns the
+079     * corresponding File object. The script will be deleted on exit.
+080     */
+081    private File createCommandFile(final CommandLine cmd, final Map<String, String> env)
+082            throws IOException {
+083        final File script = File.createTempFile("EXEC", ".TMP");
+084        script.deleteOnExit();
+085        PrintWriter out = null;
+086        try {
+087            out = new PrintWriter(new FileWriter(script.getAbsolutePath(),true));
+088
+089            // add the environment as global symbols for the DCL script
+090            if (env != null) {
+091                final Set<Entry<String, String>> entries = env.entrySet();
+092
+093                for (final Entry<String, String> entry : entries) {
+094                    out.print("$ ");
+095                    out.print(entry.getKey());
+096                    out.print(" == "); // define as global symbol
+097                    out.println('\"');
+098                    String value = entry.getValue();
+099                    // Any embedded " values need to be doubled
+100                    if (value.indexOf('\"') > 0) {
+101                        final StringBuilder sb = new StringBuilder();
+102                        for (int i = 0; i < value.length(); i++) {
+103                            final char c = value.charAt(i);
+104                            if (c == '\"') {
+105                                sb.append('\"');
+106                            }
+107                            sb.append(c);
+108                        }
+109                        value=sb.toString();
+110                    }
+111                    out.print(value);
+112                    out.println('\"');
+113                }
+114            }
+115
+116            final String command = cmd.getExecutable();
+117            if (cmd.isFile()) {// We assume it is it a script file
+118                out.print("$ @");
+119                // This is a bit crude, but seems to work
+120                final String parts[] = StringUtils.split(command,"/");
+121                out.print(parts[0]); // device
+122                out.print(":[");
+123                out.print(parts[1]); // top level directory
+124                final int lastPart = parts.length-1;
+125                for (int i=2; i< lastPart; i++) {
+126                    out.print(".");
+127                    out.print(parts[i]);
+128                }
+129                out.print("]");
+130                out.print(parts[lastPart]);
+131            } else {
+132                out.print("$ ");
+133                out.print(command);                
+134            }
+135            final String[] args = cmd.getArguments();
+136            for (final String arg : args) {
+137                out.println(" -");
+138                out.print(arg);
+139            }
+140            out.println();
+141        } finally {
+142            if (out != null) {
+143                out.close();
+144            }
+145        }
+146        return script;
+147    }
+148}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/WinNTCommandLauncher.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/WinNTCommandLauncher.html new file mode 100644 index 0000000..7a801e3 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/launcher/WinNTCommandLauncher.html @@ -0,0 +1,138 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.launcher;
+020
+021import java.io.File;
+022import java.io.IOException;
+023import java.util.Map;
+024
+025import org.apache.commons.exec.CommandLine;
+026
+027/**
+028 * A command launcher for Windows XP/2000/NT that uses 'cmd.exe' when launching
+029 * commands in directories other than the current working directory.
+030 *
+031 * @version $Id: WinNTCommandLauncher.java 1557338 2014-01-11 10:34:22Z sebb $
+032 */
+033public class WinNTCommandLauncher extends CommandLauncherProxy {
+034    public WinNTCommandLauncher(final CommandLauncher launcher) {
+035        super(launcher);
+036    }
+037
+038    /**
+039     * Launches the given command in a new process, in the given working
+040     * directory.
+041     * 
+042     * @param cmd
+043     *            the command line to execute as an array of strings
+044     * @param env
+045     *            the environment to set as an array of strings
+046     * @param workingDir
+047     *            working directory where the command should run
+048     * @throws IOException
+049     *             forwarded from the exec method of the command launcher
+050     */
+051    @Override
+052    public Process exec(final CommandLine cmd, final Map<String, String> env,
+053            final File workingDir) throws IOException {
+054        if (workingDir == null) {
+055            return exec(cmd, env);
+056        }
+057
+058        // Use cmd.exe to change to the specified directory before running
+059        // the command
+060        final CommandLine newCmd = new CommandLine("cmd");
+061        newCmd.addArgument("/c");
+062        newCmd.addArguments(cmd.toStrings());
+063
+064        return exec(newCmd, env);
+065    }
+066}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/DebugUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/DebugUtils.html new file mode 100644 index 0000000..dcbe323 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/DebugUtils.html @@ -0,0 +1,158 @@ + + + +Source code + + + +
+
001/*
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.util;
+020
+021/**
+022 * Provides debugging support.
+023 *
+024 * @version $Id: DebugUtils.java 1636203 2014-11-02 22:26:31Z ggregory $
+025 */
+026public class DebugUtils
+027{
+028    /**
+029     * System property to determine how to handle exceptions. When
+030     * set to "false" we rethrow the otherwise silently catched
+031     * exceptions found in the original code. The default value
+032     * is "true"
+033     */
+034    public static final String COMMONS_EXEC_LENIENT = "org.apache.commons.exec.lenient";
+035
+036    /**
+037     * System property to determine how to dump an exception. When
+038     * set to "true" we print any exception to stderr. The default
+039     * value is "false"
+040     */
+041    public static final String COMMONS_EXEC_DEBUG = "org.apache.commons.exec.debug";
+042
+043    /**
+044     * Handles an exception based on the system properties.
+045     *
+046     * @param msg message describing the problem
+047     * @param e an exception being handled
+048     */
+049    public static void handleException(final String msg, final Exception e) {
+050
+051        if (isDebugEnabled()) {
+052            System.err.println(msg);
+053            e.printStackTrace();
+054        }
+055
+056        if (!isLenientEnabled()) {
+057            if (e instanceof RuntimeException) {
+058                throw (RuntimeException) e;
+059            }
+060            // can't pass root cause since the constructor is not available on JDK 1.3
+061            throw new RuntimeException(e.getMessage());
+062        }
+063    }
+064
+065    /**
+066     * Determines if debugging is enabled based on the
+067     * system property "COMMONS_EXEC_DEBUG".
+068     *
+069     * @return true if debug mode is enabled
+070     */
+071    public static boolean isDebugEnabled() {
+072        final String debug = System.getProperty(COMMONS_EXEC_DEBUG, Boolean.FALSE.toString());
+073        return Boolean.TRUE.toString().equalsIgnoreCase(debug);
+074    }
+075
+076    /**
+077     * Determines if lenient mode is enabled.
+078     *
+079     * @return true if lenient mode is enabled
+080     */
+081    public static boolean isLenientEnabled() {
+082        final String lenient = System.getProperty(COMMONS_EXEC_LENIENT, Boolean.TRUE.toString());
+083        return Boolean.TRUE.toString().equalsIgnoreCase(lenient);
+084    }
+085
+086}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/MapUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/MapUtils.html new file mode 100644 index 0000000..67aafe6 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/MapUtils.html @@ -0,0 +1,187 @@ + + + +Source code + + + +
+
001/*
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.util;
+020
+021import java.util.HashMap;
+022import java.util.Map;
+023
+024/**
+025 * Helper classes to manipulate maps to pass substition map to the CommandLine. This class is not part of the public API
+026 * and could change without warning.
+027 *
+028 * @version $Id: MapUtils.java 1636205 2014-11-02 22:32:33Z ggregory $
+029 */
+030public class MapUtils
+031{
+032    /**
+033     * Clones a map.
+034     * 
+035     * @param source
+036     *            the Map to clone
+037     * @param <K>
+038     *            the map key type
+039     * @param <V>
+040     *            the map value type
+041     * @return the cloned map
+042     */
+043   public static <K, V> Map<K, V> copy(final Map<K, V> source) {
+044
+045        if (source == null) {
+046            return null;
+047        }
+048
+049        final Map<K, V> result = new HashMap<K, V>();
+050        result.putAll(source);
+051        return result;
+052    }
+053
+054    /**
+055     * Clones a map and prefixes the keys in the clone, e.g. for mapping "JAVA_HOME" to "env.JAVA_HOME" to simulate the
+056     * behaviour of Ant.
+057     *
+058     * @param source
+059     *            the source map
+060     * @param prefix
+061     *            the prefix used for all names
+062     * @param <K>
+063     *            the map key type
+064     * @param <V>
+065     *            the map value type
+066     * @return the clone of the source map
+067     */
+068    public static <K, V> Map<String, V> prefix(final Map<K, V> source, final String prefix) {
+069
+070        if (source == null) {
+071            return null;
+072        }
+073
+074        final Map<String, V> result = new HashMap<String, V>();
+075
+076        for (final Map.Entry<K, V> entry : source.entrySet()) {
+077            final K key = entry.getKey();
+078            final V value = entry.getValue();
+079            result.put(prefix + '.' + key.toString(), value);
+080        }
+081
+082        return result;
+083    }
+084
+085    /**
+086     * Clones the lhs map and add all things from the rhs map.
+087     *
+088     * @param lhs
+089     *            the first map
+090     * @param rhs
+091     *            the second map
+092     * @param <K>
+093     *            the map key type
+094     * @param <V>
+095     *            the map value type
+096     * @return the merged map
+097     */
+098    public static <K, V> Map<K, V> merge(final Map<K, V> lhs, final Map<K, V> rhs) {
+099
+100        Map<K, V> result = null;
+101
+102        if (lhs == null || lhs.size() == 0) {
+103            result = copy(rhs);
+104        }
+105        else if (rhs == null || rhs.size() == 0) {
+106            result = copy(lhs);
+107        }
+108        else {
+109            result = copy(lhs);
+110            result.putAll(rhs);
+111        }
+112        
+113        return result;
+114    }
+115}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/StringUtils.html b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/StringUtils.html new file mode 100644 index 0000000..18a86e2 --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/src-html/org/apache/commons/exec/util/StringUtils.html @@ -0,0 +1,335 @@ + + + +Source code + + + +
+
001/* 
+002 * Licensed to the Apache Software Foundation (ASF) under one or more
+003 *  contributor license agreements.  See the NOTICE file distributed with
+004 *  this work for additional information regarding copyright ownership.
+005 *  The ASF licenses this file to You under the Apache License, Version 2.0
+006 *  (the "License"); you may not use this file except in compliance with
+007 *  the License.  You may obtain a copy of the License at
+008 *
+009 *      http://www.apache.org/licenses/LICENSE-2.0
+010 *
+011 *  Unless required by applicable law or agreed to in writing, software
+012 *  distributed under the License is distributed on an "AS IS" BASIS,
+013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+014 *  See the License for the specific language governing permissions and
+015 *  limitations under the License.
+016 *
+017 */
+018
+019package org.apache.commons.exec.util;
+020
+021
+022import java.io.File;
+023import java.util.ArrayList;
+024import java.util.List;
+025import java.util.Map;
+026import java.util.StringTokenizer;
+027
+028/**
+029 * Supplement of commons-lang, the stringSubstitution() was in a simpler
+030 * implementation available in an older commons-lang implementation.
+031 *
+032 * This class is not part of the public API and could change without
+033 * warning.
+034 *
+035 * @version $Id: StringUtils.java 1636204 2014-11-02 22:30:31Z ggregory $
+036 */
+037public class StringUtils {
+038
+039    private static final String SINGLE_QUOTE = "\'";
+040    private static final String DOUBLE_QUOTE = "\"";
+041    private static final char SLASH_CHAR = '/';
+042    private static final char BACKSLASH_CHAR = '\\';
+043
+044    /**
+045     * Perform a series of substitutions.
+046     * <p>
+047     * The substitutions are performed by replacing ${variable} in the target string with the value of provided by the
+048     * key "variable" in the provided hash table.
+049     * </p>
+050     * <p>
+051     * A key consists of the following characters:
+052     * </p>
+053     * <ul>
+054     * <li>letter
+055     * <li>digit
+056     * <li>dot character
+057     * <li>hyphen character
+058     * <li>plus character
+059     * <li>underscore character
+060     * </ul>
+061     *
+062     * @param argStr
+063     *            the argument string to be processed
+064     * @param vars
+065     *            name/value pairs used for substitution
+066     * @param isLenient
+067     *            ignore a key not found in vars or throw a RuntimeException?
+068     * @return String target string with replacements.
+069     */
+070    public static StringBuffer stringSubstitution(final String argStr, final Map<? super String, ?> vars, final boolean isLenient) {
+071
+072        final StringBuffer argBuf = new StringBuffer();
+073
+074        if (argStr == null || argStr.length() == 0) {
+075            return argBuf;
+076        }
+077
+078        if (vars == null || vars.size() == 0) {
+079            return argBuf.append(argStr);
+080        }
+081
+082        final int argStrLength = argStr.length();
+083
+084        for (int cIdx = 0; cIdx < argStrLength;) {
+085
+086            char ch = argStr.charAt(cIdx);
+087            char del = ' ';
+088
+089            switch (ch) {
+090
+091                case '$':
+092                    final StringBuilder nameBuf = new StringBuilder();
+093                    del = argStr.charAt(cIdx + 1);
+094                    if (del == '{') {
+095                        cIdx++;
+096
+097                        for (++cIdx; cIdx < argStr.length(); ++cIdx) {
+098                            ch = argStr.charAt(cIdx);
+099                            if (ch == '_' || ch == '.' || ch == '-' || ch == '+' || Character.isLetterOrDigit(ch)) {
+100                                nameBuf.append(ch);
+101                            } else {
+102                                break;
+103                            }
+104                        }
+105
+106                        if (nameBuf.length() >= 0) {
+107
+108                            String value;
+109                            final Object temp = vars.get(nameBuf.toString());
+110
+111                            if (temp instanceof File) {
+112                                // for a file we have to fix the separator chars to allow
+113                                // cross-platform compatibility
+114                                value = fixFileSeparatorChar(((File) temp).getAbsolutePath());
+115                            }
+116                            else {
+117                                value = temp != null ? temp.toString() : null;    
+118                            }
+119
+120                            if (value != null) {
+121                                argBuf.append(value);
+122                            } else {
+123                                if (isLenient) {
+124                                    // just append the unresolved variable declaration
+125                                    argBuf.append("${").append(nameBuf.toString()).append("}");
+126                                } else {
+127                                    // complain that no variable was found
+128                                    throw new RuntimeException("No value found for : " + nameBuf);
+129                                }
+130                            }
+131
+132                            del = argStr.charAt(cIdx);
+133
+134                            if (del != '}') {
+135                                throw new RuntimeException("Delimiter not found for : " + nameBuf);
+136                            }
+137                        }
+138
+139                        cIdx++;
+140                    }
+141                    else {
+142                        argBuf.append(ch);
+143                        ++cIdx;
+144                    }
+145
+146                    break;
+147
+148                default:
+149                    argBuf.append(ch);
+150                    ++cIdx;
+151                    break;
+152            }
+153        }
+154
+155        return argBuf;
+156    }
+157
+158    /**
+159     * Split a string into an array of strings based
+160     * on a separator.
+161     *
+162     * @param input     what to split
+163     * @param splitChar what to split on
+164     * @return the array of strings
+165     */
+166    public static String[] split(final String input, final String splitChar) {
+167        final StringTokenizer tokens = new StringTokenizer(input, splitChar);
+168        final List<String> strList = new ArrayList<String>();
+169        while (tokens.hasMoreTokens()) {
+170            strList.add(tokens.nextToken());
+171        }
+172        return strList.toArray(new String[strList.size()]);
+173    }
+174
+175    /**
+176     * Fixes the file separator char for the target platform
+177     * using the following replacement.
+178     * 
+179     * <ul>
+180     *  <li>'/' &#x2192; File.separatorChar</li>
+181     *  <li>'\\' &#x2192; File.separatorChar</li>
+182     * </ul>
+183     *
+184     * @param arg the argument to fix
+185     * @return the transformed argument 
+186     */
+187    public static String fixFileSeparatorChar(final String arg) {
+188        return arg.replace(SLASH_CHAR, File.separatorChar).replace(
+189                BACKSLASH_CHAR, File.separatorChar);
+190    }
+191
+192    /**
+193     * Concatenates an array of string using a separator.
+194     *
+195     * @param strings the strings to concatenate
+196     * @param separator the separator between two strings
+197     * @return the concatenated strings
+198     */
+199    public static String toString(final String[] strings, final String separator) {
+200        final StringBuilder sb = new StringBuilder();
+201        for (int i = 0; i < strings.length; i++) {
+202            if (i > 0) {
+203                sb.append(separator);
+204            }
+205            sb.append(strings[i]);
+206        }
+207        return sb.toString();
+208    }
+209
+210    /**
+211     * Put quotes around the given String if necessary.
+212     * <p>
+213     * If the argument doesn't include spaces or quotes, return it as is. If it
+214     * contains double quotes, use single quotes - else surround the argument by
+215     * double quotes.
+216     * </p>
+217     *
+218     * @param argument the argument to be quoted
+219     * @return the quoted argument
+220     * @throws IllegalArgumentException If argument contains both types of quotes
+221     */
+222    public static String quoteArgument(final String argument) {
+223
+224        String cleanedArgument = argument.trim();
+225
+226        // strip the quotes from both ends
+227        while (cleanedArgument.startsWith(SINGLE_QUOTE) || cleanedArgument.startsWith(DOUBLE_QUOTE)) {
+228            cleanedArgument = cleanedArgument.substring(1);
+229        }
+230        
+231        while (cleanedArgument.endsWith(SINGLE_QUOTE) || cleanedArgument.endsWith(DOUBLE_QUOTE)) {
+232            cleanedArgument = cleanedArgument.substring(0, cleanedArgument.length() - 1);
+233        }
+234
+235        final StringBuilder buf = new StringBuilder();
+236        if (cleanedArgument.indexOf(DOUBLE_QUOTE) > -1) {
+237            if (cleanedArgument.indexOf(SINGLE_QUOTE) > -1) {
+238                throw new IllegalArgumentException(
+239                        "Can't handle single and double quotes in same argument");
+240            }
+241            return buf.append(SINGLE_QUOTE).append(cleanedArgument).append(
+242                    SINGLE_QUOTE).toString();
+243        } else if (cleanedArgument.indexOf(SINGLE_QUOTE) > -1
+244                || cleanedArgument.indexOf(" ") > -1) {
+245            return buf.append(DOUBLE_QUOTE).append(cleanedArgument).append(
+246                    DOUBLE_QUOTE).toString();
+247        } else {
+248            return cleanedArgument;
+249        }
+250    }
+251
+252    /**
+253     * Determines if this is a quoted argument - either single or
+254     * double quoted.
+255     *
+256     * @param argument the argument to check
+257     * @return true when the argument is quoted
+258     */
+259    public static boolean isQuoted(final String argument) {
+260        return argument.startsWith(SINGLE_QUOTE) && argument.endsWith(SINGLE_QUOTE)
+261                || argument.startsWith(DOUBLE_QUOTE) && argument.endsWith(DOUBLE_QUOTE);
+262    }
+263}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/Holmes/lib/commons-exec-1.3/apidocs/stylesheet.css b/Holmes/lib/commons-exec-1.3/apidocs/stylesheet.css new file mode 100644 index 0000000..0e0d70c --- /dev/null +++ b/Holmes/lib/commons-exec-1.3/apidocs/stylesheet.css @@ -0,0 +1,474 @@ +/* Javadoc style sheet */ +/* +Overall document style +*/ +body { + background-color:#ffffff; + color:#353833; + font-family:Arial, Helvetica, sans-serif; + font-size:76%; + margin:0; +} +a:link, a:visited { + text-decoration:none; + color:#4c6b87; +} +a:hover, a:focus { + text-decoration:none; + color:#bb7a2a; +} +a:active { + text-decoration:none; + color:#4c6b87; +} +a[name] { + color:#353833; +} +a[name]:hover { + text-decoration:none; + color:#353833; +} +pre { + font-size:1.3em; +} +h1 { + font-size:1.8em; +} +h2 { + font-size:1.5em; +} +h3 { + font-size:1.4em; +} +h4 { + font-size:1.3em; +} +h5 { + font-size:1.2em; +} +h6 { + font-size:1.1em; +} +ul { + list-style-type:disc; +} +code, tt { + font-size:1.2em; +} +dt code { + font-size:1.2em; +} +table tr td dt code { + font-size:1.2em; + vertical-align:top; +} +sup { + font-size:.6em; +} +/* +Document title and Copyright styles +*/ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:.8em; + z-index:200; + margin-top:-7px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + background-image:url(resources/titlebar.gif); + background-position:left top; + background-repeat:no-repeat; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* +Navigation bar styles +*/ +.bar { + background-image:url(resources/background.gif); + background-repeat:repeat-x; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:1em; + margin:0; +} +.topNav { + background-image:url(resources/background.gif); + background-repeat:repeat-x; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; +} +.bottomNav { + margin-top:10px; + background-image:url(resources/background.gif); + background-repeat:repeat-x; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; +} +.subNav { + background-color:#dee3e9; + border-bottom:1px solid #9eadc0; + float:left; + width:100%; + overflow:hidden; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding:3px 6px; +} +ul.subNavList li{ + list-style:none; + float:left; + font-size:90%; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; +} +.navBarCell1Rev { + background-image:url(resources/tab.gif); + background-color:#a88834; + color:#FFFFFF; + margin: auto 5px; + border:1px solid #c9aa44; +} +/* +Page header and footer styles +*/ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexHeader { + margin:10px; + position:relative; +} +.indexHeader h1 { + font-size:1.3em; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 25px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:1.2em; +} +/* +Heading styles +*/ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border-top:1px solid #9eadc0; + border-bottom:1px solid #9eadc0; + margin:0 0 6px -8px; + padding:2px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border-top:1px solid #9eadc0; + border-bottom:1px solid #9eadc0; + margin:0 0 6px -8px; + padding:2px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* +Page layout container styles +*/ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:1.0em; +} +.indexContainer h2 { + font-size:1.1em; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:1.1em; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:10px 0 10px 20px; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* +List styles +*/ +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:25px; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #9eadc0; + background-color:#f9f9f9; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:1px solid #9eadc0; + border-top:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; + border-bottom:1px solid #9eadc0; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* +Table styles +*/ +.contentContainer table, .classUseContainer table, .constantValuesContainer table { + border-bottom:1px solid #9eadc0; + width:100%; +} +.contentContainer ul li table, .classUseContainer ul li table, .constantValuesContainer ul li table { + width:100%; +} +.contentContainer .description table, .contentContainer .details table { + border-bottom:none; +} +.contentContainer ul li table th.colOne, .contentContainer ul li table th.colFirst, .contentContainer ul li table th.colLast, .classUseContainer ul li table th, .constantValuesContainer ul li table th, .contentContainer ul li table td.colOne, .contentContainer ul li table td.colFirst, .contentContainer ul li table td.colLast, .classUseContainer ul li table td, .constantValuesContainer ul li table td{ + vertical-align:top; + padding-right:20px; +} +.contentContainer ul li table th.colLast, .classUseContainer ul li table th.colLast,.constantValuesContainer ul li table th.colLast, +.contentContainer ul li table td.colLast, .classUseContainer ul li table td.colLast,.constantValuesContainer ul li table td.colLast, +.contentContainer ul li table th.colOne, .classUseContainer ul li table th.colOne, +.contentContainer ul li table td.colOne, .classUseContainer ul li table td.colOne { + padding-right:3px; +} +.overviewSummary caption, .packageSummary caption, .contentContainer ul.blockList li.blockList caption, .summary caption, .classUseContainer caption, .constantValuesContainer caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#FFFFFF; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + margin:0px; +} +caption a:link, caption a:hover, caption a:active, caption a:visited { + color:#FFFFFF; +} +.overviewSummary caption span, .packageSummary caption span, .contentContainer ul.blockList li.blockList caption span, .summary caption span, .classUseContainer caption span, .constantValuesContainer caption span { + white-space:nowrap; + padding-top:8px; + padding-left:8px; + display:block; + float:left; + background-image:url(resources/titlebar.gif); + height:18px; +} +.overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd { + width:10px; + background-image:url(resources/titlebar_end.gif); + background-repeat:no-repeat; + background-position:top right; + position:relative; + float:left; +} +ul.blockList ul.blockList li.blockList table { + margin:0 0 12px 0px; + width:100%; +} +.tableSubHeadingColor { + background-color: #EEEEFF; +} +.altColor { + background-color:#eeeeef; +} +.rowColor { + background-color:#ffffff; +} +.overviewSummary td, .packageSummary td, .contentContainer ul.blockList li.blockList td, .summary td, .classUseContainer td, .constantValuesContainer td { + text-align:left; + padding:3px 3px 3px 7px; +} +th.colFirst, th.colLast, th.colOne, .constantValuesContainer th { + background:#dee3e9; + border-top:1px solid #9eadc0; + border-bottom:1px solid #9eadc0; + text-align:left; + padding:3px 3px 3px 7px; +} +td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { + font-weight:bold; +} +td.colFirst, th.colFirst { + border-left:1px solid #9eadc0; + white-space:nowrap; +} +td.colLast, th.colLast { + border-right:1px solid #9eadc0; +} +td.colOne, th.colOne { + border-right:1px solid #9eadc0; + border-left:1px solid #9eadc0; +} +table.overviewSummary { + padding:0px; + margin-left:0px; +} +table.overviewSummary td.colFirst, table.overviewSummary th.colFirst, +table.overviewSummary td.colOne, table.overviewSummary th.colOne { + width:25%; + vertical-align:middle; +} +table.packageSummary td.colFirst, table.overviewSummary th.colFirst { + width:25%; + vertical-align:middle; +} +/* +Content styles +*/ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} +/* +Formatting effect styles +*/ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:.9em; +} +.block { + display:block; + margin:3px 0 0 0; +} +.strong { + font-weight:bold; +} diff --git a/Holmes/lib/commons-exec-1.3/commons-exec-1.3-javadoc.jar b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-javadoc.jar new file mode 100644 index 0000000..4659a36 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-javadoc.jar differ diff --git a/Holmes/lib/commons-exec-1.3/commons-exec-1.3-sources.jar b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-sources.jar new file mode 100644 index 0000000..b4bb7c7 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-sources.jar differ diff --git a/Holmes/lib/commons-exec-1.3/commons-exec-1.3-test-sources.jar b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-test-sources.jar new file mode 100644 index 0000000..53fce56 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-test-sources.jar differ diff --git a/Holmes/lib/commons-exec-1.3/commons-exec-1.3-tests.jar b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-tests.jar new file mode 100644 index 0000000..fb22f8b Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/commons-exec-1.3-tests.jar differ diff --git a/Holmes/lib/commons-exec-1.3/commons-exec-1.3.jar b/Holmes/lib/commons-exec-1.3/commons-exec-1.3.jar new file mode 100644 index 0000000..9a64351 Binary files /dev/null and b/Holmes/lib/commons-exec-1.3/commons-exec-1.3.jar differ diff --git a/Holmes/lib/commons-io-2.6.jar b/Holmes/lib/commons-io-2.6.jar new file mode 100644 index 0000000..00556b1 Binary files /dev/null and b/Holmes/lib/commons-io-2.6.jar differ diff --git a/Holmes/lib/commons-text-1.0.jar b/Holmes/lib/commons-text-1.0.jar new file mode 100644 index 0000000..fad2dd1 Binary files /dev/null and b/Holmes/lib/commons-text-1.0.jar differ diff --git a/Holmes/lib/google-collect-0.5.jar b/Holmes/lib/google-collect-0.5.jar new file mode 100644 index 0000000..06ae482 Binary files /dev/null and b/Holmes/lib/google-collect-0.5.jar differ diff --git a/Holmes/lib/intrace-agent.jar b/Holmes/lib/intrace-agent.jar new file mode 100644 index 0000000..8747ba3 Binary files /dev/null and b/Holmes/lib/intrace-agent.jar differ diff --git a/Holmes/lib/intrace-ui.jar b/Holmes/lib/intrace-ui.jar new file mode 100644 index 0000000..003ff1b Binary files /dev/null and b/Holmes/lib/intrace-ui.jar differ diff --git a/Holmes/lib/javax.inject-1.jar b/Holmes/lib/javax.inject-1.jar new file mode 100644 index 0000000..b2a9d0b Binary files /dev/null and b/Holmes/lib/javax.inject-1.jar differ diff --git a/Holmes/lib/jdcallgraph/config.ini b/Holmes/lib/jdcallgraph/config.ini new file mode 100644 index 0000000..bb66c62 --- /dev/null +++ b/Holmes/lib/jdcallgraph/config.ini @@ -0,0 +1,17 @@ +# Callgraph and logs are written to this directory +outDir: /Users/bjohnson/Documents/oxy-workspace/tracer_output + +# Set the log level. Valid levels are 0 - 6: OFF - TRACE +logLevel: 6 + +# Log debug output on stdout +logConsole: true + +# Remove duplicate edges +multiGraph: false + +# One graph per or +groupBy: THREAD + +# store dot files and coverage matrix +writeTo: TRACE, DOT, DATA \ No newline at end of file diff --git a/Holmes/lib/jdcallgraph/jdcallgraph-0.1-agent.jar b/Holmes/lib/jdcallgraph/jdcallgraph-0.1-agent.jar new file mode 100644 index 0000000..000d7e3 Binary files /dev/null and b/Holmes/lib/jdcallgraph/jdcallgraph-0.1-agent.jar differ diff --git a/Holmes/lib/org.eclipse.core.commands-3.3.0.jar b/Holmes/lib/org.eclipse.core.commands-3.3.0.jar new file mode 100755 index 0000000..f61ebba Binary files /dev/null and b/Holmes/lib/org.eclipse.core.commands-3.3.0.jar differ diff --git a/Holmes/lib/org.eclipse.core.resources.jar b/Holmes/lib/org.eclipse.core.resources.jar new file mode 100755 index 0000000..3ed4d4c Binary files /dev/null and b/Holmes/lib/org.eclipse.core.resources.jar differ diff --git a/Holmes/lib/org.eclipse.core.runtime-3.1.0.jar b/Holmes/lib/org.eclipse.core.runtime-3.1.0.jar new file mode 100755 index 0000000..746421b Binary files /dev/null and b/Holmes/lib/org.eclipse.core.runtime-3.1.0.jar differ diff --git a/Holmes/lib/org.eclipse.jdt.core-3.10.0.jar b/Holmes/lib/org.eclipse.jdt.core-3.10.0.jar new file mode 100644 index 0000000..d396c3c Binary files /dev/null and b/Holmes/lib/org.eclipse.jdt.core-3.10.0.jar differ diff --git a/Holmes/lib/org.eclipse.jdt.core-3.6.0.v_a58.jar b/Holmes/lib/org.eclipse.jdt.core-3.6.0.v_a58.jar new file mode 100755 index 0000000..c6b5ad4 Binary files /dev/null and b/Holmes/lib/org.eclipse.jdt.core-3.6.0.v_a58.jar differ diff --git a/Holmes/lib/org.eclipse.jdt.core-3.8.0.v_c18.jar b/Holmes/lib/org.eclipse.jdt.core-3.8.0.v_c18.jar new file mode 100755 index 0000000..e484895 Binary files /dev/null and b/Holmes/lib/org.eclipse.jdt.core-3.8.0.v_c18.jar differ diff --git a/Holmes/lib/org.eclipse.jdt.ui-3.12.2.jar b/Holmes/lib/org.eclipse.jdt.ui-3.12.2.jar new file mode 100644 index 0000000..0a623d8 Binary files /dev/null and b/Holmes/lib/org.eclipse.jdt.ui-3.12.2.jar differ diff --git a/Holmes/lib/org.eclipse.jdt.ui_3.5.2.r352_v20100106-0800.jar b/Holmes/lib/org.eclipse.jdt.ui_3.5.2.r352_v20100106-0800.jar new file mode 100644 index 0000000..b54febb Binary files /dev/null and b/Holmes/lib/org.eclipse.jdt.ui_3.5.2.r352_v20100106-0800.jar differ diff --git a/Holmes/lib/org.eclipse.jface-3.6.0.jar b/Holmes/lib/org.eclipse.jface-3.6.0.jar new file mode 100755 index 0000000..41ced57 Binary files /dev/null and b/Holmes/lib/org.eclipse.jface-3.6.0.jar differ diff --git a/Holmes/lib/org.eclipse.jface.text_3.5.0.jar b/Holmes/lib/org.eclipse.jface.text_3.5.0.jar new file mode 100755 index 0000000..b249011 Binary files /dev/null and b/Holmes/lib/org.eclipse.jface.text_3.5.0.jar differ diff --git a/Holmes/lib/org.eclipse.osgi-3.2.2.jar b/Holmes/lib/org.eclipse.osgi-3.2.2.jar new file mode 100755 index 0000000..525067d Binary files /dev/null and b/Holmes/lib/org.eclipse.osgi-3.2.2.jar differ diff --git a/Holmes/lib/org.eclipse.text_3.5.0 copy.jar b/Holmes/lib/org.eclipse.text_3.5.0 copy.jar new file mode 100755 index 0000000..6945b18 Binary files /dev/null and b/Holmes/lib/org.eclipse.text_3.5.0 copy.jar differ diff --git a/Holmes/lib/org.eclipse.text_3.5.0.jar b/Holmes/lib/org.eclipse.text_3.5.0.jar new file mode 100755 index 0000000..6945b18 Binary files /dev/null and b/Holmes/lib/org.eclipse.text_3.5.0.jar differ diff --git a/Holmes/lib/org.eclipse.ui-3.5.0.I20090604-2000.jar b/Holmes/lib/org.eclipse.ui-3.5.0.I20090604-2000.jar new file mode 100644 index 0000000..55dbbba Binary files /dev/null and b/Holmes/lib/org.eclipse.ui-3.5.0.I20090604-2000.jar differ diff --git a/Holmes/lib/org.eclipse.ui.ide-3.3.2.jar b/Holmes/lib/org.eclipse.ui.ide-3.3.2.jar new file mode 100755 index 0000000..4812d46 Binary files /dev/null and b/Holmes/lib/org.eclipse.ui.ide-3.3.2.jar differ diff --git a/Holmes/lib/org.eclipse.ui.workbench-3.1.0.jar b/Holmes/lib/org.eclipse.ui.workbench-3.1.0.jar new file mode 100755 index 0000000..d2247c4 Binary files /dev/null and b/Holmes/lib/org.eclipse.ui.workbench-3.1.0.jar differ diff --git a/Holmes/lib/org.eclipse.ui.workbench-3.3.2.jar b/Holmes/lib/org.eclipse.ui.workbench-3.3.2.jar new file mode 100755 index 0000000..e4431ff Binary files /dev/null and b/Holmes/lib/org.eclipse.ui.workbench-3.3.2.jar differ diff --git a/Holmes/lib/org.eclipse.ui.workbench.texteditor-3.3.2.jar b/Holmes/lib/org.eclipse.ui.workbench.texteditor-3.3.2.jar new file mode 100755 index 0000000..80a0a36 Binary files /dev/null and b/Holmes/lib/org.eclipse.ui.workbench.texteditor-3.3.2.jar differ diff --git a/Holmes/lib/roaster-api-2.20.8.Final.jar b/Holmes/lib/roaster-api-2.20.8.Final.jar new file mode 100644 index 0000000..e192702 Binary files /dev/null and b/Holmes/lib/roaster-api-2.20.8.Final.jar differ diff --git a/Holmes/lib/string-similarity-1.0.0.jar b/Holmes/lib/string-similarity-1.0.0.jar new file mode 100644 index 0000000..ef0692d Binary files /dev/null and b/Holmes/lib/string-similarity-1.0.0.jar differ diff --git a/Holmes/lib/swt.jar b/Holmes/lib/swt.jar new file mode 100644 index 0000000..bbd9d8a Binary files /dev/null and b/Holmes/lib/swt.jar differ diff --git a/Holmes/plugin.xml b/Holmes/plugin.xml new file mode 100644 index 0000000..293069e --- /dev/null +++ b/Holmes/plugin.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Holmes/src/org/holmes/plugin/actions/RunHolmes.java b/Holmes/src/org/holmes/plugin/actions/RunHolmes.java new file mode 100644 index 0000000..15b45db --- /dev/null +++ b/Holmes/src/org/holmes/plugin/actions/RunHolmes.java @@ -0,0 +1,2119 @@ +package org.holmes.plugin.actions; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.io.FileUtils; +import org.apache.commons.text.similarity.LevenshteinDetailedDistance; +import org.apache.commons.text.similarity.LevenshteinResults; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.ITypeRoot; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTParser; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.BooleanLiteral; +import org.eclipse.jdt.core.dom.CastExpression; +import org.eclipse.jdt.core.dom.CharacterLiteral; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.NumberLiteral; +import org.eclipse.jdt.core.dom.ParenthesizedExpression; +import org.eclipse.jdt.core.dom.PrefixExpression; +import org.eclipse.jdt.core.dom.PrefixExpression.Operator; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor; +import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.ui.IEditorActionDelegate; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IFileEditorInput; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.holmes.plugin.nodevisitor.GeneratedTestVisitor; +import org.holmes.plugin.nodevisitor.TestMethodVisitor; +import org.holmes.plugin.util.Test; + +public class RunHolmes implements IEditorActionDelegate { + private IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + private IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + private IWorkbenchPage page = window.getActivePage(); + + public File workingDirectory = new File ("/Users/bjohnson/Documents/Research_2019-2020/causal_testing/Holmes/"); + + public String testGenJar = workingDirectory.getPath() + "/lib/evosuite-1.0.6.jar"; + + public String packageNameStart = "org"; + public File inputFile; + + public Object input; + + File binInstrumentedTestDir; + File binInstrumentedDepDir; + + + IFile testFile; + Document testDocument; + ICompilationUnit icu; + AST ast; + CompilationUnit cu; + ASTParser parser; + + // parameter from single method parameter call + Object currentParam; + // parameters from multi-parameter method call + List currentParams = new ArrayList<>(); + + boolean isMultiParam; + + Test targetTest; + IProject targetProject; + String targetProjectName; + + List filesToExport = new ArrayList<>(); + + List passingTests = new ArrayList<>(); + List failingTests = new ArrayList<>(); + + // store input closest to original found in generated tests + String closestGeneratedInput; + // store inputs closest to original for multi-param +// List closestGeneratedInputs; + HashMap> closestGeneratedInputs = new HashMap<>(); + + List executedInputs = new ArrayList<>(); + + List fuzzedValues = new ArrayList<>();; + + HashMap editDistances = new HashMap(); + List distanceResults = new ArrayList(); + + String[] srcDirectory; + String[] classpath; + + + @Override + public void run(IAction arg0) { + +// IViewPart view; +// try { +// view = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("org.holmes.plugin.views.HolmesView"); +// PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().hideView(view); +// } catch (PartInitException e2) { +// e2.printStackTrace(); +// } + + // File of interest + IEditorInput input = editor.getEditorInput(); + testFile = ((IFileEditorInput)input).getFile(); + + // get selected method & line number + CompilationUnitEditor editor = (CompilationUnitEditor)this.editor; + ITextSelection selection = getSelection(editor); + int lineNo = selection.getStartLine() +1; + String selectedMethod = selection.getText(); + + System.out.println("Line number = " + lineNo); + System.out.println("The method under test is: " + selectedMethod); + + // create test object + targetTest = new Test(testFile.getName()); + targetProjectName = testFile.getProject().getName(); + + //if training defect, run the rest + + if (targetProjectName.equals("Defect_0_Training")) { + runFullProcess(selection, lineNo, selectedMethod); + } + + try { + IViewPart output = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("org.holmes.plugin.views.HolmesView"); + + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().hideView(output); + TimeUnit.SECONDS.sleep(3); + + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("org.holmes.plugin.views.HolmesView"); + + } + catch (InterruptedException e) { + + e.printStackTrace(); + } + catch (PartInitException e) { + e.printStackTrace(); + } + + + } + + + private void runFullProcess(ITextSelection selection, int lineNo, String selectedMethod) { + // create compilation unit from test file + icu = JavaCore.createCompilationUnitFrom(testFile); + + // directory where source project is located (working directory for test generation) + File executorDirectory = new File(workingDirectory.getPath() + "/" + testFile.getProject().getName()); + + + try { + // creation of document containing source code + String source = icu.getSource(); + testDocument = new Document(source); + + // find source directory + File baseClassDir; + + if ((new File(executorDirectory.getPath() + "/bin/").exists())){ + baseClassDir = new File(executorDirectory.getPath() + "/bin/"); + } else { + baseClassDir = new File(executorDirectory.getPath() + "/target/classes"); + } + File srcDir; + + if ((new File(executorDirectory.getPath() + "/src").exists())) { + srcDir = new File(executorDirectory.getPath() + "/src/"); + + } else { + srcDir = new File(executorDirectory.getPath() + "/source/"); + } + + //get Java project for type bindings + IProject currentProject = testFile.getProject(); + IJavaProject javaProject = JavaCore.create(currentProject); + + if (javaProject.exists()) { + System.out.println("Java project found!"); + + classpath = getClasspath(javaProject); + srcDirectory = new String[] {srcDir.getPath()}; + + // create and set up ASTParser (with source directory and classpath) + updateASTParser(); + + } else { + System.out.println("No java projects found!"); + } + + // get parameter of interest + getParamOfInterest(selection, lineNo, selectedMethod, executorDirectory, source); + + System.out.println("\nTest file: " + targetTest.getFilename()); + System.out.println("Project: " + targetProjectName); + System.out.println("Test method: " + targetTest.getTestMethod()); + System.out.println("Target method: " + targetTest.getTargetMethod()); + + if (targetTest.getOriginalParameter() == null) { + isMultiParam = true; + System.out.println("Original test parameters: "); + for (String s : targetTest.getOriginalParameters()) { + System.out.println(s); + } + } else { + isMultiParam = false; + System.out.println("Original test parameter: " + targetTest.getOriginalParameter()); + } + + System.out.println("Full test: " + targetTest.getFullTest() + "\n"); + + // write original test to file to pipe to view later +// writeOriginalTestToFile(workingDirectory.getPath()+"/holmes-output-original.txt"); + writeOriginalTestToFile(workingDirectory.getAbsolutePath() + "/holmes-output-original.txt"); + + String testFile = this.testFile.getName(); + String fileUnderTest = testFile.substring(0, testFile.indexOf("Test")); + String targetFilePackage = ""; + String classDir = baseClassDir.getAbsolutePath(); + + // find file under test + boolean recursive = true; + Collection files = FileUtils.listFiles(srcDir, null, recursive); + + for (Iterator i = files.iterator(); i.hasNext();) { + File f = (File) i.next(); + + // only check files that are java files + if (f.getName().contains(".java")) { + + String className = f.getName().substring(0, f.getName().indexOf(".java")); + + // check if target file; if so, store necessary information + if (className.equals(fileUnderTest)) { + System.out.println("Path to target file = " + f.getAbsolutePath()); + + File targetFileDir = new File (f.getAbsolutePath()); + String pathToFile = targetFileDir.getAbsolutePath(); + targetFilePackage = pathToFile.substring(pathToFile.indexOf("org"), pathToFile.length()-5).replace("/", "."); + + String targetFileDirectory = targetFilePackage.substring(0, targetFilePackage.lastIndexOf(".")); + classDir = baseClassDir + "/" + targetFileDirectory.replace(".", "/"); + + System.out.println("Working directory = " + executorDirectory.getPath()); + System.out.println("File package = " + targetFilePackage); + System.out.println("Class file directory = " + classDir); + + } + } + } + + /* + * RUN EVOSUITE + */ + +// runEvoSuite(executorDirectory, targetFilePackage, baseClassDir.getAbsolutePath()); + + /* + * PARSE TESTS FOR INPUTS + */ + + List evoGeneratedInputs = new ArrayList<>(); + String targetMethod = targetTest.getTargetMethod(); + System.out.println(targetMethod); + + // directory with tests + targetFilePackage = targetFilePackage.substring(0, targetFilePackage.lastIndexOf(".")); + File evoTestsDir = new File(executorDirectory.getAbsolutePath() + "/evosuite-tests/" + targetFilePackage.replace(".", "/")); + System.out.println(evoTestsDir.getAbsolutePath()); + + // find and parse files in directory + File[] testFiles = evoTestsDir.listFiles(); + + parseGeneratedTests(targetMethod, testFiles); + + if (isMultiParam) { + System.out.println("\n Original parameters are --> " + targetTest.getOriginalParameters()); + } else { + System.out.println("\n Original parameter is --> " + targetTest.getOriginalParameter()); + + } + + + /* + * RUN INPUT FUZZERS + */ + + String cmdLineArg = ""; + + // Run fuzzers with original input(s) + // TODO update to iterate over currentParams (Literal, Decls, Assigns) not originalParameters (Strings) + if (isMultiParam) { + List params = targetTest.getOriginalParameters(); + + for (int i=0; i < params.size(); i++) { + String param = params.get(i); + + if (param.contains("=")) { + cmdLineArg = param.substring(param.indexOf("="), param.indexOf(";")).replaceAll("\"", ""); + } else { + cmdLineArg = params.get(i).replaceAll("\"", ""); + } + + System.out.println("Input to fuzz --> " + cmdLineArg); + + String fileId = Integer.toString(i); + runFuzzers(cmdLineArg, true, fileId); + } + } else { + cmdLineArg = targetTest.getOriginalParameter().replaceAll("\"", ""); + System.out.println("Input to fuzz --> " + cmdLineArg); + + runFuzzers(cmdLineArg, true, "1"); + } + + // Run fuzzers with generated input(s) + Iterator it = closestGeneratedInputs.entrySet().iterator(); + + // iterate over each parameter (will only be multiple iterations if multiple parameters) + int param_count = 0; + while (it.hasNext()) { + Map.Entry> pair = (Map.Entry>) it.next(); + List genParams = pair.getValue(); + List noDups = new ArrayList<>(new HashSet<>(genParams)); + + for (int i=0; i < noDups.size(); i++) { + cmdLineArg = noDups.get(i).replaceAll("\"", ""); + System.out.println("Input to fuzz --> " + cmdLineArg); + + String paramId = Integer.toString(param_count); + String fileId = Integer.toString(i); + runFuzzers(cmdLineArg, false, paramId+ "_"+ fileId); + } + + param_count ++; + } + + /* + * PARSE FUZZER OUTPUT & EXECUTE TESTS + */ + + // parse original mutation files + if (isMultiParam) { + List originalParams = targetTest.getOriginalParameters(); + for (int i=0; i originalParams = new ArrayList<>(); + originalParams.add(original); + + updateAndRunTest(lineNo, executorDirectory, originalParams, 0, br, threshold, 0, false); + + } + + } + + // parse generated mutation files + Iterator it2 = closestGeneratedInputs.entrySet().iterator(); + + // iterate over each parameter (will only be multiple iterations if multiple parameters) + int param_num = 0; + + while (it.hasNext()) { + + Map.Entry> pair = (Map.Entry>) it.next(); + + List genParams = pair.getValue(); + + for (int i=0; i param = new ArrayList<>(); + param.add(targetTest.getOriginalParameter()); + updateAndRunTest(0, executorDirectory, param, 0, new BufferedReader(new FileReader(workingDirectory.getAbsolutePath() + "/holmes-output-original.txt")), 2, 0, true); + } + + + + + } catch (JavaModelException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } +// catch (ExecuteException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (BadLocationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + private void updateAndRunTest(int lineNo, File executorDirectory, List originalParams, int i, + BufferedReader br, int threshold, int paramPlace, boolean last) + throws IOException, BadLocationException, JavaModelException, InterruptedException, ExecuteException { + + String line; + int distance; + + if (last) { + updateTestInput(0, originalParams.get(0)); + savePage(page); + } else { + while ((line = br.readLine() )!= null) { + + if ((failingTests.size() < 3 && passingTests.size() < 3)) { + // find inputs within threshold and run + if (isValidNumber(line)) { + Object oldNum = determineNumType(originalParams.get(i)); + Object newNum = determineNumType(line); + + // check if generated/fuzzed input same type as original (so compiles and runs) + if (oldNum instanceof Integer && newNum instanceof Integer) { + Integer originalNum = (Integer) oldNum; + Integer fuzzNum = (Integer) newNum; + + // see how close fuzzed input is from original + distance = Math.abs(originalNum.intValue()-fuzzNum.intValue()); + + // if difference is within threshold, run test with that input + if (distance > 0 && distance <= threshold) { + + executedInputs.add(fuzzNum); + + // update and save page + updateTestInput(paramPlace, fuzzNum); + savePage(page); + + // wait for build to finish before running test + TimeUnit.SECONDS.sleep(2); + + // update AST parser + updateASTParser(); + getMethodParameters(testDocument.get(), targetTest.getTargetMethod(), targetTest.getTestMethod(), false, lineNo); + + // D4J compile + d4jCompile(executorDirectory); + + // D4J test + d4jTest(executorDirectory); + } + + } else if (oldNum instanceof Double && newNum instanceof Double) { + Double originalNum = (Double) oldNum; + Double fuzzNum = (Double) newNum; + + distance = (int) Math.abs(originalNum.doubleValue()-fuzzNum.doubleValue()); + + if (distance > 0 && distance <= threshold) { + + executedInputs.add(fuzzNum); + + // update and save page + updateTestInput(paramPlace, fuzzNum); + savePage(page); + + // wait for build to finish before running test + TimeUnit.SECONDS.sleep(2); + + // update AST parser + updateASTParser(); + getMethodParameters(testDocument.get(), targetTest.getTargetMethod(), targetTest.getTestMethod(), false, lineNo); + + // D4J compile + d4jCompile(executorDirectory); + + // D4J test + d4jTest(executorDirectory); + } + + } else if (oldNum instanceof Float && newNum instanceof Float) { + Float originalNum = (Float) oldNum; + Float fuzzNum = (Float) newNum; + + distance = (int) Math.abs(originalNum.floatValue()-fuzzNum.floatValue()); + + if (distance > 0 && distance <= threshold) { + + executedInputs.add(fuzzNum); + + // update and save page + updateTestInput(paramPlace, fuzzNum); + savePage(page); + + // wait for build to finish before running test + TimeUnit.SECONDS.sleep(2); + + // update AST parser + updateASTParser(); + getMethodParameters(testDocument.get(), targetTest.getTargetMethod(), targetTest.getTestMethod(), false, lineNo); + + // D4J compile + d4jCompile(executorDirectory); + + // D4J test + d4jTest(executorDirectory); + } + + + } else if(oldNum instanceof Long && newNum instanceof Long) { + Long originalNum = (Long) oldNum; + Long fuzzNum = (Long) newNum; + + distance = (int) Math.abs(originalNum.longValue()-fuzzNum.longValue()); + + if (distance > 0 && distance <= threshold) { + + executedInputs.add(fuzzNum); + + // update and save page + updateTestInput(paramPlace, fuzzNum); + savePage(page); + + // wait for build to finish before running test + TimeUnit.SECONDS.sleep(2); + + // update AST parser + updateASTParser(); + getMethodParameters(testDocument.get(), targetTest.getTargetMethod(), targetTest.getTestMethod(), false, lineNo); + + // D4J compile + d4jCompile(executorDirectory); + + // D4J test + d4jTest(executorDirectory); + } + + + } else if (oldNum instanceof BigInteger && newNum instanceof BigInteger) { + BigInteger originalNum = (BigInteger) oldNum; + BigInteger fuzzNum = (BigInteger) newNum; + + distance = Math.abs(originalNum.intValue()-fuzzNum.intValue()); + + if (distance > 0 && distance <= threshold) { + + executedInputs.add(fuzzNum); + + // update and save page + updateTestInput(paramPlace, fuzzNum); + savePage(page); + + // wait for build to finish before running test + TimeUnit.SECONDS.sleep(2); + + // update AST parser + updateASTParser(); + getMethodParameters(testDocument.get(), targetTest.getTargetMethod(), targetTest.getTestMethod(), false, lineNo); + + // D4J compile + d4jCompile(executorDirectory); + + // D4J test + d4jTest(executorDirectory); + } + + } else if (oldNum instanceof BigDecimal && newNum instanceof BigDecimal) { + BigDecimal originalNum = (BigDecimal) oldNum; + BigDecimal fuzzNum = (BigDecimal) newNum; + + distance = (int) Math.abs(originalNum.floatValue()-fuzzNum.floatValue()); + + if (distance > 0 && distance <= threshold) { + + executedInputs.add(fuzzNum); + + // update and save page + updateTestInput(paramPlace, fuzzNum); + savePage(page); + + // wait for build to finish before running test + TimeUnit.SECONDS.sleep(2); + + // update AST parser + updateASTParser(); + getMethodParameters(testDocument.get(), targetTest.getTargetMethod(), targetTest.getTestMethod(), false, lineNo); + + // D4J compile + d4jCompile(executorDirectory); + + // D4J test + d4jTest(executorDirectory); + } + } + } else { + if (!line.startsWith("FuzzManager")) { + String oldString = originalParams.get(i); + String fuzzString = line; + + distance = levenshteinDistance(oldString, fuzzString); + + if (distance > 0 && distance <= threshold) { + + executedInputs.add(fuzzString); + + // update and save page + updateTestInput(paramPlace, fuzzString); + savePage(page); + + // wait for build to finish before running test + TimeUnit.SECONDS.sleep(2); + + // update AST parser + updateASTParser(); + getMethodParameters(testDocument.get(), targetTest.getTargetMethod(), targetTest.getTestMethod(), false, lineNo); + + // D4J compile + d4jCompile(executorDirectory); + + // D4J test + d4jTest(executorDirectory); + } + + } + } + } + } + + } + + } + + private String[] getClasspath(IJavaProject javaProject) throws JavaModelException { + IClasspathEntry[] rawClassPath = javaProject.getRawClasspath(); + String[] classpathEntries = new String[rawClassPath.length]; + + for (int i=0; i < rawClassPath.length; i++) { + classpathEntries[i] = rawClassPath[i].toString(); + } + + IJavaElement element = JavaCore.create(testFile); + ICompilationUnit icu = (ICompilationUnit) element; + return classpathEntries; + } + + private void getParamOfInterest(ITextSelection selection, int lineNo, String selectedMethod, File executorDirectory, + String source) throws JavaModelException { + boolean first = true; + + // get test method of selected method + int selectionOffset = selection.getOffset(); + ITypeRoot root = EditorUtility.getEditorInputJavaElement(this.editor, false); + IJavaElement selectedElement = root.getElementAt(selectionOffset); + + String targetTestMethod = selectedElement.getElementName(); + + // pass target method into visitor to get test method and other relevant parts + getMethodParameters(source, selectedMethod, targetTestMethod, first, lineNo); + + targetTest.setTargetMethod(selectedMethod); + + } + + private String updateTestInput(int paramPlace, Object param) + throws BadLocationException, JavaModelException { + + // Creation of ASTRewrite + ASTRewrite rewrite = ASTRewrite.create(ast); + String newSource = null; + + if (isMultiParam) { + for (int i=0; i " + file.getName()); + + // find generated inputs closest to each original + List generatedInputs = findGeneratedInputs(targetMethod, file); + List originals = targetTest.getOriginalParameters(); + String original = targetTest.getOriginalParameter(); + + int distance = 0; + Object oldNumValue; + Object newNumValue; + + for (int j=0; j < generatedInputs.size(); j++) { + + // check if multi or single parameter + Object singleGenerated = generatedInputs.get(j); + if (singleGenerated instanceof ArrayList) { + // multi-param + List genParams = (ArrayList)singleGenerated; + + // iterate over lists to find compare inputs in each position (assumption = same number of params and same order) + if (originals.size() == genParams.size()) { + + for (int i=0; i < originals.size(); i++) { + + String[] oldAndNew = new String[2]; + + String originalParam = originals.get(i); + Object generatedParam = genParams.get(i); + + if (generatedParam instanceof NumberLiteral) { + NumberLiteral newNum = (NumberLiteral) generatedParam; + + Object oldNumType = determineNumType(originalParam); + Object newNumType = determineNumType(newNum.toString()); + + distance = getDistance(originalParam, oldNumType, newNumType); + + oldAndNew[0] = originalParam; + oldAndNew[1] = newNum.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (generatedParam instanceof CastExpression) { + CastExpression fullGenerated = (CastExpression) generatedParam; + Type paramType = fullGenerated.getType(); + Expression paramValue = fullGenerated.getExpression(); + + Object oldNumType = determineNumType(originalParam); + Object newNumType = determineNumType(paramValue.toString()); + + distance = getDistance(originalParam, oldNumType, newNumType); + + oldAndNew[0] = originalParam; + oldAndNew[1] = fullGenerated.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (generatedParam instanceof PrefixExpression) { + PrefixExpression fullGenerated = (PrefixExpression) generatedParam; + + System.out.println(fullGenerated.getOperator()); + System.out.println(fullGenerated.getOperand()); + + Object oldNumType = determineNumType(originalParam); + Object newNumType = determineNumType(fullGenerated.toString()); + + distance = getDistance(originalParam, oldNumType, newNumType.toString()); + + oldAndNew[0] = originalParam; + oldAndNew[1] = fullGenerated.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (generatedParam instanceof ParenthesizedExpression) { + ParenthesizedExpression fullGenerated = (ParenthesizedExpression) generatedParam; + Expression genValue = fullGenerated.getExpression(); + + Object oldNumType = determineNumType(originalParam); + Object newNumType = determineNumType(genValue.toString()); + + distance = getDistance(originalParam, oldNumType, newNumType); + + oldAndNew[0] = originalParam; + oldAndNew[1] = fullGenerated.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (generatedParam instanceof StringLiteral || generatedParam instanceof CharacterLiteral) { + + String genInput = String.valueOf(singleGenerated); + + if (originalParam.length() < genInput.length()) { + distance = hammingDistance(originalParam, genInput); + } else { + distance = hammingDistance(genInput, originalParam); + } + + oldAndNew[0] = originalParam; + oldAndNew[1] = genInput; + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + } else if (generatedParam instanceof SimpleName) { + // TODO what to do if simple name? am I storing what I need from ASTVisitor? + } + } + } + + } else { + + System.out.println("Generated input = " + singleGenerated.toString()); + + String[] oldAndNew = new String[2]; + + // Strings (Hamming distance) + if (singleGenerated instanceof StringLiteral || singleGenerated instanceof CharacterLiteral) { + String genInput = String.valueOf(singleGenerated); + + if (genInput.startsWith("\"")) { + genInput = genInput.substring(1, genInput.length()-1); + } + + System.out.println(original); + System.out.println(genInput); + + if (original.length() < genInput.length()) { + distance = hammingDistance(original, genInput); + } else { + distance = hammingDistance(genInput, original); + } + + oldAndNew[0] = original; + oldAndNew[1] = genInput; + + if (!genInput.equals("\"\"")) { + editDistances.put(oldAndNew, distance); + } + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (singleGenerated instanceof NumberLiteral) { + NumberLiteral newNum = (NumberLiteral) singleGenerated; + + Object oldNumType = determineNumType(original); + Object newNumType = determineNumType(newNum.toString()); + + distance = getDistance(original, oldNumType, newNumType); + + oldAndNew[0] = original; + oldAndNew[1] = newNum.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (singleGenerated instanceof PrefixExpression) { + PrefixExpression fullGenerated = (PrefixExpression) singleGenerated; + + System.out.println(fullGenerated.getOperator()); + System.out.println(fullGenerated.getOperand()); + + Object oldNumType = determineNumType(original); + Object newNumType = determineNumType(fullGenerated.toString()); + + distance = getDistance(original, oldNumType, newNumType.toString()); + + oldAndNew[0] = original; + oldAndNew[1] = fullGenerated.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (singleGenerated instanceof CastExpression) { + CastExpression fullGenerated = (CastExpression) singleGenerated; + Type paramType = fullGenerated.getType(); + Expression paramValue = fullGenerated.getExpression(); + + Object oldNumType = determineNumType(original); + Object newNumType = determineNumType(paramValue.toString()); + + distance = getDistance(original, oldNumType, newNumType); + + oldAndNew[0] = original; + oldAndNew[1] = fullGenerated.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } else if (singleGenerated instanceof ParenthesizedExpression) { + ParenthesizedExpression fullGenerated = (ParenthesizedExpression) singleGenerated; + Expression genValue = fullGenerated.getExpression(); + + Object oldNumType = determineNumType(original); + Object newNumType = determineNumType(genValue .toString()); + + distance = getDistance(original, oldNumType, newNumType); + + oldAndNew[0] = original; + oldAndNew[1] = fullGenerated.toString(); + + editDistances.put(oldAndNew, distance); + + System.out.println("Success! Distance between original and generated input = " + distance); + + } + + } + } + + System.out.println("Parsing of generated inputs successful!"); + + // find closest input to original(s) + closestGeneratedInputs = findClosestInputs(isMultiParam); + + } + + + } + } + } + + private int getDistance(String original, Object oldNumType, Object newNumType) { + int distance = 0; + if (oldNumType != null && newNumType != null) { + if (oldNumType instanceof Integer && newNumType instanceof Integer) { + Integer oldVal = (Integer) oldNumType; + Integer genVal = (Integer) newNumType; + + distance = Math.abs(oldVal - genVal); + } else if (determineNumType(original) instanceof Double && newNumType instanceof Double) { + Double oldVal = (Double) oldNumType; + Double genVal = (Double) newNumType; + + distance = (int) Math.abs(oldVal-genVal); + } else if (oldNumType instanceof Float && newNumType instanceof Float) { + Float oldVal = (Float) oldNumType; + Float genVal = (Float) newNumType; + + distance = (int) Math.abs(oldVal-genVal); + } else if (oldNumType instanceof Long && newNumType instanceof Long) { + Long oldVal = (Long) oldNumType; + Long genVal = (Long) newNumType; + + distance = (int) Math.abs(oldVal-genVal); + } else if (oldNumType instanceof BigInteger && newNumType instanceof BigInteger) { + BigInteger oldVal = (BigInteger) oldNumType; + BigInteger genVal = (BigInteger) newNumType; + + distance = (int) Math.abs(oldVal.floatValue()-genVal.floatValue()); + } else if (oldNumType instanceof BigDecimal && newNumType instanceof BigDecimal) { + BigDecimal oldVal = (BigDecimal) oldNumType; + BigDecimal genVal = (BigDecimal) newNumType; + + distance = (int) Math.abs(oldVal.floatValue() - genVal.floatValue()); + } + } + + return distance; + } + + private Object determineNumType(String newNum) { + try { + Integer newNumber = Integer.parseInt(newNum.toString()); + System.out.println(newNum + " is an integer."); + + return newNumber; + + } catch (NumberFormatException e) { + System.out.println(newNum + " is not an integer!"); + } + + try { + Double newNumber = Double.parseDouble(newNum); + System.out.println(newNum + " is a double."); + + return newNumber; + + } catch (NumberFormatException e) { + System.out.println(newNum.toString() + " is not a double!"); + + try { + Float newNumber = Float.parseFloat(newNum); + System.out.println(newNum + " is a float."); + + return newNumber; + + } catch (NumberFormatException e1) { + System.out.println(newNum + " is not a float!"); + } + } + + try { + Long newNumber = Long.parseLong(newNum); + System.out.println(newNum + " is a long."); + + return newNumber; + } catch (NumberFormatException e) { + System.out.println(newNum + " is not a long!"); + } + + try { + BigInteger newNumber = new BigInteger(newNum); + System.out.println(newNum + " is a Big Integer."); + + return newNumber; + + } catch (NumberFormatException e) { + System.out.println(newNum + " is not a Big Integer!"); + } + + try { + BigDecimal newNumber = new BigDecimal(newNum); + System.out.println(newNum + " is a Big Decimal."); + + return newNumber; + + } catch (NumberFormatException e) { + System.out.println(newNum + " is not a Big Decimal!"); + } + + return null; + } + + private void runEvoSuite(File executorDirectory, String targetClassPackage, String classDir) + throws ExecuteException, IOException { + DefaultExecutor evoExecutor = new DefaultExecutor(); + evoExecutor.setWorkingDirectory(executorDirectory); + + CommandLine runEvoSuiteCmd = new CommandLine("java"); + runEvoSuiteCmd.addArgument("-jar"); + runEvoSuiteCmd.addArgument(testGenJar); + runEvoSuiteCmd.addArgument("-class"); + runEvoSuiteCmd.addArgument(targetClassPackage); + runEvoSuiteCmd.addArgument("-projectCP"); + runEvoSuiteCmd.addArgument(classDir); + runEvoSuiteCmd.addArgument("-criterion"); + runEvoSuiteCmd.addArgument("branch"); + + evoExecutor.execute(runEvoSuiteCmd); + } + + private List findGeneratedInputs(String targetMethod, File file) throws FileNotFoundException, IOException { + InputStream is = new FileInputStream(file); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + + + String line = br.readLine(); + StringBuilder sb = new StringBuilder(); + + while (line != null) { + sb.append(line).append("\n"); + line = br.readLine(); + } + + String fileAsString = sb.toString(); + Document genTestDocument = new Document(fileAsString); + + +// +// IFile genTestFile = (IFile) file; +// IJavaElement element = JavaCore.create(genTestFile); +// ICompilationUnit icu = (ICompilationUnit) element; + + // TODO Make sure this works! + ASTParser genTestParser = createParser(genTestDocument.get()); + CompilationUnit gcu = (CompilationUnit) genTestParser.createAST(null); + + GeneratedTestVisitor visitor = new GeneratedTestVisitor(fileAsString.toCharArray(), targetMethod); + gcu.accept(visitor); + + List generatedInputs = new ArrayList<>(); + + // for single parameter tests + if (!visitor.getIsMultiParam()) { + generatedInputs = visitor.getGeneratedSingleParamInputs(); + } else { + generatedInputs = visitor.getGeneratedMultiParamInputs(); + } + + return generatedInputs; + } + + private String findClosestInput(HashMap editDistances) { + String closestInput = ""; + int lowestDistance = 0; + boolean firstIteration = true; + + Iterator it = editDistances.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pair = (Map.Entry)it.next(); + int value = (int) pair.getValue(); + String key = pair.getKey().toString(); + + System.out.println("Input = " + key + " with edit distance = " + value); + + if (firstIteration) { + closestInput = key; + lowestDistance = value; + firstIteration = false; + } else { + if (value < lowestDistance) { + closestInput = key; + lowestDistance = value; + } + } + } + + return closestInput; + } + + private HashMap> findClosestInputs (boolean isMultiParam) { + // store closest inputs with input it's closest too (for multi param) + HashMap> closestInputs = new HashMap>(); + int lowestDistance = 0; + boolean firstIteration = true; + + + if (isMultiParam) { + List originals = targetTest.getOriginalParameters(); + + for (String s: originals) { + Iterator it = editDistances.entrySet().iterator(); + // reset first iteration to true for each original parameter + firstIteration = true; + + while (it.hasNext()) { + Map.Entry pair = (Map.Entry) it.next(); + int distanceValue = (int) pair.getValue(); + String[] origAndGen = pair.getKey(); + + if (s.equals(origAndGen[0])) { + if (firstIteration && distanceValue > 0) { + lowestDistance = distanceValue; + List inputsList = new ArrayList<>(); + // add to closest inputs if edit distance between 1 and 3 + if (lowestDistance > 0 && lowestDistance <=3) { + inputsList.add(origAndGen[1]); + closestInputs.put(s, inputsList); + } else { + closestInputs.put(s, inputsList); + } + firstIteration = false; + } else { + if ((distanceValue <= lowestDistance && distanceValue > 0) || (distanceValue > 0 && distanceValue <= 3)) { + lowestDistance = distanceValue; + List closest = closestInputs.get(s); + closest.add(origAndGen[1]); + closestInputs.put(s, closest); + } + } + } + } + } + + } else { + Iterator it = editDistances.entrySet().iterator(); + String original = targetTest.getOriginalParameter(); + + while(it.hasNext()) { + Map.Entry pair = (Map.Entry) it.next(); + int distanceValue = (int) pair.getValue(); + String[] origAndGen = pair.getKey(); + + if (firstIteration) { + lowestDistance = distanceValue; + List inputsList = new ArrayList<>(); + + // add to closest inputs if edit distance between 1 and 3 + if (lowestDistance > 0 && lowestDistance <=3) { + inputsList.add(origAndGen[1]); + closestInputs.put(original, inputsList); + } else { + closestInputs.put(original, inputsList); + } + firstIteration = false; + } else { + if (distanceValue <= lowestDistance && distanceValue > 0) { + lowestDistance = distanceValue; + List closest = closestInputs.get(original); + closest.add(origAndGen[1]); + closestInputs.put(original, closest); + } + } + + } + + } + + return closestInputs; + } + + private void removeQuotations(HashMap closestInputs) { + for (int i=0; i used = new ArrayList(); + + for (String test : passingTests) { + + for (Object input : executedInputs) { + writeTest(bwPassing, used, test, input); + } + } + + for (String test : failingTests) { + for (Object input : executedInputs) { + writeTest(bwFailing, used, test, input); + } + } + + + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bwPassing != null) + bwPassing.close(); + + if (bwFailing != null) + bwFailing.close(); + + if (fwPassing != null) + fwPassing.close(); + + if (fwFailing != null) { + fwFailing.close(); + } + + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + } + + private void writeTest(BufferedWriter bwPassing, List used, String test, Object input) throws IOException { + String subTest = test.substring(test.lastIndexOf(targetTest.getTargetMethod())); + String testInput = input.toString(); + String params = subTest.substring(subTest.lastIndexOf("(")); + + // find executed input that matches current passing test + if (params.contains(testInput) && used.contains(subTest) == false && used.contains(input) == false) { + used.add(subTest); + used.add(input); + + // bold testInput within params + String formattedParams = params.substring(0, params.indexOf(testInput)) + "" + + params.substring(params.indexOf(testInput), params.indexOf(testInput)+testInput.length()) + "" + + params.substring(params.indexOf(testInput)+testInput.length(), params.length()); + + System.out.println(formattedParams); + + // re-construct test + String formattedTest = test.substring(0, test.indexOf(params)) + formattedParams; + + System.out.println(formattedTest); + + bwPassing.write("P:" + formattedTest); + bwPassing.write("\n"); + } + } + + + + private void savePage(IWorkbenchPage page) { + + for (IEditorPart dirtyPage: page.getDirtyEditors()) { + dirtyPage.doSave(null); + System.out.println("Editor saved!"); + } + + } + + private String replaceVariableDeclaration(ASTRewrite rewrite, Object newParam, String type) + throws BadLocationException, JavaModelException { + + // Old variable fragments + VariableDeclarationStatement oldVarDec = (VariableDeclarationStatement) currentParam; + VariableDeclarationFragment frag = (VariableDeclarationFragment) oldVarDec.fragments().get(0); + SimpleName varName = frag.getName(); + + // new variable fragments + String newSource = ""; + VariableDeclarationFragment newVarFrag = ast.newVariableDeclarationFragment(); + SimpleName newVarName = ast.newSimpleName(varName.getIdentifier()); + newVarFrag.setName(newVarName); + + targetTest.setNewParameter(newParam.toString()); + + // new variable declaration statement based on fragment + // TODO: is this in the wrong location? + VariableDeclarationStatement newVarDec = ast.newVariableDeclarationStatement(newVarFrag); + + // determine which type of parameter passed in + if (newParam instanceof BooleanLiteral) { + // already has value if boolean + BooleanLiteral param = (BooleanLiteral)newParam; + newVarFrag.setInitializer(param); + + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("boolean"))); + + } else if (newParam instanceof StringLiteral) { + StringLiteral param = (StringLiteral)newParam; + if (this.input == null) { + // TODO should this be actual null value or the string "null"? + param.setLiteralValue("null"); + + } else { + param.setLiteralValue(this.input.toString()); + } + + newVarFrag.setInitializer(param); + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("String"))); + + } else if (newParam instanceof CharacterLiteral) { + CharacterLiteral param = (CharacterLiteral)newParam; + if (this.input == null) { + // TODO: figure out how to do this (if possible) + } else { + param.setCharValue((char)this.input); + } + + newVarFrag.setInitializer(param); + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("char"))); + + } else if (newParam instanceof NumberLiteral) { + + if (this.input == null) { + // TODO handle if null + } else { + NumberLiteral param = (NumberLiteral)newParam; + + if (this.input == null) { + // TODO handle if null + } else { + param.setToken(this.input.toString()); + } + + newVarFrag.setInitializer(param); + + if (type.equals("int")) { + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("int"))); + + } else if (type.equals("float")) { + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("float"))); + + } else if (type.equals("double")) { + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("double"))); + + } else if (type.equals("short")) { + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("short"))); + + } else if (type.equals("long")) { + newVarDec.setType(ast.newSimpleType(ast.newSimpleName("long"))); + + } + + } + + } + + rewrite.replace(oldVarDec, newVarDec, null); + + TextEdit edits = rewrite.rewriteAST(testDocument, JavaCore.getOptions()); + edits.apply(testDocument); + + newSource = testDocument.get(); + icu.getBuffer().setContents(newSource); + + return newSource; + } + + + private void d4jCompile(File executorDirectory) throws ExecuteException, IOException { + CommandLine d4j_compile_cmdLine = new CommandLine("/Users/bjohnson/Documents/Research_2017-2018/defects4j/framework/bin/defects4j"); + d4j_compile_cmdLine.addArgument("compile"); + + DefaultExecutor d4j_compile_executor = new DefaultExecutor(); + d4j_compile_executor.setWorkingDirectory(executorDirectory); + + System.out.println(d4j_compile_cmdLine.toString()); + + try { + d4j_compile_executor.execute(d4j_compile_cmdLine); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + + private void d4jTest(File executorDirectory) throws ExecuteException, IOException { + // Store output to know if test passed or failed + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream); + + CommandLine d4j_test_cmdLine = new CommandLine("/Users/bjohnson/Documents/Research_2017-2018/defects4j/framework/bin/defects4j"); + d4j_test_cmdLine.addArgument("test"); + d4j_test_cmdLine.addArgument("-t"); + + // get package name + String path = testFile.getFullPath().toString(); + String fullPackage = path.replaceAll("\\/", "."); + String targetPackage = fullPackage.substring(fullPackage.indexOf("org"), fullPackage.length()-5); + String singleTest = targetPackage + "::" + targetTest.getTestMethod(); + + d4j_test_cmdLine.addArgument(singleTest); + + DefaultExecutor d4j_test_executor = new DefaultExecutor(); + d4j_test_executor.setWorkingDirectory(executorDirectory); + d4j_test_executor.setStreamHandler(streamHandler); + + System.out.println(d4j_test_cmdLine.toString()); + + try { + d4j_test_executor.execute(d4j_test_cmdLine); + + } catch (IOException e) { + e.printStackTrace(); + } + + System.out.println(outputStream.toString()); + + // Store test in appropriate list + if (outputStream.toString().contains("Failing tests: 1") && failingTests.size() < 3) { + + failingTests.add(targetTest.getFullTest()); + + } else { +// System.out.println(targetTest.getFullTest()); + + passingTests.add(targetTest.getFullTest()); + + } + + } + + + private void writeOriginalTestToFile(String filename) { + BufferedWriter bw = null; + FileWriter fw = null; + + try { + fw = new FileWriter(filename); + bw = new BufferedWriter(fw); + + bw.write("O: " + targetTest.getOriginalTest()); + bw.write("\n"); + + + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bw != null) + bw.close(); + + if (fw != null) + fw.close(); + + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + } + + + private void runFuzzers(String cmdLineArg, boolean originalInput, String fileID) throws ExecuteException, IOException { + DefaultExecutor py_executor = new DefaultExecutor(); + py_executor.setWorkingDirectory(new File(workingDirectory.getPath() + "/fuzzers/")); + + CommandLine py_fuzzer = new CommandLine("./fuzz.sh"); +// py_lower_cmdLine.addArgument("fuzz-lowercase.py"); + py_fuzzer.addArgument(cmdLineArg); +// py_lower_cmdLine.addArgument(">"); + + // pipe output to files for parsing + if (originalInput) { + py_fuzzer.addArgument("fuzzer_results_original_" + fileID + ".txt"); + } else { + py_fuzzer.addArgument("fuzzer_results_generated_" + fileID +".txt"); + } + + py_executor.execute(py_fuzzer); + System.out.println("Success!"); + } + + private void parseOtherMutations() throws FileNotFoundException, IOException { + File otherMutationsFile = new File("other-mutations.txt"); + FileReader otherFileReader = new FileReader(otherMutationsFile); + BufferedReader otherBR = new BufferedReader(otherFileReader); + + String otherLine; + + while ((otherLine = otherBR.readLine()) != null) { + if (otherLine.startsWith("\"") && otherLine.endsWith("\"")) { + String removeQuotes = otherLine.replace("\"", ""); + String removeSemicolon = removeQuotes.substring(0, removeQuotes.length()-1); + + System.out.println(removeSemicolon); + + fuzzedValues.add(removeSemicolon); + } else { + + fuzzedValues.add(otherLine); + } + } + + otherBR.close(); + } + + private void parseLengthMutations() throws FileNotFoundException, IOException { + File lengthMutationFile = new File("length-mutations.txt"); + FileReader lengthFileReader = new FileReader(lengthMutationFile); + BufferedReader lengthBR = new BufferedReader(lengthFileReader); + + String lengthLine; + + while ((lengthLine = lengthBR.readLine()) != null ) { + if (lengthLine.startsWith("\"") && lengthLine.endsWith("\"")) { + String removeQuotes = lengthLine.replace("\"", ""); + String removeSemicolon = removeQuotes.substring(0, removeQuotes.length()-1); + + System.out.println(removeSemicolon); + + fuzzedValues.add(removeSemicolon); + } else { + + fuzzedValues.add(lengthLine); + } + } + + lengthFileReader.close(); + } + + private void parseCaseMutations() throws FileNotFoundException, IOException { + File caseMutationFile = new File("case-mutations.txt"); + FileReader caseFileReader = new FileReader(caseMutationFile); + BufferedReader caseBR = new BufferedReader(caseFileReader); + + String caseLine; + + while ((caseLine = caseBR.readLine()) != null) { + if (caseLine.startsWith("\"") && caseLine.endsWith("\"") ) { + String removeQuotes = caseLine.replace("\"", ""); + String removeSemicolon = removeQuotes.substring(0, removeQuotes.length()-1); + + System.out.println(removeSemicolon); + + fuzzedValues.add(removeSemicolon); + } else { + + fuzzedValues.add(caseLine); + } + } + + caseFileReader.close(); + } + + private void getMethodParameters(String source, String targetMethod, String targetTestMethod, boolean first, int lineNo) { + TestMethodVisitor visitor; + if (first) { + visitor = new TestMethodVisitor(source.toCharArray(), targetMethod, targetTestMethod, true, lineNo); + } else { + visitor = new TestMethodVisitor(source.toCharArray(), targetMethod, targetTestMethod, false, lineNo); + } + + cu.accept(visitor); + + targetTest.setOriginalTest(visitor.getOriginalTest()); + + MethodInvocation testMethodInvoc = visitor.getFullMethod(); + + if (visitor.getTestStatements() == null) { + targetTest.setFullTest(visitor.getFullTest()); + } else { + targetTest.setFullTest(visitor.getTestStatements()); + } + + targetTest.setTestMethod(visitor.getTargetTestMethod()); + + // set up old and new parameters for modification + if (!visitor.getIsMultiParam()) { + if (visitor.getIsNotLiteral()) { + // if not hard coded string, get var frag with value + currentParam = visitor.getFragOfInterest(); + + } else { + currentParam = visitor.getParamOfInterest(); + } + + System.out.println("Current parameter = " + currentParam.toString()); + + // set original test parameter (if first go around) + if (first) { + String originalParam = currentParam.toString(); + // if String, make sure quotes aren't saved along with input (only value) + if (originalParam.contains("\"")) { + // TODO: for fragments, may need to do -2 to account for semi-colon at the end + originalParam = originalParam.substring(originalParam.indexOf("\"")+1, originalParam.length()-1); + } + + targetTest.setOriginalParameter(originalParam); + } + + } else { + System.out.println("Current set of parameters are:"); + for (Object param : visitor.getParamsOfInterst()) { + currentParams.add(param); + System.out.println(param.toString()); + // set original test parameters (if first go around) + if (first) { + String originalParam = param.toString(); + + if (originalParam.contains("\"")){ + originalParam = originalParam.substring(originalParam.indexOf("\""), originalParam.length()-1); + } + + targetTest.addOriginalParameter(originalParam); + } + } + } + } + + private void updateASTParser() { + parser = createParser(testDocument.get()); + + cu = (CompilationUnit) parser.createAST(null); + ast = cu.getAST(); + + if (ast.hasBindingsRecovery()) { + System.out.println("Binding activated."); + } + } + + private ASTParser createParser(String source) { + ASTParser parser = ASTParser.newParser(AST.JLS8); + parser.setResolveBindings(true); + parser.setKind(ASTParser.K_COMPILATION_UNIT); + + parser.setBindingsRecovery(true); + + Map options = JavaCore.getOptions(); +// JavaCore.setComplianceOptions(JavaCore.VERSION_1_6, options); + parser.setCompilerOptions(options); + + parser.setStatementsRecovery(true); + parser.setSource(source.toCharArray()); + + return parser; + } + + private ITextSelection getSelection(CompilationUnitEditor editor) { + ISelection selection = editor.getSelectionProvider() + .getSelection(); + return (ITextSelection) selection; + } + + private String getSelectedText(CompilationUnitEditor editor) { + return getSelection(editor).getText(); + } + + @Override + public void selectionChanged(IAction arg0, ISelection arg1) { + + } + + @Override + public void setActiveEditor(IAction arg0, IEditorPart arg1) { + + } + +} diff --git a/Holmes/src/org/holmes/plugin/nodevisitor/GeneratedTestVisitor.java b/Holmes/src/org/holmes/plugin/nodevisitor/GeneratedTestVisitor.java new file mode 100644 index 0000000..1efee8e --- /dev/null +++ b/Holmes/src/org/holmes/plugin/nodevisitor/GeneratedTestVisitor.java @@ -0,0 +1,334 @@ +package org.holmes.plugin.nodevisitor; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.BooleanLiteral; +import org.eclipse.jdt.core.dom.CastExpression; +import org.eclipse.jdt.core.dom.CharacterLiteral; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.NullLiteral; +import org.eclipse.jdt.core.dom.NumberLiteral; +import org.eclipse.jdt.core.dom.ParenthesizedExpression; +import org.eclipse.jdt.core.dom.PrefixExpression; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.Statement; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; + +public class GeneratedTestVisitor extends ASTVisitor { + + public char[] source; + + // method call of interest + public String targetMethod; + + // store generated inputs for single param method + public List newInputs; + // store generated inputs for multi parameter method + public List newMultiInputs; + + List declStatements; + HashMap assignments; + + public boolean notStringLiteral = false; + public boolean isMultiParam = false; + + // list of statements in test + String testStatements; + + // full test + String fullTest; + + public Object genParamOfInterest; + public List genParamsOfInterest; + + public GeneratedTestVisitor() { + + } + + public GeneratedTestVisitor(char[] source, String targetMethod) { + this.source = source; + this.targetMethod = targetMethod; + newInputs = new ArrayList(); + newMultiInputs = new ArrayList<>(); + declStatements = new ArrayList(); + assignments = new HashMap(); + genParamsOfInterest = new ArrayList<>(); + } + + public boolean visit (VariableDeclarationStatement node) { + declStatements.add(node); + + return true; + } + + public boolean visit (Assignment node) { + MethodDeclaration methDec = getMethodDeclaration(node); + + assignments.put(methDec.getName().toString(), node); + + return true; + } + + public boolean visit (MethodInvocation node) { + + String methInv = node.getName().getFullyQualifiedName(); + + MethodDeclaration methDec = getMethodDeclaration(node); + String methodName = methDec.getName().toString(); + + if (methInv.equals(targetMethod)) { +// System.out.println("Test calling target method --> " + findSourceForNode(node)); + + List params = node.arguments(); + + if (params.size() == 1) { + setSingleParamValues(node, methDec, params); + } else { + isMultiParam = true; + setMultiParamValues(node, methDec, params); + } + + + } + + return true; + } + + private void setMultiParamValues(MethodInvocation node, MethodDeclaration methDec, List params) { + Object fullTest = findFullTest(node); + + if (fullTest != null) { + this.fullTest = fullTest.toString(); + } + // get parent (test) method that calls target method + MethodDeclaration targetMethodDeclaration = getMethodDeclaration(node); + String targetMethodDeclarationName = targetMethodDeclaration.getName().toString(); + + List genParamsOfInterest = new ArrayList<>(); + + for (Object param : params) { + if (param instanceof SimpleName) { + SimpleName nameGenParam = (SimpleName) param; +// System.out.println(nameGenParam.getParent().toString()); + + // first check assignments + Iterator it = assignments.entrySet().iterator(); + + while (it.hasNext()) { + Map.Entry pair = (Map.Entry) it.next(); + String currentMethDeclName = (String) pair.getKey(); + Assignment assignment = (Assignment) pair.getValue(); + + // check if parent method of assignment same as target method invocation + if (currentMethDeclName.equals(targetMethodDeclarationName)) { + // add assignment to list of generated params for this method call + genParamsOfInterest.add(assignment); + } + } + + // check if size of genParams matches params (to see if need to even go through declarations) + if (genParamsOfInterest.size() < params.size()) { + if (declStatements != null) { + for (VariableDeclarationStatement stmt : declStatements) { + MethodDeclaration currentMethDecl = getMethodDeclaration(stmt); + String currentMethDeclName = currentMethDecl.getName().toString(); + String varName = ""; + + // parent method of fragment is same as parent method of invocation (in same method) + if (currentMethDeclName.equals(targetMethodDeclarationName)) { + for (Object frag : stmt.fragments()) { + VariableDeclarationFragment varFrag = (VariableDeclarationFragment) frag; + varName = varFrag.getName().toString(); + + if (varName.equals(nameGenParam.toString())) { + genParamsOfInterest.add(stmt); + } + } + + } + } + } + } + + } else { + if (param instanceof StringLiteral || param instanceof CharacterLiteral) { + genParamsOfInterest.add(param); + } else if (param instanceof CastExpression) { + // TODO this may not properly handle cast to object rather than primitive + CastExpression genParam = (CastExpression) param; + + genParamsOfInterest.add(genParam); + + } else if (param instanceof PrefixExpression) { + PrefixExpression genParam = (PrefixExpression) param; + + genParamsOfInterest.add(genParam); + + } else if (param instanceof NumberLiteral) { + NumberLiteral genParam = (NumberLiteral) param; + + genParamsOfInterest.add(genParam); + } else if (param instanceof BooleanLiteral) { + BooleanLiteral genParam = (BooleanLiteral) param; + + genParamsOfInterest.add(genParam); + } else if (param instanceof NullLiteral) { + NullLiteral genParam = (NullLiteral) param; + + genParamsOfInterest.add(genParam); + } else if (param instanceof ParenthesizedExpression) { + ParenthesizedExpression genParam = (ParenthesizedExpression) param; + + genParamsOfInterest.add(genParam); + } + } + } + newMultiInputs.add(genParamsOfInterest); + + + } + + private void setSingleParamValues(MethodInvocation node, MethodDeclaration methDec, List params) { + ExpressionStatement fullTest = (findFullTest(node)); + if (fullTest != null) { + this.fullTest = fullTest.toString(); + } + + // get parent (test) method that calls target method + MethodDeclaration targetMethodDeclaration = getMethodDeclaration(node); + String targetMethodDeclarationName = targetMethodDeclaration.getName().toString(); + + Object param = params.get(0); + + if (param instanceof SimpleName) { + + SimpleName nameGenParam = (SimpleName) param; +// System.out.println(nameGenParam.getParent().toString()); + + // first check assignments + Iterator it = assignments.entrySet().iterator(); + + while (it.hasNext()) { + Map.Entry pair = (Map.Entry) it.next(); + String currentMethDeclName = (String) pair.getKey(); + Assignment assignment = (Assignment) pair.getValue(); + + // check if parent method of assignment same as target method invocation + if (currentMethDeclName.equals(targetMethodDeclarationName)) { + // add assignment to list of generated params for this method call + genParamOfInterest = assignment; + } + } + + // check if size of genParams matches params (to see if need to even go through declarations) + if (genParamOfInterest == null) { + if (declStatements != null) { + for (VariableDeclarationStatement stmt : declStatements) { + MethodDeclaration currentMethDecl = getMethodDeclaration(stmt); + String currentMethDeclName = currentMethDecl.getName().toString(); + String varName = ""; + + // parent method of fragment is same as parent method of invocation (in same method) + if (currentMethDeclName.equals(targetMethodDeclarationName)) { + for (Object frag : stmt.fragments()) { + VariableDeclarationFragment varFrag = (VariableDeclarationFragment) frag; + varName = varFrag.getName().toString(); + + if (varName.equals(nameGenParam.toString())) { + genParamOfInterest = stmt; + } + } + + } + } + } + } + } else { + + if (param instanceof StringLiteral || param instanceof CharacterLiteral) { + genParamOfInterest = param; + + } else if (param instanceof NumberLiteral) { + // numbers + NumberLiteral genNumParam = (NumberLiteral) param; + + genParamOfInterest = genNumParam; + + } else if (param instanceof BooleanLiteral) { + // boolean + BooleanLiteral genBoolParam = (BooleanLiteral) param; + + genParamOfInterest = genBoolParam; + + } else if (param instanceof NullLiteral) { + NullLiteral genNullParam = (NullLiteral) param; + + genParamOfInterest = genNullParam; + } + + + newInputs.add(genParamOfInterest); + } + } + + public boolean getIsMultiParam() { + return isMultiParam; + } + + public List getGeneratedSingleParamInputs() { + return newInputs; + } + + public List getGeneratedMultiParamInputs(){ + return newMultiInputs; + } + + public Object getGenParamOfInterest() { + return genParamOfInterest; + } + + public List getGenParamsOfInterest(){ + return genParamsOfInterest; + } + + private ExpressionStatement findFullTest(ASTNode node) { + if (node.getParent() != null) { + return node instanceof ExpressionStatement ? (ExpressionStatement)node : findFullTest(node.getParent()); + } + + return null; + } + + protected String findSourceForNode(ASTNode node) { + try { + return new String(Arrays.copyOfRange(source, node.getStartPosition(), node.getStartPosition() + node.getLength())); + } + catch (Exception e) { + System.err.println("OMG PROBLEM MAKING SOURCE FOR "+node); + return ""; + } + } + + private MethodDeclaration getMethodDeclaration(ASTNode node) { + if (node.getParent() != null){ + return node instanceof MethodDeclaration ? (MethodDeclaration)node : getMethodDeclaration(node.getParent()); + } + + return null; + } + +} diff --git a/Holmes/src/org/holmes/plugin/nodevisitor/TestMethodVisitor.java b/Holmes/src/org/holmes/plugin/nodevisitor/TestMethodVisitor.java new file mode 100644 index 0000000..d4145ae --- /dev/null +++ b/Holmes/src/org/holmes/plugin/nodevisitor/TestMethodVisitor.java @@ -0,0 +1,368 @@ +package org.holmes.plugin.nodevisitor; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.BooleanLiteral; +import org.eclipse.jdt.core.dom.CharacterLiteral; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.MethodInvocation; +import org.eclipse.jdt.core.dom.NullLiteral; +import org.eclipse.jdt.core.dom.NumberLiteral; +import org.eclipse.jdt.core.dom.PrefixExpression; +import org.eclipse.jdt.core.dom.PrefixExpression.Operator; +import org.eclipse.jdt.core.dom.PrimitiveType; +import org.eclipse.jdt.core.dom.PrimitiveType.Code; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.Statement; +import org.eclipse.jdt.core.dom.StringLiteral; +import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.VariableDeclaration; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; + +public class TestMethodVisitor extends ASTVisitor { + + public char[] source; + + public boolean originalTest; + + // method call of interest + public MethodInvocation methOfInterest; + public Object paramOfInterest; + public List paramsOfInterest; + public Assignment assignOfInterest; + public VariableDeclarationFragment fragOfInterest; + + // test method to find + public String targetTestMethod; + // method call of interest in target test method + public String targetMethod; + // line number of method call of interest + public int lineNo; + + // full test statement (for tool output) + public String fullTest; + public String originalFullTest; + + public boolean notLiteral = false; + public boolean multiParam = false; + + // list of variables declared (in case needed to find value for test input) + public List declFragments; + // list of values assigned to variables (in case needed to find value for test input) + public List assignments; + + // list of statements in test + String testStatements; + + public TestMethodVisitor() { + + } + + public TestMethodVisitor (char[] source, String targetMethod, String targetTestMethod, boolean original, int lineNo) { + this.source = source; + this.targetTestMethod = targetTestMethod; + this.targetMethod = targetMethod; + this.lineNo = lineNo; + declFragments = new ArrayList<>(); + assignments = new ArrayList<>(); + originalTest = original; + paramsOfInterest = new ArrayList<>(); + } + + /* + * (non-Javadoc) + * + * This method visits all the variable declarations and saves them all. + * + * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.VariableDeclarationStatement) + */ + public boolean visit (VariableDeclarationFragment node) { + declFragments.add(node); + + return true; + } + + /* + * (non-Javadoc) + * + * This method collects all assignments in the target test method + * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Assignment) + */ + public boolean visit (Assignment node) { + + MethodDeclaration methDec = getMethodDeclaration(node); + + if (methDec.getName().toString().equals(targetTestMethod)) { + assignments.add(node); + } + + return true; + } + + public boolean visit (MethodInvocation node) { + + String methInv = node.getName().getFullyQualifiedName(); + + MethodDeclaration methDec = getMethodDeclaration(node); + String methodName = methDec.getName().toString(); + + if (methDec != null) { + // this makes sure we're in the scope of right test method (which means it works for local but not global variables + if (methInv.equals(targetMethod) && methodName.equals(targetTestMethod)) { + + methOfInterest = node; + int lineNo = ((CompilationUnit) node.getRoot()).getLineNumber(node.getStartPosition()); + + if (node.arguments().size() == 1) { + if (lineNo == this.lineNo) { + setSingleParamValues(node, methDec); + } + } else { + multiParam = true; + + if (lineNo == this.lineNo) { + setMultiParamValues(node, methDec); + } + + } + + } + + } + + + return true; + } + + private void setMultiParamValues(MethodInvocation node, MethodDeclaration methDec) { + for (Object arg : node.arguments()) { + if (arg instanceof SimpleName) { + SimpleName nameParamOfInterest = (SimpleName) arg; + + for (int i=0; i < assignments.size(); i++) { + + if (i+1 == assignments.size()-1) { + Assignment nextAssign = assignments.get(i+1); + String nextAssignVariable = nextAssign.getLeftHandSide().toString(); + + if (nextAssignVariable.equals(nameParamOfInterest.toString())) { + if (originalTest) { + originalFullTest = findFullTest(node).toString(); + } + fullTest = findFullTest(node).toString(); + // add assignment to list of parameters + paramsOfInterest.add(nextAssign); + } + } + } + + if (assignOfInterest == null) { + if (declFragments != null) { + for (VariableDeclarationFragment frag: declFragments) { + if (frag.getName().toString().equals(nameParamOfInterest.toString())) { + // if not hard coded string, get the variable declaration with value + paramsOfInterest.add(frag); + } + } + } + } + } else { + if (arg instanceof StringLiteral || arg instanceof CharacterLiteral) { + paramsOfInterest.add(arg); + } else if (arg instanceof PrefixExpression) { + PrefixExpression param = (PrefixExpression) arg; + + paramsOfInterest.add(param); + } else if (arg instanceof NumberLiteral) { + NumberLiteral param = (NumberLiteral) arg; + + paramsOfInterest.add(param); + } else if (arg instanceof BooleanLiteral) { + BooleanLiteral param = (BooleanLiteral) arg; + } + } + } + + if (originalTest) { + originalFullTest = findFullTest(node).toString(); + } + + fullTest = findFullTest(node).toString(); + + StringBuffer sb = new StringBuffer(); + + for (Object param : paramsOfInterest) { + sb.append(param.toString()); + sb.append("\n"); + } + + sb.append(fullTest); + + testStatements = sb.toString(); + + } + + private void setSingleParamValues(MethodInvocation node, MethodDeclaration methDec) { + if (node.arguments().get(0) instanceof SimpleName) { + notLiteral = true; + SimpleName nameParamOfInterest = (SimpleName) node.arguments().get(0); + + for (int i=0; i < assignments.size(); i++) { +// Assignment assign = assignments.get(i); +// int assignLineNo = ((CompilationUnit) assign.getRoot()).getLineNumber(assign.getStartPosition()); + + if (i+1 == assignments.size()-1) { + Assignment nextAssign = assignments.get(i+1); + + String nextAssignVariable = nextAssign.getLeftHandSide().toString(); + if (nextAssignVariable.equals(nameParamOfInterest.toString())) { + if (originalTest) { + originalFullTest = findFullTest(node).toString(); + } + + fullTest = findFullTest(node).toString(); + assignOfInterest = nextAssign; + testStatements = assignOfInterest + "\n" + fullTest; + } + } + } + + if (assignOfInterest == null) { + if (declFragments != null) { + for (VariableDeclarationFragment frag: declFragments) { + if (frag.getName().toString().equals(nameParamOfInterest.toString())) { + if (originalTest) { + originalFullTest = findFullTest(node).toString(); + } + + fullTest = findFullTest(node).toString(); + fragOfInterest = frag; + testStatements = fragOfInterest + "\n" + fullTest; + } + } + } + } + + } else { + // if hardcoded value, get just gather test statement + ExpressionStatement fullTest = findFullTest(node); + + if (fullTest != null) { + if (originalTest) { + originalFullTest = fullTest.toString(); + } + + this.fullTest = fullTest.toString(); + } + + if (node.arguments().get(0) instanceof StringLiteral || node.arguments().get(0) instanceof CharacterLiteral) { + paramOfInterest = node.arguments().get(0); + + } else if (node.arguments().get(0) instanceof PrefixExpression) { + // number with a sign + PrefixExpression param = (PrefixExpression) node.arguments().get(0); + + paramOfInterest = param; + + } else if (node.arguments().get(0) instanceof NumberLiteral) { + // handle numbers + NumberLiteral numParam = (NumberLiteral) node.arguments().get(0); + + paramOfInterest = numParam; + + } else if (node.arguments().get(0) instanceof BooleanLiteral ) { + BooleanLiteral boolParam = (BooleanLiteral) node.arguments().get(0); + + paramOfInterest = boolParam.booleanValue(); + } +// else if (node.arguments().get(0) instanceof NullLiteral) { +// NullLiteral nullParam = (NullLiteral) node.arguments().get(0); +// +// paramOfInterest = null; +// } + + } + } + + private ExpressionStatement findFullTest(ASTNode node) { + if (node.getParent() != null) { + return node instanceof ExpressionStatement ? (ExpressionStatement)node : findFullTest(node.getParent()); + } + + return null; + } + + public boolean getIsNotLiteral() { + return notLiteral; + } + + public boolean getIsMultiParam() { + return multiParam; + } + + public String getFullTest() { + return fullTest; + } + + public String getOriginalTest() { + return originalFullTest; + } + + public String getTestStatements() { + return testStatements; + } + + public Object getParamOfInterest() { + return paramOfInterest; + } + + public List getParamsOfInterst(){ + return paramsOfInterest; + } + + public VariableDeclarationFragment getFragOfInterest() { + return fragOfInterest; + } + + public MethodInvocation getFullMethod() { + return methOfInterest; + } + + public String getTargetTestMethod() { + return targetTestMethod; + } + + public String getTargetMethod() { + return targetMethod; + } + + protected String findSourceForNode(ASTNode node) { + try { + return new String(Arrays.copyOfRange(source, node.getStartPosition(), node.getStartPosition() + node.getLength())); + } + catch (Exception e) { + System.err.println("OMG PROBLEM MAKING SOURCE FOR "+node); + return ""; + } + } + + private MethodDeclaration getMethodDeclaration(ASTNode node) { + if (node.getParent() != null){ + return node instanceof MethodDeclaration ? (MethodDeclaration)node : getMethodDeclaration(node.getParent()); + } + + return null; + } + +} diff --git a/Holmes/src/org/holmes/plugin/util/Test.java b/Holmes/src/org/holmes/plugin/util/Test.java new file mode 100644 index 0000000..4601507 --- /dev/null +++ b/Holmes/src/org/holmes/plugin/util/Test.java @@ -0,0 +1,108 @@ +package org.holmes.plugin.util; + +import java.util.ArrayList; +import java.util.List; + +public class Test { + + String filename; + String originalParameter; + List originalParameters; + String newParameter; + String testMethod; + String targetMethod; + String originalTest; + String fullTest; + String projectName; + boolean passed; + + public Test(String fname) { + filename = fname; + originalParameters = new ArrayList<>(); + } + + public Test(String fname, String param, String test) { + filename = fname; + originalParameter = param; + fullTest = test; + originalParameters = new ArrayList(); + } + + public void setPassed(boolean passed) { + this.passed = passed; + } + + public void setOriginalParameter(String param) { + originalParameter = param; + } + + public void addOriginalParameter(String param) { + originalParameters.add(param); + } + + public void setOriginalTest(String test) { + originalTest = test; + } + + public void setNewParameter(String param) { + newParameter = param; + + } + + public void setTestMethod(String method) { + testMethod = method; + } + + public void setTargetMethod(String method) { + targetMethod = method; + } + + public String getTargetMethod(){ + return targetMethod; + } + + public void setFullTest(String test) { + fullTest = test; + } + + public void setProjectName(String name) { + projectName = name; + } + + public boolean getPassed() { + return passed; + } + + public String getOriginalParameter() { + return originalParameter; + } + + public List getOriginalParameters(){ + return originalParameters; + } + + public String getOriginalTest() { + return originalTest; + } + + public String getNewParameter() { + return newParameter; + } + + public String getFullTest() { + return fullTest; + } + + public String getTestMethod() { + return testMethod; + } + + public String getFilename() { + return filename; + } + + public String getProjectName() { + return projectName; + } + +} diff --git a/Holmes/src/org/holmes/plugin/util/Util.java b/Holmes/src/org/holmes/plugin/util/Util.java new file mode 100644 index 0000000..1f93da0 --- /dev/null +++ b/Holmes/src/org/holmes/plugin/util/Util.java @@ -0,0 +1,12 @@ +package org.holmes.plugin.util; + +import org.junit.runner.Result; + +public class Util { + + public static void printResult (Result result) { + System.out.printf("Tests ran: %s, Failed: %s%n", + result.getRunCount(), result.getFailureCount()); + } + +} \ No newline at end of file diff --git a/Holmes/src/org/holmes/plugin/views/HolmesView.java b/Holmes/src/org/holmes/plugin/views/HolmesView.java new file mode 100644 index 0000000..d5f46ad --- /dev/null +++ b/Holmes/src/org/holmes/plugin/views/HolmesView.java @@ -0,0 +1,460 @@ +package org.holmes.plugin.views; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +import org.eclipse.core.resources.IFile; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTError; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.browser.LocationEvent; +import org.eclipse.swt.browser.LocationListener; +import org.eclipse.swt.browser.OpenWindowListener; +import org.eclipse.swt.browser.WindowEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.browser.IWebBrowser; +import org.eclipse.ui.browser.IWorkbenchBrowserSupport; +import org.eclipse.ui.part.ViewPart; + +public class HolmesView extends ViewPart { + Composite composite; + + Browser browser; + String browserId; + volatile boolean allowUrlChange; + + String workingDirectory = "/Users/bjohnson/Documents/Research_2019-2020/causal_testing/Holmes/"; + + public static class ViewLabelProvider extends LabelProvider implements ITableLabelProvider { + public String getColumnText(Object obj, int index) { + return getText(obj); + } + public Image getColumnImage(Object obj, int index) { + return getImage(obj); + } + public Image getImage(Object obj) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT); + } + } + + public HolmesView() { + + } + + public void createPartControl(Composite parent) { + composite = parent; + + updateView(); + + } + + private void openBrowserInEditor(LocationEvent event) { + URL url; + try { + url = new URL(event.location); + } catch (MalformedURLException ignored) { + return; + } + IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport(); + try { + IWebBrowser newBrowser = support.createBrowser(browserId); + browserId = newBrowser.getId(); + newBrowser.openURL(url); + return; + } catch (PartInitException e) { + e.printStackTrace(); + } + } + + public void updateView() { + IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); + String projectName=""; + + if (editor != null) { + // TODO: get project + IEditorInput editorInput = editor.getEditorInput(); + IFile file = (IFile) editorInput.getAdapter(IFile.class); + + if (file != null) { + projectName = file.getProject().getName(); + } + + + } + + StringBuffer html = new StringBuffer(); + + html.append(""); + html.append(""); + html.append(""); + html.append(""); + html.append(""); + html.append(""); + html.append(""); + html.append(""); + + html.append("
"); + + + if (projectName.equals("Defect_0_Training")) { + showOutput(html, new File(workingDirectory + "/holmes-output-original.txt"), new File(workingDirectory + "/holmes-output-passing.txt"), new File(workingDirectory + "/holmes-output-failing.txt"), true); + } else { + if (projectName.equals("Defect_1")) { + showOutput(html, new File(workingDirectory + "/test_traces/Defect_1_original.txt"), new File(workingDirectory + "/test_traces/Defect_1_passing.txt"), + new File(workingDirectory + "/test_traces/Defect_1_failing.txt"), false); + } else if (projectName.equals("Defect_2")) { + showOutput(html, new File(workingDirectory + "/test_traces/Defect_2_original.txt"), new File(workingDirectory + "/test_traces/Defect_2_passing.txt"), + new File(workingDirectory + "/test_traces/Defect_2_failing.txt"), false); + } else if (projectName.equals("Defect_3")) { + showOutput(html, new File(workingDirectory + "/test_traces/Defect_3_original.txt"), new File(workingDirectory + "/test_traces/Defect_3_passing.txt"), + new File(workingDirectory + "/test_traces/Defect_3_failing.txt"), false); + } else if (projectName.equals("Defect_4")) { + showOutput(html, new File(workingDirectory + "/test_traces/Defect_4_original.txt"), new File(workingDirectory + "/test_traces/Defect_4_passing.txt"), + new File(workingDirectory + "/test_traces/Defect_4_failing.txt"), false); + } else if ((projectName.equals("Defect_5"))) { + showOutput(html, new File(workingDirectory + "/test_traces/Defect_5_original.txt"), new File(workingDirectory + "/test_traces/Defect_5_passing.txt"), + new File(workingDirectory + "test_traces/Defect_5_failing.txt"), false); + } else if (projectName.equals("Defect_6")) { + showOutput(html, new File(workingDirectory + "/test_traces/Defect_6_original.txt"), new File(workingDirectory + "/test_traces/Defect_6_passing.txt"), + new File(workingDirectory + "/test_traces/Defect_6_failing.txt"), false); + } + } + + } + + public void showOutput(StringBuffer html, File original, File passing, File failing, boolean training) { + + if (original.exists()) { + try { + BufferedReader br = new BufferedReader(new FileReader(original)); + + String line = null; + StringBuilder sb = new StringBuilder(); + + while ((line=br.readLine())!=null) { + sb.append(line); + sb.append("
"); + } + + String originalContents = sb.toString(); + + String oTest = ""; + if (training) { + oTest = originalContents.substring(originalContents.indexOf("O:")+2); + + } else { + oTest = originalContents.substring(originalContents.indexOf("O:")+2, originalContents.indexOf("T:")); + } + + + html.append("

Original Failing Test

"); + html.append(""+oTest+""); + + if (!training) { + String oTrace = originalContents.substring(originalContents.indexOf("T:")+2); + + html.append(""); + html.append("
\n"); + html.append(oTrace); + html.append("
"); + } + + html.append("
"); + + html.append(""); + + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + if (passing.length() == 0) { + html.append("" + "No similar passing tests found." +""); + } + + if (passing.exists() && passing.length() > 0) { + try { + BufferedReader br = new BufferedReader(new FileReader(passing)); + + String line = null; + StringBuffer sb = new StringBuffer(); + + while ((line=br.readLine()) != null) { + sb.append(line); + sb.append("
"); + } + + String passingTests = sb.toString(); + + html.append("

Passing Tests

"); + + if (training) { + String[] lines = sb.toString().split("P:"); + + for (String test: lines) { + html.append("" +test+""); + html.append("
"); + } + } else { + int lastIndexPassing = 0; + String findStr = "P:"; + int count = 0; + String test = ""; + String findStrT = "T:"; + int lastIndexTrace = 0; + String trace = ""; + + + while (lastIndexPassing != -1) { + lastIndexPassing = passingTests.indexOf(findStr, lastIndexPassing); + + lastIndexTrace = passingTests.indexOf(findStrT, lastIndexTrace); + + + + if (lastIndexPassing != -1) { + + test = passingTests.substring(lastIndexPassing+2, lastIndexTrace); + + html.append("" +test+""); + html.append("
"); + + lastIndexPassing += findStr.length(); + + int nextIndex = passingTests.indexOf(findStr, lastIndexPassing); + + // Process differently if only one passing test + if (nextIndex == -1) { + trace = passingTests.substring(lastIndexTrace+2, passingTests.length()); + } else { + trace = passingTests.substring(lastIndexTrace+2, nextIndex); + } + + + lastIndexTrace += findStrT.length(); + + html.append(""); + html.append("
\n"); + html.append(trace); + html.append("
"); + + + + html.append("
"); + + html.append(""); + + count ++; + } + } + + } + + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + html.append("

Additional Failing Tests

"); + + + if (failing.length() == 0) { + html.append("" + "No similar failing tests found." +""); + } + + if (failing.exists() && failing.length() > 0) { + try { + BufferedReader br = new BufferedReader(new FileReader(failing)); + + String line = null; + StringBuffer sb = new StringBuffer(); + + while ((line=br.readLine()) != null) { + sb.append(line); + sb.append("
"); + } + + String failingTests = sb.toString(); + + if (training) { + String[] lines = sb.toString().split("\\n"); + + for (String test: lines) { + test = test.substring(2, test.length()).trim(); + html.append("" +test+""); + html.append("
"); + + + + } + + } else { + int lastIndexFailing = 0; + String findStr = "F:"; + String findStrT = "T:"; + int lastIndexTrace = 0; + String test = ""; + String trace = ""; + int count = 5; + + while (lastIndexFailing != -1) { + lastIndexFailing = failingTests.indexOf(findStr, lastIndexFailing); + lastIndexTrace = failingTests.indexOf(findStrT, lastIndexTrace); + + + if (lastIndexFailing != -1) { + test = failingTests.substring(lastIndexFailing+2, lastIndexTrace); + + html.append("" +test+""); + html.append("
"); + + lastIndexFailing += test.length(); + + int nextIndex = failingTests.indexOf(findStr, lastIndexFailing); + + // Process differently if only one passing test + if (nextIndex == -1) { + trace = failingTests.substring(lastIndexTrace+2, failingTests.length()); + } else { + trace = failingTests.substring(lastIndexTrace+2, nextIndex); + } + + lastIndexTrace += findStrT.length(); + + html.append(""); + html.append("
\n"); + html.append(trace); + html.append("
"); + + + html.append("
"); + + html.append(""); + + count ++; + } + } + + } + + + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + GridData data = new GridData(GridData.FILL_BOTH); + data.grabExcessHorizontalSpace = true; + data.grabExcessVerticalSpace = true; + try { + browser = new Browser(composite, SWT.NO_BACKGROUND); + browser.setLayoutData(data); + browser.setBackground(composite.getBackground()); + browser.addOpenWindowListener(new OpenWindowListener() { + + @Override + public void open(WindowEvent event) { + event.required = true; // Cancel opening of new windows + } + }); + + browser.addLocationListener(new LocationListener() { + + @Override + public void changing(LocationEvent event) { + // fix for SWT code on Won32 platform: it uses "about:blank" + // before + // set any non-null url. We ignore this url + if (allowUrlChange || "about:blank".equals(event.location)) { + return; + } + // disallow changing of property view content + event.doit = false; + // for any external url clicked by user we should leave + // property view + openBrowserInEditor(event); + } + @Override + public void changed(LocationEvent event) { + // TODO Auto-generated method stub + + } + }); + + } catch (SWTError e) { + System.out.println("Could not create org.eclipse.swt.widgets.Composite.Browser"); + } + + String onReady = "$(document).ready(function() { \n $(\".livepreview\").livePreview(); \n});"; + boolean result = browser.execute(onReady); + + if (!result){ + System.out.println(onReady); + } + + browser.setText(html.toString()); + + } + + public Composite getParent() { + return composite; + } + public void setFocus() { + } +} diff --git a/README.md b/README.md index 30fd3e4..8bbbc77 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,2 @@ -# Causal Testing Artifact (ICSE 2020) - -This is the artifact for the paper *"Causal Testing: Understanding -Defects' Root Causes"*. This artifact replicates the user study setup -used to evaluate our technique, including the supplementary data -collection materials. - -## What is included in the artifact? - -Our artifact includes the following: - -1. A virtual machine file (CausalTesting_Artifact.ova) that contains -the user study setup and version of Holmes used. - -2. The form participants completed as they worked through -each defect in the user study (Cause-Identification-Form.pdf). - -3. The post-questionnaire participants filled out as a form of -debriefing following the study (Evaluation-Questionnaire.pdf) - -4. The demographic questionnaire used to gather information about our - participants background and experience (Demographic-Questionnaire.pdf). - -5. The script used to explain to participants what they would be doing - during the user study (User-Study-Script.pdf). - -## Where can I obtain the artifact components? - -All the above listed artifacts, with the exception of the virtual machine file, are located in this repository. - - -The **INSTALL.md** file provides details on how to locate, set up, and run the virutal machine. \ No newline at end of file +# Holmes +This repository contains the source code for the Holmes prototype used in the ICSE 2020 technical track paper "Causal Testing: Understanding Defects' Root Causes". diff --git a/CONTACT.md b/artifact_documentation/CONTACT.md similarity index 100% rename from CONTACT.md rename to artifact_documentation/CONTACT.md diff --git a/ICSE2020-paper.pdf b/artifact_documentation/ICSE2020-paper.pdf similarity index 100% rename from ICSE2020-paper.pdf rename to artifact_documentation/ICSE2020-paper.pdf diff --git a/INSTALL.md b/artifact_documentation/INSTALL.md similarity index 100% rename from INSTALL.md rename to artifact_documentation/INSTALL.md diff --git a/LICENSE.md b/artifact_documentation/LICENSE.md similarity index 100% rename from LICENSE.md rename to artifact_documentation/LICENSE.md diff --git a/artifact_documentation/README.md b/artifact_documentation/README.md new file mode 100644 index 0000000..30fd3e4 --- /dev/null +++ b/artifact_documentation/README.md @@ -0,0 +1,32 @@ +# Causal Testing Artifact (ICSE 2020) + +This is the artifact for the paper *"Causal Testing: Understanding +Defects' Root Causes"*. This artifact replicates the user study setup +used to evaluate our technique, including the supplementary data +collection materials. + +## What is included in the artifact? + +Our artifact includes the following: + +1. A virtual machine file (CausalTesting_Artifact.ova) that contains +the user study setup and version of Holmes used. + +2. The form participants completed as they worked through +each defect in the user study (Cause-Identification-Form.pdf). + +3. The post-questionnaire participants filled out as a form of +debriefing following the study (Evaluation-Questionnaire.pdf) + +4. The demographic questionnaire used to gather information about our + participants background and experience (Demographic-Questionnaire.pdf). + +5. The script used to explain to participants what they would be doing + during the user study (User-Study-Script.pdf). + +## Where can I obtain the artifact components? + +All the above listed artifacts, with the exception of the virtual machine file, are located in this repository. + + +The **INSTALL.md** file provides details on how to locate, set up, and run the virutal machine. \ No newline at end of file diff --git a/STATUS.md b/artifact_documentation/STATUS.md similarity index 100% rename from STATUS.md rename to artifact_documentation/STATUS.md diff --git a/fuzzers/AUTHORS.md b/fuzzers/AUTHORS.md new file mode 100755 index 0000000..7bab5b2 --- /dev/null +++ b/fuzzers/AUTHORS.md @@ -0,0 +1,14 @@ +## Credits + +#### Development Lead + +* Christoph Diehl cdiehl@mozilla.com + +#### Contributors + +* Michael Eddington +* Jesse Schwarzentruber +* Tyson Smith +* Christian Holler +* Mark Goodwin +* Aditya Murray diff --git a/fuzzers/LICENSE b/fuzzers/LICENSE new file mode 100755 index 0000000..5fa70aa --- /dev/null +++ b/fuzzers/LICENSE @@ -0,0 +1,375 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +``` +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ +``` + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/fuzzers/Peach/.project b/fuzzers/Peach/.project new file mode 100644 index 0000000..f5d004a --- /dev/null +++ b/fuzzers/Peach/.project @@ -0,0 +1,17 @@ + + + Peach + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/fuzzers/Peach/.pydevproject b/fuzzers/Peach/.pydevproject new file mode 100644 index 0000000..bfb3605 --- /dev/null +++ b/fuzzers/Peach/.pydevproject @@ -0,0 +1,19 @@ + + + +/${PROJECT_DIR_NAME} +/${PROJECT_DIR_NAME}/Agent +/${PROJECT_DIR_NAME}/Analyzers +/${PROJECT_DIR_NAME}/Engine +/${PROJECT_DIR_NAME}/Fixups +/${PROJECT_DIR_NAME}/Generators +/${PROJECT_DIR_NAME}/MutateStrategies +/${PROJECT_DIR_NAME}/Mutators +/${PROJECT_DIR_NAME}/Publishers +/${PROJECT_DIR_NAME}/Strategies +/${PROJECT_DIR_NAME}/Transformers +/${PROJECT_DIR_NAME}/Utilities + +python interpreter +Default + diff --git a/fuzzers/Peach/Agent/__init__.py b/fuzzers/Peach/Agent/__init__.py new file mode 100755 index 0000000..025bdf3 --- /dev/null +++ b/fuzzers/Peach/Agent/__init__.py @@ -0,0 +1,25 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import network +import debugger +import process +import test +import memory +import gui +import socketmon +import osx +import util + +__all__ = [ + "network", + "debugger", + "process", + "test", + "memory", + "socketmon", + "gui", + "osx", + "util", + "linux" +] diff --git a/fuzzers/Peach/Agent/__init__.pyc b/fuzzers/Peach/Agent/__init__.pyc new file mode 100644 index 0000000..80eed13 Binary files /dev/null and b/fuzzers/Peach/Agent/__init__.pyc differ diff --git a/fuzzers/Peach/Agent/b2g.py b/fuzzers/Peach/Agent/b2g.py new file mode 100755 index 0000000..431aaf5 --- /dev/null +++ b/fuzzers/Peach/Agent/b2g.py @@ -0,0 +1,318 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import sys +import time +import subprocess + +from Peach.Utilities import ADB, network +from Peach.agent import Monitor, MonitorDebug +try: + from marionette import Marionette +except ImportError: + sys.exit("Please install Marionette first.") +from Peach.Utilities.Gaia import gaia + + +class LaunchEmulator(Monitor): + """ + This monitor will start the B2G emulator and point the FirefoxApp to our publisher. + We also monitor the main B2G process and other crashes via DEBUG:I in adb logcat. + """ + + def __init__(self, args): + Monitor.__init__(self, args) + + if args.has_key("URL"): + self.publisherRequestPath = str(args["URL"]).replace("'''", "") + else: + raise Exception("No publisher URL provided.") + + if args.has_key("EmulatorScript"): + self.emulatorStartScript = str(args["EmulatorScript"]).replace("'''", "") + else: + raise Exception("No script provided to run the emulator.") + + if args.has_key("AppName"): + self.appName = str(args["AppName"]).replace("'''", "") + else: + self.appName = "browser" + + if args.has_key("ScriptTimeout"): + self.scriptTimeout = int(args["ScriptTimeout"]).replace("''", "") + else: + self.scriptTimeout = 600000 + + if args.has_key("PortADB"): + self.forwardedPortADB = int(args["PortADB"]) + else: + self.forwardedPortADB = 2828 + + self._name = "MarionetteEmulator" + self.monitoringProcessId = -1 + self.monitoredProcessName = "/system/b2g/b2g" + self.publisherHost = "10.0.2.2" + self.publisherPort = network.runHTTPDThread() + self.publisherURL = "http://%s:%d/%s" % (self.publisherHost, self.publisherPort, self.publisherRequestPath) + self.isEmulatorInitialized = False + self.isMonitorInitialized = False + self.adb = ADB.AccessDebugBridge(isEmulator=True) + self.emulatorProcess = None + self.crashSuccess = False + self.adbLogcat = self.adb.runCmd(["logcat"]) + self.debugLogData = str() + + def OnTestStarting(self): + if not self._IsRunning(): + self._StartProcess() + + def _StartProcess(self): + if not self.isEmulatorInitialized: + print("Starting Emulator ...") + self.emulatorProcess = subprocess.Popen( + [self.emulatorStartScript], cwd=os.path.dirname(self.emulatorStartScript), shell=True) + + # adb shell setprop net.dns1 10.0.2.3 + + self._isBootFinished() + self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName) + + print("Forwarding TCP port %d ..." % self.forwardedPortADB) + self.adb.command(["forward", "tcp:%d" % self.forwardedPortADB, "tcp:%d" % self.forwardedPortADB]) + + self.isEmulatorInitialized = True + + time.sleep(20) + + if self.crashSuccess: + print("Restarting %s ..." % self.monitoredProcessName) + self.adb.killProcess(self.monitoredProcessName, True) + time.sleep(40) + self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName) + self.crashSuccess = False + self.debugLogData = str() + self.adb.checkCmd(["logcat", "-c"]) + + print("Starting Marionette session ...") + marionette = Marionette('localhost', self.forwardedPortADB) + print(marionette.status()) + marionette.start_session() + marionette.set_script_timeout(self.scriptTimeout) + marionette.switch_to_frame() + + lock = gaia.LockScreen(marionette) + lock.unlock() + + apps = gaia.GaiaApps(marionette) + print(apps.runningApps()) + + print("Launching Browser application") + apps.launch(self.appName, switch_to_frame=True) + + print("Navigating to %s ..." % self.publisherURL) + marionette.execute_script("return window.wrappedJSObject.Browser.navigate('%s')" % self.publisherURL) + + self.isMonitorInitialized = True + + def _isBootFinished(self): + stdout = self.adbLogcat.stdout.readline() + while stdout: + if stdout.find("Get idle time: time since reset") >= 0: + return 0 + stdout = self.adbLogcat.stdout.readline() + return -1 + + def _getB2GPid(self): + pid = -1 + while pid == -1: + pid = self.adb.getPID(self.monitoredProcessName) + return pid + + def _detectPidChange(self): + processIds = self.adb.getPID(self.monitoredProcessName) + return processIds + + def _IsRunning(self): + if not self.isMonitorInitialized or self.crashSuccess: + return False + # We get might get the pid directly but we need to wait till the process + # is finished with loading for futher actions. See _isBootFinished() + pid = self._getB2GPid() + if self.monitoringProcessId != pid: + MonitorDebug(self._name, "pid of %s changed from %d to %d" % + (self.monitoredProcessName, self.monitoringProcessId, pid)) + return False + MonitorDebug(self._name, "pid of %s is %d" % (self.monitoredProcessName, pid)) + + debugLog = self.adb.runCmd(["logcat", "-d", "-s", "DEBUG:I", "-v", "threadtime"]) + self.debugLogData = debugLog.stdout.read() + if "Build fingerprint" in self.debugLogData: + return False + else: + debugLog.kill() + + return True + + def OnTestFinished(self): + if not self._IsRunning(): + self.crashSuccess = True + + def DetectedFault(self): + if self.crashSuccess: + return True + return False + + def GetMonitorData(self): + if not self.crashSuccess: + return {} + + id = self.monitoredProcessName.replace("/", "-").strip("-") + + bucket = { + "Bucket": id, + "process.txt": "Process %s (%d) aborted." % (id, self.monitoringProcessId), + "device.txt": self.adb.makeDeviceReport() + } + if self.debugLogData: + bucket["debugLogData.txt"] = self.debugLogData + + return bucket + + +class LaunchDevice(LaunchEmulator): + + def __init__(self, args): + Monitor.__init__(self, args) + + if args.has_key("URL"): + self.publisherRequestPath = str(args["URL"]).replace("'''", "") + else: + raise Exception("No publisher URL provided.") + + if args.has_key("AppName"): + self.appName = str(args["AppName"]).replace("'''", "") + else: + self.appName = "browser" + + if args.has_key("ScriptTimeout"): + self.scriptTimeout = int(args["ScriptTimeout"]).replace("''", "") + else: + self.scriptTimeout = 600000 + + if args.has_key("PublisherHost"): + self.publisherHost = str(args["PublisherHost"]).replace("''", "") + else: + self.publisherHost = "192.168.178.20" + + if args.has_key("PortADB"): + self.forwardedPortADB = int(args["PortADB"]) + else: + self.forwardedPortADB = 2828 + + self._name = "MarionetteDevice" + self.monitoringProcessId = -1 + self.monitoredProcessName = "b2g" + self.publisherPort = network.runHTTPDThread() + self.publisherURL = "http://%s:%d/%s" % (self.publisherHost, self.publisherPort, self.publisherRequestPath) + self.isDeviceInitialized = False + self.isMonitorInitialized = False + self.adb = ADB.AccessDebugBridge(isEmulator=False) + + self.crashSuccess = False + self.adbLogcat = self.adb.runCmd(["logcat"]) + self.debugLogData = str() + + def _StartProcess(self): + if not self.isDeviceInitialized: + print("Starting ...") + self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName) + print("Forwarding TCP port %d ..." % self.forwardedPortADB) + self.adb.command(["forward", "tcp:%d" % self.forwardedPortADB, "tcp:%d" % self.forwardedPortADB]) + self.isDeviceInitialized = True + + print("Sleeping ...") + time.sleep(20) + + if self.crashSuccess: + print("Restarting %s" % self.monitoredProcessName) + self.adb.killProcess(self.monitoredProcessName, True) + time.sleep(40) + self.monitoringProcessId = self.adb.getPID(self.monitoredProcessName) + self.crashSuccess = False + self.debugLogData = str() + self.adb.checkCmd(["logcat", "-c"]) + + print("Starting Marionette session") + marionette = Marionette('localhost', self.forwardedPortADB) + print(marionette.status()) + marionette.start_session() + marionette.set_script_timeout(self.scriptTimeout) + marionette.switch_to_frame() + + lock = gaia.LockScreen(marionette) + assert(lock.unlock()) + + apps = gaia.GaiaApps(marionette) + print(apps.runningApps()) + + print("Launching Browser application") + apps.launch(self.appName, switch_to_frame=True) + + print("Navigating to %s ..." % self.publisherURL) + marionette.execute_script("return window.wrappedJSObject.Browser.navigate('%s')" % self.publisherURL) + + self.isMonitorInitialized = True + + def _isBootFinished(self): + stdout = self.adbLogcat.stdout.readline() + while stdout: + if stdout.find("Get idle time: time since reset") >= 0: + return 0 + stdout = self.adbLogcat.stdout.readline() + return -1 + + def _getB2GPid(self): + pid = -1 + while pid == -1: + pid = self.adb.getPID(self.monitoredProcessName) + return pid + + def _detectPidChange(self): + processIds = self.adb.getPID(self.monitoredProcessName) + return processIds + + def _IsRunning(self): + if not self.isMonitorInitialized or self.crashSuccess: + return False + pid = self._getB2GPid() + if self.monitoringProcessId != pid: + MonitorDebug(self._name, "pid of %s changed from %d to %d" % + (self.monitoredProcessName, self.monitoringProcessId, pid)) + return False + MonitorDebug(self._name, "pid of %s is %d" % (self.monitoredProcessName, pid)) + + debugLog = self.adb.runCmd(["logcat", "-d", "-s", "DEBUG:I", "-v", "threadtime"]) + self.debugLogData = debugLog.stdout.read() + if "Build fingerprint" in self.debugLogData: + return False + else: + debugLog.kill() + + return True + + def GetMonitorData(self): + if not self.crashSuccess: + return {} + + id = self.monitoredProcessName.replace("/", "-").strip("-") + + bucket = { + "Bucket": id, + "process.txt": "Process %s (%d) aborted." % (id, self.monitoringProcessId), + "device.txt": self.adb.makeDeviceReport() + } + if self.debugLogData: + bucket["debugLogData.txt"] = self.debugLogData + + return bucket diff --git a/fuzzers/Peach/Agent/debugger.py b/fuzzers/Peach/Agent/debugger.py new file mode 100755 index 0000000..cfe51cf --- /dev/null +++ b/fuzzers/Peach/Agent/debugger.py @@ -0,0 +1,1070 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import gc +import re +import sys +import time +import struct +import signal +import pickle +import tempfile + +import psutil + +from Peach.agent import Monitor + +try: + import comtypes + from ctypes import * + from comtypes import HRESULT, COMError + from comtypes.client import CreateObject, GetEvents, PumpEvents + from comtypes.hresult import S_OK, E_FAIL, E_UNEXPECTED, E_INVALIDARG + from comtypes.automation import IID + import PyDbgEng + from comtypes.gen import DbgEng + import win32serviceutil + import win32service + import win32api, win32con, win32process, win32pdh + from multiprocessing import * + + + class _DbgEventHandler(PyDbgEng.IDebugOutputCallbacksSink, PyDbgEng.IDebugEventCallbacksSink): + + buff = '' + TakeStackTrace = True + + def LocateWinDbg(self): + """ + This method also exists in process.PageHeap! + """ + + try: + + hkey = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, "Software\\Microsoft\\DebuggingTools") + + except: + + # Lets try a few common places before failing. + pgPaths = [ + "c:\\", + os.environ["SystemDrive"] + "\\", + os.environ["ProgramFiles"], + ] + if "ProgramW6432" in os.environ: + pgPaths.append(os.environ["ProgramW6432"]) + if "ProgramFiles(x86)" in os.environ: + pgPaths.append(os.environ["ProgramFiles(x86)"]) + + dbgPaths = [ + "Debuggers", + "Debugger", + "Debugging Tools for Windows", + "Debugging Tools for Windows (x64)", + "Debugging Tools for Windows (x86)", + ] + + for p in pgPaths: + for d in dbgPaths: + testPath = os.path.join(p, d) + + if os.path.exists(testPath): + return testPath + + return None + + val, type = win32api.RegQueryValueEx(hkey, "WinDbg") + win32api.RegCloseKey(hkey) + return val + + def Output(self, this, Mask, Text): + self.buff += Text + + def LoadModule(self, unknown, imageFileHandle, baseOffset, moduleSize, moduleName, imageName, checkSum, + timeDateStamp=None): + if self.pid is None: + self.dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, + c_char_p("|."), + DbgEng.DEBUG_EXECUTE_ECHO) + + match = re.search(r"\.\s+\d+\s+id:\s+([0-9a-fA-F]+)\s+\w+\s+name:\s", self.buff) + if match is not None: + self.pid = int(match.group(1), 16) + + # Write out PID for main peach process + fd = open(self.TempfilePid, "wb+") + fd.write(str(self.pid)) + fd.close() + + def GetInterestMask(self): + return PyDbgEng.DbgEng.DEBUG_EVENT_EXCEPTION | PyDbgEng.DbgEng.DEBUG_FILTER_INITIAL_BREAKPOINT | \ + PyDbgEng.DbgEng.DEBUG_EVENT_EXIT_PROCESS | PyDbgEng.DbgEng.DEBUG_EVENT_LOAD_MODULE + + def ExitProcess(self, dbg, ExitCode): + print("_DbgEventHandler.ExitProcess: Target application has exitted") + self.quit.set() + return DEBUG_STATUS_NO_CHANGE + + def Exception(self, dbg, ExceptionCode, ExceptionFlags, ExceptionRecord, + ExceptionAddress, NumberParameters, ExceptionInformation0, ExceptionInformation1, + ExceptionInformation2, ExceptionInformation3, ExceptionInformation4, + ExceptionInformation5, ExceptionInformation6, ExceptionInformation7, + ExceptionInformation8, ExceptionInformation9, ExceptionInformation10, + ExceptionInformation11, ExceptionInformation12, ExceptionInformation13, + ExceptionInformation14, FirstChance): + + if self.IgnoreSecondChanceGardPage and ExceptionCode == 0x80000001: + return DbgEng.DEBUG_STATUS_NO_CHANGE + + # Only capture dangerouse first chance exceptions + if FirstChance: + if self.IgnoreFirstChanceGardPage and ExceptionCode == 0x80000001: + # Ignore, sometimes used as anti-debugger + # by Adobe Flash. + return DbgEng.DEBUG_STATUS_NO_CHANGE + + # Guard page or illegal op + elif ExceptionCode == 0x80000001 or ExceptionCode == 0xC000001D: + pass + elif ExceptionCode == 0xC0000005: + # is av on eip? + if ExceptionInformation0 == 0 and ExceptionInformation1 == ExceptionAddress: + pass + + # is write a/v? + elif ExceptionInformation0 == 1 and ExceptionInformation1 != 0: + pass + + # is DEP? + elif ExceptionInformation0 == 0: + pass + + else: + # Otherwise skip first chance + return DbgEng.DEBUG_STATUS_NO_CHANGE + else: + # otherwise skip first chance + return DbgEng.DEBUG_STATUS_NO_CHANGE + + if self.handlingFault.is_set() or self.handledFault.is_set(): + # We are already handling, so skip + #sys.stdout.write("_DbgEventHandler::Exception(): handlingFault set, skipping.\n") + return DbgEng.DEBUG_STATUS_BREAK + + try: + print("Exception: Found interesting exception") + + self.crashInfo = {} + self.handlingFault.set() + + ## 1. Output registers + print("Exception: 1. Output registers") + + dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, + c_char_p("r"), + DbgEng.DEBUG_EXECUTE_ECHO) + dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, + c_char_p("rF"), + DbgEng.DEBUG_EXECUTE_ECHO) + dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, + c_char_p("rX"), + DbgEng.DEBUG_EXECUTE_ECHO) + self.buff += "\n\n" + + ## 2. Ouput stack trace + if _DbgEventHandler.TakeStackTrace: + print("Exception: 2. Output stack trace") + + dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, + c_char_p("kb"), + DbgEng.DEBUG_EXECUTE_ECHO) + self.buff += "\n\n" + + else: + _DbgEventHandler.TakeStackTrace = True + self.buff += "\n[Peach] Error, stack trace failed.\n\n" + + ## 3. Write dump file + minidump = None + + ## 4. Bang-Exploitable + print("Exception: 3. Bang-Exploitable") + + handle = None + try: + p = None + if not (hasattr(sys, "frozen") and sys.frozen == "console_exe"): + p = __file__[:-24] + "tools\\bangexploitable\\" + if sys.version.find("AMD64") != -1: + p += "x64" + else: + p += "x86" + + else: + p = os.path.dirname(os.path.abspath(sys.executable)) + + dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, c_char_p(".load %s\\msec.dll" % p), + DbgEng.DEBUG_EXECUTE_ECHO) + dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, c_char_p("!exploitable -m"), + DbgEng.DEBUG_EXECUTE_ECHO) + dbg.idebug_control.Execute(DbgEng.DEBUG_OUTCTL_THIS_CLIENT, c_char_p("!msec.exploitable -m"), + DbgEng.DEBUG_EXECUTE_ECHO) + + except: + raise + + ## Now off to other things... + print("Exception: Building crashInfo") + + if minidump: + self.crashInfo = {'StackTrace.txt': self.buff.replace(chr(0x0a), "\r\n"), 'Dump.dmp': minidump} + else: + self.crashInfo = {'StackTrace.txt': self.buff.replace(chr(0x0a), "\r\n")} + + # Build bucket string + try: + bucketId = re.compile("DEFAULT_BUCKET_ID:\s+([A-Za-z_]+)").search(self.buff).group(1) + exceptionAddress = re.compile("ExceptionAddress: ([^\s\b]+)").search(self.buff).group(1) + exceptionCode = re.compile("ExceptionCode: ([^\s\b]+)").search(self.buff).group(1) + + exceptionType = "AV" + if re.compile("READ_ADDRESS").search(self.buff) is not None: + exceptionType = "ReadAV" + elif re.compile("WRITE_ADDRESS").search(self.buff) is not None: + exceptionType = "WriteAV" + + bucket = "%s_at_%s" % (exceptionType, exceptionAddress) + + except: + # Sometimes !analyze -v fails + bucket = "Unknown" + + self.crashInfo["Bucket"] = bucket + + ## Do we have !exploitable? + + try: + majorHash = re.compile("^MAJOR_HASH:(0x.*)$", re.M).search(self.buff).group(1) + minorHash = re.compile("^MINOR_HASH:(0x.*)$", re.M).search(self.buff).group(1) + classification = re.compile("^CLASSIFICATION:(.*)$", re.M).search(self.buff).group(1) + shortDescription = re.compile("^SHORT_DESCRIPTION:(.*)$", re.M).search(self.buff).group(1) + + if majorHash is not None and minorHash is not None: + bucket = "%s_%s_%s_%s" % (classification, + shortDescription, + majorHash, + minorHash) + + self.crashInfo["Bucket"] = bucket + + except: + pass + + # Done + + except: + sys.stdout.write(repr(sys.exc_info()) + "\n") + raise + + self.buff = "" + self.fault = True + + print("Exception: Writing to file") + fd = open(self.Tempfile, "wb+") + fd.write(pickle.dumps(self.crashInfo)) + fd.close() + + self.handledFault.set() + return DbgEng.DEBUG_STATUS_BREAK + + + def WindowsDebugEngineProcess_run(*args, **kwargs): + + started = kwargs['Started'] + handlingFault = kwargs['HandlingFault'] + handledFault = kwargs['HandledFault'] + CommandLine = kwargs.get('CommandLine', None) + Service = kwargs.get('Service', None) + ProcessName = kwargs.get('ProcessName', None) + ProcessID = kwargs.get('ProcessID', None) + KernelConnectionString = kwargs.get('KernelConnectionString', None) + SymbolsPath = kwargs.get('SymbolsPath', None) + IgnoreFirstChanceGardPage = kwargs.get('IgnoreFirstChanceGardPage', None) + IgnoreSecondChanceGardPage = kwargs.get('IgnoreSecondChanceGardPage', None) + quit = kwargs['Quit'] + Tempfile = kwargs['Tempfile'] + WinDbg = kwargs['WinDbg'] + TempfilePid = kwargs['TempfilePid'] + FaultOnEarlyExit = kwargs['FaultOnEarlyExit'] + + dbg = None + + print("WindowsDebugEngineProcess_run") + + # Hack for comtypes early version + comtypes._ole32.CoInitializeEx(None, comtypes.COINIT_APARTMENTTHREADED) + + try: + _eventHandler = _DbgEventHandler() + _eventHandler.pid = None + _eventHandler.handlingFault = handlingFault + _eventHandler.handledFault = handledFault + _eventHandler.IgnoreFirstChanceGardPage = IgnoreFirstChanceGardPage + _eventHandler.IgnoreSecondChanceGardPage = IgnoreSecondChanceGardPage + _eventHandler.quit = quit + _eventHandler.Tempfile = Tempfile + _eventHandler.TempfilePid = TempfilePid + _eventHandler.FaultOnEarlyExit = FaultOnEarlyExit + + if KernelConnectionString: + dbg = PyDbgEng.KernelAttacher(connection_string=KernelConnectionString, + event_callbacks_sink=_eventHandler, + output_callbacks_sink=_eventHandler, + symbols_path=SymbolsPath, + dbg_eng_dll_path=WinDbg) + + elif CommandLine: + dbg = PyDbgEng.ProcessCreator(command_line=CommandLine, + follow_forks=True, + event_callbacks_sink=_eventHandler, + output_callbacks_sink=_eventHandler, + symbols_path=SymbolsPath, + dbg_eng_dll_path=WinDbg) + + elif ProcessName: + + pid = None + for x in range(10): + print("WindowsDebugEngineThread: Attempting to locate process by name...") + pid = GetProcessIdByName(ProcessName) + if pid is not None: + break + + time.sleep(0.25) + + if pid is None: + raise Exception("Error, unable to locate process '%s'" % ProcessName) + + dbg = PyDbgEng.ProcessAttacher(pid, + event_callbacks_sink=_eventHandler, + output_callbacks_sink=_eventHandler, + symbols_path=SymbolsPath, + dbg_eng_dll_path=WinDbg) + + elif ProcessID: + + print("Attaching by pid: %d" % ProcessID) + pid = ProcessID + dbg = PyDbgEng.ProcessAttacher(pid, event_callbacks_sink=_eventHandler, + output_callbacks_sink=_eventHandler, symbols_path=SymbolsPath, + dbg_eng_dll_path=WinDbg) + + elif Service: + + # Make sure service is running + if win32serviceutil.QueryServiceStatus(Service)[1] != 4: + try: + # Some services auto-restart, if they do + # this call will fail. + win32serviceutil.StartService(Service) + except: + pass + + while win32serviceutil.QueryServiceStatus(Service)[1] == 2: + time.sleep(0.25) + + if win32serviceutil.QueryServiceStatus(Service)[1] != 4: + raise Exception("WindowsDebugEngine: Unable to start service!") + + # Determine PID of service + scm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ALL_ACCESS) + hservice = win32service.OpenService(scm, Service, 0xF01FF) + + status = win32service.QueryServiceStatusEx(hservice) + pid = status["ProcessId"] + + win32service.CloseServiceHandle(hservice) + win32service.CloseServiceHandle(scm) + + dbg = PyDbgEng.ProcessAttacher(pid, + event_callbacks_sink=_eventHandler, + output_callbacks_sink=_eventHandler, + symbols_path=SymbolsPath, + dbg_eng_dll_path=WinDbg) + + else: + raise Exception("Didn't find way to start debugger... bye bye!!") + + _eventHandler.dbg = dbg + started.set() + dbg.event_loop_with_quit_event(quit) + + finally: + if dbg is not None: + if dbg.idebug_client is not None: + dbg.idebug_client.EndSession(DbgEng.DEBUG_END_ACTIVE_TERMINATE) + dbg.idebug_client.Release() + elif dbg.idebug_control is not None: + dbg.idebug_control.EndSession(DbgEng.DEBUG_END_ACTIVE_TERMINATE) + dbg.idebug_control.Release() + + dbg = None + + comtypes._ole32.CoUninitialize() + + + def GetProcessIdByName(procname): + """ + Try and get pid for a process by name. + """ + + ourPid = -1 + procname = procname.lower() + + try: + ourPid = win32api.GetCurrentProcessId() + + except: + pass + + pids = win32process.EnumProcesses() + for pid in pids: + if ourPid == pid: + continue + + try: + hPid = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, 0, pid) + + try: + mids = win32process.EnumProcessModules(hPid) + for mid in mids: + name = str(win32process.GetModuleFileNameEx(hPid, mid)) + if name.lower().find(procname) != -1: + return pid + + finally: + win32api.CloseHandle(hPid) + except: + pass + + return None + + class WindowsDebugEngine(Monitor): + """ + Windows debugger agent. This debugger agent is based on the windbg engine and + supports the following features: + + * User mode debugging + * Kernel mode debugging + * x86 and x64 + * Symbols and symbol server + + """ + + def __init__(self, args): + Monitor.__init__(self, args) + + print("WindowsDebugEngine::__init__()") + + self.started = None + # Set at start of exception handling + self.handlingFault = None + # Set when collection finished + self.handledFault = None + self.crashInfo = None + self.fault = False + self.thread = None + self.tempfile = None + self.WinDbg = None + + if args.has_key('CommandLine'): + self.CommandLine = str(args['CommandLine']).replace("'''", "") + else: + self.CommandLine = None + + if args.has_key('Service'): + self.Service = str(args['Service']).replace("'''", "") + else: + self.Service = None + + if args.has_key('ProcessName'): + self.ProcessName = str(args['ProcessName']).replace("'''", "") + else: + self.ProcessName = None + + if args.has_key('ProcessID'): + self.ProcessID = int(args['ProcessID'].replace("'''", "")) + else: + self.ProcessID = None + + if args.has_key('KernelConnectionString'): + self.KernelConnectionString = str(args['KernelConnectionString']).replace("'''", "") + else: + self.KernelConnectionString = None + + if args.has_key('SymbolsPath'): + self.SymbolsPath = str(args['SymbolsPath']).replace("'''", "") + else: + self.SymbolsPath = "SRV*http://msdl.microsoft.com/download/symbols" + + if args.has_key("StartOnCall"): + self.StartOnCall = True + self.OnCallMethod = str(args['StartOnCall']).replace("'''", "").lower() + else: + self.StartOnCall = False + + if args.has_key("WinDbg"): + self.WinDbg = str(args['WinDbg']).replace("'''", "").lower() + + if args.has_key("IgnoreFirstChanceGardPage"): + self.IgnoreFirstChanceGardPage = True + else: + self.IgnoreFirstChanceGardPage = False + + if args.has_key("IgnoreSecondChanceGardPage"): + self.IgnoreSecondChanceGardPage = True + else: + self.IgnoreSecondChanceGardPage = False + + if args.has_key("NoCpuKill"): + self.NoCpuKill = True + else: + self.NoCpuKill = False + + if args.has_key("FaultOnEarlyExit"): + self.FaultOnEarlyExit = True + else: + self.FaultOnEarlyExit = False + + if self.Service is None and self.CommandLine is None and self.ProcessName is None \ + and self.KernelConnectionString is None and self.ProcessID is None: + raise PeachException( + "Unable to create WindowsDebugEngine, missing Service, or CommandLine, or ProcessName, or ProcessID, or KernelConnectionString parameter.") + + self.handlingFault = None + self.handledFault = None + + def _StartDebugger(self): + + try: + if self.cpu_hq is not None: + win32pdh.RemoveCounter(self.cpu_counter_handle) + win32pdh.CloseQuery(self.cpu_hq) + self.cpu_hq = None + self.cpu_counter_handle = None + except: + pass + + # Clear all our event handlers + self.started = Event() + self.quit = Event() + self.handlingFault = Event() + self.handledFault = Event() + self.crashInfo = None + self.fault = False + self.pid = None + self.cpu_process = None + self.cpu_path = None + self.cpu_hq = None + self.cpu_counter_handle = None + + (fd, self.tempfile) = tempfile.mkstemp() + os.close(fd) + (fd, self.tempfilepid) = tempfile.mkstemp() + os.close(fd) + + try: + os.unlink(self.tempfile) + except: + pass + + self.thread = Process(group=None, target=WindowsDebugEngineProcess_run, kwargs={ + 'Started': self.started, + 'HandlingFault': self.handlingFault, + 'HandledFault': self.handledFault, + 'CommandLine': self.CommandLine, + 'Service': self.Service, + 'ProcessName': self.ProcessName, + 'ProcessID': self.ProcessID, + 'KernelConnectionString': self.KernelConnectionString, + 'SymbolsPath': self.SymbolsPath, + 'IgnoreFirstChanceGardPage': self.IgnoreFirstChanceGardPage, + 'IgnoreSecondChanceGardPage': self.IgnoreSecondChanceGardPage, + 'Quit': self.quit, + 'Tempfile': self.tempfile, + 'WinDbg': self.WinDbg, + 'TempfilePid': self.tempfilepid, + 'FaultOnEarlyExit': self.FaultOnEarlyExit + }) + + # Kick off our thread: + self.thread.start() + + # Wait it...! + self.started.wait() + + if not self.NoCpuKill: + # Make sure we wait at least 1 second + # for program to startup. Needed with new + # CPU killing k0de. + time.sleep(1) + + def _StopDebugger(self, force=False): + + if force == False and self.handledFault is not None and ( + self.handlingFault.is_set() and not self.handledFault.is_set()): + print("_StopDebugger(): Not killing process due to fault handling") + return + + print("_StopDebugger() - force:", force) + + if self.thread is not None and self.thread.is_alive(): + self.quit.set() + self.started.clear() + + self.thread.join(5) + + if force == False and self.handledFault is not None and ( + self.handlingFault.is_set() and not self.handledFault.is_set()): + print("_StopDebugger(): Not killing process due to fault handling - 2") + return + + if self.thread.is_alive(): + + # 1. Terminate child process + if self.pid is not None: + psutil.Process(self.pid).terminate() + + # 2. Terminate debugger process + self.thread.terminate() + + # 3. Join process to avoid ZOMBIES! + self.thread.join() + + time.sleep(0.25) # Take a breath + + elif self.thread is not None: + # quit could be set by event handler now + self.thread.join() + + self.thread = None + + def _IsDebuggerAlive(self): + return self.thread and self.thread.is_alive() + + def OnTestStarting(self): + """ + Called right before start of test. + """ + + if not self.StartOnCall and not self._IsDebuggerAlive(): + self._StartDebugger() + elif self.StartOnCall: + self._StopDebugger() + + def PublisherCall(self, method): + + if not self.StartOnCall: + return None + + if self.OnCallMethod == method.lower(): + self._StartDebugger() + return True + + if self.OnCallMethod + "_isrunning" == method.lower(): + + # Program has stopped if we are handling a fault. + if self.handlingFault.is_set() or self.handledFault.is_set(): + return False + + if not self.quit.is_set(): + if self.pid is None: + fd = open(self.tempfilepid, "rb+") + pid = fd.read() + fd.close() + + if len(pid) != 0: + self.pid = int(pid) + + try: + os.unlink(self.tempfilepid) + except: + pass + + if self.NoCpuKill == False and self.pid is not None: + try: + # Check and see if the CPU utilization is low + cpu = psutil.Process(self.pid).get_cpu_percent(interval=1.0) + if cpu is not None and cpu < 1.0: + cpu = psutil.Process(self.pid).get_cpu_percent(interval=1.0) + if cpu is not None and cpu < 1.0 and not self.quit.is_set(): + print("PublisherCall: Stopping debugger, CPU: %f" % cpu) + self._StopDebugger() + return False + + except psutil.NoSuchProcess as e: + pass + + return not self.quit.is_set() + + return None + + def OnTestFinished(self): + if not self.StartOnCall or not self._IsDebuggerAlive(): + return + + self._StopDebugger() + + def GetMonitorData(self): + """ + Get any monitored data. + """ + + print("GetMonitorData(): Loading from file") + fd = open(self.tempfile, "rb+") + self.crashInfo = pickle.loads(fd.read()) + fd.close() + + try: + os.unlink(self.tempfile) + except: + pass + + print("GetMonitorData(): Got it!") + if self.crashInfo is not None: + ret = self.crashInfo + self.crashInfo = None + return ret + + return None + + def RedoTest(self): + """ + Returns True if the current iteration should be repeated + """ + + if self.handlingFault is None: + return False + + if self.thread and self.thread.is_alive(): + time.sleep(0.15) + + if not self.handlingFault.is_set(): + return False + + print("RedoTest: Waiting for self.handledFault...") + + t = 60.0 * 3 + self.handledFault.wait(timeout=t) + + if not self.handledFault.is_set(): + print("RedoTest: Timmed out waiting for fault information") + print("RedoTest: Killing debugger and target") + self._StopDebugger(True) + _DbgEventHandler.TakeStackTrace = False + print("RedoTest: Attempting to re-run iteration") + return True + + return False + + def DetectedFault(self): + """ + Check if a fault was detected. + """ + + if self.FaultOnEarlyExit and (self.thread is None or not self.thread.is_alive()) and \ + (self.handledFault is None or not self.handledFault.is_set()): + print(">>>>>> RETURNING EARLY EXIT FAULT <<<<<<<<<") + return True + + if self.handlingFault is None: + print("DetectedFault: Agent was re-set, returning false") + return False + + if self.thread and self.thread.is_alive(): + time.sleep(0.15) + + if not self.handlingFault.is_set(): + return False + + print(">>>>>> RETURNING FAULT <<<<<<<<<") + + return True + + def OnFault(self): + """ + Called when a fault was detected. + """ + self._StopDebugger() + + def OnShutdown(self): + """ + Called when Agent is shutting down. + """ + self._StopDebugger() + +except: + # Only complain on Windows platforms. + #if sys.platform == 'win32': + # print "Warning: Windows debugger failed to load: ", sys.exc_info() + pass + +try: + + import vtrace, envi + import threading + + class PeachNotifier(vtrace.Notifier): + def __init__(self): + pass + + def notify(self, event, trace): + print("Got event: %d from pid %d, signal: %d" % (event, trace.getPid(), trace.getMeta("PendingSignal"))) + + UnixDebugger.handlingFault.set() + buff = "" + + addr = None + + # Stacktrace + buff += "\nStacktrace:\n" + buff += " [ PC ] [ Frame ] [ Location ]\n" + for frame in trace.getStackTrace(): + buff += " 0x%.8x 0x%.8x %s\n" % (frame[0], frame[1], self.bestName(trace, frame[0])) + if addr is None: + addr = frame[0] + + # Registers + buff += "\nRegisters:\n" + regs = trace.getRegisters() + rnames = regs.keys() + rnames.sort() + for r in rnames: + buff += " %s 0x%.8x\n" % (r, regs[r]) + + # Dissassembly + arch = trace.getMeta("Architecture") + arch = envi.getArchModule(arch) + + mem = trace.readMemory(addr - 256, 512) + addrStart = addr - 256 + offset = 0 + count = 0 + buff += "\nDisassembly:\n" + ops = [] + while offset < 500 and count < 200: + va = addrStart + offset + op = arch.makeOpcode(mem[offset:]) + + if va == addr: + for i in ops[-20:]: + buff += i + + buff += ">>>0x%.8x: %s\n" % (va, arch.reprOpcode(op, va=va)) + count = 190 + elif va < addr: + ops.append(" 0x%.8x: %s\n" % (va, arch.reprOpcode(op, va=va))) + else: + buff += " 0x%.8x: %s\n" % (va, arch.reprOpcode(op, va=va)) + + offset += len(op) + count += 1 + + print(buff) + + UnixDebugger.lock.acquire() + UnixDebugger.crashInfo = {'DebuggerOutput.txt': buff, 'Bucket': "AV_at_%d" % addr} + UnixDebugger.fault = True + UnixDebugger.lock.release() + UnixDebugger.handledFault.set() + + + def bestName(self, trace, address): + """ + Return a string representing the best known name for + the given address + """ + if not address: + return "NULL" + + match = trace.getSymByAddr(address) + if match is not None: + if int(match) == address: + return repr(match) + else: + return "%s+%d" % (repr(match), address - int(match)) + + map = trace.getMap(address) + if map: + return map[3] + + return "Who knows?!?!!?" + + class _TraceThread(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + + def run(self): + self.trace = vtrace.getTrace() + self.trace.registerNotifier(vtrace.NOTIFY_SIGNAL, PeachNotifier()) + self.trace.execute(self._command + " " + self._params) + UnixDebugger.started.set() + self.trace.run() + + + class UnixDebugger(Monitor): + """ + Unix GDB monitor. This debugger monitor uses the gdb + debugger via pygdb wrapper. Tested under Linux and OS X. + + * Collect core files + * User mode debugging + * Capturing stack trace, registers, etc + * Symbols is available + """ + + def __init__(self, args): + + UnixDebugger.quit = threading.Event() + UnixDebugger.started = threading.Event() + UnixDebugger.handlingFault = threading.Event() + UnixDebugger.handledFault = threading.Event() + UnixDebugger.lock = threading.Lock() + UnixDebugger.crashInfo = None + UnixDebugger.fault = False + self.thread = None + + if args.has_key('Command'): + self._command = str(args['Command']).replace("'''", "\"") + self._params = str(args['Params']).replace("'''", "\"") + self._pid = None + + elif args.has_key('ProcessName'): + self._command = None + self._params = None + self._pid = self.GetProcessIdByName(str(args['ProcessName']).replace("'''", "\"")) + + else: + raise Exception("Unable to create UnixGdb! Error in params!") + + if args.has_key("StartOnCall"): + self.StartOnCall = True + self.OnCallMethod = str(args['StartOnCall']).replace("'''", "").lower() + + else: + self.StartOnCall = False + + def PublisherCall(self, method): + + if not self.StartOnCall: + return + + if self.OnCallMethod == method.lower(): + self._StartDebugger() + + def _StartDebugger(self): + UnixDebugger.quit.clear() + UnixDebugger.started.clear() + UnixDebugger.handlingFault.clear() + UnixDebugger.handledFault.clear() + UnixDebugger.fault = False + UnixDebugger.crashInfo = None + + self.thread = _TraceThread() + self.thread._command = self._command + self.thread._params = self._params + self.thread._pid = self._pid + + self.thread.start() + UnixDebugger.started.wait() + time.sleep(2) # Let things spin up! + + def _StopDebugger(self): + + if self.thread is not None: + if self.thread.isAlive(): + UnixDebugger.quit.set() + UnixDebugger.started.clear() + self.thread.trace.kill() + self.thread.join() + time.sleep(0.25) # Take a breath + + self.thread.trace.release() # FIX + self.thread.trace.releaseMemory() # FIX fd + + def _IsDebuggerAlive(self): + return self.thread is not None and self.thread.isAlive() + + def OnTestStarting(self): + """ + Called right before start of test. + """ + if not self.StartOnCall and not self._IsDebuggerAlive(): + self._StartDebugger() + + elif self.StartOnCall: + self._StopDebugger() + + def OnTestFinished(self): + if not self.StartOnCall or not self._IsDebuggerAlive(): + return + + self._StopDebugger() + + def GetMonitorData(self): + """ + Get any monitored data. + """ + UnixDebugger.lock.acquire() + if UnixDebugger.crashInfo is not None: + ret = UnixDebugger.crashInfo + UnixDebugger.crashInfo = None + UnixDebugger.lock.release() + print("Returning crash data!") + return ret + + UnixDebugger.lock.release() + print("Not returning any crash data!") + return None + + def DetectedFault(self): + """ + Check if a fault was detected. + """ + + time.sleep(0.25) + + if not UnixDebugger.handlingFault.is_set(): + return False + + UnixDebugger.handledFault.wait() + UnixDebugger.lock.acquire() + + if UnixDebugger.fault or not self.thread.isAlive(): + print(">>>>>> RETURNING FAULT <<<<<<<<<") + UnixDebugger.fault = False + UnixDebugger.lock.release() + return True + + UnixDebugger.lock.release() + return False + + def OnFault(self): + """ + Called when a fault was detected. + """ + self._StopDebugger() + + def OnShutdown(self): + """ + Called when Agent is shutting down. + """ + self._StopDebugger() + + +except: + # Only complain on non-Windows platforms. + #if not sys.platform in ['win32', 'darwin']: + # print "Warning: Unix debugger failed to load: ", sys.exc_info() + pass diff --git a/fuzzers/Peach/Agent/debugger.pyc b/fuzzers/Peach/Agent/debugger.pyc new file mode 100644 index 0000000..9251543 Binary files /dev/null and b/fuzzers/Peach/Agent/debugger.pyc differ diff --git a/fuzzers/Peach/Agent/gui.py b/fuzzers/Peach/Agent/gui.py new file mode 100755 index 0000000..b4d7456 --- /dev/null +++ b/fuzzers/Peach/Agent/gui.py @@ -0,0 +1,143 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +try: + + import win32gui, win32con + import sys, time, os, signal + from threading import * + from Peach.agent import * + + class _WindowWatcher(Thread): + """ + Look one child deep on each top level window to try + and locate dialog boxen. + """ + + def __init__(self): + Thread.__init__(self) + + self.CloseWindows = False + self.FoundWindowEvent = None # Will be Event() + self.WindowNames = None # Will be [] + self.StopEvent = None # Will be Event() + + @staticmethod + def enumCallback(hwnd, self): + title = win32gui.GetWindowText(hwnd) + + for name in self.WindowNames: + if title.find(name) > -1: + try: + self.FoundWindowEvent.set() + + if self.CloseWindows: + win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0) + except: + pass + else: + try: + win32gui.EnumChildWindows(hwnd, _WindowWatcher.enumChildCallback, self) + except: + pass + + return True + + @staticmethod + def enumChildCallback(hwnd, self): + title = win32gui.GetWindowText(hwnd) + + for name in self.WindowNames: + if title.find(name) > -1: + try: + self.FoundWindowEvent.set() + + if self.CloseWindows: + win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0) + except: + pass + + return True + + def run(self): + while not self.StopEvent.isSet(): + win32gui.EnumWindows(_WindowWatcher.enumCallback, self) + time.sleep(.2) + + + class PopupWatcher(Monitor): + """ + Will watch for specific dialogs and optionally kill + or log a fault when detected. + """ + + def __init__(self, args): + """ + Constructor. Arguments are supplied via the Peach XML + file. + + @type args: Dictionary + @param args: Dictionary of parameters + """ + + # Our name for this monitor + self._name = "PopupWatcher" + self._closeWindows = False + self._triggerFaults = False + + if args.has_key("CloseWindows"): + if args["CloseWindows"].replace("'''", "").lower() in ["yes", "true", "1"]: + self._closeWindows = True + + if args.has_key("TriggerFaults"): + if args["TriggerFaults"].replace("'''", "").lower() in ["yes", "true", "1"]: + self._triggerFaults = True + + if not args.has_key("WindowNames"): + raise Exception("PopupWatcher requires a parameter named WindowNames.") + + self._names = args["WindowNames"].replace("'''", "").split(',') + + def OnTestStarting(self): + """ + Called right before start of test case or variation + """ + + self._thread = _WindowWatcher() + + self._thread.CloseWindows = self._closeWindows + self._thread.FoundWindowEvent = Event() + self._thread.WindowNames = self._names + self._thread.StopEvent = Event() + + self._thread.start() + + def OnTestFinished(self): + """ + Called right after a test case or variation + """ + self._thread.StopEvent.set() + time.sleep(.6) + + def DetectedFault(self): + """ + Check if a fault was detected. + """ + if self._triggerFaults: + return self._thread.FoundWindowEvent.isSet() + + return False + + def OnShutdown(self): + """ + Called when Agent is shutting down, typically at end + of a test run or when a Stop-Run occurs + """ + try: + self._thread.StopEvent.set() + time.sleep(.6) + except: + pass + +except: + pass diff --git a/fuzzers/Peach/Agent/gui.pyc b/fuzzers/Peach/Agent/gui.pyc new file mode 100644 index 0000000..0a03a06 Binary files /dev/null and b/fuzzers/Peach/Agent/gui.pyc differ diff --git a/fuzzers/Peach/Agent/linux.py b/fuzzers/Peach/Agent/linux.py new file mode 100755 index 0000000..385a557 --- /dev/null +++ b/fuzzers/Peach/Agent/linux.py @@ -0,0 +1,62 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import sys +import time +import os + +from Peach.agent import Monitor + + +class LinuxApport(Monitor): + + def __init__(self, args): + if 'Executable' in args: + self.programPath = str(args['ProgramPath']).replace("'''", "") + self.processName = os.path.basename(self.programPath) + else: + self.processName = None + + if 'LogFolder' in args: + self.logFolder = str(args['LogFolder']).replace("'''", "") + else: + self.logFolder = "/var/crash/" + + if 'Apport' in args: + self.Apport = self.logFolder = str(args['Apport']).replace("'''", "") + else: + self.Apport = "/usr/share/apport/apport" + + self._name = "LinuxApport" + + self.data = None + self.startingFiles = None + + def OnTestStarting(self): + self.startingFiles = os.listdir(self.logFolder) + + def GetMonitorData(self): + if not self.data: + return None + return {"LinuxApport.txt": self.data} + + def DetectedFault(self): + try: + time.sleep(0.25) + time.sleep(0.25) + self.data = None + for f in os.listdir(self.logFolder): + if f not in self.startingFiles and f.endswith(".crash") and \ + (self.processName is None or f.find(self.processName) > -1): + fd = open(os.path.join(self.logFolder, f), "rb") + self.data = fd.read() + fd.close() + os.unlink(os.path.join(self.logFolder, f)) + return True + return False + except: + print(sys.exc_info()) + return False + + def StopRun(self): + return False diff --git a/fuzzers/Peach/Agent/linux.pyc b/fuzzers/Peach/Agent/linux.pyc new file mode 100644 index 0000000..3ae0d0e Binary files /dev/null and b/fuzzers/Peach/Agent/linux.pyc differ diff --git a/fuzzers/Peach/Agent/memory.py b/fuzzers/Peach/Agent/memory.py new file mode 100755 index 0000000..2cd3c6d --- /dev/null +++ b/fuzzers/Peach/Agent/memory.py @@ -0,0 +1,254 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +try: + import sys + import ctypes + import win32pdhutil + import win32api + + sys.path.append("..") + sys.path.append("../..") + + from Peach.agent import Monitor + + PROCESS_VM_READ = 0x0010 + PROCESS_QUERY_INFORMATION = 0x0400 + + DWORD = ctypes.c_ulong + SIZE_T = ctypes.c_ulong + + MAX_PROCESSES = 1024 + MAX_PATH = 1024 + + Psapi = ctypes.windll.Psapi + Kernel32 = ctypes.windll.Kernel32 + + class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): + _fields_ = [("cb", DWORD), + ("PageFaultCount", DWORD), + ("PeakWorkingSetSize", SIZE_T), + ("WorkingSetSize", SIZE_T), + ("QuotaPeakPagedPoolUsage", SIZE_T), + ("QuotaPagedPoolUsage", SIZE_T), + ("QuotaPeakNonPagedPoolUsage", SIZE_T), + ("QuotaNonPagedPoolUsage", SIZE_T), + ("PagefileUsage", SIZE_T), + ("PeakPagefileUsage", SIZE_T), + ("PrivateUsage", SIZE_T), + ] + + class Memory(Monitor): + """ + Agent that monitors the amount of memory a process is utilizing. This is + useful for detecting memory leaks within the fuzzing target + """ + + def __init__(self, args): + """ + Constructor. Arguments are supplied via the Peach XML + file. + + @type args: Dictionary + @param args: Dictionary of parameters + """ + + try: + + # Our name for this monitor + self._name = "Memory Monitor" + self._pid = None + self._processName = None + self._hProcess = None + self._internalError = False + self._memoryInfo = None + self._threshold = None + self._detectedFault = False + self._stopOnFault = False + + # Report an error if no MemoryLimit and/or neither pid nor processName is defined + + while 1: + + if args.has_key('StopOnFault'): + self._stopOnFault = str(args["StopOnFault"]).replace("'''", "") + + if args.has_key('MemoryLimit'): + self._memoryLimit = int(args['MemoryLimit'].replace("'''", "")) + print("Memory: Memory Limit = %d" % self._memoryLimit) + else: + print("Memory: No memory limit specified") + self._internalError = True + break + + if args.has_key('Pid'): + self._pid = int(args['Pid'].replace("'''", "")) + print("Memory: Pid = %d" % self._pid) + + if args.has_key('ProcessName'): + self._processName = str(args['ProcessName']).replace("'''", "") + print("Memory: Process Name = %s" % self._processName) + + if self._pid is None and self._processName is None: + print("Memory: No pid or process name provided") + self._internalError = True + break + + break + + except: + print("Memory: Caught Exception") + raise + + def _OpenProcess(self, pid=None): + + if pid is not None: + return Kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 0, pid) + else: + return None + + def _CloseProcess(self, handle=None): + + if handle is not None: + Kernel32.CloseHandle(handle) + + def _GetProcessIdByName(self, name): + """ + Try and get pid for a process by name. + """ + + try: + win32pdhutil.GetPerformanceAttributes('Process', 'ID Process', name) + except: + sys.stdout.write("Memory: Unable to locate process [%s]\n" % name) + raise + + pids = win32pdhutil.FindPerformanceAttributesByName(name) + + # If _my_ pid in there, remove it + try: + pids.remove(win32api.GetCurrentProcessId()) + except ValueError: + pass + + return pids[0] + + def _GetProcessMemoryInfo(self, handle=None): + + if handle is None: + return None + + psmemCounters = PROCESS_MEMORY_COUNTERS_EX() + cb = DWORD(ctypes.sizeof(psmemCounters)) + b = Psapi.GetProcessMemoryInfo(handle, ctypes.byref(psmemCounters), cb) + + if not b: + return None + + dict = {} + + for k, t in psmemCounters._fields_: + dict[k] = getattr(psmemCounters, k) + + return dict + + def OnTestStarting(self): + """ + Called right before start of test case or variation + """ + + # if only a process name was passed in, derive the pid from it + if self._processName is not None: + self._pid = self._GetProcessIdByName(self._processName) + + if self._pid is None: + print("Memory: OnTestStarting: Could not resolve pid") + self._internalError = True + return + + self._hProcess = self._OpenProcess(self._pid) + + if self._hProcess is None: + print("Memory: Could not open target process") + self._internalError = True + return + + print("OnTestStarting: Process handle = %d" % self._hProcess) + + if self._hProcess is None: + print("Memory: Could not open target process") + self._internalError = True + return + + self._memoryInfo = self._GetProcessMemoryInfo(self._hProcess) + + if self._memoryInfo is None: + print("Memory: Could not acquire memory info") + self._internalError = True + return + else: + print("Memory Used = %d" % self._memoryInfo['PrivateUsage']) + + if self._memoryInfo['PrivateUsage'] > self._memoryLimit: + self._detectedFault = True + + if self._stopOnFault == "True": + print("Memory: Stopping on fault") + self._internalError = True + + def OnTestFinished(self): + """ + Called right after a test case or variation + """ + self._CloseProcess(self._hProcess) + self._hProcess = None + + def GetMonitorData(self): + """ + Get any monitored data from a test case. + """ + return {'MemoryUsed.txt': str(self._memoryInfo['PrivateUsage'])} + + def DetectedFault(self): + """ + Check if a fault was detected. + """ + return self._detectedFault + + def OnFault(self): + """ + Called when a fault was detected. + """ + pass + + def OnShutdown(self): + """ + Called when Agent is shutting down, typically at end + of a test run or when a Stop-Run occurs + """ + self._CloseProcess(self._hProcess) + + def StopRun(self): + """ + Return True to force test run to fail. This + should return True if an unrecoverable error + occurs. + """ + return self._internalError + + if __name__ == "__main__": + d = { + "MemoryLimit": "5000000", + "ProcessName": "CrashableServer" + } + a = Memory(d) + a.OnTestStarting() + + print(a.DetectedFault()) + a.OnTestFinished() + a.OnTestStarting() + + print(a.DetectedFault()) + a.OnTestFinished() +except: + pass diff --git a/fuzzers/Peach/Agent/memory.pyc b/fuzzers/Peach/Agent/memory.pyc new file mode 100644 index 0000000..690451c Binary files /dev/null and b/fuzzers/Peach/Agent/memory.pyc differ diff --git a/fuzzers/Peach/Agent/network.py b/fuzzers/Peach/Agent/network.py new file mode 100755 index 0000000..1ab3036 --- /dev/null +++ b/fuzzers/Peach/Agent/network.py @@ -0,0 +1,216 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import sys +import threading +import os +import re +import socket + +from Peach.agent import Monitor + + +try: + def search_file(filename): + """Find a file in a search path.""" + search_path = os.getenv("path") + paths = search_path.split(os.path.pathsep) + for path in paths: + if os.path.exists(os.path.join(path, filename)): + return True + return False + if sys.platform == 'win32' and search_file("wpcap.dll"): + import pcap + elif sys.platform != 'win32': + import pcap +except: + pass + + +class PingMonitor(Monitor): + """ + This monitor will report a fault if it cannot ping the specified hostname. + """ + + def __init__(self, args): + """ + Constructor. Arguments are supplied via the Peach XML file. + + @type args: Dictionary + @param args: Dictionary of parameters + """ + self.hostname = str(args['hostname']).replace("'''", "") + self._name = "PingMonitor" + + def DetectedFault(self): + """ + Check if a fault was detected. + """ + if sys.platform == "win32": + ping_send_command = "ping -n 2 " + ping_send_command3 = "ping -n 3 " + ping_reply_regex = r"Reply from \d+\.\d+\.\d+\.\d+: bytes=" + elif sys.platform == "linux2": + ping_send_command = "ping -c 2 " + ping_send_command3 = "ping -c 3 " + ping_reply_regex = r"64 bytes from \d+\.\d+\.\d+\.\d+:" + else: + raise Exception("PingAgent running on unsupported platform " + "{}".format(sys.platform)) + pipe = os.popen(ping_send_command + self.hostname) + buff = pipe.read() + pipe.close() + if re.compile(ping_reply_regex, re.M).search(buff) is not None: + return False + # If we didn't see a ping, let's try again with 3 pings just to make + # sure. + pipe = os.popen(ping_send_command3 + self.hostname) + buff = pipe.read() + pipe.close() + if re.compile(ping_reply_regex, re.M).search(buff) is not None: + return False + return True + + +class UdpThread(threading.Thread): + """ + Thread class for UdpMonitor + """ + + def __init__(self, host, port): + threading.Thread.__init__(self) + threading.Thread.setDaemon(self, True) + self._host = host + self._port = port + self.stopEvent = threading.Event() + self.stopEvent.clear() + self.receivedPacket = threading.Event() + self.receivedPacket.clear() + self.packets = [] + + def run(self): + print("UdpThread(): Starting up UDP listener") + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.bind((self._host, int(self._port))) + sock.setblocking(False) + while not self.stopEvent.isSet(): + try: + data = None + data, addr = sock.recvfrom(65565) + if data is not None and len(data) > 0: + print("UdpThread: Received packet from {}".format(addr)) + self.packets.append(data) + self.receivedPacket.set() + except socket.error: + # Thrown if non-blocking and no packet available to receive. + pass + print("UdpThread: Shutting down") + sock.close() + + +class UdpMonitor(Monitor): + """ + Watches for incoming packets on a UDP port. If packet received will + trigger fault saving data from packet. + """ + + def __init__(self, args): + self.host = str(args['host']).replace("'''", "") + self.port = str(args['port']).replace("'''", "") + self._name = "UdpMonitor" + self.thread = None + self.thread = UdpThread(self.host, self.port) + self.thread.start() + + def GetMonitorData(self): + data = "" + for d in self.thread.packets: + data += d + self.thread.packets = [] + self.thread.receivedPacket.clear() + return {'UdpMonitor.txt': data} + + def OnShutdown(self): + if self.thread is not None and self.thread.isAlive(): + self.thread.stopEvent.set() + self.thread.join() + self.thread = None + + def DetectedFault(self): + return self.thread.receivedPacket.isSet() + + +class PcapThread(threading.Thread): + def __init__(self, parent, device, filter, pcapFile): + threading.Thread.__init__(self) + threading.Thread.setDaemon(self, True) + self._device = device + self._filter = filter + self._pcapFile = pcapFile + self.stopEvent = threading.Event() + self.stopEvent.clear() + self.dumpClosed = threading.Event() + self.dumpClosed.clear() + self._packets = [] + + def run(self): + print("PcapThread(): Starting up pcap") + pc = pcap.pcap(self._device) + pc.dumpopen(self._pcapFile) + if self._filter is not None: + pc.setfilter(self._filter) + pc.setnonblock() + print("PcapThread(): Packet capture loop") + while not self.stopEvent.isSet(): + # Do not remove print. For some reason packets are only captures + # when it's there!!! + print(".") + pc.readpkts() + pc.dumpclose() + self.dumpClosed.set() + + +class PcapMonitor(Monitor): + """ + Monitor network using pcap library. + """ + + def __init__(self, args): + try: + self.device = str(args['device']).replace("'''", "") + if len(self.device) < 1: + self.device = pcap.getDefaultName() + except: + self.device = pcap.getDefaultName() + self.filter = str(args['filter']).replace("'''", "") + self.data = None + self.tempFile = os.tmpnam() + self.thread = None + + def OnTestStarting(self): + self.thread = PcapThread(self, self.device, self.filter, self.tempFile) + self.thread.start() + self.data = None + print("PcapMonitor: OnTestStarting done") + + def OnTestFinished(self): + # Stop thread + self.data = None + if self.thread is not None and self.thread.isAlive(): + self.thread.stopEvent.set() + self.thread.join() + self.thread.dumpClosed.wait() + # Read dump + f = open(self.tempFile, "rb") + self.data = f.read() + f.close() + print("PcapMonitor: Thread joined, dump saved") + self.thread = None + + def GetMonitorData(self): + return {'Capture.pcap': self.data} + + def OnShutdown(self): + if self.thread is not None and self.thread.isAlive(): + self.thread.stopEvent.set() + self.thread.join() diff --git a/fuzzers/Peach/Agent/network.pyc b/fuzzers/Peach/Agent/network.pyc new file mode 100644 index 0000000..02973d7 Binary files /dev/null and b/fuzzers/Peach/Agent/network.pyc differ diff --git a/fuzzers/Peach/Agent/osx.py b/fuzzers/Peach/Agent/osx.py new file mode 100755 index 0000000..9931288 --- /dev/null +++ b/fuzzers/Peach/Agent/osx.py @@ -0,0 +1,531 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import sys +import re +import time +import signal + +from Peach.agent import Monitor + + +class CrashReporter(Monitor): + """ + Monitor crash reporter for log files. + """ + + def __init__(self, args): + """ + Arguments are supplied via the Peach XML file. + + :param args: dict of parameters + :type args: dict + """ + Monitor.__init__(self, args) + self._name = "CrashReporter" + + if args.has_key('ProcessName'): + self.process_name = str(args['ProcessName']).replace("'''", "") + self.process_name = os.path.basename(self.process_name) + else: + self.process_name = None + + if args.has_key('LogFolder'): + self.log_folder = str(args['LogFolder']).replace("'''", "") + else: + self.logFolder = os.path.join(os.environ['HOME'], "Library/Logs/DiagnosticReports") + + if args.has_key('LookoutTime'): + self.lookout_time = float(args['LookoutTime']).replace("''", "") + else: + self.lookout_time = None + + self.data = None + self.starting_files = None + + def OnTestStarting(self): + # The monitor folder does not exist on a fresh installed system. + if not os.path.isdir(self.log_folder): + os.mkdir(self.log_folder) + self.starting_files = os.listdir(self.log_folder) + + def GetMonitorData(self): + if not self.data: + return None + return {"CrashReport.txt": self.data} + + def DetectedFault(self): + try: + # Give crash reporter time to find the crash. Only explicit from + # now on, since we have enough time during the re-launch of the + # process. We do not need to wait 0.50 seconds on each testcase + # to check for crashes if we monitor a single process. + if self.lookout_time: + time.sleep(self.lookout_time) + self.data = None + for f in os.listdir(self.log_folder): + if f not in self.starting_files and \ + f.endswith(".crash") and \ + (self.process_name is None or f.find(self.process_name) > -1): + fd = open(os.path.join(self.log_folder, f), "r") + self.data = fd.read() + fd.close() + return True + return False + except: + print(sys.exc_info()) + return False + + +class CrashWrangler(Monitor): + """ + Use Apple Crash Wrangler to detect and sort crashes. + """ + + def __init__(self, args): + """ + Arguments are supplied via the Peach XML file. + + :param args: dict of parameters + :type args: dict + """ + Monitor.__init__(self, args) + + if args.has_key('EnvironmentCommand'): + self.EnvCommand = str(args['EnvironmentCommand']).replace("'''", "") + try: + self.EnvCommand = os.environ[self.EnvCommand] + except KeyError: + self.EnvCommand = None + else: + self.EnvCommand = None + + if args.has_key('EnvironmentArguments'): + self.EnvArguments = str(args['EnvironmentArguments']).replace("'''", "") + try: + self.EnvArguments = os.environ[self.EnvArguments] + except KeyError: + self.EnvArguments = "" + else: + self.EnvArguments = "" + + if not self.EnvCommand: + if args.has_key('Command'): + self.Command = str(args['Command']).replace("'''", "") + else: + self.Command = None + else: + self.Command = self.EnvCommand + + if not self.EnvArguments: + if args.has_key('Arguments'): + self.Arguments = str(args['Arguments']).replace("'''", "") + else: + self.Arguments = "" + else: + self.Arguments = self.EnvArguments + + if args.has_key('StartOnCall'): + self.StartOnCall = str(args['StartOnCall']).replace("'''", "") + else: + self.StartOnCall = None + + if args.has_key('UseDebugMalloc'): + self.UseDebugMalloc = str(args['UseDebugMalloc']).replace("'''", "").lower() == 'true' + else: + self.UseDebugMalloc = False + + if args.has_key('EnvironmentExecHandler'): + self.EnvExecHandler = str(args['EnvironmentExecHandler']).replace("'''", "") + try: + self.EnvExecHandler = os.environ[self.EnvExecHandler] + except KeyError: + self.EnvExecHandler = "" + else: + self.EnvExecHandler = "" + + if not self.EnvExecHandler: + if args.has_key('ExecHandler'): + self.ExecHandler = str(args['ExecHandler']).replace("'''", "") + else: + raise PeachException("Error, CrashWrangler monitor requires 'ExecHandler' parameter.") + else: + self.ExecHandler = self.EnvExecHandler + + if args.has_key('ExploitableReads') and str(args['ExploitableReads']).replace("'''", "").lower() == "false": + self.ExploitableReads = False + else: + self.ExploitableReads = True + + if args.has_key("NoCpuKill"): + self.NoCpuKill = True + else: + self.NoCpuKill = False + + if args.has_key('CwLogFile'): + self.CwLogFile = str(args['CwLogFile']).replace("'''", "") + else: + self.CwLogFile = "cw.log" + + if args.has_key('CwLockFile'): + self.CwLockFile = str(args['CwLockFile']).replace("'''", "") + else: + self.CwLockFile = "cw.lck" + + if args.has_key('CwPidFile'): + self.CwPidFile = str(args['CwPidFile']).replace("'''", "") + else: + self.CwPidFile = "cw.pid" + + # Our name for this monitor + self._name = "CrashWrangler" + self.pid = None + self.pid2 = None + self.currentCount = 0 + self.restartFinger = 1000 + + def OnTestStarting(self): + if not self.StartOnCall: + if not self._IsRunning(): + self._StartProcess() + + def OnTestFinished(self): + if self.StartOnCall and self._IsRunning(): + self._StopProcess() + + def GetMonitorData(self): + if os.path.exists(self.CwLogFile): + fd = open(self.CwLogFile, "rb") + data = fd.read() + fd.close() + bucket = "Unknown" + if re.match(r".*:is_exploitable=\s*no\s*:.*", data): + bucket = "NotExploitable" + elif re.match(r".*:is_exploitable=\s*yes\s*:.*", data): + bucket = "Exploitable" + if data.find("exception=EXC_BAD_ACCESS:") > -1: + bucket += "_BadAccess" + if data.find(":access_type=read:") > -1: + bucket += "_Read" + elif data.find(":access_type=write:") > -1: + bucket += "_Write" + elif data.find(":access_type=exec:") > -1: + bucket += "_Exec" + elif data.find(":access_type=recursion:") > -1: + bucket += "_Recursion" + elif data.find(":access_type=unknown:") > -1: + bucket += "_Unknown" + + elif data.find("exception=EXC_BAD_INSTRUCTION:") > -1: + bucket += "_BadInstruction" + elif data.find("exception=EXC_ARITHMETIC:") > -1: + bucket += "_Arithmetic" + elif data.find("exception=EXC_CRASH:") > -1: + bucket += "_Crash" + # Locate crashing address to help bucket duplicates + try: + threadId = re.search(r"Crashed Thread:\s+(\d+)", data).group(1) + threadPos = data.find("Thread " + threadId + " Crashed:") + crashAddress = re.search(r"(0x[0-9a-fA-F]+)", data[threadPos:]).group(1) + bucket += "_" + crashAddress + except: + print(sys.exc_info()) + try: + os.unlink(self.CwLogFile) + os.unlink(self.CwLockFile) + except: + pass + if self.pid is not None: + return {"CrashWrangler" + str(self.pid) + ".txt": data, "Bucket": bucket} + else: + return {"CrashWrangler.txt": data, "Bucket": bucket} + return None + + def DetectedFault(self): + try: + # Give crash wrangler time to find the crash + time.sleep(0.25) + time.sleep(0.25) + return os.path.exists(self.CwLogFile) + except: + print(sys.exc_info()) + return False + + def OnShutdown(self): + self._StopProcess() + + def PublisherCall(self, method): + if self.StartOnCall: + if self.StartOnCall == method: + self._StartProcess() + elif self.StartOnCall + "_isrunning" == method: + if self._IsRunning(): + if not self.NoCpuKill: + cpu = None + try: + os.system("ps -o pcpu %d > .cpu" % self.pid2) + fd = open(".cpu", "rb") + data = fd.read() + fd.close() + os.unlink(".cpu") + cpu = re.search(r"\s*(\d+\.\d+)", data).group(1) + if cpu.startswith("0.") and not os.path.exists("cw.lck"): + time.sleep(1.5) + # Check and see if crashwrangler is going + if os.path.exists(self.CwLockFile): + return True + print("CrashWrangler: PCPU is low (%s), stopping process" % cpu) + self._StopProcess() + return False + except: + print(sys.exc_info()) + return True + else: + return False + return None + + def unlink(self, file): + try: + os.unlink(file) + except: + pass + + def _StartProcess(self): + if self._IsRunning(): + return + self.currentCount += 1 + # OS X can get very unstable during testing. This will hopefully + # allow for longer fuzzing runs by killing off some processes + # that seem to get "stuck". + if self.currentCount % self.restartFinger == 0: + os.system('killall -KILL Finder') + os.system('killall -KILL Dock') + os.system('killall -KILL SystemUIServer') + # Clean up any files + self.unlink(self.CwLockFile) + self.unlink(self.CwLogFile) + self.unlink(self.CwPidFile) + # If no command is specified, assume we are running exc_handler some + # other way. + if self.Command is None: + return + args = ["/usr/bin/env", + "CW_LOG_PATH=" + self.CwLogFile, + "CW_PID_FILE=" + self.CwPidFile, + "CW_LOCK_FILE=" + self.CwLockFile] + if self.UseDebugMalloc: + args.append("CW_USE_GMAL=1") + if self.ExploitableReads: + args.append("CW_EXPLOITABLE_READS=1") + args.append(self.ExecHandler) + args.append(self.Command) + splitArgs = self.Arguments.split(" ") + for i in range(len(splitArgs)): + if i > 0 and splitArgs[i - 1][-1] == '\\': + args[-1] = args[-1][:-1] + " " + splitArgs[i] + else: + args.append(splitArgs[i]) + print("CrashWrangler._StartProcess():" % args) + self.pid = os.spawnv(os.P_NOWAIT, "/usr/bin/env", args) + while not os.path.exists(self.CwPidFile): + time.sleep(0.15) + fd = open(self.CwPidFile, "rb") + self.pid2 = int(fd.read()) + fd.close() + self.unlink(self.CwPidFile) + print("_StartProcess(): Pid2: %d" % self.pid2) + + + def _StopProcess(self): + if self.pid is not None: + try: + # Verify if process is still running + (pid1, ret) = os.waitpid(self.pid, os.WNOHANG) + if not (pid1 == 0 and ret == 0): + self.pid = None + return + # Check for cw.lck before killing + while os.path.exists("cw.lck"): + time.sleep(0.25) + (pid1, ret) = os.waitpid(self.pid, os.WNOHANG) + if not (pid1 == 0 and ret == 0): + self.pid = None + return + except: + return + try: + # Kill process with signal + os.kill(self.pid2, signal.SIGTERM) + time.sleep(0.25) + os.kill(self.pid2, signal.SIGKILL) + except: + pass + try: + # Kill process with signal + os.kill(self.pid, signal.SIGTERM) + time.sleep(0.25) + os.kill(self.pid, signal.SIGKILL) + except: + pass + # Prevent Zombies! + os.wait() + self.pid = None + + + def _IsRunning(self): + if self.pid: + try: + (pid1, ret) = os.waitpid(self.pid, os.WNOHANG) + if pid1 == 0 and ret == 0: + print("_IsRunning: True") + return True + except: + pass + print("_IsRunning: False") + return False + + +class Process(Monitor): + """ + Start a process and kill it based on CPU usage. + """ + + def __init__(self, args): + """ + Arguments are supplied via the Peach XML file. + + :param args: dict of parameters + :type args: dict + """ + Monitor.__init__(self, args) + + if args.has_key('Command'): + self.Command = str(args['Command']).replace("'''", "") + else: + self.Command = None + + if args.has_key('Arguments'): + self.Arguments = str(args['Arguments']).replace("'''", "") + else: + self.Arguments = "" + + if args.has_key('StartOnCall'): + self.StartOnCall = str(args['StartOnCall']).replace("'''", "") + else: + self.StartOnCall = None + + if args.has_key("NoCpuKill"): + self.NoCpuKill = True + else: + self.NoCpuKill = False + + self._name = "OsxProcess" + self.pid = None + self.currentCount = 0 + self.restartFinger = 1000 + + def OnTestStarting(self): + if not self.StartOnCall: + if not self._IsRunning(): + self._StartProcess() + + def OnTestFinished(self): + if self.StartOnCall and self._IsRunning(): + self._StopProcess() + + def OnShutdown(self): + self._StopProcess() + + def PublisherCall(self, method): + if self.StartOnCall: + if self.StartOnCall == method: + self._StartProcess() + elif self.StartOnCall + "_isrunning" == method: + if self._IsRunning(): + if not self.NoCpuKill: + cpu = None + try: + os.system("ps -o pcpu %d > .cpu" % self.pid) + fd = open(".cpu", "rb") + data = fd.read() + fd.close() + self.unlink(".cpu") + cpu = re.search(r"\s*(\d+\.\d+)", data).group(1) + if cpu.startswith("0."): + time.sleep(1) + print("osx.Process: PCPU is low (%s), stopping process" % cpu) + self._StopProcess() + return False + except: + print(sys.exc_info()) + return True + else: + return False + return None + + def unlink(self, file): + try: + os.unlink(file) + except: + pass + + def _StartProcess(self): + if self._isRunning(): + return + self.currentCount += 1 + # OS X can get very unstable during testing. This will hopefully + # allow for longer fuzzing runs by killing off some processes + # that seem to get "stuck" + if self.currentCount % self.restartFinger == 0: + os.system('killall -KILL Finder') + os.system('killall -KILL Dock') + os.system('killall -KILL SystemUIServer') + # If no command is specified, assume we are running + # exc_handler some other way. + if self.Command is None: + return + args = [self.Command] + splitArgs = self.Arguments.split(" ") + for i in range(len(splitArgs)): + if i > 0 and splitArgs[i - 1][-1] == '\\': + args[-1] = args[-1][:-1] + " " + splitArgs[i] + else: + args.append(splitArgs[i]) + print("osx.Process._StartProcess(): %s" % args) + self.pid = os.spawnv(os.P_NOWAIT, self.Command, args) + time.sleep(1.5) + print("osx.Process: pid: %d" % self.pid) + + def _StopProcess(self): + if self.pid is not None: + try: + # Verify if process is still running + (pid1, ret) = os.waitpid(self.pid, os.WNOHANG) + if not (pid1 == 0 and ret == 0): + self.pid = None + return + except: + return + try: + # Kill process with signal + os.kill(self.pid, signal.SIGTERM) + time.sleep(0.25) + os.kill(self.pid, signal.SIGKILL) + except: + pass + # Prevent Zombies! + os.wait() + self.pid = None + + def _IsRunning(self): + if self.pid is not None: + try: + (pid1, ret) = os.waitpid(self.pid, os.WNOHANG) + if pid1 == 0 and ret == 0: + print("osx.Process._IsRunning: True") + return True + except: + pass + print("osx.Process._IsRunning: False") + return False diff --git a/fuzzers/Peach/Agent/osx.pyc b/fuzzers/Peach/Agent/osx.pyc new file mode 100644 index 0000000..4efb1dd Binary files /dev/null and b/fuzzers/Peach/Agent/osx.pyc differ diff --git a/fuzzers/Peach/Agent/process.py b/fuzzers/Peach/Agent/process.py new file mode 100755 index 0000000..9eb29e0 --- /dev/null +++ b/fuzzers/Peach/Agent/process.py @@ -0,0 +1,794 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import re +import sys +import time +import json +import shlex +import signal +import threading +try: + import Queue +except ImportError: + import queue +from subprocess import Popen, STDOUT, PIPE, check_output + +try: + # Todo: Test monitors on Windows and check Python 3 compatibility with PyWin32 + import win32con + import win32api + import win32serviceutil + # Todo: Find out which methods are used from this import and do it the right way. + from win32process import * +except: + if sys.platform == 'win32': + print("Warning: PyWin32 extensions not found, disabling various process monitors.") + +from Peach.agent import Monitor, MonitorDebug +from Peach.Engine.common import PeachException +from Peach.Utilities.common import * + + +class PageHeap(Monitor): + """ + A monitor that will enable/disable pageheap on an executable. + """ + + def __init__(self, args): + try: + self._path = os.path.join(args['Path'].replace("'''", ""), "gflags.exe") + except: + self._path = os.path.join(self.LocateWinDbg(), 'gflags.exe') + self._exe = os.path.basename(args['Executable'].replace("'''", "")) + self._onParams = ['gflags.exe', '/p', '/full', '/enable', self._exe] + self._offParams = ['gflags.exe', '/p', '/disable', self._exe] + try: + os.spawnv(os.P_WAIT, self._path, self._onParams) + except: + print("Error, PageHeap failed to launch:") + print("\tself._path:", self._path) + print("\tself._onParams", self._onParams) + raise + + def LocateWinDbg(self): + # NOTE: Update master copy in debugger.py if you change this. + try: + hkey = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, "Software\\Microsoft\\DebuggingTools") + val, _ = win32api.RegQueryValueEx(hkey, "WinDbg") + return val + except: + # Lets try a few common places before failing. + pgPaths = [ + "c:\\", + os.environ["SystemDrive"] + "\\", + os.environ["ProgramFiles"], + ] + if "ProgramW6432" in os.environ: + pgPaths.append(os.environ["ProgramW6432"]) + if "ProgramFiles(x86)" in os.environ: + pgPaths.append(os.environ["ProgramFiles(x86)"]) + + dbgPaths = [ + "Debuggers", + "Debugger", + "Debugging Tools for Windows", + "Debugging Tools for Windows (x64)", + "Debugging Tools for Windows (x86)", + ] + for p in pgPaths: + for d in dbgPaths: + testPath = os.path.join(p, d) + if os.path.exists(testPath): + return testPath + print("Unable to locate gflags.exe!") + + def OnShutdown(self): + os.spawnv(os.P_WAIT, self._path, self._offParams) + + +class WindowsProcess(Monitor): + """ + Process control agent. This agent is able to start, stop, and monitor if a process is running. + If the process exits early a fault will be issued to the fuzzer. + """ + + def __init__(self, args): + self.restartOnTest = False + if args.has_key('RestartOnEachTest'): + if args['RestartOnEachTest'].replace("'''", "").lower() == 'true': + self.restartOnTest = True + self.faultOnEarlyExit = True + if args.has_key('FaultOnEarlyExit'): + if args['FaultOnEarlyExit'].replace("'''", "").lower() != 'true': + self.faultOnEarlyExit = False + self.startOnCall = False + if args.has_key('StartOnCall'): + self.startOnCall = True + self.startOnCallMethod = args['StartOnCall'].replace("'''", "").lower() + self.waitForExitOnCall = False + if args.has_key('WaitForExitOnCall'): + self.waitForExitOnCall = True + self.waitForExitOnCallMethod = args['WaitForExitOnCall'].replace("'''", "").lower() + if not args.has_key('Command'): + raise PeachException("Error, monitor Process requires a parameter named 'Command'") + self.strangeExit = False + self.command = args["Command"].replace("'''", "") + self.args = None + self.pid = None + self.hProcess = None + self.hThread = None + self.dwProcessId = None + self.dwThreadId = None + + def PublisherCall(self, method): + method = method.lower() + if self.startOnCall and self.startOnCallMethod == method: + print("Process: startOnCall, starting process!") + self._StopProcess() + self._StartProcess() + elif self.waitForExitOnCall and self.waitForExitOnCallMethod == method: + print("Process: waitForExitOnCall, waiting on process exit") + while True: + if not self._IsProcessRunning: + print("Process: Process exitted") + return + time.sleep(0.25) + + def _StopProcess(self): + if self.hProcess is None: + return + if self._IsProcessRunning(): + TerminateProcess(self.hProcess, 0) + self.hProcess = None + self.hThread = None + self.dwProcessId = None + self.dwThreadId = None + + def _StartProcess(self): + if self.hProcess is not None: + self._StopProcess() + hProcess, hThread, dwProcessId, dwThreadId = CreateProcess(None, self.command, None, None, + 0, 0, None, None, STARTUPINFO()) + self.hProcess = hProcess + self.hThread = hThread + self.dwProcessId = dwProcessId + self.dwThreadId = dwThreadId + + def _IsProcessRunning(self): + if self.hProcess is None: + return False + ret = GetExitCodeProcess(self.hProcess) + if ret != win32con.STILL_ACTIVE: + return False + ret = GetExitCodeThread(self.hThread) + if ret != win32con.STILL_ACTIVE: + return False + return True + + def OnTestStarting(self): + self.strangeExit = False + if not self.startOnCall and (self.restartOnTest or not self._IsProcessRunning()): + self._StopProcess() + self._StartProcess() + elif self.startOnCall: + self._StopProcess() + + def OnTestFinished(self): + if not self._IsProcessRunning(): + self.strangeExit = True + if self.restartOnTest: + self._StopProcess() + elif self.startOnCall: + self._StopProcess() + + def GetMonitorData(self): + if self.strangeExit: + return {"WindowsProcess.txt": "Process exited early"} + return None + + def DetectedFault(self): + if self.faultOnEarlyExit: + return not self._IsProcessRunning() + else: + return False + + def OnFault(self): + self._StopProcess() + + def OnShutdown(self): + self._StopProcess() + + +class Process(Monitor): + """ + Process control agent. This agent is able to start, stop, and monitor if a process is running. + If the process exits early a fault will be issued to the fuzzer. + """ + + def __init__(self, args): + self.restartOnTest = False + if args.has_key('RestartOnEachTest'): + if args['RestartOnEachTest'].replace("'''", "").lower() == 'true': + self.restartOnTest = True + self.faultOnEarlyExit = True + if args.has_key('FaultOnEarlyExit'): + if args['FaultOnEarlyExit'].replace("'''", "").lower() != 'true': + self.faultOnEarlyExit = False + self.startOnCall = False + if args.has_key('StartOnCall'): + self.startOnCall = True + self.startOnCallMethod = args['StartOnCall'].replace("'''", "").lower() + self.waitForExitOnCall = False + if args.has_key('WaitForExitOnCall'): + self.waitForExitOnCall = True + self.waitForExitOnCallMethod = args['WaitForExitOnCall'].replace("'''", "").lower() + if not args.has_key('Command'): + raise PeachException("Error, monitor Process requires a parameter named 'Command'") + self.strangeExit = False + self.command = args["Command"].replace("'''", "") + self.args = self.command.split() + self.pid = None + self.process = None + + def PublisherCall(self, method): + method = method.lower() + if self.startOnCall and self.startOnCallMethod == method: + print("Process: startOnCall, starting process!") + self._StopProcess() + self._StartProcess() + elif self.waitForExitOnCall and self.waitForExitOnCallMethod == method: + print("Process: waitForExitOnCall, waiting on process exit") + while True: + if not self._IsProcessRunning(): + print("Process: Process exitted") + return + time.sleep(0.25) + + def _StopProcess(self): + print("Process._StopProcess") + if not self.process: + return + if self._IsProcessRunning(): + try: + os.kill(self.process.pid, signal.SIGTERM) + os.kill(self.process.pid, signal.SIGKILL) + except: + pass + self.process.wait() + self.process = None + + def _StartProcess(self): + print("Process._StartProcess") + if self.process: + self._StopProcess() + self.process = Popen(self.args) + + def _IsProcessRunning(self): + if self.process is None: + print("Process._IsProcessRunning: False (self.process == None)") + return False + if self.process.poll() is not None: + print("Process._IsProcessRunning: False (self.process.poll != None)") + return False + print("Process._IsProcessRunning: True") + return True + + def OnTestStarting(self): + self.strangeExit = False + if not self.startOnCall and (self.restartOnTest or not self._IsProcessRunning()): + print("Process.OnTestStarting: Stopping and starting process") + self._StopProcess() + self._StartProcess() + elif self.startOnCall: + print("Process.OnTestStarting: Stopping process") + self._StopProcess() + print("Exiting OnTestStarting...") + + def OnTestFinished(self): + if not self._IsProcessRunning(): + self.strangeExit = True + if self.restartOnTest: + print("Process.OnTestFinished: Stopping process") + self._StopProcess() + elif self.startOnCall: + print("Process.OnTestFinished: Stopping process") + self._StopProcess() + + def GetMonitorData(self): + if self.strangeExit: + return {"Process.txt": "Process exited early"} + return None + + def DetectedFault(self): + if self.faultOnEarlyExit: + return self.strangeExit + else: + return False + + def OnFault(self): + self._StopProcess() + + def OnShutdown(self): + self._StopProcess() + + +class WindowsService(Monitor): + """ + Controls a windows service making sure it's started, optionally restarting, etc. + """ + + def __init__(self, args): + if args.has_key('RestartOnEachTest'): + if args['RestartOnEachTest'].lower() == 'true': + self.restartOnTest = True + else: + self.restartOnTest = False + else: + self.restartOnTest = False + if args.has_key('FaultOnEarlyExit'): + if args['FaultOnEarlyExit'].lower() == 'true': + self.faultOnEarlyExit = True + else: + self.faultOnEarlyExit = False + else: + self.faultOnEarlyExit = True + self.strangeExit = False + self.service = args["Service"].replace("'''", "") + if args.has_key("Machine"): + self.machine = args["Machine"].replace("'''", "") + else: + self.machine = None + + def _StopProcess(self): + win32serviceutil.StopService(self.service, self.machine) + while win32serviceutil.QueryServiceStatus(self.service, self.machine)[1] == 3: + time.sleep(0.25) + if win32serviceutil.QueryServiceStatus(self.service, self.machine)[1] != 1: + raise Exception("WindowsService: Unable to stop service!") + + def _StartProcess(self): + if self._IsProcessRunning(): + return + win32serviceutil.StartService(self.service, self.machine) + while win32serviceutil.QueryServiceStatus(self.service, self.machine)[1] == 2: + time.sleep(0.25) + if win32serviceutil.QueryServiceStatus(self.service, self.machine)[1] == 4: + raise Exception("WindowsService: Unable to start service!") + + def _IsProcessRunning(self): + if win32serviceutil.QueryServiceStatus(self.service, self.machine)[1] == 4: + return True + return False + + def OnTestStarting(self): + self.strangeExit = False + if self.restartOnTest or not self._IsProcessRunning(): + self._StopProcess() + self._StartProcess() + + def OnTestFinished(self): + if not self._IsProcessRunning(): + self.strangeExit = True + if self.restartOnTest: + self._StopProcess() + + def GetMonitorData(self): + if self.strangeExit: + return {"WindowsService.txt": "Process exited early"} + return None + + def DetectedFault(self): + #if self.faultOnEarlyExit: + # return not self._IsProcessRunning() + # + #else: + # return False + return False + + def OnFault(self): + self._StopProcess() + + def OnShutdown(self): + pass + + +class ProcessKiller(Monitor): + """Will watch for specific process and kill.""" + + def __init__(self, args): + self._name = "ProcessWatcher" + if not args.has_key("ProcessNames"): + raise Exception("ProcessWatcher requires a parameter named ProcessNames.") + self._names = args["ProcessNames"].replace("'''", "").split(',') + + def OnTestStarting(self): + pass + + def OnTestFinished(self): + for name in self._names: + os.popen('TASKKILL /IM ' + name + ' /F') + time.sleep(.6) + + def DetectedFault(self): + return False + + def OnShutdown(self): + try: + for name in self._names: + os.popen('TASKKILL /IM ' + name + ' /F') + time.sleep(.6) + except: + pass + + +class ProcessID(Monitor): + """ + Monitors CrashReporter on MacOS, LinuxApport on Linux and the process id of a process. + There are external monitors present for CrashReporter and LinuxApport but applying them + means having a delay between each testcase because they will wait and observe a folder for a + crash report after each test case. This monitor tries to observe the process id for a change + and will only after observe a specific folder for a crash report. The monitor does not work + with child processes like plugin processes. + """ + + def __init__(self, args): + Monitor.__init__(self, args) + self._name = "ProcessID" + + self.command = getStringAttribute(args, "Command") + if not self.command: + raise ValueError("Command not provided or empty in %s" % __file__) + self.arguments = shlex.split(self.command) + shlex.split(getStringAttribute(args, "Arguments")) + + self.process_environment = getStringAttribute(args, "Environment") + if self.process_environment: + os.environ.update(dict([p.split("=") for p in self.process_environment.split("|")])) + + self.asan_options = getStringAttribute(args, "ASanOptions") + if self.asan_options: + os.environ["ASAN_OPTIONS"] = "%s" % self.asan_options + + self.asan_library_path = getStringAttribute(args, "ASanMacOSRuntime") + if isMacOS and self.asan_library_path: + os.environ["DYLD_LIBRARY_PATH"] = getStringAttribute(args, "ASanMacOSRuntime") + + self.asan_symbolizer = getStringAttribute(args, "ASanSymbolizer") + if self.asan_symbolizer: + os.environ["ASAN_SYMBOLIZER_PATH"] = self.asan_symbolizer + self.heartbeat = getFloatAttribute(args, "Heartbeat", "0.0") + self.monitor_console = getBooleanAttribute(args, "NoConsoleLogging") + self.gdb_cmd_batch = getStringAttribute(args, "GDBCommands") + self.print_subprocess_output = getBooleanAttribute(args, "PrintSubprocessOutput") + self.lookout_time = getFloatAttribute(args, "LookoutTime", "5.0") + + self.system_report_path = getStringAttribute(args, 'LogFolder') + if self.system_report_path and not os.path.isdir(self.system_report_path): + raise ValueError("Provided path for LogFolder is invalid.") + elif isMacOS(): + self.system_report_path = os.path.join(os.environ['HOME'], "Library/Logs/DiagnosticReports") + if os.path.isdir(self.system_report_path): + try: + os.makedirs(self.system_report_path) + except (IOError, OSError) as e: + if e.errno != 17: + raise + + self.pid = self.process = None + self.console_log = self.crash_trace = [] + self.failure = False + self.first_run = True + + def OnTestStarting(self): + if not self._IsRunning(): + self._StartProcess() + + def _StartProcess(self): + print("Command: {}".format(self.arguments)) + self.process = Popen(self.arguments, stderr=STDOUT, stdout=PIPE, + env=os.environ, bufsize=1, close_fds=isPosix()) + self.pid = self.process.pid + + def enqueue_output(out, queue): + for line in iter(out.readline, ""): + queue.put(line) + out.close() + + self.terminal_queue = Queue.Queue() + self.terminal_producer = threading.Thread(target=enqueue_output, args=(self.process.stdout, self.terminal_queue)) + self.terminal_consumer = threading.Thread(target=self._grab_sanitizer_trace) + self.terminal_producer.setDaemon(True) + self.terminal_consumer.setDaemon(True) + self.terminal_producer.start() + self.terminal_consumer.start() + + def _IsRunning(self): + if self.process is None: + MonitorDebug(self._name, "IsRunning: False (self.process == None") + return False + if self.process.poll() is not None: + MonitorDebug(self._name, "IsRunning: False (self.process.poll != None)") + return False + MonitorDebug(self._name, "IsRunning: True") + return True + + def _grab_sanitizer_trace(self): + """Run in the background and set self.failure to true once an ASan crash got detected.""" + inside_sanitizer_trace = False + self.crash_trace = [] + while True: + captured_line = self.terminal_queue.get() + if self.print_subprocess_output: + print(captured_line.strip("\n")) + if self.monitor_console: + self.console_log.append(captured_line) + if not inside_sanitizer_trace: + if captured_line.find("ERROR: AddressSanitizer") != -1 and captured_line.find("AddressSanitizer failed to allocate") == -1: + inside_sanitizer_trace = True + if inside_sanitizer_trace and \ + (captured_line.find("Stats: ") != -1 or + captured_line.find("ABORTING") != -1 or + captured_line.find("ERROR: Failed") != -1): + inside_sanitizer_trace = False + self.failure = True + break + if inside_sanitizer_trace: + self.crash_trace.append(captured_line) + if self.failure and self._IsRunning(): + self.process.terminate() + self.process.kill() + self.process = None + + def OnTestFinished(self): + self.console_log = [] + if not self._IsRunning(): + self.failure = True + time.sleep(self.heartbeat) + + def _from_core_dump(self, log_folder): + core_filename = os.path.join(log_folder, 'core.%s' % str(self.pid)) + if os.path.exists(core_filename): + gdb_args = ["gdb", "-n", "-batch", "-x", self.gdb_cmd_batch, self.command, core_filename] + gdb_output = check_output(gdb_args, stdin=None, stderr=STDOUT, close_fds=isPosix()) + os.remove(core_filename) + return gdb_output + + def _from_crash_reporter(self, log_folder): + report = "" + for fname in os.listdir(log_folder): + if not fname.endswith(".crash"): + continue + with open(os.path.join(log_folder, fname)) as fd: + content = fd.readlines() + try: + crash_pid = int(re.findall("\[(\d+)\]", content[0])[0]) + except: + continue + if crash_pid == self.pid: + report = "".join(content) + os.remove(os.path.join(log_folder, fname)) + break + return report + + def get_crash_report(self, log_folder): + if not os.path.isdir(log_folder): + return "" + if isMacOS(): + return self._from_crash_reporter(log_folder) + if isLinux(): + return self._from_core_dump(log_folder) + + def DetectedFault(self): + return self.failure + + def GetMonitorData(self): + time.sleep(self.lookout_time) + sytem_crash_report = self.get_crash_report(self.system_report_path) + bucket = {} + + if not len(self.crash_trace): + if self.process.returncode < 0: + crashSignals = [ + # POSIX.1-1990 signals + signal.SIGILL, + signal.SIGABRT, + signal.SIGFPE, + signal.SIGSEGV, + # SUSv2 / POSIX.1-2001 signals + signal.SIGBUS, + signal.SIGSYS, + signal.SIGTRAP, + ] + for crashSignal in crashSignals: + if process.returncode == -crashSignal: + bucket["auxdat.txt"] = "Process exited with signal: %d" % -process.returncode + else: + bucket["auxdat.txt"] = "".join(self.crash_trace) + + if sytem_crash_report: + bucket["system_crash_report.txt"] = sytem_crash_report + + if self.console_log: + bucket["stdout.txt"] = "".join(self.console_log[-1000:]) + + if self.failure: + meta = { + "environ": os.environ.data, + "command": self.arguments + } + bucket["meta.txt"] = json.dumps(dict(meta)) + bucket["Bucket"] = os.path.basename(self.command) + return bucket + + def OnFault(self): + self._StopProcess() + + def OnShutdown(self): + self._StopProcess() + + def _StopProcess(self): + self.failure = False + if self._IsRunning(): + try: + MonitorDebug(self._name, "calling terminate()") + self.process.terminate() + MonitorDebug(self._name, "calling kill()") + self.process.kill() + except Exception: + print(sys.exc_info()) + self.process.wait() + self.process = None + + +class ASanConsoleMonitor(Monitor): + + def __init__(self, args): + Monitor.__init__(self, args) + self._name = "ASanConsoleMonitor" + + self.command = getStringAttribute(args, "Command") + if not self.command: + raise ValueError("Command not provided or empty in %s" % __file__) + self.arguments = shlex.split(self.command) + shlex.split(getStringAttribute(args, "Arguments")) + + self.process_environment = getStringAttribute(args, "Environment") + if self.process_environment: + os.environ.update(dict([p.split("=") for p in self.process_environment.split("|")])) + + self.asan_options = getStringAttribute(args, "ASanOptions") + if self.asan_options: + os.environ["ASAN_OPTIONS"] = "%s" % self.asan_options + + self.asan_library_path = getStringAttribute(args, "ASanMacOSRuntime") + if isMacOS and self.asan_library_path: + os.environ["DYLD_LIBRARY_PATH"] = getStringAttribute(args, "ASanMacOSRuntime") + + self.asan_symbolizer = getStringAttribute(args, "ASanSymbolizer") + if self.asan_symbolizer: + os.environ["ASAN_SYMBOLIZER_PATH"] = self.asan_symbolizer + + if "StartOnCall" in args: + self.start_on_call = True + self.OnCallMethod = getStringAttribute(args, 'StartOnCall') + else: + self.start_on_call = False + + self.asan_regex = "(ERROR: AddressSanitizer:.*[Stats:|ABORTING|ERROR: Failed])" + self.stderr = [] + self.stdout = [] + self.sanlog = [] + self.process = None + self.failure = False + + def OnTestStarting(self): + if not self.start_on_call and not self._IsRunning(): + self._StopProcess() + self._StartProcess() + elif self.start_on_call: + self._StopProcess() + + def PublisherCall(self, method): + if self.start_on_call and self.OnCallMethod == method: + MonitorDebug(self._name, "PublisherCall") + self._StopProcess() + self._StartProcess() + + def _IsRunning(self): + if self.process is None: + MonitorDebug(self._name, "IsRunning: False (self.process == None") + return False + if self.process.poll() is not None: + MonitorDebug(self._name, "IsRunning: False (self.process.poll != None)") + return False + MonitorDebug(self._name, "IsRunning: True") + return True + + def _StartProcess(self): + MonitorDebug(self._name, "_StartProcess") + self.failure = False + self.sanlog = [] + self.stderr = [] + self.stdout = [] + + print("Command: {}".format(self.arguments)) + self.process = Popen(self.arguments, stderr=PIPE, stdout=PIPE, + env=os.environ, bufsize=1, close_fds=isPosix()) + + # Todo: Add timeout= for GUI applications. + stdout, stderr = self.process.communicate() + + if stderr.find("ERROR: AddressSanitizer: ") != -1: + if stderr.find("AddressSanitizer failed to allocate") == -1: + self.failure = True + self.sanlog = re.findall(self.asan_regex, stderr, re.DOTALL)[0] + self.stdout = stdout + self.stderr = stderr + else: + if self.process.returncode < 0: + crashSignals = [ + # POSIX.1-1990 signals + signal.SIGILL, + signal.SIGABRT, + signal.SIGFPE, + signal.SIGSEGV, + # SUSv2 / POSIX.1-2001 signals + signal.SIGBUS, + signal.SIGSYS, + signal.SIGTRAP, + ] + for crashSignal in crashSignals: + if process.returncode == -crashSignal: + self.failure = True + self.sanlog = "Process exited with signal: %d" % -process.returncode + self.stdout = stdout + self.stderr = stderr + + if self.failure: + self._StopProcess() + + def OnTestFinished(self): + if self._IsRunning(): + self._StopProcess() + + def DetectedFault(self): + return self.failure + + def GetMonitorData(self): + #if not self.failure: + # return + bucket = {} + if self.sanlog: + bucket["auxdat.txt"] = "".join(self.sanlog) + if self.stdout: + bucket["stdout.txt"] = "".join(self.stdout) + if self.stderr: + bucket["stderr.txt"] = "".join(self.stderr) + meta = { + "environ": os.environ.data, + "command": self.arguments, + "returncode": self.process.returncode + } + bucket["meta.txt"] = json.dumps(dict(meta)) + bucket["Bucket"] = os.path.basename(self.command) + return bucket + + def OnFault(self): + self._StopProcess() + + def OnShutdown(self): + self._StopProcess() + + def _StopProcess(self): + if not self.process: + return + if self._IsRunning(): + try: + MonitorDebug(self._name, "calling terminate()") + self.process.terminate() + MonitorDebug(self._name, "calling kill()") + self.process.kill() + except Exception: + print(sys.exc_info()) + self.process.wait() + self.process = None diff --git a/fuzzers/Peach/Agent/process.pyc b/fuzzers/Peach/Agent/process.pyc new file mode 100644 index 0000000..1476631 Binary files /dev/null and b/fuzzers/Peach/Agent/process.pyc differ diff --git a/fuzzers/Peach/Agent/socketmon.py b/fuzzers/Peach/Agent/socketmon.py new file mode 100755 index 0000000..a1ba8be --- /dev/null +++ b/fuzzers/Peach/Agent/socketmon.py @@ -0,0 +1,165 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import sys +import time +import socket + +sys.path.append("..") +sys.path.append("../..") + +from Peach.agent import Monitor +from twisted.internet import reactor, protocol +from threading import Thread + +g_socketData = None +g_faultDetected = False +g_stopReactor = False + +# TODO: Port this over to use ThreadedSelectReactor +# http://twistedmatrix.com/documents/current/api/twisted.internet._threadedselect.ThreadedSelectReactor.html + +class SocketMonitor(Monitor): + + def __init__(self, args): + """ + Constructor. Arguments are supplied via the Peach XML file. + + @type args: Dictionary + @param args: Dictionary of parameters + """ + try: + self._name = "Socket Monitor" + self._ip = "" + self._port = "" + self._protocol = "" + self._thread = None + self._internalError = False + self._stopOnFault = False + # Report an error if no MemoryLimit and/or neither pid nor + # processName is defined. + while 1: + if args.has_key('IP'): + self._ip = str(args["IP"]).replace("'''", "") + else: + print("Socket Monitor: No IP specified, using using " + "127.0.0.1") + self._ip = "127.0.0.1" + if args.has_key('Port'): + self._port = int(args['Port'].replace("'''", "")) + print("Socket Monitor: Listening on Port: {}" + .format(self._port)) + else: + print("Socket Monitor: No Port specified, using 80") + self._port = "8002" + if args.has_key('Protocol'): + self._protocol = args['Protocol'].replace("'''", "") + print("Socket Monitor: Protocol = %s" % self._protocol) + else: + print("Socket Monitor: No Protocol specified, using TCP") + self._protocol = "tcp" + break + except: + self._internalError = True + print("Socket Monitor: Caught Exception Parsing Arguments") + raise + + def OnTestStarting(self): + """ + Called right before start of test case or variation. + """ + global g_faultDetected + global g_socketData + # fire up twisted if it hasn't been already + if self._thread is None: + self._thread = ReactorThread(self._ip, self._port, self._protocol) + self._thread.start() + g_socketData = None + g_faultDetected = False + return + + def GetMonitorData(self): + """ + Get any monitored data from a test case. + """ + global g_socketData + return {'SocketData.txt': str(g_socketData)} + + def DetectedFault(self): + """ + Check if a fault was detected. + """ + global g_faultDetected + return g_faultDetected + + def OnShutdown(self): + """ + Called when Agent is shutting down, typically at end of a test run or + when a Stop-Run occurs. + """ + global g_stopReactor + g_stopReactor = True + s = None + # hack to stop reactor + if self._protocol.lower() == "tcp": + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + else: + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect((self._ip, int(self._port))) + s.close() + + def StopRun(self): + """ + Return True to force test run to fail. This should return True if an + unrecoverable error occurs. + """ + return self._internalError + + +class ReactorThread(Thread): + def __init__(self, ip, port, protocol): + Thread.__init__(self) + self._ip = ip + self._port = port + self._protocol = protocol + self._factory = None + + def run(self): + self._factory = protocol.ServerFactory() + self._factory.protocol = Listener + if self._protocol.lower() == "tcp": + reactor.listenTCP(int(self._port), self._factory) + else: + reactor.listenUDP(int(self._port), self._factory) + reactor.run(installSignalHandlers=0) + + +class Listener(protocol.Protocol): + def connectionMade(self): + global g_stopReactor + global g_socketData + # hack until ThreadedSelectReactor is implemented + if g_stopReactor: + print("Socket Monitor: Stopping Reactor") + reactor.stop() + else: + host = self.transport.getHost() + g_socketData = host.host + ":" + str(host.port) + global g_faultDetected + g_faultDetected = True + + +if __name__ == "__main__": + d = { + "IP": "127.0.0.1", + "Port": "8002", + "Protocol": "tcp" + } + a = SocketMonitor(d) + a.OnTestStarting() + while True: + a.OnTestStarting() + time.sleep(2) + print(a.DetectedFault()) + a.OnTestFinished() + a.OnShutdown() diff --git a/fuzzers/Peach/Agent/socketmon.pyc b/fuzzers/Peach/Agent/socketmon.pyc new file mode 100644 index 0000000..b5b7c08 Binary files /dev/null and b/fuzzers/Peach/Agent/socketmon.pyc differ diff --git a/fuzzers/Peach/Agent/util.py b/fuzzers/Peach/Agent/util.py new file mode 100755 index 0000000..da6c8fe --- /dev/null +++ b/fuzzers/Peach/Agent/util.py @@ -0,0 +1,108 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import shutil + +from Peach.agent import Monitor + + +class CleanupFolder(Monitor): + """ + This monitor will remove any files created in a folder during a fuzzing + iteration. Create for removing stale temp files, etc. + """ + + def __init__(self, args): + """ + Constructor. Arguments are supplied via the Peach XML file. + + @type args: Dictionary + @param args: Dictionary of parameters + """ + self._name = None + self._folder = args['Folder'].replace("'''", "") + self._folderListing = os.listdir(self._folder) + + def OnTestStarting(self): + """ + Called right after a test case or variation. + """ + listing = os.listdir(self._folder) + for item in listing: + if item not in self._folderListing: + realName = os.path.join(self._folder, item) + print("CleanupFolder: Removing '{}'".format(realName)) + try: + os.unlink(realName) + except: + pass + try: + shutil.rmtree(realName) + except: + pass + + +try: + import win32api, win32con +except: + pass + + +class CleanupRegistry(Monitor): + """ + This monitor will remove any sub-keys for a specified registry key before + each run. This is useful for removing document recovery keys for fuzzing + Office. + """ + + def __init__(self, args): + """ + Constructor. Arguments are supplied via the Peach XML file. + + @type args: Dictionary + @param args: Dictionary of parameters + """ + self._name = None + self._key = args['Key'].replace("'''", "") + + if self._key.startswith("HKCU\\"): + self._root = win32con.HKEY_CURRENT_USER + elif self._key.startswith("HKCC\\"): + self._root = win32con.HKEY_CURRENT_CONFIG + elif self._key.startswith("HKLM\\"): + self._root = win32con.HKEY_LOCAL_MACHINE + elif self._key.startswith("HKPD\\"): + self._root = win32con.HKEY_PERFORMANCE_DATA + elif self._key.startswith("HKU\\"): + self._root = win32con.HKEY_USERS + else: + print("CleanupRegistry: Error, key must be prefixed with: " + "HKCU, HKCC, HKLM, HKPD, or HKU.") + raise Exception("CleanupRegistry: Error, key must be prefixed " + "with: HKCU, HKCC, HKLM, HKPD, or HKU.") + self._key = self._key[self._key.find("\\") + 1:] + + def OnTestStarting(self): + self.deleteKey(self._root, self._key) + + def deleteKey(self, hKey, subKey): + """ + Recursively remove registry keys. + """ + try: + hKey = win32api.RegOpenKeyEx(hKey, subKey, 0, + win32con.KEY_ALL_ACCESS) + try: + while True: + s = win32api.RegEnumKey(hKey, 0) + self.deleteKey(hKey, s) + print("CleanupRegistry: Removing sub-key '{}'".format(s)) + win32api.RegDeleteKey(hKey, s) + except win32api.error: + pass + finally: + win32api.RegCloseKey(hKey) + except: + print("Warning: Unable to open registry key!") + pass diff --git a/fuzzers/Peach/Agent/util.pyc b/fuzzers/Peach/Agent/util.pyc new file mode 100644 index 0000000..126c7e4 Binary files /dev/null and b/fuzzers/Peach/Agent/util.pyc differ diff --git a/fuzzers/Peach/Analyzers/__init__.py b/fuzzers/Peach/Analyzers/__init__.py new file mode 100755 index 0000000..6fc5718 --- /dev/null +++ b/fuzzers/Peach/Analyzers/__init__.py @@ -0,0 +1,28 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import pit +import shark +import stringtoken +import xml +import binary +import asn1 + +from xml import XmlAnalyzer + +# Alias default analyzers +XmlAnalyzer = xml.XmlAnalyzer +Asn1Analyzer = asn1.Asn1Analyzer +BinaryAnalyzer = binary.Binary +PitXmlAnalyzer = pit.PitXmlAnalyzer +WireSharkAnalyzer = shark.WireSharkAnalyzer +StringTokenAnalyzer = stringtoken.StringTokenAnalyzer + +__all__ = ["xml", "shark", "stringtoken", "pit", "binary", "asn1", + "XmlAnalyzer", + "Asn1Analyzer", + "BinaryAnalyzer", + "PitXmlAnalyzer", + "WireSharkAnalyzer", + "StringTokenAnalyzer" +] diff --git a/fuzzers/Peach/Analyzers/__init__.pyc b/fuzzers/Peach/Analyzers/__init__.pyc new file mode 100644 index 0000000..d0391bd Binary files /dev/null and b/fuzzers/Peach/Analyzers/__init__.pyc differ diff --git a/fuzzers/Peach/Analyzers/asn1.py b/fuzzers/Peach/Analyzers/asn1.py new file mode 100755 index 0000000..b1f2516 --- /dev/null +++ b/fuzzers/Peach/Analyzers/asn1.py @@ -0,0 +1,173 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import sys + +from Peach.analyzer import * +from Peach.Engine.dom import * +from Peach.Engine.common import * + +try: + from pyasn1.type import univ + import pyasn1.codec.ber.decoder + import pyasn1.codec.cer.decoder + import pyasn1.codec.der.decoder + + import pyasn1.codec.ber.encoder + import pyasn1.codec.cer.encoder + import pyasn1.codec.der.encoder + +except: + #raise PeachException("Error loading pyasn1 library. This library\ncan be installed from the dependencies folder.\n\n") + pass + + +class Asn1Analyzer(Analyzer): + """ + Produces data models or peach pits from XML documents. + """ + + #: Does analyzer support asDataElement() + supportDataElement = True + #: Does analyzer support asCommandLine() + supportCommandLine = False + #: Does analyzer support asTopLevel() + supportTopLevel = True + + def __init__(self): + pass + + def analyzeAsn1(self, codec, data): + + decoder = eval("pyasn1.codec.%s.decoder" % codec) + + asn1Obj = decoder.decode(data)[0] + return self.Asn12Peach(codec, asn1Obj) + + def Asn12Peach(self, codec, asn1Obj): + + obj = Asn1Type(None, None) + obj.asn1Type = asn1Obj.__class__.__name__ + obj.encodeType = codec + obj.asnTagSet = None #asn1Obj._tagSet + obj.asn1Spec = None # asn1Obj._asn1Spec + + if hasattr(asn1Obj, "_value"): + value = asn1Obj._value + obj.objType = type(value) + + if type(value) == long or type(value) == int: + n = Number(None, None) + n.defaultValue = str(value) + n.size = 32 + + obj.append(n) + + elif type(value) == str: + # Could be blob or string...hmmm + + # Sometimes we have ASN.1 inside of ASN.1 + # most common for OctetString type + if asn1Obj.__class__.__name__ == 'OctetString': + try: + decoder = eval("pyasn1.codec.%s.decoder" % codec) + subAsn1 = decoder.decode(asn1Obj._value)[0] + + child = self.Asn12Peach(codec, subAsn1) + b = Block(None, None) + b.append(child) + + except: + b = Blob(None, None) + b.defaultValue = value + + else: + b = Blob(None, None) + b.defaultValue = value + + obj.append(b) + + elif type(value) == tuple: + # Probably and ObjectIdentifier! + + if asn1Obj.__class__.__name__ == 'ObjectIdentifier': + oid = [] + for i in value: + oid.append(str(i)) + + b = String(None, None) + b.defaultValue = ".".join(oid) + + obj.append(b) + + elif asn1Obj.__class__.__name__ == 'BitString': + # Make this a blob + b = Blob(None, None) + + encoder = eval("pyasn1.codec.%s.encoder" % codec) + b.defaultValue = encoder.encode(asn1Obj)[4:] + + obj.append(b) + + else: + print("UNKNOWN TUPLE TYPE") + print(asn1Obj.__class__.__name__) + print(value) + raise Exception("foo") + + if hasattr(asn1Obj, "_componentValues"): + for c in asn1Obj._componentValues: + child = self.Asn12Peach(codec, c) + obj.append(child) + + return obj + + def asDataElement(self, parent, args, dataBuffer): + """ + Called when Analyzer is used in a data model. + + Should return a DataElement such as Block, Number or String. + """ + + dom = self.analyzeAsn1("der", dataBuffer) + + # Replace parent with new dom + + dom.name = parent.name + parentOfParent = parent.parent + + indx = parentOfParent.index(parent) + del parentOfParent[parent.name] + parentOfParent.insert(indx, dom) + + # now just cross our fingers :) + + def asCommandLine(self, args): + """ + Called when Analyzer is used from command line. Analyzer + should produce Peach PIT XML as output. + """ + + raise Exception("asCommandLine not supported (yet)") + + #try: + # inFile = args["xmlfile"] + # outFile = args["out"] + #except: + # raise PeachException("XmlAnalyzer requires two parameters, xmlfile and out.") + # + #xml = _Xml2Peach().xml2Peach("file:"+inFile) + # + #fd = open(outfile, "wb+") + #fd.write(xml) + #fd.close() + + def asTopLevel(self, peach, args): + """ + Called when Analyzer is used from top level. + + From the top level producing zero or more data models and + state models is possible. + """ + raise Exception("asTopLevel not supported") diff --git a/fuzzers/Peach/Analyzers/asn1.pyc b/fuzzers/Peach/Analyzers/asn1.pyc new file mode 100644 index 0000000..0e96e07 Binary files /dev/null and b/fuzzers/Peach/Analyzers/asn1.pyc differ diff --git a/fuzzers/Peach/Analyzers/binary.py b/fuzzers/Peach/Analyzers/binary.py new file mode 100755 index 0000000..228e6b4 --- /dev/null +++ b/fuzzers/Peach/Analyzers/binary.py @@ -0,0 +1,224 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +from Peach.Engine.dom import * +from Peach.Engine.common import * +from Peach.analyzer import Analyzer + + +class _Node(object): + def __init__(self, type, startPos, endPos, value): + self.type = type + self.value = value + self.startPos = startPos + self.endPos = endPos + + +class Binary(Analyzer): + """ + Analyzes binary blobs to build data models + + 1. Locate strings, char & wchar + a. Analyze string for XML + b. UTF8/UTF16 and byte order marks + 2. Find string lengths (relations!) --> Would also give us endian + 3. Compressed segments (zip, gzip) + """ + + supportParser = False + supportDataElement = True + supportCommandLine = False + supportTopLevel = True + + def locateStrings(self, data): + maxLooseStrings = 200 + strs = [] + cnt = 0 + for match in re.finditer(r"[\n\r\ta-zA-Z0-9,./<>\?;':\"\[\]\\\{\}|=\-+_\)\(*&^%$#@!~`]{4,}\0?", data): + strs.append(_Node('str', match.start(), match.end(), match.group(0))) + cnt += 1 + if cnt > maxLooseStrings: + break + if cnt < maxLooseStrings: + return strs + strs = [] + cnt = 0 + for match in re.finditer(r"[a-zA-Z0-9,./\?;':\"\\\-_&%$@!]{5,}\0?", data): + strs.append(_Node('str', match.start(), match.end(), match.group(0))) + cnt += 1 + if cnt > maxLooseStrings: + break + if cnt < maxLooseStrings: + return strs + strs = [] + cnt = 0 + for match in re.finditer(r"[a-zA-Z0-9,.?:\"&@!]{5,}\0?", data): + strs.append(_Node('str', match.start(), match.end(), match.group(0))) + cnt += 1 + if cnt > maxLooseStrings: + break + if cnt < maxLooseStrings: + return strs + strs = [] + cnt = 0 + for match in re.finditer(r"[a-zA-Z0-9.\"]{6,}\0?", data): + strs.append(_Node('str', match.start(), match.end(), match.group(0))) + cnt += 1 + if cnt > maxLooseStrings: + break + if cnt < maxLooseStrings: + return strs + strs = [] + cnt = 0 + for match in re.finditer(r"[a-zA-Z0-9.\"]{10,}\0?", data): + strs.append(_Node('str', match.start(), match.end(), match.group(0))) + cnt += 1 + if cnt > maxLooseStrings: + break + if cnt < maxLooseStrings: + return strs + return [] + + def locateStringLengths(self, strs, data): + lengths = {} + for s in strs: + (lengthL16, lengthL32, lengthB16, lengthB32) = 0, 0, 0, 0 + length = len(s.value) + try: + lengthL16 = struct.pack("H", length) + lengthB16 = struct.pack("!H", length) + except: + pass + lengthL32 = struct.pack("I", length) + lengthB32 = struct.pack("!I", length) + first2 = data[s.startPos - 2:s.startPos] + first4 = data[s.startPos - 4:s.startPos] + # Always check larger # first in case 0x00AA :) + if first4 == lengthL32: + obj = _Node('len', s.startPos - 4, s.startPos, length) + obj.endian = 'little' + obj.lengthOf = s + obj.size = 32 + lengths[s] = obj + elif first4 == lengthB32: + obj = _Node('len', s.startPos - 4, s.startPos, length) + obj.endian = 'big' + obj.lengthOf = s + obj.size = 32 + lengths[s] = obj + elif first2 == lengthL16: + obj = _Node('len', s.startPos - 2, s.startPos, length) + obj.endian = 'little' + obj.lengthOf = s + obj.size = 16 + lengths[s] = obj + elif first2 == lengthB16: + obj = _Node('len', s.startPos - 2, s.startPos, length) + obj.endian = 'big' + obj.lengthOf = s + obj.size = 16 + lengths[s] = obj + return lengths + + def locateCompressedSegments(self, data): + pass + + def analyzeBlob(self, data): + """ + Will analyze a binary blob and return a Block data element containing the split up blob. + """ + # 1. First we locate strings + strs = self.locateStrings(data) + # 2. Now we check for lengths + lengths = self.locateStringLengths(strs, data) + # 3. Now we need to build up our DataElement DOM + root = Block(None, None) + pos = 0 + for s in strs: + # Check and see if we need a Blob starter + startPos = s.startPos + if s in lengths: + startPos = lengths[s].startPos + if startPos > pos: + # Need a Blob filler + b = Blob(None, None) + b.defaultValue = data[pos:startPos] + root.append(b) + # Now handle what about length? + stringNode = String(None, None) + numberNode = None + if s in lengths: + l = lengths[s] + numberNode = Number(None, None) + numberNode.size = l.size + numberNode.endian = l.endian + numberNode.defaultValue = str(l.value) + root.append(numberNode) + relation = Relation(None, None) + relation.type = "size" + relation.of = stringNode.name + numberNode.relations.append(relation) + relation = Relation(None, None) + relation.type = "size" + relation.From = numberNode.name + stringNode.relations.append(relation) + if s.value[-1] == "\0": + stringNode.defaultValue = s.value[:-1] + stringNode.nullTerminated = True + else: + stringNode.defaultValue = s.value + root.append(stringNode) + pos = s.endPos + + # Finally, we should see if we need a trailing blob... + if pos < (len(data) - 1): + b = Blob(None, None) + b.defaultValue = data[pos:] + root.append(b) + return root + + def asDataElement(self, parent, args, dataBuffer): + """ + Called when Analyzer is used in a data model. + Should return a DataElement such as Block, Number or String. + """ + dom = self.analyzeBlob(dataBuffer) + # Replace parent with new dom + parentOfParent = parent.parent + dom.name = parent.name + indx = parentOfParent.index(parent) + del parentOfParent[parent.name] + parentOfParent.insert(indx, dom) + + def asCommandLine(self, args): + """ + Called when Analyzer is used from command line. + Analyzer should produce Peach PIT XML as output. + """ + raise Exception("asCommandLine not supported") + + def asTopLevel(self, peach, args): + """ + Called when Analyzer is used from top level. + From the top level producing zero or more data models and state models is possible. + """ + raise Exception("asTopLevel not supported") + + +if __name__ == "__main__": + + from lxml import etree + + data = None + with open("sample.bin", "rb+") as fo: + data = fo.read() + dom = Binary().analyzeBlob(data) + data2 = dom.getValue() + + if data2 == data: + print("THEY MATCH") + else: + print(repr(data2)) + print(repr(data)) + + dom.toXmlDom(etree.XML("", {})).write(sys.stdout, pretty_print=True) diff --git a/fuzzers/Peach/Analyzers/binary.pyc b/fuzzers/Peach/Analyzers/binary.pyc new file mode 100644 index 0000000..77497d2 Binary files /dev/null and b/fuzzers/Peach/Analyzers/binary.pyc differ diff --git a/fuzzers/Peach/Analyzers/pit.py b/fuzzers/Peach/Analyzers/pit.py new file mode 100755 index 0000000..b79d91e --- /dev/null +++ b/fuzzers/Peach/Analyzers/pit.py @@ -0,0 +1,26 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +from Peach.Engine.parser import * +from Peach.Engine.common import * +from Peach.analyzer import * + + +class PitXmlAnalyzer(Analyzer): + """ + Analyzers produce data and state models. Examples of analyzers would be the parsing + of PeachPit XML files, tokenizing a string, building a data model based on XML file, etc. + """ + + supportParser = True + + def __init__(self): + self.configs = None + + def asParser(self, uri): + """ + Called when Analyzer is used as default Pit parser. + Should produce a Peach DOM. + """ + return ParseTemplate(self.configs).parse(uri) + diff --git a/fuzzers/Peach/Analyzers/pit.pyc b/fuzzers/Peach/Analyzers/pit.pyc new file mode 100644 index 0000000..f1ad83a Binary files /dev/null and b/fuzzers/Peach/Analyzers/pit.pyc differ diff --git a/fuzzers/Peach/Analyzers/shark.py b/fuzzers/Peach/Analyzers/shark.py new file mode 100755 index 0000000..f5ae491 --- /dev/null +++ b/fuzzers/Peach/Analyzers/shark.py @@ -0,0 +1,1144 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import re +import sys +import struct + +from Peach.analyzer import * +from Peach.Engine.common import * + +from lxml import etree + + +class WireSharkAnalyzer(Analyzer): + """ + Analyzers produce data and state models. Examples of analyzers would be + the parsing of Peach PIT XML files, tokenizing a string, building a data + model based on XML file, etc. + """ + + #: Does analyzer support asCommandLine() + supportCommandLine = True + + def asParser(self, uri): + """ + Called when Analyzer is used as default PIT parser. + + Should produce a Peach DOM. + """ + raise Exception("asParser not supported") + + def asDataElement(self, parent, args, dataBuffer): + """ + Called when Analyzer is used in a data model. + + Should return a DataElement such as Block, Number or String. + """ + raise Exception("asDataElement not supported") + + def asCommandLine(self, args): + """ + Called when Analyzer is used from command line. Analyzer + should produce Peach PIT XML as output. + """ + + inFile = args["in"] + if args.has_key("proto"): + proto = args["proto"] + else: + proto = None + + if args.has_key("out"): + outFile = args["out"] + else: + outFile = None + + xml = DoTheShark(inFile, proto) + + if outFile is not None: + fd = open(outFile, "wb+") + fd.write(xml) + fd.close() + else: + print(xml) + + def asTopLevel(self, peach, args): + """ + Called when Analyzer is used from top level. + + From the top level producing zero or more data models and + state models is possible. + """ + raise Exception("asTopLevel not supported") + + +def debug(str): + sys.stderr.write("debug: %s\n" % str) + +#pdml/packet/proto +# method + +# 1. Check for children, if we have them make block and recurse +# 2. Look for value show attribute and see if it contains a sub portion of the +# data (treat this different) +# 3. Look for items labled "len" or "length" and try and match them up +# 4. Optionally look at RFC's and try and match things up + +class PeachShark(object): + def __init__(self): + self._currentPos = 0 + self._regexIp = re.compile("^\d+\.\d+\.\d+\.\d+$") + self._regexFlagBit1 = re.compile("^(\.*)(\d+)(\.*)") + self._relations = {} + self._findStack = [] + self._templates = [] + + def inStr(self, str, values): + str = str.lower() + for value in values: + if str.find(value) > -1: + #debug("found str") + return True + + #debug("No: %s" % str) + return False + + + def findSizeRelation(self, sizeNode, node): + # We know two things: + # + # 1. Sizes always come first + # 2. It will be the size of something :P + # + + # Prevent infinit looping + if node in self._findStack: + return None + self._findStack.append(node) + + size = self.findSizeGetSize(sizeNode) + + # Search from us forward + sibling = sizeNode.getnext() + while sibling is not None: + checkSize = self._getNodeSize(sibling) + + if checkSize == size: + return sibling + + sibling = sibling.getnext() + + # That didn't work look from parent + for child in node.iterchildren(): + if child != sizeNode: + checkSize = self._getNodeSize(child) + if checkSize == size: + return child + + ret = self.findSizeRelation(sizeNode, child) + if ret is not None: + return ret + + # Search from parent forward + sibling = node.getnext() + while sibling is not None: + if sibling.get('size') is None: + sibling = sibling.getnext() + continue + + checkSize = int(sibling.get('size')) + + if checkSize == size: + return sibling + + ret = self.findSizeRelation(sizeNode, sibling) + if ret is not None: + return ret + + sibling = sibling.getnext() + + # !!!TODO!!! Sometimes length can indicate the rest of our siblings + # but they may not be in a block of there own. + # -> Detect + # -> Force into a bock + # + #sibling = node.getprevious() + #while sibling != None: + # sizeUptoMe += int(sibling.get('size')) + # sibling = sibling.getprevious() + # + ## This is good, but not what we want! + #if (parentSize - sizeUptoMe) == size: + # return True + #else: + # debug("Nope: ParentSize: %d - SizeUptoMe: %d -- Size: %d" % (parentSize, sizeUptoMe, size)) + + return None + + def findSizes(self, nodes): + """ + Find nodes that could be sizes or lengths. + """ + + if nodes is None: + return [] + + findValues = ["length", "size"] + sizeNodes = [] + + for node in nodes: + if node is None: + continue + + name = node.get('name') + show = node.get('show') + showName = node.get('showname') + + if self.inStr(show, findValues) or self.inStr(showName, findValues) or self.inStr(name, findValues): + #debug("findSizes(): Found size: %s:%s" % (split_ns(node.tag)[1], name)) + sizeNodes.append(node) + + for n in self.findSizes(node.iterchildren()): + sizeNodes.append(n) + + return sizeNodes + + def findSizeGetSize(self, node): + """ + Take a size/length node and figure out it's value. + """ + + ret = None + if node.get('show') is not None and len(node.get('show')) > 0: + try: + return int(node.get('show')) + except: + pass + + if node.get('value') is not None and len(node.get('value')) > 0: + try: + return int(node.get('value'), 16) + except: + pass + + try: + return int(re.search(r"(\d+)", node.get('show')).group(1)) + + except: + pass + + debug(str("Failed on %s:%s" % (node.get('name'), split_ns(node.tag)[1]))) + debug(str("Show: " + node.get('show'))) + debug(str("Value: " + node.get('value'))) + raise Exception("OMG!!") + + + def findSizeRelationCheckSelf(self, node): + """ + Check if parent - me + prior siblings == size + """ + + parentSize = self._getNodeSize(node.getparent()) + sizeUptoMe = self._getNodeSize(node) + size = self.findSizeGetSize(node) + #debug("%d:%d" % (parentSize,size)) + + # If our parent is the size we are indicating + # then return True! + if parentSize == size: + return True + + return False + + def findSizeRelations(self, nodes): + """ + Find and resolve size relations. + """ + + node0_name = split_ns(nodes[0].tag)[1] + debug("Finding relations: " + node0_name) + if node0_name == 'proto': + parentNode = nodes[0] + else: + parentNode = nodes[0].getparent() + + for node in self.findSizes(nodes): + #debug("findSizeRelations()... %s:%s" % (split_ns(node.tag)[1], node.get('name'))) + + if self.findSizeRelationCheckSelf(node): + debug("findSizeRelations: Found relation to parent: %s and %s" % ( + node.get('name'), node.getparent().get('name'))) + self._relations[node] = node.getparent() + + else: + ret = self.findSizeRelation(node, parentNode) + if ret is not None: + debug("findSizeRelations: Found relation: %s and %s" % ( + node.get('name'), ret.get('name'))) + self._relations[node] = ret + + + def removeTextNodes(self, node): + node.text = node.tail = None + for child in node.iterdescendants(): + child.text = child.tail = None + + def htmlEncode(self, strInput, default=''): + + if strInput is None or len(strInput) == 0: + strInput = default + + if strInput is None or len(strInput) == 0: + return '' + + # Allow: a-z A-Z 0-9 SPACE , . + # Allow (dec): 97-122 65-90 48-57 32 44 46 + + out = '' + for char in strInput: + c = ord(char) + if ((97 <= c <= 122) or + (65 <= c <= 90 ) or + (48 <= c <= 57 ) or c == 32 or c == 44 or c == 46): + out += char + else: + out += "&#%d;" % c + + return out + + def getNodeName(self, node): + """ + Check for name and show attributes. Figureout a possible name + for this node. + """ + + if node.get('name') is not None: + name = node.get('name') + + if len(name.strip()) < 1: + return None + + # Sounds good on paper, but causes problems + #try: + # name = name[name.rindex('.')+1:] + #except: + # pass + + return name.replace(' ', '_').replace('.', '_') + + return None + + def _getNodeSize(self, node): + if node.get('size') is None: + size = 0 + + for child in node.iterchildren(): + if child.get("size") is not None: + size += int(child.get('size')) + else: + size = int(node.get('size')) + + return size + + def _getNodePosition(self, node): + if node.get("pos") is None: + pos = 0 + + for child in node.iterchildren(): + if child.get("pos") is not None: + pos = int(child.get('pos')) + break + + else: + pos = int(node.get('pos')) + + return pos + + def peachNode(self, node, tabCount, size, parent): + + tabs = '\t' * tabCount + name = node.get('name') + show = node.get('show') + showName = node.get('showname') + size = self._getNodeSize(node) + pos = self._getNodePosition(node) + + ret = '' + nodeName = self.getNodeName(node) + if nodeName is not None: + nodeName = 'name="%s"' % nodeName + else: + nodeName = '' + + debug("peachNode: " + name) + + # This should be prior sibling, not parent!! + if parent is not None: + parentPos = self._getNodePosition(parent) + parentSize = self._getNodeSize(parent) + else: + parentPos = -1 + parentSize = -1 + + self._currentPos = pos + + if size == 0: + #print "Size == 0: ", node.get('size') + return '', 0, 0 + + if tabCount == 1: + # Do this just once + self.findSizeRelations([node]) + + if name.find('-'): + newName = '' + for n in name.split('-'): + newName += n[:1].upper() + n[1:] + name = newName + + self._groupName = name[:1].upper() + name[1:] + self._genName = name[:1].upper() + name[1:] + self._templates.append(self._genName) + + name = node.get('name') + + #if len(node) > 0 and not (self._getNodeSize(node[0]) == size and self._getNodePosition(node[0]) == pos): + if len(node) > 0: + + curPos = pos + sizeOfChildren = 0 + + if tabCount == 1: + if len(showName) > 1: ret += tabs + '\n' % showName + ret += tabs + '\n' % self._genName + else: + ret += tabs + '\n' % nodeName + + for child in node.iterchildren(): + + if child.get("value") is None: + continue + + sibling = child.getnext() + if sibling is not None: + siblingSize = self._getNodeSize(sibling) + siblingPos = self._getNodePosition(sibling) + childSize = self._getNodeSize(child) + childPos = self._getNodePosition(child) + + if siblingPos == childPos and siblingSize < childSize and sibling.get("value") is not None: + debug("Skipping " + child.get('name') + " same as " + sibling.get("name")) + ret += tabs + "\t\n" % child.get('name') + continue + + childShow = child.get('show') + + #print "Child: %s" % childShow + + childRet, childSize, childPos = self.peachNode(child, tabCount + 1, size, node) + + childPos = int(childPos) + childSize = int(childSize) + + #print "Child: %s, %d, %d" % (childShow, childPos, childSize) + + if childSize == 0: + if len(childRet) > 0: + ret += childRet + continue + + if int(childPos) == pos + int(sizeOfChildren): + ret += childRet + + else: + valueHex = node.get('value') + value = self.hex2bin(valueHex) + + # Locate "extra" bits not covered by children and + # add them in. Maybe we should fuzz this too? + if curPos < childPos: + if len(valueHex) >= (childPos - pos) * 2: + ret += tabs + "\t\n" + ret += tabs + "\t\n" % ( + nodeName, valueHex[(curPos - pos) * 2:(childPos - pos) * 2]) + else: + ret += tabs + "\t\n" + ret += tabs + "\t\n\n" % ( + nodeName, ('00' * ((childPos - pos) - (curPos - pos)))) + + ret += childRet + + sizeOfChildren += childSize + curPos = childPos + childSize + + #if sizeOfChildren != size: + # raise Exception("Size not match %d != %d" % (size, sizeOfChildren)) + + + # Dunno if we need this anymore + if tabCount == 1: + name = self._genName[3:] + ret += tabs + '\n' + else: + ret += tabs + '\n' + + else: + + type = self.figureType(node) + valueHex = node.get('value') + show = node.get('show') + showName = node.get('showname') + if len(showName) < 1: + showName = show + value = self.hex2bin(valueHex) + + if type != 'bit_flag': + if node.previousSibling is not None: + previousSiblingPos = self._getNodePosition(node.previousSibling) + previousSiblingSize = self._getNodeSize(node.previousSibling) + + if pos == previousSiblingPos and size == previousSiblingSize: + debug("node same position and size of previousSibling") + return tabs + "\n\n" % node.get('name'), 0, 0 + #return '', 0, 0 + + #ret += " [%s] " % type + + if len(showName) > 0: + ret += tabs + '\n' % showName + + if type.find('str') > -1: + # TODO: We should take into account that this string + # may be fixed in size as well as different lengths. + + if len(valueHex) == size * 2: + str = 'valueType="hex" value="%s"' % valueHex + else: + str = 'value="%s"' % value + + if type == 'str': + # regular string + ret += tabs + '\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'p_str': + # Padded string + ret += tabs + '\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'w_str': + # wchar string + ret += tabs + '\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'p_w_str': + # padded wchar string + ret += tabs + '\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'byte' or type == 'uint8': + ret += tabs + '\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'int16': + ret += tabs + ('\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'uint16': + ret += tabs + ('\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'n_int16': + ret += tabs + ( + '\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'n_uint16': + ret += tabs + ( + '\n' + tabs + '\n' + else: + ret += ' />\n' + + + elif type == 'int32': + ret += tabs + ('\n' + tabs + '\n' + else: + ret += ' />\n' + elif type == 'uint32': + ret += tabs + ('\n' + tabs + '\n' + else: + ret += ' />\n' + elif type == 'n_int32': + ret += tabs + ( + '\n' + tabs + '\n' + else: + ret += ' />\n' + elif type == 'n_uint32': + ret += tabs + ( + '\n' + tabs + '\n' + else: + ret += ' />\n' + + elif type == 'blob': + ret += tabs + '\n' % (nodeName, valueHex) + + elif type == 'ip': + #ret += tabs + "WithDefault(%s.addNewGroup(), '%s', BadIpAddress()).setTransformer(Ipv4StringToOctet()),\n" % ( self._groupName, show ) + ret += tabs + "\n" + ret += tabs + '\n' % (nodeName, show) + ret += tabs + '\t\n' + ret += tabs + '\n' + #raise Exception("TODO") + + elif type == 'n_ip': + #ret += tabs + "WithDefault(%s.addNewGroup(), '%s', BadIpAddress()).setTransformer(Ipv4StringToNetworkOctet()),\n" % ( self._groupName, show ) + ret += tabs + "\n" + ret += tabs + '\n' % (nodeName, show) + ret += tabs + '\t\n' + ret += tabs + '\n' + #raise Exception("TODO") + + elif type == 'bit_flag': + # TODO: Handle flags! + + if node.previousSibling is None: + # First flag, lets do it! + + nodeNames = [] + offsets = [] + bits = [] + shownames = [] + length = 0 + + offset, bit = self.getFlagBits(node) + length += bit + + offsets.append(offset) + bits.append(bit) + shownames.append(showName) + + nodeName = self.getNodeName(node) + if nodeName is not None: + nodeNames.append('name="%s"' % nodeName) + else: + nodeNames.append('') + + sibling = node.getnext() + while sibling is not None: + offset, bit = self.getFlagBits(sibling) + + length += bit + + offsets.append(offset) + bits.append(bit) + shownames.append(sibling.get('showname')) + + nodeName = self.getNodeName(sibling) + if nodeName is not None: + nodeNames.append('name="%s"' % nodeName) + else: + nodeNames.append('') + + sibling = sibling.getnext() + + # Now output Flags generator + + # make sure length is multiple of 2 + while length % 2 != 0: + length += 1 + + parentName = self.getNodeName(node.getparent()) + if parentName is not None: + ret += tabs + '\n' % (parentName, length) + else: + ret += tabs + '\n' % length + + for i in range(len(offsets)): + ret += tabs + '\t\n' % (nodeNames[i], offsets[i], bits[i]) + + ret += tabs + "\n" + + else: + raise Exception("Unknown type: %s" % type) + + return ret + '\n', size, pos + + def hex2bin(self, h): + """ + Convert hex string to binary string + """ + ret = '' + for cnt in range(0, len(h), 2): + ret += chr(int(h[cnt:cnt + 2], 16)) + + return ret + + def isWideString(self, str): + """ + Is this a wchar string? + """ + + # Wide chars should always have even string + # length + if len(str) < 4 or len(str) % 2 != 0: + return False + + for i in range(0, len(str), 2): + c = str[i] + c2 = str[i + 1] + + # Assume we don't actually have characters that + # require two bytes to display. So second byte + # should always be NULL + if c2 != '\0': + return False + + o = ord(c) + if o < 32 or o > 126: + if c == '\n' or c == '\r' or c == '\t': + continue + + return False + + return True + + def isPaddedWideString(self, str): + """ + Is this a wchar string with nulls at the end? + """ + + # Wide chars should always have even string + # length + if len(str) < 4 or len(str) % 2 != 0: + return False + + if str[-1] != '\0' or str[-2] != '\0': + return False + + for i in range(0, len(str), 2): + c = str[i] + c2 = str[i + 1] + + # Assume we don't actually have characters that + # require two bytes to display. So second byte + # should always be NULL + if c2 != '\0': + return False + + o = ord(c) + if o < 32 or o > 126: + if c == '\n' or c == '\r' or c == '\t' or c == '\0': + continue + + return False + + return True + + def isString(self, str): + """ + Is this a char string? + """ + + if len(str) < 3: + return False + + for c in str: + o = ord(c) + if o < 32 or o > 126: + if c == '\n' or c == '\r' or c == '\t': + continue + + return False + + #debug("isString('%s'): True" % str) + + return True + + def isPaddedString(self, str): + """ + Is this a char string with nulls at the end? + """ + + if len(str) < 3: + #debug("to small") + return False + + if str[-1] != '\0': + #debug("no null term") + return False + + for c in str: + o = ord(c) + if o < 32 or o > 126: + if c == '\n' or c == '\r' or c == '\t' or c == '\0': + continue + + debug("odd char [%d]" % o) + return False + + return True + + def getFlagBits(self, node): + """ + Checks out the showname field to see if we can determin + the number of bits this flag is and it's offset in the packet. + """ + # .... ...1 .... .... = Recursion desired: Do query recursively + + show = node.get('showname') + + #debug("flag str (initial): [%s]" % show) + + # remove spaces + show = show.replace(' ', '') + + # Get dots and numbers + try: + result = self._regexFlagBit1.match(show) + firstDots = result.group(1) + number = result.group(2) + lastDots = result.group(3) + + offset = len(firstDots) + bits = len(number) + + #debug("flag str: [%s]" % show) + #debug("offset: %d - bits: %s - remander: %d" % (offset, bits, len(lastDots))) + + if (len(firstDots) + len(number) + len(lastDots)) % 2 != 0: + debug( + "getFlagBits(): Something fishy about this!!! %d" % (len(firstDots) + len(number) + len(lastDots))) + + return offset, bits + + except: + return -1, 1 + + def figureType(self, node): + + # Try and figure out our type, number, string, etc. + + show = node.get('show') + showName = node.get('showname') + value = self.hex2bin(node.get('value')) + valueHex = node.get('value') + size = self._getNodeSize(node) + pos = self._getNodePosition(node) + parentPos = self._getNodePosition(node.getparent()) + parentSize = self._getNodeSize(node.getparent()) + + #print "Show: [%s], valueHex: [%s], size: %d" % (show, valueHex, size) + + if showName is not None and showName.find("Data:") == 0: + return 'blob' + + # If just compar pos == parentPos we will get the first + # child. Should also check next child and size + if pos == parentPos and parentSize == size: + # A flag will have the same position as it's parent + # parent will have size of 1 + #print "bit_flag: pos: %d parentPos: %d" % (pos, parentPos) + #debug("show: %s - showName: %s" % (show, showName)) + + (p, l) = self.getFlagBits(node) + + if p > -1: + return 'bit_flag' + + if len(value) > 2 and value.isalnum() and not show.isdigit(): + return 'str' + + elif self._regexIp.match(show) is not None and size == 4: + # ip address + ip1, ip2, ip3, ip4 = show.split('.') + + #debug("ip: %s - %s - %s - %s" % (show, ip1, valueHex[len(valueHex)-2:], valueHex)) + if int(ip1) == int(valueHex[6:], 16) and int(ip2) == int(valueHex[4:6], 16) and int(ip3) == int( + valueHex[2:4], 16) and int(ip4) == int(valueHex[:2], 16): + return 'n_ip' + + if int(ip1) == int(valueHex[:2], 16): + return 'ip' + + elif show[:2] == "0x": + + # Figure if we are little or big endian + + showHex = show[2:] + + if showHex == valueHex or int(showHex, 16) == int(valueHex, 16): + # little + if size == 1: + return 'uint8' + + if size == 2: + return 'uint16' + + elif size == 4: + return 'uint32' + + elif size == 8: + return 'uint64' + + #debug("bigBalue: [%s][%s][%s]" % (valueHex, show, repr(value))) + + if len(value) == 2: + format = '!H' + elif len(value) == 4: + format = '!I' + else: + debug("There's an issue with bigValue: [%s][%s][%s]" % (valueHex, show, repr(value))) + if len(value) > 4: + value = value[:4] + format = '!I' + else: + value = value.ljust(4) + format = '!I' + + bigValue = struct.unpack(format, value)[0] + if int(bigValue) == int(showHex, 16): + if size == 1: + return 'n_uint8' + + if size == 2: + return 'n_uint16' + + elif size == 4: + return 'n_uint32' + + elif size == 8: + return 'n_uint64' + + + elif not show.isdigit() and self.isWideString(value): + return 'w_str' + + elif not show.isdigit() and self.isPaddedWideString(value): + return 'p_w_str' + + elif not show.isdigit() and self.isString(value): + return 'str' + + elif not show.isdigit() and self.isPaddedString(value): + return 'p_str' + + elif show.isdigit() or (len(showName) == 0 and size <= 4): + + cnt = len(valueHex) + + if size == 1: + # Byte I bet + return 'byte' + + elif size == 2: + # Maybe 16 bit int? + + try: + show = int(show) + except: + show = 0 + + try: + val = struct.unpack('H', value)[0] + if int(val) == show: + return 'uint16' + + val = struct.unpack('h', value)[0] + if val == show: + return 'int16' + + val = struct.unpack('!H', value)[0] + if val == show: + return 'n_int16' + + val = struct.unpack('!h', value)[0] + if val == show: + return 'n_uint16' + + except struct.error: + pass + + return 'n_uint16' + + elif size == 4: + # Maybe 32 bit int? + if struct.unpack('I', value)[0] == show: + return 'uint32' + + elif struct.unpack('i', value)[0] == show: + return 'int32' + + elif struct.unpack('!I', value)[0] == show: + return 'n_int32' + + return 'n_uint32' + + return 'blob' + + def figureOutPublisher(self, doc): + """ + Look for udp or tcp protocol and pull out + address and port. + """ + + defaultPublisher = "\t" + + nodes = doc.xpath('descendant::proto[@name="ip"]') + if len(nodes) == 0: + return defaultPublisher + + nodeIp = nodes[0] + + nodes = doc.xpath('descendant::proto[@name="tcp"]') + if len(nodes) == 0: + nodes = doc.xpath('descendant::proto[@name="udp"]') + + if len(nodes) == 0: + return defaultPublisher + + nodeProt = nodes[0] + + m = re.search("Dst: ([^\s(]*)", str(nodeIp.get('showname'))) + ip = m.group(1) + + ret = '' + for child in nodeProt.iterchildren(): + if child.get('name') == 'udp.dstport': + ret = """ + + + + + """ % (ip, str(child.get('show'))) + + if child.get('name') == 'tcp.dstport': + ret = """ + + + + + """ % (ip, str(child.get('show'))) + + return ret + +# ######################################################################## + +def DoTheShark(fileName, proto): + if proto == 2: + # print out the protocols + print("Select one of the following protocols:\n") + + doc = etree.parse(fileName) + nodes = doc.xpath('descendant::proto') + + for n in nodes: + print("\t%s" % n.get('name')) + + raise PeachException("") + + name = fileName + doc = etree.parse(fileName) + + node = doc.xpath('descendant::proto[@name="%s"]' % proto)[0] + + shark = PeachShark() + shark.removeTextNodes(node.getparent()) + + ret = """ + + + + + + + + + +""" + + sibling = node + while sibling is not None: + #shark.removeTextNodes(sibling.getparent()) + debug("Handing node: " + sibling.get('name')) + templateStr, s, p = shark.peachNode(sibling, 1, sibling.get('size'), None) + ret += templateStr + sibling = sibling.getnext() + + ret += '\t\n' + + for t in shark._templates: + ret += '\t\t\n' % t + + ret += """ + + + + %s + + + + + + + +""" % shark.figureOutPublisher(doc) + + return ret diff --git a/fuzzers/Peach/Analyzers/shark.pyc b/fuzzers/Peach/Analyzers/shark.pyc new file mode 100644 index 0000000..deed448 Binary files /dev/null and b/fuzzers/Peach/Analyzers/shark.pyc differ diff --git a/fuzzers/Peach/Analyzers/stringtoken.py b/fuzzers/Peach/Analyzers/stringtoken.py new file mode 100755 index 0000000..7a4b060 --- /dev/null +++ b/fuzzers/Peach/Analyzers/stringtoken.py @@ -0,0 +1,148 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +from Peach.Engine.dom import * +from Peach.Engine.common import * +from Peach.analyzer import * + + +class StringTokenAnalyzer(Analyzer): + """ + Produces a tree of strings based on token precidence. + """ + + supportCommandLine = False + supportDataElement = True + supportTopLevel = True + + # Tokens that group parts of a string + pairs = [ + [u'{', u'}'], + [u'(', u')'], + [u'[', u']'], + [u'<', u'>'], + ] + + # Tokens in order of precidence + tokens = [ + u'\0', u'\n', u'\r', u'<', u'>', u'?', u';', u',', u'|', u'@', u':', u'(', u')', + u'{', u'}', u'[', u']', u'/', u'\\', u'&', u'=', u' ', u'-', u'+', u'.' + ] + + def asCommandLine(self, args): + """ + Called when Analyzer is used from command line. + Analyzer should produce PeachPit XML as output. + """ + raise NotImplementedError("StringTokenAnalyzer asCommandLine is not supported.") + + def asTopLevel(self, peach, args): + """ + Called when Analyzer is used from top level. + From the top level producing zero or more data models and state models is possible. + """ + raise NotImplementedError("StringTokenAnalyzer asTopLevel is not supported.") + + def asDataElement(self, parent, args, data): + """ + Called when Analyzer is used in a data model. Should return a DataElement. + """ + if not isinstance(parent, String): + raise PeachException("StringTokenAnalyzer can only be attached to elements.") + self.stringType = parent.type + dom = self.tokenize_string(data, None) + if parent.nullTerminated: + blob = Blob(None, None) + blob.defaultValue = "\x00" if parent.type is "wchar" else "\x00\x00" + dom.append(blob) + # replace parent with new dom + dom.name = parent.name + i = parent.parent.index(parent) + del parent.parent[parent.name] + parent.parent.insert(i, dom) + + def _new_string_element(self, value, parent=None): + s = String(None, parent) + s.type = self.stringType + s.defaultValue = value + try: + _ = int(s.defaultValue) + hint = Hint("NumericalString", s) + hint.value = "true" + s.hints.append(hint) + except ValueError: + pass + return s + + def _split(self, string, token): + """ + A version of split that also returns the tokens. + """ + # return re.split('(\%c)' % token, string) + pos = string.find(token) + parts = [] + if pos is -1: + return parts + while pos > -1: + parts.append(string[:pos]) + parts.append(string[pos:pos + 1]) + string = string[pos + 1:] + pos = string.find(token) + parts.append(string) + return parts + + def tokenize_string(self, string, tokens=None): + if string is None: + return None + tokens = self.tokens if tokens is None else tokens + parent = Block(None, None) + parent.append(self._new_string_element(string)) + for p in self.pairs: + self._pair_tree(p, parent) + for t in tokens: + self._token_tree(t, parent) + return parent + + def _pair_tree(self, p, node): + if isinstance(node, Block): + for c in node: + self._pair_tree(p, c) + return + string = node.defaultValue + index1 = string.find(p[0]) + if index1 is -1: + return + index2 = string[index1:].find(p[1]) + if index2 is -1: + return + index2 += index1 + block = Block(None, None) + pre = string[:index1] + token_start = string[index1] + middle = string[index1 + 1:index2] + token_end = string[index2] + after = string[index2 + 1:] + if len(pre): + block.append(self._new_string_element(pre)) + block.append(self._new_string_element(token_start)) + block.append(self._new_string_element(middle)) + block.append(self._new_string_element(token_end)) + if len(after): + block.append(self._new_string_element(after)) + block.name = node.name + node.parent[node.name] = block + + def _token_tree(self, token, node): + if isinstance(node, Block): + for c in node: + self._token_tree(token, c) + return + if len(node.defaultValue) < 2: + return + stuff = self._split(node.defaultValue, token) + if not len(stuff): + return + block = Block(node.name, None) + for s in stuff: + block.append(self._new_string_element(s)) + node.parent[node.name] = block diff --git a/fuzzers/Peach/Analyzers/stringtoken.pyc b/fuzzers/Peach/Analyzers/stringtoken.pyc new file mode 100644 index 0000000..4b6a4ea Binary files /dev/null and b/fuzzers/Peach/Analyzers/stringtoken.pyc differ diff --git a/fuzzers/Peach/Analyzers/xml.py b/fuzzers/Peach/Analyzers/xml.py new file mode 100755 index 0000000..6abcb52 --- /dev/null +++ b/fuzzers/Peach/Analyzers/xml.py @@ -0,0 +1,225 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +from Peach.analyzer import * +from Peach.Engine.dom import * +from Peach.Engine.common import * +from Peach.Engine.parser import PeachResolver + +from lxml import etree + + +class XmlAnalyzer(Analyzer): + """ + Produces data models or PeachPits from XML documents. + """ + + supportDataElement = True + supportCommandLine = True + supportTopLevel = True + + def __init__(self): + pass + + def asDataElement(self, parent, args, dataBuffer): + """ + Called when Analyzer is used in a data model. + Should return a DataElement such as Block, Number or String. + """ + if len(dataBuffer) == 0: + return + dom = _Xml2Dom().xml2Dom(dataBuffer) + # replace parent with new dom + dom.name = parent.name + parentOfParent = parent.parent + indx = parentOfParent.index(parent) + del parentOfParent[parent.name] + parentOfParent.insert(indx, dom) + + def asCommandLine(self, args): + """ + Called when Analyzer is used from command line. + Analyzer should produce PeachPit XML as output. + """ + try: + inFile = args["xmlfile"] + outFile = args["out"] + except: + raise PeachException("XmlAnalyzer requires two parameters, xmlfile and out.") + xml = _Xml2Peach().xml2Peach("file:" + inFile) + with open(outFile, "wb+") as fo: + fo.write(xml) + + def asTopLevel(self, peach, args): + """ + Called when Analyzer is used from top level. + From the top level producing zero or more data models and state models is possible. + """ + raise Exception("asTopLevel not supported") + + +class _Xml2Peach(object): + XmlContainer = """ + + + + + +%s + + + + + + + + + + + + + + --> + + + + + + + + + + + + + +""" + + def xml2Peach(self, url): + parser = etree.XMLParser() + parser.resolvers.add(PeachResolver()) + doc = etree.parse(url, parser=parser) + peachDoc = etree.Element("DEADBEEF") + self.handleElement(doc, peachDoc) + # Get the string representation + # TODO: make it better + value = etree.tostring(peachDoc, pretty_print=True).strip() + deadbeef, value = value[:10], value[10:] + assert deadbeef == "" + value, deadbeef = value[:-11], value[-11:] + assert deadbeef == "" + return self.XmlContainer % value + + def handleElement(self, node, parent): + """ + Handle an XML element, children and attributes. Returns an XmlElement object. + """ + if parent is None: + return None + # Element + element = etree.Element("XmlElement") + ns, tag = split_ns(node.tag) + element.set("elementName", tag) + if ns is not None: + element.set("ns", ns) + parent.append(element) + # Element attributes + for attrib in node.keys(): + attribElement = self.handleAttribute(attrib, node.get(attrib), element) + element.append(attribElement) + # Element children + self._handleText(node.text, element) + for child in node.iterchildren(): + if etree.iselement(child): # TODO: skip comments + self.handleElement(child, element) + self._handleText(child.tail, element) + return element + + def _handleText(self, text, parent): + if text is not None and len(text.strip('\n\r\t\x10 ')) > 0: + string = etree.Element("String") + string.set("value", text) + string.set("type", "utf8") + parent.append(string) + + def handleAttribute(self, attrib, attribObj, parent): + """ + Handle an XML attribute. Returns an XmlAttribute object. + """ + # Attribute + element = etree.Element("XmlAttribute") + ns, attrib = split_ns(attrib) + if ns is not None: + element.set("ns", ns) + element.set("attributeName", attrib) + # Attribute value + string = etree.Element("String") + string.set("value", attribObj) + string.set("type", "utf8") + element.append(string) + return element + + +class _Xml2Dom(object): + """ + Convert an XML Document into a Peach DOM. + """ + + def xml2Dom(self, data): + child = etree.XML(data) + doc = child.getroottree() + root = self.handleElement(child, None) + return root + + def handleElement(self, node, parent): + """ + Handle an XML element, children and attributes. Returns an XmlElement object. + """ + doc = node.getroottree() + # Element + element = XmlElement(None, parent) + ns, tag = split_ns(node.tag) + if ns is not None: + element.xmlNamespace = ns + element.elementName = tag + # Element attributes + for attrib in node.keys(): + attribElement = self.handleAttribute(attrib, node.get(attrib), element) + element.append(attribElement) + # Element children + self._handleText(node.text, element) + for child in node.iterchildren(): + if etree.iselement(child): # TODO: skip comments + childElement = self.handleElement(child, element) + element.append(childElement) + self._handleText(child.tail, element) + return element + + def _handleText(self, text, parent): + if text is not None and len(text.strip('\n\r\t\x10 ')) > 0: + string = String(None, parent) + string.defaultValue = text + parent.append(string) + try: + _ = int(string.defaultValue) + hint = Hint("NumericalString", string) + hint.value = "true" + string.hints.append(hint) + except ValueError: + pass + + def handleAttribute(self, attrib, attribObj, parent): + """ + Handle an XML attribute. Returns an XmlAttribute object. + """ + # Attribute + element = XmlAttribute(None, parent) + ns, attrib = split_ns(attrib) + if ns is not None: + element.xmlNamespace = ns + element.attributeName = attrib + # Attribute value + string = String(None, element) + string.defaultValue = attribObj + element.append(string) + return element diff --git a/fuzzers/Peach/Analyzers/xml.pyc b/fuzzers/Peach/Analyzers/xml.pyc new file mode 100644 index 0000000..ae0822b Binary files /dev/null and b/fuzzers/Peach/Analyzers/xml.pyc differ diff --git a/fuzzers/Peach/Engine/__init__$py.class b/fuzzers/Peach/Engine/__init__$py.class new file mode 100644 index 0000000..31d1a81 Binary files /dev/null and b/fuzzers/Peach/Engine/__init__$py.class differ diff --git a/fuzzers/Peach/Engine/__init__.py b/fuzzers/Peach/Engine/__init__.py new file mode 100755 index 0000000..bbadb12 --- /dev/null +++ b/fuzzers/Peach/Engine/__init__.py @@ -0,0 +1,10 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Circular dependencies were caused by this file! + +#import engine, parser, incoming, dom, state, common +#__all__ = [ "engine", "parser", "incoming", "dom", "state", "common" ] + +# end diff --git a/fuzzers/Peach/Engine/__init__.pyc b/fuzzers/Peach/Engine/__init__.pyc new file mode 100644 index 0000000..6cbe3b7 Binary files /dev/null and b/fuzzers/Peach/Engine/__init__.pyc differ diff --git a/fuzzers/Peach/Engine/common$py.class b/fuzzers/Peach/Engine/common$py.class new file mode 100644 index 0000000..3c7e8a5 Binary files /dev/null and b/fuzzers/Peach/Engine/common$py.class differ diff --git a/fuzzers/Peach/Engine/common.py b/fuzzers/Peach/Engine/common.py new file mode 100755 index 0000000..da68b6f --- /dev/null +++ b/fuzzers/Peach/Engine/common.py @@ -0,0 +1,966 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import sys +import types +import traceback + + +def split_ns(text): + """ + Splits an ElementTree style namespace out + + input: {namespace}element + output: (namespace, element) + + input: element + output: (None, element) + """ + if text.startswith("{"): + return text[1:].split("}", 1) + else: + return None, text + +class Holder(object): + """ + Holds static stuff + """ + globals = None + locals = None + + +class SoftException(Exception): + """ + Soft exceptions should end the current test iteration, but not the run. + They are "recoverable" or "try again" errors. + """ + pass + + +class HardException(Exception): + """ + Hard exceptions are non-recoverable and should end the fuzzing run. + """ + pass + + +class RedoTestException(SoftException): + """ + Indicate we should re-run the current test. A recoverable error occurred. + The main engine loop should only retry the test case 3 times before turning this into a hard exception. + """ + pass + + +class PeachException(HardException): + """ + Peach exceptions are specialized hard exceptions. + The message contained in a PeachException is presentable to the user w/o any stack trace, etc. + Examples would be: + "Error: The DataModel element requires a name attribute." + """ + def __init__(self, msg, module="Unknown"): + Exception.__init__(self, msg) + self.module = module + self.msg = msg + + +def peachEval(code, environment=False): + """ + Eval using the Peach namespace stuffs. + """ + return eval(code, Holder.globals, Holder.locals) + + +def GetClassesInModule(module): + """ + Return array of class names in module. + """ + classes = [] + for item in dir(module): + i = getattr(module, item) + if type(i) == types.ClassType and item[0] != '_': + classes.append(item) + elif type(i) == types.MethodType and item[0] != '_': + classes.append(item) + elif type(i) == types.FunctionType and item[0] != '_': + classes.append(item) + return classes + + +def buildImports(node, g, l): + root = node.getRoot() + for child in root: + if child.elementType == 'import': + # Import module + importStr = child.importStr + fromStr = child.fromStr + if fromStr is not None: + if importStr == "*": + module = __import__(fromStr, globals(), locals(), [importStr], -1) + try: + # If we are a module with other modules in us then we have an __all__ + for item in module.__all__: + g[item] = getattr(module, item) + except: + # Else we just have some classes in us with no __all__ + for item in GetClassesInModule(module): + g[item] = getattr(module, item) + else: + module = __import__(fromStr, globals(), locals(), [importStr], -1) + for item in importStr.split(','): + item = item.strip() + g[item] = getattr(module, item) + else: + g[importStr] = __import__(importStr, globals(), locals(), [], -1) + + +def peachPrint(msg): + print("Print: %s", msg) + return True + + +def domPrint(node): + from Peach.Engine.dom import DomPrint + print("vv[ DomPrint ]vvvvvvvvvvvvvvvv\n%s\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" % DomPrint(0, node)) + return True + + +def changeDefaultEndian(endian): + if endian not in ['little', 'big']: + raise PeachException("Called ChangeEndian with invalid paramter [%s]" % endian) + from Peach.Engine.dom import Number + Number.defaultEndian = endian + return True + + +def evalEvent(code, environment, node=None): + """ + Eval python code returning result. + code - String + environment - Dictionary, keys are variables to place in local scope + """ + globalScope = { + 'Print': peachPrint, + 'peachPrint': peachPrint, + 'ChangeDefaultEndian': changeDefaultEndian, + 'DomPrint': domPrint, + } + localScope = { + 'Print': peachPrint, + 'peachPrint': peachPrint, + 'ChangeDefaultEndian': changeDefaultEndian, + 'DomPrint': domPrint, + } + if node is not None: + buildImports(node, globalScope, localScope) + if Holder.globals is not None: + for k in Holder.globals: + globalScope[k] = Holder.globals[k] + if Holder.locals is not None: + for k in Holder.locals: + localScope[k] = Holder.locals[k] + for k in environment.keys(): + globalScope[k] = environment[k] + localScope[k] = environment[k] + try: + ret = eval(code, globalScope, localScope) + except: + print("Code: [%s]" % code) + print("Exception: %s" % sys.exc_info()[1]) + print("Environment:") + for k in environment.keys(): + print(" [%s] = [%s]" % (k, repr(environment[k]))) + raise + return ret + + +class _Getch(object): + """Gets a single character from standard input. Does not echo to the screen.""" + def __init__(self): + try: + self.impl = _GetchWindows() + except ImportError: + self.impl = _GetchUnix() + + def __call__(self): return self.impl() + + +class _GetchUnix(object): + + def __call__(self): + import tty, termios + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + + +class _GetchWindows(object): + + def __call__(self): + import msvcrt + return msvcrt.getch() + + +getch = _Getch() + + +class StreamBuffer(object): + """ + A Peach data stream. Used when generating or cracking data. + """ + + def __init__(self, data=None): + #: Current position + self.pos = 0 + #: Data buffer + self.data = "" + #: History of data locations + self.positions = {} + #: History of data length + self.lengths = {} + + if data is not None: + self.data = data + + def getValue(self): + """ + Return the value created by this stream. + """ + return self.data + + def setValue(self, data): + """ + Set the internal buffer. + """ + self.data = data + + def peek(self, size=None): + """ + Read data with out changing position. + """ + if size is None: + return self.data[self.pos:] + + if self.pos + size > len(self.data): + raise Exception("StreamBuffer.peek(%d): Peeking passed end of buffer." % size) + + return self.data[self.pos:self.pos + size] + + def read(self, size=None): + """ + Read from current position. If size + isn't specified, read rest of stream. + + Read will shift the current position. + """ + + if size is None: + ret = self.data[self.pos:] + self.pos = len(self.data) + return ret + + if self.pos + size > len(self.data): + raise Exception("StreamBuffer.read(%d): Reading passed end of buffer." % size) + + ret = self.data[self.pos:self.pos + size] + self.pos += size + return ret + + def storePosition(self, name): + """ + Store our position by name + """ + #print "Storing position of %s at %d" % (name, self.pos) + self.positions[name] = self.pos + return self.pos + + def getPosition(self, name): + """ + Retreave position by name + """ + if name not in self.positions: + return None + + return self.positions[name] + + def write(self, data, name=None): + """ + Write a block of data at current position. + Stream will expand if needed to support the + written data. Otherwise it will overright + the existing data. + + @type data: string + @param data: Data to write + @type name: string + @param name: Name to store position under [optional] + """ + + if name is not None: + #print "write: %s: %s" % (name, repr(data)) + self.storePosition(name) + self.lengths[name] = len(data) + + dataLen = len(data) + ourDataLen = len(self.data) + + # Replace existing data + if ourDataLen - self.pos > dataLen: + ret = self.data[:self.pos] + ret += data + ret += self.data[self.pos + dataLen:] + self.data = ret + + # Append new data + elif self.pos == ourDataLen: + self.data += data + + # Do both + else: + self.data = self.data[:self.pos] + data + + # Move position + self.pos += dataLen + + def count(self): + """ + Get the current size in bytes of the data stream. + """ + return len(self.data) + + def tell(self): + """ + Return the current position in the data stream. + """ + return self.pos + + def seekFromCurrent(self, pos): + """ + Change current position in data. + + NOTE: If the position is past the end of the + existing stream data the data will be expanded + such that the position exists padded with '\0' + """ + + newpos = self.pos + pos + self.seekFromStart(newpos) + + def seekFromStart(self, pos): + """ + Change current position in data. + + NOTE: If the position is past the end of the + existing stream data the data will be expanded + such that the position exists padded with '\0' + """ + + if pos < 0: + raise Exception("StreamBuffer.seekFromStart(%d) results in negative position" % pos) + + # Should we expand buffer? + if pos > len(self.data): + self.data += '\0' * (pos - len(self.data)) + + self.pos = pos + + def seekFromEnd(self, pos): + """ + Change current position in data. + + NOTE: If the position is past the end of the + existing stream data the data will be expanded + such that the position exists padded with '\0' + """ + + newpos = len(self.data) + pos + self.seekFromStart(newpos) + + +import weakref + + +class PeachEvent(object): + """ + A .NET like Event system. Uses weak references + to avoid memory issues. + """ + + def __init__(self): + self.handlers = set() + + def _objectFinalized(self, obj): + """ + Called when an object we have a weak reference + to is being garbage collected. + """ + self.handlers.remove(obj) + + def handle(self, handler): + """ + Add a handler to our event + """ + self.handlers.add(weakref.ref(handler, self._objectFinalized)) + return self + + def unhandle(self, handler): + """ + Remove a handler from our event + """ + try: + for ref in self.handlers: + if ref() == handler: + self.handlers.remove(ref) + except: + raise ValueError("Handler is not handling this event, so cannot unhandle it.") + + return self + + def fire(self, *args, **kargs): + """ + Trigger event and call our handlers + """ + for handler in self.handlers: + handler()(*args, **kargs) + + def getHandlerCount(self): + """ + Count of handlers registered for this event + """ + return len(self.handlers) + + __iadd__ = handle + __isub__ = unhandle + __call__ = fire + __len__ = getHandlerCount + +#class MockFileWatcher: +# def __init__(self): +# self.fileChanged = Event() +# +# def watchFiles(self): +# source_path = "foo" +# self.fileChanged(source_path) +# +#def log_file_change(source_path): +# print "%r changed." % (source_path,) +# +#def log_file_change2(source_path): +# print "%r changed!" % (source_path,) +# +#watcher = MockFileWatcher() +#watcher.fileChanged += log_file_change2 +#watcher.fileChanged += log_file_change +#watcher.fileChanged -= log_file_change2 +#watcher.watchFiles() + + +class ArraySetParent(object): + """ + Special array type that will + set the parent on all children. + """ + + def __init__(self, parent): + if parent is None: + raise Exception("Whoa, parent == None!") + self._parent = parent + self._array = [] + + def append(self, obj): + #if hasattr(obj, "of"): + # if obj.of == "Tables": + # print "SETTING TABLES PARENT TO:", self._parent + # print obj + # traceback.print_stack(); + + obj.parent = self._parent + return self._array.append(obj) + + def index(self, obj): + return self._array.index(obj) + + def insert(self, index, obj): + obj.parent = self._parent + return self._array.insert(index, obj) + + def remove(self, obj): + return self._array.remove(obj) + + def __len__(self): + return self._array.__len__() + + def __getitem__(self, key): + return self._array.__getitem__(key) + + def __setitem__(self, key, value): + value.parent = self._parent + return self._array.__setitem__(key, value) + + def __delitem__(self, key): + return self._array.__delitem__(key) + + def __iter__(self): + return self._array.__iter__() + + def __contains__(self, item): + return self._array.__contains__(item) + + +class BitBuffer(object): + """ + Access buffer as bit stream. Support the normal reading from left to right + of bits as well as the reverse right to left. + """ + + def __init__(self, buf='', bigEndian=False): + self.buf = [ord(x) for x in buf] + + self.pos = 0 + self.len = len(buf) * 8 + + self.closed = False + self.softspace = 0 + + self.bigEndian = bigEndian + + def close(self): + """Let me think... Closes and flushes the toilet!""" + if not self.closed: + self.closed = True + del self.buf, self.pos, self.len, self.softspace + + def isatty(self): + if self.closed: + raise ValueError("I/O operation on closed file") + return 0 + + def seek(self, pos, mode=0): + """Set new position""" + + if self.closed: + raise ValueError("I/O operation on closed file") + if mode == 1: + pos += self.pos + elif mode == 2: + pos += self.len + self.pos = max(0, pos) + + def tell(self): + """Tell current position""" + + if self.closed: + raise ValueError("I/O operation on closed file") + return self.pos + + def flush(self): + """Flush the toilet""" + + if self.closed: + raise ValueError("I/O operation on closed file") + + def truncate(self, size=None): + if self.closed: + raise ValueError("I/O operation on closed file") + if size is None: + size = self.pos + elif size < 0: + raise IOError(EINVAL, "Negative size not allowed") + elif size < self.pos: + self.pos = size + + self.len = size + self.buf = self.buf[:(size // 8) + (size % 8 != 0)] + if self.buf: self.buf[-1] &= (1 << (size % 8)) - 1 + + def writebits(self, n, bitlen): + """Writes bits""" + + if self.closed: + raise ValueError("I/O operation on closed file") + + n &= (1 << bitlen) - 1 + + newpos = self.pos + bitlen + + startBPos = self.pos % 8 + startBlock = self.pos // 8 + + endBPos = newpos % 8 + endBlock = newpos // 8 + (endBPos != 0) + + #print startBlock, startBPos, endBlock, endBPos + + while len(self.buf) < endBlock: self.buf += [0] + + pos = startBPos + + if not self.bigEndian: + while bitlen > 0: + bitsLeft = 8 - (pos % 8) + if bitsLeft > bitlen: bitsLeft = bitlen + + mask = (1 << bitsLeft) - 1 + + self.buf[startBlock + (pos // 8)] ^= self.buf[startBlock + (pos // 8)] & (mask << (pos % 8)) + self.buf[startBlock + (pos // 8)] |= int(n & mask) << (pos % 8) + + n >>= bitsLeft + bitlen -= bitsLeft + + pos += bitsLeft + + self.pos = newpos + if self.pos > self.len: + self.len = self.pos + + else: + while bitlen > 0: + bitsLeft = 8 - (pos % 8) + if bitsLeft > bitlen: bitsLeft = bitlen + + mask = (1 << bitsLeft) - 1 + shift = (8 - self.bitlen(self.binaryFormatter(mask, 8))) - (pos - (pos / 8 * 8)) + + byte = n >> bitlen - self.bitlen(self.binaryFormatter(mask, 8)) + + self.buf[startBlock + (pos // 8)] |= ((byte & mask) << shift) + + bitlen -= bitsLeft + pos += bitsLeft + + self.pos = newpos + if self.pos > self.len: + self.len = self.pos + + def binaryFormatter(self, num, bits): + """ + Create a string in binary notation + """ + ret = "" + for i in range(bits - 1, -1, -1): + ret += str((num >> i) & 1) + + assert len(ret) == bits + return ret + + def bitlen(self, s): + return len(s) - s.find('1') + + def readbits(self, bitlen): + """ + Reads bits based on endianness + """ + + if self.closed: + raise ValueError("I/O operation on closed file") + + newpos = self.pos + bitlen + orig_bitlen = bitlen + + startBPos = self.pos % 8 + startBlock = self.pos // 8 + + endBPos = newpos % 8 + endBlock = newpos // 8 + (endBPos != 0) + + ret = 0 + + pos = startBPos + + while bitlen > 0: + bitsLeft = 8 - (pos % 8) + bitsToLeft = pos - (pos / 8 * 8) + if bitsLeft > bitlen: + bitsLeft = bitlen + + mask = (1 << bitsLeft) - 1 + + byte = self.buf[startBlock + (pos // 8)] + + if not self.bigEndian: + # Reverse all bits + newByte = 0 + for _ in range(8): + bit = byte & 0x01 + byte >>= 1 + newByte <<= 1 + newByte |= bit + byte = newByte + + byte >>= (8 - bitsLeft) - bitsToLeft + + shift = self.bitlen(self.binaryFormatter(mask, 8)) + ret <<= shift + ret |= byte & mask + + shift += bitsLeft + bitlen -= bitsLeft + pos += bitsLeft + + # Reverse requested bits + if not self.bigEndian: + newByte = 0 + for _ in range(orig_bitlen): + bit = ret & 0x01 + ret >>= 1 + newByte <<= 1 + newByte |= bit + ret = newByte + + self.pos = newpos + return ret + + def getvalue(self): + """Get the buffer""" + + return ''.join(map(chr, self.buf)) + + def write(self, s): + for c in str(s): + self.writebits(ord(c), 8) + + def writelines(self, list): + self.write(''.join(list)) + + def read(self, i): + ret = [] + for i in range(i): + ret.append(chr(self.readbits(8))) + + return ''.join(ret) + + def writebit(self, b): + """Writes Bit (1bit)""" + + self.writebits(b, 1) + + def readbit(self): + """Reads Bit (1bit)""" + + return self.readbits(1) + + def writebyte(self, i): + """Writes Byte (8bits)""" + + self.writebits(i, 8) + + def readbyte(self): + """Reads Byte (8bits)""" + + return self.readbits(8) + + def writeword(self, i): + """Writes Word (16bits)""" + + self.writebits(i, 16) + + def readword(self): + """Reads Word (16bits)""" + + return self.readbits(16) + + def writedword(self, i): + """Writes DWord (32bits)""" + + self.writebits(i, 32) + + def readdword(self): + """Reads DWord (32bits)""" + + return self.readbits(32) + + def writevbl(self, n): + """Writes Variable bit length.""" + + self.writebit(n < 0) + n = abs(n) + self.writebits(n, 6) + n >>= 6 + + while n: + self.writebit(1) + self.writebits(n, 8) + n >>= 8 + + self.writebit(0) + + def readvbl(self): + """Reads Variable bit length.""" + + isNeg = self.readbit() + r = self.readbits(6) + pos = 6 + + while self.readbit(): + r |= self.readbits(8) << pos + pos += 8 + + if isNeg: + r = -r + + return r + + +import threading + + +class DomBackgroundCopier(object): + """ + This class spins up a thread that makes + copies of Data Models. This should + allow us to take advantage of multi-core + CPUs and increase fuzzing speed. + """ + + copyThread = None + stop = None + + def __init__(self): + self.doms = [] + self.copies = {} + self.minCopies = 1 + self.maxCopies = 10 + self.copiesLock = threading.Lock() + DomBackgroundCopier.needcopies = threading.Event() + DomBackgroundCopier.copyThread = None + DomBackgroundCopier.stop = threading.Event() + + self.singleThread = True + if os.getenv("PEACH_SINGLETHREAD") is None: + self.singleThread = False + DomBackgroundCopier.copyThread = threading.Thread(target=self.copier) + self.copyThread.start() + + def copier(self): + while not self.stop.isSet(): + for dom in self.doms: + self.copiesLock.acquire() + if len(self.copies[dom]) < self.minCopies: + self.copiesLock.release() + + domCopy = dom.copy(None) + + self.copiesLock.acquire() + self.copies[dom].append(domCopy) + self.copiesLock.release() + else: + self.copiesLock.release() + + for dom in self.doms: + self.copiesLock.acquire() + if len(self.copies[dom]) < self.maxCopies: + #print "DOM[%s]: %d copies < %d" % (dom, len(self.copies[dom]), self.maxCopies) + self.copiesLock.release() + + domCopy = dom.copy(None) + + self.copiesLock.acquire() + self.copies[dom].append(domCopy) + self.copiesLock.release() + + else: + self.copiesLock.release() + + DomBackgroundCopier.needcopies.wait() + DomBackgroundCopier.needcopies.clear() + + def addDom(self, dom): + if dom in self.doms: + return + + self.copiesLock.acquire() + try: + self.doms.append(dom) + self.copies[dom] = [] + finally: + self.copiesLock.release() + DomBackgroundCopier.needcopies.set() + + def getCopy(self, dom): + # If using a single thread just return a copy + if self.singleThread: + return dom.copy(None) + + if not dom in self.doms: + return None + + if len(self.copies[dom]) == 0: + return None + + if len(self.copies[dom]) < (self.maxCopies / 2): + DomBackgroundCopier.needcopies.set() + + self.copiesLock.acquire() + try: + c = self.copies[dom][0] + self.copies[dom] = self.copies[dom][1:] + return c + finally: + self.copiesLock.release() + + def removeDom(self, dom): + if not dom in self.doms: + return + + self.copiesLock.acquire() + try: + self.doms.remove(dom) + del self.copies[dom] + finally: + self.copiesLock.release() + + +class Highlight(object): + HEADER = '\033[95m' + INFO = '\033[36m' + OK = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + REPR = '\033[35m' + BLOCK = '\033[30;47m' + NOTE = '\033[1;37m' + ENDC = '\033[0m' + + def __init__(self): + if os.sys.platform == "win32": + self.disable() + + def error(self, msg): + return "%s%s%s" % (self.FAIL, msg, self.ENDC) + + def ok(self, msg): + return "%s%s%s" % (self.OK, msg, self.ENDC) + + def warning(self, msg): + return "%s%s%s" % (self.WARNING, msg, self.ENDC) + + def repr(self, msg): + return "%s%s%s" % (self.REPR, msg, self.ENDC) + + def block(self, msg): + return "%s%s%s" % (self.BLOCK, msg, self.ENDC) + + def info(self, msg): + return "%s%s%s" % (self.INFO, msg, self.ENDC) + + def note(self, msg): + return "%s%s%s" % (self.NOTE, msg, self.ENDC) + + def disable(self): + self.HEADER = '' + self.INFO = '' + self.GREEN = '' + self.WARNING = '' + self.FAIL = '' + self.ENDC = '' + + +highlight = Highlight() diff --git a/fuzzers/Peach/Engine/common.pyc b/fuzzers/Peach/Engine/common.pyc new file mode 100644 index 0000000..024e48a Binary files /dev/null and b/fuzzers/Peach/Engine/common.pyc differ diff --git a/fuzzers/Peach/Engine/defaults.xml b/fuzzers/Peach/Engine/defaults.xml new file mode 100755 index 0000000..9ac12be --- /dev/null +++ b/fuzzers/Peach/Engine/defaults.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fuzzers/Peach/Engine/dom.py b/fuzzers/Peach/Engine/dom.py new file mode 100755 index 0000000..4ef4d09 --- /dev/null +++ b/fuzzers/Peach/Engine/dom.py @@ -0,0 +1,5195 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os +import re +import sys +import time +import glob +import base64 +import ctypes +import struct +import random +import logging +import traceback + +from Peach import Transformers +from Peach.Engine.common import * +from Peach.Engine.engine import Engine +from Peach.publisher import PublisherBuffer + +import Peach +PeachModule = Peach + +from copy import deepcopy +import cPickle as pickle +from lxml import etree + + +class Empty(object): + pass + + +def new_instancemethod(function, instance): + """ + bind 'method' to 'instance.method_name' + """ + instance_method_type = type(getattr(instance, "__init__")) + return instance_method_type(function, instance, type(instance)) + + +class Element(object): + """ + Element in our template tree. + """ + + #: For generating unknown element names + __CurNameNum = 0 + + def __init__(self, name = None, parent = None): + #: Name of Element, cannot include "."s + self._name = name + if not self._name: + self._name = Element.getUniqueName() + #: Parent of Element + self.parent = parent + + #: If element has children + self.hasChildren = False + + #: Type of this element + self.elementType = None + + #: Fullname cache + self.fullName = None + + #: The reference that made us, or None + self.ref = None + + @property + def name(self): + return self._name + + @name.setter + def name(self, value): + if self.parent is not None and self.parent.get(self._name) == self: + del self.parent._childrenHash[self._name] + delattr(self.parent.children, self._name) + + self.parent._childrenHash[value] = self + setattr(self.parent.children, value, self) + + self._name = value + + def toXml(self, parent): + pass + + def __deepcopy__(self, memo): + """ + Copying objects in our DOM is a crazy business. Here we + try and help out as much as we can. + """ + + # Copy procedures + # + # - Only copy children array (_children) + # - Remove array and re-add children via append + # - Set our __deepcopy__ attributes + # - Fixup our toXml functions + + parent = self.parent + self.parent = None + + # Only copy _children array + if isinstance(self, ElementWithChildren): + # Save other children collections + _childrenHash = self._childrenHash + children = self.children + + # Null out children except for array + self._childrenHash = None + self.children = None + + if self.elementType == 'block' or self.elementType == 'namespace': + toXml = self.toXml + self.toXml = None + + ## Perform actual copy + + e = pickle.loads(pickle.dumps(self, -1)) + + ## Remove attributes + + if e.elementType == 'block': + e.toXml = toXml + self.toXml = toXml + + self.parent = parent + + if isinstance(self, ElementWithChildren): + # Set back other children collections + self._childrenHash = _childrenHash + self.children = children + + # Fixup ElementWithChildren types + # We need to try and keep things in order + # and not have to many duplicated elements + children = e._children + + e._children = [] + e._childrenHash = {} + e.children = PeachModule.Engine.engine.Empty() + + for c in children: + e.append(c) + + # Fixup DataElements + if isinstance(e, DataElement): + for r in e.relations: + r.parent = e + + if e.placement is not None: + e.placement.parent = e + + for h in e.hints: + h.parent = e + + if e.transformer is not None: + e.transformer.parent = e + + return e + + def getElementsByType(self, type, ret=None): + """ + Will return an array all elements of a specific type + in the tree starting with us. + TODO: optimize + """ + + if ret is None: + ret = [] + + if isinstance(self, type): + ret.append(self) + + return ret + + @staticmethod + def getUniqueName(): + """ + Provide a unique default name for elements. + + Note: Some graphs can get very large (500K nodes) + at which point this name can eat up alot of memeory. So + lets keep it simple/small. + """ + + name = "Named_%d" % Element.__CurNameNum + Element.__CurNameNum += 1 + + return name + + def getRoot(self): + """ + Get the root of this DOM tree + """ + + stack = {self} + + root = self + while root.parent is not None: + if root.parent in stack: + raise Exception("Error: getRoot found a recursive relationship! EEk!") + root = root.parent + stack.add(root) + return root + + def printDomMap(self, level = 0): + """ + Print out a map of the dom. + """ + print("%s- %s [%s](%s)" % ((" "*level), self.name, self.elementType, str(self)[-9:])) + + def toXmlDom(self, parent, dict): + """ + Convert to an XML DOM object tree for use in xpath queries. + """ + + owner = parent.getroottree() + if owner is None: + owner = parent + + # Only use ref if name is not available! + if getattr(self, 'ref', None) is not None and self.name.startswith('Named_'): + ref = self.ref.replace(":", "_") + node = etree.Element(ref) + else: + try: + name = self.name.replace(":", "_") + node = etree.Element(name) + except Exception: + print("name:", self.name) + raise + + node.set("elementType", self.elementType) + node.set("name", self.name) + + if getattr(self, 'ref', None) is not None: + self._setXmlAttribute(node, "ref", self.ref) + + self._setXmlAttribute(node, "fullName", self.getFullname()) + + dict[node] = self + dict[self] = node + + parent.append(node) + + return node + + def toXmlDomLight(self, parent, dict): + """ + Convert to an XML DOM object tree for use in xpath queries. + Does not include values (Default or otherwise) + """ + + owner = parent.getroottree() + if owner is None: + owner = parent + + node = etree.Element(self.name) + + node.set("elementType", self.elementType) + node.set("name", self.name) + + if getattr(self, 'ref', None) is not None: + self._setXmlAttribute(node, "ref", self.ref) + + self._setXmlAttribute(node, "fullName", self.getFullname()) + + dict[node] = self + dict[self] = node + + parent.append(node) + + return node + + @staticmethod + def _setXmlAttribute(node, key, value): + """ + Set an XML attribute with handling for UnicodeDecodeError. + """ + + try: + node.set(key, str(value)) + value = str(node.get(key)) + + except UnicodeEncodeError: + node.set("%s-Encoded" % key, "base64") + node.set(key, base64.b64encode(str(value))) + + except UnicodeDecodeError: + node.set("%s-Encoded" % key, "base64") + node.set(key, base64.b64encode(str(value))) + + @staticmethod + def _getXmlAttribute(node, key): + """ + Get an XML attribute with handling for UnicodeDecodeError. + """ + + if node.get(key) is None: + return None + + if node.get("%s-Encoded" % key) is not None: + value = node.get(key) + value = base64.b64decode(value) + + else: + value = str(node.get(key)) + + return value + + def updateFromXmlDom(self, node, dict): + """ + Update our object based on an XML DOM object. + All we are taking for now is defaultValue. + """ + + if node.get('defaultValue') is not None: + self.defaultValue = self._getXmlAttribute(node, "defaultValue") + + if node.get('currentValue') is not None: + self.currentValue = self._getXmlAttribute(node, "currentValue") + + if node.get('value') is not None: + self.value = self._getXmlAttribute(node, "value") + + def compareTree(self, node1, node2): + """ + This method will compare two ElementWithChildren + object tree's. + """ + + if node1.name != node2.name: + raise Exception("node1.name(%s) != node2.name(%s)" %(node1.name, node2.name)) + + if node1.elementType != node2.elementType: + raise Exception("Element types don't match [%s != %s]" % (node1.elementType, node2.elementType)) + + if not isinstance(node1, DataElement): + return True + + if len(node1) != len(node2): + raise Exception("Lengths do not match %d != %d" % (len(node1), len(node2))) + + if len(node1._childrenHash) > len(node1._children): + raise Exception("Node 1 length of hash > list") + + if len(node2._childrenHash) > len(node2._children): + print("node1.name", node1.name) + print("node2.name", node2.name) + print("len(node1)", len(node1)) + print("len(node2)", len(node2)) + print("len(node1._childrenHash)", len(node1._childrenHash)) + print("len(node2._childrenHash)", len(node2._childrenHash)) + for c in node1._childrenHash.keys(): + print("node1 hash key:", c) + for c in node2._childrenHash.keys(): + print("node2 hash key:", c) + raise Exception("Node 2 length of hash > list") + + for key, value in node1._childrenHash.iteritems(): + if value not in node1._children: + raise Exception("Error: %s not found in node1 list" % key) + + for key, value in node2._childrenHash.iteritems(): + if value not in node2._children: + raise Exception("Error: %s not found in node2 list" % key) + + for a, b in zip(node1, node2): + if not self.compareTree(a, b): + return False + + return True + + def copy(self, parent): + + # We need to remove realParents before we can perform + # the copy and then replace then. + + if isinstance(self, DataElement): + + if hasattr(self, 'realParent'): + selfRealParent = self.realParent + self.realParent = object() + + for child in self.getAllChildDataElements(): + if getattr(child, 'realParent', None) is not None: + child.parent = child.realParent + child.realParent = object() + + # Perform actual copy + + newSelf = deepcopy(self) + newSelf.parent = parent + self._FixParents(newSelf, parent) + + if isinstance(self, DataElement): + + if hasattr(self, 'realParent'): + self.realParent = selfRealParent + + for child in self.getAllChildDataElements(): + if getattr(child, 'realParent', None) is not None: + child.realParent = child.parent + + for child in newSelf.getAllChildDataElements(): + if getattr(child, 'realParent', None) is not None: + child.realParent = child.parent + + # Not sure if we realy want todo this. + if self.parent is None and parent is None and hasattr(self, 'realParent'): + newSelf.realParent = self.realParent + + return newSelf + + def _FixParents(self, start = None, parent = None): + """ + Walk down from start and fix parent settings on children + """ + + if start is None: + start = self + + if parent is not None: + start.parent = parent + + if hasattr(start, 'fixup') and getattr(start, 'fixup') is not None: + start.fixup.parent = start + + if isinstance(start, ElementWithChildren): + for child in start._children: + self._FixParents(child, start) + + def getFullname(self): + + if self.fullName is not None: + return self.fullName + + name = self.name + node = self + + while node.parent is not None: + + # We need to handle namespaces here!!! + # TODO + node = node.parent + name = "%s.%s" % (node.name, name) + + return name + + def nextSibling(self): + """ + Get the next sibling or return None + """ + + if self.parent is None: + return None + + # First determin our position in parents children + ourIndex = self.parent._children.index(self) + + # Check for next child + if len(self.parent._children) <= (ourIndex+1): + return None + + #sys.stderr.write("nextSibling: %d:%d\n" % (len(self.parent), (ourIndex+1))) + return self.parent._children[ourIndex+1] + + def previousSibling(self): + """ + Get the prior sibling or return None + """ + + if self.parent is None: + return None + + # First determin our position in parents children + ourIndex = self.parent._children.index(self) + + # Check for next child + if ourIndex == 0: + return None + + return self.parent._children[ourIndex-1] + + def _setAttribute(self, node, name, value, default = None): + """ + Set an attribute on an XML Element. We only set the + attribute in the following cases: + + 1. We have no attached xml node or self.ref == None + 2. We have a node, and the node has that attribute + 3. The value is not None + + """ + + # Simplify the XML by not adding defaults + if value == default or value is None: + return + + node.set(name, str(value)) + + GuidRegex = re.compile('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') + def _xmlHadChild(self, child): + """ + Verify that we should serialize child node. Checks + to see if we have an attached xml node and that xml + node has the child. If we don't have an attached + xml node then say we should add child. + """ + + return True + + +class ElementWithChildren(Element): + """ + Contains functions that cause Element to act as a + hash table and array for children. Also children can + be accessed by name via self.children.name. + """ + + def __init__(self, name = None, parent = None): + Element.__init__(self, name, parent) + self._children = [] #: List of children (in order) + self._childrenHash = {} #: Dictionary of children (by name) + self.children = Empty() #: Children object, has children as attributes by name + self.hasChildren = True + + def getByName(self, name): + """ + Internal helper method, not for use! + """ + + names = name.split(".") + node = self.getRoot() + + if node.name != names[0]: + return None + + obj = node + for i in range(1, len(names)): + if not obj.has_key(names[i]): + return None + + obj = obj[names[i]] + + return obj + + def getElementsByType(self, type, ret = None): + """ + Will return array of a specific type + in the tree starting with us. + """ + + if ret is None: + ret = [] + + if isinstance(self, type): + ret.append(self) + + for child in self: + if isinstance(child, ElementWithChildren): + child.getElementsByType(type, ret) + + return ret + + def printDomMap(self, level = 0): + """ + Print out a map of the dom. + """ + print("") + print(" "*level) + "+ %s [%s](%s)" % (self.name, self.elementType, str(self)[-9:]) + + for child in self: + if isinstance(child, Element): + child.printDomMap(level+1) + + if child.parent != self: + raise Exception("Error: printDomMap: %s.parent != self : %s:%s " % (child.name, child.name, repr(child.parent))) + + def verifyDomMap(self): + """ + Verify parent child relationship across DOM Tree + """ + for child in self: + if isinstance(child, Element): + if child.parent != self: + raise Exception("Error: verifyDomMap: %s.parent != self : %s:%s " % (child.name, child.name, repr(child.parent))) + + if isinstance(child, ElementWithChildren): + child.verifyDomMap() + + def toXmlDom(self, parent, dict): + """ + Convert to an XML DOM boject tree for use in xpath queries. + """ + + node = Element.toXmlDom(self, parent, dict) + + for child in self._children: + if hasattr(child, 'toXmlDom'): + child.toXmlDom(node, dict) + + return node + + def toXmlDomLight(self, parent, dict): + """ + Convert to an XML DOM boject tree for use in xpath queries. + + Note: toXmlDomLight and toXmlDom are the same now + """ + + node = Element.toXmlDomLight(self, parent, dict) + + for child in self._children: + if hasattr(child, 'toXmlDomLight'): + child.toXmlDomLight(node, dict) + + return node + + def updateFromXmlDom(self, node, dict): + """ + Update our object based on an XML DOM object. + All we are taking for now is defaultValue. + """ + + Element.updateFromXmlDom(self, node, dict) + + if node.hasChildNodes(): + for child in node.iterchildren(): + dict[child].updateFromXmlDom(child, dict) + + def append(self, obj): + # If we have the key we need to replace it + if self._childrenHash.has_key(obj.name): + self[obj.name] = obj + obj.parent = self + return + + # Otherwise add it at the end + self._children.append(obj) + self._childrenHash[obj.name] = obj + setattr(self.children, obj.name, obj) + + # Reset parent relationship + obj.parent = self + + def index(self, obj): + return self._children.index(obj) + + def insert(self, index, obj): + if obj in self._children: + raise Exception("object already child of element") + + # Update parent + obj.parent = self + + self._children.insert(index, obj) + if obj.name is not None: + #print "inserting ",obj.name + self._childrenHash[obj.name] = obj + setattr(self.children, obj.name, obj) + + def firstChild(self): + if len(self._children) >= 1: + return self._children[0] + + return None + + def lastChild(self): + if len(self._children) >= 1: + return self._children[-1] + + return None + + def has_key(self, name): + return self._childrenHash.has_key(name) + + + # Container emulation methods ############################ + + # Note: We have both a dictionary and an ordered list + # that we must keep upto date. This allows us + # to access children by index or by key + # So saying: elem[0] is valid as is elem['Name'] + + def __len__(self): + return self._children.__len__() + + def get(self, key, default=None): + try: + return self.__getitem__(key) + except (KeyError, IndexError): + return default + + def __getitem__(self, key): + if type(key) == int: + return self._children.__getitem__(key) + + return self._childrenHash.__getitem__(key) + + def __setitem__(self, key, value): + if type(key) == int: + oldObj = self._children[key] + if oldObj.name is not None: + del self._childrenHash[oldObj.name] + #delattr(self.children, oldObj.name) + + if value.name is not None: + self._childrenHash[value.name] = value + setattr(self.children, value.name, value) + + return self._children.__setitem__(key, value) + + else: + if key in self._childrenHash: + # Existing item + inx = self._children.index( self._childrenHash[key] ) + + self._children[inx] = value + self._childrenHash[key] = value + setattr(self.children, value.name, value) + else: + self._children.append(value) + self._childrenHash[key] = value + setattr(self.children, value.name, value) + + def __delitem__(self, key): + if type(key) == int: + obj = self._children[key] + if obj.name is not None: + del self._childrenHash[obj.name] + delattr(self.children, obj.name) + + return self._children.__delitem__(key) + + obj = self._childrenHash[key] + + try: + self._children.remove(obj) + except: + pass + + try: + del self._childrenHash[key] + except: + pass + + if hasattr(self.children, key): + delattr(self.children, key) + + def __iter__(self): + return self._children.__iter__() + + def __contains__(self, item): + return self._children.__contains__(item) + +class Mutatable(ElementWithChildren): + """ + To mark a DOM object as mutatable(fuzzable) or not + """ + def __init__(self, name = None, parent = None, isMutable = True): + ElementWithChildren.__init__(self, name, parent) + + #: Can this object be changed by the mutators? + self.isMutable = isMutable + + def setMutable(self, value): + """ + Update this element and all childrens isMutable. + """ + for child in self: + if isinstance(child, Mutatable): + child.setMutable(value) + + self.isMutable = value + +class DataElement(Mutatable): + """ + Data elements compose the Data Model. This is the base + class for String, Number, Block, Template, etc. + + When iterating over the Peach DOM if an element + isinstance(obj, DataElement) it is part of a data model. + """ + + def __init__(self, name = None, parent = None): + ElementWithChildren.__init__(self, name, parent) + + if name is not None and (name.find(".") > -1 or name.find(":") > -1): + raise PeachException("Name '%s' contains characters not allowed in names such as period (.) or collen (:)" % name) + + #: Is this a ctypes pointer to something? (Defaults to False) + self.isPointer = False + + #: What is out pointer depth? (e.g. void** p is 2), (Defaults to 1) + self.pointerDepth = 1 + + #: Optional constraint used during data cracking, python expression + self.constraint = None + + #: Should element be mutated? + self.isMutable = True + + #: Does data model have an offset relation? + self.modelHasOffsetRelation = None + + #: Cache of relation, list of full data names (String) of each relation from here down. cache is build post incoming. + self.relationCache = None + + #: Key is full data name of "of" element (string), value is list of relation full data names (String). cache is bulid post incoming. + self.relationOfCache = None + + #: Event that occurs prior to parsing the next array element. + self.onArrayNext = None + + #: Transformers to apply + self.transformer = None + + #: Fixup if any + self.fixup = None + + #: Placement if any + self.placement = None + + #: Relations this element has + self.relations = ArraySetParent(self) + + #: Mutator Hints + self.hints = ArraySetParent(self) + + #: Fixed occurs + self.occurs = None + #: Minimum occurences + self._minOccurs = 1 + #: Maximum occurences + self._maxOccurs = 1 + + self.generatedOccurs = 1 + + #: Default value to use + self._defaultValue = None + #: Mutated value prior to packing and transformers + self._currentValue = None + #: Mutated value after everything but transformers + self._finalValue = None + #: Current value + self._value = None + + #: Expression used by data cracker to determin + #: if element should be included in cracking. + self.when = None + + self._inInternalValue = False #: Used to prevent recursion + + # Attributes for elements part of an array + self.array = None #: Name of array. The origional name of the data element. + self.arrayPosition = None #: Our position in the array. + self.arrayMinOccurs = None #: The min occurences in the array + self.arrayMaxOccurs = None #: The max occurences in the array + + #: Position in data stream item was parsed at + self._pos = None + self._possiblePos = None + #: Parse rating for element + self.rating = None + + #: Is this element a static token? + self.isStatic = False + + #: A StringBuffer used to determin offset relations + self.relationStringBuffer = None + + #: Fullname in data model + self.fullNameDataModel = None + + def get_DefaultValue(self): + return self._defaultValue + def set_DefaultValue(self, value): + self._defaultValue = value + #self._currentValue = None + self._value = None + self._finalValue = None + defaultValue = property(get_DefaultValue, set_DefaultValue, None) + def get_CurrentValue(self): + return self._currentValue + def set_CurrentValue(self, value): + self._currentValue = value + self._value = None + self._finalValue = None + currentValue = property(get_CurrentValue, set_CurrentValue, None) + def get_Value(self): + return self._value + def set_Value(self, value): + self._value = value + self._finalValue = None + value = property(get_Value, set_Value, None) + def get_FinalValue(self): + return self._finalValue + def set_FinalValue(self, value): + self._finalValue = value + finalValue = property(get_FinalValue, set_FinalValue, None) + + @property + def pos(self): + """ + Getter for pos property. If we have a string buffer + associated with the root node, use that for the correct + position. + """ + + obj = self + while obj.parent is not None and (not hasattr(obj, "relationStringBuffer") or obj.relationStringBuffer is None): + obj = obj.parent + + if hasattr(obj, "relationStringBuffer") and obj.relationStringBuffer is not None: + value = obj.relationStringBuffer.getPosition(self.getFullnameInDataModel()) + if value is not None: + return value + else: + return 0 + + return self._pos + @pos.setter + def pos(self, value): + """ + Setter for pos property + """ + self._pos = value + return self._pos + + def get_possiblePos(self): + """ + Getter for pos property. If we have a string buffer + associated with the root node, use that for the correct + position. + """ + + obj = self + while obj.parent is not None and (not hasattr(obj, "relationStringBuffer") or obj.relationStringBuffer is None): + obj = obj.parent + + if hasattr(obj, "relationStringBuffer") and obj.relationStringBuffer is not None: + value = obj.relationStringBuffer.getPosition(self.getFullnameInDataModel()) + if value is not None: + return value + ##BUG: Leave this commented out else we introduce a bug in the data cracker + ## that was run into with opentype.xml used in eot.xml. + ##else: + ## print "get_possiblePos: relationStringBuffer was of no use to us!" + ## return 0 + + return self._possiblePos + def set_possiblePos(self, value): + """ + Setter for pos property + """ + self._possiblePos = value + return self._possiblePos + possiblePos = property(get_possiblePos, set_possiblePos, None) + + def getElementsByType(self, type, ret = None): + """ + Will return an array all elements of a specific type + in the tree starting with us. + """ + + if ret is None: + ret = [] + + if isinstance(self, type): + ret.append(self) + + elif self.fixup is not None: + for child in self.fixup: + if isinstance(child, ElementWithChildren): + child.getElementsByType(type, ret) + + for child in self: + if isinstance(child, ElementWithChildren): + child.getElementsByType(type, ret) + + return ret + + def clone(self, obj): + + if obj is None: + raise Exception("Generic clone needs object instance!") + + obj.name = self.name + obj.parent = self.parent + obj.hasChildren = self.hasChildren + obj.elementType = self.elementType + obj.fullName = self.fullName + obj.ref = self.ref + obj.generatedOccurs = self.generatedOccurs + + obj.isPointer = self.isPointer + obj.pointerDepth = self.pointerDepth + obj.constraint = self.constraint + obj.isMutable = self.isMutable + obj.modelHasOffsetRelation = self.modelHasOffsetRelation + + if self.relationCache is not None: + obj.relationCache = self.relationCache[:] + if self.relationOfCache is not None: + obj.relationOfCache = self.relationOfCache.copy() + + obj.onArrayNext = self.onArrayNext + + if self.transformer is not None: + obj.transformer = self.transformer.clone() + if self.fixup is not None: + obj.fixup = self.fixup.clone() + if self.placement is not None: + obj.placement = self.placement.clone() + + for r in self.relations: + obj.relations.append( r.clone() ) + + for h in self.hints: + obj.hints.append( h.clone() ) + + obj.occurs = self.occurs + obj._minOccurs = self._minOccurs + obj._maxOccurs = self._maxOccurs + + obj._defaultValue = self._defaultValue + obj._currentValue = self._currentValue + obj._finalValue = self._finalValue + obj._value = self._value + + obj.when = self.when + obj._inInternalValue = self._inInternalValue + obj.array = self.array + obj.arrayPosition = self.arrayPosition + obj.arrayMinOccurs = self.arrayMinOccurs + obj.arrayMaxOccurs = self.arrayMaxOccurs + obj._pos = self._pos + obj._possiblePos = self._possiblePos + obj.rating = self.rating + obj.isStatic = self.isStatic + obj.fullNameDataModel = self.fullNameDataModel + + return obj + + + def asCType(self): + """ + Returns a ctypes module type for this DataElement. + """ + + raise Exception("Error: asCType method not implemented yet!") + + def pickleModel(self, model): + newModel = model.copy(None) + newModel.parent = None + + self._pickleRemoveInstanceMethods(newModel) + + return pickle.dumps(newModel) + + def unpickleModel(self, dump): + model = pickle.loads(dump) + self._pickleAddInstanceMethods(model) + + return model + + def _pickleAddInstanceMethods(self, model): + """ + Add back in the non-pickleable instancemethods. + """ + + if model.elementType == 'block': + model.toXml = new_instancemethod(Block.toXml, model) + + for c in dir(model): + if c == 'parent': + continue + + obj = getattr(model, c) + if isinstance(obj, Element): + self._pickleAddInstanceMethods(obj) + + if isinstance(model, ElementWithChildren): + for c in model: + if isinstance(c, Element): + self._pickleAddInstanceMethods(c) + + def _pickleRemoveInstanceMethods(self, model): + """ + Remove any instance methods. + """ + + #if hasattr(model, "__deepcopy__"): + # delattr(model, "__deepcopy__") + + if hasattr(model, "toXml") and (model.elementType == 'block' or model.elementType == 'namespace'): + delattr(model, "toXml") + + for c in dir(model): + if c == 'parent': + continue + + obj = getattr(model, c) + if isinstance(obj, Element): + self._pickleRemoveInstanceMethods(obj) + + if isinstance(model, ElementWithChildren): + for c in model: + if isinstance(c, Element): + self._pickleRemoveInstanceMethods(c) + + def setDefaults(self, data, dontCrack = False, mustPass = False): + """ + Set data elements defaultValue based on a Data object. + """ + + if data.fileName is not None: + + if dontCrack: + return + + ## Node: We are not ready to use the .peach files yet + ## still problems to work out! + + statPeach = None + + if statPeach is not None and statPeach.st_mtime > statFile.st_mtime and statPeach.st_mtime > statPit.st_mtime: + # Load pre-parsed peach file + print("[*] Loading model for: %s" % data.fileName) + + fd = open(data.fileName+".peach", "rb+") + data = fd.read() + fd.close() + + model = self.unpickleModel(data) + model.parent = self.parent + + # Remove self and insert model + index = self.parent.index(self) + del self.parent[self.name] + self.parent.insert(index, model) + + else: + logging.info("Cracking data from '%s' into DataModel '%s'" % (data.fileName, self.name)) + + with open(data.fileName, "rb") as fp: + stuff = fp.read() + + buff = PublisherBuffer(None, stuff) + + parent = self.parent + while parent.parent is not None: + parent = parent.parent + + cracker = PeachModule.Engine.incoming.DataCracker(parent) + #cracker.haveAllData = True + startTime = time.time() + cracker.crackData(self, buff, "setDefaultValue") + #if mustPass and not cracker.crackPassed: + # raise PeachException("Error, file did not properly parse.") + logging.info("Total time to crack data: %.2f" % (time.time() - startTime)) + logging.info("Building relation cache.") + self.BuildRelationCache() + + ## Pickle model + ##try: + ## fd = open(data.fileName + ".peach", "wb+") + ## fd.write(self.pickleModel(self)) + ## fd.close() + ##except: + ## try: + ## os.unlink(data.fileName+".peach") + ## except: + ## pass + + return cracker.crackPassed + + if data.expression is not None: + + stuff = evalEvent(data.expression, {}, data) + buff = PublisherBuffer(None, stuff) + + parent = self.parent + while parent.parent is not None: parent = parent.parent + + cracker = PeachModule.Engine.incoming.DataCracker(parent) + cracker.haveAllData = True + cracker.crackData(self, buff, "setDefaultValue") + + return + + for field in data: + obj = self + + for name in field.name.split('.'): + + # See if we have an array index "name[n]" + m = re.search(r"(.*)\[(-?\d+)\]$", name) + if m is not None: + name = m.group(1) + idx = int(m.group(2)) + + if hasattr(obj.children, name): + obj = getattr(obj.children, name) + elif hasattr(obj.children, name + "-0"): + obj = getattr(obj.children, name + "-0") + else: + raise PeachException("Error: Unable to locate field %s" % field.name) + + if idx == -1: + # Negative index will cause + # array to be removed + relations = obj.getRelationsOfThisElement() + del obj.parent[obj.name] + + # Remove any relations pointing to our + # removed array. + for r in relations: + try: + del r.parent[r.name] + except: + pass + + if r in r.parent.relations: + r.parent.relations.remove(r) + + break + + if obj.maxOccurs > 1 and idx >= 0: + # Convert first element to array + + orig = obj.copy(obj.parent) + obj.origional = orig + + index = obj.parent.index(obj) + del obj.parent[obj.name] + + obj.array = obj.name + obj.name += "-0" + obj.arrayPosition = 0 + obj.arrayMinOccurs = obj.minOccurs + obj.arrayMaxOccurs = obj.maxOccurs + obj.minOccurs = 1 + obj.maxOccurs = 1 + + obj.parent.insert(index, obj) + + if obj.array is not None: + + # Check and see if we need to expand + arrayCount = obj.getArrayCount() + if arrayCount == idx: + + # Expand object + newobj = obj.origional.copy(obj.parent) + newobj.name = "%s-%d" % (obj.array, arrayCount) + newobj.array = obj.array + newobj.arrayPosition = arrayCount + newobj.arrayMinOccurs = obj.arrayMinOccurs + newobj.arrayMaxOccurs = obj.arrayMaxOccurs + newobj.minOccurs = 1 + newobj.maxOccurs = 1 + + lastobj = obj.getArrayElementAt(newobj.arrayPosition - 1) + index = obj.parent.index(lastobj) + obj.parent.insert(index+1, newobj) + obj = newobj + + # Are we trying to expand by more then 1? + elif arrayCount < idx: + raise PeachException("Error: Attempting to expand array by more then one element. [%s]" % field.name) + + # Already expanded, just get correct index + else: + obj = obj.getArrayElementAt(idx) + + else: + raise PeachException("Error: Attempting to use non-array element as array. [%s]" % field.name) + + else: + if hasattr(obj.children, name): + obj = getattr(obj.children, name) + + else: + raise PeachException("Error: Unable to locate field %s" % field.name) + + # Was parent a choice? If so select this element. + if isinstance(obj.parent, Choice): + obj.parent.currentElement = obj + + # Removing other children. This is what incoming + # cracker does, so lets match that behaviour. + remove = [] + for child in obj.parent: + if isinstance(child, DataElement) and child != obj: + remove.append(child) + + for child in remove: + del obj.parent[child.name] + + + # If obj is a number, and field type is hex we + # need todo some mojo + if field.valueType == 'hex' \ + and (isinstance(obj, Number) or isinstance(obj, Flags) + or isinstance(obj, Flag)): + + # Convert hex to number + hexString = "" + for b in field.value: + h = hex(ord(b))[2:] + if len(h) < 2: + h = "0" + h + + hexString += h + + if len(hexString) == 0: + obj.setDefaultValue(str(0)) + + else: + obj.setDefaultValue(str(int(hexString, 16))) + + else: + obj.setDefaultValue(field.value) + + def BuildFullNameCache(self): + """ + Figure out our fullname and fullname in data model + """ + + for node in self._getAllRelationsInDataModel(): + node.fullName = node.getFullname() + node.fullNameDataModel = node.getFullnameInDataModel() + + def BuildRelationCache(self): + """ + Build the relation cache for this data element and it's children. + """ + + root = self.getRootOfDataMap() + if root != self: + root.BuildRelationCache() + return + + # 0. Build the fullname cache first + if self.fullName is None or self.fullNameDataModel is None: + self.BuildFullNameCache() + + # Update modelHasOffsetRelation when not using cache + if self.modelHasOffsetRelation is None: + relations = self._getAllRelationsInDataModel(self, False) + for r in relations: + if r.type == 'offset': + self.modelHasOffsetRelation = True + break + + # 1. Build list of all relations from here down + relations = self._getAllRelationsInDataModel(self, False) + + # 2. Fill in both cache lists + self.relationCache = [] + self.relationOfCache = {} + + for r in relations: + + # Skip from relations + if r.From is not None: + continue + + rStr = r.getFullnameInDataModel() + + # Update modelHasOffsetRelation + if r.type == 'count': + self.modelHasOffsetRelation = True + + if r.type != 'when': + ofStr = r.getOfElement().getFullnameInDataModel() + if not self.relationOfCache.has_key(ofStr): + self.relationOfCache[ofStr] = [] + + if rStr not in self.relationOfCache[ofStr]: + self.relationOfCache[ofStr].append(rStr) + + if rStr not in self.relationCache: + self.relationCache.append(rStr) + + + def get_minOccurs(self): + minOccurs = self._minOccurs + + if minOccurs is not None: + minOccurs = eval(str(minOccurs)) + + if minOccurs is None: + minOccurs = 1 + + elif minOccurs is not None: + minOccurs = int(minOccurs) + + return minOccurs + + def set_minOccurs(self, value): + if value is None: + self._maxOccurs = None + + else: + self._minOccurs = str(value) + + #: Minimum occurences (property) + minOccurs = property(get_minOccurs, set_minOccurs) + + def get_maxOccurs(self): + if self._maxOccurs is None: + return None + + return eval(str(self._maxOccurs)) + + def set_maxOccurs(self, value): + if value is None: + self._maxOccurs = None + else: + self._maxOccurs = str(value) + + #: Maximum occurences (property) + maxOccurs = property(get_maxOccurs, set_maxOccurs) + + def getAllChildDataElements(self, ret = None): + """ + Get all children data elements. Recursive + """ + + if ret is None: + ret = [] + + for child in self: + if isinstance(child, DataElement): + ret.append(child) + child.getAllChildDataElements(ret) + + return ret + + def hasRelation(self): + """ + Does this element have a size, count or offset relation? + """ + + for relation in self.relations: + if relation.type in ['size', 'count', 'offset']: + return True + + return False + + def _HasSizeofRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'size' and relation.of is not None and relation.From is None: + return True + + return False + + def _HasOffsetRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'offset' and relation.of is not None and relation.From is None: + return True + + return False + + def _GetOffsetRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'offset' and relation.of is not None and relation.From is None: + return relation + + return False + + def _GetSizeofRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'size' and relation.of is not None and relation.From is None: + return relation + + return None + + def GetWhenRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'when': + return relation + + return None + + def HasWhenRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'when': + return True + + return False + + def _HasCountofRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'count' and relation.of is not None and relation.From is None: + return True + + return False + + def _GetCountofRelation(self, node = None): + + if node is None: + node = self + + for relation in node.relations: + if relation.type == 'count' and relation.of is not None and relation.From is None: + return relation + + return None + + def getFullnameInDataModel(self): + """ + This will get fully qualified name of this element starting with the + root node of the data model. + """ + + if self.fullNameDataModel is not None: + return self.fullNameDataModel + + name = self.name + node = self + + while node.parent is not None and isinstance(node.parent, DataElement): + node = node.parent + name = "%s.%s" % (node.name, name) + + return name + + def getRootOfDataMap(self): + """ + Return the root of this data map. This should always return + a Template object. + """ + + root = self + while root.parent is not None and isinstance(root.parent, DataElement): + root = root.parent + + return root + + def findArrayByName(self, name): + """ + Will find first element in array named "name". + + This method should allow for more natural reuse of Blocks/Templates + w/o the user needing to think about it. + + @type name: string + @param name: Array to find. Does not support dotted name. + @rtype: DataElement + @return: DataElement or None + """ + + if name.find(".") > -1: + # Handle foo.bar.wee + parentName = name[:name.rfind(".")] + arrayName = name[name.rfind(".")+1:] + + parent = self.find(parentName) + if parent is None: + print(self) + print(self.getFullname()) + + for r in self.relations: + print("r.of:", r.of) + + raise Exception("Unable to locate [%s]" % parentName) + + obj = self._findArrayByName(parent, arrayName) + if obj is not None: + return obj + + for block in self._findAllBlocksGoingUp(): + obj = self._findArrayByName(block, name) + if obj is not None: + return obj + + return None + + def _findArrayByName(self, node, name): + """ + A generator that returns each instance of name in a data model. + """ + + # look at us! + if node.array == name: + # Try and locate array elem 0 + obj = node.getArrayElementAt(0) + if obj is not None: + return obj + + # Otherwise we found something :) + return node + + # look at each child + for child in node._children: + if isinstance(child, DataElement) and child.array == name and child.arrayPosition == 0: + return child + + # search down each child path + for child in node._children: + if isinstance(child, DataElement): + obj = self._findArrayByName(child, name) + if obj is not None: + return obj + + # done! + return None + + def _findDataElementByName(self, names): + for block in self._findAllBlocksGoingUp(): + #print "findDataElementByName: Looking for %s in %s" % (name, block.name) + for node in self.__findDataElementByName(block, names[0]): + obj = self._checkDottedName(node, names) + if obj is not None: + return obj + return None + + def findDataElementByName(self, name): + """ + Will find a data element in this data map by name. The search + pattern we use is to locate each block we are a member of + starting with the nearest. At each block we look down to see + if we can resolve the name. If not we move closer towards the + root of the data model. + + This method should allow for more natural reuse of Blocks/Templates + w/o the user needing to think about it. + + @type name: string + @param name: Name of element to find. Can be full or relative. + @rtype: DataElement + @return: DataElement or None + """ + + try: + self._fixRealParent(self) + + names = name.split('.') + + if self.name == names[0]: + obj = self._checkDottedName(self, names) + if obj is not None: + return obj + + # Assume if we have more then 2 parts we may be from the root + if len(names) > 2: + obj = self._checkDottedName(self.getRootOfDataMap(), names) + if obj is not None: + return obj + + + ret = self._findDataElementByName(names) + + return ret + + + finally: + self._unFixRealParent(self) + + def find(self, name): + """ + Alias for findDataElementByName. + + Will find a data element in this data map by name. The search + pattern we use is to locate each block we are a member of + starting with the nearest. At each block we look down to see + if we can resolve the name. If not we move closer towards the + root of the data model. + + This method should allow for more natural reuse of Blocks/Templates + w/o the user needing to think about it. + + @type name: string + @param name: Name of element to find. Can be full or relative. + @rtype: DataElement + @return: DataElement or None + """ + return self.findDataElementByName(name) + + def _findAllBlocksGoingUp(self): + """ + Generator that locates all blocks by walking up + our tree. + """ + + ret = [] + + obj = self + if isinstance(obj, Block) or isinstance(obj, Template): + ret.append(obj) + + while isinstance(obj.parent, DataElement): + obj = obj.parent + ret.append(obj) + + return ret + + def __findDataElementByName(self, node, name): + """ + A generator that returns each instance of name in a data model. + """ + + # look at us! + if node.name == name: + yield node + + # look at each child + if node._childrenHash.has_key(name): + yield node[name] + #else: + # for c in node: + # print "%s: %s != %s" % (node.name, c.name, name) + + # search down each child path + hist = set() + for child in node._children: + if isinstance(child, DataElement) and child not in hist: + hist.add(child) + for n in self.__findDataElementByName(child, name): + yield n + + # done! + + def _checkDottedName(self, node, names): + """ + Internal helper method, not for use! + """ + + if node.name != names[0]: + print("_checkDottedName: %s != %s" % (node.name, names[0])) + return None + + obj = node + for i in range(1, len(names)): + if not obj.has_key(names[i]): + #print "_checkDottedName: %s not found" % (names[i]) + #for child in obj: + # print "_checkDottedNames: Have:", child.name + # if child.parent != obj: + # print "_checkDottedNames: BAD PARRENT" + #for key in obj._childrenHash.keys(): + # print "_checkDottedName: Key:", key + return None + + obj = obj[names[i]] + + return obj + + def getAllPlacementsInDataModel(self): + """ + As the name says, recurse looking for + placements + """ + + if self.placement is not None: + yield self.placement + + for child in self: + if isinstance(child, DataElement): + for p in child.getAllPlacementsInDataModel(): + yield p + + def getDataElementByName(self, name): + """ + Get an element relative to here with a qualified name + """ + + names = name.split(".") + + if self.name != names[0]: + #print "[%s] != [%s]" % (self.name, names[0]) + return None + + obj = self + for i in range(1, len(names)): + if not obj.has_key(names[i]): + #print "no [%s]" % (names[i]) + return None + + obj = obj[names[i]] + + return obj + + + def getRelationOfThisElement(self, type): + """ + Locate and return a relation of this element. + """ + + self._fixRealParent(self) + try: + + if Engine.relationsNew: + # Assume both of and from relations in model + + for r in self.relations: + # Lets not return "when" :) + if r.type == 'when' or r.From is None: + continue + + if type is None or r.type == type: + obj = self.findDataElementByName(r.From) + + if obj is None: + raise Exception("Mismatched relations? Can't find r.From: '%s'" % r.From) + + if type is not None: + for rel in obj.relations: + if rel.type == type and rel.of.endswith(r.parent.name): + return rel + + print("r.parent.name:", r.parent.name) + print("rel.of:") + print("of-object:", obj) + print("of-obj.fullname:", obj.getFullname()) + print("self.fullname:", self.getFullname()) + print("r.From:", r.From) + print("len(obj.relations)", len(obj.relations)) + for rel in obj.relations: + print("rel:", rel.type, rel.of) + + raise Exception("Mismatched relations???") + + for rel in obj.relations: + if rel.type == 'when': + continue + + return rel + + raise Exception("MIssmatched relations2???") + + return None + + if self.relationCache is not None: + root = self.getRootOfDataMap() + name = self.getFullnameInDataModel() + + if root.relationOfCache.has_key(name): + for r in root.relationOfCache[name]: + r = self.find(r) + if r is not None and (type is None or r.type == type): + return r + + return None + + # Back to native python due to bug fixes + for r in self.getRelationsOfThisElement(): + if r.type == type: + return r + + return None + + finally: + self._unFixRealParent(self) + + def getRelationByName(self, name): + relName = name[name.rfind(".")+1:] + parentName = name[:name.rfind(".")] + obj = self.getRootOfDataMap().getDataElementByName(parentName) + + if obj is None: + print("Unable to locate:", parentName, name) + for r in obj: + if r.name == relName: + return r + + print("Returning None!") + return None + + def getRelationsOfThisElement(self): + """ + Locate and return a relation of this element. + """ + + relations = [] + + if Engine.relationsNew: + # Assume both of and from relations in model + + for r in self.relations: + # Lets not return "when" :) + if r.type == 'when' or r.From is None: + continue + + self._fixRealParent(self) + obj = self.find(r.From) + self._unFixRealParent(self) + + if obj is None: + raise Exception("Mismatched relations1??? [%s]" % r.From) + + for rel in obj.relations: + if rel.type == 'when' or rel.of is None or not rel.of.endswith(self.name): + continue + + #print rel.of + relations.append(rel) + + return relations + + self._fixRealParent(self) + if self.relationCache is not None: + #print "Using relation cache!" + root = self.getRootOfDataMap() + name = self.getFullnameInDataModel() + + if root.relationOfCache.has_key(name): + for r in root.relationOfCache[name]: + r = self.getRelationByName(r) + if r is not None: + relations.append(r) + + self._unFixRealParent(self) + return relations + + for r in self._genRelationsInDataModelFromHere(self, False): + # Huh, do we break something here? + if r.parent is None: + raise Exception("Relation with no parent!") + + if r.type == 'when' or r.of is None: + continue + + ## The last part of both names must match + ## for it to ever be the same + if r.of.split(".")[-1] != self.name: + continue + + if r.getOfElement() == self: + relations.append(r) + + self._unFixRealParent(self) + return relations + + def getLastNamePart(self, name): + """Return the last part of a name: + + foo.bar.hello -- return hello + """ + + names = name.split('.') + return names[-1] + + def _genRelationsInDataModelFromHere(self, node = None, useCache = True): + """ + Instead of returning all relations starting with + root we will walk up looking for relations. + """ + + if node is None: + node = self + + # Check if we are the top of the data model + if node.parent is None or not isinstance(node.parent, DataElement): + for r in self._getAllRelationsInDataModel(node, useCache): + if r is None: + continue + + yield r + + else: + # If not start searching + cur = node.parent + while cur is not None and isinstance(cur, DataElement): + for r in self._getAllRelationsInDataModel(cur, useCache): + if r is None: + continue + + yield r + + cur = cur.parent + + def _getAllRelationsInDataModel(self, node = None, useCache = True): + """ + Generator that gets all relations in data model. + """ + + if node is None: + node = self.getRootOfDataMap() + + # Use cache if we have it + if useCache and isinstance(node, DataElement) and node.relationCache is not None: + root = self.getRootOfDataMap() + for s in node.relationCache: + relName = s[s.rfind(".")+1:] + parentName = s[:s.rfind(".")] + obj = root.getDataElementByName(parentName) + + if obj is None: + continue + + for r in obj: + if r.name == relName: + yield r + + return + + for r in node.relations: + if r.From is None: + yield r + + for child in node._children: + if isinstance(child, DataElement): + for r in self._getAllRelationsInDataModel(child, useCache): + yield r + + def isArray(self): + """ + Check if this data element is part of an array. + """ + + if self.array is not None: + return True + + def getArrayCount(self): + """ + Return number of elements in array. + """ + + if not self.isArray(): + return -1 + + maxPos = int(self.arrayPosition) + for c in self.parent: + if isinstance(c, DataElement) and c.array == self.array: + if int(c.arrayPosition) > maxPos: + maxPos = int(c.arrayPosition) + + return maxPos+1 + + def getArrayElementAt(self, num): + """ + Return array element at position num. + """ + + if not self.isArray(): + return None + + for c in self.parent: + if isinstance(c, DataElement) and c.array == self.array and int(c.arrayPosition) == num: + return c + + return None + + def getCount(self): + """ + Return how many times this element occurs. If it is part + of an array the array size is returned, otherwise we will + look at the min/max and any count relations. + """ + + # If we are an array, we have a size already + if self.isArray(): + return self.getArrayCount() + + # Sanity check + if self.minOccurs == 1 and self.maxOccurs == 1: + return 1 + + # Otherwise see if we have a relation and min/max occurs + rel = self.getRelationOfThisElement('count') + if rel is not None: + try: + #print "of: ",self.getFullname() + #print "from:",rel.parent.getFullname() + #print rel.of + #print rel.From + cnt = int(rel.parent.getInternalValue()) + + if cnt < self.minOccurs: + cnt = self.minOccurs + elif cnt > self.maxOccurs: + cnt = self.maxOccurs + + return cnt + + except: + # If relation wasn't set with number then ignore + pass + + # If our minOccurs is larger than one and no relation + # go with the min. + if self.minOccurs > 1: + return self.minOccurs + + return 1 + + def getInternalValue(self): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int or long value. + """ + print(self) + raise Exception("TODO: Implement me!") + + def getRelationValue(self, value): + """ + This is common logic that was being duplicated across several data + elements. The logic is used in getInternalValue() to check if a + relation of size-of or count-of should modify the value. + + @rtype: string or number + @return: the value passed in or an integer if the value needed to be changed. + """ + + if self._HasSizeofRelation(self) and not self._inInternalValue: + try: + self._inInternalValue = True + relation = self._GetSizeofRelation(self) + value = relation.getOfElement().getSize() + value = relation.setValue(value) + + finally: + self._inInternalValue = False + + elif self._HasCountofRelation(self) and not self._inInternalValue: + # This could cause recursion, use this variable to prevent + self._inInternalValue = True + try: + + relation = self._GetCountofRelation(self) + ofElement = relation.getOfElement() + + # Ask for value before we get the count + # Why do we do this? When could this cause + # the element to expand into an array? + ofElement.getValue() + + #print "getRelationValue.count: ofElement:", ofElement.getFullname() + value = ofElement.getCount() + value = relation.setValue(value) + #print "getRelationValue.count: getCount:", value + #print "COUNT REALTION %s of %s: " % (relation.parent.name, relation.of), value + + finally: + self._inInternalValue = False + + elif self._HasOffsetRelation() and not self._inInternalValue and self.getRootOfDataMap().relationStringBuffer is not None: + try: + self._inInternalValue = True + relation = self._GetOffsetRelation(self) + ofElement = relation.getOfElement() + + # Look for the nearest relationStringBuffer + of = self.getRootOfDataMap().find(ofElement.getFullnameInDataModel()) + obj = of + while obj.relationStringBuffer is None: + obj = obj.parent + + newValue = obj.relationStringBuffer.getPosition(ofElement.getFullnameInDataModel()) + + # Set value + if newValue is not None: + value = relation.setValue(newValue) + + finally: + self._inInternalValue = False + + return value + + def getRawValue(self, sout = None): + """ + Get the value of this data element pre-transformers. + """ + raise Exception("TODO: Implement me!") + + def isInvalidated(self): + """ + Check if we need to reproduce this value. + + If we have a relation always True. + Otherwise False. + """ + + if len(self.relations) > 0: + return True + + return False + + def getSize(self): + """ + Determine length in bytes of this element. Please + override me and make faster :) + """ + # Default SLOW version + return len(self.getValue()) + + def getValue(self, sout = None): + """ + Get the value of this data element. + """ + + ## Otherwise lets generate and store our value + + # This method can be called while we are in it. + # so lets not use self.value to hold anything. + value = None + + if sout is not None: + sout.storePosition(self.getFullnameInDataModel()) + + ## If we have a cached value for ourselves, use it! + if self.elementType not in ['template', 'block', 'choice', 'flags', + 'xmlelement', 'xmlattribute', 'asn1type', 'custom']: + if self.value is not None and self.finalValue is None\ + and self.currentValue is None and self.fixup is None\ + and not self.hasRelation(): + + if sout is not None: + sout.write(self.value) + + #print "getValue(%s): Using self.value" % self.name + + return self.value + + if self.transformer is not None: + #print "getValue(%s): Transformer will be applied" % self.name + + value = self.getRawValue() + value = self.transformer.transformer.encode(value) + + if sout is not None: + sout.write(value) + + else: + #print "getValue(%s): Using getrawvalue" % self.name + value = self.getRawValue(sout) + #print "getValue(%s): Using getrawvalue: %s" % (self.name, type(value)) + + + # See if we need to repeat ourselvs. + if not self.isArray(): + count = self.getCount() + if count > 1: + #print "getValue(%s): Item is array, %d" % (self.name, count) + origValue = value + value *= count + + if sout is not None: + sout.write(origValue * (count-1)) + + if value is None: + raise Exception("value is None for %s type %s" % (self.name, self.elementType)) + + if self.elementType != 'flag' and type(value) == type(5): + print("getValue(%s): WHOA, Returning integer!!!" % self.name) + print("self:", self) + print("self.name:", self.name) + print("self.getfullname", self.getFullnameInDataModel()) + print("self.maxOccurs", self.maxOccurs) + print("self.ref:", self.ref) + print("self.getInternalValue", self.getInternalValue()) + print("len(self._children)", len(self._children)) + for child in self: + print("child:", child) + print("child.name", child.name) + print("child.getValue", child.getValue()) + raise Exception("WHOA, Returning integer!!") + + self.value = value + return self.value + + def setDefaultValue(self, value): + """ + Set the default value for this data element. + """ + self.defaultValue = value + + def setValue(self, value): + """ + Set the current value for this data element + """ + self.currentValue = value + self.getValue() + + def reset(self): + """ + Reset the value of this data element back to + the default. + """ + self.currentValue = None + self.value = None + + def resetDataModel(self, node = None): + """ + Reset the entire data model. + """ + + if node is None: + node = self.getRootOfDataMap() + + node.reset() + + for c in node._children: + if isinstance(c, DataElement): + self.resetDataModel(c) + + def _fixRealParent(self, node): + """ + Look for realParent attributes and + enable that nodes correct parent. + + We could have multiple layers of realParents + to deal with, so keep going until we find no more. + """ + + #print "---> FIX REAL PARENT <-----", node + #print traceback.format_stack() + + while True: + # 1. Find root + + root = node + while root.parent is not None: + root = root.parent + + # 2. Check if has a realParent + + if hasattr(root, 'realParent') and root.realParent is not None: + #print "FIXING:", root + root.parent = root.realParent + else: + break + + # done! + + def _unFixRealParent(self, node): + """ + Locate any realParent attributes in our + parent chain and enable them by setting + that nodes parent to None. + + We could have several layers of realParents + so check out each of our parents back to + root. + """ + + #print "---> UN-FIX REAL PARENT <-----", node + #print traceback.format_stack() + + parents = [node] + + root = node + while isinstance(root.parent, DataElement): + root = root.parent + parents.append(root) + + for parent in parents: + # 1. Look for fake root + if hasattr(parent, 'realParent') and parent.parent is not None: + # 2. Remove parent link + #print "UNFIXING:", parent + parent.parent = None + + def calcLength(self): + """ + Calculate length + """ + + environment = { + 'self' : self + } + + try: + self._fixRealParent(self) + return evalEvent(self.lengthCalc, environment, self) + finally: + self._unFixRealParent(self) + +class Transformer(ElementWithChildren): + """ + The Trasnfomer DOM object. Should only be a child of + a data element. + """ + def __init__(self, parent, transformer = None): + ElementWithChildren.__init__(self, None, parent) + self.elementType = 'transformer' + + # Instance of actual transformer + self.transformer = transformer + + # Class string used to create transformer instance + self.classStr = None + + def clone(self, obj = None): + if obj is None: + obj = Transformer(self.parent, self.transformer) + + obj.classStr = self.classStr + + return obj + + def changesSize(self): + return self.transformer.changesSize() + +class Fixup(ElementWithChildren): + """ + Fixup DOM element. Child of data elements only. + """ + def __init__(self, parent, fixup = None): + ElementWithChildren.__init__(self, None, parent) + self.elementType = 'fixup' + self.classStr = None + self.fixup = fixup + + def clone(self, obj = None): + + if obj is None: + obj = Fixup(self.parent, self.fixup) + + obj.elementType = self.elementType + obj.classStr = self.classStr + + return obj + + +class Placement(ElementWithChildren): + """ + Indicates were a block goes after cracking. + """ + def __init__(self, parent): + ElementWithChildren.__init__(self, None, parent) + self.elementType = 'placement' + self.after = None + self.before = None + + def clone(self, obj = None): + + if obj is None: + obj = Placement(self.parent) + + obj.elementType = self.elementType + obj.after = self.after + obj.before = self.before + + return obj + +class Param(ElementWithChildren): + def __init__(self, parent): + ElementWithChildren.__init__(self, None, parent) + self.elementType = 'param' + self.valueType = 'string' + + +class Peach(ElementWithChildren): + """ + This is our root node container. + """ + def __init__(self): + ElementWithChildren.__init__(self, 'peach', None) + + self.elementType = 'peach' + self.version = None + self.description = None + self.author = None + + +class Test(ElementWithChildren): + def __init__(self, name, parent = None): + ElementWithChildren.__init__(self, name, parent) + + self.elementType = 'test' + self.description = None + self.template = None + self.data = None + self.publishers = None + self.stateMachine = None + self.ref = None + self.mutators = None + self.mutator = None + + # To mark Mutatable elements + self.mutatables = [] + + def getMutators(self): + """ + returns a lsit of mutators + """ + + ret = [] + for m in self.mutators: + if m.elementType == 'mutator': + ret.append(m) + + return ret + + + def markMutatableElements(self, node): + if len(self.mutatables) == 0: + return + + domDict = {} + xmlDom = self.stateMachine.toXmlDomLight(node, domDict) + + for opt in self.mutatables: + isMutable = opt[0] + xpath = str(opt[1]) + + try: + xnodes = xmlDom.xpath(xpath) + print("XPATH: %s # of nodes: %s" % (xpath, str(len(xnodes)))) + if len(xnodes) == 0: + print("Warning: XPath:[%s] must return at least an XNode. Please check your references or xpath declarations." % xpath) + continue + + for node in xnodes: + try: + elem = domDict[node] + + if isinstance(elem, Mutatable): + elem.setMutable(isMutable) + + except KeyError: + pass + + except SyntaxError: + raise PeachException("Invalid xpath string: %s" % xpath) + +class Run(ElementWithChildren): + def __init__(self, name, parent = None): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'run' + self.description = None + self.tests = [] + self.parent = None + self.waitTime = 0 + + def getLoggers(self): + ret = [] + + for child in self: + if child.elementType == 'logger': + ret.append(child) + + if len(ret) == 0: + return None + + return ret + + +class Agent(ElementWithChildren): + def __init__(self, name, parent = None): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'agent' + self.description = None + self.location = None + self.password = None + + def getPythonPaths(self): + p = [] + + for child in self: + if child.elementType == 'pythonpath': + p.append({'name': child.name}) + + if len(p) == 0: + return None + + return p + + def getImports(self): + p = [] + + for child in self: + if child.elementType == 'import': + p.append({'import': child.importStr, 'from' : child.fromStr}) + + if len(p) == 0: + return None + + return p + +class Monitor(ElementWithChildren): + def __init__(self, name, parent = None): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'monitor' + self.classStr = None + self.params = {} + +############################################################################# +## Data Generating Elements + +class Template(DataElement): + """ + Essentially a Block, but is the top level element in a data model. + + TODO: Refactor this to DataModel + """ + + ctypeClassName = 0 + + def __init__(self, name): + DataElement.__init__(self, name, None) + self.elementType = 'template' + self.ref = None + self.length = None + self.lengthType = None + + def clone(self, obj = None): + + if obj is None: + obj = Template(self.name) + + DataElement.clone(self, obj) + + obj.ref = self.ref + obj.length = self.length + obj.lengthType = self.lengthType + + for c in self: + obj.append( c.clone() ) + + return obj + + def asCType(self): + + Template.ctypeClassName += 1 + ctypeClassName = Template.ctypeClassName + + exec("""class TemplateTempClass%d(ctypes.Structure): + pass +""" % ctypeClassName) + + values = [] + fields = [] + for c in self: + if isinstance(c, DataElement): + cValue = c.asCType() + fields.append((c.name, type(cValue))) + values.append((c.name, cValue)) + + exec("TemplateTempClass%d._fields_ = fields" % ctypeClassName) + exec("ret = TemplateTempClass%d()" % ctypeClassName) + + for c in values: + setattr(ret, c[0], c[1]) + + # Are we a pointer? + if self.isPointer: + if self.pointerDepth is not None: + for i in range(int(self.pointerDepth)): + ret = ctypes.pointer(ret) + else: + ret = ctypes.pointer(ret) + + return ret + + def asCTypeType(self): + + Template.ctypeClassName += 1 + ctypeClassName = Template.ctypeClassName + + exec("""class TemplateTempClass%d(ctypes.Structure): + pass +""" % ctypeClassName) + + values = [] + fields = [] + for c in self: + if isinstance(c, DataElement): + cValue = c.asCType() + fields.append((c.name, type(cValue))) + values.append((c.name, cValue)) + + exec("TemplateTempClass%d._fields_ = fields" % ctypeClassName) + exec("ret = TemplateTempClass%d" % ctypeClassName) + + # Are we a pointer? + if self.isPointer: + if self.pointerDepth is not None: + for i in range(int(self.pointerDepth)): + ret = ctypes.POINTER(ret) + else: + ret = ctypes.POINTER(ret) + + return ret + + def getSize(self): + """ + Return the length of this data element. Try and + be fast about it! + """ + + if self.transformer is not None and not self.transformer.changesSize(): + return len(self.getValue()) + + if self.fixup is not None: + return len(self.getValue()) + + if self.currentValue is not None: + return len(self.getValue()) + + size = 0 + for c in self: + if isinstance(c, DataElement): + size += c.getSize() + + return size + + def hasLength(self): + if self.length is not None: + return True + + return False + + def getLength(self): + """ + Get the length of this element. + """ + + if self.lengthType == 'calc': + self.length = self.calcLength() + + if self.length is not None and self.length < 0: + self.length = None + + elif self.isStatic: + return len(self.getValue()) + + return self.length + + def getValue(self, sout = None): + """ + Template needs a custom getValue method! + """ + try: + # Sometimes a Template becomes a Block + if self.elementType == 'template': + self.relationStringBuffer = sout + + return DataElement.getValue(self, sout) + + finally: + self.relationStringBuffer = None + + def isInvalidated(self): + """ + Check if we need to reproduce this value. + + If we have a relation always True. + Otherwise False. + """ + + if len(self.relations) > 0: + return True + + # Check children + for c in self: + if isinstance(c, DataElement) and c.isInvalidated(): + return True + + # Return false + return False + + def getInternalValue(self, sout = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + + @type sout: StreamBuffer + @param sout: Output stream + """ + + #print "getInternalValue(%s)" % self.name + value = "" + + # 0. If using a stream store our location + if sout is not None: + pos = sout.storePosition(self.getFullnameInDataModel()) + + # 1. Override with currentValue + + if self.currentValue is not None: + #print "getInternalValue(%s): using currentValue" % self.name + + value = self.currentValue + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + return value + + # 2. Get value from children + + for c in self: + if isinstance(c, DataElement): + try: + if self.fixup is not None or self.transformer is not None: + cv = c.getValue() + + value += cv + else: + cv = c.getValue(sout) + + value += cv + + except: + print(sys.exc_info()) + raise + + # 3. Fixup + + if self.fixup is not None: + self.fixup.fixup.context = self + ret = self.fixup.fixup.do_fixup() + if ret is not None: + value = ret + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + return value + + def getRawValue(self, sout = None): + """ + Get value for this data element. + + Performs any needed transforms to produce + value. + """ + + return self.getInternalValue(sout) + + def setValue(self, value): + """ + Override value created via children. + """ + + self.currentValue = value + + def reset(self): + """ + Reset current state. + """ + self.currentValue = None + self.value = None + + +class Choice(DataElement): + """ + Choice, chooses one or emore sub-elements + """ + def __init__(self, name, parent): + """ + Don't put too much logic here. See HandleBlock in the parser. + """ + DataElement.__init__(self, name, parent) + self.elementType = 'choice' + self.currentElement = None + self.length = None + self.lengthType = None + + #: Used by cracker to optimize choice cracking + self.choiceCache = (False, 0, None) + + def clone(self, obj = None): + + if obj is None: + obj = Choice(self.name, self.parent) + + DataElement.clone(self, obj) + + obj.currentElement = self.currentElement + obj.elementType = self.elementType + obj.length = self.length + obj.lengthType = self.lengthType + + for c in self: + obj.append( c.clone() ) + + return obj + + def asCType(self): + + self.getValue() + return self.currentElement.asCType() + + def getSize(self): + """ + Return the length of this data element. Try and + be fast about it! + """ + + if self.transformer is not None or self.fixup is not None: + return len(self.getValue()) + + if self.currentElement is not None: + return self.currentElement.getSize() + + if self.currentValue is not None: + return len(self.getValue()) + + return len(self.getValue()) + + def hasLength(self): + if self.length is not None: + return True + + return False + + def getLength(self): + """ + Get the length of this element. + """ + + if self.lengthType == 'calc': + self.length = self.calcLength() + + if self.length is not None and self.length < 0: + self.length = None + + elif self.isStatic: + return len(self.getValue()) + + return self.length + + + def SelectedElement(self, value = None): + + if value is not None: + self.currentElement = self[value] + + return self.currentElement + + def isInvalidated(self): + """ + Check if we need to reproduce this value. + + If we have a relation always True. + Otherwise False. + """ + + if len(self.relations) > 0: + return True + + # Check children + if self.currentElement is None: + return True + + if self.currentElement.isInvalidated(): + return True + + # Return false + return False + + def getInternalValue(self, sout = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + return self.getRawValue(sout) + + def getRawValue(self, sout = None): + + value = "" + if self.currentValue is not None: + value = self.currentValue + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + else: + if self.currentElement is None: + for n in self: + if isinstance(n, DataElement): + self.currentElement = n + break + + value = self.currentElement.getValue(sout) + + if value is None or type(value) != type(""): + print("Choice.getRawValue: value is null or string!", type(value)) + print("Choice.getRawValue: ", self.currentElement.getFullname()) + print("Choice.getRawValue: ", self.currentElement.elementType) + print("Choice.getRawValue: ", self.currentElement) + raise Exception("Value should not be null or string!") + + return value + +class Block(DataElement): + """ + Block or sequence of other data types. + """ + + ctypeClassName = 0 + + def __init__(self, name, parent): + """ + Don't put too much logic here. See HandleBlock in the parser. + """ + DataElement.__init__(self, name, parent) + self.elementType = 'block' + self.length = None + self.lengthType = None + + def toXml(self, parent): + node = etree.Element('Block') + parent.append(node) + + self._setAttribute(node, 'name', self.name) + self._setAttribute(node, 'ref', self.ref) + + for child in self: + if self._xmlHadChild(child): + child.toXml(node) + + return node + + def clone(self, obj = None): + + if obj is None: + obj = Block(self.name, self.parent) + + DataElement.clone(self, obj) + + obj.elementType = self.elementType + obj.length = self.length + obj.lengthType = self.lengthType + + for c in self: + obj.append( c.clone() ) + + if obj.getValue() != self.getValue(): + print("Value missmatch") + sys.exit(0) + for item in dir(self): + if not hasattr(obj, item): + print("Missing:", item) + sys.exit(0) + return obj + + def asCType(self): + + Block.ctypeClassName += 1 + ctypeClassName = Block.ctypeClassName + + exec("""class BlockTempClass%d(ctypes.Structure): pass""" % ctypeClassName) + + values = [] + fields = [] + for c in self: + if isinstance(c, DataElement): + cValue = c.asCType() + fields.append( (c.name, type(cValue) ) ) + values.append((c.name, cValue)) + + exec("BlockTempClass%d._fields_ = fields" % ctypeClassName) + exec("ret = BlockTempClass%d()" % ctypeClassName) + + for c in values: + setattr(ret, c[0], c[1]) + + # Are we a pointer? + if self.isPointer: + if self.pointerDepth is not None: + for i in range(int(self.pointerDepth)): + ret = ctypes.pointer(ret) + else: + ret = ctypes.pointer(ret) + + return ret + + def asCTypeType(self): + + Block.ctypeClassName += 1 + ctypeClassName = Block.ctypeClassName + + exec("""class BlockTempClass%d(ctypes.Structure): pass""" % ctypeClassName) + + values = [] + fields = [] + for c in self: + if isinstance(c, DataElement): + cValue = c.asCType() + fields.append( (c.name, type(cValue) ) ) + values.append((c.name, cValue)) + + exec("BlockTempClass%d._fields_ = fields" % ctypeClassName) + exec("ret = BlockTempClass%d" % ctypeClassName) + + # Are we a pointer? + if self.isPointer: + if self.pointerDepth is not None: + for i in range(int(self.pointerDepth)): + ret = ctypes.POINTER(ret) + else: + ret = ctypes.POINTER(ret) + + return ret + + def hasLength(self): + if self.length is not None: + return True + + return False + + def getLength(self): + """ + Get the length of this element. + """ + + if self.lengthType == 'calc': + self.length = self.calcLength() + + if self.length is not None and self.length < 0: + self.length = None + + elif self.isStatic: + return len(self.getValue()) + + return self.length + + def isInvalidated(self): + """ + Check if we need to reproduce this value. + + If we have a relation always True. + Otherwise False. + """ + + if len(self.relations) > 0: + return True + + # Check children + for c in self: + if isinstance(c, DataElement): + if c.isInvalidated(): + return True + + # Return false + return False + + def getInternalValue(self, sout = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + + @type sout: StreamBuffer + @param sout: Output stream + """ + + #print "Block.getInternalValue(%s)" % self.name + value = "" + + # 0. If using a stream store our location + if sout is not None: + pos = sout.storePosition(self.getFullnameInDataModel()) + + # 1. Override with currentValue + + if self.currentValue is not None: + value = str(self.currentValue) + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + return value + + # 2. Get value from children + + if self.transformer is None and self.fixup is None: + for c in self: + if isinstance(c, DataElement): + try: + value += c.getValue(sout) + + except: + print(c) + print(repr(value)) + print(repr(c.getValue(sout))) + print("c.getValue(sout) failed." + repr(sys.exc_info())) + print("c.name: %s" % c.name) + traceback.print_stack() + print("---------------") + raise + else: + print("FOUND NON DATAELEMENT:", c) + + else: + + # To support offset relations in children we will + # get the value twice using our own stringBuffer + + stringBuffer = StreamBuffer() + self.relationStringBuffer = stringBuffer + + for c in self: + if isinstance(c, DataElement): + try: + #print "Block.getInternalValue(%s): Getting child value" % self.name + value += c.getValue(stringBuffer) + + except: + #print "value: [%s]" % repr(value) + print("c.name: %s" % c.name) + print("---------------") + raise + + stringBuffer.setValue("") + stringBuffer.seekFromStart(0) + value = "" + + for c in self: + if isinstance(c, DataElement): + try: + value += c.getValue(stringBuffer) + + except: + #print "value: [%s]" % repr(value) + print("c.name: %s" % c.name) + print("---------------") + raise + + # 3. Fixup + + if self.fixup is not None: + #print "Block.getInternalValue(%s): Using fixup" % self.name + self.fixup.fixup.context = self + ret = self.fixup.fixup.do_fixup() + if ret is not None: + value = ret + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + if value is None: + raise Exception("value should not be None here") + + return value + + def getRawValue(self, sout = None): + """ + Get value for this data element. + + Performs any needed transforms to produce + value. + """ + + return self.getInternalValue(sout) + + +class Number(DataElement): + """ + A numerical field + """ + + _allowedSizes = [8, 16, 24, 32, 64] + + #: Default value used for size + defaultSize = 8 + #: Default value used for endian + defaultEndian = 'little' + #: Default value used for signed + defaultSigned = False + #: Default value used for valueType + defaultValueType = 'string' + + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'number' + + self.size = Number.defaultSize + self.signed = Number.defaultSigned + self.valueType = Number.defaultValueType + + # When None, the property method will + # return the default. This allows tricky users + # to change Endian ness after we start cracking + # a template file. + self._endian = None + + self.ref = None + self.currentValue = None + self.generatedValue = None + self.insideRelation = False + + def clone(self, obj = None): + + if obj is None: + obj = Number(self.name, self.parent) + + DataElement.clone(self, obj) + + obj.size = self.size + obj.signed = self.signed + obj.valueType = self.valueType + obj._endian = self._endian + obj.ref = self.ref + obj.insideRelation = self.insideRelation + + return obj + + def getEndian(self): + if self._endian is None: + return Number.defaultEndian + + return self._endian + def setEndian(self, value): + self._endian = value + endian = property(getEndian, setEndian, None) + + def asCType(self): + + if self.size == 24: + raise Exception("Number.asCType does not support 24bit numbers") + + value = int(self.getInternalValue()) + ret = None + + if self.signed: + evalString = "ctypes.c_int%d(value)" % self.size + else: + evalString = "ctypes.c_uint%d(value)" % self.size + + ret = eval(evalString) + + return ret + + def getSize(self): + """ + Return the length of this data element. Try and + be fast about it! + """ + + # Note in the case of numbers a fixup will not + # make a difference + if self.transformer is not None: + return len(self.getValue()) + + return self.size/8 + + def getMinValue(self): + """ + Get the minimum value this number can have. + """ + + if not self.signed: + return 0 + + max = int('FF'*int(self.size/8), 16) + return 0 - max + + def getMaxValue(self): + """ + Get the maximum value for this number. + """ + max = int('FF'*int(self.size/8), 16) + if self.signed: + return max/2 + + return max + + def getInternalValue(self, sout = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + + # 0. Override default? + if self.currentValue is not None: + return self.currentValue + + # 1. Our value to return + value = 0 + + # 2. Have default value? + + if self.defaultValue is not None: + value = self.defaultValue + + # 3. Relation? + + value = self.getRelationValue(value) + + # 4. fixup? + if self.fixup is not None: + self.fixup.fixup.context = self + ret = self.fixup.fixup.do_fixup() + if ret is not None: + value = ret + + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + return value + + def pack(self, num): + """ + Pack a number into proper format for this Number + """ + + # 1. Get the transformer we need + isSigned = 0 + if self.signed: + isSigned = 1 + + isLittleEndian = 0 + if self.endian == 'little': + isLittleEndian = 1 + + if self.size == 8: + trans = Transformers.Type.Integer.AsInt8(isSigned, isLittleEndian) + elif self.size == 16: + trans = Transformers.Type.Integer.AsInt16(isSigned, isLittleEndian) + elif self.size == 24: + trans = Transformers.Type.Integer.AsInt24(isSigned, isLittleEndian) + elif self.size == 32: + trans = Transformers.Type.Integer.AsInt32(isSigned, isLittleEndian) + elif self.size == 64: + trans = Transformers.Type.Integer.AsInt64(isSigned, isLittleEndian) + + # 2. Encode number + + try: + # This could fail if our override was not + # a number or empty ('') + num = int(num) + except: + num = 0 + + return trans.encode(int(num)) + + def unpack(self, buff): + """ + Unpack a number from proper format fo this Number + """ + # 1. Get the transformer we need + isSigned = 0 + if self.signed: + isSigned = 1 + + isLittleEndian = 0 + if self.endian == 'little': + isLittleEndian = 1 + + if self.size == 8: + trans = Transformers.Type.Integer.AsInt8(isSigned, isLittleEndian) + elif self.size == 16: + trans = Transformers.Type.Integer.AsInt16(isSigned, isLittleEndian) + elif self.size == 24: + trans = Transformers.Type.Integer.AsInt24(isSigned, isLittleEndian) + elif self.size == 32: + trans = Transformers.Type.Integer.AsInt32(isSigned, isLittleEndian) + elif self.size == 64: + trans = Transformers.Type.Integer.AsInt64(isSigned, isLittleEndian) + + # 2. Encode number + + try: + # This could fail if our override was not + # a number or empty ('') + return trans.decode(buff) + + except: + pass + + return 0 + + def getRawValue(self, sout = None): + + value = self.getInternalValue() + if value == '': + return '' + + ret = self.pack(value) + + if sout is not None: + sout.write(ret, self.getFullnameInDataModel()) + + return ret + +try: + from pyasn1.type import univ, char, useful + import pyasn1.codec.ber.encoder + import pyasn1.codec.cer.encoder + import pyasn1.codec.der.encoder + from pyasn1.type import tag + + class Asn1Type(DataElement): + """ + An XML Element + """ + + ASN1_TYPES = ["BitString", "Boolean", "Choice", "Enumerated", "Integer", "Null", + "ObjectIdentifier", "OctetString", "Real", "Sequence", + "SequenceAndSetBase", "SequenceOf", "Set", "SetOf"] + + ASN1_ENCODE = ["ber", "cer", "der"] + + ASN1_MAP = { + "BitString":univ.BitString, + "Boolean":univ.Boolean, + "Choice":univ.Choice, + "Enumerated":univ.Enumerated, + "Integer":univ.Integer, + "Null":univ.Null, + "ObjectIdentifier":univ.ObjectIdentifier, + "OctetString":univ.OctetString, + "Real":univ.Real, + "Sequence":univ.Sequence, + "SequenceAndSetBase":univ.SequenceAndSetBase, + "SequenceOf":univ.SequenceOf, + "Set":univ.Set, + "SetOf":univ.SetOf, + "UTF8String":char.UTF8String, + "NumericString":char.NumericString, + "PrintableString":char.PrintableString, + "TeletexString":char.TeletexString, + "VideotexString":char.VideotexString, + "IA5String":char.IA5String, + "GraphicString":char.GraphicString, + "VisibleString":char.VisibleString, + "GeneralString":char.GeneralString, + "UniversalString":char.UniversalString, + "BMPString":char.BMPString, + "GeneralizedTime":useful.GeneralizedTime, + "UTCTime":useful.UTCTime, + } + + ASN1_TAG_CLASS_MAP = { + "universal" : 0x00, + "application" : 0x40, + "context" : 0x80, + "private" : 0xc0, + } + + ASN1_TAG_TYPE_MAP = { + "simple" : 0x00, + "constructed" : 0x20, + } + + ASN1_TAG_CAT_MAP = { + "implicit":0x01, + "explicit":0x02, + "untagged":0x04, + } + + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'asn1type' + self.currentValue = None + self.generatedValue = None + self.insideRelation = False + self.asn1Type = "" + self.encodeType = "ber" + self.tagClass = None + self.tagFormat = None + self.tagCategory = None + self.tagNumber = None + + def clone(self, obj = None): + + if obj is None: + obj = Asn1Type(self.name, self.parent) + + DataElement.clone(self, obj) + + obj.elementType = self.elementType + obj.insideRelation = self.insideRelation + obj.asn1Type = self.asn1Type + obj.encodeType = self.encodeType + + return obj + + def asCType(self): + # TODO: Should support Ctype, return a string or something... + raise Exception("This DataElement (Asn1Type) does not support asCType()!") + + def int2bin(self, n, count=32): + """returns the binary of integer n, using count number of digits""" + return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)]) + + def blob2bin(self, data): + ret = "" + for b in data: + ret += self.int2bin(ord(b), 8) + + return ret + + def getInternalValue(self, sout = None, parent = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + try: + + if parent is None: + haveParent = False + elif isinstance(parent, Asn1Type): + haveParent = True + + asn1Obj = None + value = None + childAsn1Objs = [] + for c in self: + if isinstance(c, Asn1Type): + childAsn1Objs.append(c.getInternalValue(None, self)) + + elif self.asn1Type == 'BitString' and isinstance(c, DataElement): + b = c.getValue() + b = self.blob2bin(b) + if b[:8] == '00000000': + b = b[8:] + + value = "'%s'B" % b + + elif isinstance(c, Number): + value = int(c.getInternalValue()) + + elif isinstance(c, DataElement): + value = c.getValue() + + if value is not None: + #if (self.objType == int or self.objType == long): + # if type(value) not in [int, long]: + # try: + # value = long(value) + # except: + # value = long(0) + + try: + if self.tagNumber is not None: + if self.tagCategory == "implicit": + tagSet=self.ASN1_MAP[self.asn1Type].tagSet.tagImplicitly( + tag.Tag(self.tagClass, self.tagFormat, self.tagNumber)) + else: + tagSet=self.ASN1_MAP[self.asn1Type].tagSet.tagExplicitly( + tag.Tag(self.tagClass, self.tagFormat, self.tagNumber)) + + asn1Obj = self.ASN1_MAP[self.asn1Type](value, tagSet = tagSet) + + else: + asn1Obj = self.ASN1_MAP[self.asn1Type](value) + except: + #raise SoftException("Error building asn.1 obj") + print(sys.exc_info()) + raise PeachException("Error building asn.1 obj") + + else: + try: + #asn1Obj = self.ASN1_MAP[self.asn1Type](self.asnTagSet, self.asn1Spec) + if self.tagNumber is not None: + if self.tagCategory == "implicit": + tagSet=self.ASN1_MAP[self.asn1Type].tagSet.tagImplicitly( + tag.Tag(self.tagClass, self.tagFormat, self.tagNumber)) + else: + tagSet=self.ASN1_MAP[self.asn1Type].tagSet.tagExplicitly( + tag.Tag(self.tagClass, self.tagFormat, self.tagNumber)) + + asn1Obj = self.ASN1_MAP[self.asn1Type](tagSet = tagSet) + + else: + asn1Obj = self.ASN1_MAP[self.asn1Type]() + + except: + print(sys.exc_info()) + raise PeachException("Error building asn.1 obj") + + if len(childAsn1Objs) > 0: + for i in range(len(childAsn1Objs)): + asn1Obj.setComponentByPosition(i, childAsn1Objs[i]) + + if not haveParent: + # Perform encoding ourselves + encoder = eval("pyasn1.codec.%s.encoder" % self.encodeType) + + try: + #print asn1Obj + bin = encoder.encode(asn1Obj) + except: + print(self.encodeType) + print(encoder) + print(asn1Obj) + print(sys.exc_info()) + raise SoftException("Error encoding asn.1 obj") + + #print asn1Obj + + return bin + + # Otherwise allow parent to perform encoding + return asn1Obj + + except: + print(sys.exc_info()) + print("Warning, ASN.1 Failed to emmit, this is OK after first iteration.") + return "" + + def getRawValue(self, sout = None, parent = None): + return self.getInternalValue(sout, parent) + +except: + pass + +class XmlElement(DataElement): + """ + An XML Element + """ + + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'xmlelement' + self.currentValue = None + self.generatedValue = None + self.insideRelation = False + self.elementName = None + self.xmlNamespace = None + + def asCType(self): + # TODO: Should support Ctype, return a string or something... + raise Exception("This DataElement (XmlElement) does not support asCType()!") + + def toXmlDomLight(self, parent, dict): + """ + Convert to an XML DOM object tree for use in xpath queries. + Does not include values (Default or otherwise) + """ + + owner = parent.getroottree() + if owner is None: + owner = parent + + node = etree.Element(self.name) + + node.set("elementType", self.elementType) + node.set("name", self.name) + node.set("elementName", self.elementName) + + if hasattr(self, 'ref') and self.ref is not None: + self._setXmlAttribute(node, "ref", self.ref) + + self._setXmlAttribute(node, "fullName", self.getFullname()) + + dict[node] = self + dict[self] = node + + parent.append(node) + + return node + + def getInternalValue(self, sout = None, parent = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + # 0. If using a stream store our location + if sout is not None: + pos = sout.storePosition(self.getFullnameInDataModel()) + + # 1. Override with currentValue + + if self.currentValue is not None: + value = str(self.currentValue) + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + return value + + if self.xmlNamespace is None: + node = etree.Element(self.elementName) + else: + node = etree.Element("{%s}%s" % (self.xmlNamespace, self.elementName)) + + if parent is None: + haveParent = False + parent = node + else: + haveParent = True + parent.append(node) + + for c in self: + if isinstance(c, XmlAttribute): + c.getInternalValue(None, node) + + elif isinstance(c, XmlElement): + c.getInternalValue(None, node) + + elif isinstance(c, DataElement): + value = c.getValue().decode('latin-1').encode('utf8') + #value = c.getValue() + if len(node) > 0: + node[-1].tail = value + else: + node.text = value + + if not haveParent: + + try: + encoding = "utf8" + unistr = etree.tostring(parent, encoding="unicode") + return unistr.encode(encoding, "xmlcharrefreplace") + #return unistr + except: + return u"" + + return None + + def getRawValue(self, sout = None, parent = None): + return self.getInternalValue(sout, parent) + +class XmlAttribute(DataElement): + """ + An XML Element + """ + + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'xmlattribute' + self.currentValue = None + self.generatedValue = None + self.insideRelation = False + self.attributeName = None + self.xmlNamespace = None + + def asCType(self): + raise Exception("This DataElement (XmlAttribute) does not support asCType()!") + + def getInternalValue(self, sout, parent): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + + if parent is None: + return u"" + + value = "" + for c in self: + if isinstance(c, DataElement): + value = c.getValue() + break + + if self.xmlNamespace is not None: + attrib = "{%s}%s" % (self.xmlNamespace, self.attributeName) + else: + attrib = self.attributeName + parent.set(attrib, value.decode('latin-1').encode('utf8')) + + return None + + def getRawValue(self, sout = None, parent = None): + return self.getInternalValue(sout, parent) + + +class String(DataElement): + """ + A string field + """ + + EncodeAs = { + 'char':'iso-8859-1', + 'wchar':'utf-16le', + 'utf8':'utf-8', + 'utf-8':'utf-8', + 'utf-16le' : 'utf-16le', + 'utf-16be' : 'utf-16be' + } + + #: Default value for valueType + defaultValueType = 'string' + #: Default value for lengthTYpe + defaultLengthType = 'string' + #: Default value for padCharacter + defaultPadCharacter = '\0' + #: Default value for type + defaultType = 'char' + #: Default value for nullTerminated + defaultNullTerminated = False + + def __init__(self, name = None, parent = None): + DataElement.__init__(self, name, parent) + self.elementType = 'string' + self.valueType = String.defaultValueType + self.defaultValue = None + self.isStatic = False + self.lengthType = String.defaultLengthType + self.lengthCalc = None + self.length = None + self.minOccurs = 1 + self.maxOccurs = 1 + self.generatedOccurs = 1 + self.currentValue = None + self.insideRelation = False + self.analyzer = None + + #: Value to pad string with, defaults to NULL '\0' + self.padCharacter = String.defaultPadCharacter + #: Type of string, currently only char and wchar are supported. + self.type = String.defaultType + #: Is string null terminated, defaults to false + self.nullTerminated = String.defaultNullTerminated + #: DEPRICATED, Use hint instead + self.tokens = None + + def clone(self, obj = None): + + if obj is None: + obj = String(self.name, self.parent) + + DataElement.clone(self, obj) + + obj.valueType = self.valueType + obj.length = self.length + obj.lengthType = self.lengthType + obj.lengthCalc = self.lengthCalc + obj.insideRelation = self.insideRelation + obj.analyzer = self.analyzer + obj.padCharacter = self.padCharacter + obj.type = self.type + obj.nullTerminated = self.nullTerminated + + return obj + + def asCType(self): + + if self.type == 'wchar': + return ctypes.c_wchar_p(self.getInternalValue()) + else: + return ctypes.c_char_p(self.getInternalValue().encode(self.EncodeAs[self.type])) + + def getLength(self, inRaw = True): + """ + Get the length of this element. + """ + + if not inRaw and (self.currentValue is not None or self.isStatic): + return len(self.getValue()) + + if self.lengthType == 'calc': + self.length = self.calcLength() + + if self.length is not None and self.length < 0: + self.length = None + + return self.length + + def getInternalValue(self, sout = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + + # 0. Override value? + if self.currentValue is not None: + + # Make sure we null terminate if needed + if self.nullTerminated: + if self.currentValue[-1] != 0: + self.currentValue += "\0" + + if sout is not None: + sout.write(self.currentValue, self.getFullnameInDataModel()) + + return self.currentValue + + # 1. Init value + value = "" + + # 3. default value? + if self.defaultValue is not None: + value = self.defaultValue + + # 4. Relations + + value = self.getRelationValue(value) + if not type(value) in [str, unicode]: + value = str(value) + + # 5. fixup + + if self.fixup is not None: + self.fixup.fixup.context = self + ret = self.fixup.fixup.do_fixup() + if ret is not None: + value = ret + + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + return value + + def getRawValue(self, sout = None): + + # finalValue overrides everything! + if self.finalValue is not None: + value = self.finalValue + + else: + + # 0. Override value? + if self.currentValue is not None: + value = self.currentValue + + else: + # 1. Init value + value = self.getInternalValue() + + if len(value) < self.length: + value += self.padCharacter * (self.length - len(value)) + else: + value = value[:self.length] + + # 7. Null terminated strings + # Lets try null terminating even the mutated value. Might as well! + if self.nullTerminated and (len(value) == 0 or value[-1] != '\0'): + value += '\0' + + # Encode, but only when needed or we get errorzZzz + if type(value) != str and self.type == 'char': + value = value.encode(self.EncodeAs['char']) + + elif self.type != 'char': + if type(value) == str: + value = value.decode(self.EncodeAs['char']) + + value = value.encode(self.EncodeAs[self.type]) + + + # Even for final values we must return binary strings + # this will "encode" them as such + if type(value) != str: + value = value.encode(self.EncodeAs['char']) + + # Output + + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + #if type(value) != str: + # print "[%s]" % value + # raise Exception("Whoa, string not str!!") + + return value + + +def ToXmlCommonDataElements(element, node): + element._setAttribute(node, 'minOccurs', str(element.minOccurs)) + element._setAttribute(node, 'maxOccurs', str(element.maxOccurs)) + element._setAttribute(node, 'generatedOccurs', str(element.generatedOccurs)) + + # Generators + for child in element.extraGenerators: + if element._xmlHadChild(child): + child.toXml(node) + + # Relations + for child in element.relations: + if element._xmlHadChild(child): + child.toXml(node) + + # Transformer + if element.transformer is not None: + if element._xmlHadChild(child): + child.toXml(node) + + +class Flags(DataElement): + """Set of flags""" + defaultEndian = 'little' + + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'flags' + self.length = None # called size + self.endian = Flags.defaultEndian + self.rightToLeft = False + self.padding = False + + def clone(self, obj=None): + if obj is None: + obj = Flags(self.name, self.parent) + DataElement.clone(self, obj) + obj.endian = self.endian + obj.length = self.length + [obj.append(c.clone()) for c in self] + return obj + + def asCType(self): + value = int(self.getInternalValue()) + ret = None + evalString = "ctypes.c_uint%d(value)" % self.size + ret = eval(evalString) + return ret + + def getSize(self): + """Return the length of this data element. Try and be fast about it!""" + if self.transformer is not None or self.fixup is not None: + return len(self.getValue()) + return self.length / 8 + + def binaryFormatter(self, num, bits): + """Convert number to binary string.""" + ret = "" + for i in range(bits - 1, -1, -1): + ret += str((num >> i) & 1) + assert len(ret) == bits + return ret + + def flipBitsByByte(self, num, size): + ret = 0 + for n in self.splitIntoBytes(num, size): + ret <<= 8 + ret += n + return ret + + def splitIntoBytes(self, num, size): + ret = [] + for i in range(size / 8): + ret.append(num & 0xFF) + num >>= 8 + return ret + + def flipBits(self, num, size): + """Reverse the bits""" + ret = 0x00 << size + for i in range(size): + b = 0x01 & (num >> i) + ret += b << (size - i) - 1 + print("flipBits: pre %s post %s" % (self.binaryFormatter(num, size), self.binaryFormatter(ret, size))) + return ret + + def isInvalidated(self): + """Check if we need to reproduce this value. + If we have a relation always True, otherwise False.""" + if len(self.relations) > 0: + return True + # Check children + for c in self: + if isinstance(c, DataElement): + if c.isInvalidated(): + return True + return False + + def getInternalValue(self, sout=None): + """Return the internal value of this date element. + This value comes before any modifications such as packing, padding, truncating, etc. + For Flags we are always a binary string.""" + # 1. Init our value + ret = 0 + # 3. Build our flags up + flags = [] + for n in self: + if n.elementType == 'flag': + flags.append(n) + if self.padding: + #print self.endian, self.rightToLeft, self.padding + bits = BitBuffer("\0" * (self.length / 8), not self.rightToLeft) + else: + bits = BitBuffer("\0" * (self.length / 8), self.endian == 'big') + for flag in flags: + #print "%s: %d:, %d, %d" % (flag.name, flag.position, int(flag.getInternalValue()), flag.length) + bits.seek(flag.position) + bits.writebits(int(flag.getInternalValue()), flag.length) + if self.padding and ((self.endian == 'little' and not self.rightToLeft) or + (self.endian == 'big' and self.rightToLeft)): + fmt = '>' + fmt2 = '<' + if self.length == 8: + fmt += 'B' + fmt2 += 'B' + elif self.length == 16: + fmt += 'H' + fmt2 += 'H' + elif self.length == 32: + fmt += 'I' + fmt2 += 'I' + elif self.length == 64: + fmt += 'Q' + fmt2 += 'Q' + ret = struct.unpack(fmt, bits.getvalue())[0] + ret = struct.pack(fmt2, ret) + else: + ret = bits.getvalue() + # 4. do we fixup? + if self.fixup is not None: + self.fixup.fixup.context = self + ret = self.fixup.fixup.do_fixup() + if ret is not None: + value = ret + # 5. Do we have an override? + if self.currentValue is not None: + ret = self.currentValue + # 7. Return value + if sout is not None: + sout.write(ret, self.getFullnameInDataModel()) + return ret + + def getRawValue(self, sout=None): + ret = self.getInternalValue() + # 7. Return value + if sout is not None: + sout.write(ret, self.getFullnameInDataModel()) + return ret + + +class Flag(DataElement): + """ + A flag in a flag set + """ + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'flag' + self.defaultValue = None + self.position = None + self.length = None # called size + self.signed = False + + def getSize(self): + return self.length + + def setSize(self, size): + self.length = size + size = property(fget=getSize, fset=setSize) + + def getMinValue(self): + """ + Get the minimum value this number can have. + """ + + if not self.signed: + return 0 + + min = 0 - (pow(2, self.length)-1) + return min + + def getMaxValue(self): + """ + Get the maximum value for this number. + """ + max = pow(2, self.length)-1 + if self.signed: + return max/2 + + return max + + def clone(self, obj = None): + + if obj is None: + obj = Flag(self.name, self.parent) + + DataElement.clone(self, obj) + + obj.position = self.position + obj.length = self.length + + return obj + + def getInternalValue(self): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + # 1. Init our value + value = 0 + + # 2. Default value? + if self.defaultValue is not None: + value = self.defaultValue + + # 3. Relations + #print self.name + ": Pre-relation:", value + value = self.getRelationValue(value) + #print self.name + ": Post-relation:", value + + # 4. Fixup + if self.fixup is not None: + self.fixup.fixup.context = self + ret = self.fixup.fixup.do_fixup() + if ret is not None: + value = ret + + # 5. Do we have an override? + if self.currentValue is not None: + value = self.currentValue + + # 6. Return value + try: + value = int(value) + except: + try: + value = ord(value) + except: + value = 0 + + return value + + def getRawValue(self, sout = None): + # We shouldn't ever be here since flag + # should always be hidden behind Flags + # but sometimes things get re-arranged. + return str(self.getInternalValue()) + + +class Seek(ElementWithChildren): + """ + Change the current position in the data stream. + """ + + def __init__(self, name, parent): + ElementWithChildren.__init__(self, name, parent) + + self.elementType = "seek" + + #: Python expression to calculate new position + self.expression = None + #: Integer position + self.position = None + #: Position change is relative to current position + self.relative = None + + # EMulate some of the DataElement stuff + self.array = None + self.minOccurs = 1 + self.maxOccurs = 1 + self.currentValue = None + self.defaultValue = None + + def clone(self, obj = None): + + if obj is None: + obj = Seek(self.name, self.parent) + + obj.expression = self.expression + obj.position = self.position + obj.relative = self.relative + + return obj + + def HasWhenRelation(self): + return False + + def _getExpressionPosition(self, currentPosition, dataLength, data): + environment = { + 'self' : self, + 'pos' : currentPosition, + 'dataLength' : dataLength + } + + #DataElement._fixRealParent(self, self) + try: + pos = -1 + pos = evalEvent(self.expression, environment, self) + + finally: + #DataElement._unFixRealParent(self) + pass + + return pos + + def _getPosition(self): + return self.position + + def getPosition(self, currentPosition, dataLength, data): + if self.expression is not None: + return self._getExpressionPosition(currentPosition, dataLength, data) + + if self.relative is not None: + return currentPosition + self.relative + + return self._getPosition() + + def _fixRealParent(self, node): + """ + Sometimes when we recurse to crack a + block we remove the parent from the block + and save it to .realParent. + + Since many scripts want to look up we will + unsave the parent for a bit. + """ + + # 1. Find root + + root = node + while root.parent is not None: + root = root.parent + + # 2. Check if has a realParent + + if hasattr(root, 'realParent'): + #print "_fixRealParent(): Found fake root: ", root.name + root.parent = root.realParent + + # done! + + def _unFixRealParent(self, node): + """ + Clear the parent if we have it saved. + """ + + # 1. Look for fake root + + root = node + while not hasattr(root, 'realParent') and root.parent is not None: + root = root.parent + + # 2. Remove parent link + #print "_unFixRealParent(): Found fake root: ", root.name + root.parent = None + + +class Blob(DataElement): + """ + A flag in a flag set + """ + + #: Default value for valueType + defaultValueType = 'string' + #: Default value for lengthType + defaultLengthType = 'string' + + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'blob' + self.valueType = Blob.defaultValueType + self.lengthType = Blob.defaultLengthType + self.length = None + self.lengthCalc = None + + def clone(self, obj = None): + + if obj is None: + blob = Blob(self.name, self.parent) + else: + blob = obj + + DataElement.clone(self, blob) + blob.elementType = self.elementType + blob.valueType = self.valueType + blob.lengthType = self.lengthType + blob.length = self.length + blob.lengthCalc = self.lengthCalc + + return blob + + def asCType(self): + + value = self.getValue() + ret = (ctypes.c_ubyte * len(value))() + + for i in range(len(value)): + ret[i] = ord(value[i]) + + # Are we a pointer? + if self.isPointer: + if self.pointerDepth is not None: + for i in range(int(self.pointerDepth)): + ret = ctypes.pointer(ret) + else: + ret = ctypes.pointer(ret) + + return ret + + def getInternalValue(self, sout = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + return self.getRawValue(sout) + + def getSize(self): + """ + Return the length of this data element. Try and + be fast about it! + """ + + l = self.getLength() + if l is not None: + return l + + return len(self.getValue()) + + def getLength(self): + """ + Get the length of this element. + """ + + if self.lengthType == 'calc': + try: + self.length = self.calcLength() + + if self.length is not None and self.length < 0: + # SANITY! + print("Length Calc is off, setting to None", self.length) + self.length = None + + except: + # This can fail while doing + # mutations. + print("Warning: Calc failed. Okay to ignore after first iteration.") + pass + + elif self.isStatic: + return len(self.getValue()) + + return self.length + + def getRawValue(self, sout = None): + + targetLength = None + + if self.lengthType == 'calc': + try: + targetLength = self.calcLength() + except: + # Calc may not run correctly yet! + pass + + elif self.length is not None: + targetLength = self.length + + # 1. init + value = "" + + if self.currentValue is not None: + value = self.currentValue + + else: + + # 2. default value? + if self.defaultValue is not None: + value = self.defaultValue + + # 3. Fixup + if self.fixup is not None: + self.fixup.fixup.context = self + ret = self.fixup.fixup.do_fixup() + if ret is not None: + value = ret + + # Make correct size + if targetLength is not None: + while len(value) < targetLength: + value += "\x00" + + # 5. If we have sout + if sout is not None: + sout.write(value, self.getFullnameInDataModel()) + + return value + + +################################################################################### +################################################################################### + +class Relation(Element): + """ + Specifies relations between data + + - size-of + - (when a flag indicates something exists) + - Zero or more + - 1 or more + """ + + ## For debugging + #def getParent(self): + # return self._parent + #def setParent(self, value): + # self._parent = value + # #if hasattr(self, "of") and self.of == "Tables": + # # print self,"Relation.setParent()",value + # # traceback.print_stack() + #parent = property(fget=getParent, fset=setParent) + + def __init__(self, name, parent): + Element.__init__(self, name, parent) + self.elementType = 'relation' + + #: Type of relation (size, count, when) + self.type = None + + #: Reference to target + self.of = None + + #: Reference to matching of relation + self.From = None + + #: Relative relation + self.relative = False + #: Relative to this element (string) + self.relativeTo = None + + #:Only for output? + self.isOutputOnly = False + + #: Parent of this object + #self.parent = parent + #: Expression to apply to relation when getting value + self.expressionGet = None + #: Expression to apply to relation when setting value + self.expressionSet = None + + def clone(self, obj = None): + + if obj is None: + obj = Relation(self.name, self.parent) + + obj.type = self.type + obj.of = self.of + obj.From = self.From + obj.relative = self.relative + obj.relativeTo = self.relativeTo + obj.expressionGet = self.expressionGet + obj.expressionSet = self.expressionSet + + return obj + + def getFullnameInDataModel(self): + """ + This will get fully qualified name of this element starting with the + root node of the data model. + """ + + name = self.name + node = self + + while isinstance(node.parent, DataElement): + node = node.parent + name = "%s.%s" % (node.name, name) + + return name + + def getValue(self, default = False): + """ + For a size-of relation get the size + of the referenced value. Apply expression + to the value if needed. + + @type default: Boolean + @param default: Should we try for .defaultValue first? (defaults False) + """ + + if self.From is not None: + raise Exception("Only 'of' relations should have getValue method called.") + + environment = None + value = 0 + + if self.type == 'size': + + if default: + try: + value = int(self.parent.defaultValue) + except: + value = int(self.parent.getInternalValue()) + + else: + value = int(self.parent.getInternalValue()) + + environment = { + 'self' : self.parent, + 'length' : value, + 'size' : value, + } + + elif self.type == 'count': + if default: + try: + value = int(self.parent.defaultValue) + except: + value = int(self.parent.getInternalValue()) + else: + value = int(self.parent.getInternalValue()) + + environment = { + 'self' : self.parent, + 'count' : value, + } + + elif self.type == 'offset': + if default: + try: + value = int(self.parent.defaultValue) + except: + value = int(self.parent.getInternalValue()) + else: + value = int(self.parent.getInternalValue()) + + # Handle Relative Relation + if self.relative: + + # Are we relative to another element? + if self.relativeTo is None: + value = value + self.parent.possiblePos + + else: + obj = self.parent.find(self.relativeTo) + try: + value = value + obj.possiblePos + except: + print("obj:", obj) + print("obj.fullname:", obj.getFullname()) + raise + + environment = { + 'self' : self.parent, + 'offset' : value, + } + else: + raise Exception("Should not be here!") + + if self.expressionGet is not None: + try: + self.parent._fixRealParent(self.parent) + return evalEvent(self.expressionGet, environment, self) + + finally: + self.parent._unFixRealParent(self.parent) + + return value + + def setValue(self, value): + """ + For a size-of relation get the size + of the referenced value. Apply expression + to the value if needed. + """ + + if self.From is not None: + raise Exception("Only 'of' relations should have setValue method called.") + + environment = None + value = int(value) + + if self.type == 'size': + environment = { + 'of' : self.getOfElement(), + 'self' : self.parent, + 'length' : value, + 'size' : int(value), + } + + elif self.type == 'count': + environment = { + 'of' : self.getOfElement(), + 'self' : self.parent, + 'count' : int(value), + } + + elif self.type == 'offset': + + # Handle Relative Relation + if self.relative: + + # Are we relative to another element? + if self.relativeTo is None: + value = value - self.parent.possiblePos + else: + obj = self.parent.find(self.relativeTo) + value = value - obj.possiblePos + + environment = { + 'of' : self.getOfElement(), + 'self' : self.parent, + 'offset' : int(value), + } + + else: + raise Exception("Should not be here!") + + if self.expressionSet is not None: + try: + self.parent._fixRealParent(self.parent) + ret = evalEvent(self.expressionSet, environment, self) + return ret + + finally: + self.parent._unFixRealParent(self.parent) + + return int(value) + + + def getOfElement(self): + """ + Resolve of reference. We want todo this at + runtime in case we are copied around. + """ + + if self.of is None: + return None + + #print self + #print self.of + obj = self.parent.findDataElementByName(self.of) + if obj is None: + # Could element have become an array? + obj = self.parent.findArrayByName(self.of) + + if obj is None: + print(self.parent.name, self.parent) + print("Parent:",self.parent.parent) + print("DataRoot:", self.parent.getRootOfDataMap()) + print("DataRoot.parent:", self.parent.getRootOfDataMap().parent) + print("Fullname:", self.getFullnameInDataModel()) + print("Couldn't locate [%s]" % self.of, self.type) + DomPrint(0, self.parent.getRootOfDataMap()) + raise Exception("Couldn't locate [%s]" % self.of) + + return obj + + def getFromElement(self): + """ + Resolve of reference. We want todo this at + runtime in case we are copied around. + """ + + if self.From is None: + return None + + return self.parent.findDataElementByName(self.From) + + +class Data(ElementWithChildren): + """ + Default data container. Children are |Field| objects. + When used in multi-file mode, |fileName| will always contain an actual real file. + It is up to the mutator strategy to use the other files. + """ + def __init__(self, name): + ElementWithChildren.__init__(self, name, None) + self.elementType = 'data' + + #: Name of file containing data to load + self.fileName = None + #: Expression that returns data to load + self.expression = None + #: Does this data element point to multiple files + self.multipleFiles = False + #: A unix style glob path + self.fileGlob = None + #: Folder of files to use + self.folderName = None + #: Maximum allowed size of file + self.maxFileSize = -1 + #: Allow recursion to find files in sub-folders + self.recurse = False + + def is_valid(self, fpath): + fname = os.path.basename(fpath) + if not os.path.isfile(fpath) or fname.startswith("."): + return False + if self.maxFileSize == -1 or \ + (self.maxFileSize > -1 and os.path.getsize(fpath) < self.maxFileSize): + return True + return False + + def gotoFirstFile(self): + if not self.multipleFiles: + raise PeachException("Data.gotoFirstFile called with self.multipleFiles == False!") + if self.folderName is not None: + self.fileName = self.folderName + self.files = [] + for fname in os.listdir(self.folderName): + fpath = os.path.join(self.folderName, fname) + if self.is_valid(fpath): + self.files.append(fpath) + elif self.fileGlob is not None: + self.files = [] + for fpath in glob.glob(self.fileGlob): + if self.is_valid(fpath): + self.files.append(fpath) + self.fileName = self.files[0] + self.files = self.files[1:] + + def gotoNextFile(self): + self.fileName = self.files[0] + self.files = self.files[1:] + + def gotoRandomFile(self): + if not self.multipleFiles: + raise PeachException("Data.gotoRandomFile called with self.multipleFiles == False!") + files = [] + if self.folderName is not None: + self.fileName = self.folderName + for fname in os.listdir(self.folderName): + fpath = os.path.join(self.folderName, fname) + if self.is_valid(fpath): + files.append(fpath) + elif self.fileGlob is not None: + for fpath in glob.glob(self.fileGlob): + if self.is_valid(fpath): + files.append(fpath) + self.fileName = random.choice(files) + + +class Field(ElementWithChildren): + """ + Default bit of data. + """ + def __init__(self, name, value, parent): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'field' + + #: Value to set on data element + self.value = value + #: Indicates type of value. ['string', 'literal', 'hex'] supported. + self.valueType = None + #: Indicates an array expantion + self.array = None + + +class Logger(ElementWithChildren): + """ + A logger used to log peach events. + """ + def __init__(self, parent): + ElementWithChildren.__init__(self, None, parent) + self.elementType = 'logger' + +class Namespace(Element): + def __init__(self): + Element.__init__(self, None, None) + self.elementType = 'namespace' + self.nsName = None + self.nsSrc = None + + def toXml(self, parent): + node = etree.Element('Include') + parent.append(node) + + self._setAttribute(node, 'ns', self.nsName) + self._setAttribute(node, 'src', self.nsSrc) + + return node + +class PythonPath(Element): + def __init__(self): + Element.__init__(self, None, None) + self.elementType = 'pythonpath' + + +class Publisher(ElementWithChildren): + def __init__(self): + ElementWithChildren.__init__(self, None, None) + self.elementType = 'publisher' + self.classStr = None + self.publisher = None + + +class StateMachine(Mutatable): + def __init__(self, name, parent): + Mutatable.__init__(self, name, parent) + self.elementType = 'statemachine' + self.initialState = None + self.onEnter = None + self.onExit = None + + def findStateByName(self, stateName): + for child in self: + if child.elementType == 'state' and child.name == stateName: + return child + + return None + + def getRoute(self): + paths = [child for child in self if child.elementType == 'path'] + return paths + + +class State(Mutatable): + def __init__(self, name, parent): + Mutatable.__init__(self, name, parent) + self.elementType = 'state' + self.onEnter = None + self.onExit = None + + def getChoice(self): + for child in self: + if child.elementType == 'stateChoice': + return child + return None + +class StateChoice(ElementWithChildren): + def __init__(self, parent): + ElementWithChildren.__init__(self, None, parent) + self.elementType = 'stateChoice' + + def findActionByRef(self, ref): + for child in self: + if child.elementType == 'stateChoiceAction' and child.ref == ref: + return child + return None + +class StateChoiceAction(Element): + def __init__(self, ref, type, parent): + Element.__init__(self, None, parent) + self.elementType = 'stateChoiceAction' + self.ref = ref + self.type = type + +class Path(Element): + def __init__(self, ref, parent): + Element.__init__(self, None, parent) + self.elementType = 'path' + self.ref = ref + self.stop = False + +class Strategy(ElementWithChildren): + def __init__(self, classStr, parent): + ElementWithChildren.__init__(self, None, parent) + self.elementType = 'strategy' + self.params = {} + self.classStr = classStr + +class Action(Mutatable): + def __init__(self, name, parent): + Mutatable.__init__(self, name, parent) + self.elementType = 'action' + self.type = None + self.ref = None + self.when = None + self.onStart = None + self.onComplete = None + self.data = None + self.template = None + self.setXpath = None + self.valueXpath = None + self.valueLiteral = None + self.value = None + self.method = None + self.property = None + self.publisher = None + + +class ActionParam(ElementWithChildren): + def __init__(self, name, parent): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'actionparam' + self.type = 'in' + self.template = None + self.data = None + self.value = None + +class ActionResult(ElementWithChildren): + def __init__(self, name, parent): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'actionresult' + self.template = None + self.value = None + +class Mutators(ElementWithChildren): + def __init__(self, name, parent): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'mutators' + +class Mutator(ElementWithChildren): + def __init__(self, name, parent): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'mutator' + self.mutator = None + +class Hint(ElementWithChildren): + """ + Hints can be a child of DataElements. They provide hints + to mutators about the data element. Hints can be things + like finer grained type information like "type=xml" or + possibly hints about related data values "related=Foo". + + Hints are optional bits of meta data. + """ + def __init__(self, name, parent): + ElementWithChildren.__init__(self, name, parent) + self.elementType = 'hint' + self.value = None + + def clone(self, obj = None): + if obj is None: + obj = Hint(self.name, self.parent) + obj.elementType = self.elementType + obj.value = self.value + return obj + + +class Custom(DataElement): + + def __init__(self, name, parent): + DataElement.__init__(self, name, parent) + self.elementType = 'custom' + + def handleParsing(self, node): + """ + Handle any custom parsing of the XML such as + attributes. + """ + + raise NotImplementedError("handleParsing not implemented") + + def handleIncomingSize(self, node, data, pos, parent): + """ + Return initial read size for this type. + """ + raise NotImplementedError("handleIncomingSize not implemented") + + def handleIncoming(self, cntx, data, pos, parent, doingMinMax = False): + """ + Handle data cracking. + """ + raise NotImplementedError("handleIncoming not implemented") + + def getInternalValue(self, sout = None): + """ + Return the internal value of this date element. This + value comes before any modifications such as packing, + padding, truncating, etc. + + For Numbers this is the python int value. + """ + raise NotImplementedError("getInternalValue not implemented") + + def getLength(self): + """ + Get the length of this element. + """ + return len(self.getValue()) + + def getRawValue(self, sout = None): + return self.getInternalValue(sout) + + +def DomPrint(indent, node): + + tabs = ' ' * indent + + if hasattr(node, 'parent') and node.parent is not None: + p = "parent" + else: + p = "!! no parent !!" + + print(tabs + node.elementType + ": " + node.name + ": " + p) + + if node.hasChildren: + for child in node._children: + DomPrint(indent+1, child) diff --git a/fuzzers/Peach/Engine/dom.pyc b/fuzzers/Peach/Engine/dom.pyc new file mode 100644 index 0000000..16d7ff5 Binary files /dev/null and b/fuzzers/Peach/Engine/dom.pyc differ diff --git a/fuzzers/Peach/Engine/engine$py.class b/fuzzers/Peach/Engine/engine$py.class new file mode 100644 index 0000000..d8bf469 Binary files /dev/null and b/fuzzers/Peach/Engine/engine$py.class differ diff --git a/fuzzers/Peach/Engine/engine.py b/fuzzers/Peach/Engine/engine.py new file mode 100755 index 0000000..20905e2 --- /dev/null +++ b/fuzzers/Peach/Engine/engine.py @@ -0,0 +1,632 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import atexit +import logging + +from common import Highlight + +# The engine component does the following: +# +# 1. Accepts a peach XML and parses it +# 2. Configures watchers, loggers +# 3. Connects to Agents and spins up Monitors +# 4. Runs each defined test +# a. Notifies Agents +# b. Calls State Engine + +class Empty(object): + pass + + +class EngineWatcher(object): + """ + Base for a class that receives callback when events occur in the Peach Engine. + """ + + def setTotalVariations(self, totalVariations): + self.totalVariations = totalVariations + + def OnCrashOrBreak(self): + """ + Called on crash or interrupt. + """ + pass + + def OnRunStarting(self, run): + """ + Called when a run is starting. + """ + pass + + def OnRunFinished(self, run): + """ + Called when a run is finished. + """ + pass + + def OnTestStarting(self, run, test, totalVariations): + """ + Called on start of a test. Each test has multiple variations. + """ + pass + + def OnTestFinished(self, run, test): + """ + Called on completion of a test. + """ + pass + + def OnTestCaseStarting(self, run, test, variationCount): + """ + Called on start of a test case. + """ + pass + + def OnStateEnter(self, state): + """ + Called as we enter a state + """ + pass + + def OnStateExit(self, state): + """ + Called as we exit a state + """ + pass + + def OnActionStart(self, action): + """ + Called as we start an action + """ + pass + + def OnActionComplete(self, action): + """ + Called after we completed action + """ + pass + + def OnTestCaseReceived(self, run, test, variationCount, value): + """ + Called when data is received from test case. + """ + pass + + def OnTestCaseException(self, run, test, variationCount, exception): + """ + Called when an exception occurs during a test case. + """ + pass + + def OnTestCaseFinished(self, run, test, variationCount, actionValues): + """ + Called when a test case has completed. + """ + pass + + def OnFault(self, run, test, variationCount, monitorData, value): + """ + Called when a fault occurred. + """ + pass + + def OnStopRun(self, run, test, variationCount, monitorData, value): + """ + Called when the run stopped. + """ + pass + + +class EngineWatchPlexer(EngineWatcher): + """ + Allows multiple watchers to be attached and will distribute messages out to them. + """ + + def __init__(self): + self.watchers = [] + + def setTotalVariations(self, totalVariations): + for w in self.watchers: + w.setTotalVariations(totalVariations) + + def OnRunStarting(self, run): + for w in self.watchers: + w.OnRunStarting(run) + + def OnRunFinished(self, run): + for w in self.watchers: + w.OnRunFinished(run) + + def OnTestStarting(self, run, test, totalVariations): + for w in self.watchers: + w.OnTestStarting(run, test, totalVariations) + + def OnTestFinished(self, run, test): + for w in self.watchers: + w.OnTestFinished(run, test) + + def OnTestCaseStarting(self, run, test, variationCount): + for w in self.watchers: + w.OnTestCaseStarting(run, test, variationCount) + + def OnTestCaseReceived(self, run, test, variationCount, value): + for w in self.watchers: + w.OnTestCaseReceived(run, test, variationCount, value) + + def OnTestCaseException(self, run, test, variationCount, exception): + for w in self.watchers: + w.OnTestCaseException(run, test, variationCount, exception) + + def OnTestCaseFinished(self, run, test, variationCount, actionValues): + for w in self.watchers: + w.OnTestCaseFinished(run, test, variationCount, actionValues) + + def OnFault(self, run, test, variationCount, monitorData, value): + for w in self.watchers: + w.OnFault(run, test, variationCount, monitorData, value) + + def OnStateEnter(self, state): + for w in self.watchers: + w.OnStateEnter(state) + + def OnStateExit(self, state): + for w in self.watchers: + w.OnStateExit(state) + + def OnActionStart(self, action): + for w in self.watchers: + w.OnActionStart(action) + + def OnActionComplete(self, action): + for w in self.watchers: + w.OnActionComplete(action) + + def OnStopRun(self, run, test, variationCount, monitorData, value): + for w in self.watchers: + w.OnStopRun(run, test, variationCount, monitorData, value) + + +class StdoutWatcher(EngineWatcher): + """ + This is the default console interface to Peach it prints out information as tests are performed. + """ + + def OnRunStarting(self, run): + logging.info('Starting run "%s".' % run.name) + + def OnRunFinished(self, run): + logging.info('Run "%s" completed.' % run.name) + + def OnTestStarting(self, run, test, totalVariations): + self.startTime = None + self.startVariationCount = None + self.remaingTime = "?" + self.totalVariations = totalVariations + logging.info('Test "%s" (%s) is starting.' % (test.name, test.description)) + + def OnTestFinished(self, run, test): + logging.info('Test "%s" completed.' % test.name) + + def OnTestCaseStarting(self, run, test, variationCount): + prefix = "Heartbeat: %d-%s-%s " % (variationCount, self.totalVariations, self.remaingTime) + logging.info(prefix + "Element: %s Mutator: %s" % (test.mutator.currentMutator().changedName, test.mutator.currentMutator().name)) + if self.startTime is None and variationCount > 1: + self.startTime = time.time() + self.startVariationCount = variationCount + try: + if variationCount % 20 == 0: + count = variationCount - (self.startVariationCount - 1) + elaps = time.time() - self.startTime + perTest = elaps / count + remaining = (int(self.totalVariations) - variationCount) * perTest + self.remaingTime = str(int((remaining / 60) / 60)) + "hrs" + if count > 5000: + self.startTime = time.time() + self.startVariationCount = variationCount + except: + pass + + def OnTestCaseReceived(self, run, test, variationCount, value): + if Engine.verbose: + print("[%d:%s:%s] Received data: %s" % + (variationCount, self.totalVariations, self.remaingTime, repr(value))) + else: + print("[%d:%s:%s] Received data" % + (variationCount, self.totalVariations, self.remaingTime)) + + def OnTestCaseException(self, run, test, variationCount, exception): + print("[%d:%s:%s] Caught error on receive, ignoring [%s]" % + (variationCount, self.totalVariations, self.remaingTime, exception)) + return True + + def OnTestCaseFinished(self, run, test, variationCount, actionValues): + pass + + +class Engine(object): + """ + The high level Peach engine. + The main entry point is Run() which consumes a Peach XML file and performs the fuzzing run. + """ + + debug = False + relationsNew = False + justOne = False + nativeDeepCopy = True + testRange = None + context = None + + def __init__(self): + self.restartFile = None + self.restartState = None + self.verbose = False + self.peach = None + self.agent = None + self._agents = {} + self.startNum = None + self.configs = {} + Engine.verbose = False + Engine.context = self + + def Count(self, peach, runName=None): + """ + Count the tests of a run. + + @type uri: String + @param uri: URI specifying the filename to use. Must have protocol prepended (file:, http:, etc) + @type runName: String + @param runName: Name of run or if None, "DefaultRun" is used. + """ + self.watcher = EngineWatchPlexer() + self.peach = peach + self.agent = AgentPlexer() + self._agents = {} + runName = "DefaultRun" if runName is None else runName + if hasattr(self.peach.runs, runName): + run = getattr(self.peach.runs, runName) + else: + raise PeachException("Can not find with name %s." % runName) + totalCount = 0 + for test in run.tests: + testCount = self._countTest(run, test, True) + totalCount += testCount + logging.info("Test with name %s has %d test cases." % (test.name, testCount)) + logging.info("Total test cases for run with name %s is %d." % (runName, totalCount)) + return totalCount + + def Run(self, args): + runName = "DefaultRun" if args.run is None else args.run + self.restartFile = args.restartFile + self.restartState = None + self.verbose = args.verbose + Engine.verbose = args.verbose + if args.pit.find(":") >= 0: + self.pitFile = args.pit[args.pit.find(":") + 1:] + else: + self.pitFile = args.pit + if self.pitFile.find("/") >= 0: + self.pitFile = os.path.basename(self.pitFile) + self.peach = args.parser.asParser(args.pit) + run = None + self.agent = AgentPlexer() + self._agents = {} + self.startNum = args.skipto + self.watcher = EngineWatchPlexer() + if args.watcher is None: + self.watcher.watchers.append(StdoutWatcher()) + else: + self.watcher.watchers.append(args.watcher) + if hasattr(self.peach.runs, runName): + run = getattr(self.peach.runs, runName) + else: + raise PeachException("Can not find run with name %s." % runName) + loggers = run.getLoggers() + if loggers is not None: + for logger in loggers: + self.watcher.watchers.append(logger) + try: + self.watcher.OnRunStarting(run) + except TypeError as t: + print(t) + print(dir(self.watcher)) + print(dir(self.watcher.OnRunStarting)) + raise t + skipToTest = False + if self.restartFile is not None: + logging.info("[Restarting] Loading state file %s." % self.restartFile) + with open(self.restartFile, "rb+") as fd: + self.restartState = pickle.loads(fd.read()) + skipToTest = True + skipToTestName = self.restartState[0] + if args.parallel is None: + for test in run.tests: + self._runPathTest(run, test) + for test in run.tests: + if skipToTest and test.name != skipToTestName: + continue + elif skipToTest and test.name == skipToTestName: + skipToTest = False + self._runTest(run, test, False, self.testRange) + else: + logging.info("Configuring run with name %s." % runName) + if len(run.tests) > 1: + raise PeachException("Only a single test per-run is currently supported for parallel fuzzing.") + totalMachines = int(args.parallel[0]) + thisMachine = int(args.parallel[1]) + test = run.tests[0] + # 1. Get our total count. We want to use a copy of everything so we don't pollute the DOM! + peach = args.parser.asParser(args.pit) + totalCount = self._countTest(getattr(peach.runs, runName), getattr(peach.runs, runName).tests[0]) + # 2. How many tests per machine? + perCount = int(totalCount / totalMachines) + leftOver = totalCount - (perCount * totalMachines) + # 3. How many for this machine? + startCount = thisMachine * perCount + thisCount = perCount + if thisMachine == totalMachines - 1: + thisCount += leftOver + logging.info("This machine will perform chunk %d through %d out of %d total" % + (startCount, startCount + thisCount, totalCount)) + self._runTest(run, test, False, [startCount, startCount + thisCount]) + self.watcher.OnRunFinished(run) + + def _startAgents(self, run, test): + """ + Start up agents listed in test. + """ + for agent in test: + if agent.elementType != 'agent': + continue + if agent.location == 'local': + server = "." + else: + server = agent.location + agent_object = self.agent.AddAgent(agent.name, server, agent.password, agent.getPythonPaths(), + agent.getImports(), self.configs) + self._agents[agent.name] = agent_object + for monitor in agent: + if monitor.elementType == 'monitor': + agent_object.StartMonitor(monitor.name, monitor.classStr, monitor.params) + + def _stopAgents(self, run, test): + self.agent.OnShutdown() + + def _countTest(self, run, test, verbose=False): + """ + Get the total test count of this test + """ + logging.info("Peach will now count the total amount of test cases, please wait.") + mutator = self._runTest(run, test, True) + count = 0 if mutator is None else mutator.getCount() + if count is None: + raise PeachException("An error occurred counting total tests.") + logging.info("Count completed, found %d possible tests." % count) + return count + + def _runTest(self, run, test, countOnly=False, testRange=None): + """ + Runs a Test as defined in the Peach XML. + + @type run: Run object + @param run: Run that test is part of + @type test: Test object + @param test: Test to run + @type countOnly: bool + @param countOnly: Should we just get total mutator count? Defaults to False. + @type testRange: list of numbers + @param testRange: Iteration # test ranges. Only used when performing parallel fuzzing. + + @rtype: number + @return: the total number of test iterations or None + """ + stateMachine = test.stateMachine + stateEngine = StateEngine(self, stateMachine, test.publishers) + totalTests = "?" + testCount = 0 + self._startAgents(run, test) + if not countOnly: + self.watcher.OnTestStarting(run, test, totalTests) + for p in test.publishers: + p.initialize() + errorCount = 0 + maxErrorCount = 10 + # Get all the mutators we will use + self.mutators = [] + for m in test.getMutators(): + try: + self.mutators.append(eval(m.name)) + except: + try: + self.mutators.append(evalEvent("PeachXml_" + m.name, {}, run)) + except: + raise PeachException( + "Unable to load mutator [%s], please verify it was imported correctly." % m.name) + mutator = test.mutator + value = "StateMachine" + if self.restartState is not None: + logging.info("State will load in 1 iteration.") + elif testRange is not None: + logging.info("Skipping to start of chunk in 1 iteration.") + # Needs to be off on its own! + startCount = None + endCount = None + if testRange is not None: + startCount = testRange[0] + endCount = testRange[1] + if self.startNum is not None: + startCount = self.startNum + redoCount = 0 + saveState = False + exitImmediate = False + actionValues = None + try: + while True: + try: + testCount += 1 + # What if we are just counting? + if testCount == 2 and countOnly: + self._stopAgents(run, test) + return mutator + # Go through one iteration before we load state. + elif testCount == 2 and self.restartState is not None: + logging.info("Restoring state.") + testCount = self.restartState[1] + mutator.setState(self.restartState[2]) + elif testCount == 2 and startCount is not None and startCount > 2: + # Skip ahead to start range, but not if we are restoring saved state. + logging.info("Skipping ahead to iteration %d." % startCount) + #testCount -= 1 + for _ in range(testCount, startCount): + mutator.next() + testCount += 1 + # Update total test count + if testRange is None: + totalTests = mutator.getCount() + else: + # If we are parallel use our endCount which will also cause the estimated time + # left to be correct. + totalTests = endCount + 1 + if totalTests == -1 or totalTests is None: + totalTests = "?" + else: + self.watcher.setTotalVariations(totalTests) + # Fire some events + self.agent.OnTestStarting() + if not countOnly: + self.watcher.OnTestCaseStarting(run, test, testCount) + self.testCount = testCount + mutator.onTestCaseStarting(test, testCount, stateEngine) + # Run the test + try: + actionValues = stateEngine.run(mutator) + except RedoTestException: + raise + except MemoryError: + # Some tests cause out of memeory exceptions, let skip past them. + logging.warning("Out of memory, going to next test.") + pass + except OverflowError: + # Some tests cause out of memeory exceptions, let skip past them. + logging.warning("Out of memory, going to next test.") + pass + except SoftException as e: + # In the case of the first iteration we should never fail. + if testCount == 1: + raise PeachException("Error: First test case failed: ", e) + # Otherwise ignore any SoftExceptions and head for next iteration. + pass + # Pause as needed + time.sleep(run.waitTime) + mutator.onTestCaseFinished(test, testCount, stateEngine) + # Notify + if not countOnly: + self.watcher.OnTestCaseFinished(run, test, testCount, actionValues) + self.agent.OnTestFinished() + # Should we repeat this test? + if self.agent.RedoTest(): + logging.warning(highlight.warning("Repeating test")) + raise RedoTestException() + if self.agent.DetectedFault(): + logging.warning(highlight.warning("Detected fault! Processing data...")) + results = self.agent.GetMonitorData() + mutator.onFaultDetected(test, testCount, stateEngine, results, actionValues) + self.watcher.OnFault(run, test, testCount, results, actionValues) + self.agent.OnFault() + # Check for stop event + if self.agent.StopRun(): + logging.warning(highlight.warning("Detected StopRun, bailing!")) + self.watcher.OnStopRun(run, test, testCount, None, actionValues) + break + # Increment our mutator + mutator.next() + # Reset the redoCounter + redoCount = 0 + except RedoTestException as e: + if redoCount == 3: + raise PeachException(e.message) + redoCount += 1 + testCount -= 1 + except PathException: + # Ignore PathException while running tests + mutator.next() + except SoftException: + mutator.next() + # Have we completed our range? + if (testRange is not None and testCount > endCount) or \ + (Engine.justOne and startCount is None) or \ + (Engine.justOne and startCount == testCount): + logging.info("Completed iteration range.") + break + except MutatorCompleted: + pass + except KeyboardInterrupt: + logging.warning("User canceled run.") + saveState = True + exitImmediate = True + except PeachException as e: + if e.msg.find("Unable to reconnect to Agent") > -1: + results = { + "_Bucket": "AgentConnectionFailed" + } + self.watcher.OnFault(run, test, testCount, results, actionValues) + raise + except: + # Always save state on exceptions + saveState = True + self.watcher.OnTestCaseException(run, test, testCount, None) + raise + finally: + try: + for publisher in test.publishers: + if hasattr(publisher, "hasBeenConnected") and publisher.hasBeenConnected: + publisher.close() + publisher.hasBeenConnected = False + if hasattr(publisher, "hasBeenStarted") and publisher.hasBeenStarted: + publisher.stop() + publisher.hasBeenStarted = False + publisher.finalize() + except: + pass + self._stopAgents(run, test) + if not countOnly: + self.watcher.OnTestFinished(run, test) + + def _runPathTest(self, run, test): + stateMachine = test.stateMachine + # If no path declaration found then simply skip the validation + if not len(stateMachine.getRoute()): + return + logging.info("Running path validation test for %s." % test.name) + try: + stateEngine = StateEngine(self, stateMachine, test.publishers) + # Create a path validator to check basic validation rules + mutator = PathValidationMutator() + pathValidator = PathValidator(stateEngine.pathFinder, mutator) + try: + actionValues = stateEngine.run(mutator) + print("Traced route: ") + print(" - ".join(["%s" % str(stateName) for stateName in mutator.states])) + pathValidator.validate() + except PathException as e: + raise PeachException(str(e)) + except PeachException as e: + logging.error("End of path validation test : Validation failed!") + raise e + else: + logging.info("End of path validation test : Successfully passed") + + +import os, time, pickle, tempfile + +from Peach.Engine.state import StateEngine +from Peach.Engine.common import * +from Peach.Engine.common import SoftException +from Peach.Engine.path import * +from Peach.agent import AgentPlexer +from Peach.mutatestrategies import * +from Peach.MutateStrategies import * +from Peach.analyzer import Analyzer +from Peach.Analyzers import * +from Peach.Mutators import * +from Peach.Mutators.path import * diff --git a/fuzzers/Peach/Engine/engine.pyc b/fuzzers/Peach/Engine/engine.pyc new file mode 100644 index 0000000..3cd4b7a Binary files /dev/null and b/fuzzers/Peach/Engine/engine.pyc differ diff --git a/fuzzers/Peach/Engine/incoming.py b/fuzzers/Peach/Engine/incoming.py new file mode 100755 index 0000000..55be1c8 --- /dev/null +++ b/fuzzers/Peach/Engine/incoming.py @@ -0,0 +1,2845 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import sys +import struct +import logging + +from Peach.Engine.common import * +from Peach.Engine.dom import * +import Peach + + +def Debug(level, msg): + """ + Debug output. Uncommenting the following + print line will cause *lots* of output + to be displayed. It significantly slows the + data cracking process. + """ + # Don't show look aheads + if Peach.Engine.engine.Engine.debug: + if DataCracker._tabLevel == 0: + print(msg) + + +def PeachStr(s): + """ + Our implementation of str() which does not + convert None to 'None'. + """ + + if s is None: + return None + + return str(s) + + +class DataCracker(object): + """ + This class will try and parse data into a data model. This + process will try and best-fit data based on performing look + aheads with fit-ratings. + """ + + #: Have we recursed into DataCracker? + _tabLevel = 0 + + def __init__(self, peachXml, inner=False): + self.peach = peachXml + self.deepString = -1 + + #: To what depth are we looking ahead? + self.lookAheadDepth = 0 + + #: Are we looking ahead? + self.lookAhead = False + + #: Parent position (if any) + self.parentPos = 0 + + if not inner: + DataCracker._tabLevel = 0 + + def internalCrackData(self, template, buff, method='setValue'): + """ + This is the internal method called when we recurse into + crackData. It will not perform certain operations that should + be performed on the entire data model instead of sub-portions. + """ + + if not isinstance(buff, PublisherBuffer): + raise Exception("Error: buff is not a PublisherBuffer") + + self.method = method + (rating, pos) = self._handleNode(template, buff, 0, None) #, self.dom) + Debug(1, "RATING: %d - POS: %d - LEN(DATA): %d" % (rating, self.parentPos + pos, len(buff.data))) + if pos < len(buff.data) - 1: + Debug(1, highlight.warning("WARNING: Did not consume all data!!!")) + + Debug(1, "Done cracking stuff") + return rating, pos + + def optmizeModelForCracking(self, datamodel, silent=False): + """ + This method will pre-compute some values that will + enable optimzing how we crack data into said model. + """ + + if not silent: + logging.info("Optimizing DataModel '%s'" % datamodel.name) + + # Setup choice fastcheck + for node in datamodel.getAllChildDataElements(): + if node.elementType == 'choice': + for child in node: + # If _isTokenNext on our choice child is true we can cache + # cache that value and use it to super speed up choice checks + fastCheck = False + fastCheckValue = None + fastCheckOffset = 0 + + if child.isStatic: + fastCheck = True + fastCheckValue = child.getValue() + fastCheckOffset = 0 + + #Debug(1, "optmizeModelForCracking: FastCheck: Child is token for '%s'" % child.name) + else: + values = self._isTokenNext(child, True) + #Debug(1, "optmizeModelForCracking: FastCheck: back from _isTokenNext") + if values is not None and values[0].getFullname().find(child.getFullname()) != -1: + fastCheck = True + fastCheckValue = values[0].getValue() + fastCheckOffset = values[1] + + # Sanity check + if len(fastCheckValue) < 1: + raise PeachException( + "optmizeModelForCracking: Warning, fastCheckValue is < 1 in length") + + #Debug(1, "optmizeModelForCracking: FastCheck: Found next token for '%s' [%s]" % (child.name, values[0].name)) + + else: + #Debug(1, "optmizeModelForCracking: Found no token for '%s'" % child.name) + #raise PeachException("_handleChoice(): Found no token for '%s'" % child.name) + pass + + child.choiceCache = (fastCheck, fastCheckOffset, fastCheckValue) + + + def crackData(self, template, buff, method='setValue'): + """ + Crack data based on template. Set values into data tree. + + Will throw an exception (NeedMoreData) if additional data is required. + The exception contains the minimum amount of additional data needed before + trying to re-crack the data. + """ + + if not isinstance(buff, PublisherBuffer): + raise Exception("Error: buff is not a PublisherBuffer") + + # Reset all values in tree + # NOTE: Do not change setValue to method. We NEEVER want + # to run this with setDefaultValue or else DEATH AND DOOM TO U! + # + # Do we really need todo this? + # + #self._resetDataElementValues(template, 'setValue') + + #self.method = 'setValue' + self.crackPassed = True + self.method = method + (rating, pos) = self._handleNode(template, buff, 0, None) #, self.dom) + Debug(1, "RATING: %d - POS: %d - LEN(DATA): %d" % (rating, self.parentPos + pos, len(buff.data))) + if pos < len(buff.data) - 1: + self.crackPassed = False + Debug(1, "WARNING: Did not consume all data!!!") + if rating > 2: + self.crackPassed = False + + # Find all our placements and shift elements around. + placements = [] + for placement in template.getAllPlacementsInDataModel(): + placements.append(placement) + + for placement in placements: + # ---- + + # We need to update all relations to fully qualified names since we have fully moved + # nodes around. There are two categories. First, of-relations and second relations. + # We will track these in to arrays of a tuple. + + relations = [] + relationsHold = [] + paramReferences = [] + + Debug(1, "Get all relations") + for relation in placement.parent.getRelationsOfThisElement(): + if relation.type == 'when': + continue + + #print "Found:",relation.getFullname() + relations.append([relation, placement.parent]) + relationsHold.append(relation) + + for child in placement.parent.getAllChildDataElements(): + for relation in child.getRelationsOfThisElement(): + if relation not in relationsHold and relation.type != 'when': + #print "Found:",relation.getFullname() + relations.append([relation, child]) + relationsHold.append(relation) + + for relation in placement.parent._getAllRelationsInDataModel(placement.parent): + if relation not in relationsHold and relation.type != 'when': + try: + obj = relation.getOfElement() + if obj is None: + print("relation:", relation.getFullname()) + print("of: ", relation.of) + + raise Exception("obj is null") + except: + print("relation:", relation.getFullname()) + print("of:", relation.of) + raise + + #print "Found:",relation.getFullname() + relations.append([relation, obj]) + relationsHold.append(relation) + + # Locate things like + Debug(1, "Get all parameter references") + for param in placement.parent.getRootOfDataMap().getElementsByType(Param): + if param.name == 'ref': + obj = param.parent.parent.find(param.defaultValue.replace("'", "")) + if obj == placement.parent: + paramReferences.append([param, obj]) + + # ---- + + if placement.after is not None: + #after = template.findDataElementByName(placement.after) + after = placement.parent.find(placement.after) + if after is None: + raise Exception("Error: Unable to locate element [%s] for placement" % placement.after) + + Debug(1, "Moving element [%s] to after [%s]." % (placement.parent.name, after.name)) + Debug(1, " Pre-name: %s" % placement.parent.getFullnameInDataModel()) + Debug(1, " Found %d relations" % len(relationsHold)) + Debug(1, " Found %d param references" % len(paramReferences)) + + # Remove from old place + placement.parent.origName = placement.parent.name + del placement.parent.parent[placement.parent.origName] + + # Do we need to rename our Element? + if after.parent.has_key(placement.parent.name): + # Yes... :) + cnt = 0 + while after.parent.has_key(placement.parent.name): + placement.parent.name = placement.parent.origName + ("_%d" % cnt) + cnt += 1 + + Debug(1, " Renamed before move from [%s] to [%s]" % ( + placement.parent.origName, placement.parent.name)) + + # Insert after after + after.parent.insert(after.parent.index(after) + 1, placement.parent) + + # Update parent + placement.parent.parent = after.parent + + # Remove placement + placement.parent.placement = None + + elif placement.before is not None: + #before = template.findDataElementByName(placement.before) + before = placement.parent.find(placement.before) + if before is None: + raise Exception("Error: Unable to locate element [%s] for placement" % placement.before) + + Debug(1, "Moving element [%s] to before [%s]." % (placement.parent.name, before.name)) + Debug(1, " Pre-name: %s" % placement.parent.getFullnameInDataModel()) + Debug(1, " Found %d relations" % len(relationsHold)) + Debug(1, " Found %d param references" % len(paramReferences)) + + # Remove from old place + placement.parent.origName = placement.parent.name + del placement.parent.parent[placement.parent.origName] + + # Do we need to rename our Element? + if before.parent.has_key(placement.parent.name): + # Yes... :) + cnt = 0 + while before.parent.has_key(placement.parent.name): + placement.parent.name = placement.parent.origName + ("_%d" % cnt) + cnt += 1 + + Debug(1, " Renamed before move from [%s] to [%s]" % ( + placement.parent.origName, placement.parent.name)) + + # Insert after after + before.parent.insert(before.parent.index(before), placement.parent) + + # Update parent + placement.parent.parent = before.parent + + # Remove placement + placement.parent.placement = None + + Debug(1, " Final name: %s" % placement.parent.getFullnameInDataModel()) + + else: + raise Exception("Error: placement is all null in bad ways!") + + # Update relations + Debug(1, "Update relations") + for relation, of in relations: + relation.of = of.getFullnameInDataModel() + + # Handle FROM side too + for r in of.relations: + if r.From is not None and r.From.endswith(relation.parent.name): + r.From = relation.parent.getFullnameInDataModel() + + #print "Updating %s to %s" % (relation.getFullname(), relation.of) + + Debug(1, "Update param references") + for param, obj in paramReferences: + # Need to recreate the fixup to make sure + # it re-parses the ref parameter. + + param.defaultValue = "'''%s'''" % obj.getFullnameInDataModel() + + fixup = param.parent + + code = "PeachXml_" + fixup.classStr + '(' + + isFirst = True + for param in fixup: + if not isinstance(param, Param): + continue + + if not isFirst: + code += ', ' + else: + isFirst = False + + code += PeachStr(param.defaultValue) + + code += ')' + + fixup.fixup = evalEvent(code, {}) + + Debug(1, "Done cracking stuff") + #sys.exit(0) + + #template.printDomMap() + + return rating, pos + + def _resetDataElementValues(self, node, method): + """ + Reset values in data tree to None. + """ + + eval("node.%s(None)" % method) + + if hasattr(node, 'rating'): + node.rating = None + + if hasattr(node, 'pos'): + node.pos = None + + for child in node._children: + if isinstance(child, Peach.Engine.dom.DataElement): + self._resetDataElementValues(child, method) + + + def _GetTemplateByName(self, str): + """ + Get the object indicated by ref. Currently the object must have + been defined prior to this point in the XML + """ + + origStr = str + baseObj = self.peach + + # Parse out a namespace + + if str.find(":") > -1: + ns, tmp = str.split(':') + str = tmp + + # Check for namespace + if hasattr(self.context.namespaces, ns): + baseObj = getattr(self.context.namespaces, ns) + else: + raise Exception("Unable to locate namespace") + + for name in str.split('.'): + # check base obj + if hasattr(baseObj, name): + baseObj = getattr(baseObj, name) + + # check templates + elif hasattr(baseObj, 'templates') and hasattr(baseObj.templates, name): + baseObj = getattr(baseObj.templates, name) + + else: + raise Exception("Could not resolve ref '%s'" % origStr) + + return baseObj + + def _getRootParent(self, node): + root = node + while hasattr(root, 'parent') and root.parent is not None: + root = root.parent + + return root + + def _handleArray(self, node, buff, pos, parent=None, doingMinMax=False): + """ + This method is used when an array has been located (an element with + minOccurs or maxOccurs set). + + Note: This code was moved out of _handleNode() on 11/16/08 + + Todo: This array handling code has gotten out of hand. It needs + some re-working and cleaning up. + """ + + Debug(1, "_handleArray(%s): %s >>Enter" % (node.name, node.elementType)) + Debug(1, "_handleArray(%s): %s" % (node.name, node.getFullname())) + + if node.parent is None: + raise Exception("Error, parent is null: " + node.name) + + Debug(1, "*** Node Occures more then once!") + rating = newRating = 1 + newCurPos = pos + origPos = pos + dom = None + curpos = None + maxOccurs = node.maxOccurs + minOccurs = node.minOccurs + name = node.name + goodLookAhead = None + hasCountRelation = False + isDeterministic = self._doesNodeHaveStatic(node) or self._doesNodeHaveConstraint(node) + origionalNode = node.copy(node.parent) + + ## Locate any count restrictions and update maxCount to match + + Debug(1, "-- Looking for Count relation...") + relation = node.getRelationOfThisElement('count') + if relation is not None and relation.type == 'count' and node.parent is not None: + maxOccurs = int(relation.getValue(True)) + Debug(1, "@@@ Found count relation [%d]" % maxOccurs) + hasCountRelation = True + + ## Check for count relation, verify > 0 + if maxOccurs < 0: + Debug(1, "_handleArray: Found negative count relation: %d" % maxOccurs) + return 4, pos + + elif maxOccurs == 0: + for child in node.getElementsByType(DataElement): + if child == node: + continue + + # Remove relation (else we get errors) + for relation in child.getRelationsOfThisElement(): + if node.getFullname().find(relation.parent.getFullname()) == 0: + # Relation inside of block we are removing + continue + + Debug(1, "@! Child Relation: From: %s - of: %s" % (relation.parent.name, relation.of)) + if relation in relation.parent.relations: + relation.parent.relations.remove(relation) + if relation.parent.has_key(relation.name): + del relation.parent[relation.name] + + for rfrom in node.relations: + if rfrom.From is not None and rfrom.From.endswith(relation.parent.name): + Debug(1, "@ Also removing FROM side") + node.relations.remove(rfrom) + if node.parent.has_key(rfrom.name): + del node.parent[rfrom.name] + + + # Remove relation (else we get errors) + for relation in node.getRelationsOfThisElement(): + Debug(1, "@ Found and removing relation: %s" % relation.getFullname()) + if relation in relation.parent.relations: + Debug(1, "@ Removing type: %s, parent.name: %s" % (relation.type, relation.parent.name)) + relation.parent.relations.remove(relation) + + if relation.parent.has_key(relation.name): + Debug(1, "@ Also removeing from collection") + del relation.parent[relation.name] + + for rfrom in node.relations: + if rfrom.From is not None and rfrom.From.endswith(relation.parent.name): + Debug(1, "@ Also removing FROM side") + node.relations.remove(rfrom) + if node.parent.has_key(rfrom.name): + del node.parent[rfrom.name] + + # Remove element + del node.parent[node.name] + + # We passed muster...I think :) + rating = 2 + pos = origPos + + Debug(1, "_handleArray(%s): Zero count on array, removed < 1 + + try: + node.relationOf = None + Debug(1, "@@@ Entering while loop") + for occurs in range(maxOccurs): + Debug(1, "@@@ In While, newCurPos=%d" % (self.parentPos + newCurPos)) + + ## Are we out at end of stream? + if buff.haveAllData and newCurPos >= len(buff.data): + Debug(1, "@ Exiting while loop, end of data! YAY!") + if occurs == 0: + Debug(1, "@ Exiting while on first loop") + if node.minOccurs > 0: + Debug(1, "@ minOccurs != 0, changing rating to 4") + rating = 4 + + else: + # This code is duplicated lower down. + + # Remove node and increase rating. + Debug(1, "@ minOccurs == 0, removing node") + + # Remove relation (else we get errors) + for relation in node.getRelationsOfThisElement(): + Debug(1, "@ Found and removing relation...") + relation.parent.relations.remove(relation) + relation.parent.__delitem__(relation.name) + + # Delete node from parent + del node.parent[node.name] + + # Fix up our rating + rating = 2 + curpos = pos + break + + else: + Debug(1, "@ Have enough data to try again: %d < %d" % (newCurPos, len(buff.data))) + + ## Make a copy so we don't overwrite existing node + if occurs > 0: + nodeCopy = origionalNode.copy(node.parent) + nodeCopy.name = name + "-%d" % occurs + + ## Add to parent + node.parent.insert(node.parent.index(node) + occurs, nodeCopy) + + else: + ## If we are on the first element + nodeCopy = node + + ## Run onArrayNext + if DataCracker._tabLevel == 0 and nodeCopy.onArrayNext is not None: + evalEvent(node.onArrayNext, {'node': nodeCopy}, node) + + ## Check out look-ahead (unless we have count relation) + if (not isDeterministic) and (not hasCountRelation) and self._nextNode(nodeCopy) is not None: + Debug(1, "*** >> node.name: %s" % node.name) + Debug(1, "*** >> nodeCopy.name: %s" % nodeCopy.name) + Debug(1, "*** >> LookAhead") + + newRating = self._lookAhead(nodeCopy, buff, newCurPos, None, False) + Debug(1, "*** << LookAhead [%d]" % newRating) + + # If look ahead was good, save and check later. + if newRating < 3: + goodLookAhead = newRating + + ## Do actual + Debug(1, "*** >> nodeCopy.name: %s" % nodeCopy.name) + Debug(1, "*** >> DOING ACTUAL HANDLENODE") + + origNewCurPos = newCurPos + (newRating, newCurPos) = self._handleNode(nodeCopy, buff, newCurPos, None, True) + if newCurPos < origNewCurPos: + raise Exception("WHoa! We shouldn't have moved back in position there... [%d:%d]" % origNewCurPos, + newCurPos) + + ## Handle minOccurs == 0 + if occurs == 0 and newRating >= 3 and node.minOccurs == 0: + # This code is duplicated higher up + + if hasCountRelation and maxOccurs > 0: + Debug(1, "Error: We think count == 0, relation says %d" % maxOccurs) + Debug(1, "Returning a rating of suck (4)") + return 4, pos + + # Remove node and increase rating. + Debug(1, "Firt element rating was poor and minOccurs == 0, remoing element and upping rating.") + + # Remove relation (else we get errors) + for relation in node.getRelationsOfThisElement(): + relation.parent.relations.remove(relation) + del relation.parent[relation.name] + + # Delete our copy + if nodeCopy.name != node.name: + del node.parent[nodeCopy.name] + + # Delete orig + del node.parent[node.name] + rating = 2 + curpos = pos = origPos + break + + ## Verify we didn't break a good lookahead + if not hasCountRelation and newRating < 3 and not self.lookAhead and goodLookAhead is not None: + lookAheadRating = self._lookAhead(nodeCopy, buff, newCurPos, None, False) + if lookAheadRating >= 3: + del node.parent[nodeCopy.name] + Debug(1, "*** Exiting min/max: We broke a good lookAhead!") + break + + ## Verify high enough rating + if newRating < 3 and not self.lookAhead: + Debug(1, "*** That worked out!") + pos = curpos = newCurPos + rating = newRating + + # First time through convert position 0 node + if occurs == 0: + ## First fix up our first node + index = node.parent.index(node) + del node.parent[node.name] + + node.array = node.name + node.name += "-0" + node.arrayPosition = 0 + node.arrayMinOccurs = node.minOccurs + node.arrayMaxOccurs = node.maxOccurs + node.minOccurs = 1 + node.maxOccurs = 1 + + node.parent.insert(index, node) + + # Update relation to have new name + if relation is not None and relation.of is not None: + # We need to support out count being outside + # a double loop, so lets check and see if + # our relation is closer to root than us + # and if so check the parents in between + + relationParents = [] + obj = relation.parent.parent + while obj is not None and obj.parent is not None: + if isinstance(obj, DataElement): + relationParents.append(obj) + obj = obj.parent + + currentParents = [] + obj = node.parent + while obj is not None and obj.parent is not None: + if isinstance(obj, DataElement): + currentParents.append(obj) + obj = obj.parent + + boolInsideArray = False + if len(currentParents) > len(relationParents): + minParents = len(relationParents) + else: + minParents = len(currentParents) + + # Make sure i gets initialized + # in some cases (minParents == 0) we never + # go through this next for loop and i is unknown. + i = minParents + + for i in range(minParents): + if relationParents[i] != currentParents[i]: + #Debug(1, "_handleArray: Miss-match parents: %s, %s" % (relationParents[i].name, currentParents[i].name)) + break + + #Debug(1, "_handleArray: i == %d" % i) + for x in range(i, len(currentParents)): + if currentParents[x].maxOccurs > 1: + #Debug(1, "_handleArray: Outside array found: %s" % currentParents[x].name) + boolInsideArray = True + break + + if boolInsideArray: + Debug(1, "_handleArray: Our count relation is outside of a double array.") + Debug(1, "_handleArray: Keeping a copy around for next iteration.") + + newRel = relation.copy(relation.parent) + relation.parent.append(newRel) + relation.parent.relations.append(newRel) + else: + Debug(1, "_handleArray: No double array relation issue") + + # Should we remove From? + for r in origionalNode.relations: + if r.From == relation.parent.name: + Debug(1, "_handleArray: Removing r.From origionalNode") + + origionalNode.relations.remove(r) + + try: + del origionalNode[r.name] + except: + pass + + # Now update curretn realtion + relation.of = node.name + + + else: + # Next fix up our copied node + nodeCopy.array = node.array + nodeCopy.arrayPosition = occurs + nodeCopy.arrayMinOccurs = node.arrayMinOccurs + nodeCopy.arrayMaxOccurs = node.arrayMaxOccurs + nodeCopy.minOccurs = 1 + nodeCopy.maxOccurs = 1 + + else: + Debug(1, "*** Didn't work out!") + del node.parent[nodeCopy.name] + break + + occurs += 1 + + Debug(1, "@@@ Looping, occurs=%d, rating=%d" % (occurs, rating)) + + if occurs < minOccurs: + rating = 4 + + Debug(1, "@@@ Exiting While Loop") + + except: + #pass + raise + + ### Do a quick dump of parent's children: + #print "------" + #for c in node.parent: + # if isinstance(c, DataElement): + # print c.name + #print "------" + + if curpos is not None: + Debug(1, "@@@ Returning a rating=%d, curpos=%d, pos=%d, newCurPos=%d, occuurs=%d" % ( + rating, self.parentPos + curpos, self.parentPos + pos, self.parentPos + newCurPos, occurs)) + node.relationOf = None + return rating, curpos + + Debug(1, "_handleArray(%s): type=%s, realpos=%d, pos=%d, rating=%d <>Enter" % (highlight.info(node.name), node.elementType, pos)) + + ## Sanity checking + + if pos > len(buff.data): + Debug(1, "_handleNode: Running past data!, pos: %d, len.data: %d" % (pos, len(buff.data))) + return 4, pos + + if node is None: + raise Exception("_handleNode: Node is None, bailing!") + + ## Save off origional position + + origPos = pos + + ## check for when relation + + if node.HasWhenRelation(): + rel = node.GetWhenRelation() + + environment = { + #'Peach' : self.engine.peach, + 'self': node, + 'pos': pos, + 'data': buff.data + } + + Debug(1, "_handleNode: When: Running expression") + node._fixRealParent(node) + + if not evalEvent(rel.when, environment, node): + # Remove this node from data tree + #print "REMOVING:",node.name + + # Locate relations and kill 'em off + for r in node.getRelationsOfThisElement(): + # With --new we had some issues with + # double deleteing. + + try: + r.parent.relations.remove(r) + del r.parent[r.name] + except: + pass + + # Remove relations for all children as well + for child in node.getAllChildDataElements(): + for r in child.getRelationsOfThisElement(): + try: + r.parent.relations.remove(r) + del r.parent[r.name] + except: + pass + + node._unFixRealParent(node) + del node.parent[node.name] + + Debug(1, "_handleNode: When: Returned False. Removing and returning 1.") + + node.relationOf = None + return 1, pos + + node._unFixRealParent(node) + Debug(1, "_handleNode: When: Returned True.") + + ## Skipp around if we have an offset relations + + popPosition = None + if isinstance(node, DataElement) and not (not doingMinMax and (node.minOccurs < 1 or node.maxOccurs > 1)): + relation = node.getRelationOfThisElement('offset') + if relation is not None and relation.type == 'offset': + # We need to move this show! + try: + Debug(1, "_handleNode: Found offset relation") + Debug(1, "_handleNode: Origional position saved as %d" % (self.parentPos + pos)) + popPosition = pos + pos = int(relation.getValue(True)) + Debug(1, "_handleNode: Changed position to %d" % (self.parentPos + pos)) + + except: + raise + else: + Debug(1, "_handleNode: Did not find offset relation") + + ## Would be nice to have our current pos in scripting :) + node.possiblePos = pos + + ## Do the crazy! (aka call specific crack handler) + + # Array handling *MUST* always be first! + if not doingMinMax and (node.minOccurs < 1 or node.maxOccurs > 1): + if popPosition is not None: + raise PeachException("Error: Found an offset relation to an array, this is not allowed!") + + (rating, pos) = self._handleArray(node, buff, pos, parent, doingMinMax) + + elif node.elementType == 'string': + (rating, pos) = self._handleString(node, buff, pos, parent, doingMinMax) + + # Do we have a transformer, if so decode the data + if node.transformer is not None: + try: + Debug(1, "_handleNode: String: Found transformer, decoding...") + node.defaultValue = node.transformer.transformer.decode(node.defaultValue) + + except: + Debug(1, "_handleNode: String: Transformer threw exception!") + pass + + elif node.elementType == 'number': + (rating, pos) = self._handleNumber(node, buff, pos, parent, doingMinMax) + + elif node.elementType in ['block', 'template', 'choice']: + # First -- Determin if we know the size of this block via a + # size-of relation + + length = None + relation = node.getRelationOfThisElement('size') + if relation is not None and relation.isOutputOnly: + relation = None + + if relation is not None and node.parent is not None: + try: + length = relation.getValue(True) + Debug(1, "-----> FOUND BLOCK OF RELATION [%s] <-----" % repr(length)) + fullName = relation.parent.getFullname() + Debug(1, "Size-of Fullname: " + fullName) + Debug(1, "node Fullname: " + node.getFullname()) + + #length = relation.getValue() + Debug(1, "Size-of Length: %s" % length) + + # Verify we are not inside the "of" portion + if fullName.find(node.getFullname() + ".") == 0: + length = None + Debug(1, "!!! Not using relation, inside of OF element") + + except: + length = None + + elif node.hasLength(): + length = node.getLength() + Debug(1, "-----> Block has known legnth: %d" % length) + + # Only if we have a length, and we are not already the top + # level element. This will prevent infinit recursion into + # the data cracker if we have a type + # situation. + if length is not None and node.parent is not None: + # Make sure we have the data + if len(buff.data) < (pos + length): + if not buff.haveAllData: + node.relationOf = None + try: + buff.read((pos + length) - len(buff.data)) + #raise NeedMoreData(length, "") + except: + rating = 4 + pos = pos + length + + else: + rating = 4 + pos = pos + length + + if len(buff.data) >= (pos + length): + Debug(1, "---- About to Crack internal Block ----") + + # Parse this node on it's own + cracker = DataCracker(self.peach, True) + cracker.haveAllData = True + cracker.parentPos = pos + self.parentPos + data = buff.data[pos:pos + length] + + # Do we have a transformer, if so decode the data + if node.transformer is not None: + try: + Debug(1, "Found transformer, decoding...") + data = node.transformer.transformer.decode(data) + + except: + Debug(1, "Transformer threw exception!") + pass + + # We need to remove the parent temporarily to + # avoid a recursion issue. + + parent = node.parent + node.parent = None + node.realParent = parent + + # We need to remove any offset relation temporarily + # to avoid running it twice + offsetRelation = node.getRelationOfThisElement('offset') + if offsetRelation is not None: + offsetRelationParent = offsetRelation.parent + + if offsetRelation in offsetRelationParent.relations: + offsetRelationParent.relations.remove(offsetRelation) + if offsetRelationParent.has_key(offsetRelation.name): + del offsetRelationParent[offsetRelation.name] + + offsetFromRelation = None + for child in node.relations: + if child.type == 'offset': + offsetFromRelation = child + + if offsetFromRelation in node.relations: + node.relations.remove(offsetFromRelation) + if node.has_key(offsetFromRelation.name): + del node[offsetFromRelation.name] + + try: + newBuff = PublisherBuffer(None, data) + (rating, crackpos) = cracker.internalCrackData(node, newBuff, self.method) + if rating == 0: + rating = 1 + + finally: + # We need to update the positions of each child + # to be + node.pos. + # + # Note: We are doing this in a finally to make + # sure the values in peach validation are + # correct. + for c in node.getAllChildDataElements(): + if hasattr(c, 'pos') and c.pos is not None: + c.pos += pos + + # Add back our offset relation + if offsetRelation is not None: + offsetRelationParent.relations.append(offsetRelation) + + if offsetFromRelation is not None: + node.relations.append(offsetFromRelation) + + # Add back our parent + node.parent = parent + delattr(node, "realParent") + node.pos = pos + node.rating = rating + + pos += length + + # Verify we used all the data + if crackpos != len(data): + Debug(1, "---- Crackpos != len(data): %d != %d ----" % (self.parentPos + crackpos, len(data))) + #rating = 4 + ## !!! NEED TO REMOVE THIS !!! + #print "WARNING: Ignoring fact that crackpos != len(data)!!!" + + Debug(1, "---- Finished with internal block (%d:%d) ----" % (rating, self.parentPos + pos)) + + else: + if node.elementType == 'choice': + (rating, pos) = self._handleChoice(node, buff, pos, parent, doingMinMax) + else: + (rating, pos) = self._handleBlock(node, buff, pos, parent, doingMinMax) + + elif node.elementType == 'blob': + (rating, pos) = self._handleBlob(node, buff, pos, parent, doingMinMax) + + # Do we have a transformer, if so decode the data + if node.transformer is not None: + try: + Debug(1, "Found transformer, decoding...") + node.defaultValue = node.transformer.transformer.decode(node.defaultValue) + + except: + Debug(1, "Transformer threw exception!") + pass + + Debug(1, "---] pos = %d" % (self.parentPos + pos)) + elif node.elementType == 'custom': + (rating, pos) = self._handleCustom(node, buff, pos, parent, doingMinMax) + Debug(1, "---] pos = %d" % (self.parentPos + pos)) + elif node.elementType == 'flags': + (rating, pos) = self._handleFlags(node, buff, pos, parent, doingMinMax) + elif node.elementType == 'seek': + (rating, pos) = self._handleSeek(node, buff, pos, parent, doingMinMax) + + else: + raise str("Unknown elementType: %s" % node.elementType) + + if popPosition is not None: + pos = popPosition + Debug(1, "Popping position back to %d" % (self.parentPos + pos)) + + try: + Debug(1, "_handleNode(%s): type=%s, realpos=%d, pos=%d, rating=%d < len(buff.data): + Debug(1, "_lookAhead(): pos > len(data), no lookahead") + return 4 + + #print "_lookAhead" + #traceback.print_stack() + + ## Setup a few variables + + DataCracker._tabLevel += 1 + + self.lookAhead = True + self.lookAheadDepth += 1 + + origNode = node + origParent = parent + + ## First lets copy the data model + root = origNode.getRootOfDataMap().copy(None) + node = root.findDataElementByName(origNode.getFullnameInDataModel()) + sibling = self._nextNode(node) + + if node is None: + raise Exception("Node should not be null here! [%s]" % origNode.getFullnameInDataModel()) + + if origParent is not None: + parent = root.findDataElementByName(origParent.getFullnameInDataModel()) + + ## If we could have more than one of the curret node + ## we will try that node again UNLESS we minMax == False + + # Why are we doing this? For String Arrays? + + if node.maxOccurs > 1 and minMax: + Debug(1, "_lookAhead(): look ahead for node") + + #try: + (rating, pos) = self._handleNode(node, buff, pos, parent) + + # If we have a good rating return it + if rating < 3: + self.lookAheadDepth -= 1 + if self.lookAheadDepth == 0: + self.lookAhead = False + + self.lookAhead = False + DataCracker._tabLevel -= 1 + return rating + + ## Now lets try that sibling if we can + + if sibling is None: + # if no sibling than everything is okay + + Debug(1, "_lookAhead(): node.nextSibling() == None, returning 1") + rating = 1 + + else: + Debug(1, "_lookAhead(): look ahead for node.Sibling(): %s->%s" % (node.name, sibling.name)) + (rating, pos) = self._handleNode(sibling, buff, pos, parent) + + self.lookAheadDepth -= 1 + if self.lookAheadDepth == 0: + self.lookAhead = False + + DataCracker._tabLevel -= 1 + if pos < len(buff.data): + return rating + 1 + + else: + return rating + + def _isTokenNext(self, node, fastChoice=False): + """ + Determine if a token node follows. Other sized + nodes can be between them. + """ + + #print "_isTokenNext(%s)" % node.name + + staticNode = None + length = 0 + n = node + while True: + if fastChoice and n.elementType == 'block' and len(n) > 0: + n = n[0] + + else: + n = self._nextNode(n) + + if n is None: + break + + if n.isStatic: + staticNode = n + break + + # If we are a choice we fail + if n.elementType == 'choice': + # Really we can look into our choice and see + # if there is a token we can match. + + for child in n: + if not hasattr(child, "choiceCache") or child.choiceCache[0] == False: + return None + + # All children are fast checks! + return n, length + + return None + + # We fail if array found + if n.minOccurs != 1 or n.maxOccurs != 1: + return None + + # If a child flag is token we don't support that + if n.elementType == 'Flags': + for child in n: + if isinstance(child, 'Flag') and child.isStatic: + if fastChoice: + return None + else: + staticNode = n + break + + # If we are a block, we need to head into the block. + if n.elementType == 'block': + # If no children then size == 0 + if len(n) == 0: + continue + + child = n[0] + if child.isStatic: + staticNode = child + break + + # If a child flag is token we don't support that + if n.elementType == 'Flags': + for child in n: + if isinstance(child, 'Flag') and child.isStatic: + if fastChoice: + return None + else: + staticNode = n + break + + s = self._hasSize(child) + if s is None: + #print "_isTokenNext: Child has no size, exiting [%s.%s]" % (n.name, child.name) + return None + + length += s + + ret = self._isTokenNext(child, fastChoice) + if ret is None: + #print "_isTokenNext: Child has no next token, exiting" + return None + + length += ret[1] + staticNode = ret[0] + break + + s = self._hasSize(n) + if s is None: + #print "_isTokenNext: N has no size, exiting [%s]" % n.name + return None + + length += s + + # Shouldn't need this check + if staticNode is None: + return None + + #print "_isTokenNext: Returning node & length" + return staticNode, length + + def _isContraintNext(self, node, fastChoice=False): + """ + Determine if a constraint node follows. + Other sized nodes can be between them. + """ + + #print "_isContraintNext(%s)" % node.name + + staticNode = None + length = 0 + n = node + while True: + if fastChoice and n.elementType == 'block' and len(n) > 0: + n = n[0] + + else: + n = self._nextNode(n) + + if n is None: + break + + if n.contraint is not None: + staticNode = n + break + + # If we are a choice we fail + if n.elementType == 'choice': + #print "_isTokenNext: Found choice, exiting" + return None + + # If a child flag is token we don't support that + if n.elementType == 'Flags': + for child in n: + if isinstance(child, 'Flag') and child.contraint is not None: + if fastChoice: + return None + else: + staticNode = n + break + + # If we are a block, we need to + # head into the block. + if n.elementType == 'block': + # If no children then size == 0 + if len(n) == 0: + continue + + child = n[0] + if child.contraint is not None: + staticNode = child + break + + # If a child flag is token we don't support that + if n.elementType == 'Flags': + for child in n: + if isinstance(child, 'Flag') and child.contraint: + if fastChoice: + return None + else: + staticNode = n + break + + s = self._hasSize(child) + if s is None: + #print "_isTokenNext: Child has no size, exiting [%s.%s]" % (n.name, child.name) + return None + + length += s + + ret = self._isConstraintNext(child, fastChoice) + if ret is None: + #print "_isTokenNext: Child has no next token, exiting" + return None + + length += ret[1] + staticNode = ret[0] + break + + s = self._hasSize(n) + if s is None: + #print "_isTokenNext: N has no size, exiting [%s]" % n.name + return None + + length += s + + # Shouldn't need this check + if staticNode is None: + return None + + #print "_isTokenNext: Returning node & length" + return staticNode, length + + def _isLastUnsizedNode(self, node): + """ + Determine if the following nodes all have known sizes. + If they do we can determine our size. + """ + + Debug(1, "_isLastUnsizedNode(%s)" % node.name) + + length = 0 + n = node + b = False + + while True: + (n, b) = self._nextNodeOrSizedParent(n) + + if b: + #Debug(1, "_isLastUnsizedNode: Found sized parent!") + break + + if n is None: + #Debug(1, "_isLastUnsizedNode: Next node returned None") + break + + s = self._hasSize(n) + if s is None: + #Debug(1, "_isLastUnsizedNode: returning None due to [%s]" % n.name) + return None + + length += s + + #Debug(1, "_isLastUnsizedNode: length: %d" % length) + return length + + def _hasSize(self, node): + """ + Determine if data element has a size and return it or None + """ + + # TODO: + # - Relations + # - Custom types? + # - Side cases + + if isinstance(node, String) or isinstance(node, Blob): + if node.length is not None: + return node.length + + if node.isStatic: + return len(node.defaultValue) + + elif isinstance(node, Number): + return int(node.size) / 8 + + elif isinstance(node, Block): + # Check for relation + relation = node.getRelationOfThisElement('size') + if relation is not None: + #Debug(1, "_hasSize(%s): Found relation" % node.name) + return int(relation.getValue(True)) + + # Check each child + size = 0 + for child in node: + if isinstance(child, DataElement): + ret = self._hasSize(child) + if ret is None: + return None + size += ret + + return size + + elif isinstance(node, Flags): + return int(node.length) / 8 + + elif isinstance(node, Choice): + # Check for relation + relation = node.getRelationOfThisElement('size') + if relation is not None: + #Debug(1, "_hasSize(%s): Found relation" % node.name) + return int(relation.getValue(True)) + + # Until choice is run we + # will not know which element + # was selected. + return None + + # Check for relation + relation = node.getRelationOfThisElement('size') + if relation is not None: + #Debug(1, "_hasSize(%s): Found relation" % node.name) + return int(relation.getValue(True)) + + return None + + def _doesNodeHaveStatic(self, node): + """ + Return true if node or it's children is static + """ + + if node.isStatic: + return True + + for c in node.getAllChildDataElements(): + if c.isStatic: + return True + + return False + + def _doesNodeHaveConstraint(self, node): + """ + Return true if node or it's children is static + """ + + if node.constraint is not None: + return True + + for c in node.getAllChildDataElements(): + if c.constraint is not None: + return True + + return False + + def _nextStaticNode(self, node): + """ + Locate the next static node or None + """ + + while node is not None and not node.isStatic: + node = self._nextNode(node) + + return node + + def _nextNodeOrSizedParent(self, node): + """ + Find the next node, or sized parent. + + Returns tubple of (Node, Boolean) + Node - Found node + Boolean - Is sized parent? + """ + + if node is None: + return None, False + + #try: + # Debug(1, "_nextNodeOrSizedParent(%s)" % node.name) + # + #except: + # Debug(1, "_nextNodeOrSizedParent: %s" % repr(node)) + # raise + + if not isinstance(node, Peach.Engine.dom.DataElement) or\ + node.elementType == 'template': + #Debug(1, "_nextNodeOrSizedParent: not data element or is template, failing") + return None, False + + # Try and escape Choice blocks. + while node.parent is not None and node.parent.elementType == 'choice': + if node.parent.maxOccurs > 1: + #Debug(1, "_nextNodeOrSizedParent: Returning node.parent due to maxOccurs > 1") + return node.parent, False + + if self._hasSize(node.parent): + #Debug(1, "_nextNodeOrSizedParent: Found sized choice parent, this is the last element") + return node.parent, True + + node = node.parent + + nextNode = node.nextSibling() + while nextNode is not None and not isinstance(nextNode, Peach.Engine.dom.DataElement): + nextNode = nextNode.nextSibling() + + if nextNode is not None and isinstance(nextNode, Peach.Engine.dom.DataElement): + #Debug(1, "_nextNodeOrSizedParent: Found: %s" % nextNode.name) + return nextNode, False + + if node.parent is not None and self._hasSize(node.parent): + #Debug(1, "_nextNodeOrSizedParent: Found sized parent, this is the last element") + return node.parent, True + + #Debug(1, "_nextNodeOrSizedParent: Calling _nextNodeOrSizedParent on parent!") + return self._nextNodeOrSizedParent(node.parent) + + + def _nextNode(self, node): + """ + Locate the next node. + + 1. Do we have a .nextSibling? + 2. Does are parent have .nextSibling? + ... + + Need to also support escaping Choice blocks! + """ + + if node is None: + return None + + #try: + # Debug(1, "_nextNode(%s)" % node.name) + # + #except: + # Debug(1, "_nextNode: %s" % repr(node)) + # raise + + if not isinstance(node, Peach.Engine.dom.DataElement) or\ + node.elementType == 'template': + #Debug(1, "_nextNode: not data element or is template") + + return None + + # Try and escape Choice blocks. + while node.parent is not None and node.parent.elementType == 'choice': + if node.parent.maxOccurs > 1: + #Debug(1, "_nextNode: Returning node.parent due to maxOccurs > 1.") + return node.parent + + node = node.parent + + nextNode = node.nextSibling() + while nextNode is not None and not isinstance(nextNode, Peach.Engine.dom.DataElement): + nextNode = nextNode.nextSibling() + + if nextNode is not None and isinstance(nextNode, Peach.Engine.dom.DataElement): + #Debug(1, "_nextNode(): Found: %s" % nextNode.name) + return nextNode + + #Debug(1, "_nextNode(): Calling _nextNode on parent!") + return self._nextNode(node.parent) + + def _adjustRating(self, rating, lookAheadRating): + if lookAheadRating == 2 and rating == 1: + rating = 2 + elif rating < 3 and lookAheadRating > 2: + return rating - 1 + elif rating == 3 and lookAheadRating > 3: + return rating - 1 + + return rating + + def _handleChoice(self, node, buff, pos, parent, doingMinMax=False): + Debug(1, "---> %s (%d)" % (node.name, self.parentPos + pos)) + + # Default is failure + rating = 4 + curpos = pos + newpos = pos + node.currentElement = None + + # Our list can shrink/expand as we go + # so lets copy the list up front. + children = [] + for child in node._children: + if isinstance(child, DataElement): + children.append(child) + + # Look for first child that matches, forget the rest. + for child in children: + # Skip any children created during array expantion + # they should already have values 'n all that good + # stuff :) + if hasattr(child, 'array') and child.array is not None: + continue + + # Try this child + + Debug(1, "_handleChoice(): Trying child [%s]" % child.name) + + fastCheck, fastCheckOffset, fastCheckValue = child.choiceCache + + # Check and see if we need to read more data for check + if fastCheck and len(fastCheckValue) > (len(buff.data) - (pos + fastCheckOffset)): + # Need to read some data in if posssible + if buff.haveAllData: + Debug(1, "_handleChoice(): FastCheck: Not enough data to match, NEXT!") + continue + + else: + size = len(fastCheckValue) - (len(buff.data) - (pos + fastCheckOffset)) + buff.read(size) + if len(fastCheckValue) > (len(buff.data) - (pos + fastCheckOffset)): + Debug(1, "_handleChoice(): FastCheck: Not enough data to match, NEXT!") + continue + + if fastCheck and buff.data[ + pos + fastCheckOffset:pos + fastCheckOffset + len(fastCheckValue)] != fastCheckValue: + Debug(1, "_handleChoice(): FastCheck: [%s] != [%s] NEXT!" % ( + buff.data[pos + fastCheckOffset:pos + len(fastCheckValue)], fastCheckValue)) + continue + + # Before we actually do this we need to emulate this as the only child. + node.choice__children = node._children + node.choice__childrenHash = node._childrenHash + node.choice_children = node.children + node._children = [] + node._childrenHash = {} + node.children = Empty() + node.append(child) + + (childRating, newpos) = self._handleNode(child, buff, curpos) + if child.currentValue is not None and len(child.currentValue) > 30: + Debug(1, "_handleChoice(): Rating: (%d) [%s]: %s = [%s]" % ( + childRating, highlight.repr(repr(child.defaultValue)), child.name, child.currentValue[:30])) + else: + Debug(1, "_handleChoice(): Rating: (%d) [%s]: %s = [%s]" % ( + childRating, highlight.repr(repr(child.defaultValue)), child.name, child.currentValue)) + + # Now lets move it all back + node._children = node.choice__children + node._childrenHash = node.choice__childrenHash + node.children = node.choice_children + node.choice__children = None + node.choice__childrenHash = None + node.choice_children = None + + # Check if we are keeping this child or not + if childRating > 2: + Debug(1, "_handleChoice(): Child did not meet requirements, NEXT!") + continue + + # Keep this child + Debug(1, "_handleChoice(): Keeping child [%s]" % child.name) + node.currentElement = child + rating = childRating + curpos = newpos + + # TODO: Lets not remove the kids, but for now to keep things + # simple, we will look like a block after this so to + # speek. + for c in children: + if c != node.currentElement: + Debug(1, "_handleChoice(): Removing unused child [%s]" % c.name) + node.__delitem__(c.name) + + break + + #Debug(1, "Choice rating: %d" % rating) + if rating < 4: + Debug(1, highlight.ok("CHOICE RATING: %d" % rating)) + if rating == 4: + Debug(1, highlight.error("CHOICE RATING: %d" % rating)) + Debug(1, "<--- %s (%d through %d)" % (node.name, self.parentPos + pos, self.parentPos + newpos)) + + if rating < 3: + node.pos = pos + node.rating = rating + + return rating, curpos + + def _handleBlock(self, node, buff, pos, parent, doingMinMax=False): + # Not going to handle alignment right now :) + + Debug(1, "---> %s (%d)" % (node.name, self.parentPos + pos)) + + rating = 0 + ratingCnt = 0 + ratingTotal = 0 + curpos = pos + + # Our list can shrink/expand as we go + # so lets copy the list up front. + children = [] + for child in node._children: + children.append(child) + + for child in children: + if not isinstance(child, DataElement) and not isinstance(child, Seek): + continue + + # Skip any children created during array expantion + # they should already have values 'n all that good + # stuff :) + if hasattr(child, 'array') and child.array is not None: + continue + + # Do the needfull + + ratingCnt += 1 + + (childRating, newpos) = self._handleNode(child, buff, curpos) + if child is not None and child.currentValue is not None and len(child.currentValue) > 30: + if child.defaultValue is not None and len(repr(child.defaultValue)) > 30: + Debug(1, "_handleBlock(%s): Rating: (%d) [%s]: %s = [%s]" % ( + node.name, childRating, highlight.repr(repr(child.defaultValue)[:30]), child.name, + child.currentValue[:30])) + else: + Debug(1, "_handleBlock(%s): Rating: (%d) [%s]: %s = [%s]" % ( + node.name, childRating, highlight.repr(repr(child.defaultValue)), child.name, + child.currentValue[:30])) + else: + if child.defaultValue is not None and len(repr(child.defaultValue)) > 30: + Debug(1, "_handleBlock(%s): Rating: (%d) [%s]: %s = [%s]" % ( + node.name, childRating, highlight.repr(repr(child.defaultValue)[:30]), child.name, + repr(child.currentValue))) + else: + Debug(1, "_handleBlock(%s): Rating: (%d) [%s]: %s = [%s]" % ( + node.name, childRating, highlight.repr(repr(child.defaultValue)), child.name, + repr(child.currentValue))) + + if childRating > 2: + Debug(1, "_handleBlock(%s): Child rating sucks, exiting" % node.name) + rating = childRating + break + + ratingTotal += childRating + if childRating > rating: + rating = childRating + + curpos = newpos + + + #Debug(1, "BLOCK RATING: %d" % rating) + if rating < 4: + Debug(1, highlight.ok("BLOCK RATING: %d" % rating)) + if rating == 4: + Debug(1, highlight.error("BLOCK RATING: %d" % rating)) + + Debug(1, "<--- %s (%d)" % (node.name, self.parentPos + pos)) + + if rating < 3: + node.pos = pos + node.rating = rating + + return rating, curpos + + def _getDataFromFullname(self, dom, name): + """ + Take a fullname (blah.blah.blah) and locate + it in our data dom. + """ + dom = self._getRootParent(dom) + obj = dom + + for part in name.split('.'): + Debug(2, "_getDataFromFullname(%s): [%s]" % (name, obj.name)) + if part == obj.name: + continue + + obj = obj[part] + + return obj[obj.name] + + def _handleString(self, node, buff, pos, parent, doingMinMax=False): + """ + Returns the rating and string. The rating is + how well we matched. + + Rating: + + 1 - BEST If our default matched and look ahead is 1 + 2 - GOOD If our default matched and look ahead is 2 + 3 - OK If our look ahead is 1 or 2 + 4 - MPH If look ahead is 3 or 4 + """ + + # We just break from this to return values + while True: + Debug(1, "---> %s (%d)" % (node.name, self.parentPos + pos)) + + self.deepString += 1 + + rating = 0 + newpos = 0 + length = None + + # If we are static we should know our + # length. + if node.length is None and node.isStatic: + try: + node.length = len(node.defaultValue) + except: + raise PeachException( + "Error: String %s doens't have a default value, yet is marked isStatic." % node.name) + + # Determin if we have a size-of relation + # and set our length accordingly. + relation = node.getRelationOfThisElement('size') + if relation is not None and relation.type == 'size': + # we have a size-of relation + Debug(1, "** FOUND SIZE OF RELATION ***") + + fullName = relation.parent.getFullname() + Debug(1, "Size-of Fullname: " + fullName) + + length = relation.getValue(True) + Debug(1, "Size-of Length: %s" % length) + + # Value may not be available yet + try: + length = int(length) + except: + pass + + # Do we know our length? + if node.getLength() is not None or length is not None: + if length is None: + length = node.getLength() + + # If we are null terminated add on to length + # Urm...! + if node.nullTerminated: + length += 1 + + Debug(1, "_handleString: Found length of: %d" % length) + + if node.type == 'wchar': + length *= 2 + + if len(buff.data) < (pos + length): + if not buff.haveAllData: + try: + buff.read((pos + length) - len(buff.data)) + + # Just make sure that buff.read actually worked. + if len(buff.data) < (pos + length): + raise Exception("Why didn't that throw???") + + except: + rating = 4 + value = "" + newpos = pos + length + Debug(1, "_handleString: Want %d, have %d" % ((pos + length), len(buff.data))) + break + + else: + rating = 4 + value = "" + newpos = pos + length + Debug(1, "_handleString: Want %d, have %d" % ((pos + length), len(buff.data))) + break + + if len(buff.data) >= (pos + length): + value = buff.data[pos:pos + length] + newpos = pos + length + defaultValue = node.defaultValue + rating = 2 + + if node.nullTerminated and node.type != 'wchar': + if value[-1] != '\0': + # Failed to locate null! + Debug(1, "%s_handleString: %s: Null not found!" % ('\t' * self.deepString, node.name)) + rating = 4 + else: + value = value[:-1] + + elif node.nullTerminated and node.type == 'wchar': + if value[-1] != '\0' and value[-2] != '\0': + # Failed to locate null! + Debug(1, "%s_handleString: %s: Null not found!" % ('\t' * self.deepString, node.name)) + rating = 4 + else: + value = value[:-2] + + if node.isStatic: + if node.type == 'wchar': + # convert to ascii string + defaultValue = node.defaultValue.decode("utf-16le") + + # Handle padding + if node.length != len(defaultValue): + defaultValue += node.padCharacter * (node.length - len(defaultValue)) + + if value != defaultValue and node.isStatic: + Debug(1, "%s_handleString: %s: Bad match, static, but default didn't match [%s != %s]" % ( + '\t' * self.deepString, node.name, repr(value), repr(defaultValue))) + rating = 4 + + else: + Debug(1, "%s_handleString: %s: By length [%s]" % ( + '\t' * self.deepString, node.name, repr(value))) + rating = 1 + + break + + raise Exception("We should not be here!") + + # Are we null terminated? + elif node.nullTerminated: + value = '' + + newpos = pos + rating = 666 + + if node.type != 'wchar': + newpos = -1 + while True: + newpos = buff.data.find('\0', pos) + + if newpos == -1: + if buff.haveAllData: + rating = 4 + value = '' + newpos = pos + break + + else: + try: + buff.read(1) + except: + rating = 4 + value = '' + newpos = pos + break + + else: + break + + if rating == 666: + newpos += 1 # find leaves us a position down, need to add one to get the null + value = buff.data[pos:newpos] + rating = 2 + + break + + elif node.type == 'wchar': + newpos = buff.data.find("\0\0", pos) + while newpos == -1: + if not buff.haveAllData: + try: + buff.read(1) + except: + pass + + elif buff.haveAllData: + rating = 4 + newpos = pos + value = '' + Debug(1, "data.find(00) returned -1, pos: %d" % pos) + break + + newpos = buff.data.find("\0\0", pos) + + if rating != 666: + break + + if newpos == pos: + Debug(1, "Found empty terminated wchar string: [%s]" % repr(value)) + value = "" + newpos += 2 + rating = 2 + break + + newpos += 3 # find leaves us a position down, need to add one to get the null + value = buff.data[pos:newpos - 2] + rating = 2 + + if len(value) % 2 != 0: + value += '\0' + + if value == '\0' or value == '\0\0': + value = "" + + # HACK for WCHAR + for i in range(1, len(value), 2): + if value[i] != '\0': + value = value[:i] + '\0' + value[i + 1:] + + for i in range(0, len(value), 2): + if ord(value[i]) > 127: + value = value[:i] + 'a' + value[i + 1:] + + Debug(1, "Found null terminated wchar string: [%s]" % repr(value)) + Debug(1, "pos: %d; newpos: %d" % (pos, newpos)) + + break + + elif node.isStatic: + # first, look for our defaultValue + if node.defaultValue is None: + raise PeachException("Error: %s is marked as static but has no default value." % node.name) + + Debug(1, "%s_handleString: %s: Found default value, doing checks" % ('\t' * self.deepString, node.name)) + + if node.type == 'wchar': + defaultValue = node.defaultValue.decode("utf-16le") + + else: + defaultValue = node.defaultValue + + newpos = pos + len(defaultValue) + value = buff.data[pos:newpos] + if value == defaultValue: + rating = 2 + break + + else: + rating = 4 + Debug(1, "%s_handleString: %s: No match [%s == %s] @ %d" % ( + '\t' * self.deepString, node.name, repr(buff.data[newpos:newpos + len(defaultValue)]), + repr(defaultValue), pos)) + break + + else: + # If we don't have a length, we try for a best fit + # by adjusting the position until our look ahead has a rating + # of 1 or 2. + + # Are we the last data element? + if self._nextNode(node) is None: + if not buff.haveAllData: + buff.readAll() + + # Keep all the data :) + Debug(1, "_handleString: Have all data, keeping it for me :)") + value = buff.data[pos:] + newpos = len(buff.data) + rating = 1 + + elif self._isTokenNext(node) is not None: + # Is there an isStatic ahead? + + staticNode, length = self._isTokenNext(node) + + Debug(1, "_handleString: self._isTokenNext(%s): %s" % (node.name, staticNode.name)) + + # 1. Locate staticNode position + val = staticNode.getValue() + Debug(1, "Looking for [%s][%s]" % (repr(val), repr(buff.data[pos:])[:50])) + valPos = buff.data[pos:].find(val) + while valPos == -1: + if buff.haveAllData: + newpos = pos + value = "" + rating = 4 + Debug(1, " :( Have all data") + break + + try: + buff.read(1) + except: + newpos = pos + value = "" + rating = 4 + Debug(1, " :( Have all data") + break + + valPos = buff.data[pos:].find(val) + + if rating == 4: + break + + # 2. Subtract length + newpos = (pos + valPos) - length + + # 3. Yuppie! + value = buff.data[pos:newpos] + rating = 1 + + Debug(1, "Found: [%d][%d:%d][%s]" % (length, self.parentPos + pos, self.parentPos + newpos, value)) + + elif self._isLastUnsizedNode(node) is not None: + # Are all other nodes of deterministic size? + + Debug(1, "_handleString: self._isLastUnsizedNode(node)") + + if not buff.haveAllData: + buff.readAll() + + length = self._isLastUnsizedNode(node) + newpos = len(buff.data) - length + value = buff.data[pos:newpos] + rating = 1 + + #elif self._isConstraintNext(node) != None: + ## Is there a constraint ahead? + + #constraintNode, length = self._isConstraintNext(node) + + #Debug(1, "_handleString: self._isConstraintNext(%s): %s" % (node.name, constraintNode.name)) + ## + ### 1. Locate staticNode position + ##val = constraintNode.getValue() + ##Debug(1, "Looking for [%s][%s]" % (repr(val), repr(buff.data[pos:]))) + ##valPos = buff.data[pos:].find(val) + ##while valPos == -1: + ## if buff.haveAllData: + ## newpos = pos + ## value = "" + ## rating = 4 + ## Debug(1, " :( Have all data") + ## break + ## + ## try: + ## buff.read(1) + ## except: + ## newpos = pos + ## value = "" + ## rating = 4 + ## Debug(1, " :( Have all data") + ## break + ## + ## valPos = buff.data[pos:].find(val) + ## + ##if rating == 4: + ## break + ## + ### 2. Subtract length + ##newpos = (pos+valPos) - length + ## + ### 3. Yuppie! + ##value = buff.data[pos:newpos] + ##rating = 1 + ## + ##Debug(1, "Found: [%d][%d:%d][%s]" % (length, self.parentPos+pos, self.parentPos+newpos, value)) + + + else: + Debug(1, "_handleString: No size for our string.") + + # Will will suckup bytes one by one check the + # look ahead each time to see if we should keep + # sucking. + # + # Note: Turns out running the lookAhead each time is slow. + + lookRating = 666 + newpos = pos + dataLen = len(buff.data) + + # If we have a following static just scan + # for it instead of calling lookAhead. + nextNode = self._nextNode(node) + if nextNode.isStatic: + nextValue = nextNode.getValue() + nextValueLen = len(nextValue) + + newpos = buff.data.find(nextValue, pos) + while newpos == -1: + if buff.haveAllData: + value = "" + rating = 4 + break + + try: + buff.read(1) + except: + value = "" + rating = 4 + break + + newpos = buff.data.find(nextValue, pos) + + if rating == 4: + break + + value = buff.data[pos:newpos] + rating = 2 + break + + # This loop is slow! Reading one char at a time! + # We should try a reading at least 2-5 chars at once. + while lookRating > 2 and newpos < dataLen: + newpos += 1 + lookRating = self._lookAhead(node, buff, newpos, parent) + + value = buff.data[pos:newpos] + + if lookRating > 2: + rating = 3 + + else: + rating = 2 + + break + + break + + # Deal with wchar + if node.type == 'wchar': + try: + value = value.decode("utf-16le") + except: + print("Error decoding: %r", value) + raise + + # contraint + if node.constraint is not None and rating < 3: + env = { + "self": node, + "pos": pos, + "newpos": newpos, + "value": value, + } + + if not evalEvent(node.constraint, env, node): + rating = 4 + newpos = pos + Debug(1, "_handleString: %s" % highlight.error("Constraint failed")) + else: + Debug(1, "_handleString: %s" % highlight.ok("Constraint passed")) + + # Set value + if rating < 3: + eval("node.%s(value)" % self.method) + + # Are we last? + if self._nextNode(node) is None: + # Are we in an array + obj = node + inArray = False + while obj.parent is not None and isinstance(obj.parent, DataElement): + if obj.maxOccurs > 1: + inArray = True + break + + obj = obj.parent + + # Note: If doingMinMax then we can't + # assume we should eat all data even + # if we are the last node! + # + # Note2: maxOccurs can lie if we are doingMinMax! + # + if newpos < len(buff.data) and not inArray and not doingMinMax: + # We didn't use it all up, sad for us! + Debug(1, "--- Didn't use all data, rating == 4") + rating = 4 + + # Return values + + Debug(1, "<--- %s (%d, %d-%d)" % (node.name, rating, self.parentPos + pos, self.parentPos + newpos)) + + if rating < 3: + node.pos = pos + node.rating = rating + + self.deepString -= 1 + return rating, newpos + + def _handleNumber(self, node, buff, pos, parent, doingMinMax=False): + """ + Handle Number. Return (rating, newpos, value) in tuple. + + Rating: + + 1 - BEST If our default matched and look ahead is 1 + 2 - GOOD If our default matched and look ahead is 2 + 3 - OK If our look ahead is 1 or 2 + 4 - MPH If look ahead is 3 or 4 + + """ + + Debug(1, "---> %s (%d)" % (node.name, self.parentPos + pos)) + + node.rating = 0 + length = node.size / 8 + + # See if we have enough data + + if (pos + length) > len(buff.data): + # need more + try: + buff.read((pos + length) - len(buff.data)) + except: + Debug(1, "_handleNumber(): Read failed: %s" % repr(sys.exc_info())) + pass + + if (pos + length) > len(buff.data): + node.rating = None + return 4, pos + + # Get value based on element length + + value = buff.data[pos:pos + length] + newpos = pos + length + + # Build format string + + fmt = '' + + if node.endian == 'little': + fmt = '<' + else: + fmt = '>' + + if node.size == 8: + fmt += 'b' + elif node.size == 16: + fmt += 'h' + #print "Number: %x %x" % (ord(value[0]), ord(value[1])) + elif node.size == 24: + fmt += 'i' + + if node.endian == 'little': + value += '\0' + else: + value = '\0' + value + + elif node.size == 32: + fmt += 'i' + elif node.size == 64: + fmt += 'q' + + if not node.signed: + fmt = fmt.upper() + + # Unpack value + + value = str(struct.unpack(fmt, value)[0]) + + # Adjust rating based on defaultValue + + if node.isStatic: + if value != str(node.defaultValue): + Debug(1, "_handleNumber: Number is static but did not match, failing. [%s] != [%s]" % ( + value, node.defaultValue)) + node.rating = 4 + else: + Debug(1, "_handleNumber: Number is static and matched. [%s] == [%s]" % (value, node.defaultValue)) + node.rating = 1 + else: + node.rating = 2 + + # contraint + if node.constraint is not None: + env = { + "self": node, + "value": int(value), + "pos": pos, + "newpos": newpos, + } + + if not evalEvent(node.constraint, env, node): + node.rating = 4 + newpos = pos + Debug(1, "_handleString: %s" % highlight.error("Constraint failed")) + else: + Debug(1, "_handleString: %s" % highlight.ok("Constraint passed")) + + # Set value on data element + if node.rating < 3: + eval("node.%s(value)" % self.method) + + # Return all of it + node.pos = pos + + Debug(1, "<--- %s (%d, %d-%d)" % (node.name, node.rating, self.parentPos + pos, self.parentPos + newpos)) + return node.rating, newpos + + def flipBitsByByte(self, num, size): + ret = 0 + for n in self.splitIntoBytes(num, size): + ret <<= 8 + ret += n + + return ret + + def splitIntoBytes(self, num, size): + ret = [] + for i in range(size / 8): + ret.append(num & 0xFF) + num >>= 8 + + return ret + + def _handleFlags(self, node, buff, pos, parent, doingMinMax=False): + """ + Returns the rating and string. The rating is + how well we matched. + + Rating: + + 1 - BEST If our default matched and look ahead is 1 + 2 - GOOD If our default matched and look ahead is 2 + 3 - OK If our look ahead is 1 or 2 + 4 - MPH If look ahead is 3 or 4 + """ + + Debug(1, "---> %s (%d)" % (node.name, self.parentPos + pos)) + + rating = 0 + length = node.length / 8 + + if (pos + length) > len(buff.data): + # need more + try: + buff.read((pos + length) - len(buff.data)) + except: + pass + + if (pos + length) > len(buff.data): + node.rating = None + return 4, pos + + value = buff.data[pos:pos + length] + newpos = pos + length + + if node.padding: + # Now, unpack the integer + + fmt2 = '>' + if node.endian == 'little' and not node.rightToLeft: + fmt = '<' + elif node.endian == 'little' and node.rightToLeft: + fmt = '>' + + elif node.endian == 'big' and node.rightToLeft: + fmt = '<' + elif node.endian == 'big' and not node.rightToLeft: + fmt = '>' + + else: + raise Exception("Error, unable to determine endian for unpack") + + if node.length == 8: + fmt += 'B' + fmt2 += 'B' + elif node.length == 16: + fmt += 'H' + fmt2 += 'H' + elif node.length == 32: + fmt += 'I' + fmt2 += 'I' + elif node.length == 64: + fmt += 'Q' + fmt2 += 'Q' + + value = int(struct.unpack(fmt, value)[0]) + value = struct.pack(fmt2, value) + + if node.endian == 'little' and not node.rightToLeft: + bits = BitBuffer(value, True) + elif node.endian == 'little' and node.rightToLeft: + bits = BitBuffer(value, False) + + elif node.endian == 'big' and node.rightToLeft: + bits = BitBuffer(value, False) + elif node.endian == 'big' and not node.rightToLeft: + bits = BitBuffer(value, True) + + else: + bits = BitBuffer(value, node.endian == 'big') + + rating = 2 + + for child in node._children: + if child.elementType != 'flag': + continue + + bits.seek(child.position) + childValue = bits.readbits(child.length) + + Debug(1, "Found child flag %s value of %s" % (child.name, str(childValue))) + + if child.isStatic: + Debug(1, "Child flag is token %s must eq %s" % (str(childValue), str(child.defaultValue))) + if str(child.defaultValue) != str(childValue): + Debug(1, "Child flag token match failed, setting rating to 4") + rating = 4 + break + + Debug(1, "Child flag token matched!") + + # Set child node value + eval("child.%s(childValue)" % self.method) + child.rating = 2 + child.pos = pos + ##print "[%s] child value:" % child.name, child.getInternalValue() + + + # contraint + if rating >= 2 and node.constraint is not None: + env = { + "self": node, + "pos": pos, + "newpos": newpos, + } + + if not evalEvent(node.constraint, env, node): + rating = 4 + newpos = pos + Debug(1, "_handleString: %s" % highlight.error("Constraint failed")) + else: + Debug(1, "_handleString: %s" % highlight.ok("Constraint passed")) + + Debug(1, "<--- %s (%d, %d-%d)" % (node.name, rating, self.parentPos + pos, self.parentPos + newpos)) + + node.pos = pos + node.rating = rating + return rating, newpos + + def binaryFormatter(self, num, bits): + ret = "" + for i in range(bits - 1, -1, -1): + ret += str((num >> i) & 1) + + assert len(ret) == bits + return ret + + + def _handleSeek(self, node, buff, pos, parent, doingMinMax=False): + """ + Handle a Seek element + """ + + Debug(1, "---> SEEK FROM %d" % (self.parentPos + pos)) + + # 1. Get the position to jump to + + newpos = node.getPosition(pos, len(buff.data), buff.data) + + # 2. Can we jump there? + + if newpos > buff.data: + # a. Do we have all the data? + if not buff.haveAllData: + # Request more + try: + buff.read((pos + newpos) - len(buff.data)) + except: + pass + + if newpos > buff.data: + # Bad rating + Debug(1, "<--- SEEK TO %d FAILED, ONLY HAVE %d" % (newpos, len(buff.data))) + return 4, pos + + elif newpos < 0: + Debug(1, "<--- SEEK TO %d FAILED, NEGATIVE NOT POSSIBLE" % newpos) + return 4, pos + + # 3. Jump there! + + Debug(1, "<--- SEEK TO %d" % newpos) + return 1, newpos + + def _handleCustom(self, node, buff, pos, parent, doingMinMax=False): + """ + Returns the rating and string. The rating is + how well we matched. + + Rating: + + 1 - BEST If our default matched and look ahead is 1 + 2 - GOOD If our default matched and look ahead is 2 + 3 - BAD + 4 - BAD + """ + + Debug(1, "---> %s (%d)" % (node.name, self.parentPos + pos)) + + rating, newpos = node.handleIncoming(self, buff, pos, parent, doingMinMax) + + # contraint + if node.constraint is not None and rating < 3: + env = { + "self": node, + "data": buff.data, + "pos": pos, + "newpos": newpos, + } + + if not evalEvent(node.constraint, env, node): + rating = 4 + newpos = pos + Debug(1, "_handleString: %s" % highlight.error("Constraint failed")) + else: + Debug(1, "_handleString: %s" % highlight.ok("Constraint passed")) + + if rating < 3: + node.pos = pos + node.rating = rating + + Debug(1, "<--- %s (%d)" % (node.name, self.parentPos + newpos)) + return rating, newpos + + def _handleBlob(self, node, buff, pos, parent, doingMinMax=False): + """ + Returns the rating and string. The rating is + how well we matched. + + Rating: + + 1 - BEST If our default matched and look ahead is 1 + 2 - GOOD If our default matched and look ahead is 2 + 3 - OK If our look ahead is 1 or 2 + 4 - MPH If look ahead is 3 or 4 + """ + + Debug(1, "---> %s (%d)" % (node.name, self.parentPos + pos)) + + rating = 0 + newpos = 0 + length = None + hasSizeofRelation = False + length = None + + # Determin if we have a size-of relation + # and set our length accordingly. + relation = node.getRelationOfThisElement('size') + if relation is not None and relation.type == 'size': + # we have a size-of relation + Debug(1, "** FOUND SIZE OF RELATION ***") + + fullName = relation.parent.getFullname() + Debug(1, "Size-of Fullname: " + fullName) + + length = relation.getValue(True) + Debug(1, "Size-of Length: %s" % length) + + # We might not be ready to get this + # value yet (look head), but try + try: + length = int(length) + except: + pass + else: + Debug(1, "_handleBlob: No relation found") + + # Do we know our length? + if node.getLength() is not None or length is not None: + Debug(1, "_handleBlob: Has length") + + if length is None: + length = node.getLength() + + if (pos + length) > len(buff.data): + if not buff.haveAllData: + try: + buff.read((pos + length) - len(buff.data)) + except: + pass + + if (pos + length) > len(buff.data): + Debug(1, "_handleBlob: Not enough data, rating = 4: %d left" % (len(buff.data) - pos)) + rating = 4 + + else: + value = buff.data[pos:pos + length] + newpos = pos + length + rating = 2 + + if value == node.defaultValue: + rating = 1 + + elif node.isStatic: + rating = 4 + + else: + Debug(1, "_handleBlob: No length found") + # If we don't have a sizeof relation, we try for a best fit + # by adjusting the position until our look ahead has a rating + # of 1 or 2. + + # Are we the last data element? + if self._nextNode(node) is None: + #print "--- Last element, snafing it all :)" + buff.readAll() + value = buff.data[pos:] + newpos = len(buff.data) + rating = 1 + elif self._isLastUnsizedNode(node) is not None: + # Are all other nodes of deterministic size? + Debug(1, "_handleBlob: self._isLastUnsizedNode(node)") + buff.readAll() + length = self._isLastUnsizedNode(node) + newpos = len(buff.data) - length + value = buff.data[pos:newpos] + rating = 1 + + elif self._isTokenNext(node) is not None: + # Is there an isStatic ahead? + staticNode, length = self._isTokenNext(node) + Debug(1, "_handleBlob: self._isTokenNext(%s): %s" % (node.name, staticNode.name)) + valPos = -1 + if isinstance(staticNode, Choice): + for n in staticNode: + Debug(1, "Looking from choice for [%s][%s]" % (repr(n.choiceCache[2]), repr(buff.data[pos:]))) + valPos = buff.data[pos:].find(n.choiceCache[2]) + if valPos != -1: + break + if valPos == -1: + newpos = pos + value = "" + rating = 4 + Debug(1, "Unable to find choice branch in look ahead") + else: + # 1. Locate staticNode position + val = staticNode.getValue() + Debug(1, "Looking for [%s][%s]" % (repr(val), repr(buff.data[pos:])[:150])) + valPos = buff.data[pos:].find(val) + while valPos == -1: + if buff.haveAllData: + newpos = pos + value = "" + rating = 4 + Debug(1, " :( Have all data") + break + try: + buff.read(1) + except: + pass + valPos = buff.data[pos:].find(val) + if valPos != -1: + # 2. Subtract length + newpos = (pos + valPos) - length + # 3. Yuppie! + value = buff.data[pos:newpos] + rating = 1 + Debug(1, "Found: [%d][%d:%d][%s]" % (length, self.parentPos + pos, self.parentPos + newpos, value)) + else: + #if buff.haveAllData: + # print "--- Was not last node" + + lookRating = 666 + newpos = pos + + # If we have a following static just scan + # for it instead of calling lookAhead. + nextNode = self._nextNode(node) + if nextNode.isStatic: + nextValue = nextNode.getValue() + nextValueLen = len(nextValue) + newpos = buff.data.find(nextValue, pos) + while newpos != -1: + if buff.haveAllData: + rating = 4 + value = "" + newpos = pos + break + try: + buff.read(1) + except: + pass + newpos = buff.data.find(nextValue, pos) + if newpos != -1: + value = buff.data[pos:newpos] + rating = 2 + else: + # Lets try and remove all _lookAhead calls. + raise PeachException("Error, unable to determine size of blob [%s] while cracking." % + node.getFullname()) + while lookRating > 2 and newpos < len(buff.data): + #Debug(1, ".") + newpos += 1 + lookRating = self._lookAhead(node, buff, newpos, parent) + #Debug(1, "newpos: %d lookRating: %d data: %d" % (newpos, lookRating, len(data))) + while lookRating <= 2 and newpos < len(buff.data): + #Debug(1, ",") + newpos += 1 + lookRating = self._lookAhead(node, buff, newpos, parent) + if lookRating > 2: + newpos -= 1 + #Debug(1, "newpos: %d lookRating: %d data: %d" % (newpos, lookRating, len(data))) + #if newpos >= len(data): + # newpos -= 1 + # #raise str("Unable to parse out blob %s" % node.name) + value = buff.data[pos:newpos] + rating = 2 + #print "Found blob: [%s]" % value + + # contraint + if node.constraint is not None: + env = { + "self": node, + "value": value, + "pos": pos, + "newpos": newpos, + } + if not evalEvent(node.constraint, env, node): + rating = 4 + newpos = pos + Debug(1, "_handleString: %s" % highlight.error("Constraint failed")) + else: + Debug(1, "_handleString: %s" % highlight.ok("Constraint passed")) + if rating < 3: + eval("node.%s(value)" % self.method) + Debug(1, "<--- %s (%d, %d-%d)" % (node.name, rating, self.parentPos + pos, self.parentPos + newpos)) + node.pos = pos + node.rating = rating + return rating, newpos + + +class NeedMoreData(object): + def __init__(self, amount, msg): + self.amount = amount + self.msg = "[%d] %s]" % (amount, msg) + + def __str__(self): + return self.msg + + +def printDom(node, level=0): + tabs = '\t' * level + if node.currentValue is not None: + Debug(1, tabs + "%s: [%s]" % (node.name, node.currentValue)) + else: + Debug(1, tabs + "%s" % node.name) + try: + for child in node._children: + printDom(child, level + 1) + except: + pass diff --git a/fuzzers/Peach/Engine/incoming.pyc b/fuzzers/Peach/Engine/incoming.pyc new file mode 100644 index 0000000..0e15603 Binary files /dev/null and b/fuzzers/Peach/Engine/incoming.pyc differ diff --git a/fuzzers/Peach/Engine/parser.py b/fuzzers/Peach/Engine/parser.py new file mode 100755 index 0000000..0823e65 --- /dev/null +++ b/fuzzers/Peach/Engine/parser.py @@ -0,0 +1,3181 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import sys, re, types, os, glob, logging +import traceback +import logging +from uuid import uuid1 + +from lxml import etree + +from Peach.Engine.dom import * +from Peach.Engine import dom +import Peach.Engine +from Peach.Mutators import * +from Peach.Engine.common import * +from Peach.Engine.incoming import DataCracker +from Peach.mutatestrategies import * +from Peach.config import getInstanceProvider + + +def PeachStr(s): + """ + Our implementation of str() which does not + convert None to 'None'. + """ + + if s is None: + return None + + return str(s) + + +class PeachResolver(etree.Resolver): + def resolve(self, url, id, context): + scheme, filename = url.split(":", 1) + # raise PeachException("URL Exception: scheme required") + + # Add the files path to our sys.path + + if scheme == 'file': + + if os.path.isfile(filename): + newpath = os.path.abspath('.') + if newpath not in sys.path: + sys.path.append(newpath) + return self.resolve_file(open(filename), context) + + for d in sys.path: + for new_fn in (os.path.join(d, filename), os.path.join(d, 'Peach/Engine', filename)): + if os.path.isfile(new_fn): + newpath = os.path.abspath(os.path.split(new_fn)[0]) + if newpath not in sys.path: + sys.path.append(newpath) + return self.resolve_file(open(new_fn), context) + + raise PeachException("Peach was unable to locate [%s]" % url) + + return etree.Resolver.resolve(self, url, id, context) + + +class ParseTemplate(object): + """ + The Peach 2 XML -> Peach DOM parser. Uses lxml library. + Parser returns a top level context object that contains things like templates, namespaces, etc. + """ + + dontCrack = False + + def __init__(self, configs=None): + self._parser = etree.XMLParser(remove_comments=True) + self._parser.resolvers.add(PeachResolver()) + if configs is None: + self._configs = {} + else: + self._configs = configs + + def _getBooleanAttribute(self, node, name): + """If node has no attribute named |name| return True.""" + v = self._getAttribute(node, name) + if not v: + return True + v = v.lower() + r = v in ('true', 'yes', '1') + if not r: + assert v in ('false', 'no', '0') + return r + + def substituteConfigVariables(self, xmlString, final=False): + result = [] + pos = 0 + numVarsLeft = 0 + numVarsFound = 0 + unresolved = [] + + if not final: + logging.info("Analyzing XML for potential macros.") + + for m in re.finditer(r"\$(\w+:?\w*)\$", xmlString): + result.append(xmlString[pos:m.start(0)]) + varName = m.group(1) + + handled = False + + if varName in self._configs: + logging.debug('Setting "{}" to "{}"'.format(varName, self._configs[varName])) + result.append(self._configs[varName]) + handled = True + + elif ':' in varName: + # Instance provider + (instanceProviderName, identifier) = varName.split(':') + + instanceProvider = getInstanceProvider(instanceProviderName) + + try: + instance = str(instanceProvider.getInstanceById(identifier, self._configs)) + + logging.debug('Setting "{}" to "{}"'.format(varName, instance)) + + result.append(instance) + + handled = True + + except Exception: + # allow it to fail for now, probably need other macros to resolve this + pass + + if not handled: + result.append(m.group(0)) + unresolved.append(m.group(1)) + numVarsLeft += 1 + + pos = m.end(0) + numVarsFound += 1 + result.append(xmlString[pos:]) + + if not final: + logging.info("Found {} macros, {} resolved.".format(numVarsFound, numVarsFound - numVarsLeft)) + elif unresolved: + for u in unresolved: + logging.warning("Unresolved macro: %s" % u) + + return "".join(result) + + def parse(self, uri): + """ + Parse a Peach XML file pointed to by uri. + """ + logging.info(highlight.info("Parsing %s" % uri)) + doc = etree.parse(uri, parser=self._parser, base_url="http://phed.org").getroot() + + if "_target" in self._configs: + + target = etree.parse(self._configs["_target"], parser=self._parser, base_url="http://phed.org").getroot() + + if split_ns(target.tag)[1] != 'Peach': + raise PeachException("First element in document must be Peach, not '%s'" % target.tag) + + for child in target.iterchildren(): + doc.append(child) + + del self._configs["_target"] + + # try early to find configuration macros + self.FindConfigurations(doc) + + xmlString = etree.tostring(doc) + + return self.parseString(xmlString, findConfigs=False) + + def parseString(self, xml, findConfigs=True): + """ + Parse a string as Peach XML. + """ + + xml = self.substituteConfigVariables(xml) + + doc = etree.fromstring(xml, parser=self._parser, base_url="http://phed.org") + return self.HandleDocument(doc, findConfigs=findConfigs) + + def GetClassesInModule(self, module): + """ + Return array of class names in module + """ + + classes = [] + for item in dir(module): + i = getattr(module, item) + if type(i) == type and item[0] != '_': + classes.append(item) + elif type(i) == types.MethodType and item[0] != '_': + classes.append(item) + elif type(i) == types.FunctionType and item[0] != '_': + classes.append(item) + elif repr(i).startswith(" elements" + has_config = True + #print "Found Configuration element" + for child in child.iterchildren(): + child_tag = split_ns(child.tag)[1] + assert child_tag == "Macro", "Unknown child in Configuration element: {}".format(child_tag) + name = child.get("name") + if name not in self._configs: + #print "\t%s = %s" % (name, child.get("value")) + self._configs[name] = child.get("value") + else: + #print "\t%s = %s [dropped]" % (name, child.get("value")) + pass + return has_config + + def HandleDocument(self, doc, uri="", findConfigs=True): + + if findConfigs and self.FindConfigurations(doc): + return self.parseString(etree.tostring(doc), findConfigs=False) + + #self.StripComments(doc) + self.StripText(doc) + + ePeach = doc + + if split_ns(ePeach.tag)[1] != 'Peach': + raise PeachException("First element in document must be Peach, not '%s'" % ePeach.tag) + + peach = dom.Peach() + peach.peachPitUri = uri + #peach.node = doc + self.context = peach + peach.mutators = None + + #: List of nodes that need some parse love list of [xmlNode, parent] + self.unfinishedReferences = [] + + for i in ['templates', 'data', 'agents', 'namespaces', 'tests', 'runs']: + setattr(peach, i, ElementWithChildren()) + + # Peach attributes + + for i in ['version', 'author', 'description']: + setattr(peach, i, self._getAttribute(ePeach, i)) + + # The good stuff -- We are going todo multiple passes here to increase the likely hood + # that things will turn out okay. + + # Pass 1 -- Include, PythonPath, Defaults + for child in ePeach.iterchildren(): + child_tag = split_ns(child.tag)[1] + if child_tag == 'Include': + # Include this file + + nsName = self._getAttribute(child, 'ns') + nsSrc = self._getAttribute(child, 'src') + + parser = ParseTemplate(self._configs) + ns = parser.parse(nsSrc) + + ns.name = nsName + ':' + nsSrc + ns.nsName = nsName + ns.nsSrc = nsSrc + ns.elementType = 'namespace' + ns.toXml = new_instancemethod(dom.Namespace.toXml, ns) + + nss = Namespace() + nss.ns = ns + nss.nsName = nsName + nss.nsSrc = nsSrc + nss.name = nsName + ":" + nsSrc + nss.parent = peach + ns.parent = nss + + peach.append(nss) + peach.namespaces.append(ns) + setattr(peach.namespaces, nsName, ns) + + elif child_tag == 'PythonPath': + # Add a search path + + p = self.HandlePythonPath(child, peach) + peach.append(p) + sys.path.append(p.name) + + elif child_tag == 'Defaults': + self.HandleDefaults(child, peach) + + # one last check for unresolved macros + for child in ePeach.iterdescendants(): + for k,v in list(child.items()): + child.set(k, self.substituteConfigVariables(v, final=True)) + + # Pass 2 -- Import + for child in ePeach.iterchildren(): + child_tag = split_ns(child.tag)[1] + if child_tag == 'Import': + # Import module + + if child.get('import') is None: + raise PeachException("Import element did not have import attribute!") + + importStr = self._getAttribute(child, 'import') + + if child.get('from') is not None: + fromStr = self._getAttribute(child, 'from') + + if importStr == "*": + module = __import__(PeachStr(fromStr), globals(), locals(), [PeachStr(importStr)], -1) + + try: + # If we are a module with other modules in us then we have an __all__ + for item in module.__all__: + globals()["PeachXml_" + item] = getattr(module, item) + + except: + # Else we just have some classes in us with no __all__ + for item in self.GetClassesInModule(module): + globals()["PeachXml_" + item] = getattr(module, item) + + else: + module = __import__(PeachStr(fromStr), globals(), locals(), [PeachStr(importStr)], -1) + for item in importStr.split(','): + item = item.strip() + globals()["PeachXml_" + item] = getattr(module, item) + + else: + globals()["PeachXml_" + importStr] = __import__(PeachStr(importStr), globals(), locals(), [], -1) + + Holder.globals = globals() + Holder.locals = locals() + + i = Element() + i.elementType = 'import' + i.importStr = self._getAttribute(child, 'import') + i.fromStr = self._getAttribute(child, 'from') + + peach.append(i) + + # Pass 3 -- Template + for child in ePeach.iterchildren(): + child_tag = split_ns(child.tag)[1] + if child_tag == "Python": + code = self._getAttribute(child, "code") + if code is not None: + exec(code) + + elif child_tag == 'Analyzer': + self.HandleAnalyzerTopLevel(child, peach) + + elif child_tag == 'DataModel' or child_tag == 'Template': + # do something + template = self.HandleTemplate(child, peach) + #template.node = child + peach.append(template) + peach.templates.append(template) + setattr(peach.templates, template.name, template) + + # Pass 4 -- Data, Agent + for child in ePeach.iterchildren(): + child_tag = split_ns(child.tag)[1] + if child_tag == 'Data': + # do data + data = self.HandleData(child, peach) + #data.node = child + peach.append(data) + peach.data.append(data) + setattr(peach.data, data.name, data) + + elif child_tag == 'Agent': + agent = self.HandleAgent(child, None) + #agent.node = child + peach.append(agent) + peach.agents.append(agent) + setattr(peach.agents, agent.name, agent) + + elif child_tag == 'StateModel' or child_tag == 'StateMachine': + stateMachine = self.HandleStateMachine(child, peach) + #stateMachine.node = child + peach.append(stateMachine) + + elif child_tag == 'Mutators': + if self._getBooleanAttribute(child, "enabled"): + mutators = self.HandleMutators(child, peach) + peach.mutators = mutators + + # Pass 5 -- Tests + for child in ePeach.iterchildren(): + child_tag = split_ns(child.tag)[1] + if child_tag == 'Test': + tests = self.HandleTest(child, None) + #tests.node = child + peach.append(tests) + peach.tests.append(tests) + setattr(peach.tests, tests.name, tests) + + elif child_tag == 'Run': + run = self.HandleRun(child, None) + #run.node = child + peach.append(run) + peach.runs.append(run) + setattr(peach.runs, run.name, run) + + # Pass 6 -- Analyzers + + # Simce analyzers can modify the DOM we need to make our list + # of objects we will look at first! + + objs = [] + + for child in peach.getElementsByType(Blob): + if child.analyzer is not None and child.defaultValue is not None and child not in objs: + objs.append(child) + for child in peach.getElementsByType(String): + if child.analyzer is not None and child.defaultValue is not None and child not in objs: + objs.append(child) + + for child in objs: + try: + analyzer = eval("%s()" % child.analyzer) + except: + analyzer = eval("PeachXml_" + "%s()" % child.analyzer) + + analyzer.asDataElement(child, {}, child.defaultValue) + + # We suck, so fix this up + peach._FixParents() + peach.verifyDomMap() + #peach.printDomMap() + + return peach + + def StripComments(self, node): + i = 0 + while i < len(node): + if not etree.iselement(node[i]): + del node[i] # may not preserve text, don't care + else: + self.StripComments(node[i]) + i += 1 + + def StripText(self, node): + node.text = node.tail = None + for desc in node.iterdescendants(): + desc.text = desc.tail = None + + def GetRef(self, str, parent=None, childAttr='templates'): + """ + Get the object indicated by ref. Currently the object must have + been defined prior to this point in the XML + """ + + #print "GetRef(%s) -- Starting" % str + + origStr = str + baseObj = self.context + hasNamespace = False + isTopName = True + found = False + + # Parse out a namespace + + if str.find(":") > -1: + ns, tmp = str.split(':') + str = tmp + + #print "GetRef(%s): Found namepsace: %s" % (str, ns) + + # Check for namespace + if hasattr(self.context.namespaces, ns): + baseObj = getattr(self.context.namespaces, ns) + else: + #print self + raise PeachException("Unable to locate namespace: " + origStr) + + hasNamespace = True + + for name in str.split('.'): + #print "GetRef(%s): Looking for part %s" % (str, name) + + found = False + + if not hasNamespace and isTopName and parent is not None: + # check parent, walk up from current parent to top + # level parent checking at each level. + + while parent is not None and not found: + #print "GetRef(%s): Parent.name: %s" % (name, parent.name) + + if hasattr(parent, 'name') and parent.name == name: + baseObj = parent + found = True + + elif hasattr(parent, name): + baseObj = getattr(parent, name) + found = True + + elif hasattr(parent.children, name): + baseObj = getattr(parent.children, name) + found = True + + elif hasattr(parent, childAttr) and hasattr(getattr(parent, childAttr), name): + baseObj = getattr(getattr(parent, childAttr), name) + found = True + + else: + parent = parent.parent + + # check base obj + elif hasattr(baseObj, name): + baseObj = getattr(baseObj, name) + found = True + + # check childAttr + elif hasattr(baseObj, childAttr): + obj = getattr(baseObj, childAttr) + if hasattr(obj, name): + baseObj = getattr(obj, name) + found = True + + else: + raise PeachException("Could not resolve ref %s" % origStr) + + # check childAttr + if found == False and hasattr(baseObj, childAttr): + obj = getattr(baseObj, childAttr) + if hasattr(obj, name): + baseObj = getattr(obj, name) + found = True + + # check across namespaces if we can't find it in ours + if isTopName and found == False: + for child in baseObj: + if child.elementType != 'namespace': + continue + + #print "GetRef(%s): CHecking namepsace: %s" % (str, child.name) + ret = self._SearchNamespaces(child, name, childAttr) + if ret: + #print "GetRef(%s) Found part %s in namespace" % (str, name) + baseObj = ret + found = True + + isTopName = False + + if not found: + raise PeachException("Unable to resolve reference: %s" % origStr) + + return baseObj + + def _SearchNamespaces(self, obj, name, attr): + """ + Used by GetRef to search across namespaces + """ + + #print "_SearchNamespaces(%s, %s)" % (obj.name, name) + #print "dir(obj): ", dir(obj) + + # Namespaces are stuffed under this variable + # if we have it we should be it :) + if hasattr(obj, 'ns'): + obj = obj.ns + + if hasattr(obj, name): + return getattr(obj, name) + + elif hasattr(obj, attr) and hasattr(getattr(obj, attr), name): + return getattr(getattr(obj, attr), name) + + for child in obj: + if child.elementType != 'namespace': + continue + + ret = self._SearchNamespaces(child, name, attr) + if ret is not None: + return ret + + return None + + def GetDataRef(self, str): + """ + Get the data object indicated by ref. Currently the object must + have been defined prior to this point in the XML. + """ + + origStr = str + baseObj = self.context + + # Parse out a namespace + + if str.find(":") > -1: + ns, tmp = str.split(':') + str = tmp + + #print "GetRef(): Found namepsace:",ns + + # Check for namespace + if hasattr(self.context.namespaces, ns): + baseObj = getattr(self.context.namespaces, ns) + else: + raise PeachException("Unable to locate namespace") + + for name in str.split('.'): + # check base obj + if hasattr(baseObj, name): + baseObj = getattr(baseObj, name) + + # check templates + elif hasattr(baseObj, 'data') and hasattr(baseObj.data, name): + baseObj = getattr(baseObj.data, name) + + else: + raise PeachException("Could not resolve ref '%s'" % origStr) + + return baseObj + + _regsHex = ( + re.compile(r"^([,\s]*\\x([a-zA-Z0-9]{2})[,\s]*)"), + re.compile(r"^([,\s]*%([a-zA-Z0-9]{2})[,\s]*)"), + re.compile(r"^([,\s]*0x([a-zA-Z0-9]{2})[,\s]*)"), + re.compile(r"^([,\s]*x([a-zA-Z0-9]{2})[,\s]*)"), + re.compile(r"^([,\s]*([a-zA-Z0-9]{2})[,\s]*)") + ) + + def GetValueFromNode(self, node): + value = None + type = 'string' + + if node.get('valueType') is not None: + type = self._getAttribute(node, 'valueType') + if not (type == 'literal' or type == 'hex'): + type = 'string' + + if node.get('value') is not None: + value = self._getAttribute(node, 'value') + + # Convert variouse forms of hex into a binary string + if type == 'hex': + if len(value) == 1: + value = "0" + value + + ret = '' + + valueLen = len(value) + 1 + while valueLen > len(value): + valueLen = len(value) + + for i in range(len(self._regsHex)): + match = self._regsHex[i].search(value) + if match is not None: + while match is not None: + ret += chr(int(match.group(2), 16)) + value = self._regsHex[i].sub('', value) + match = self._regsHex[i].search(value) + break + + return ret + + elif type == 'literal': + return eval(value) + + if value is not None and (type == 'string' or node.get('valueType') is None): + value = re.sub(r"([^\\])\\n", r"\1\n", value) + value = re.sub(r"([^\\])\\r", r"\1\r", value) + value = re.sub(r"([^\\])\\t", r"\1\t", value) + value = re.sub(r"([^\\])\\n", r"\1\n", value) + value = re.sub(r"([^\\])\\r", r"\1\r", value) + value = re.sub(r"([^\\])\\t", r"\1\t", value) + value = re.sub(r"^\\n", r"\n", value) + value = re.sub(r"^\\r", r"\r", value) + value = re.sub(r"^\\t", r"\t", value) + value = re.sub(r"\\\\", r"\\", value) + + return value + + def GetValueFromNodeString(self, node): + """ + This one is specific to elements. We + want to preserve unicode characters. + """ + + value = None + type = 'string' + + if node.get('valueType') is not None: + type = self._getAttribute(node, 'valueType') + if not type in ['literal', 'hex', 'string']: + raise PeachException("Error: [%s] has invalid valueType attribute." % node.getFullname()) + + if node.get('value') is not None: + value = node.get('value') + + # Convert variouse forms of hex into a binary string + if type == 'hex': + value = str(value) + + if len(value) == 1: + value = "0" + value + + ret = '' + + valueLen = len(value) + 1 + while valueLen > len(value): + valueLen = len(value) + + for i in range(len(self._regsHex)): + match = self._regsHex[i].search(value) + if match is not None: + while match is not None: + ret += chr(int(match.group(2), 16)) + value = self._regsHex[i].sub('', value) + match = self._regsHex[i].search(value) + break + + return ret + + elif type == 'literal': + value = eval(value) + + if value is not None and type == 'string': + value = re.sub(r"([^\\])\\n", r"\1\n", value) + value = re.sub(r"([^\\])\\r", r"\1\r", value) + value = re.sub(r"([^\\])\\t", r"\1\t", value) + value = re.sub(r"([^\\])\\n", r"\1\n", value) + value = re.sub(r"([^\\])\\r", r"\1\r", value) + value = re.sub(r"([^\\])\\t", r"\1\t", value) + value = re.sub(r"^\\n", r"\n", value) + value = re.sub(r"^\\r", r"\r", value) + value = re.sub(r"^\\t", r"\t", value) + value = re.sub(r"\\\\", r"\\", value) + + return value + + def GetValueFromNodeNumber(self, node): + value = None + type = 'string' + + if node.get('valueType') is not None: + type = self._getAttribute(node, 'valueType') + if not type in ['literal', 'hex', 'string']: + raise PeachException("Error: [%s] has invalid valueType attribute." % node.getFullname()) + + if node.get('value') is not None: + value = self._getAttribute(node, 'value') + + # Convert variouse forms of hex into a binary string + if type == 'hex': + if len(value) == 1: + value = "0" + value + + ret = '' + + valueLen = len(value) + 1 + while valueLen > len(value): + valueLen = len(value) + + for i in range(len(self._regsHex)): + match = self._regsHex[i].search(value) + if match is not None: + while match is not None: + ret += match.group(2) + value = self._regsHex[i].sub('', value) + match = self._regsHex[i].search(value) + break + + return int(ret, 16) + + elif type == 'literal': + value = eval(value) + + return value + + # Handlers for Template ################################################### + + def HandleTemplate(self, node, parent): + """ + Parse an element named Template. Can handle actual + Template elements and also reference Template elements. + + e.g.: + + + + or + +