├── jmxsh.jar ├── lib ├── jacl.jar ├── tcljava.jar ├── jline-0.9.93.jar ├── log4j-1.2.15.jar ├── commons-cli-1.1.jar ├── jakarta-oro-2.0.8.jar └── one-jar-ant-task-0.96.jar ├── LICENSE-ONEJAR ├── LICENSE-TCLJAVA-3 ├── jmxsh.mf ├── HIST ├── jmxsh ├── one-jar-ant-task.xml ├── NOTICE ├── .project ├── .classpath ├── testold ├── test.jmxsh └── run.jmxsh ├── src └── jmxsh │ ├── Mode.java │ ├── Context.java │ ├── package.html │ ├── Readline.java │ ├── JInterp.java │ ├── Utils.java │ ├── ListCmd.java │ ├── CloseCmd.java │ ├── TypeName.java │ ├── SetCmd.java │ ├── GetCmd.java │ ├── ShellMode.java │ ├── ConnectCmd.java │ ├── InvokeCmd.java │ ├── Jmx.java │ ├── Main.java │ └── BrowseMode.java ├── LICENSE-TCLJAVA-2 ├── test └── jmxsh │ └── test │ └── SampleJmxServer.java ├── LICENSE-JLINE ├── LICENSE-TCLJAVA ├── .settings └── org.eclipse.jdt.core.prefs ├── LICENSE-TCLJAVA-4 └── LICENSE /jmxsh.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/jmxsh.jar -------------------------------------------------------------------------------- /lib/jacl.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/lib/jacl.jar -------------------------------------------------------------------------------- /LICENSE-ONEJAR: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/LICENSE-ONEJAR -------------------------------------------------------------------------------- /lib/tcljava.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/lib/tcljava.jar -------------------------------------------------------------------------------- /LICENSE-TCLJAVA-3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/LICENSE-TCLJAVA-3 -------------------------------------------------------------------------------- /jmxsh.mf: -------------------------------------------------------------------------------- 1 | Main-Class: com.simontuffs.onejar.Boot 2 | One-Jar-Main-Class: jmxsh.Main 3 | -------------------------------------------------------------------------------- /lib/jline-0.9.93.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/lib/jline-0.9.93.jar -------------------------------------------------------------------------------- /lib/log4j-1.2.15.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/lib/log4j-1.2.15.jar -------------------------------------------------------------------------------- /lib/commons-cli-1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/lib/commons-cli-1.1.jar -------------------------------------------------------------------------------- /lib/jakarta-oro-2.0.8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/lib/jakarta-oro-2.0.8.jar -------------------------------------------------------------------------------- /lib/one-jar-ant-task-0.96.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davr/jmxsh/HEAD/lib/one-jar-ant-task-0.96.jar -------------------------------------------------------------------------------- /HIST: -------------------------------------------------------------------------------- 1 | jmxsh2.0 -- Lots of refactoring. tclsh, readline, command-line parsing. 2 | jmxsh2.1 -- Added rudimentary menus, navigation to mbean. Started on invoke, but stopped. 3 | jmxsh2.6 -- Multi-server, browser broken. 4 | jmxsh2.7 -- Browser fixed. 5 | -------------------------------------------------------------------------------- /jmxsh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # jmxsh 4 | # 5 | # A shell wrapper for jmxsh. 6 | # 7 | # Assumes java is in the PATH. If not, will need to edit this script. 8 | # 9 | # You'll need to modify this when you find a place to jmxsh. 10 | # 11 | JMXSH_JARFILE=./jmxsh.jar 12 | 13 | exec java -jar $JMXSH_JARFILE "$@" 14 | -------------------------------------------------------------------------------- /one-jar-ant-task.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This software includes the following components from the Apache Software Foundation, also 2 | released under the Apache Software License Version 2.0: 3 | 4 | commons-cli-1.1.jar 5 | jakarta-oro-2.0.8.jar 6 | log4j-1.2.15.jar 7 | 8 | The following components are covered under different licenses: 9 | 10 | jline-0.9.94.jar (LICENSE-JLINE) 11 | One-Jar (LICENSE-ONEJAR) 12 | Java/Tcl v1.3.3 (LICENSE-TCLJAVA,-2,-3,-4) 13 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | jmxsh.old 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /testold/test.jmxsh: -------------------------------------------------------------------------------- 1 | set MBEAN DefaultDomain:type=SimpleStandard 2 | 3 | puts "Integer is: [jmx_get -m $MBEAN Int]" 4 | puts "Number of state changes is: [jmx_get -m $MBEAN NbChanges]" 5 | puts "Current State is: [jmx_get -m $MBEAN State]" 6 | 7 | puts [jmx_invoke -m $MBEAN currentState] 8 | 9 | jmx_set -m $MBEAN Int 555 10 | jmx_set -m $MBEAN State "NewJersey" 11 | 12 | puts [jmx_invoke -m $MBEAN currentState] 13 | 14 | puts "Resetting..." 15 | 16 | jmx_invoke -m $MBEAN reset 17 | jmx_set -m $MBEAN Int 100 18 | 19 | puts "" 20 | 21 | puts "Integer is: [jmx_get -m $MBEAN Int]" 22 | puts "Number of state changes is: [jmx_get -m $MBEAN NbChanges]" 23 | puts "Current State is: [jmx_get -m $MBEAN State]" 24 | 25 | puts [jmx_invoke -m $MBEAN currentState] 26 | -------------------------------------------------------------------------------- /src/jmxsh/Mode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | abstract class Mode { 26 | 27 | abstract String getPrePromptDisplay(); 28 | abstract String getPrompt(); 29 | abstract String handleInput(String input); 30 | abstract void displayHelp(); 31 | 32 | static Mode getBrowseModeInstance() { 33 | return BrowseMode.instance; 34 | } 35 | 36 | static Mode getShellModeInstance() { 37 | return ShellMode.instance; 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /LICENSE-TCLJAVA-2: -------------------------------------------------------------------------------- 1 | Portions of Jacl and Tcl Blend are 2 | Copyright (c) 1997-1999 The Regents of the University of California. 3 | All rights reserved. 4 | 5 | Permission is hereby granted, without written agreement and without 6 | license or royalty fees, to use, copy, modify, and distribute this 7 | software and its documentation for any purpose, provided that the above 8 | copyright notice and the following two paragraphs appear in all copies 9 | of this software. 10 | 11 | IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 12 | FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 13 | ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 14 | THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 15 | SUCH DAMAGE. 16 | 17 | THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 18 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 20 | PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 21 | CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 22 | ENHANCEMENTS, OR MODIFICATIONS. 23 | 24 | -------------------------------------------------------------------------------- /testold/run.jmxsh: -------------------------------------------------------------------------------- 1 | puts "Now where are running it." 2 | puts "argv0: $argv0" 3 | puts "argv: $argv" 4 | puts "argc: $argc" 5 | 6 | foreach item $argv { 7 | puts "Arg: $item" 8 | } 9 | 10 | set server "foo" 11 | set mbean "DefaultDomain:type=SimpleStandard" 12 | 13 | puts "Original Int: [jmx_get -s $server -m $mbean Int]" 14 | puts "Original State: [jmx_get -s $server -m $mbean State]" 15 | 16 | jmx_set -s $server -m $mbean Int 20 17 | puts "New Int: [jmx_get -s $server -m $mbean Int]" 18 | 19 | puts "Number of changes: [jmx_get -s $server -m $mbean NbChanges]" 20 | 21 | jmx_set -s $server -m $mbean State "Here's your new state" 22 | puts "New state: [jmx_get -s $server -m $mbean State]" 23 | 24 | puts "Number of changes: [jmx_get -s $server -m $mbean NbChanges]" 25 | 26 | puts "Current state: [jmx_invoke -s $server -m $mbean currentState]" 27 | 28 | puts "Invoking reset." 29 | jmx_invoke -s $server -m $mbean reset 30 | 31 | puts "Current state: [jmx_invoke -s $server -m $mbean currentState]" 32 | 33 | puts "Current NbChange: [jmx_get -s $server -m $mbean NbChanges]" 34 | puts "Current Int: [jmx_get -s $server -m $mbean Int]" 35 | puts "Current State: [jmx_get -s $server -m $mbean State]" 36 | 37 | #set result [jmx_invoke -s $server -m $mbean [list currentState java.lang.Integer] 35] 38 | #puts "Result: $result" 39 | -------------------------------------------------------------------------------- /src/jmxsh/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | /** 26 | A tuplet that identifies a server/mbean/attribute/operation. 27 | */ 28 | 29 | class Context { 30 | String server; 31 | String domain; 32 | String mbean; 33 | String attrop; 34 | 35 | Context() { 36 | this.server = null; 37 | this.domain = null; 38 | this.mbean = null; 39 | this.attrop = null; 40 | } 41 | 42 | static private Context tclContext = new Context(); 43 | 44 | static Context fromTcl() { 45 | tclContext.server = JInterp.getGlobal("SERVER", null); 46 | tclContext.domain = JInterp.getGlobal("DOMAIN", null); 47 | tclContext.mbean = JInterp.getGlobal("MBEAN", null); 48 | tclContext.attrop = JInterp.getGlobal("ATTROP", null); 49 | return tclContext; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /test/jmxsh/test/SampleJmxServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh.test; 24 | 25 | import javax.management.*; 26 | import java.lang.management.*; 27 | import java.io.IOException; 28 | 29 | /** 30 | * A simple JMX server to use for testing. 31 | * 32 | * @author Dad 33 | */ 34 | public class SampleJmxServer { 35 | 36 | public static void main(String[] args) { 37 | System.out.println("Starting up server..."); 38 | 39 | MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 40 | 41 | 42 | 43 | System.out.println("Press enter to quit."); 44 | try { 45 | int c = System.in.read(); 46 | } 47 | catch (IOException e) { 48 | System.err.println("Error reading input."); 49 | } 50 | 51 | System.out.println("Shutting down server..."); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /LICENSE-JLINE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2006, Marc Prud'hommeaux 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or 5 | without modification, are permitted provided that the following 6 | conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer 13 | in the documentation and/or other materials provided with 14 | the distribution. 15 | 16 | Neither the name of JLine nor the names of its contributors 17 | may be used to endorse or promote products derived from this 18 | software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 22 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 23 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 24 | EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 26 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 32 | OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | -------------------------------------------------------------------------------- /src/jmxsh/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 27 | 28 | 29 | 30 | An easy-to-use, scriptable, command-line interface to JMX servers based on Java/Tcl. 31 | 32 |

Features

33 | 34 | 43 | 44 |

Future

45 | 46 | 50 | 51 | 52 | @author robspassky 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /LICENSE-TCLJAVA: -------------------------------------------------------------------------------- 1 | SUN MICROSYSTEMS, INC. THROUGH ITS SUN MICROSYSTEMS LABORATORIES 2 | DIVISION ("SUN") WILL LICENSE THIS SOFTWARE AND THE ACCOMPANYING 3 | DOCUMENTATION TO YOU (a "Licensee") ONLY ON YOUR ACCEPTANCE OF ALL 4 | THE TERMS SET FORTH BELOW. 5 | 6 | Sun grants Licensee a non-exclusive, royalty-free right to download, 7 | install, compile, use, copy and distribute the Software, modify or 8 | otherwise create derivative works from the Software (each, a 9 | "Modification") and distribute any Modification in source code and/or 10 | binary code form to its customers with a license agreement containing 11 | these terms and noting that the Software has been modified. The 12 | Software is copyrighted by Sun and other third parties and Licensee 13 | shall retain and reproduce all copyright and other notices presently 14 | on the Software. As between Sun and Licensee, Sun is the sole owner of 15 | all rights in and to the Software other than the limited rights 16 | granted to Licensee herein; Licensee will own its Modifications, 17 | expressly subject to Sun's continuing ownership of the 18 | Software. Licensee will, at its expense, defend and indemnify Sun and 19 | its licensors from and against any third party claims, including costs 20 | and reasonable attorneys' fees, and be wholly responsible for any 21 | liabilities arising out of or related to Licensee's development, use 22 | or distribution of the Software or Modifications. Any distribution of 23 | the Software and Modifications must comply with all applicable United 24 | States export control laws. 25 | 26 | THE SOFTWARE IS BEING PROVIDED TO LICENSEE "AS IS" AND ALL EXPRESS OR 27 | IMPLIED CONDITIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF 28 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, 29 | ARE DISCLAIMED. IN NO EVENT WILL SUN BE LIABLE HEREUNDER FOR ANY 30 | DIRECT DAMAGES OR ANY INDIRECT, PUNITIVE, SPECIAL, INCIDENTAL OR 31 | CONSEQUENTIAL DAMAGES OF ANY KIND. 32 | 33 | -------------------------------------------------------------------------------- /src/jmxsh/Readline.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.log4j.*; 26 | import java.io.*; 27 | import jline.*; 28 | 29 | /** 30 | Facade for jline classes. 31 | */ 32 | 33 | class Readline { 34 | 35 | private static Logger logger = Logger.getLogger(Readline.class); 36 | private static final Readline instance = new Readline(); 37 | 38 | public static Readline getInstance() { return instance; } 39 | 40 | private ConsoleReader reader; 41 | 42 | private Readline() { 43 | 44 | try { 45 | reader = new ConsoleReader(); 46 | } 47 | catch (IOException e) { 48 | logger.fatal("Could not create jline reader.", e); 49 | throw new IllegalStateException("Error creating jline reader.", e); 50 | } 51 | 52 | reader.setUseHistory(false); 53 | } 54 | 55 | void setHistoryFile(String filename) { 56 | File history = new File(filename); 57 | 58 | try { 59 | reader.getHistory().setHistoryFile(history); 60 | } 61 | catch(IOException e) { 62 | throw new IllegalArgumentException("History file '" + filename + "' does not exist is not writable.", e); 63 | } 64 | } 65 | 66 | public void addToHistory(String command) { 67 | reader.getHistory().addToHistory(command); 68 | } 69 | 70 | public String readline(String prompt) { 71 | try { 72 | return reader.readLine(prompt); 73 | } 74 | catch (IOException e) { 75 | logger.error("Readline error.", e); 76 | throw new IllegalArgumentException("Readline error: " + e.getMessage(), e); 77 | } 78 | } 79 | 80 | public String readline(String prompt, char mask) { 81 | try { 82 | return reader.readLine(prompt, mask); 83 | } 84 | catch (IOException e) { 85 | logger.error("Readline error.", e); 86 | throw new IllegalArgumentException("Readline error: " + e.getMessage(), e); 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Sat May 10 19:29:44 EDT 2008 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning 4 | org.eclipse.jdt.core.compiler.problem.autoboxing=ignore 5 | org.eclipse.jdt.core.compiler.problem.deprecation=warning 6 | org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled 7 | org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled 8 | org.eclipse.jdt.core.compiler.problem.discouragedReference=warning 9 | org.eclipse.jdt.core.compiler.problem.emptyStatement=warning 10 | org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning 11 | org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled 12 | org.eclipse.jdt.core.compiler.problem.fieldHiding=warning 13 | org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning 14 | org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning 15 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=error 16 | org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning 17 | org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning 18 | org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning 19 | org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning 20 | org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning 21 | org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning 22 | org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=error 23 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore 24 | org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning 25 | org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning 26 | org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning 27 | org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore 28 | org.eclipse.jdt.core.compiler.problem.nullReference=error 29 | org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning 30 | org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning 31 | org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning 32 | org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning 33 | org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning 34 | org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning 35 | org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled 36 | org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=ignore 37 | org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled 38 | org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning 39 | org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning 40 | org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning 41 | org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning 42 | org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning 43 | org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning 44 | org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning 45 | org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore 46 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning 47 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled 48 | org.eclipse.jdt.core.compiler.problem.unusedImport=warning 49 | org.eclipse.jdt.core.compiler.problem.unusedLabel=warning 50 | org.eclipse.jdt.core.compiler.problem.unusedLocal=warning 51 | org.eclipse.jdt.core.compiler.problem.unusedParameter=warning 52 | org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled 53 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled 54 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled 55 | org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning 56 | org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning 57 | -------------------------------------------------------------------------------- /src/jmxsh/JInterp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.log4j.*; 26 | import tcl.lang.*; 27 | 28 | class JInterp extends Interp { 29 | 30 | static private Logger logger = Logger.getLogger(JInterp.class); 31 | 32 | static JInterp instance = new JInterp(); 33 | 34 | static String getGlobal(String name, String defaultValue) { 35 | try { 36 | TclObject result = instance.getVar(name, TCL.GLOBAL_ONLY); 37 | return result.toString(); 38 | 39 | } 40 | catch (TclException e) { 41 | return defaultValue; 42 | } 43 | } 44 | 45 | static void setGlobal(String name, String value) { 46 | try { 47 | instance.setVar(name, TclString.newInstance(value), TCL.GLOBAL_ONLY); 48 | } 49 | catch (TclException e) { 50 | throw new IllegalArgumentException("Tcl error setting variable '" + name + "' to '" + value + ".", e); 51 | } 52 | } 53 | 54 | static void setGlobal(String name, int value) { 55 | try { 56 | instance.setVar(name, TclInteger.newInstance(value), TCL.GLOBAL_ONLY); 57 | } 58 | catch (TclException e) { 59 | throw new IllegalArgumentException("Tcl error setting variable '" + name + "' to '" + value + ".", e); 60 | } 61 | } 62 | 63 | static void setGlobal(String array, String key, String value) { 64 | try { 65 | instance.setVar(array, key, value, TCL.GLOBAL_ONLY); 66 | } 67 | catch (TclException e) { 68 | throw new IllegalArgumentException("Tcl error setting array value."); 69 | } 70 | } 71 | 72 | static void setGlobal(String name, String[] value, int startIndex) { 73 | TclObject list = TclList.newInstance(); 74 | 75 | try { 76 | for (int i=startIndex; i ctor = Class.forName(newType.toString()).getConstructor(new Class[]{String.class}); 106 | result = ctor.newInstance(new Object[]{obj.toString()}); 107 | } 108 | catch (NoSuchMethodException e) { 109 | throw new IllegalArgumentException("Cannot instantiate attribute of type: '" + newType.toString() + "' - cannot convert from string.", e); 110 | } 111 | catch (ClassNotFoundException e) { 112 | throw new IllegalArgumentException("Cannot instantiate attribute of type: '" + newType.toString() + "' - class not found locally.", e); 113 | } 114 | catch (InstantiationException e) { 115 | throw new IllegalArgumentException("Cannot instantiate attribute of type: '" + newType.toString() + "' - class cannot be instantiated.", e); 116 | } 117 | catch (IllegalAccessException e) { 118 | throw new IllegalArgumentException("Cannot instantiate attribute of type: '" + newType.toString() + "' - cannot access constructor.", e); 119 | } 120 | catch (InvocationTargetException e) { 121 | throw new IllegalArgumentException("Cannot instantiate attribute of type: '" + newType.toString() + "' - exception thrown in constructor.", e); 122 | } 123 | 124 | return result; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/jmxsh/ListCmd.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | 26 | import java.util.*; 27 | import org.apache.commons.cli.*; 28 | import tcl.lang.*; 29 | 30 | 31 | class ListCmd implements Command { 32 | 33 | private final static ListCmd instance = new ListCmd(); 34 | 35 | private String server; 36 | private Options opts; 37 | 38 | static ListCmd getInstance() { 39 | return instance; 40 | } 41 | 42 | private ListCmd() { 43 | this.opts = new Options(); 44 | 45 | this.opts.addOption( 46 | OptionBuilder.withLongOpt("server") 47 | .withDescription("Server containing mbean.") 48 | .withArgName("SERVER") 49 | .hasArg() 50 | .create("s") 51 | ); 52 | 53 | this.opts.addOption( 54 | OptionBuilder.withLongOpt("help") 55 | .withDescription("Display usage help.") 56 | .hasArg(false) 57 | .create("?") 58 | ); 59 | } 60 | 61 | private CommandLine parseCommandLine(TclObject argv[]) 62 | throws ParseException { 63 | 64 | String[] args = new String[argv.length - 1]; 65 | 66 | for(int i = 0; i < argv.length - 1; i++) 67 | args[i] = argv[i + 1].toString(); 68 | 69 | CommandLine cl = (new PosixParser()).parse(this.opts, args); 70 | return cl; 71 | } 72 | 73 | private void listDefaults(Interp interp) { 74 | this.server = null; 75 | 76 | try { 77 | this.server = interp.getVar("SERVER", TCL.GLOBAL_ONLY).toString(); 78 | } 79 | catch (TclException e) { 80 | /* If one doesn't exist, it will just be null. */ 81 | } 82 | 83 | } 84 | 85 | public void cmdProc(Interp interp, TclObject argv[]) 86 | throws TclException { 87 | 88 | try { 89 | CommandLine cl = parseCommandLine(argv); 90 | String args[] = cl.getArgs(); 91 | String[] expressions = null; 92 | 93 | if (cl.hasOption("help")) { 94 | new HelpFormatter().printHelp ( 95 | "jmx_list [-?] [-s server] domain_regex:mbean_regex", 96 | "======================================================================", 97 | this.opts, 98 | "======================================================================", 99 | false 100 | ); 101 | System.out.println("jmx_list retrieves the list of known mbeans for the given"); 102 | System.out.println("server. It takes a pair of regex expressions separated by"); 103 | System.out.println("colon. The first is an expression for the domain, the"); 104 | System.out.println("second is an expression for the mbean."); 105 | System.out.println(""); 106 | System.out.println("It will return a list of tcl strings."); 107 | return; 108 | } 109 | 110 | listDefaults(interp); 111 | 112 | this.server = cl.getOptionValue("server", this.server); 113 | 114 | if (args.length > 0) { 115 | expressions = args[0].split(":"); 116 | } 117 | 118 | if (this.server == null) { 119 | throw new TclException(interp, "No server specified; please set SERVER variable or use -s option.", TCL.ERROR); 120 | } 121 | 122 | String domain_regex = (expressions != null && expressions.length > 0) ? expressions[0] : ""; 123 | String mbean_regex = (expressions != null && expressions.length > 1) ? expressions[1] : ""; 124 | 125 | String[] domains = Jmx.getInstance().getDomains(this.server, domain_regex); 126 | Vector beans = new Vector(); 127 | for (String domain : domains) { 128 | List list = Arrays.asList(Jmx.getInstance().getMBeans(this.server, domain, mbean_regex)); 129 | beans.addAll(list); 130 | } 131 | 132 | String[] emptyStringArray = new String[0]; 133 | TclObject result = Utils.array2list(beans.toArray(emptyStringArray)); 134 | interp.setResult(result); 135 | } 136 | catch(ParseException e) { 137 | throw new TclException(interp, e.getMessage(), 1); 138 | } 139 | catch(RuntimeException e) { 140 | throw new TclException(interp, "Cannot convert result to a string.", 1); 141 | } 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/jmxsh/CloseCmd.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.commons.cli.CommandLine; 26 | import org.apache.commons.cli.HelpFormatter; 27 | import org.apache.commons.cli.OptionBuilder; 28 | import org.apache.commons.cli.Options; 29 | import org.apache.commons.cli.ParseException; 30 | import org.apache.commons.cli.PosixParser; 31 | import org.apache.log4j.Logger; 32 | 33 | import tcl.lang.Command; 34 | import tcl.lang.Interp; 35 | import tcl.lang.TCL; 36 | import tcl.lang.TclException; 37 | import tcl.lang.TclObject; 38 | import tcl.lang.TclString; 39 | 40 | /** 41 | * Tcl command for closing a JMX connection. 42 | * 43 | * @author robspassky 44 | */ 45 | 46 | class CloseCmd implements Command { 47 | 48 | final static CloseCmd instance = new CloseCmd(); 49 | 50 | /** Initializes private variables. Setup the command-line options. */ 51 | private CloseCmd() { 52 | this.opts = new Options(); 53 | 54 | this.opts.addOption( 55 | OptionBuilder.withLongOpt("server") 56 | .withDescription("Server containing mbean.") 57 | .withArgName("SERVER") 58 | .hasArg() 59 | .create("s") 60 | ); 61 | 62 | this.opts.addOption( 63 | OptionBuilder.withLongOpt("help") 64 | .withDescription("Display usage help.") 65 | .hasArg(false) 66 | .create("?") 67 | ); 68 | } 69 | 70 | private CommandLine parseCommandLine(TclObject argv[]) 71 | throws ParseException { 72 | 73 | String[] args = new String[argv.length - 1]; 74 | 75 | for(int i = 0; i < argv.length - 1; i++) 76 | args[i] = argv[i + 1].toString(); 77 | 78 | CommandLine cl = (new PosixParser()).parse(this.opts, args); 79 | return cl; 80 | } 81 | 82 | private void getDefaults(Interp interp) { 83 | this.server = null; 84 | 85 | try { 86 | this.server = interp.getVar("SERVER", TCL.GLOBAL_ONLY).toString(); 87 | } 88 | catch (TclException e) { 89 | /* If one doesn't exist, it will just be null. */ 90 | } 91 | 92 | } 93 | 94 | public void cmdProc(Interp interp, TclObject argv[]) 95 | throws TclException { 96 | 97 | try { 98 | CommandLine cl = parseCommandLine(argv); 99 | 100 | if (cl.hasOption("help")) { 101 | new HelpFormatter().printHelp ( 102 | "jmx_close [-?] [-s server]", 103 | "======================================================================", 104 | this.opts, 105 | "======================================================================", 106 | false 107 | ); 108 | 109 | System.out.println("jmx_close closes a connection with a JMX server."); 110 | return; 111 | } 112 | 113 | getDefaults(interp); 114 | 115 | String serverToClose = cl.getOptionValue("server", this.server); 116 | 117 | if (serverToClose == null) { 118 | throw new TclException(interp, "No server specified; please set SERVER variable or use -s option.", TCL.ERROR); 119 | } 120 | 121 | Jmx.getInstance().close(serverToClose); 122 | 123 | if (serverToClose.equals(this.server)) { 124 | // We need this to avoid getting a "cannot unset non-existent variable" 125 | // error, which I could not find a way to suppress nicely. 126 | TclObject space = TclString.newInstance(" "); 127 | interp.setVar("SERVER", space, TCL.GLOBAL_ONLY); 128 | interp.setVar("DOMAIN", space, TCL.GLOBAL_ONLY); 129 | interp.setVar("MBEAN", space, TCL.GLOBAL_ONLY); 130 | interp.setVar("ATTROP", space, TCL.GLOBAL_ONLY); 131 | interp.unsetVar("SERVER", TCL.GLOBAL_ONLY); 132 | interp.unsetVar("DOMAIN", TCL.GLOBAL_ONLY); 133 | interp.unsetVar("MBEAN", TCL.GLOBAL_ONLY); 134 | interp.unsetVar("ATTROP", TCL.GLOBAL_ONLY); 135 | BrowseMode.instance.setServerMenuLevel(); 136 | } 137 | 138 | } 139 | catch(ParseException e) { 140 | throw new TclException(interp, e.getMessage(), 1); 141 | } 142 | catch(RuntimeException e) { 143 | logger.error("Runtime Exception", e); 144 | throw new TclException(interp, "Runtime exception.", 1); 145 | } 146 | } 147 | 148 | private static Logger logger = Logger.getLogger(CloseCmd.class); 149 | 150 | private String server; 151 | private Options opts; 152 | 153 | 154 | } -------------------------------------------------------------------------------- /src/jmxsh/TypeName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.log4j.*; 26 | 27 | /** 28 | The name of a class. 29 | 30 | Automatically handles parsing and printing of nice class names, 31 | including the kludgy representation of array names. 32 | */ 33 | 34 | 35 | 36 | class TypeName { 37 | 38 | static private Logger logger = Logger.getLogger(TypeName.class); 39 | 40 | private int depth; 41 | private String className; 42 | 43 | static public String translateClassName(String className) { 44 | return TypeName.parseClassName(className).toString(); 45 | } 46 | 47 | static public String translateNiceName(String niceName) { 48 | String result = TypeName.fromNiceName(niceName).toClassName(); 49 | logger.debug("Input nicename: " + niceName + ", output class name: " + result); 50 | return result; 51 | } 52 | 53 | /** Parse the java internal class name. */ 54 | static public TypeName parseClassName(String typeString) { 55 | TypeName tn = new TypeName(); 56 | 57 | if (typeString.charAt(0) != '[') { 58 | tn.className = typeString; 59 | return tn; 60 | } 61 | 62 | int pos = 0; 63 | while (typeString.charAt(pos) == '[') { 64 | tn.depth++; 65 | pos++; 66 | } 67 | 68 | switch (typeString.charAt(pos)) { 69 | case 'L': { 70 | int name_begin = pos + 1; 71 | int name_end = typeString.indexOf(';', name_begin); 72 | 73 | tn.className = typeString.substring(name_begin, name_end); 74 | break; 75 | } 76 | case 'Z': 77 | tn.className = "boolean"; 78 | break; 79 | case 'B': 80 | tn.className = "byte"; 81 | break; 82 | case 'C': 83 | tn.className = "char"; 84 | break; 85 | case 'D': 86 | tn.className = "double"; 87 | break; 88 | case 'F': 89 | tn.className = "float"; 90 | break; 91 | case 'I': 92 | tn.className = "int"; 93 | break; 94 | case 'J': 95 | tn.className = "long"; 96 | break; 97 | case 'S': 98 | tn.className = "short"; 99 | break; 100 | } 101 | 102 | return tn; 103 | } 104 | 105 | /** Return the TypeName from an actual class. */ 106 | static public TypeName fromClass(Class klass) { 107 | return parseClassName(klass.getName()); 108 | } 109 | 110 | /** Return the TypeName from an actual class. */ 111 | static public TypeName fromNiceName(String niceName) { 112 | TypeName tn = new TypeName(); 113 | tn.depth = 0; 114 | for (int pos = niceName.indexOf('['); pos != -1; pos = niceName.indexOf('[', pos+1)) { 115 | tn.depth++; 116 | } 117 | if (tn.depth > 0) { 118 | tn.className = niceName.substring(0, niceName.indexOf('[')); 119 | } 120 | else { 121 | tn.className = niceName; 122 | } 123 | return tn; 124 | } 125 | 126 | /** Print a nice string. Remove java.lang. */ 127 | public String toString() { 128 | StringBuilder sb = new StringBuilder(50); 129 | if (className.startsWith("java.lang.")) { 130 | sb.append(className.substring(10)); 131 | } 132 | else { 133 | sb.append(className); 134 | } 135 | for (int i=0; i 1) { 122 | attribute = args[0]; 123 | newvalue = argv[argv.length-args.length+1]; 124 | } 125 | else { 126 | attribute = attrop; 127 | newvalue = argv[argv.length-args.length]; 128 | } 129 | 130 | if (server == null) { 131 | throw new TclException(interp, "No server specified; please set SERVER variable or use -s option.", TCL.ERROR); 132 | } 133 | 134 | if (mbean == null) { 135 | throw new TclException(interp, "No mbean specified; please set MBEAN variable or use -m option.", TCL.ERROR); 136 | } 137 | 138 | if (attribute == null) { 139 | throw new TclException(interp, "No attribute specified; please set ATTROP variable or add it to the command line.", TCL.ERROR); 140 | } 141 | 142 | if (newvalue == null) { 143 | throw new TclException(interp, "No new value provided for the attribute.", TCL.ERROR); 144 | } 145 | 146 | Jmx.getInstance().setAttribute(server, mbean, attribute, newvalue); 147 | } 148 | catch(ParseException e) { 149 | throw new TclException(interp, e.getMessage(), 1); 150 | } 151 | catch(RuntimeException e) { 152 | throw new TclException(interp, e.getMessage(), 1); 153 | } 154 | } 155 | 156 | private String server; 157 | //private String domain; 158 | private String mbean; 159 | private String attrop; 160 | 161 | //private static Logger logger = Logger.getLogger(SetCmd.class); 162 | private Options opts; 163 | } 164 | -------------------------------------------------------------------------------- /src/jmxsh/GetCmd.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.commons.cli.*; 26 | //import org.apache.log4j.Logger; 27 | import tcl.lang.*; 28 | 29 | class GetCmd implements Command { 30 | 31 | private final static GetCmd instance = new GetCmd(); 32 | //private final static Logger logger = Logger.getLogger(GetCmd.class); 33 | 34 | private String server; 35 | //private String domain; 36 | private String mbean; 37 | private String attrop; 38 | private Options opts; 39 | 40 | static GetCmd getInstance() { 41 | return instance; 42 | } 43 | 44 | private GetCmd() { 45 | this.opts = new Options(); 46 | 47 | this.opts.addOption( 48 | OptionBuilder.withLongOpt("server") 49 | .withDescription("Server containing mbean.") 50 | .withArgName("SERVER") 51 | .hasArg() 52 | .create("s") 53 | ); 54 | 55 | this.opts.addOption( 56 | OptionBuilder.withLongOpt("mbean") 57 | .withDescription("MBean containing attribute.") 58 | .withArgName("MBEAN") 59 | .hasArg() 60 | .create("m") 61 | ); 62 | 63 | this.opts.addOption( 64 | OptionBuilder.withLongOpt("noconvert") 65 | .withDescription("Do not auto-convert the result to a Tcl string, instead create a java object reference.") 66 | .hasArg(false) 67 | .create("n") 68 | ); 69 | 70 | this.opts.addOption( 71 | OptionBuilder.withLongOpt("help") 72 | .withDescription("Display usage help.") 73 | .hasArg(false) 74 | .create("?") 75 | ); 76 | } 77 | 78 | private CommandLine parseCommandLine(TclObject argv[]) 79 | throws ParseException { 80 | 81 | String[] args = new String[argv.length - 1]; 82 | 83 | for(int i = 0; i < argv.length - 1; i++) 84 | args[i] = argv[i + 1].toString(); 85 | 86 | CommandLine cl = (new PosixParser()).parse(this.opts, args); 87 | return cl; 88 | } 89 | 90 | private void getDefaults(Interp interp) { 91 | this.server = null; 92 | //domain = null; 93 | this.mbean = null; 94 | this.attrop = null; 95 | 96 | try { 97 | this.server = interp.getVar("SERVER", TCL.GLOBAL_ONLY).toString(); 98 | //domain = interp.getVar("DOMAIN", TCL.GLOBAL_ONLY).toString(); 99 | this.mbean = interp.getVar("MBEAN", TCL.GLOBAL_ONLY).toString(); 100 | this.attrop = interp.getVar("ATTROP", TCL.GLOBAL_ONLY).toString(); 101 | } 102 | catch (TclException e) { 103 | /* If one doesn't exist, it will just be null. */ 104 | } 105 | 106 | } 107 | 108 | public void cmdProc(Interp interp, TclObject argv[]) 109 | throws TclException { 110 | 111 | try { 112 | CommandLine cl = parseCommandLine(argv); 113 | String args[] = cl.getArgs(); 114 | String attribute = null; 115 | 116 | if (cl.hasOption("help")) { 117 | new HelpFormatter().printHelp ( 118 | "jmx_get [-?] [-n] [-s server] [-m mbean] [ATTRIBUTE]", 119 | "======================================================================", 120 | this.opts, 121 | "======================================================================", 122 | false 123 | ); 124 | System.out.println("jmx_get retrieves the current value of the given attribute."); 125 | System.out.println("If you do not specify server, mbean, or ATTRIBUTE, then the"); 126 | System.out.println("values in the global variables SERVER, MBEAN, and ATTROP,"); 127 | System.out.println("respectively, will be used."); 128 | System.out.println(""); 129 | System.out.println("If you specify -n, then the return will be a Java/Tcl java"); 130 | System.out.println("object reference. See the Java/Tcl documentation on the"); 131 | System.out.println("internet for more details."); 132 | return; 133 | } 134 | 135 | getDefaults(interp); 136 | 137 | this.server = cl.getOptionValue("server", this.server); 138 | this.mbean = cl.getOptionValue("mbean", this.mbean); 139 | this.attrop = cl.getOptionValue("attrop", this.attrop); 140 | 141 | if (args.length > 0) { 142 | attribute = args[0]; 143 | } 144 | else { 145 | attribute = this.attrop; 146 | } 147 | 148 | if (this.server == null) { 149 | throw new TclException(interp, "No server specified; please set SERVER variable or use -s option.", TCL.ERROR); 150 | } 151 | 152 | if (this.mbean == null) { 153 | throw new TclException(interp, "No mbean specified; please set MBEAN variable or use -m option.", TCL.ERROR); 154 | } 155 | 156 | if (attribute == null) { 157 | throw new TclException(interp, "No attribute specified; please set ATTROP variable or add it to the command line.", TCL.ERROR); 158 | } 159 | 160 | if (cl.hasOption("noconvert")) { 161 | String result = Utils.java2tcl(Jmx.getInstance().getAttribute(this.server, this.mbean, attribute)); 162 | interp.setResult(result); 163 | } else { 164 | interp.setResult(Jmx.getInstance().getAttribute(this.server, this.mbean, attribute).toString()); 165 | } 166 | } 167 | catch(ParseException e) { 168 | throw new TclException(interp, e.getMessage(), 1); 169 | } 170 | catch(RuntimeException e) { 171 | throw new TclException(interp, "Cannot convert result to a string.", 1); 172 | } 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /src/jmxsh/ShellMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.log4j.*; 26 | import tcl.lang.*; 27 | 28 | /** 29 | Implementation of shell mode. 30 | 31 | Interpret user input as Tcl commands. Maintain command line history. 32 | */ 33 | class ShellMode extends Mode { 34 | 35 | static private Logger logger = Logger.getLogger(ShellMode.class); 36 | static ShellMode instance = new ShellMode(); 37 | 38 | private StringBuilder stringBuilder; 39 | 40 | private ShellMode() { 41 | stringBuilder = new StringBuilder(100); 42 | } 43 | 44 | String getPrePromptDisplay() { 45 | return ""; 46 | } 47 | 48 | String getPrompt() { 49 | if (stringBuilder.length() == 0) { 50 | return "%"; 51 | } 52 | 53 | return ">>"; 54 | } 55 | 56 | String handleInput(String input) { 57 | 58 | stringBuilder.append(input); 59 | 60 | final String command = stringBuilder.toString(); 61 | 62 | logger.debug(command); 63 | 64 | if (!Interp.commandComplete(command)) { 65 | return null; 66 | } 67 | 68 | stringBuilder.setLength(0); 69 | 70 | TclEvent event = 71 | new TclEvent() { 72 | public int processEvent(int flags) { 73 | Interp interp = JInterp.instance; 74 | 75 | TclObject cmdObj = TclString.newInstance(command); 76 | cmdObj.preserve(); 77 | 78 | try { 79 | interp.recordAndEval(cmdObj, 0); 80 | } 81 | catch (TclException e) { 82 | switch (e.getCompletionCode()) { 83 | case TCL.ERROR: 84 | case TCL.CONTINUE: 85 | String message = interp.getResult().toString(); 86 | if (message.length() == 0) { 87 | message = e.getMessage(); 88 | } 89 | System.out.println("Error: " + message); 90 | break; 91 | case TCL.BREAK: 92 | System.out.println("Error: invoked \"break\" outside of a loop."); 93 | break; 94 | default: 95 | System.out.println("Error: command returned bad completion code - " + e.getCompletionCode()); 96 | } 97 | 98 | } 99 | finally { 100 | cmdObj.release(); 101 | } 102 | 103 | System.out.println(interp.getResult().toString()); 104 | return 1; 105 | } 106 | }; 107 | 108 | JInterp.instance.getNotifier().queueEvent(event, TCL.QUEUE_TAIL); 109 | event.sync(); 110 | 111 | return command; 112 | } 113 | 114 | void displayHelp() { 115 | StringBuilder sb = new StringBuilder(1000); 116 | 117 | sb.append("=====================================================\n"); 118 | sb.append(" Shell Mode Help\n"); 119 | sb.append("\n"); 120 | sb.append("This mode is a tcl shell. Several JMX-related commands\n"); 121 | sb.append("have been added:\n"); 122 | sb.append("\n"); 123 | sb.append("o jmx_connect - connect to a JMX server\n"); 124 | sb.append("o jmx_close - close a connection\n"); 125 | sb.append("o jmx_set - change a JMX attribute\n"); 126 | sb.append("o jmx_get - read a JMX attribute\n"); 127 | sb.append("o jmx_invoke - invoke a JMX operation\n"); 128 | sb.append("o jmx_list - list attribs w/regex (NOT TESTED)\n"); 129 | sb.append("\n"); 130 | sb.append("To get further help on each command, invoke it with the\n"); 131 | sb.append("-? option.\n"); 132 | sb.append("\n"); 133 | sb.append("The jmx_get and jmx_invoke commands return data from the\n"); 134 | sb.append("remote JMX server. This data will be automatically converted\n"); 135 | sb.append("to a String when the result is created. If the data being\n"); 136 | sb.append("returned is more complex, then the -n or --noconvert option\n"); 137 | sb.append("should be used. This will cause jmxsh to create and return\n"); 138 | sb.append("a Jacl java object reference. This string (usually of the\n"); 139 | sb.append("form 'java0x1' or similar) can be used with the various Jacl\n"); 140 | sb.append("java:: commands to obtain full access to the Java object.\n"); 141 | sb.append("\n"); 142 | sb.append("Most of the commands take -s SERVER and -m MBEAN arguments\n"); 143 | sb.append("to determine where they will take effect. Rather than\n"); 144 | sb.append("specifying these values each time, the commands will also\n"); 145 | sb.append("attempt to read the global variables SERVER and MBEAN\n"); 146 | sb.append("and use them if no command-line option was specified.\n"); 147 | sb.append("\n"); 148 | sb.append("This is intended to work hand-in-hand with the Browse\n"); 149 | sb.append("Mode: As one browses through the JMX namespace, these\n"); 150 | sb.append("global variables will be constantly updated. Thus, one\n"); 151 | sb.append("can flip back to shell mode and enter commands, flip\n"); 152 | sb.append("back to browser modes and navigate, then flip back\n"); 153 | sb.append("to shell mode, etc.\n"); 154 | sb.append("\n"); 155 | sb.append("Incidentally, to flip to Browse mode, just hit enter\n"); 156 | sb.append("on an empty line. You will know you have left Shell\n"); 157 | sb.append("Mode when you see a Browse-style prompt (usually a\n"); 158 | sb.append("phrase followed by a colon, such as 'Select a domain:'\n"); 159 | sb.append("=====================================================\n"); 160 | 161 | System.out.println(sb.toString()); 162 | } 163 | 164 | } 165 | 166 | -------------------------------------------------------------------------------- /src/jmxsh/ConnectCmd.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | /** 26 | * ConnectCmd.java 27 | * 28 | * Tcl Command to connect via JMX to a running process. 29 | * 30 | * @author robspassky 31 | */ 32 | 33 | import org.apache.commons.cli.CommandLine; 34 | import org.apache.commons.cli.HelpFormatter; 35 | import org.apache.commons.cli.OptionBuilder; 36 | import org.apache.commons.cli.Options; 37 | import org.apache.commons.cli.ParseException; 38 | import org.apache.commons.cli.PosixParser; 39 | import org.apache.log4j.Logger; 40 | 41 | import tcl.lang.Command; 42 | import tcl.lang.Interp; 43 | import tcl.lang.TclException; 44 | import tcl.lang.TclObject; 45 | 46 | 47 | 48 | class ConnectCmd implements Command { 49 | 50 | private final static ConnectCmd instance = new ConnectCmd(); 51 | 52 | static ConnectCmd getInstance() { return instance; } 53 | 54 | /** Initialize private variables. Setup the command-line options. */ 55 | private ConnectCmd() { 56 | this.opts = new Options(); 57 | 58 | this.opts.addOption( 59 | OptionBuilder.withLongOpt("server") 60 | .withDescription("Server to connect to (in the form of an URL).") 61 | .withArgName("SERVER") 62 | .hasArg() 63 | .create("s") 64 | ); 65 | 66 | this.opts.addOption( 67 | OptionBuilder.withLongOpt("host") 68 | .withDescription("Host to connect to.") 69 | .withArgName("HOST") 70 | .hasArg() 71 | .create("h") 72 | ); 73 | 74 | this.opts.addOption( 75 | OptionBuilder.withLongOpt("port") 76 | .withDescription("Port to connect to.") 77 | .withArgName("PORT") 78 | .hasArg() 79 | .create("p") 80 | ); 81 | 82 | this.opts.addOption( 83 | OptionBuilder.withLongOpt("url_path") 84 | .withDescription("Path portion of the JMX Service URL.") 85 | .withArgName("PATH") 86 | .hasArg() 87 | .create("T") 88 | ); 89 | 90 | this.opts.addOption( 91 | OptionBuilder.withLongOpt("user") 92 | .withArgName("USER") 93 | .hasArg() 94 | .withDescription("Connect with this username.") 95 | .create("U") 96 | ); 97 | 98 | this.opts.addOption( 99 | OptionBuilder.withLongOpt("password") 100 | .withArgName("PASSWORD") 101 | .hasArg() 102 | .withDescription("Connect with this password.") 103 | .create("P") 104 | ); 105 | 106 | this.opts.addOption( 107 | OptionBuilder.withLongOpt("help") 108 | .withDescription("Display usage help.") 109 | .hasArg(false) 110 | .create("?") 111 | ); 112 | 113 | this.opts.addOption( 114 | OptionBuilder.withLongOpt("protocol") 115 | .withDescription("Choose a connection protocol (rmi|jmxmp), default rmi.") 116 | .hasArg(true) 117 | .withArgName("PROTOCOL") 118 | .create("R") 119 | ); 120 | } 121 | 122 | private CommandLine parseCommandLine(TclObject argv[]) 123 | throws ParseException { 124 | 125 | String[] args = new String[argv.length - 1]; 126 | 127 | for(int i = 0; i < argv.length - 1; i++) 128 | args[i] = argv[i + 1].toString(); 129 | 130 | CommandLine cl = (new PosixParser()).parse(this.opts, args); 131 | return cl; 132 | } 133 | 134 | private void connect(CommandLine commandLine) { 135 | String serverUrl = commandLine.getOptionValue("server"); 136 | String host = commandLine.getOptionValue("host"); 137 | String protocol = commandLine.getOptionValue("protocol", "rmi"); 138 | String path = commandLine.getOptionValue("url_path"); 139 | String user = commandLine.getOptionValue("user"); 140 | String password = commandLine.getOptionValue("password"); 141 | int port = -1; 142 | if (commandLine.hasOption("port")) { 143 | port = Integer.parseInt(commandLine.getOptionValue("port")); 144 | } 145 | 146 | if (Main.interactive) { 147 | Readline rl = Readline.getInstance(); 148 | 149 | if (user != null && password == null) { 150 | password = rl.readline("Password: ", '*'); 151 | } 152 | } 153 | 154 | if (serverUrl != null) { 155 | Jmx.getInstance().connect(serverUrl, user, password); 156 | } 157 | else { 158 | Jmx.getInstance().connect(host, port, protocol, path, user, password); 159 | } 160 | } 161 | 162 | 163 | public void cmdProc(Interp interp, TclObject argv[]) 164 | throws TclException { 165 | 166 | try { 167 | CommandLine cl = parseCommandLine(argv); 168 | 169 | if (cl.hasOption("help")) { 170 | new HelpFormatter().printHelp ( 171 | "jmx_connect ", 172 | "======================================================================", 173 | this.opts, 174 | "======================================================================", 175 | true 176 | ); 177 | 178 | System.out.println("jmx_connect establishes a connection to a JMX server."); 179 | return; 180 | } 181 | 182 | this.connect(cl); 183 | } 184 | catch (ParseException e) { 185 | throw new TclException(interp, e.getMessage(), 1); 186 | } 187 | catch (RuntimeException e) { 188 | logger.error("Runtime Exception", e); 189 | throw new TclException(interp, "Runtime exception.", 1); 190 | } 191 | } 192 | 193 | private static Logger logger = Logger.getLogger(ConnectCmd.class); 194 | private Options opts; 195 | 196 | } 197 | -------------------------------------------------------------------------------- /src/jmxsh/InvokeCmd.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.log4j.Logger; 26 | import org.apache.commons.cli.*; 27 | import tcl.lang.*; 28 | 29 | /** Retrieve the value of an mbean's attribute. */ 30 | class InvokeCmd implements Command { 31 | 32 | private final static InvokeCmd instance = new InvokeCmd(); 33 | 34 | static InvokeCmd getInstance() { return instance; } 35 | 36 | /** Initialize private variables. Setup the command-line options. */ 37 | private InvokeCmd() { 38 | this.opts = new Options(); 39 | 40 | this.opts.addOption( 41 | OptionBuilder.withLongOpt("server") 42 | .withDescription("Server containing mbean.") 43 | .withArgName("SERVER") 44 | .hasArg() 45 | .create("s") 46 | ); 47 | 48 | this.opts.addOption( 49 | OptionBuilder.withLongOpt("mbean") 50 | .withDescription("MBean containing attribute.") 51 | .withArgName("MBEAN") 52 | .hasArg() 53 | .create("m") 54 | ); 55 | 56 | this.opts.addOption( 57 | OptionBuilder.withLongOpt("noconvert") 58 | .withDescription("Do not auto-convert the result to a Tcl string, instead create a java object reference.") 59 | .hasArg(false) 60 | .create("n") 61 | ); 62 | 63 | this.opts.addOption( 64 | OptionBuilder.withLongOpt("help") 65 | .withDescription("Display usage help.") 66 | .hasArg(false) 67 | .create("?") 68 | ); 69 | } 70 | 71 | private CommandLine parseCommandLine(TclObject argv[]) 72 | throws ParseException { 73 | 74 | String[] args = new String[argv.length - 1]; 75 | 76 | for(int i = 0; i < argv.length - 1; i++) 77 | args[i] = argv[i + 1].toString(); 78 | 79 | CommandLine cl = (new PosixParser()).parse(this.opts, args); 80 | return cl; 81 | } 82 | 83 | private void getDefaults(Interp interp) { 84 | this.server = null; 85 | //this.domain = null; 86 | this.mbean = null; 87 | this.attrop = null; 88 | 89 | try { 90 | this.server = interp.getVar("SERVER", TCL.GLOBAL_ONLY).toString(); 91 | //this.domain = interp.getVar("DOMAIN", TCL.GLOBAL_ONLY).toString(); 92 | this.mbean = interp.getVar("MBEAN", TCL.GLOBAL_ONLY).toString(); 93 | this.attrop = interp.getVar("ATTROP", TCL.GLOBAL_ONLY); 94 | } 95 | catch (TclException e) { 96 | /* If one doesn't exist, it will just be null. */ 97 | } 98 | 99 | } 100 | 101 | public void cmdProc(Interp interp, TclObject argv[]) 102 | throws TclException { 103 | 104 | try { 105 | CommandLine cl = parseCommandLine(argv); 106 | String args[] = cl.getArgs(); 107 | String opname = null; 108 | TclObject opTclObj = null; 109 | Object[] params = null; 110 | String[] signature = null; 111 | 112 | if (cl.hasOption("help")) { 113 | new HelpFormatter().printHelp ( 114 | "jmx_invoke [-?] [-n] [-s server] [-m mbean] [OPERATION] [ARGS]", 115 | "======================================================================", 116 | this.opts, 117 | "======================================================================", 118 | false 119 | ); 120 | 121 | System.out.println("jmx_invoke executes an operation on a remote mbean, returning the result"); 122 | System.out.println("(if any)."); 123 | System.out.println(""); 124 | System.out.println("If you specify -n, then the return will be a Java/Tcl java"); 125 | System.out.println("object reference. See the Java/Tcl documentation on the"); 126 | System.out.println("internet for more details."); 127 | System.out.println(""); 128 | System.out.println("If there are multiple operations with the same name in the mbean, you can"); 129 | System.out.println("disambiguate by specifying 'operation' as a tcl list of the operation name"); 130 | System.out.println("and the java types of its parameters."); 131 | System.out.println(" e.g., "); 132 | System.out.println(" jmx_invoke -m $MBEAN [hello java.lang.Integer java.lang.String] arg1 arg2"); 133 | System.out.println(" jmx_invoke -m $MBEAN [hello java.lang.String java.lang.String] arg1 arg2"); 134 | System.out.println(" Invoke two different operations, both named 'hello'."); 135 | return; 136 | } 137 | 138 | getDefaults(interp); 139 | 140 | this.server = cl.getOptionValue("server", this.server); 141 | this.mbean = cl.getOptionValue("mbean", this.mbean); 142 | 143 | logger.debug("argv length:" + argv.length); 144 | logger.debug("args length:" + args.length); 145 | logger.debug("offset :" + args.length); 146 | 147 | if (this.server == null) { 148 | throw new TclException(interp, "No server specified; please set SERVER variable or use -s option.", TCL.ERROR); 149 | } 150 | 151 | if (this.mbean == null) { 152 | throw new TclException(interp, "No mbean specified; please set MBEAN variable or use -m option.", TCL.ERROR); 153 | } 154 | 155 | int offset = argv.length - args.length; 156 | if (args.length > 0) { 157 | opTclObj = argv[offset]; 158 | offset++; 159 | } 160 | else { 161 | opTclObj = this.attrop; 162 | } 163 | 164 | if (opTclObj == null) { 165 | throw new TclException(interp, "No operation specified; please set ATTROP variable or add it to the command line.", TCL.ERROR); 166 | } 167 | 168 | //int num_params = argv.length - offset; 169 | 170 | opname = TclList.index(interp, opTclObj, 0).toString(); 171 | if (TclList.getLength(interp, opTclObj) > 1) { 172 | signature = new String[TclList.getLength(interp, opTclObj)-1]; 173 | for (int i=1; i connectors; 46 | 47 | private Jmx() { 48 | this.connectors = new HashMap(); 49 | } 50 | 51 | 52 | public String[] getServers() { 53 | return this.connectors.keySet().toArray(EMPTY_STRING_ARRAY); 54 | } 55 | 56 | 57 | public String[] getDomains(String server, String regex) { 58 | try { 59 | Vector result = new Vector(); 60 | String[] domains = getMBSC(server).getDomains(); 61 | if (domains == null) { 62 | domains = EMPTY_STRING_ARRAY; 63 | } 64 | for (String domain : domains) { 65 | if (regex.length() == 0 || domain.matches(regex)) { 66 | result.add(domain); 67 | } 68 | } 69 | return result.toArray(EMPTY_STRING_ARRAY); 70 | } 71 | catch (IOException e) { 72 | logger.error("Error getting domains.", e); 73 | throw new IllegalArgumentException("Unable to get domains for " + server + ".", e); 74 | } 75 | } 76 | 77 | 78 | public String[] getDomains(String server) { 79 | return getDomains(server, ".*"); 80 | } 81 | 82 | public void close(String server) { 83 | try { 84 | this.connectors.get(server).close(); 85 | this.connectors.remove(server); 86 | JInterp.unsetGlobal("SERVERS", server); 87 | } 88 | catch (IOException e) { 89 | logger.error("Error closing connection.", e); 90 | throw new IllegalArgumentException("Error closing connection.", e); 91 | } 92 | } 93 | 94 | 95 | public String[] getMBeans(String server, String domain, String regex) { 96 | try { 97 | ObjectName wildcardQuery = getObjectName(domain + ":*"); 98 | Set mbeans = getMBSC(server).queryNames(wildcardQuery, null); 99 | Vector result = new Vector(); 100 | for (Object mbean : mbeans) { 101 | String name = ((ObjectName) mbean).toString(); 102 | if (regex.length() == 0 || name.matches(regex)) { 103 | result.add(name); 104 | } 105 | } 106 | return result.toArray(EMPTY_STRING_ARRAY); 107 | } 108 | catch (IOException e) { 109 | logger.error("Error getting mbeans.", e); 110 | throw new IllegalArgumentException("Error getting mbeans."); 111 | } 112 | } 113 | 114 | public String[] getMBeans(String server, String domain) { 115 | return getMBeans(server, domain, ".*"); 116 | } 117 | 118 | public MBeanOperationInfo getOperationInfo(String server, String mbean, String opname) { 119 | MBeanOperationInfo[] operations = getMBI(server, mbean).getOperations(); 120 | for (MBeanOperationInfo operation : operations) { 121 | if (operation.getName().equals(opname)) { 122 | return operation; 123 | } 124 | } 125 | return null; 126 | } 127 | 128 | public MBeanOperationInfo[] getOperations(String server, String mbean) { 129 | return getMBI(server, mbean).getOperations(); 130 | } 131 | 132 | public String[] getSignature(String server, String mbean, String opname) { 133 | MBeanOperationInfo info = getOperationInfo(server, mbean, opname); 134 | 135 | if (info == null) { 136 | throw new IllegalArgumentException("Could not find operation " + opname); 137 | } 138 | 139 | MBeanParameterInfo[] params = info.getSignature(); 140 | String[] signature = new String[params.length]; 141 | for (int i=0; i credentials = null; 369 | JMXConnector connector = this.connectors.get(url.toString()); 370 | 371 | if (connector != null) { 372 | if (Main.interactive) { 373 | System.out.println("Already connected."); 374 | } 375 | return; 376 | } 377 | 378 | try { 379 | if (user != null) { 380 | credentials = new HashMap(); 381 | credentials.put(JMXConnector.CREDENTIALS, new String[] { user, password }); 382 | } 383 | 384 | String urlStr = url.toString(); 385 | connector = JMXConnectorFactory.connect(url, credentials); 386 | this.connectors.put(urlStr, connector); 387 | JInterp.setGlobal("SERVER", urlStr); 388 | JInterp.setGlobal("SERVERS", urlStr, urlStr); 389 | BrowseMode.instance.setDomainMenuLevel(); 390 | if (Main.interactive) { 391 | System.out.println("Connected to " + urlStr + "."); 392 | } 393 | } 394 | catch (SecurityException e) { 395 | logger.error("Connection error.", e); 396 | throw new IllegalArgumentException("Authentication error: " + e.getMessage()); 397 | } 398 | catch (IOException e) { 399 | logger.error("Connection error.", e); 400 | try { 401 | if (e.getCause().getClass() == Class.forName("javax.naming.ConfigurationException")) { 402 | throw new IllegalArgumentException("Host name not found."); 403 | } 404 | if (e.getCause().getClass() == Class.forName("javax.naming.ServiceUnavailableException")) { 405 | throw new IllegalArgumentException("Nothing is listening on that port, or it's firewalled off."); 406 | } 407 | if (e.getCause().getClass() == Class.forName("javax.naming.CommunicationException")) { 408 | throw new IllegalArgumentException("Timed out. Probably some non-JMX process is listening on it."); 409 | } 410 | if (e.getCause().getClass() == Class.forName("javax.net.ssl.SSLHandshakeException")) { 411 | throw new IllegalStateException("Host is using SSL, set the appropriate System Properties to connect to it."); 412 | } 413 | if (e.getCause().getClass() == Class.forName("java.net.ConnectException")) { 414 | throw new IllegalStateException("Connection refused."); 415 | } 416 | } 417 | 418 | catch (java.lang.ClassNotFoundException ee) { 419 | // Do nothing, fall through to default error message. 420 | } 421 | 422 | throw new IllegalStateException("Network error, see log."); 423 | } 424 | } 425 | 426 | 427 | } 428 | -------------------------------------------------------------------------------- /src/jmxsh/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | import org.apache.commons.cli.*; 26 | import org.apache.log4j.*; 27 | import java.io.IOException; 28 | import java.util.Date; 29 | 30 | 31 | /** 32 | Wrapper class for main() function of jmxsh. 33 | 34 | This class must be public because it is not invoked directly by 35 | java. Instead, the One-Jar code is executed by the java 36 | command-line, which then calls this main() function. 37 | */ 38 | public final class Main { 39 | 40 | // Change this version information before a release. 41 | static final String VERSION = "1.0"; 42 | static final long EPOCH_DATE = 1201018992L; // Get with date +"%s" 43 | static final String CODENAME = "ERETRIA"; 44 | static final Date DATE = new Date(EPOCH_DATE*1000); 45 | 46 | static final protected Logger logger = Logger.getLogger(Main.class); 47 | static boolean interactive = false; 48 | 49 | protected boolean historyEnabled; 50 | protected CommandLine commandLine; 51 | 52 | private Options makeCommandLineOptions() { 53 | 54 | Options opts = new Options(); 55 | 56 | opts.addOption( 57 | OptionBuilder.withLongOpt("server") 58 | .withDescription("JMX Service URL of remote JMX service.") 59 | .withArgName("SERVER") 60 | .hasArg() 61 | .create("s") 62 | ); 63 | 64 | opts.addOption( 65 | OptionBuilder.withLongOpt("host") 66 | .withDescription("Hostname or IP address of remote JMX service.") 67 | .withArgName("HOST") 68 | .hasArg() 69 | .create("h") 70 | ); 71 | 72 | opts.addOption( 73 | OptionBuilder.withLongOpt("port") 74 | .withDescription("Port of remote JMX service.") 75 | .withArgName("PORT") 76 | .hasArg() 77 | .create("p") 78 | ); 79 | 80 | opts.addOption( 81 | OptionBuilder.withLongOpt("url_path") 82 | .withDescription("Path portion of the JMX Service URL.") 83 | .withArgName("PATH") 84 | .hasArg() 85 | .create("T") 86 | ); 87 | 88 | opts.addOption( 89 | OptionBuilder.withLongOpt("user") 90 | .withArgName("USER") 91 | .hasArg() 92 | .withDescription("Connect with this username.") 93 | .create("U") 94 | ); 95 | 96 | opts.addOption( 97 | OptionBuilder.withLongOpt("password") 98 | .withArgName("PASSWORD") 99 | .hasArg() 100 | .withDescription("Connect with this password.") 101 | .create("P") 102 | ); 103 | 104 | opts.addOption( 105 | OptionBuilder.withLongOpt("debug") 106 | .withDescription("Verbose logging.") 107 | .hasArg(false) 108 | .create("d") 109 | ); 110 | 111 | opts.addOption( 112 | OptionBuilder.withLongOpt("logfile") 113 | .withDescription("Log information to this file.") 114 | .withArgName("LOGFILE") 115 | .hasArg() 116 | .create("l") 117 | ); 118 | 119 | opts.addOption( 120 | OptionBuilder.withLongOpt("version") 121 | .hasArg(false) 122 | .withDescription("Show version information.") 123 | .create("v") 124 | ); 125 | 126 | opts.addOption( 127 | OptionBuilder.withLongOpt("help") 128 | .withDescription("Display usage help.") 129 | .hasArg(false) 130 | .create("?") 131 | ); 132 | 133 | opts.addOption( 134 | OptionBuilder.withLongOpt("protocol") 135 | .withDescription("Choose a connection protocol (rmi|jmxmp), default rmi.") 136 | .hasArg(true) 137 | .withArgName("PROTOCOL") 138 | .create("R") 139 | ); 140 | 141 | opts.addOption( 142 | OptionBuilder.withLongOpt("include") 143 | .withDescription("Source this file. May be specified multiple times. [N.B. Do not make this the last option, because of a bug in CLI parsing library.]") 144 | .withArgName("FILE") 145 | .hasArg() 146 | .hasArgs() 147 | .create("i") 148 | ); 149 | 150 | opts.addOption( 151 | OptionBuilder.withLongOpt("interactive") 152 | .withDescription("Always go into interactive mode, even if executing a script.") 153 | .hasArg(false) 154 | .create("I") 155 | ); 156 | 157 | opts.addOption( 158 | OptionBuilder.withLongOpt("browse") 159 | .withDescription("Start interactive session in browser mode.") 160 | .hasArg(false) 161 | .create("b") 162 | ); 163 | 164 | opts.addOption( 165 | OptionBuilder.withLongOpt("nohistory") 166 | .withDescription("Do not save history.") 167 | .hasArg(false) 168 | .create("n") 169 | ); 170 | 171 | opts.addOption( 172 | OptionBuilder.withLongOpt("historyfile") 173 | .withDescription("Use this file to save history (default $HOME/.jmxsh_history).") 174 | .hasArg(true) 175 | .withArgName("HISTORYFILE") 176 | .create("H") 177 | ); 178 | 179 | return opts; 180 | } 181 | 182 | 183 | private void showVersion() { 184 | 185 | System.out.println("jmxsh " + Main.VERSION + " (" + Main.CODENAME + "), " + Main.DATE + ". #69108"); 186 | System.out.println(""); 187 | System.out.println("Brought to you by the letter 'X', and the number 25."); 188 | System.out.println(""); 189 | System.out.println("\"There was a point to this story, but it has temporarily "); 190 | System.out.println(" escaped the chronicler's mind.\""); 191 | System.out.println(" -- Douglas Adams"); 192 | 193 | } 194 | 195 | 196 | private void showUsage(Options opts) { 197 | 198 | System.out.println("Start a command-line interface to a JMX service provider."); 199 | System.out.println("The first non-option argument, if present, is the"); 200 | System.out.println("file name of a script to execute. Any remaining arguments"); 201 | System.out.println("are passed 'argv' elements to the script."); 202 | System.out.println(""); 203 | System.out.println("If no script file is specified, or if the -I option was specified,"); 204 | System.out.println("then an interactive session will be started."); 205 | System.out.println(""); 206 | 207 | new HelpFormatter().printHelp("java -jar jmxsh.jar [OPTIONS] -h host -p port [FILENAME ARGS]", 208 | "=========================================================================", 209 | opts, 210 | "=========================================================================", 211 | false); 212 | 213 | } 214 | 215 | 216 | private void connect() { 217 | String server = commandLine.getOptionValue("server"); 218 | String host = commandLine.getOptionValue("host"); 219 | String protocol = commandLine.getOptionValue("protocol", "rmi"); 220 | String path = commandLine.getOptionValue("url_path"); 221 | String user = commandLine.getOptionValue("user"); 222 | String password = commandLine.getOptionValue("password"); 223 | int port = Integer.parseInt(commandLine.getOptionValue("port")); 224 | 225 | try { 226 | if (user == null && password != null) { 227 | user = Readline.getInstance().readline("User: "); 228 | } 229 | 230 | if (password == null && user != null) { 231 | password = Readline.getInstance().readline("Password: ", '*'); 232 | } 233 | 234 | if (server == null) { 235 | Jmx.getInstance().connect(host, port, protocol, path, user, password); 236 | } 237 | else { 238 | Jmx.getInstance().connect(server, user, password); 239 | } 240 | BrowseMode.instance.setDomainMenuLevel(); 241 | } 242 | catch (RuntimeException e) { 243 | System.err.println("Failed to connect to " + host + ", port " + port + ": " + e.getMessage()); 244 | System.exit(1); 245 | } 246 | } 247 | 248 | 249 | /** 250 | Entry-point when jmxsh is executed. 251 | 252 | Parses command line options, evaluates tcl files, then goes to 253 | interactive mode if desired. 254 | 255 | @param args Command line arguments passed to jmxsh. 256 | */ 257 | public static void main(String[] args) { 258 | 259 | Main mainObj = new Main(); 260 | 261 | try { 262 | mainObj.run(args); 263 | } 264 | catch (RuntimeException e) { 265 | System.err.println("Error: " + e.getMessage()); 266 | logger.fatal("Runtime Exception received in main(): " + e.getMessage(), e); 267 | System.exit(1); 268 | } 269 | 270 | System.exit(0); 271 | 272 | } 273 | 274 | void run(String[] args) { 275 | 276 | // 1. Parse the command line options. 277 | 278 | Options opts = makeCommandLineOptions(); 279 | 280 | try { 281 | commandLine = new PosixParser().parse(opts, args, true); 282 | } 283 | catch (ParseException e) { 284 | showUsage(opts); 285 | System.err.println("Usage error: " + e.getMessage()); 286 | System.exit(1); 287 | } 288 | 289 | String logfile = commandLine.getOptionValue("logfile", "/dev/null"); 290 | try { 291 | BasicConfigurator.configure(new FileAppender(new PatternLayout("%r [%t] %-5p %c %x - %m%n"), logfile)); 292 | } 293 | catch (IOException e) { 294 | System.err.println("Unable to open logfile: " + e.getMessage()); 295 | System.exit(1); 296 | } 297 | 298 | if (commandLine.hasOption("help")) { 299 | showUsage(opts); 300 | System.exit(0); 301 | } 302 | 303 | if (commandLine.hasOption("version")) { 304 | showVersion(); 305 | System.exit(0); 306 | } 307 | 308 | if (commandLine.hasOption("debug")) { 309 | Logger.getRootLogger().setLevel(Level.ALL); 310 | } 311 | 312 | // 2. Make any specified JMX connections. 313 | 314 | if (commandLine.hasOption("host") && commandLine.hasOption("port")) { 315 | connect(); 316 | } 317 | 318 | // 4. Source in any include files. 319 | 320 | String[] includeFiles = commandLine.getOptionValues("include"); 321 | if (includeFiles != null) { 322 | for (String filename: commandLine.getOptionValues("include")) { 323 | logger.debug("Including " + filename); 324 | JInterp.evaluateFile(filename); 325 | } 326 | } 327 | 328 | // 5a. If script file name provided, run it and exit. 329 | 330 | String[] scriptArgs = commandLine.getArgs(); 331 | 332 | if (scriptArgs.length > 0) { 333 | String scriptName = scriptArgs[0]; 334 | 335 | JInterp.setGlobal("argv0", scriptName); 336 | JInterp.setGlobal("argv", scriptArgs, 1); 337 | JInterp.setGlobal("argc", scriptArgs.length-1); 338 | 339 | JInterp.evaluateFile(scriptName); 340 | 341 | if (!commandLine.hasOption("interactive")) { 342 | System.exit(0); 343 | } 344 | } 345 | 346 | // 5b. Otherwise, start interactive session. 347 | 348 | interactive = true; 349 | historyEnabled = true; 350 | if (commandLine.hasOption("nohistory")) { 351 | historyEnabled = false; 352 | } 353 | 354 | ConsoleThread thread = new ConsoleThread(); 355 | thread.setDaemon(true); 356 | thread.start(); 357 | 358 | JInterp.processTclEvents(); 359 | 360 | System.exit(0); 361 | } 362 | 363 | class ConsoleThread extends Thread { 364 | 365 | private Mode mode; 366 | 367 | public ConsoleThread() { 368 | setName("ConsoleThread"); 369 | String filename = commandLine.getOptionValue("historyfile", System.getenv("HOME") + "/.jmxsh_history"); 370 | if (historyEnabled == true) { 371 | try { 372 | Readline.getInstance().setHistoryFile(filename); 373 | } 374 | catch (IllegalArgumentException e) { 375 | System.out.println("History file " + filename + " not writable, command-line history disabled."); 376 | historyEnabled = false; 377 | } 378 | } 379 | mode = null; 380 | } 381 | 382 | private void switchMode() { 383 | if (mode == Mode.getBrowseModeInstance()) { 384 | System.out.println("Entering shell mode."); 385 | mode = Mode.getShellModeInstance(); 386 | } 387 | else { 388 | System.out.println("Entering browse mode."); 389 | mode = Mode.getBrowseModeInstance(); 390 | } 391 | } 392 | 393 | public synchronized void run() { 394 | 395 | try { 396 | 397 | System.out.println("jmxsh v" + Main.VERSION + ", " + Main.DATE + "\n"); 398 | System.out.println("Type 'help' for help. Give the option '-?' to any command"); 399 | System.out.println("for usage help.\n"); 400 | 401 | if (commandLine.hasOption("browse")) { 402 | System.out.println("Starting up in browser mode."); 403 | mode = Mode.getBrowseModeInstance(); 404 | } else { 405 | System.out.println("Starting up in shell mode."); 406 | mode = Mode.getShellModeInstance(); 407 | } 408 | 409 | String lastResult = ""; 410 | while (true) { 411 | 412 | System.out.print(mode.getPrePromptDisplay()); 413 | 414 | String line = Readline.getInstance().readline(mode.getPrompt() + " "); 415 | 416 | if (line == null) { 417 | System.exit(0); 418 | } 419 | else if (line.length() == 0) { 420 | switchMode(); 421 | continue; 422 | } 423 | else if (line.equals("help")) { 424 | mode.displayHelp(); 425 | continue; 426 | } 427 | 428 | String result = mode.handleInput(line); 429 | 430 | if (historyEnabled && result != null && !result.equals(lastResult)) { 431 | Readline.getInstance().addToHistory(result); 432 | lastResult = result; 433 | } 434 | } 435 | } 436 | catch (RuntimeException e) { 437 | logger.error("Runtime exception caught.", e); 438 | System.err.println("Exception caught: " + e.getMessage()); 439 | } 440 | } 441 | } 442 | 443 | } 444 | 445 | -------------------------------------------------------------------------------- /src/jmxsh/BrowseMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * $URL$ 3 | * 4 | * $Revision$ 5 | * 6 | * $LastChangedDate$ 7 | * 8 | * $LastChangedBy$ 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | */ 23 | package jmxsh; 24 | 25 | /** 26 | * BrowseMode.java 27 | * 28 | * Implements a menu-based browsing mode of the JMX namespace. 29 | * 30 | * @author robspassky 31 | */ 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | import javax.management.MBeanAttributeInfo; 37 | import javax.management.MBeanOperationInfo; 38 | import javax.management.MBeanParameterInfo; 39 | 40 | import org.apache.log4j.Logger; 41 | import org.apache.oro.text.GlobCompiler; 42 | import org.apache.oro.text.regex.MalformedPatternException; 43 | import org.apache.oro.text.regex.Pattern; 44 | import org.apache.oro.text.regex.PatternCompiler; 45 | import org.apache.oro.text.regex.PatternMatcher; 46 | import org.apache.oro.text.regex.Perl5Matcher; 47 | 48 | import tcl.lang.TclException; 49 | import tcl.lang.TclList; 50 | import tcl.lang.TclObject; 51 | import tcl.lang.TclString; 52 | 53 | class BrowseMode extends Mode { 54 | 55 | enum Menu { ATTRIBUTE, ATTROP, DOMAIN, MBEAN, NONE, OPERATION, SERVER } 56 | 57 | static BrowseMode instance = new BrowseMode(); 58 | 59 | static private PatternCompiler GLOB_COMPILER = new GlobCompiler(); 60 | static private Logger logger = Logger.getLogger(BrowseMode.class); 61 | static private PatternMatcher PERL5_MATCHER = new Perl5Matcher(); 62 | 63 | private List attributes; 64 | private Menu currentMenu; 65 | 66 | private String[] items; 67 | private int maxChoice; 68 | private List operations; 69 | private Pattern pattern; 70 | private String prompt; 71 | 72 | private BrowseMode() { 73 | this.prompt = ""; 74 | this.currentMenu = Menu.SERVER; 75 | this.pattern = null; 76 | this.attributes = new ArrayList(); 77 | this.operations = new ArrayList(); 78 | this.maxChoice = 0; 79 | } 80 | 81 | void accessAttribute(MBeanAttributeInfo attr) { 82 | Context context = Context.fromTcl(); 83 | Object value = Jmx.getInstance().getAttribute(context.server, context.mbean, attr.getName()); 84 | 85 | System.out.println("=====================================================\n"); 86 | System.out.printf(" Accessing Attribute %s\n\n", attr.getName()); 87 | System.out.printf("%s = %s\n\n", attr.getName(), value.toString()); 88 | 89 | if (attr.isWritable()) { 90 | System.out.println("Enter a new value for this attribute, or hit enter to leave it unchanged."); 91 | this.prompt = String.format("New value (%1$s): ", TypeName.translateClassName(attr.getType())); 92 | String newValue = Readline.getInstance().readline(this.prompt); 93 | if (newValue != null && newValue.length() > 0) { 94 | Jmx.getInstance().setAttribute( 95 | context.server, 96 | context.mbean, 97 | attr.getName(), 98 | TclString.newInstance(newValue) 99 | ); 100 | System.out.println("Value changed."); 101 | } 102 | else { 103 | System.out.println("Value not changed."); 104 | } 105 | } 106 | Readline.getInstance().readline("Press enter to continue."); 107 | } 108 | 109 | void displayHelp() { 110 | StringBuilder sb = new StringBuilder(1000); 111 | 112 | sb.append("=====================================================\n"); 113 | sb.append(" Browse Mode Help\n"); 114 | sb.append("\n"); 115 | sb.append("This mode is a tree browser of the JMX namespace. It\n"); 116 | sb.append("is menu-driven, so there are no commands to memorize.\n"); 117 | sb.append("\n"); 118 | sb.append("At most times, you will be presented with a list of\n"); 119 | sb.append("JMX objects. You can select one by number and that\n"); 120 | sb.append("will result in descending the tree, and opening a new\n"); 121 | sb.append("menu of choices.\n"); 122 | sb.append("\n"); 123 | sb.append("Besides entering a number, you can enter the words 'up'\n"); 124 | sb.append("or 'down' (or 'u' or 'd') and you will return to the\n"); 125 | sb.append("move a level up or down in the browsing hierarchy, based\n"); 126 | sb.append("on your browsing history.\n"); 127 | sb.append("\n"); 128 | sb.append("If you enter some other non-numerical string,\n"); 129 | sb.append("that string will be treated as a glob pattern (case-\n"); 130 | sb.append("insensitive, with *'s prefixed and suffixed) and applied\n"); 131 | sb.append("to the current listing of JMX items.\n"); 132 | sb.append("\n"); 133 | sb.append("To clear a glob currently in effect, enter a single space\n"); 134 | sb.append("and hit enter.\n"); 135 | sb.append("\n"); 136 | sb.append("As you browse, the current SERVER, DOMAIN, MBEAN, and\n"); 137 | sb.append("ATTROP (attribute or operation) values will be shown.\n"); 138 | sb.append("These represent actual global variables in the Tcl\n"); 139 | sb.append("session that will be usable when you leave Browse mode.\n"); 140 | sb.append("\n"); 141 | sb.append("To leave the Browse mode, press enter at an empty line.\n"); 142 | sb.append("You will know you have left when you see the Shell prompt,\n"); 143 | sb.append("'% '\n"); 144 | sb.append("=====================================================\n"); 145 | 146 | System.out.println(sb.toString()); 147 | Readline.getInstance().readline("Press enter to continue."); 148 | } 149 | 150 | private String getAttropMenu() { 151 | StringBuilder msb = new StringBuilder(1000); 152 | Context context = Context.fromTcl(); 153 | 154 | this.attributes.clear(); 155 | this.operations.clear(); 156 | 157 | MBeanAttributeInfo[] attrArray = Jmx.getInstance().getAttributes(context.server, context.mbean); 158 | MBeanOperationInfo[] operArray = Jmx.getInstance().getOperations(context.server, context.mbean); 159 | 160 | int i = 0; 161 | 162 | msb.append(" Attribute List:\n\n"); 163 | 164 | for (MBeanAttributeInfo attr : attrArray) { 165 | if (this.pattern != null && !PERL5_MATCHER.matches(attr.getName(), this.pattern)) 166 | continue; 167 | 168 | this.attributes.add(attr); 169 | 170 | StringBuilder sb = new StringBuilder(100); 171 | sb.append(attr.isIs() ? "i" : "-"); 172 | sb.append(attr.isReadable() ? "r" : "-"); 173 | sb.append(attr.isWritable() ? "w" : "-"); 174 | sb.append(" "); 175 | String typename = TypeName.translateClassName(attr.getType()); 176 | sb.append(typename); 177 | int numSpaces = 5 - (typename.length() % 5); 178 | if (typename.length() < 5) { 179 | numSpaces += 5; 180 | } 181 | for (int j=0; j 0) 191 | msb.append("\n Operation List:\n\n"); 192 | 193 | for (MBeanOperationInfo op : operArray) { 194 | if (this.pattern != null && !PERL5_MATCHER.matches(op.getName(), this.pattern)) 195 | continue; 196 | 197 | this.operations.add(op); 198 | 199 | StringBuilder namesb = new StringBuilder(50); 200 | MBeanParameterInfo[] params = op.getSignature(); 201 | StringBuilder sb = new StringBuilder(100); 202 | TclObject paramTclList = TclList.newInstance(); 203 | 204 | String typename = TypeName.translateClassName(op.getReturnType()); 205 | sb.append(typename); 206 | int numSpaces = 5 - (typename.length() % 5); 207 | if (typename.length() < 5) { 208 | numSpaces += 5; 209 | } 210 | for (int j=0; j menu = new ArrayList(); 283 | for (String item: this.items) { 284 | if (this.pattern == null || PERL5_MATCHER.matches(item, this.pattern)) { 285 | menu.add(item); 286 | } 287 | } 288 | 289 | this.items = new String[menu.size()]; 290 | this.items = menu.toArray(this.items); 291 | 292 | for (int i=1; i<=this.items.length; i++) { 293 | sb.append(String.format(" %1$3d. %2$s\n", i, this.items[i-1])); 294 | } 295 | 296 | if (this.items.length == 0) { 297 | sb.append("\n ((((( No options available.\n\n"); 298 | this.prompt = "(no options available):"; 299 | } 300 | 301 | this.maxChoice = this.items.length; 302 | return sb.toString(); 303 | } 304 | 305 | String getPrePromptDisplay() { 306 | 307 | StringBuilder sb = new StringBuilder(1000); 308 | 309 | sb.append("====================================================\n\n"); 310 | 311 | switch (this.currentMenu) { 312 | 313 | case SERVER: 314 | sb.append(" Available Servers:\n\n"); 315 | sb.append(getMenu()); 316 | break; 317 | 318 | case DOMAIN: 319 | sb.append(" Available Domains:\n\n"); 320 | sb.append(getMenu()); 321 | break; 322 | 323 | case MBEAN: 324 | sb.append(" Available MBeans:\n\n"); 325 | sb.append(getMenu()); 326 | break; 327 | 328 | case ATTROP: 329 | sb.append(getAttropMenu()); 330 | break; 331 | 332 | default: 333 | throw new IllegalStateException("Bad menu state."); 334 | 335 | } 336 | 337 | 338 | Context context = Context.fromTcl(); 339 | if (context.server != null) { 340 | sb.append("\n SERVER: "); 341 | sb.append(context.server); 342 | } 343 | if (context.domain != null) { 344 | sb.append("\n DOMAIN: "); 345 | sb.append(context.domain); 346 | } 347 | if (context.mbean != null) { 348 | sb.append("\n MBEAN: "); 349 | sb.append(context.mbean); 350 | } 351 | if (context.attrop != null) { 352 | sb.append("\n ATTROP: "); 353 | sb.append(context.attrop); 354 | } 355 | if (this.pattern != null) { 356 | String pattstr = this.pattern.getPattern(); 357 | pattstr = pattstr.substring(2, pattstr.length()-2); 358 | sb.append("\n GLOB: "); 359 | sb.append("*" + pattstr + "*"); 360 | sb.append(" (space to clear)"); 361 | } 362 | 363 | sb.append("\n\n====================================================\n"); 364 | 365 | return sb.toString(); 366 | } 367 | 368 | String getPrompt() { 369 | return this.prompt; 370 | } 371 | 372 | String handleInput(String input) { 373 | if (input.equals("up") || input.equals("u")) { 374 | switch (this.currentMenu) { 375 | case SERVER: 376 | break; 377 | case DOMAIN: 378 | this.currentMenu = Menu.SERVER; 379 | break; 380 | case MBEAN: 381 | this.currentMenu = Menu.DOMAIN; 382 | break; 383 | case ATTROP: 384 | this.currentMenu = Menu.MBEAN; 385 | break; 386 | case ATTRIBUTE: 387 | case OPERATION: 388 | this.currentMenu = Menu.ATTROP; 389 | this.attributes.clear(); 390 | this.operations.clear(); 391 | break; 392 | default: 393 | break; 394 | } 395 | return null; 396 | } 397 | 398 | if (input.equals("down") || input.equals("d")) { 399 | switch (this.currentMenu) { 400 | case SERVER: 401 | this.currentMenu = Menu.DOMAIN; 402 | break; 403 | case DOMAIN: 404 | this.currentMenu = Menu.MBEAN; 405 | break; 406 | case MBEAN: 407 | this.currentMenu = Menu.ATTROP; 408 | break; 409 | case ATTROP: 410 | break; 411 | case ATTRIBUTE: 412 | case OPERATION: 413 | this.currentMenu = Menu.ATTROP; 414 | break; 415 | default: 416 | break; 417 | } 418 | return null; 419 | } 420 | 421 | int choice = 0; 422 | 423 | try { 424 | choice = Integer.parseInt(input); 425 | } 426 | catch (NumberFormatException e) { 427 | if (input.equals(" ")) { 428 | this.pattern = null; 429 | } 430 | else { 431 | try { 432 | this.pattern = GLOB_COMPILER.compile("*" + input + "*", GlobCompiler.CASE_INSENSITIVE_MASK); 433 | } 434 | catch (MalformedPatternException me) { 435 | System.out.println("Invalid glob pattern '" + input + "' - " + me.getMessage()); 436 | this.pattern = null; 437 | } 438 | } 439 | return null; 440 | } 441 | 442 | if (choice < 1 || choice > this.maxChoice) { 443 | System.out.printf("Please make a choice between %d and %d.\n", 1, this.maxChoice); 444 | Readline.getInstance().readline("Press enter to continue."); 445 | return null; 446 | } 447 | 448 | switch (this.currentMenu) { 449 | case SERVER: 450 | JInterp.setGlobal("SERVER", this.items[choice-1]); 451 | JInterp.unsetGlobal("DOMAIN"); 452 | JInterp.unsetGlobal("MBEAN"); 453 | JInterp.unsetGlobal("ATTROP"); 454 | this.currentMenu = Menu.DOMAIN; 455 | break; 456 | case DOMAIN: 457 | JInterp.setGlobal("DOMAIN", this.items[choice-1]); 458 | this.currentMenu = Menu.MBEAN; 459 | JInterp.unsetGlobal("MBEAN"); 460 | JInterp.unsetGlobal("ATTROP"); 461 | break; 462 | case MBEAN: 463 | JInterp.setGlobal("MBEAN", this.items[choice-1]); 464 | this.currentMenu = Menu.ATTROP; 465 | JInterp.unsetGlobal("ATTROP"); 466 | break; 467 | case ATTROP: 468 | if (choice > this.attributes.size()) { 469 | choice = choice - this.attributes.size(); 470 | JInterp.setGlobal("ATTROP", this.operations.get(choice-1).getName()); 471 | invokeOperation(this.operations.get(choice-1)); 472 | } 473 | else { 474 | JInterp.setGlobal("ATTROP", this.attributes.get(choice-1).getName()); 475 | accessAttribute(this.attributes.get(choice-1)); 476 | } 477 | break; 478 | default: 479 | throw new IllegalStateException("Unsupported menu action."); 480 | } 481 | 482 | return null; 483 | } 484 | 485 | void invokeOperation(MBeanOperationInfo op) { 486 | MBeanParameterInfo[] signature = op.getSignature(); 487 | String[] paramTypes = new String[signature.length]; 488 | 489 | Context context = Context.fromTcl(); 490 | 491 | System.out.println("=====================================================\n"); 492 | System.out.printf(" Invoking Operation %s\n\n", op.getName()); 493 | 494 | if (signature.length > 0) { 495 | System.out.println("Please enter values for " + signature.length + " parameters."); 496 | } 497 | 498 | Object[] parameters = new Object[signature.length]; 499 | for (int i=0; i