发布新日志

  • Beanshell翻译12

    2008-09-02 20:23:52

    Beanshell翻译12

    http://user.qzone.qq.com/281696143/blog/1219126057  Ronger
    1.Files and Directories 文件和目录
    The following commands work with files, directories, and the working directory:
    下面的命令和文件,目录,工作目录一起工作:
    cd(), pwd(), dir(), rm(), mv(), cat()
    Unix Style file commands.
    Unix 样式文件命令。
    pathToFile()
    Translate a relative path
    to an absolute path taking into account the BeanShell current working directory.
    通过Beanshell当前的工作路径,将相对路径转变为绝对路径。
    Desktop and Class Browser 桌面和类浏览器
    The following commands work with GUI tools:
    下面的命令是和GUI工具一起工作的:
    classBrowser(), browseClass() Open a class browser window or browse a specific class or object.
    打开一个类浏览器窗口,或者展示一个特殊类或对象。
    desktop() Launch the BeanShell GUI desktop.
    desktop() 弹出Beanshell的GUI桌面。
    setNameCompletion() Turn on or off name completion in the GUI console.
    在GUI控制台中,打开或者关闭名字。
    Note: 注意
    The dir() command is written in Java;
    dir()命令在Java中被重写;
    2.Adding BeanShell Commands 增加Beanshell命令
    BeanShell Commands are scrīpted methods or compiled Java classes
    which are dynamically loaded from the classpath to implement a method.
    All of the standard commands we discuss in this manual live in the
    BeanShell JAR file under the path /bsh/commands.
    Beanshell命令是脚本函数或者编译的Java类,这个Java类是从类路径中动态加载的。
    我们讨论的Beanshell的JAR文件下的所有标准命令,都在路径/bsh/commands下面。
    Adding to the set of "prefab" commands supplied with BeanShell
    is as easy as writing any other BeanShell methods.
    You simply have to place your scrīpt into a file named with the same name as the command
    and place the file in the classpath.
    You may then "import" the commands with the importCommands() method.
    在Beanshell中增加"prefab"命令的设置就像写一个其它的Beanshell函数一样简单。
    你可以简单的将你的脚本放到,一个名字和这个命令一样名字的文件中,并且将这个文件放在类路径中。
    你也可以通过importCommands()函数来导入命令。
    Command files can be placed anywhere in the BeanShell classpath.
    You can use even use the addClassPath() or setClassPath() commands
    to add new command directories or JARs containing commands to your scrīpt at any time.
    命令文件可以放在Beanshell类路径中的任何地方。
    你甚至可以使用addClassPath()或者setClassPath()命令,
    任何时间都可以增加一个新的命令目录或者包含命令的JARs,到你的脚本中。
    Hello World
    For example, let's make a helloWorld() command:
    例如,让我们做一个helloWorld()命令:
    // File: helloWorld.bsh
    helloWorld() {
    print("Hello World!");
    }
    Place the command file helloWorld.bsh in a directory or JAR in your classpath
    and import it with the importCommands() command.
    You can either set the classpath externally for Java or inside of BeanShell with
    the addClassPath() command.
    For example, suppose we have placed the file in the path:
    /home/pat/mycommands/helloWorld.bsh. We could then do:
    将这个命令文件helloWorld.bsh放在你的类路径的路径中,并且使用importCommands()命令导入它。
    你不仅可以为Java设置第三方类路径,也可以使用addClassPath()命令进入Beanshell.
    例如,假设我们已经将文件放在路径中:/home/pat/mycommands/helloWorld.bsh.我们可以这么做:
    addClassPath("/home/pat"); // If it's not already in our classpath 如果它不总是在我们的类路径中
    importCommands("/mycommands");
    We can now use helloWorld() just like any other BeanShell command.
    我们现在可以像其它的Beanshell命令一样使用helloWorld()。
    helloWorld(); // prints "Hello World!" 打印"Hello World!"
    importCommands() will accept either a "resource path" style path name or a Java package name.
    Either one is simply converted to a resource path or Java package name as required
    to load scrīpts or compiled BeanShell command classes.
    A relative path (e.g. "mycommands") is turned into an absolute path by prepending "/".
    You may import "loose" commands (like unpackaged classes)
    at the top of the classpath by importing "/".
    importCommands()将接受一个"resource path"式样的路径名字或者一个Java包名。
    任一个都是简单的转变成一个源路径或者需要的Java包名,
    去加载脚本或者编译Beanshell命令类。
    一个相对的路径(比如"mycommands"),是通过一个预先的"/"来转变成一个绝对路径。
    你可以通过在类路径的前面导入"/",导入"loose"命令(就像没有包装的类)。
    If for example you have placed BeanShell commands
    along with your other classes in a Java package called com.xyz.utils in your classpath,
    you can import those commands with:
    如果在例子中,你通过一个Java包来将Beanshell命令放到你的其它类中,
    你可以像下面一样导入命令:
    // equivalent 等价于
    importCommands("com.xyz.utils");
    importCommands("/com/xyz/utils");
    Imported commands are scoped just like imported classes.
    So if you import commands in a method or object they are local to that scope.
    导入命令的有效性和导入的类一致。
    所以如果你在一个方法或者对象中导入命令,他们都有一个本地的作用域。
    3.Overloaded Commands 重新加载命令
    BeanShell command scrīpts can contain any number of overloaded forms of the command method,e.g.:
    Beansehll命令脚本包含一些重新加载样式的命令函数,例如:
    // File: helloWorld.bsh 文件:helloWorld.bsh
    helloWorld() {
    print("Hello World!");
    }
    helloWorld( String msg ) {
    print("Hello World: "+msg);
    }
    BeanShell will select the appropriate method based on the usual rules for methods selection.
    Beanshell将选择可供专用的方法,是建立在方法选择的通用规则的基础上。
    4.Compiled Commands 编译命令
    You can also implement BeanShell commands as compiled classes instead of scrīpts if you wish.
    Your class name must simply be the name of the command (matching case as well)
    and it must implement one or more static invoke() methods who's signatures match a pattern.
    The first two arguments of the invoke() method must be the bsh.Interpreter and bsh.CallStack objects
    that provide context to all BeanShell scrīpts.
    Then any number (possibly zero) of arguments,
    which are the arguments of the command may follow.
    BeanShell will select the appropriate method based on the usual rules for methods selection.
    如果你想这样做的话,你也可以用编译好的类代替脚本来实现Beanshell命令。
    你的类名必须简单的和命令的名字一样(最好是匹配的),
    并且它必须实现一个或者多个静态invoke()方法,方法的签名匹配一个模式。
    这个invoke()函数的前面两个参数必须为bsh.Interpreter和bsh.CallStack对象,
    对象是为所有的Beanshell脚本提供环境。
    那么一些数量的参数(有可能为0),这些参数是命令的参数。
    Beanshell将选择可供专用的方法,是建立在方法选择的通用规则的基础上。
    The dir() command is an example of a BeanShell command that is implemented in Java.
    Let's look at a snippet from it
    to see how it implements a pair of invoke() methods
    for the dir() and dir(path) commands.
    dir()命令是一个Beanshell命令的例子,这个命令是在Java中实现的。
    我们来看看为了dir()和dir(path)命令儿做的片断,看看它是如何实现invoke()函数的。
    /**
    Implement dir() command. 实现dir()命令
    */
    public static void invoke( Interpreter env, CallStack callstack )
    {
    String dir = ".";
    invoke( env, callstack, dir );
    }
    /**
    Implement dir( String directory ) command. 实现dir(String directory)命令。
    */
    public static void invoke(
    Interpreter env, CallStack callstack, String dir )
    {
    ...
    }
    5.User Defined Commands with invoke() 用户通过invoke()定义命令
    It is useful to note that the invoke() meta.method
    which we described in the section "scrīpting Interfaces"
    can be used directly in scope as well as through an object reference
    and one could use this to load arbitrary commands or implement arbitrary behavīor
    for commands (undefined method calls). For example:
    它是有用并且需要注意的,我们在章节"scrīpting Interfaces"中提到的invoke()方法
    meta.method可以直接用在一个对象引用的范围中,
    并且可以使用这个来加载任意的命令或者为命令实现任意的行为(未定义的方法调用)。例如:
    invoke( String methodName, Object [] arguments ) {
    print("You invoked the method: "+ methodName );
    }
    // invoke() will be called to handle noSuchMethod()
    invoke()将被调用去处理noSuchMethod()
    noSuchMethod("foo");
    invoke() is called to handle any method invocations for undefined methods within its scope.
    In this case we have declared it at the global scope.
    为未定义的函数,invoke()被调用处理一些函数。
    在这个例子中,我们可以在全局的作用域中定义它。
    6.Commands Scope 命令作用域
    scrīpted BeanShell commands are loaded when no existing method matches the command name.
    When a command scrīpt is loaded
    it is sourced (evaluated) in the 'global' scope of the interpreter.
    This means that once the command is loaded the methods declared in the command scrīpt
    are then defined in the interpreter's global scope
    and subsequent calls to the command
    are simply handled by the those methods as any other scrīpted method.
    当不存在方法匹配命令的名字的时候,脚本的Beanshell命令被加载。
    当一个命令脚本被加载,它是解释器的全局作用域的源。
    这个的意思就是,命令中加载定义在命令脚本中的函数,是定义在解释器的全局作用域中的。
    并且后来对这个命令的调用,是简单的被其它的函数处理。
    Note: 注意:
    Note that this means that currently scrīpted commands may only be loaded once
    and then they are effectively cached.
    注意这个的意思就是,当前脚本命令会被马上加载,并且他们会马上被储藏起来。

  • Beanshell翻译11

    2008-09-02 20:22:39

    Beanshell翻译11

    http://user.qzone.qq.com/281696143/blog/1218618449  Ronger
    1.Undefined Variables 没有定义的变量
    You can test to see if a variable is defined using the special value void. For example:
    你可以看一下,当一个变量用特殊的值void来进行定义的时候,例如:
    if ( foobar == void )
    // undefined 没有定义
    You can return a variable to the undefined state using the unset() command:
    你可以使用unset()命令,返回一个没有定义状态的变量。
    a == void; // true
    a=5;
    unset("a"); // note the quotes 注意这个引用
    a == void; // true
    Setting the Command Prompt 设置命令提示
    Users may set the command line prompt string for use in interactive mode
    by setting the value of the variable bsh.prompt or
    by defining the scrīpted method (or command) getBshPrompt().
    用户可以通过设置命令行prompt字符串,
    设置变量bsh.prompt的值或者是通过定义脚本函数getBshPrompt()
    来在交互模式下使用。
    If the command or method getBshPrompt() is defined
    it will be called to get a string to display as the user prompt.
    For example, one could define the following method
    to place the current working directory into their command prompt:
    如果命令或者函数getBshPrompt()被定义,它将被调用,取得一个用于提示用户的字符串。
    例如,一个人可以定义下面的函数,将当前的工作路径进入它的命令提示。
    getBshPrompt() { return bsh.cwd + " % "; }
    The default getBshPrompt() command returns the value of the variable bsh.prompt
    if it is defined or the string "bsh % " if not.
    If the getBshPrompt() method or command does not exist, throws an exception,
    or does not return a String, a default prompt of "bsh % " will be used.
    默认的getBshPrompt()命令返回变量bsh.prompt的值,条件是如果它被定义了或者
    字符串"bsh % "没有定义。
    如果getBshPrompt()函数或者命令不存在,抛出一个异常,
    或者没有返回一个字符串,一个默认的"bsh % "的提示将被使用。
    BeanShell Commands Beanshell命令
    BeanShell commands appear to the user as pre.defined methods such as print(), load(), or save().
    BeanShell Commands can be implemented as scrīpted methods or compiled Java classes
    which are dynamically loaded on demand from the classpath.
    We'll talk about adding your own commands in the next section "Adding BeanShell Commands".
    Beanshell命令对用户来说就是一些提前定义的函数例如print(),load(),或者save().
    Beanshell命令可以使用脚本函数或者编译好的Java类来实现,其中
    Java类是可以按要求从类路径中动态加载的。
    我们将在下一章"Adding BeanShell Commands"中谈谈添加你自己的命令。
    Tip: 提示:
    You can easily override any BeanShell command simply
    by defining the method yourself in your scrīpt. For example:
    通过在脚本中定义你自己的函数,你可以很容易的重写Beanshell命令。例如:
    print( arg ) {
    System.out.println( "You printed: " + arg );
    }
    If you define the method in the global scope it will apply everywhere.
    If you define it local to a scrīpted object it will only apply in that object context.
    如果你定义函数在全局的作用域中,它将在任何地方应用。
    如果你在一个脚本对象中定义它为本地的,它将只能在对象环境中应用。
    2.Commands Overview 命令的总的看法
    This is a high level overview of the BeanShell command set.
    You can find full documentation for all BeanShell commands
    in the "BeanShell Commands Documentation" section of this manual.
    See also the "BshDoc" section
    which covers javadoc style documentation of BeanShell scrīpt files.
    这里是Beanshell的命令设置的高度概括。
    你可以找到关于Beanshell命令的完整文档,在"Beanshell Commands Documentation"章节中。
    也可以"BshDoc"章节,这个章节讲解了Beanshell脚本文件的javadoc样式的文档。
    3.Interpreter Modes 解释器模式
    The following commands affect general modes of operation of the interpreter.
    下面的命令影响解释器操作的常用模式。
    exit() Exit the interpreter. (Also Control.D).
    退出解释器
    show()
    Turn on "show" mode
    which prints the result of every evaluation that is not of void type.
    show() 打开"show"模式,这个模式是用来打印每个计算的结果的。
    setAccessibility()
    Turn on access to private and protected members of Java classes.
    setAccessibility() 打开Java类的私有和受保护变量的存取。
    server()
    Launch the remote access mode,
    allowing remote access to the interpreter from a web browser or telnet client.
    server() 打开远程存取模式,允许从一个web浏览器或者是远程登录客户端,对解释器进行远程存取。
    debug()
    Turns on debug mode. Note: this is very verbose, unstructured output and is primarily of
    interest to developers.
    debug() 打开调试模式。注意:这里是非常详细的,非结构化的输出,并且最初对开发者来说是很有趣的。
    setStrictJava()
    Turn on "strict Java" mode
    which enforces Java compatibility by dissallowing loose types and undeclared variables.
    setStrictJava() 打开"strict Java"模式,
    这个模式,这个模式可以强迫Java不接受松散类型和未定义的变量。
    Output 输出
    The following commands are used for output:
    下面的命令是用来做输出的:
    print(), error() Print output to standard out or standard error.
    print(), error()打印输出到标准输出或者标准错误。
    print() always goes to the console,
    whereas System.out may or may not be captured by a GUI console or servlet.
    print()也可以去控制台,
    然而System.out可以被一个GUI控制台或者servlet捕捉,也可以不这样。
    frame() Display the AWT or Swing component in a Frame
    frame()在一个Frame中显示AWT或者Swing组件
    4.Source and Evaluation 源和计算表达式
    The following commands are used for evaluation or to run external scrīpts or applications:
    下面的命令是用来计算表达式或者运行第三方的脚本或者应用程序:
    eval() Evaluate a string as if it were typed in the current scope.
    eval() 计算一个字符串,当它定义在当前的作用域中。
    source(), sourceRelative()
    Read an external scrīpt file into the interpreter and evaluate it in the current scope
    读取一个第三方的脚本文件进入解释器并且在当前的作用域中计算它。
    run(), bg()
    Run an external file in a subordinate interpreter or
    in a background thread in a subordinate interpreter.
    在一个从属的解释器中,运行一个第三方的文件。
    exec()
    Run a native executable in the host OS
    在主机OS中,运行一个本地的可以执行的脚本。
    Utilities 有效性
    The following commands are useful utilities:
    下面的命令是很有效的:
    javap() Print the methods and fields of an object, similar to the output of javap
    javap() 打印一个对象的方法和属性,和javap的输出类似。
    which()
    Like the Unix 'which' command for executables.
    Map the classpath and determine the location of the specified class.
    就像Unix中的'which'命令一样。
    绘制类路径,并且决定特殊类的位置。
    load(), save()
    load a serializable object from a file or save one to a file.
    Special handling is provided for certain objects.
    从一个文件中,加载一个序列化的对象,或者将它存到文件中。
    特殊处理是提供确定的对象。
    object() Create an "empty" object context to hold variables; analogous to a Map.
    创建一个空对象环境,用来保存变量;类似于一个Map.
    5.Variables and Scope 变量和作用域
    The following commands affect the current scope: 下面的命令影响当前的作用域:
    clear() Clear all variables, methods and imports from the current scope.
    clear() 清理所有的变量,方法和从当前作用域中导入的东西。
    unset() Remove a variable from the current scope. (Return it to the "undefined" state).
    unset() 从一个当前的作用域中移除一个变量。(将它返回个"undefined"状态)。
    setNameSpace()
    Set the current namespace to a specified scope.
    Effectively bind the current scope to a new parent scope.
    设置当前名字空间为一个特殊的作用域。
    有效的将当前的作用域绑定到一个新的父亲作用域上面。
    6.Classpath 类路径
    The following commands manipulate or access the classpath:
    下面的命令巧妙的操作来存取类路径:
    addClassPath(), setClassPath(), getClassPath() Modify the BeanShell classpath.
    修改Beanshell类路径。
    reloadClasses() Reload a class or group of classes.
    重新加载一个类或者一群类。
    getClass()
    Load a class explicitly taking into account the BeanShell classpath.
    从Beanshell类路径下面明确的加载一个类。
    getResource() Get a resource from the classpath.
    从类路径中取得一个源。

  • Beanshell翻译10

    2008-09-02 20:21:24

    Beanshell翻译10

    http://user.qzone.qq.com/281696143/blog/1218006867  Ronger
    1.Special Variables and Values 特殊的变量和值
    In addition to the scope modifiers: 'this', 'super', 'global',
    BeanShell supports a number of pre.defined system variables, "magic" values, and methods.
    为了增加作用域的使用:'this','super','global',
    Beanshell提供一些提前定义好的系统变量,"magic"值,和方法。
    Special Values 特殊值
    · $_ . The value of the last expression evaluated.
    The strange construct for this is drawn from Perl,
    but the idea exists in many scrīpting languages.
    It is useful for getting back the last result when you are working interactively.
    $_最后一个表达式。
    这个奇怪的构造是从perl中过来的,但是这个创意存在于很多脚本语言中。
    当你在交互式的运行的时候,在取到最后的结果上面它是很有用的。
    · $_e . The last uncaught exception object thrown.
    This is useful in interactive use for retrieving the last exception to inspect it for details.
    最后一个没有捕获的异常对象
    在交互式使用中去检查它得细节而重新取得最后一个异常,它是有用的,
    · bsh . The BeanShell root system object, containing system information and variables.
    Beanshell根系统对象,包含系统信息和变量。
    · bsh.args . An array of Strings passed as command line arguments to the BeanShell interpreter.
    通过命令行参数到Beanshell解释器得到的一个字符串数组。
    · bsh.shared . A special static space which is shared across all interpreter instances.
    Normally each bsh.Interpreter instance is entirely independent;
    having its own unique global namespace and settings.
    bsh.shared is implemented as a static namespace in the bsh.Interpreter class.
    It was added primarily to support communication among instances for the GUI desktop.
    一个特殊的静态空间,和所有的解释器实例共享。
    正常的每个bsh.Interpreter实例是完全独立的;
    有他们自己单独的全局名字空间和设置。
    在bsh.Interpreter类中,bsh.shared是作为一个静态的名字空间实现的。
    它最初加进来是为了,支持实例和GUI平台之间的通信。
    · bsh.console . If BeanShell is running in its GUI desktop mode,
    this variable holds a reference to the current interpreter's console, if it has one.
    如果Beanshell运行在它的桌面模式,这个变量保存一个引用指向当前的解释器控制台,
    当然它只有一个。
    · bsh.appletcontext . If BeanShell is running inside an Applet,
    the current applet context, if one exists.
    如果Beanshell运行在一个Applet中,就是指这个当前的applet环境。
    · bsh.cwd . A String representing the current working directory of the BeanShell interpreter.
    This is used or manipulated by the cd(), dir(), pwd(), and pathToFile() commands.
    一个字符串,直接为Beanshell解释器工作的,
    这些是被使用或者是通过cd(),dir(),pwd(),pathToFile()命令来操作。
    · bsh.show . A boolean value used by the show() command.
    It indicates whether results are always printed, for interactive use.
    用在show()命令中的布尔值,它表示结果是否要被打印,在交互使用中。
    · bsh.interactive .
    A boolean indicating whether this interpreter running in an interactive mode。
    一个布尔值,表示解释器是否运行在一个交互模式下。
    · bsh.evalOnly .
    A boolean indicating whether this interpreter has an input stream or whether is it only
    serving as an engine for eval() operations (e.g. for embedded use).
    一个布尔值,表示解释器是否有一个输入流,
    或者它作为一个引擎仅仅是为eval()操作服务的。
    Note: 提示:
    The choice of "bsh" for the root system object name was somewhat unfortunate
    because it conflicts with the current package name for BeanShell (also bsh).
    This means that if you wish to work with BeanShell classes explicitly from BeanShell scrīpts
    (e.g. bsh.Interpreter)
    you must first import them, e.g.:
    对于系统根对象名来说,"bsh"的选择在有些情况下不太好。
    因为它对Beanshell来说避免了当前的包名。
    这些表明了,如果你希望和Beanshell中的类一起工作,你必须首先导入他们。
    import bsh.Interpreter;
    i=new Interpreter();
    2.Special Members of 'this' type References 'this'类型引用的特别属性
    'this' type references have several "magic" members: 'this'类型引用有几类"magic"属性
    · this.variables .
    An array of Strings listing the variables defined in the current method context(namespace).
    一个字符串数组列出了定义在当前函数环境(名字空间)的变量。
    · this.methods .
    An array of Strings listing the methods defined the current method context(namespace).
    一个字符串数组列出了定义在当前函数环境(名字空间)的变量。
    · this.interpreter .
    A bsh.Interpreter reference to the currently executing BeanShell Interpreter object.
    bsh.Interpreter引用指向当前执行的Beanshell解释器对象。
    · this.namespace .
    A bsh.NameSpace reference to the BeanShell NameSpace object of the current method context.
    See "Advanced Topics".
    bsh.NameSpace引用指向Beanshell当前函数环境名字空间对象。请看"高级话题"。
    · this.caller .
    A bsh.This reference to the calling BeanShell method context.
    See "Variables and Scope Modifiers".
    bsh.This引用指向Beanshell函数环境。请看"变量和作用域修改"。
    · this.callstack .
    An array of bsh.NameSpace references representing the "call stack" up to the current method context.
    See "Advanced Topics".
    一个bsh.NameSpace引用数组表示,"call stack"指向当前函数环境。请看"高级话题"。
    These magic references are primarily used by BeanShell commands.
    这些魔术引用是最初使用在Beansehll命令中。

  • Beanshell翻译9

    2008-09-02 20:20:12

    Beanshell翻译9

    http://user.qzone.qq.com/281696143/blog/1217928367  Ronger
    1.Interface Types and Casting 接口和类型转换
    It is legal,
    but not usually necessary to perform an explicit cast of a BeanShell scrīpted object to an interface
    type. For example:
    这是合法的,但是通常不需要,将Beanshell脚本对象执行一个显式的转换变成一个接口类型,例如:
    actionPerformed( event ) {
    print( event );
    }
    button.addActionListener(
    (ActionListener)this ); // added cast 增加转换
    In the above,
    the cast to ActionListener would have been done automatically by BeanShell
    when it tried to match the 'this' type argument
    to the signature of the addActionListener() method.
    在上面的例子中,当它尝试将'this'类型的参数和addActionListener()方法相匹配时,
    转换为ActionListener将被Beanshell自动完成。
    Doing the cast explicitly has the same effect,
    but takes a different route internally.
    With the cast,
    BeanShell creates the necessary adapter that implements the ActionListener interface first,
    at the time of the cast, and then later finds that the method is a perfect match.
    进行显式的转换也有同样的效果,但是在内部使用了不同的方法.
    转换时,在转换的过程中,
    Beanshell创建需要的实现ActionListener接口的适配器,后来可以找到这个匹配的方法。
    What's the difference? Well,
    there are times where performing an explicit cast to control
    when the type is created may be important.
    Specifically, when you are passing references out of your scrīpt,
    to Java classes that don't immediately use them as their intended type.
    In our earlier discussion we said that automatic casting happens "within your BeanShell scrīpts".
    And in our examples so far BeanShell has always had the
    opportunity to arrange for the scrīpted object to become the correct type,
    before passing it on.
    But it is possible for you to pass a 'this' reference to a method that,
    for example, takes the type 'Object',
    in which case BeanShell would have no way of knowning what it was destined for later.
    You might do this, for example,
    if you were placing your scrīpted objects into a collection (Map or List) of some kind.
    In that case,
    you can control the process by performing an explicit cast to the desired type
    before the reference leaves your scrīpt.
    区别是什么呢?有时当类型被创建,执行一个显式的转换控制是重要的.
    特别的是,当你将你的引用从脚本中传递到Java类中时,不要马上当做打算好的类型使用他们。
    在我们前面的讨论中,我们说自动的转型发生在"和你的Beanshell脚本在一起"。
    在通过它之前,安排脚本对象变成正确类型的时机。
    但是对你来说它可能将一个'this'引用赋给一个方法,例如,取到类型'Object',
    在一个Beanshell也没有办法知道后来它的目的是什么的情况中。
    你可以这样做,例如,如果你将你的脚本对象放到一个某种类型的集合中(Map或者List).
    在上面这个情形中,在这个引用离开你的脚本之前,你可以通过执行显式的类型转换来控制这个过程。
    Another case where you may have to perform a cast is
    where you are using BeanShell in an embedded application
    and returning a scrīpted object as the result of an eval() or a get() variable
    from the Interpreter class.
    There again is a case where BeanShell has no way of knowing the intended type within the scrīpt.
    By performing an explicit cast you can create the type before the reference leaves your scrīpt.
    另一个情况,你执行一个转换的地点是,
    在一个内含的应用程序中,在哪儿使用Beanshell
    并且从解释器中返回一个eval()或者get()的变量的脚本对象。
    另外的一种情况,Beanshell没有方法知道在脚本中的对象在哪儿。
    在引用离开脚本之前,通过执行一个显式的转换来创建类型。
    We'll discuss embedded applications of BeanShell
    in the "Embedding BeanShell" section a bit later,
    along with the Interpreter getInterface() method,
    which is another way of accomplishing this type of cast from outside a scrīpt.
    稍后我们将在"Embedding Beanshell"章节中讨论Beanshell的嵌入式应用程序,
    通过解释器中的getInterface()方法,这个方法是从脚本外完成类型转换的另一种方法。
    2."Dummy" Adapters and Incomplete Interfaces
    It is common in Java to see "dummy" adapters created for interfaces that have more than one method.
    The job of a dummy adapter is to implement all of the methods of the interface with stubs
    (empty bodies),
    allowing the developer to extend the adapter and override just the methods of interest.
    "Dummy"适配器和不完善的接口
    为不止一个方法的接口创建"dummy"适配器,在Java中是很常见的。
    一个哑适配器的工作是通过存根(内容为空的方法)创建接口中的所有方法,
    允许开发者继承适配器并且仅仅重写感兴趣的方法。
    We hinted in our earlier discussion that BeanShell could handle scrīpted interfaces
    that implement only the subset of methods that are actually used and that is indeed the case.
    You are free in BeanShell to scrīpt only the interface methods that you expect to be called.
    The penalty for leaving out a method that is actually
    invoked is a special run.time exception: java.lang.reflect.
    UndeclaredThrowableException, which the caller will receive.
    在早先的讨论中我们提到Beanshell可以处理仅仅实现方法子集的脚本接口,
    这些方法是实际中用到的并且是在这个例子中的。
    离开这个通常调用的方法就会调用运行时异常:java.lang.reflect.
    UndeclaredThrowableException,调用者将会接受这个异常。
    The UndeclaredThrowableException is an artifact of Java Proxy API that makes dynamic interfaces possible.
    It says that an interface threw a checked exception type that was not prescribed by the method signature.
    This is a situation that cannot normally happen in compiled Java.
    So the Java reflection API handles it by wrapping the checked exception
    in this special unchecked (RuntimeException) type in order to throw it.
    You can get the underlying error using the exception's getCause() method,
    which will, in this case, reveal the BeanShell EvalError exception,
    reporting that the scrīpted method of the correct signature was not found.
    UndeclaredThrowableException是一个Java代理API为实现动态接口的人造品。
    它说明了,一个接口抛出一个没有在函数中标示出来的可检查异常类型。
    这是一种不是通常发生在经过编译的Java的情况,所以
    在发生普通的运行时异常时,为了可以抛出这个异常,Java反射API通过包装可检查异常来处理它。
    你可以通过异常的getCause()方法(这个方法可以取到Beanshell的EvalError异常),取到潜在的错误。
    3.The invoke() Meta.Method invoke() Meta.Method
    BeanShell provides a very simple short.hand mechanism for scrīpting interfaces
    with large numbers of methods.
    You can implement the special method invoke( name, args ) in any scrīpted context.
    The invoke() method will be called to handle the invocation of any method of the interface
    that is not defined. For example:
    Beanshell为脚本接口通过大量的方法提供了一个非常简单的short.hand机制。
    在一些脚本环境中,你可以实现特殊的方法调用(名字,参数)。
    invoke()方法被调用去处理没有定义的接口的方法。例如:
    mouseHandler = new MouseListener() {
    mousePressed( event ) {
    print("mouse button pressed");
    }
    invoke( method, args ) {
    print("Undefined method of MouseListener interface invoked:"
    + name +", with args: "+args
    );
    }
    };
    In the above example
    we have neglected to implement four of the five methods of the MouseListener interface.
    They will be handled by the invoke() method,
    which will simply print the name of the method and its arguments.
    However since mousePressed() is defined it will be called for the interface.
    在上面的例子中,我们已经疏忽实现MouseListener接口中的五个方法中的四个方法。
    他们将被invoke()方法处理,在这里这个方法仅仅简单的打印了方法的名字和参数。
    但是由于mousePressed()方法定义了,它将被这个接口调用。
    Here is a slightly more realistic example of where this comes in handy.
    Let's use the invoke() method
    to print the names of methods called via the ContentHandler interface of the Java SAX API,
    while parsing an XML document.
    这是一个轻微的实际的信手捻来的例子。
    我们使用invoke()方法通过Java的SAX API的环境处理接口打印被调用的方法名。
    import javax.xml.parsers.*;
    import org.xml.sax.InputSource;
    factory = SAXParserFactory.newInstance();
    saxParser = factory.newSAXParser();
    parser = saxParser.getXMLReader();
    parser.setContentHandler( this );
    invoke( name, args ) {
    print( name );
    }
    parser.parse( new InputSource(bsh.args[0]) );
    By running this scrīpt with the XML file as an argument,
    we can see which of the dozen or so methods of the SAX API
    are being exercised by the structure of the document,
    without having to write a stub for each of them.
    通过当成一个参数一样来运行XML文件的脚本,
    我们可以看到SAX API的一些方法可以通过文档的结构来演练。
    没有为他们中的每一个写一个存根。
    Tip:提示:
    You can use the invoke( name, args ) meta.method directly
    in your own scope or in the global scope as well,
    in which case you can handle arbitrary "unknown" method invocations yourself,
    perhaps to implement your own "virtual" commands.
    Try typing this on the command line:
    在你自己的作用域或者在全局的作用域中,你可以直接使用invoke(name,args)meta.method,
    在某种情况下你可以处理任意未知的方法,或许是去实现你自己的"虚拟"命令。
    尝试在你的命令行中定义这些:
    invoke(name,args) { print("Command: "+name+" invoked!"); }
    "run()" method in your bsh objects and make it the target of a Thread:
    "run()"方法在你的bsh对象中并且使它成为一个线程的对象:
    foo() {
    run() {
    // do work...
    }
    return this;
    }
    foo = foo();
    // Start two threads on foo.run() 通过foo.run()开始两个线程
    new Thread( foo ).start();
    new Thread( foo ).start();
    non.thread safe (e.g. access shared variables or objects) you can write multi.threaded scrīpts.
    Note:
    You can use the bg() "background" command to run an external scrīpt in a separate thread.
    See bg().
    没有线程的情况下很安全,你可以写多线程脚本。
    注意:
    你可以使用bg()"background"命令,在一个单独的线程中运行一个外部的脚本。
    请看bg().
     

  • Beanshell翻译8

    2008-09-02 20:19:05

    Beanshell翻译8

    http://user.qzone.qq.com/281696143/blog/1217472349   Ronger
    1.scrīpting Interfaces 脚本接口
    One of the most powerful features of BeanShell is the ability to scrīpt Java interfaces.
    This feature allows you to write scrīpts that serve as event handlers, listeners,
    and components of other Java APIs.
    It also makes calling scrīpted components from within your applications easier
    because they can be made to look just like any other Java object.
    在Beanshll中最强大的特性是脚本支持接口的能力。
    这个特性允许你写可以为时间处理,监听器,其它的Java组件服务的脚本。
    它还可以让你从你的应用程序中调用脚本组件变得容易,
    因为他们看起来和其它的Java对象一样。
    2.Anonymous Inner.Class Style 匿名的内部类样式
    One way to get a scrīpted component to implement a Java interface
    is by using the standard Java anonymous inner class syntax
    to construct a scrīpted object implementing the interface type. For example:
    取得一个实现了Java接口的脚本组件的方法,
    是使用标准的Java匿名类创建一个实现接口的脚本对象。例如:
    buttonHandler = new ActionListener() {
    actionPerformed( event ) {
    print(event);
    }
    };
    button = new JButton();
    button.addActionListener( buttonHandler );
    frame(button);
    In the above example we have created an object that implements the ActionListener interface
    and assigned it to a variable called buttonHandler.
    The buttonHandler object contains the scrīpted method actionPerformed(),
    which will be called to handle invocations of that method on the interface.
    在上面的例子中,我们创建一个实现ActionListener接口的对象,并且定义它为buttonHandler.
    buttonHandler对象包含脚本方法actionPerformed(),
    这个方法在处理事件的时候会被调用。
    Note that in the example we registered our scrīpted ActionListener
    with a JButton using its addActionListener() method.
    The JButton is, of course, a standard Swing component written in Java.
    It has no knowledge that when it invokes the buttonHandler's actionPerformed() method
    it will actually be causing the BeanShell interpreter to run a scrīpt to evaluate the outcome.
    现在在这个例子中,我们通过addActionListener()方法给按钮注册脚本监听器。
    这个按钮,当然应该是,用Java写成的一个标准的Swing组件。
    它还不知道,当它调用buttonHandler的actionPerformed()方法时,
    它将完全的依靠Beanshll解释器运行脚本得到结果。
    To generalize beyond this example a bit .
    scrīpted interfaces work by looking for scrīpted methods to implement the methods of the interface.
    A Java method invocation on a scrīpt that implements an interface
    causes BeanShell to look for a corresponding scrīpted method with a matching signature
    (name and argument types). BeanShell then invokes the method,
    passing along the arguments and passing back any return value.
    When BeanShell runs in the same Java VM as the rest of the code,
    you can freely pass "live" Java objects as arguments and return values,
    working with them dynamically in your scrīpts; the integration can be seamless.
    See also the dragText example.
    超出这个例子进行概括。脚本接口通过寻找实现接口的函数来工作。
    一个实现接口的脚本函数,使Beanshell寻找一个相应的脚本函数(通过名字和参数类型匹配)。
    Beanshell于是可以调用这个方法,通过参数,得到返回值。
    当Beanshell和其它的代码一起在同一个Java虚拟机中工作时,你可以自由的使用存活的
    Java对象作为参数和返回值,在你的脚本中和他们一起动态的工作。
    也可以看看dratText这个例子。

    3.'this' references as Interface Types 用在接口类型中的'this'引用
    The anonymous inner class style syntax which
    we just discussed allows you to explicitly create an object of a specified interface type,
    just as you would in Java. But BeanShell is more flexible than that.
    In fact, within your BeanShell scrīpts,
    any 'this' type scrīpt reference can automatically implement any interface type, as needed.
    This means that you can simply use a 'this' reference to your scrīpt or a scrīpted object anywhere that
    you would use the interface type.
    BeanShell will automatically "cast" it to the correct type
    and perform the method delegation for you.
    匿名的内部类语法,我们可以允许你显式的定义一个指定接口类型的对象,就像在Java中一样。
    但是Beanshell可以比这个更加灵活。
    实际上,通过你的Beanshell脚本,需要的时候,
    一些'this'类型的脚本引用可以动态的实现一些接口类型。
    这些的意思就是,你可以简单的在你的脚本中使用一个'this'引用,
    或者简单的使用'this'引用指向一个脚本对象,
    这个对象是可以使用接口类型的用在任何地方的对象。
    Beanshell将自动的将它转换成正确的类型并且执行相应的函数。
    For example, we could scrīpt an event handler for our button even more simply using just a global method,
    like this:
    例如,通过很简单的使用一个全局方法,我们可以为我们的按钮定义一个事件处理,像下面这样:
    actionPerformed( event ) {
    print( event );
    }
    button = new JButton("Foo!");
    button.addActionListener( this );
    frame( button );
    Here, instead of making a scrīpted object to hold our actionPerformed() method
    we have simply placed the method in the current context (the global scope)
    and told BeanShell to look there for the method.
    在这儿,我们不是使用一个脚本对象保存actionPerformed()方法,
    我们是简单的将这个方法放在当前的环境中(全局作用域),并且告诉Beanshell去哪儿寻找这个方法。
    Just as before, when ActionEventsare fired by the button,
    your actionPerformed() method will be invoked.
    The BeanShell 'this' reference to our scrīpt implements the interface
    and directs method invocations to the appropriately named method, if it exists.
    就像以前一样,当ActionEventsare被按钮激发,你的actionPerformed()方法将被调用。
    Beanshell中脚本的'this'引用实现了接口,并且引导程序找到存在的适合的方法。
    Note: 注意:
    If you want to have some fun,
    try entering the previous example interactively in a shell or on the command line.
    You'll see that you can then redefine actionPerformed() as often as you like
    by simply entering the method again.
    Each button press will find the current version in your shell. In a sense,
    you are working inside a dynamic Java object that you are creating and modifying as you type.
    Neat, huh? Be the Bean! Of course,
    you don't have to define all of your interface methods globally.
    You can create references in any scope, as we discussed in "scrīpting Objects".
    For example, the following code creates a scrīpted message button object
    which displays a message when its pushed.
    The scrīpted object holds its own actionPerformed() method,
    along with a variable to hold the Frame used for the GUI:
    如果你想有趣一些,尝试将上面的例子中的代码顺序的输入在shell或者命令行上。
    你可以看到,你可以以你喜欢的方式通过简单的再次输入函数来重新定义actionPerformed()函数。
    每一个按钮的点击都会在你的shell中寻找到当前的版本。
    感觉上,你在一个自己创建和定义的动态Java对象内部工作。
    当然,在全局作用域中,你不用定义接口中的所有方法。
    你可以在一些作用域中创建引用,就像我们在"脚本对象"中讨论的一样。
    例如,下面的代码创建了一个脚本消息按钮对象,当这个按钮被点击的时候会显示消息。
    这个脚本对象保存它自己的actionPerformed()方法,同时通过一个变量保存用来GUI中的Frame.
    messageButton( message ) {
    JButton button = new JButton("Press Me");
    button.addActionListener( this );
    JFrame frame = frame( button );
    actionPerformed( e ) {
    print( message );
    frame.setVisible(false);
    }
    }
    messageButton("Hey you!");
    messageButton("Another message...");
    The above example creates two buttons, with separate messages.
    Each button prints its message when pushed and then dismisses itself.
    The buttons are created by separate calls to the messageButton() method,
    so each will have its own method context, separate local variables,
    and a separate instance of the ActionListener interface handler.
    Each registers itself (its own method context) as the ActionListener for its button,
    using its own 'this' reference.
    上面的例子中创建了两个按钮,它们会弹出不同的信息。
    当点击按钮并且释放它,每个按钮都会打印它的信息。
    这两个按钮是分别被messageButton()方法创建的,所以每一个都有它自己的方法环境,
    不同的本地变量,和不同的ActionListener接口处理实例。
    每一个都为了它的按钮当做ActionListener一样来注册自己,使用它自己的'this'引用。
    In this example all of the "action" is contained in messageButton() method context.
    It serves as a scrīpted object that implements the interface and also holds some state,
    the frame variable, which is used to dismiss the GUI.
    More generally however, as we saw in the "scrīpting Objects" section,
    we could have returned the 'this' reference to the caller,
    allowing it to work with our messageButton object in other ways.
    在这个例子中,所有的"action"都被包含在messageButton()方法环境中。
    它为实现接口和保存状态的脚本对象服务,frame变量,用来让GUI画面消失。
    更多的,就像我们在"脚本对象"章节中看到在,
    我们可以返回'this'引用给调用者,允许它和我们的messageButton对象以其它的方式一起工作。
     

  • Beanshell翻译7

    2008-09-02 20:17:53

    Beanshell翻译7

    http://user.qzone.qq.com/281696143/blog/1217322665  Ronger
    1.The 'this' reference 'this'引用
    As in most languages,
    an executing method in BeanShell has its own "local" scope that holds argument
    (parameter) variables and locally declared variables.
    For example, in the following code segment any
    variables that we might use within the foo() method will normally only be visible within the scope of foo()
    and for the lifetime of one particular foo() method invocation:
    就像大多数的语言一样,在Beanshell中一个生效的方法有它自己的本地作用域,
    这个作用域包括参数变量和本地定义变量。
    例如,在下面的代码片段中,在foo()方法中用到的一些变量将仅仅在foo()方法内可见。
    // Define the foo() method: 定义foo()方法
    foo() {
    int bar = 42;
    print( bar );
    }
    // Invoke the foo() method: 调用foo()方法
    foo(); // prints 42
    print( bar ); // Error, bar is undefined here 错误,在这里bar没有定义
    In the above, the bar variable is local to foo() and therefore not available outside of the method invocation .
    it is thrown away when the method exits, just like a standard Java local variable.
    在上面,bar变量是foo()中的本地变量,所以在方法外面不可用。
    当方法退出的时候,它会被抛弃,就像标准语法中的本地变量一样。
    Now comes the twist .
    In BeanShell you have the option to "hang on" to the scope of a method invocation
    after exiting the method by referring to the special 'this' reference.
    As in Java, 'this' refers to the current object context.
    The only difference is that in this case the context is associated with the method
    and not a class instance.
    By saving the 'this' reference after the method returns,
    you can continue to refer to variables defined within the method,
    using the standard Java "." notation:
    现在来看看这个用法。在Beanshll中,在推出函数之后,通过'this'引用
    ,你可以选择挂在函数的作用域中。就像在Java中一样,'this'指向当前环境对象。
    唯一的区别是,在这个例子中,环境是和这个方法联系起来了,而不是一个类实例。
    在函数返回之后,通过保存'this'引用,使用标准的Java中的'.'符号,
    你可以继续方法定义在这个函数中的对象。
    foo() {
    int bar = 42;
    return this;
    }
    fooObject = foo();
    print( fooObject.bar ); // prints 42!
    In the above, the value returned by the foo() method (the 'this' reference)
    can be thought of as an instance of a "foo" object.
    Each foo() method invocation effectively creates a new object;
    foo() is now not just a method, but a kind of object constructor.
    In the above case our foo object is not so much an object,
    but really more of a structure.
    It contains variables (bar) but no "behavīor".
    The next twist that we'll introduce is that BeanShell methods are also allowed to
    contain other methods:
    在上面的例子中,通过foo()函数返回的值('this'引用)可以理解为一个'foo'对象的实例。
    每一个foo()函数马上创建为一个新的对象;foo()现在不仅是一个函数,而是一个对象的构造函数。
    在上面的例子中,我们的foo对象不是一个对象,实际上是一个结构。
    它包含了变量bar但是没有行为。
    下面的用法中,我们将介绍,Beanshll函数也允许包含其它的函数:
    foo() {
    bar() {
    ...
    }
    }
    scrīpted methods may define any number of nested methods in this way,
    to an arbitrary depth. The methods are "local" to the method invocation.
    用这种方法,脚本函数可以定义任意深度的内置函数,这些内置函数都是本地的。
    Statements and expressions within the enclosing BeanShell method can call their "local" methods just like any
    other method.
    (Locally declared methods override outer.more methods like local variables hide instance
    variables in Java.)
    The enclosed methods are not directly visible outside of their enclosing method.
    However, as you might expect, we can invoke them as we would on a Java object,
    through an appropriate object reference:
    在函数中的申明和表达式可以访问他们的本地函数。
    (本地函数覆盖外部函数就像本地变量覆盖Java中的实例变量一样)。
    在函数的外面,内部函数是不可见的。
    但是,就像你期望的一样,我们可以通过适当的对象引用调用它们,就像在Java中一样。
    foo() {
    int a = 42;
    bar() {
    print("The bar is open!");
    }
    bar();
    return this;
    }
    // Construct the foo object 构造foo对象
    fooObject = foo(); // prints "the bar is open!" 打印"the bar is open!"
    // Print a variable of the foo object 打印foo对象中的一个变量
    print ( fooObject.a ) // 42
    // Invoke a method on the foo object 调用foo对象的函数
    fooObject.bar(); // prints "the bar is open!" 打印"the bar is open!"
    scrīpted Objects 脚本对象
    method. i.e. there are no block.local methods. For example:
    在一个程序块中没有本地函数。例如:
    foo() {
    bar() { }
    if ( true ) {
    bar2() { }
    }
    return this;
    }
    2.Scope Modifiers 作用域修改
    Now that we've seen how methods can be nested and treated as objects,
    we can revisit the topic of variable scope and scope modifiers.
    现在我们可以看到,函数如何变成内置的和怎样理解成一个对象,
    我们可以用新的方法来访问变量。
    3.'this', 'super', and 'global' 'this','super',和'global'
    In the "scrīpted Methods" section we described the use of 'super' to refer to a method's parent scope
    (the scope in which the method is defined).
    And in the previous section we talked about super's brother 'this',
    which refers to the current method's scope,
    allowing us to think of a method scope as an object.
    Now we can see how these concepts are related.
    Any method scope, and indeed the 'global' scope, can be thought as an object context.
    A scrīpted object can be thought of as encapsulated in a parent scope that determines its
    "environment" . its inherited variables and methods.
    在脚本函数这个章节中,我们使用'super'指向函数的父作用域.
    并且在前一个章节中,我们谈到了'super'的兄弟'this',
    'this'指向当前的方法作用域,允许我们将一个函数理解为一个对象。
    现在我们可以看到这种观点怎样联系起来的.
    一些方法的作用域,当然是'global'的作用域,可以理解为一个对象环境。
    一个脚本对象可以理解为它的父作用域中的一个独立个体,在父作用域中包括变量和函数。
    The references 'this', 'super', and 'global' are really the same kind of reference .
    references to BeanShell method contexts, which can be used as scrīpted objects.
    From here on We'll refer to 'this', 'super', 'global',
    and any other reference to a scrīpted object context in general as a 'this' type reference.
    'this','super'和'global'是同样类型的引用。指向Beanshell中函数的引用可以用在脚本对象中。
    从这里,我们可以指向'this','super','global',
    并且其它的常用的指向脚本对象的引用可以当成'this'类型的引用。
    Note: 注意:
    If you print a 'this' type reference you'll see what it refers to:
    如果你打印一个'this'类型引用,你将可以看到它指向的是什么:
    BeanShell 1.3 . by Pat Niemeyer (pat@pat.net)
    bsh % print( this );
    'this' reference (XThis) to Bsh object: global 'this'引用指向Bsh对象:global
    bsh % foo() { print(this); print(super); }
    bsh % foo();
    'this' reference (XThis) to Bsh object: foo 'this'引用指向Bsh对象:foo
    'this' reference (XThis) to Bsh object: global 'this'引用指向Bsh对象:global
    The above note shows that the foo() method's 'this' reference is local (named 'foo')
    and that it's parent is the global scope;
    the same scope in which foo is defined.
    上面的代码段表明了,foo()函数的'this'引用是本地的(名字为'foo'),并且它的父亲是global作用域;
    global是foo被定义的作用域。
    4.'global'
    The scope modifier 'global' allows you to always refer to the top.most scope.
    In the previous note you can see that the top level scrīpt context is called "global"
    and that it appears again as the 'super' of our foo() method.
    The global context is always the top scope of the scrīpt.
    It is the global namespace of the current interpreter.
    Referring to 'super' from the top scope simply returns the same 'global' again.
    'global'允许你指向最顶层的作用域。
    在上面的例子中,你可以看到,最顶层的脚本环境叫'global',并且以'super'出现在foo()函数中.
    global环境常常是脚本的顶层作用域,它是当前解释器的global名字空间。
    从上层作用域指向'super'也是很简单的返回'global'.
    global.foo = 42;
    Global variables are not special in any way.
    Their visibility derives simply from the fact that they are in the topmost scope.
    However, for those who do not like the idea of qualifying anything with "global".
    You can always use a more object oriented approach like the following.
    Global变量一点也不特殊。它的可见性是简单的来自这个事实,它们是在最顶层的作用域中。
    但是,对于那些不喜欢使用'global'的人来说,你也可以像下面一样使用一些对象来表示。
    // Create a top level object to hold some state 创建一个最顶层的对象来保存状态
    dataholder = object();
    foo() {
    ...
    bar() {
    dataholder.value = 42;
    }
    bar();
    print( dataholder.value );
    }
    }
    In the above example we used a global object to hold some state,
    rather than putting the 'value' variable directly in the global scope.
    在上面的例子中,我们使用一个global对象去保存状态,比将变量的值直接放在global作用域中更恰当。
    Tip: 提示
    In the above example we used the BeanShell object() command
    to create an "empty" BeanShell scrīpted object context in which to hold some data.
    The object() command is just a standard empty method named object() that returns 'this'.
    The variable 'dataholder' above is a 'this' type reference and has all of the
    properties of any other BeanShell object scope.
    在上面的例子中,我们使用Beanshll中的object()命令,创建一个可以保存数据的空的Beanshell脚本对象。
    object()命令仅仅是一个标准的返回'this'的空方法。
    上面的变量'dataholder'是一个'this'类型的引用并且有Beanshll对象作用域的所有属性。
    5.Synchronized Methods Revisited 同步的方法更新
    Now that we have covered the meaning of 'this' and 'super' with respect to BeanShell methods,
    we can define the meaning of the 'synchronized' modifier for BeanShell methods.
    Synchronized BeanShell methods behave as if
    they were in a common class by synchronizing on their common 'super' reference object.
    For example, in the four cases in the following example,
    synchronization occurs on the same Java object.
    That object is the 'this' type reference of the global scope
    (a Beanshell object of type bsh.This):
    现在我们可以通过'this'和'super'来表示Beanshell函数,我们在Beanshell函数上面加上同步修改。
    同步Beanshell函数行为就像在它们的'super'引用上加同步一样。
    例如,在下面的四个例子中,同步出现在同一个Java对象上,
    这个对象就是global作用域上面的'this'类型引用(一个类型为bsh.This的Beanshell对象)
    print( this );
    // 'this' reference (XThis) to Bsh object: global 表示Bsh对象(global)的'this'引用
    // The following cases all synchronize on the same lock 下面的例子都是相同级别的同步
    synchronized ( this ) { } // synchronized block 同步程序块
    synchronized int foo () { } // synchronized method foo() 同步函数foo()
    synchronized int bar () { } // synchronized method bar() 同步函数bar()
    int gee() {
    synchronized( super ) { } // synchronized blockinside gee() 同步gee()中的程序块
    }
     

  • Beanshell翻译6

    2008-09-02 20:16:47

    Beanshell翻译6

    http://user.qzone.qq.com/281696143/blog/1217311291  Ronger
    1.Document Friendly Entities 友好的文档
    BeanShell supports special overloaded text forms of all common operators to make it easier to embed
    BeanShell scrīpts inside other kinds of documents (e.g XML).
    Beanshell支持文档类型,所有普通操作者容易嵌入的文档类型。
    Beanshell脚本也可以放在其它的文档里面(比如XML).
    scrīpted Methods 脚本函数
    You can define methods in BeanShell, just as they would appear in Java:
    你可以像在Java中一样,在Beanshell中定义函数:
    int addTwoNumbers( int a, int b ) {
    return a + b;
    }
    And you can use them in your scrīpts just as you would any Java method or "built.in" BeanShell command:
    并且你可以在你的脚本中使用他们,就像你使用Java中的方法一样
    sum = addTwoNumbers( 5, 7 );
    Just as BeanShell variables may be dynamically typed,
    methods may have dynamic argument and return types.
    We could, for example, have declared our add() method above like so:
    就像Beanshell变量可以动态的定义类型一样,方法也可以有动态类型的参数和返回值。
    我们可以,像这样的定义上面的方法add():
    add( a, b ) {
    return a + b;
    }
    In this case, BeanShell would dynamically determine the types when the method is called and attempt to "do
    the right thing":
    在这个例子中,当这个函数被调用的时候,Beanshell可以动态的决定类型并且尝试执行正确的程序。
    foo = add(1, 2);
    print( foo ); // 3
    foo = add("Oh", " baby");
    print( foo ); // Oh baby
    In the first case Java performed arithmetic addition on the integers 1 and 2.
    (By the way, if we had passed in
    numbers of other types BeanShell would have performed the appropriate numeric promotion
    and returned the correct Java primitive type.)
    In the second case BeanShell performed the usual string concatenation for String
    types and returned a String object.
    This example is a bit extreme,
    as there are no other overloaded operators like string concatenation in Java.
    But it serves to emphasize that BeanShell methods can work with loose types.
    在第一个例子中Java执行整数1和2的算术加法。(通过这种方法,如果我们输入其它类型的
    数字,Beanshell将会执行适当的程序并且返回正确的Java基础类型。)。在第二个例子中,
    Beanshell执行Java中的字符串连接并且返回一个字符串对象。
    这个例子有一些极端,就像在Java中没有连接字符串的操作符一样。
    但是这个强调了Beanshell的方法可以使用宽松类型定义。
    Methods with unspecified return types may return any type of object (as in the previous example).
    Alternatively they may also simply issue a "return;"
    without a value, in which case the effective type of the method is "void" (no type).
    In either case, the return statement is optional.
    If the method does not perform an explicit "return" statement
    and the return type is not explicitly set to void,
    the value of the last statement or expression in the method body becomes the return value
    (and must adhere to any declared return typing).
    没有定义返回类型的方法可以返回任何的对象类型(就像前面的例子中)。
    也可以没有返回值而仅仅简单的返回“return”,就是返回类型为void的这种情况
    在任何一个例子中,返回表达式是可选的。
    如果函数没有定义一个显式的"return"表达式并且返回类型没有显式的定义为void,
    函数中的最后一个定义或表达式变成返回值(并且附着在一些定义的返回类型上面)。
    2.Method Modifiers and 'throws' Clauses 函数调用和"thros"语句
    The standard Java modifiers may be applied to methods:
    private / protected / public, synchronized, final, native, abstract, and static.
    The synchronized modifier is the only modifier currently implemented.
    The others are ignored.
    The 'throws' clause of methods is checked for valid class type names,
    but is not otherwise enforced.
    Synchronized methods are synchronized on the object representing the method's common parent scope,
    so they behave like Java methods contained in a class.
    We will return to this topic after discussing scrīpted
    标准的Java定义可以应用在函数上:
    private / protected / public, synchronized, final, native, abstract, and static.
    同步修改是目前已经实现的修改,其它的还没有。
    带"throws"语句的方法会检查有效类名,但是不会被另外强迫。
    同步方法是同步的,在本对象的父亲对象的作用域中,他们就像Java方法被包含在一个类中一样。
    再讨论了脚本之后,我们将再回到这个观点。
    3.scrīpted Methods 脚本函数
    objects and "closures".
    // foo() and bar() are synchronized as if they were in a common class
    //如果是在一个普通的类中,foo()和bar()是同步的。
    synchronized foo() { }
    synchronized bar() { }
    Scoping of Variables and Methods 变量和函数的作用域
    As in Java, a method can refer to the values of variables and method names from the enclosing scope
    (in Java the "enclosing scope" would be a class). For example:
    就像在Java中一样,一个方法可以指向变量和函数的值(在Java中"封闭的作用域"可以是一个类)。示例:
    a = 1;
    anotherMethod() { ... }
    foo() {
    print( a );
    a = a+1;
    anotherMethod();
    }
    // invoke foo() 调用foo()
    foo(); // prints 1
    print( a ); // prints 2
    Variables and methods are "inherited" from the parent scope in the usual way.
    In the example above there are just two levels of scope:
    the top or "global" scope and the scope of the method foo().
    Later we'll talk about scrīpting objects in BeanShell
    and see that there can be arbitrary levels of scoping involved.
    But the rules will be the same.
    变量和方法在通常的情况下是继承父类的作用域。
    在上面的例子中,仅仅存在两种作用域:
    全局作用域和方法foo()中的作用域。稍候我们谈谈在Beanshell中的脚本对象,
    并且可以看到任意级别的作用域。但是这个规则是一样的。
    As in Java, a typed variable is not visible outside the scope in which it is declared.
    So declaring a variable with a type is a way to limit its scope or make a local variable.
    In BeanShell using an untyped or "loosely" typed variable is also equivalent to declaring a local variable.
    That is, if you use a variable that has not been defined elsewhere,
    it defaults to the local scope:
    就像在Java中一样,一个有类型的变量在作用域的外面是不可见的。
    所以定义一个有类型的变量是限制它的作用域或者定义一个本地变量的方法。
    在Beanshll中使用一个宽松类型的变量也等价于定义一个本地变量。
    那也就是,如果你在使用一个在其它地方没有定义的变量,它默认是本地变量:
    a = 1;
    foo() {
    a = a + 1; // a is defined in parent scope a有父亲作用域。
    b = 3; // undefined, defaults local scope 没有定义,默认本地作用域
    int c = 4; // declared local scope 定义本地变量
    }
    // invoke foo()
    print( a ); // prints 2
    print( b ); // ERROR! b undefined 错误!b没有定义
    print( c ); // ERROR! c undefined 错误!c没有定义
    In the above example the variable 'a' is declared in the global scope.
    When its value is read and assigned inside of foo() the global value of 'a' will be affected.
    The variable 'b' is a usage of an untyped variable.
    Since 'b' has not been declared or assigned a value in any enclosing scope,
    it becomes a local variable 'b' in the scope of foo.
    The variable 'c' is explicitly declared (with a type) in the scope of foo() and is therefore,
    of course, local to foo().
    在上面的例子中,变量"a"是定义的全局变量。
    在foo()中全局变量"a"的值将被改变。
    变量"b"是一个没有定义类型的变量,"b"在一个封闭的作用域中没有定义类型,
    它将变成foo中的一个本地变量。
    在foo()中变量"c"被显式定义为一个有类型的变量,所以它是一个本地变量。
    Later we'll see that BeanShell allows arbitrary nesting of methods.
    If we were to declare another method
    inside of foo() it could see all of these variables (a, b, and c)
    as it is also in the scope of foo().
    稍后我们将看到Beanshll允许任意的内置函数,
    如果我们在foo()中定义另一个函数,它将可以调用所有的这些变量(a,b和c),
    就像在foo()中一样。
    4.Scoping of Loosely Typed Variables 宽松类型变量的作用域
    As in Java, declaring a variable with a type will always make it local.
    Even if the variable exists in the outer scope,
    it will be hidden by the local variable declaration.
    But what of loosely typed variables? As we've seen,
    untyped variable usage looks just like an ordinary Java assignment.
    What do we do if we want to make a local variable with the same name as a global one?
    One answer would be to resort to declaring the variable with a type.
    But if we wish to continue working with loosely typed variables in this case we have two options:
    We can explicitly declare a loosely typed variable with the BeanShell 'var' type.
    Or we can simply qualify our assignment with the 'this.' qualifier.
    就像在Java中一样,通常定义一个有类型的本地变量。
    如果这个变量存在外面的作用域中,它将被本地定义的变量隐藏。
    但是什么是宽松类型变量呢?就像我们看到的一样,
    宽松类型变量使用看起来像一个普通Java定义。
    如果我们想让一个本地变量和一个全局变量有同样的名字,我们应该做什么?
    答案之一就是你应该将这个变量定义为有类型的变量。
    但是如果我们希望在这种情况下定义宽松类型变量,我们将有两种选择:
    我们可以显式的定义一个Beanshll中的宽松类型"var".
    或者我们可以简单的将变量定义在this对象中。
    If you wish to, you can explicitly declare an untyped variable (making it local) using the special type 'var'. e.g.
    如果你想的话,你可以使用"var"显式的定义一个没有类型的变量:
    foo() {
    var a = 1;
    }
    foo();
    print( a ); // ERROR! a is undefined! 错误!a没有定义
    'var' is a magic type in BeanShell that represents a loose (untyped) variable.
    The default value of a variable declared with 'var' is null.
    Alternately, you can use the scope modifier 'this' to explicitly qualify the variable assignment and make it
    local.
    'var'是一个神奇的类型,是Beanshll中用来定义宽松类型变量。
    定义为'var'类型的变量的默认值为null.
    你也可以使用'this'显式的定义一个变量并且使它本地化。
    foo() {
    this.a = 1;
    }
    foo();
    print( a ); // ERROR! a is undefined! 错误!a没有定义
    In this example we used the modifier 'this' to qualify an untyped variable's scope and make it local.
    We will
    explain 'this' and what it means in BeanShell scrīpted methods in the next section on scrīpted Objects.
    在这个例子中,我们使用'this'显式的定义一个变量并且使它本地化。
    在下面的章节中,我们将解释'this',在Beanshell脚本函数中它的含义是什么。
    5.Scope Modifier: 'super' 作用域修改:'super'
    Within a method, it is possible to explicitly qualify a variable or method reference with the identifier 'super' in
    order to refer to a variable or method defined in an enclosing scope
    (the scope in which the method is defined
    or "higher"). e.g.
    在一个函数中,为了调用一个封闭的作用域(一个更高的作用域)中的变量或者函数,
    可以显式的定义一个变量或者函数指向'super'
    int a = 42;
    foo() {
    int a = 97;
    print( a );
    print( super.a );
    }
    foo(); // prints 97, 42
    Scoping of Loosely Typed Variables 宽松类型变量的作用域
    As in Java, the 'super' modifiers tells the scoping to begin its search for the variable or method in the parent
    scope.
    In the case above, the variable 'a' by default refers to the variable in the local scope.
    By qualifying 'a'
    with 'super' we can refer to the variable 'a' in the global scope (the "topmost" scope).
    So, we've seen that 'super' can be used to refer to the method's parent context.
    We'll see in the next section
    how 'this' and 'super' are used in scrīpting Objects in BeanShell.
    就像在Java中一样,'super'的作用就是在更高的作用域搜索变量或者函数。
    在上面的例子中,变量'a'指向一个本地是一个本地变量(代码print(a)).
    通过'super'来定义变量'a',我们可以指向全局的变量'a'(最高的作用域).
    于是,我们可以看到,'super'可以用作指向函数的外部环境。
    在下面的章节中,我们也可以看到在Beanshll的脚本对象中如何应用'this'和'super'.
    6.scrīpted Objects 脚本对象
    Many people who use BeanShell use it to write scrīpts that work with existing Java classes and APIs,
    or perform other kinds of dynamic activities for their own applications at run.
    time without the aid of a compiler.
    Often this means writing relatively unstructured code .
    for example, a sequence of method invocations or loops,
    all contained in a single scrīpt file or eval() statement.
    In the previous section we saw that BeanShell is also capable of scrīpting methods,
    just like Java.
    Creating methods and new BeanShell commands (which are
    just methods in their own files)
    is the natural progression of organizing your scrīpts into re.usable and
    maintainable components.
    许多人使用Beanshell来写和Java类和API一起工作的脚本。
    或者在他们自己的在运行的应用程序中执行其它种类的动态活动,并且不需要编译。
    这个意思常常是说写非结构的代码。
    例如,一序列方法调用或循环,所有包含在单脚本文件中或者执行表达式。
    在上面的章节中,我们看到也可以使用脚本函数,就像Java中一样。
    创建函数和新Beanshell命令(正好函数在他们自己的文件中)
    是很自然的进展,并且可以组织您的脚本到re.usable和变成可维护的组件。
    Beyond methods and structured programming lie, of course,
    objects and the full breadth of object oriented programming.
    In Java objects are the products of classes.
    While BeanShell is compatible with standard Java syntax for statements,
    expressions, and methods, you can't yet scrīpt new Java classes within BeanShell.
    Instead, BeanShell allows you to scrīpt objects as "method closures",
    similar to the way it is done in Perl 5.x,
    Javascrīpt, and other object.capable scrīpting languages.
    This style of scrīpting objects (which we'll describe
    momentarily) is simple and flows very naturally from the style of scrīpting methods.
    The syntax, as you'll see,
    is a straightforward extension of the standard Java concept of referring to an object with a 'this' reference.
    超越了方法和结构化编程,对象可以引导编程,在Java中对象是类型的实例。
    Beanshell和标准的Java语法是一致的,在语句申明,表达式和方法方面,
    但是你不可以在Beanshll中定义新的类型。可以这样来替代,
    Beanshell允许你类似于"method closures"一样的定义对象,
    和Perl5.x,Javascrīpt等支持对象的脚本语言中的实现相似。
    这种样式的脚本对象很简单并且用对象来表示脚本函数很自然。
    你看到的这种语法,是一种通过this引用指向一个对象的标准Java概念的扩展。
    Note: 注意:
    In standard Java, a method inside of an object (an instance method) may refer to the enclosing
    object using the special variable 'this'. For example:
    在标准的Java中,一个对象中的方法通过使用变量'this'可以指向装入的对象。例如:
    // MyClass.java
    MyClass {
    Object getObject() {
    return this; // return a reference to our object 返回一个引用
    }
    }
    In the example above, the getObject() method of MyClass returns a reference to its own object
    instance (an instance of the MyClass object) using 'this'.
    在上面的例子中,MyClass中的getObject()方法使用'this'返回一个引用给它自己的对象实例。 

  • Beanshell翻译5

    2008-09-02 20:14:48

    Beanshell翻译5

    http://user.qzone.qq.com/281696143/blog/1216972587  Ronger
    1.In BeanShell you may access JavaBean properties as if they were fields:
    在Beanshell中你可以访问JavaBean中的属性:
    button = new java.awt.Button();
    button.label = "my button"; // Equivalent to等价于: b.setLabel("my button");
    print( button.label ); // Equivalent to 等价于 print( b.getLabel() ); 等价于
    JavaBean properties are simply pairs of "setter" and "getter" methods
    that adhere to a naming convention.
    In the above example BeanShell located a "setter" method with the name "setLabel()"
    and used it to assign the string value.
    It then found the method named getLabel() to retrieve the value.
    JavaBean的属性是一类简单的"setter"和"getter"方法。在上面的例子中,Beanshell通过名字
    "setLabel()"来定为一个"setter"方法,并且通过它来赋值,通过getLable()方法取值。
    Boolean properties may optionally use the syntax "is" for their "getter". e.g.
    Boolean属性可以使用"is"来代替"getter"
    Float f = new Float(42f);
    print( f.infinite ); // Equivalent to 等价于 print( f.isInfinite() ); // false
    If there is any ambiguity with an actual Java field name of the object
    (e.g. label in the above example) then the
    actual field name takes precedence.
    If you wish to avoid any ambiguity BeanShell provides an additional,
    uniform syntax for accessing both Java Bean properties and Hashtable or Map entries.
    You may use the "{}" curly brace construct
    with a String identifier as a qualifier on any variable of the appropriate type:
    如果和实际的对象的属性名字有不明确的地方(比如上面的例子中的label),
    将优先考虑实际的属性名称。如果你希望避免Beanshell中不明确的地方。
    Hashtable,Map和JavaBean属性都可以用使用。
    你可以使用"{}"构造一个字符串来限定适当类型的变量。
    b = new java.awt.Button();
    b{"label"} = "my button"; // Equivalent to 等价于: b.setLabel("my button");
    h = new Hashtable();
    h{"foo"} = "bar"; // Equivalent to等价于: h.put("foo", "bar");
    Where the java.util.Collections API is available, Maps are also supported.
    java.util.Collection已经导入,Maps也是可以支持的。
    2.Enhanced 'for' Loop 支持循环
    BeanShell supports the Java 1.5 style enhanced for.loop for iterating over collections and array types.
    (Note that you do not have to be running Java 1.5 to use this feature).
    Beanshell支持Java1.5以上的for.loop功能,用来遍历集合和数组。
    (注意你不能通过运行Java1.5来使用这个特性)
    List foo = getSomeList();
    for ( untypedElement : foo )
    print( untypedElement );
    for ( Object typedElement: foo )
    print( typedElement );
    int [] array = new int [] { 1, 2, 3 };
    for( i : array )
    print(i);
    for( char c : "a string" )
    print( c );
    Supported iterable types include all the obvious things. 支持包含下面这些集合类型
    · JDK 1.1+ . (no collections): Enumeration, arrays, Vector, String, StringBuffer
    Convenience Syntax 便利的语法
    · JDK 1.2+ . (w/collections): Collections, Iterator
    See also the BshIterator API which supports the ehanced for.loop and allows iteration over these types using
    the dynamically loaded BeanShell Collection manager.
    也可以看到BshIterator API,支持for.loop并且通过使用动态加载Beanshell集合管理器来允许遍历更多的类型。
    3.Switch Statements 选择语句
    In BeanShell, the switch statement may be used not only with numeric types but with objects.
    For example,
    you may switch on Dates and Strings which are compared for equality with their equals() methods:
    在Beanshell中,选择语句不仅可以用在数字类型中,也可以用于对象。
    比如,你可以通过equals()方法来比较Dates和Strings类型。
    dateobj = new Date();
    switch( dateobj )
    {
    case newYears:
    break;
    case christmas:
    break;
    default:
    }
    4.Auto Boxing and Unboxing 自动包装和拆包
    "Boxing" and "Unboxing" are the terms used to describe automatically wrapping a primitive type in a wrapper
    class and unwrapping it as necessary.
    Boxing is a feature of Java (SDK1.5) and has been supported in
    BeanShell for many years.
    BeanShell supports boxing and unboxing of primitive types. For example:
    "包装"和"拆包"是一种技术,当需要的时候,这种技术是用来自动包装基础类型和拆包的。
    包装是一个Java1.5的特性并且Beanshell很多年前就可以支持这些。Beanshell支持
    基础类型的包装和拆包。例如:
    int i=5;
    Integer iw = new Integer(5);
    print( i * iw ); // 25
    Vector v = new Vector();
    v.put(1);
    int x = v.getFirstElement();
    Importing Classes and Packages 导入类和包
    In BeanShell as in Java, you can either refer to classes by their fully qualified names,
    or you can import one or more classes from a Java package.
    在Beanshll中就像和在Java中一样,你可以通过类的全名来导入一个类,
    或者你可以从一个包中导入一个或多个类。
    // Standard Java 标准Java
    import javax.xml.parsers.*;
    import mypackage.MyClass;
    In BeanShell import statements may appear anywhere, even inside a method,
    not just at the top of a file.
    In the event of a conflict, later imports take precedence over earlier ones.
    A somewhat experimental feature is the "super import".
    With it you may automatically import the entire classpath, like so:
    在Beanshll中导入一个申明可以用在任何地方,甚至在一个方法里面,
    而不仅仅是在一个文件的顶部。在冲突的时候,后导入的优先于前面导入的。
    一些新的特性是"super import"。通过它你可以自动的导入完整的类路径,像下面一样:
    5.Switch Statements 选择申明
    import *; import *;
    The first time you do this BeanShell will map out your entire classpath;
    so this is primarily intended for interactive use.
    Note that importing every class in your classpath can be time consuming.
    It can also result in a lot of ambiguities.
    Currently BeanShell will report an error when resolving an ambiguous import from
    mapping the entire classpath.
    You may disambiguate it by importing the class you intend.
    第一次你做这些,Beanshell将覆盖完整的类路径,所以这是主要的互动使用。
    注意在通过你的类路径来导入会很消耗时间。它也会导入不明确的类。
    当通过导入类路径而产生了一个不明确的导入时,Beanshell将产生一个错误。
    你可以通过导入你想要的类来明确它。
    Tip: 提示:
    The BeanShell which() command will use the classpath mapping capability to tell you
    where exactly in your classpath a specified class is located:
    Beanshell的which()命令将在类路径中寻找一个确切的类型的完整路径:
    bsh % which( java.lang.String );
    Jar: file:/usr/java/j2sdk1.4.0/jre/lib/rt.jar
    See "Class Path Management" for information about modifying the BeanShell classpath at run.
    time with the addClassPath() or setClassPath() commands.
    Also see "BeanShell Commands" for information about importing new BeanShell commands from the
    classpath.
    通过"Class Path Management"获得更多信息,在运行时修改Beanshell类路径,
    通过addClassPath()或者setClassPath()命令。
    也可以通过"Beanshell Commands"获得更多信息,从类路径中导入新的Beanshell命令。
    6.Default Imports 默认导入
    By default, common Java core and extension packages are imported for you.
    They are, in the order in which they are imported:
    通过默认导入,通用的Java核心和扩展包被导入进来。他们是以下的这些:
    · javax.swing.event
    · javax.swing
    · java.awt.event
    · java.awt
    · java.net
    · java.util
    · java.io
    · java.lang
    Two BeanShell package classes are also imported by default:
    两个Beanshll包中的类也被默认导入:
    · bsh.EvalError
    · bsh.Interpreter
    Finally, we should mention that BeanShell commands may be imported from the classpath.
    The default commands are imported in the following way:
    最后,我们会说起,Beanshell的命令可以从类路径中导入。默认的命令是从下面的路径导入的:
    importCommands("/bsh/commands");
    We will discuss how to import your own commands in a later section.
    我们将在后面的章节中讨论怎样导入你自己的命令。
    Tip: 提示:
    The classes java.awt.List and java.util.List are both imported by default.
    Because java.util.List is imported later, as part of the java.util package,
    it takes precedence. To access java.awt.List simply import it in,
    or the java.awt package again your scrīpt. Later imports take precedence.
    类型java.awt.List和java.util.List都是通过默认导入的。因为java.util.List
    (作为java.util包中的一部分)是后导入的,所以它有更高的优先级。
     

  • Beanshell翻译4

    2008-09-02 20:13:29

    Beanshell翻译4

    http://user.qzone.qq.com/281696143/blog/1216273325  Ronger
    1.Basic Syntax 基本语法
    BeanShell is, foremost, a Java interpreter.
    So you probably already know most of what you need to start scrīpting with BeanShell.
    This section describes specifically what portion of the Java language BeanShell
    interprets and how BeanShell extends it or "loosens" it to be more scrīpting language like.
    Beanshell更多的,是一个Java解释者。于是你已经大概知道了开始脚本语言Beanshell时你需要什么。
    这一部分描述Beanshell解释者的一部分和Beanshell是怎样比普通的脚本语言更好的扩展它。
    2.Standard Java Syntax 标准Java语法
    In a BeanShell scrīpt (and on the command line) you can type normal Java statements and expressions and
    display the results.
    Statements and expressions are the kinds of things you normally find inside of a Java
    method: variable assignments, method calls, math expressions, for.loops, etc.
    在一个Beanshell的脚本中你可以定义普通的Java申明和表达式并且可以显示结果。
    申明和表达式一类你通常可以在如下的地方可以看到的:
    Java方法,变量申明,方法调用,数学表达式,for循环等等。
    Here are some examples: 这儿是一些示例:
    /*
    Standard Java syntax 标准Java语法
    */
    // Use a hashtable 使用hashtable
    Hashtable hashtable = new Hashtable();
    Date date = new Date();
    hashtable.put( "today", date );
    // Print the current clock value 打印当前时间
    print( System.currentTimeMillis() );
    // Loop 循环
    for (int i=0; i<5; i++)
    print(i);
    // Pop up a frame with a button in it 弹出一个带有按钮的面板
    JButton button = new JButton( "My Button" );
    JFrame frame = new JFrame( "My Frame" );
    frame.getContentPane().add( button, "Center" );
    frame.pack();
    frame.setVisible(true);
    You can also define your own methods and use them just as you would inside a Java class.
    We'll get to that in a moment.
    你也可以就像在一个Java类中一样定义你自己的方法并且使用它们。稍等我们将开始。
    3.Loosely Typed Java Syntax 松散定义Java类型
    In the examples above, all of our variables have declared types.e.g. "JButton button".
    Beanshell will enforce these types,
    as you will see if you later try to assign something other than a JButton to the variable "button"
    (you will get an error message).
    However BeanShell also supports "loose" or dynamically typed variables.
    That is, you can refer to variables without declaring them first and without specifying any type.
    In this case BeanShell will do type checking where appropriate at runtime.
    So, for example, we could have left off the types in the above example and written all of the above as:
    在上面的例子中,所有的变量都定义了类型。比如JButton button.
    Beanshell将检查这些类型,如果你尝试将其它类型的变量赋值给"button",你可以看到你将得到一个错误的消息。
    但是Beanshell也支持“松散”或者动态定义变量。
    那就是说,你可以使用没有定义并且没有申明类型的变量。
    在这个案例中Beanshell将在运行是进行类型检查。
    所以,我们可以去掉上例中左边的类型并且可以写成下面这样:
    /*
    Loosely Typed Java syntax 松散定义Java类型
    */
    // Use a hashtable 使用hashtable
    hashtable = new Hashtable();
    hashtable.put( "today", date );
    // Print the current clock value 打印当前时间
    print( System.currentTimeMillis() );
    // Loop 循环
    for (i=0; i<5; i++)
    print(i);
    // Pop up a frame with a button in it  弹出一个带有按钮的面板
    button = new JButton( "My Button" );
    frame = new JFrame( "My Frame" );
    frame.getContentPane().add( button, "Center" );
    frame.pack();
    frame.setVisible(true);
    This may not seem like it has saved us a great deal of work.
    But you will see the difference when you come to
    rely on scrīpting as part of your development and testing process;
    especially for in interactive use.
    When a "loose" variable is used you are free to reassign it to another type of Java object later.
    Untyped BeanShell variables can also freely hold Java primitive values like int and boolean.
    Don't worry, BeanShell always knows the real types and only lets you use the values where appropriate.
    For primitive types this includes doing the correct numeric promotion
    that the real Java language would do when you use them in an expression.
    这些看起来不会给我们带来很多的工作。但是当你将脚本当成你的应用程序的一部分的时候,你将看到不同,
    特别是在交互的使用中。当一个松散类型使用的时候你可以自由的将它赋给另一个Java对象。
    无类型Beanshell变量也可以支持Java原始类型int和boolean.
    不要担心,Beanshell总是知道真实的类型并且允许你在适当的时候使用变量的值。
    对于原始类型来说,这些包含正确的数字校验,当你在一个表达式中使用它们的时候,
    正式的Java语言将会这样做。
    4.Exception Handling 异常处理
    Exception handling using try/catch blocks works just as it does in Java. For example:
    就像在Java语言中一样,异常处理使用try/catch块。举例:
    try {
    int i = 1/0;
    } catch ( ArithmeticException e ) {
    print( e );
    }
    But you can loosely type your catch blocks if you wish:
    如果你希望你也可以松散定义你的catch块。
    try {
    ...
    } catch ( e ) {
    print( "caught exception: "+e );
    }
    5.Basic Scoping of Variables 变量的有效作用空间
    Note: 注意:
    As of BeanShell version 1.3 the default scoping of loosely typed variables was changed to be
    more consistent with Java.
    BeanShell still supports an alternate scoping used in earlier versions.
    This mode can be enabled for legacy code by setting the system property "localscoping" to true.
    See appendix "Local Scoping".
    在Beanshell 1.3版本中松散类型变量的默认作用空间变化的和Java中一致。
    Beanshell仍然支持用在早期版本中的交替作用空间。通过设置系统属性"localscoping"为true
    为了支持遗留代码这种模式也可以启用。见附录“本地作用空间”。
    Exception Handling 异常处理
    Variable scoping in BeanShell behaves, wherever possible, just like that in Java.
    Ordinary Java, however,
    does not offer "loose" variables (variables that can be used without being declared first).
    So we must define their behavīor within BeanShell.
    We'll see in the next section that untyped variables .
    variables that are not declared and not assigned a value elsewhere .
    default to the local scope. This means that, in general,
    if you assign a value to a variable without first declaring it, you are creating a new local variable in the current scope.
    变量作用空间在Beanshell中的行为表现,就像在Java中一样。
    普通的Java,没有提供“松散类型”变量(开始没有定义就可以使用的变量)。
    当然我们必须在Beanshell中定义它们的行为。我们将在下面的篇幅中看到没有类型的变量。
    没有定义并且没有赋值的变量,默认是本地变量。这个意思就是说,通常情况下,
    如果你开始没有定义一个变量,就将值赋给它,你就是在本地作用域中创建了一个本地变量。
    6.Blocks 程序块
    Blocks are statements between curly braces {}.
    In BeanShell, as in Java, blocks define a level of scope for typed variables:
    typed variables declared within a block are local to the block.
    Other assignments within the block occur, as always, wherever the variable was defined.
    程序块语句是在两个符号{}之间的部分。在Beanshell中就和在Java中一样,程序块为定义的变量
    声明了一个作用域,不管变量定义在那里,在程序块中的其它任务和通常的一样。
    Untyped variables in BeanShell, however, are not constrained by blocks.
    Instead they act as if they were declared at the outer (enclosing) scope's level.
    With this in mind, BeanShell code looks just like Java code.
    In BeanShell if you declare a typed variable within a block it is local to the block.
    But if you use an untyped variable
    (which looks just like an ordinary assignment in Java)
    it behaves as an assignment to the enclosing scope.
    在Beanshell中没有类型的变量,没有被程序块制约。它们的行为就和定义在外面的变量一样。
    考虑到这些,Beanshll代码看起来很像Java代码。在Beanshell中如果你在一个程序块中定义了一个
    有类型的变量,它就是程序块中的本地变量。
    但是如果你使用一个没有类型的变量(看起来是一个Java中普通的作业)
    ,它的行为就像在一个封闭作用域中的任务一样。
    This will make sense with a few examples: 通过下面的例子来找一下感觉。
    // Arbitrary code block 任意的代码块
    {
    y = 2; // Untyped variable assigned 没有类型定义的变量
    int x = 1; // Typed variable assigned 有定义类型的变量
    }
    print( y ); // 2
    print( x ); // Error! x is undefined. 错误!X的类型不明确。
    // Same with any block statement: if, while, try/catch, etc.
    和这些语句块一样:if,while,try/catch,等等。
    if ( true ) {
    y = 2; // Untyped variable assigned 没有类型定义的变量
    int x = 1; // Typed variable assigned 有定义类型的变量
    }
    print( y ); // 2
    print( x ); // Error! x is undefined. 错误!X的类型不明确。
    Variables declared in the for.init area of a for.loop follow the same rules as part of the block:
    定义在for循环中的for初始化中的变量同程序块中的其它部分一样遵守同样的规则。
    for( int i=0; i<10; i++ ) { // typed for.init variable有类型的for.init中的变量
    j=42;
    }
    print( i ); // Error! 'i' is undefined. 错误!i的类型不明确。
    print( j ); // 42
    for( z=0; z<10; z++ ) { } // untyped for.init variable没有类型的for.init中的变量
    print( z ); // 10  
    7.Variable Modifiers 变量修改
    The standard Java variable modifiers may be used on typed variables:
    private / protected / public, final,
    transient, volatile, static. Only 'final' is currently implemented. The others are currently ignored.
    Modifiers may not be applied to untyped variables.
    标准的Java变量的修改可以用在类型变量中:
    private/protected/public,final,transient,volatile,static.
    仅仅'final'是马上实现,其它的当前是忽略的。修改不可以应用在没有类型的变量上。

  • Beanshell翻译3

    2008-09-02 20:12:12

    Beanshell翻译3

    http://user.qzone.qq.com/281696143/blog/1194238270  Ronger
    1.Quick Start 快速开始
    Welcome to BeanShell. This is a crash course to get you going. We'll leave out many important options and details.
    Please see the rest of the user's guide for more information.
    欢迎来到Beanshell,这是一个快速前进的过程。我们将列出很多重要的项和细节.请看用户手册获取更多的信息。
    2.Download and Run BeanShell  下载和运行Beanshell
    Download the latest JAR file from http://www.beanshell.org and start up BeanShell either in the graphical desktop mode or on the command line.
    If you just want to start playing around you may be able to launch the BeanShell desktop by simply double clicking on the BeanShell JAR file.
    More generally however you'll want to add the jar to your classpath so
    that you can work with your own classes and applications easily.
    To do this you can either drop the BeanShell JAR file into your Java extensions folder or add it to your classpath.
    (Important: If you put BeanShell in the extensions folder and wish to use it with BSF applications
    like Jakarta Ant you must install the bsf.jar in the same location).
    http://www.beanshell.org上下载最新的Jar文件并且不管是以图形桌面模式或者是命令行模式开始Beanshell.
    如果你仅仅想了解一下你可以通过简单的点击Beanshell的Jar文件来发动Beanshell的桌面。更通用的,如果你将Jar文件
    加到你的类路径中,你可以像使用你自己的类或者应用程序一样轻松的使用它。
    要想这样,你可以将Beanshell的Jar文件拖到你的Java扩展文件夹中或者加到你的类路径中。(重要:如果你将Beanshell放到
    你的扩展文件夹中并且希望使用BSF应用程序中类似于Jakarta Ant的功能,你必须把bsf.jar放在同样的位置)。
    To install as an extension place the bsh.jar file in your
    $JAVA_HOME/jre/lib/ext folder.
    (OSX users: place the bsh.jar in /Library/Java/Extensions or ~/Library/Java/Extensions for individual users.)
    Or add BeanShell to your classpath like this:
    在$JAVA_HOME/jre/lib/ext文件夹中安装bsh.jar
    或者是像这样将Beanshell加到你的类路径中:
    unix: export CLASSPATH=$CLASSPATH:bsh.xx.jar
    windows: set classpath %classpath%;bsh.xx.jar
    Tip:   提示
    You can modify the classpath from within BeanShell using the addClassPath() and setClassPath() commands.
    You can then run BeanShell in either a GUI or command line mode:
    你可以使用addClassPath()和setClasPath()来修改类路径。
    你可以在GUI或者是命令行上运行Beanshell.
    java bsh.Console // run the graphical desktop   运行在图形桌面上
    or
    java bsh.Interpreter // run as text.only on the command line  在命令行行运行文本
    or
    java bsh.Interpreter filename [ args ] // run scrīpt file  运行脚本文件。
    It's also possible to call BeanShell from within your own Java applications, to reach it in a remote server mode for debugging,
    to use it as a servlet, or even in an applet. See "BeanShell Modes of Operation" for more details.
    也可以从你的Java应用程序上调用Beanshell,通过远程服务器模式调试它,当成Servlet甚至是applet来使用它。
    请看“Beanshell操作模式”获得详细信息。
    3.The BeanShell GUI  
    The BeanShell GUI desktop is meant to allow some experimentation with the features of BeanShell. It is not
    intended to be a replacement for a full featured IDE. Please check out the jEdit editor for an example of a full
    featured development environment based in part on BeanShell scrīpting capabilities. Upon starting the BeanShell in GUI mode a console window will open.
    By right clicking on the desktop background you can open additional console windows and other tools such as a simple class browser.
    Beanshell GUI 桌面将实验的特性加入进来。它并没有打算成为一个全功能的IDE.作为一个例子,请检查jEdit编辑器
    的Beanshell脚本功能。
    使用Beanshell的GUI模式时一个平台窗口将会打开。通过在平台上正确的点击你可以打开附加的平台窗口和其它的一些工具,
    比如一个简单的类浏览器。
    4.Quick Start 快速开始
    Each console window runs a separate instance of the BeanShell interpreter. The graphical console supports
    basic command history, line editing, cut and paste, and even class and variable name completion. From the
    console you can open a simple editor window. In it you can write scrīpts and use the 'eval' option to evaluate
    the text in the attached console's workspace or a new workspace.
    每个平台窗口运行一个Beanshell解释者的独立实例。图形平台支持历史上的基本命令,图形编辑,剪切和粘贴,申明类和变量。
    从平台上你可以打开一个简单的编辑窗口。在它里面你可以写脚本,在一个隶属于平台的工作空间或者一个新工作空间中使用
    'eval'命令计算表达式的值。
    5.Java Statements and Expressions Java申明和表达式
    BeanShell understands standard Java statements, expressions, and method declarations. Statements and
    expressions are all of the normal things that you'd say inside a Java method such as variable declarations and
    assignments, method calls, loops, and conditionals.
    Beanshell理解标准的Java申明,表达式,和方法定义。申明和表达式是最常见的,你可以在一个Java方法中进行变量定义和
    分配,方法调用,循环和条件语句。
    You can use these exactly as they would appear in Java, however in BeanShell you also have the option of working with "loosely typed" variables.
    That is, you can simply omit the types of variables that you use (both
    primitives and objects).
    BeanShell will only signal an error if you attempt to misuse the actual type of the variable.
    你可以完全使用在Java中出现的,但是在Beanshell中你还可以使用宽松类型来定义变量。
    那就是说,你可以忽略你使用的变量的类型(包括简单类型和对象)。如果你用错了变量的类型,
    Beanshell将仅仅标记一个错误。
    Here are some examples:  以下是示例:
    foo = "Foo";
    four = (2 + 2)*2/2;
    print( foo + " = " + four ); // print() is a BeanShell command  print()是Beanshell提供的命令
    // Do a loop  循环
    for (i=0; i<5; i++)
    print(i);
    // Pop up a frame with a button in it  在一个面板上放一个按钮
    button = new JButton( "My Button" );
    frame = new JFrame( "My Frame" );
    frame.getContentPane().add( button, "Center" );
    frame.pack();
    frame.setVisible(true);
    Useful BeanShell Commands 使用Beanshell的命令。
    In the previous example we used a convenient "built.in" BeanShell command called print(), to display values. print() does pretty much the same thing as System.out.println() except that it insures that the output always goes to the command line.
    print() also displays some types of objects (such as arrays) more verbosely than
    Java would. Another related command is show(),which toggles on and off automatic display of the result of every line you type.
    在上面的例子中,我们使用了一个方便的Beanshell的命令pring(),来显示值。
    print()可以和System.out.println()做的一样好,并且它还可以将输出显示在命令行中。
    print()可以显示对象的时候比Java冗长。另外一个相关的命令是show(),可以
    显示和关闭你选择的每一行结果的自动显示。
    Here are a few other examples of BeanShell commands: 这儿是一些Beanshell命令的其它的例子:
    · source(), run() . Read a bsh scrīpt into this interpreter, or run it in a new interpreter
    对一个bsh脚本进入解释者,或者在一个新的解释者中运行它。
    · frame() . Display a GUI component in a Frame or JFrame.
    在一个面板中显示一个GUI组件。
    · load(), save() . Load or save serializable objects to a file.
    加载或者存储一个序列化对象到一个文件中。
    · cd(), cat(), dir(), pwd(), etc. . Unix.like shell commands  Unix的命令很像shell命令
    · exec() . Run a native application   运行一个本地应用程序。
    · javap() . Print the methods and fields of an object,
    similar to the output of the Java javap command. 打印一个对象的方法和属性,类似于
    Java中的javap命令。
    · setAccessibility() . Turn on unrestricted access to private and protected components.
    See the complete list of BeanShell Commands for more information.
    打开通往私有和受保护组件的入口。通过Beanshell命令的完全列表来获得更多信息。
    6. Java Statements and Expressions   Java申明和表达式
    Tip:  提示
    BeanShell commands are not really "built.in"
    but are simply BeanShell scrīpts that are automatically loaded
    from the classpath.
    You can add your own scrīpts to the classpath to extend the basic command set.
    Beanshell命令不是编译进来的,而是简单的从类路径中加载的Beanshell脚本。
    你可以将你自己的脚本增加到类路径中来扩展基本的命令。
    7.scrīpted Methods 脚本函数
    You can declare and use methods in BeanShell just as you would in a Java class.
    你可以在Beanshell中就像在一个Java类一样申明函数。
    int addTwoNumbers( int a, int b ) {
    return a + b;
    }
    sum = addTwoNumbers( 5, 7 ); // 12
    Bsh methods may also allow dynamic (loose) argument and return types.
    Bsh方法也允许宽松的参数类型和返回类型。
    add( a, b ) {
    return a + b;
    }
    foo = add(1, 2); // 3
    foo = add("Oh", " baby"); // "Oh baby"
    Implementing Interfaces 实现接口
    Note: implementing arbitrary interfaces requires BeanShell be run under a Java 1.3 or higher environment.
    注意:想实现任意的接口,Beanshell需要运行在Java1.3或者是更高的环境上。
    You can use the standard Java anonymous inner class syntax to
    implement an interface type with a scrīpt. For example:
    在脚本中你可以使用标准Java匿名内部类去实现一个接口。示例:
    ActionListener scrīptedListener = new ActionListener() {
    actionPerformed( event ) { ... }
    }
    You don't have to scrīpt all of the methods of an interface.
    You can opt to scrīpt only those that you intend to call if you want to.
    The calling code will simply throw an exception
    if it tries to invoke a method that isn't defined.
    If you wish to override the behavīor of a large number of methods .
    say to produce a "dummy" adapter for logging .
    you can implement a special method signature:
    invoke(name, args) in your scrīpted object.
    The invoke() method is called to handle any undefined method invocations:
    你不需要实现接口中的所有方法。你可以选择实现那些你打算调用的方法。
    如果你尝试调用一个你没有实现的方法,调用代码仅仅简单的抛出一个异常。
    如果你希望去覆盖很多方法的行为,制造一个“虚拟”适配器来进行记录。
    你可以实现一个特别的方法:invoke(name, args)在你的脚本对象中。
    通过invoke()方法调用一些没有定义的方法。
    ml = new MouseListener() {
    mousePressed( event ) { ... }
    // handle the rest 调用其它方法
    invoke( name, args ) { print("Method: "+name+" invoked!");
    }
    8.scrīpted Objects 脚本对象
    In BeanShell, as in Javascrīpt and Perl, method "closures" allow you to create scrīpted objects.
    You can turn the results of a method call into an object reference
    by having the method return the special value this.
    You can then use the reference to refer to any variables set during the method call. Useful objects need methods of scrīpted Methods course,
    so in BeanShell scrīpted methods may also contain methods at any level.
    For example:
    在Beanshell中,就像在Javascrīpt和Perl中一样,方法"closures"允许你创建脚本对象。
    你可以将一个方法的调用结果通过返回特殊的值this赋给一个对象引用。
    在方法的调用中你甚至可以将这个引用赋给一些变量.
    有用的对象需要出现在脚本函数中,
    于是在Beanshell中脚本方法中的任何地方也可以包含方法。示例:
    foo() {
    print("foo");
    x=5;
    bar() {
    print("bar");
    }
    return this;
    }
    myfoo = foo(); // prints "foo"
    print( myfoo.x ); // prints "5"
    myfoo.bar(); // prints "bar"
    If this "closure" thing seems strange to don't worry.
    It's just an evolutionary step that languages acquired along the path to Objects.
    Please see the user's manual for a more thorough explanation.
    如果这个“closure”看起来很陌生,你也不要担心。
    它仅仅是一个渐进的的步骤,是语言需要顺着路径找到对象的步骤。
    请看用户使用手册来获取更多信息。
    Within your scrīpts, BeanShell scrīpted objects
    (i.e. any 'this' type reference like myfoo in the previous example)
    can automatically implement any Java interface type.
    When Java code calls methods on the interface
    the corresponding scrīpted methods will be invoked to handle them.
    BeanShell will automatically "cast" your scrīpted object
    when you attempt to pass it as an argument to a method that takes an interface type. For passing scrīpt references outside of BeanShell,
    you can perform an explicit cast where necessary.
    Please see the user manual for full details.
    在你的脚本中,Beanshell脚本对象(比如上例中的myfoo这个this引用)可以自动的实现一些Java接口。
    当Java代码在接口中调用方法的时候,响应的脚本函数将被调用去处理它们。
    当你通过传入一个参数调用一个函数的时候,Beanshell将自动的转换你的脚本对象。
    因为允许的脚本引用是在Beanshell之外,你可以在需要的时候执行一个强制转型。
    请看用户使用手册来获取完整细节。
    Calling BeanShell From Your Application 从你的应用程序中调用Beanshell
    You can evaluate text and run scrīpts from within your application
    by creating an instance of the BeanShell interpreter and using the eval() or source() commands. You may pass in variable references to objects you wish
    to use in scrīpts via the set() method and retrieve results with the get() method.
    你可以通过创建一个Beanshell解释者实例和使用eval(),source()命令
    ,计算一个文本和通过你的引用程序来运行脚本。
    你可以通过使用set()和通过get(),将变量引用赋给特定的对象。
    import bsh.Interpreter;
    Interpreter i = new Interpreter(); // Construct an interpreter 构造一个解释者
    i.set("foo", 5); // Set variables 设置变量
    i.set("date", new Date() );
    Date date = (Date)i.get("date"); // retrieve a variable 返回一个变量
    // Eval a statement and get the result 计算一个语句并且返回结果
    i.eval("bar = foo*10");
    System.out.println( i.get("bar") );
    // Source an external scrīpt file 发起一个外部脚本文件
    i.source("somefile.bsh");
    Tip: 提示
    In the above example the Interpreter's eval() method
    also returned the value of bar as the result of the evaluation.
    在上面的例子中解释者的eval()方法也返回变量bar的值。
    9。Conclusion 结束语
    We hope this brief introduction gets you started.
    Please see the full user manual for more details.
    Please consult the mailing list archives for more useful information. http://www.beanshell.org/
    我希望这一份摘要可以让你开始。请看完整的用户手册或者更多细节。
    请参考邮件列表获取更多有用的信息。http://www.beanshell.org/
                 -------------------------20080714北京 

  • Beanshell翻译2

    2008-09-02 20:10:41

    Beanshell翻译2

    http://user.qzone.qq.com/281696143/blog/1194238416  Ronger
    Introduction 介绍
    This document is about BeanShell. BeanShell is a small, free, embeddable Java source interpreter with object
    scrīpting language features, written in Java. BeanShell executes standard Java statements and expressions but
    also extends Java into the scrīpting domain with common scrīpting language conventions and syntax.
    BeanShell is a natural scrīpting language for Java.
    这个文档是关于BeanShell,BeanShell是一种用Java写成的小的,自由的,可嵌入的拥有对象脚本语言特性的Java语言解释器。
    Beamshell可以支持Java声明和表达式,同时可以使用通用的脚本语言习惯和语法将Java扩充进脚本领域。Beanshell对于Java来说,
    是一种自然脚本语言。
    scrīpting vs. Application Languages 脚本对比应用程序
    Traditionally, the primary difference between a scrīpting language and a compiled language has been in its
    type system: the way in which you define and use data elements. You might be thinking that there is a more
    obvious difference here . that of "interpreted" code vs. compiled code. But the compiler in and of itself does
    not fundamentally change the way you work with a language. Nor does interpreting a language necessarily
    make it more useful for what we think of as "scrīpting". It is the type system of a language that makes it
    possible for a compiler to analyze the structure of an application for correctness. Without types, compilation is
    reduced to just a grammar check and an optimization for speed. From the developer's perspective, it is also the
    type system that characterizes the way in which we interact with the code.
    传统上说,在一个脚本语言和可编译语言之间的最初不同是在系统类型上:你定义和使用数据的方法。你可以想到解释代码和
    编译代码之间的明显区别。但是编译器本身并不会从根本上改变你使用语言的方式。解释语言也不必使我们认为的脚本更加有用。
    它是语言的一种系统类型,使分析程序结构和正确性成为可能。没有类型,编辑器的工作减少为仅仅语法检查和速度最优化。
    从开发者的角度看,它仅仅是一种我们使用特征定义的方式来编写程序的系统类型。
    Types are good. Without strongly type languages it would be very hard to write large scale systems and make
    any assertions about their correctness before they are run. But working with types imposes a burden on the
    developer. Types are labels and labeling things can be tedious. It can be especially tedious during certain
    kinds of development or special applications where it is flexibility and not program structure that is
    paramount. There are times where simplicity and ease of use is a more important criterion.
    类型是很好的,没有严格的类型的语言很难写出大系统和在运行之前的关于代码正确性的验证。但是用类型语言工作对开发者来说
    是一种负担。类型是标签并且所标示的对象是沉闷乏味的,在发展的软件或者是弹性很高的应用程序中这些会显得特别沉闷乏味。
    有时候简单使用是一个很重要的标准.
    This is not just rationalization to cover some underlying laziness. Productivity affects what people do and
    more importantly do *not* do in the real world, much more than you might think. There is a lot of important
    software that exists in the world today only because the cost/benefit ratio in some developer's mind reached a
    certain threshold.
    掩盖下面的错误是不合理的。产品影响了人们应该做什么和现实世界中认为是重要的,比你想像的要多。有很多重要的软件今天
    还存在这个世界上仅仅是因为在某些开发者头脑中费用比率要在一个合理范围之内。
    Unit testing . one of the foundations of writing good code . is a prime example. Unit tests for well written
    code are, in general, vitally important as a collective but almost insignificant individually. It's a "tragedy of
    the commons" that leads individual developers to repeatedly weigh the importance of writing another unit test
    with working on "real code". Give developers have a tool that makes it easy to perform a test with a line or
    two of code they will probably use it. If, moreover, it is also a tool that they enjoy using during their
    development process . that saves the time, they will be even more inclined to use it.
    单元测试。写出好代码的基础之一。是一个简单的例子。想写出好的代码,对于集体来说单元测试通常是极其重要的,
    对于个人来说是基本上不重要的。这是一个通常的策略,可以使个人开发者重新认识到使用真实的代码写单元测试的重要性。
    给开发者一个很容易用一两句代码就可以构建测试的工具,他们将有可能使用它。如果,更多的,这还是一个在发布
    过程中让他们很喜欢使用的工具。那样可以节省时间,他们将更加倾向于使用它。
    Customizability through scrīpting also opens the door to applications that are more powerful than the sum of
    their parts. When users can extend, enhance, and add to their applications they use them in new and
    unexpected ways. scrīpting is powerful.
    客户通过脚本还可以打开一道应用程序的门。当用户能够扩展,增强并且将这些都带入到应用程序中是,他们可以用一些
    全新或者是不可预料的方法来使用他们。脚本是强大的。
    Tearing Down the Barriers  销毁屏障。
    Traditionally scrīpting languages have traded in the power of types for simplicity. Most scrīpting languages
    distill the type system to just one or a handful of types such as strings, numbers, or simple lists. This is
    sufficient for many kinds of scrīpting.
    Many scrīpting languages operate in a loose, unstructured land . a place dominated by text and
    course.grained tools. As such these scrīpting languages have evolved sophisticated mechanisms for working 。
    传统的脚本语言用类型的特征交换简单特征。许多脚本语言将类型系统提取为一种或者少数几种类型,比如:字符串,数字,
    或简单的结合。对很多的脚本语言来说这些已经很充分。
    许多脚本语言可以执行松散的,没有结构的程序,一个受控的文本和过程。一些脚本语言已经发展出久经考验的机制。
    Introduction  介绍
    with these simple types (regular expressions, pipes, etc.). As a result there has developed a casm between the
    scrīpting languages and the application languages created by the collapse of the type system in.between. The
    scrīpting languages have remained a separate species, isolated and speaking a different dialect from their
    brothers the application languages.
    对于这些简单的类型(通常为表达式)。结果在脚本语言和被类型系统in.between创建失败的应用程序语言之间制定了casm。
    脚本语言还是一个单独的物种,孤立和说着和它的兄弟语言应用程序语言不同的语调。
    BeanShell is a new kind of scrīpting language. BeanShell begins with the standard Java language and bridges
    it into the scrīpting domain in a natural way, but allowing the developer to relaxing types where appropriate. It
    is possible to write BeanShell scrīpts that look exactly like Java method code. But it's also possible to write
    scrīpts that look more like a traditional scrīpting language, while still maintaining the framework of the Java
    syntax.
    Beanshell是一个全新种类的语言.Beanshell开始于标准的Java语言并且以一个自然的方式将它带入脚本领域,并且允许开发着
    酌情放宽类型。完全像Java方法代码一样的书写Beanshell脚本是可能的。但是更有可能是像传统脚本语言一样书写Beanshell
    脚本,同时仍然保持Java语法框架。
    BeanShell emulates typed variables and parameters when they are used. This allows you to "seed" your code
    with strong types where appropriate. You can "shore up" repeatedly used methods as you work on them,
    migrating them closer to Java. Eventually you may find that you want to compile these methods and maintain
    them in standard Java. With BeanShell this is easy. BeanShell does not impose a syntactic boundary between
    your scrīpts and Java.
    当需要的时候Beanshell仿效定义变量和参数。这允许你写下适当的严格类型的代码。你可以使用函数来重复调用,
    将他们迁移到Java中。甚至你会发现你想去编译这些方法并且在标准Java中调用他们,对于Beanshell来说这是很容易的。
    在你的脚本和Java之间Beanshell并没有硬性的句法边界。
    But the bridge to Java extends much deeper than simple code similarity. BeanShell is one of a new breed of
    scrīpting languages made possible by Java's advanced reflection capabilities. Since BeanShell can run in the
    same Java virtual machine as your application, you can freely work with real, live, Java objects . passing
    them into and out of your scrīpts. Combined with BeanShell's ability to implement Java interfaces, you can
    achieve seamless and simple integration of scrīpting into your Java applications. BeanShell does not impose a
    type boundary between your scrīpts and Java.
    但是和Java联系的桥扩展的比简单的代码更深刻。Beanshell是通过Java的高级映射功能实现的新脚本语言之一。
    既然Beanshell可以像你的引用程序一样运行在Java虚拟机中,你可以自由的调用存在的Java对象,让它们自由出
    入你的脚本。结合Beanshell实现Java接口的能力,你可以将完成脚本和Java应用程序之间的无缝连接。在你的
    脚本和Java之间Beanshell没有硬性的类型边界。
    History 历史
    What seems like an eternity ago, back in the summer of 1993, I was working at Southwestern Bell
    Technology Resources and I was infatuated with the Tcl/Tk scrīpting language. On the advice of someone at
    Sun I also began playing around a bit with the Oak language written by James Gosling. Little did I know that
    within just a few years Oak, which would become Java, would not only spark a revolution, but that I would be
    writing one of the first books on the new Java language (Exploring Java, O'Reilly & Associates) and creating
    Java's first scrīpting language, BeanShell, drawing inspiration from Tcl.
    看起来就像很久以前,回到1993年的夏天,我在西南地区的贝尔技术研究所工作并且我对Tcl/Tk语言很着迷。
    在Sun公司的一些人的建议上我还是研究James Gosling写在Oak语言。我不知道过了一些年之后将转变成Java的语言Oak不仅
    发起了一场革命,但是我将要写一本新Java语言方面的书并且创建Java的第一个脚本语言,Beanshell,我的灵感来自于Tcl.
    BeanShell's first public release was not until 1997, but I had been poking at it in one form or another for some
    time before that. BeanShell as a language became practical when Sun added reflection to the Java language in
    version 1.1. After that, and after having seen its value in helping me create examples and snippets for the
    second edition of my book, I decided to try to polish it up and release it.
    Beanshell直到1997年才首次公开发布。但是在这之前我已经了解它了。当sun公司将反射加到Java1.1的时候,Beanshell作为
    一zhong语言变得很流行。在这之后,并且在看到它在我的第二版书中帮助我创建实例和摘录的价值之后,我决定尝试使它更完美
    并且发布它。
    BeanShell has slowly, but steadily gained popularity since then. It has grown in fits and spurts as its
    contributor's time has allowed. But recently BeanShell has achieved a sort of critical mass. BeanShell is
    distributed with Emacs as part of the JDE and with Sun Microsystem's NetBeans / Forte for Java IDEs.
    BeanShell is also bundled by BEA with their Weblogic application server. We've had reports of BeanShell
    being used everywhere from the high energy physics laboratory CERN, to classrooms teaching programming
    to nine year olds. BeanShell is being used in everything from large financial applications all the way down to
    embedded systems floating in Buoys in the pacific ocean. I attribute this success to the power of the open
    source development model and owe many thanks to everyone who has contributed.
    从此之后,Beanshell慢慢的变得流行。当允许捐赠者捐赠的时候它增长的速度很快。但是最近Beanshell已经有了一批
    使用者。Beanshell作为IDE的一部分分布在Emacs和Sun公司的NetBeans中。Beanshell也被BEA公司绑定在Weblogic应用
    服务器中。我们已经有报告表示,Beanshell被用在从高能物理实验室CERN到给9岁孩子上课的教室中的每个地方。Beanshell
    被用在从大的金融应用程序到太平洋的浮标的嵌入系统的每件事情上。我将成功归结于开源框架的力量并且感谢每个曾经
    贡献力量的人。
    Conclusion  结束
    I believe that BeanShell is the simplest and most natural scrīpting language for Java because it is, foremost,
    Java. BeanShell draws on a rich history of scrīpting languages for its scrīpting syntax and uses it to very
    conservatively extend the Java language into this new domain. I hope that you have half as much fun using
    BeanShell as I have had working on it and I welcome all comments and suggestions.
    我相信Beanshell是Java中最简单和最自然的脚本语言。因为Java.Beanshell采用成熟的脚本语言来定义语法并且将Java语言
    适当的扩充进来。我希望当你使用Beanshell的时候,你可以有我工作在上面一半的开心并且我欢迎你的评论和意见。
                                 -------20080711北京

  • Beanshell翻译1

    2008-09-02 20:08:43

    Beanshell翻译1
    开源框架Beanshell翻译

    http://user.qzone.qq.com/281696143/blog/1197940650 Ronger
    1.bsh.Interpreter:
    说明:The BeanShell scrīpt interpreter. An instance of Interpreter can be used to source scrīpts and evaluate statements or expressions.
    Beanshell脚本解释者。一个解释的实例可以用作发起脚本或者计算申明或者表达式。
    Here are some example:
      Interpeter bsh = new Interpreter();
    // Evaluate statements and expressions计算表达式
      bsh.eval("foo=Math.sin(0.5)");
      bsh.eval("bar=foo*5; bar=Math.cos(bar);");
      bsh.eval("for(i=0; i<10; i++) { print(\"hello\"); }");
      // same as above using java syntax and apis only像上面一样使用java语法和句法。
       bsh.eval("for(int i=0; i<10; i++) { System.out.println(\"hello\"); }");
      // Source from files or streams从文件或者流中发起。
       bsh.source("myscrīpt.bsh");  // or bsh.eval("source(\"myscrīpt.bsh\")");
      // Use set() and get() to pass objects in and out of variables
    使用set()和get()方法让对象进入和变量返回。
    bsh.set( "date", new Date() );
    Date date = (Date)bsh.get( "date" );
    // This would also work:下面的也可以实现。
    Date date = (Date)bsh.eval( "date" );
    bsh.eval("year = date.getYear()");
    Integer year = (Integer)bsh.get("year");
    // primitives use wrappers最初使用包装类
    // With Java1.3+ scrīpts can implement arbitrary interfaces...
    JDK为java1.3以上脚本可以实现任意的接口。
    // scrīpt an awt event handler (or source it from a file, more likely)
    使用一个awt事件助手(或者从一个文件发起,更多类似)
    bsh.eval( "actionPerformed( e ) { print( e ); }");
    // Get a reference to the scrīpt object (implementing the interface)
    取得一个指向脚本对象的引用。
      ActionListener scrīptedHandler =
             (ActionListener)bsh.eval("return (ActionListener)this");
    // Use the scrīpted event handler normally...
    通常使用已经定义好的事件助手。
    new JButton.addActionListener( scrīpt );

    In the above examples we showed a single interpreter instance, however you may wish to use many instances, depending on the application and how you structure your scrīpts. Interpreter instances are very light weight to create, however if you are going to execute the same scrīpt repeatedly and require maximum performance you should consider scrīpting the code as a method and invoking the scrīpted method each time on the same interpreter instance (using eval()).
    我上面的例子中,我们演示了一个解释者实例。但是你会希望依靠应用程序和定义脚本的结构来使用很多的实例。解释者实例是轻量级的。但是如果你准备重复的执行一段脚本,你就应该将脚本代码定义成一个方法并且没有都用同一个解释者实例来调用这个脚本方法(使用eval())。
    2.bsh.NameSpace
    A namespace in which methods, variables, and imports (class names) live. This is package public because it is used in the implementation of some bsh commands. However for normal use you should be using methods on bsh.Interpreter to interact with your scrīpts.
    A bsh.This object is a thin layer over a NameSpace that associates it with an Interpreter instance. Together they comprise a Bsh scrīpted object context.
    一个放置方法,变量,和导入类名的名字空间。这是一个公共包,因为它通常用在一些bsh命令的执行上。但是对于通常的使用你必须使用bsh.Interpreter中的方法来执行你的脚本。
    一个bsh.This对象是一个超过和Interpreter实例联系的NameSpace的薄层。
    bsh.This对象和NameSpace合起来是一个bsh脚本对象上下文。
    (理解:这句话的意思就是可以通过NameSpace取到脚本中的所有对象。)
    3.目前已经实现了一个demo,就是已知软件系统的请求报文,通过Beanshell的脚本,得到应答报文:
    3.1.条件:请求报文(XML),寄存器中的变量(以一个XML来模拟)。
    3.2.实现思路:
    3.2.1通过程序将请求报文和寄存器报文中的内容全部读出来。将内容全部放到以in_和reg_开头的变量中,同时将变量全部传入Interpreter。
    3.2.2.通过Interpreter中提供的命令执行脚本。
    3.2.3.通过NameSpace中提供的命令,就脚本中定义的变量的名字和值全部返回。同时写入XML文件中,也就是应答报文。

    4.报文格式:
    4.1.请求报文格式:
    <?xml version="1.0" encoding="utf-8"?>
    <REQ_HQXH>
      <requester_id>1</requester_id>
      <channel_id>10</channel_id>
      <branch_no>100080</branch_no>
      <jym>101100</jym>
      <khlx>0</khlx>
      <zh>955880010132429877</zh>
      <pzh>8001</pzh>
      <wdh>1008</wdh>
      <reqdate>20080703</reqdate>
      <reqtime>153000</reqtime>
    </REQ_HQXH>
    4.2.寄存器报文格式:
    <?xml version="1.0" encoding="utf-8"?>
    <register>
      <lsh>1234567</lsh>
      <ye>120000.3</ye>
      <lxjs>0.15</lxjs>
      <lv>0.15</lv>
      <sl>0.15</sl>
    </register>
    4.3.脚本格式:
    4.3.1.公共脚本(函数脚本)。
    toNum(String param){
      return Double.parseDouble(param);
    }
    sysdate(){
      Date date=new Date();
      return date.toLocaleString();
    }
    systime(){
      Date date=new Date();
      return String.valueOf(date.getTime());
    }
    double random(int length){    
      return Math.random();
    }
    4.3.2.业务脚本:
    out_zh=in_zh;  
    //应答报文中的帐号取输入报文中的帐号
    out_lsh=reg_lsh;    
    //应答报文中的流水号从寄存器中获取。
    out_ye=reg_ye;    
    //应答报文中的余额从寄存器中获取。
    lxjs=reg_lxjs;          
    //应答报文中的利息积数从寄存器中获取。
    out_lxjs= lxjs;  
    lx=toNum(reg_lv)*toNum(lxjs);  
    //利息=利率?á利息积数。
    out_lx=lx;
    lxs=toNum(reg_sl)*lx;      
    //利息税=税率?á利息
    out_lxs=lxs;    
    out_xhrq=sysdate();  //销户日期=系统日期。
    out_askdate=sysdate();
    out_asktime=systime();  //应答时间=系统时间      
    out_zdh=random();  //终端号=随机数。
    out_hh=in_zh.substring(0,5);  
    //行号=输入报文中帐号的前五位。
    if(toNum(reg_ye)>0)
      out_status="complete";
    else
      out_status="fail";
    4.4.生成的应答报文的格式:
    <?xml version="1.0" encoding="utf-8"?>
    <ASK_HQXH>
    <zh>955880010132429877</zh>
    <lxjs>0.15</lxjs>
    <lx>0.0225</lx>
    <zdh>0.5654736967697099</zdh>
    <hh>95588</hh>
    <status>complete</status>
    <ye>120000.3</ye>
    <xhrq>2008-7-9 13:11:49</xhrq>
    <lxs>0.003375</lxs>
    <asktime>1215580309281</asktime>
    <askdate>2008-7-9 13:11:49</askdate>
    <lsh>1234567</lsh>
    </ASK_HQXH>

                   回答这个技术有何作用----细细品味方知其中滋味20080709北京。

  • Fortify分析翻译10

    2008-09-02 20:05:12

                                   Fortify分析翻译10

                        http://user.qzone.qq.com/281696143/blog/1220335112 Ronger
    25.Denial of service(Data Flow):
    25.1.源文件:Metronome.java
    代码:sleep(thisTime);
    25.2.原文:An attacker could cause the program to crash or otherwise become unavailable to legitimate users.
    翻译:攻击者可以使程序崩溃,否则为了让自己变成合法用户而让程序变得不可用。
    理解:如果给变量thisTime一个很大的值,就可以让本线程一直sleep下去,所以这种风险类型归纳为服务拒绝。
    25.3.EXPLANATION 解释
    Attackers may be able to deny service to legitimate users by flooding the application
    with requests, but flooding attacks can often be defused at the network layer.
    More problematic are bugs
    that allow an attacker to overload the application using a small number of requests.
    Such bugs allow the attacker to specify the quantity of system resources their requests
    will consume or the duration for which they will use them.
    攻击者可以通过大量的发送请求给应用程序,对合法用户拒绝服务,
    但是淹没式的攻击常常在网络层被拒绝。
    许多的问题是程序臭虫,允许攻击者使用少量的请求使应用程序超过负载。
    一些臭虫允许攻击者详细列出系统资源的数量,
    他们的请求将消耗应用程序的一部分时间。
    Example 1: The following code allows a user to specify the amount of time for
    which a thread will sleep. By specifying a large number,
    an attacker can tie up the thread indefinitely.
    With a small number of requests, the attacker can deplete the application's thread pool.
    例子:下面的代码将允许一个用户详细列出一个线程将休眠的时间值。
    通过指定一个很大的数值,攻击者有可能会约束这个线程。
    通过很少数量的请求,攻击者可以耗尽应用程序的线程池。
      int usrSleepTime = Integer.parseInt(usrInput);
      Thread.sleep(usrSleepTime);
    Example 2: The following code reads a String from a zip file.
    Because it uses the readLine() method, it will read an unbounded amount of input.
    An attacker can take advantage of this code to cause an OutOfMemoryException
    or to consume a large amount of memory so
    that the program spends more time performing garbage collection
    or runs out of memory during some subsequent operation.
    例子2:下面的代码从一个zip文件中读入字符串。
    因为它使用readLine()方法,它将读入一个不可预知的输入。
    攻击者可以利用这个代码产生一个内存溢出异常,或者消费一大块内存,
    导致程序花费很多时间执行垃圾回收,或者在一些并发操作的过程中内存被完全占满。
      InputStream zipInput = zipFile.getInputStream(zipEntry);
      Reader zipReader = new InputStreamReader(zipInput);
      BufferedReader br = new BufferedReader(zipReader);
      String line = br.readLine();
    25.4.RECOMMENDATIONS 建议
    Validate user input to ensure that it will not cause inappropriate resource utilization.
    验证用户输入去确认,它将不会导致不确当的源使用。
    Example 1 Revisited: The following code allows a user to specify the amount of time for
    which a thread will sleep, but only if the value is within reasonable bounds.
    例子1 重新确认:下面的代码将允许一个用户详细列出一个线程将休眠的时间值,
    但是仅仅当这个值是在合理的范围内。
      int usrSleepTime = Integer.parseInt(usrInput);
      if (usrSleepTime >= SLEEP_MIN &&
          usrSleepTime <= SLEEP_MAX) {
        Thread.sleep(usrSleepTime);
      } else {
        throw new Exception("Invalid sleep duration");
      }
    }
    Example 2 Revisited: The following code reads a String from a zip file.
    The maximum string length it will read is MAX_STR_LEN characters.
    例子 2 重新确认:下面的代码从一个zip文件中读入字符串。
    它将读到的最大的字符串长度是MAX_STR_LEN。
      InputStream zipInput = zipFile.getInputStream(zipEntry);
      Reader zipReader = new InputStreamReader(zipInput);
      BufferedReader br = new BufferedReader(zipReader);
      StringBuffer sb = new StringBuffer();
      int intC;
      while ((intC = br.read()) != -1) {
        char c = (char) intC;
        if (c == '\n') {
          break;
        }
        if (sb.length() >= MAX_STR_LEN) {
          throw new Exception("input too long");
        }
        sb.append(c);
      }
      String line = sb.toString();
    26.System information leak:missing catch block(structural):
    26.1.源文件:FileDownloadServlet.java
    代码:public void doGet(HttpServletRequest req, HttpServletResponse rep)throws ServletException,IOException{
    26.2.原文:If a Servlet fails to catch all exceptions, it may reveal debugging information that will help an adversary form a plan of attack..
    翻译:如果一个Servlet不能捕捉所有异常,它将会显示出可以帮助攻击者制定攻击计划的调试信息,
    理解: 该方法的全部程序如下:
    public void doGet(HttpServletRequest req, HttpServletResponse rep)throws ServletException,IOException{
    try{
    doDownload(req, rep);
    }catch(BizException ex){
    throw new ServletException("File download failure",ex);
    }
    }
    在该方法中只捕捉了BizException,这样如果出现ServletException或IOException的时候,
    如果代码中包含一下代码:out.println("hello " + addr.getHostName());,将会存在风险。
    26.3.EXPLANATION 解释
    When a Servlet throws an exception,
    the default error response the Servlet container
    sends back to the user typically includes debugging information.
    This information is of great value to an attacker.
    For example, a stack trace might show the attacker a malformed SQL query string,
    the type of database being used, and the version of the application container.
    This information enables the attacker to target known vulnerabilities in these components.
    当一个Servlet抛出一个异常,
    默认错误反应的Servlet容器,发送给用户信息的时候,
    通常包含调试信息。
    这些信息对于攻击者来说非常有价值。
    例如,一个堆栈的痕迹可以将SQL查询语句显示给攻击者,
    使用的数据库类型,和应用程序容器的版本。
    这些信息允许攻击者了解在这些组件中的漏洞。
    Example 1: In the following method a DNS lookup failure
    will cause the Servlet to throw an exception.
    例子1:下面的方法中,一个DNS查找失败将导致Servlet抛出一个异常。
    protected void doPost (HttpServletRequest req,                
                        HttpServletResponse res)
                  throws IOException {
        String ip = req.getRemoteAddr();
        InetAddress addr = InetAddress.getByName(ip);
        ...
        out.println("hello " + addr.getHostName());
    }
    Example 2: The following method will throw a NullPointerException
    if the parameter "name" is not part of the request.
    例子2:下面的方法将抛出一个NullPointException,
    如果参数"name"不是请求的一部分。
    protected void doPost (HttpServletRequest req,                
                        HttpServletResponse res)
                  throws IOException {
        String name = getParameter("name");
        ...
        out.println("hello " + name.trim());
    }
    26.4.RECOMMENDATIONS 建议
    All top-level Servlet methods should catch Throwable,
    thereby minimizing the chance that the Servlet's error response mechanism is invoked.
    Example 3: The method from Example 1 should be rewritten as follows:
    所有高级别的Servlet方法需要捕捉Throwable,
    从而,减少Servlet的错误返回机制被调用的机会。
    例子3:从例子1中的方法可以以下面的方式重写。
    proteced void doPost (HttpServletRequest req,                
                        HttpServletResponse res) {
          try {
              String ip = req.getRemoteAddr();
              InetAddress addr = InetAddress.getByName(ip);
          ...
              out.println("hello " + addr.getHostName());
          }catch (Throwable t) {
              logger.error("caught throwable at top level", t);
          }
      }
    }
    27. J2EE bad practices:Leftover debug code(Structural):   
    27.1.源文件:BizElementMapping.java.
    代码:  public static void main(String args[]){
    27.2.原文:Debug code can create unintended entry points in a deployed web application.
    翻译:在一个已经发布的web应用程序中,调试代码会创建一个无意识的入口。
    理解:就是从项目的安全方面考虑,攻击者可以在web应用程序中直接调用main方法。
    27.3.EXPLANATION 解释
    A common development practice is to add "back door" code specifically designed
    for debugging or testing purposes that is not intended to be shipped or deployed
    with the application. When this sort of debug code is accidentally left in the application,
    the application is open to unintended modes of interaction.
    These back door entry points create security risks
    because they are not considered during design or testing
    and fall outside of the expected operating conditions of the application.
    一个通常的开发习惯是增加"后门"代码,这些代码是为调试和测试而设计的,
    而没有打算去运行或者发布在应用程序中。
    当这种类型的调试代码意外的留在应用程序中,
    应用程序将会有一些没有预料到的模式开放。
    这些后门输入创建安全风险,
    因为他们在设计和测试的时候没有考虑到并且变成在应用程序的可预期的操作条件之外。
    The most common example of forgotten debug code is a main() method appearing
    in a web application. Although this is an acceptable practice during product development,
    classes that are part of a production J2EE application should not define a main().
    被遗忘的调试代码的最常见的例子是出现在web应用程序中的main()方法。
    虽然在产品的开发阶段,这些是可以接受的习惯,
    作为一个J2EE应用产品的一部分,类不可以定义一个main().
    27.4.RECOMMENDATIONS 建议
    Remove debug code before deploying a production version of an application.
    Regardless of whether a direct security threat can be articulated,
    it is unlikely that there is a legitimate reason for such code
    to remain in the application after the early stages of development.
    在发布一个生产版本的应用程序之前,移除调试代码。
    不管是否一个直接的安全威胁可以很清晰,
    在开发阶段之后,在应用程序中保存这些代码,
    所有合法的理由,都是不行的。
    27.5.TIPS 提示
    27.5.1. The presence of a main() method may represent the tip of an iceberg.
    When you find a main(), look for other indications
    that developers were rushed or otherwise not able to conclude their efforts normally.
    一个main()方法的存在可以描绘出冰山一角。
    当你发现一个main(),可以发现其它的迹象,
    就是开发过程是匆忙的,或者以其它的方式不能正常地结束他们的努力。
    27.5.2. If you are auditing a non-J2EE Java application,
    the J2EE Bad Practices category might not apply to your environment.
    If this is the case, you can use AuditGuide to suppress these issues.
    如果你在审计一个非J2EE的Java应用程序,
    这个J2EE的坏习惯分类将不能应用到你的环境中。
    如果这里是这种情况,你可以使用AuditGuide挂起这些事件。

  • Fortify分析翻译9

    2008-09-02 20:03:16

    Fortify分析翻译9

                            http://user.qzone.qq.com/281696143/blog/1220322706  Ronger
    24.Http response splitting(Data Flow):
    24.1.源文件:WorkPageDispatcher.java.
    代码:rep.sendRedirect(url);
    24.2.原文:Including unvalidated data in an HTTP response header can enable cache-poisoning, cross-site scrīpting, cross-user defacement or page hijacking attacks.
    翻译:在Http响应头中包含没有经过验证的数据将会使缓存中毒,经过的站点和经过的用户信息遭到毁坏,页面受到控制。
    理解:在此处指url这个参数有可能会不安全。
    24.3.EXPLANATION 解释
    HTTP response splitting vulnerabilities occur when:
    HTTP响应的漏洞出现在:
    24.3.1. Data enters a web application through an untrusted source,
    most frequently an HTTP request.
    In this case the data enters at getParameterMap()
    in web/common/WorkPageDispatcher.java at line 52.
    数据通过一个不可信任的源进入web应用程序,
    大多数是通过HTTP请求实现的。
    在这个例子中,数据通过WorkPageDispatcher.java52行的getParameterMap()进入。
    24.3.2. The data is included in an HTTP response header sent to a web user
    without being validated for malicious characters.
    In this case the data is sent at sendRedirect()
    in web/common/WorkPageDispatcher.java at line 58.
    没有验证恶意字符,数据被包含在响应头中发送给一个web用户。
    在这个例子中,数据通过WorkPageDispatcher.java58行的sendRedirect()发送。
    As with many software security vulnerabilities,
    HTTP response splitting is a means to an end, not an end in itself.
    At its root, the vulnerability is straightforward:
    an attacker passes malicious data to a vulnerable application,
    and the application includes the data in an HTTP response header.
    就像许多软件安全性漏洞一样,
    HTTP响应分离意味着结束,而不是自身的结束。
    在它的根上,漏洞是直接了当的:
    攻击这将恶意数据通过一个有漏洞的应用程序,
    并且应用程序将这些数据包含在HTTP响应头中。
    To mount a successful exploit, the application must allow input that contains CR
    (carriage return, also given by %0d or \r)
    and LF (line feed, also given by %0a or \n)characters into the header.
    These characters not only give attackers control of the remaining headers
    and body of the response the application intends to send,
    but also allows them to create additional responses entirely under their control.
    作为一个成功的使用,应用程序应该允许包含CR和LF的输入字符进入响应头。
    这些字符不仅让攻击者控制存在的头信息和响应的内容,这个内容是应用程序准备发送的,
    但是也要允许他们创建完全在控制之下的额外的响应。
    Example: The following code segment reads the name of the author of a weblog entry,
    author, from an HTTP request and sets it in a cookie header of an HTTP response.
    例如:下面的代码片段读入一个weblog输入的作者名字,
    作者,从一个HTTP请求,并且设置它在一个HTTP响应的cookie头中。
    String author = request.getParameter(AUTHOR_PARAM);
    ...
    Cookie cookie = new Cookie("author", author);
         cookie.setMaxAge(cookieExpiration);
         response.addCookie(cookie);
    Assuming a string consisting of standard alpha-numeric characters,
    such as "Jane Smith",
    is submitted in the request the HTTP response including this cookie
    might take the following form:
    假设字符完全是由标准alpha数字字符构成,
    例如"Jane Smith",在请求中被提交,包含这个cookie的HTTP响应将采取下面的形式:
    HTTP/1.1 200 OK
    ...
    Set-Cookie: author=Jane Smith
    ...
    However, because the value of the cookie is formed of unvalidated user input
    the response will only maintain this form
    if the value submitted for AUTHOR_PARAM does not contain any CR and LF characters.
    If an attacker submits a malicious string, such as "Wiley Hacker\r\nHTTP/1.1 200 OK\r\n...",
    then the HTTP response would be split into two responses of the following form:
    但是,因为cookie的值是和未经验证的用户输入相匹配的,响应将仅仅维持这种模式。
    如果从AUTHOR_PARAM提交的值没有包含一些CR和LF字符。
    如果攻击者提交一个恶意的字符,例如"Wiley Hacker\r\nHTTP/1.1 200 OK\r\n...",
    那么HTTP响应将分离为下面这样的两次响应。
    HTTP/1.1 200 OK
    ...
    Set-Cookie: author=Wiley Hacker
    HTTP/1.1 200 OK
    ...
    Clearly, the second response is completely controlled by the attacker
    and can be constructed with any header and body content desired.
    The ability of attacker to construct arbitrary HTTP responses permits a variety of resulting attacks,
    including: cross-user defacement, web and browser cache poisoning,
    cross-site scrīpting and page hijacking.
    很明显的,第二次响应是完全被攻击者控制的,
    并且可以通过一些头信息和渴望得到的内容信息来构造。
    攻击者构造任意的HTTP响应的能力决定了结果攻击的多样性,
    包括:用户被毁损,web和浏览器缓存中毒,
    站点脚本和页面被修改。
    Cross-User Defacement:
    An attacker can make a single request to a vulnerable server
    that will cause the server to create two responses,
    the second of which may be misinterpreted as a response to a different request,
    possibly one made by another user sharing the same TCP connection with the server.
    This can be accomplished by convincing the user to submit the malicious request themselves,
    or remotely in situations where the attacker
    and the user share a common TCP connection to the server,
    such as a shared proxy server. In the best case,
    an attacker can leverage this ability to convince users that the application has been hacked,
    causing users to lose confidence in the security of the application.
    In the worst case,
    an attacker may provide specially crafted content designed to mimic the behavīor of the application
    but redirect private information, such as account numbers and passwords,
    back to the attacker.
    用户被毁损:
    攻击者可以使用一个单独的请求到一个有漏洞的服务器上,
    可以使这个服务器创建两个响应,这两个就可以被曲解为给不同的请求进行响应,
    有可能另一个用户和服务器共享同样的TCP连接。
    这些可以被实现,通过确信这个用户提交恶意的请求,
    或者在远程的情况下,攻击者和用户共享通向服务器的TCP连接,
    例如一个共享的代理服务器。在最好的情况下,
    攻击者有这样的能力,确信应用程序已经砍掉的用户,
    使用户失去对应用程序安全的信心。
    在最坏的情况下,
    攻击者可以提供特别的内容,这段内容设计为假装应用程序的行为,
    但是使私人的信息改变方向,例如帐号和密码,
    返回给攻击者。
    Cache Poisoning:
    The impact of a maliciously constructed response can be magnified
    if it is cached either by a web cache used by multiple users
    or even the browser cache of a single user.
    If a response is cached in a shared web cache,
    such as those commonly found in proxy servers,
    then all users of that cache will continue receive the malicious content
    until the cache entry is purged. Similarly,
    if the response is cached in the browser of an individual user,
    then that user will continue to receive the malicious content until the cache entry is purged,
    although only the user of the local browser instance will be affected.
    缓存中毒:
    恶意数据构造响应的影响可以被放大的,
    不管它是一个被很多用户使用的web缓存,还是一个用户使用的浏览器。
    如果一个响应在一个共享的web缓存中被存储,
    例如那些普通的在代理服务器上面的,
    那么所有缓存中的用户将持续接受恶意内容,直到缓存输入被清除,
    尽管仅仅本地的浏览器实例用户将被影响到。
    Cross-Site scrīpting:
    Once attackers have control of the responses sent by an application,
    they have a choice of a variety of malicious content to provide users.
    Cross-site scrīpting is common form of attack
    where malicious Javascrīpt or other code included in a response
    is executed in the user's browser.
    The variety of attacks based on XSS is almost limitless,
    but they commonly include transmitting private data like cookies
    or other session information to the attacker,
    redirecting the victim to web content controlled by the attacker,
    or performing other malicious operations on the user's machine
    under the guise of the vulnerable site.
    The most common and dangerous attack vector against users of a vulnerable application
    uses Javascrīpt to transmit session
    and authentication information back to the attacker
    who can then take complete control of the victim's account.
    站点脚本:
    一旦攻击者已经控制了通过应用程序发送的响应,
    他们可以可以选择提供恶意内容给用户。
    站点脚本也是一种攻击方式,在响应中的恶意Javascrīpt或者其它的代码在用户的浏览器中被执行。
    建立在VSS基础上的攻击总是无限的,
    但是他们常常包含传输的私有数据,比如cookies或者其它发给攻击者的session信息,
    将发给用户的信息转发给被攻击者控制的web内容,
    或者通过有弱点的站点的伪装,在用户的机器上执行其它的恶意操作。
    最常用和危险的攻击有弱点的应用程序中的用户,
    是使用Javascrīpt将session和安全信息传输给攻击者,
    攻击者可以完全控制受害者的帐户。
    Page Hijacking: In addition to using a vulnerable application to send malicious content
    to a user, the same root vulnerability can also be leveraged
    to redirect sensitive content generated by the server
    and intended for the user to the attacker instead.
    By submitting a request that results in two responses,
    the intended response from the server and the response generated by the attacker,
    an attacker can cause an intermediate node, such as a shared proxy server,
    to misdirect a response generated by the server for the user to the attacker.
    Because the request made by the attacker generates two responses,
    the first is interpreted as a response to the attacker's request,
    while the second remains in limbo.
    When the user makes a legitimate request through the same TCP connection,
    the attacker's request is already waiting and is interpreted as a response
    to the victim's request. The attacker then sends a second request to the server,
    to which the proxy server responds with the server generated request intended for the victim,
    thereby compromising any sensitive information in the headers
    or body of the response intended for the victim.
    页面注入:除了使用有漏洞的应用程序发送恶意的内容给用户之外,
    同根的弱点也可以产生杠杆作用,发送通过服务器产生的敏感信息,
    并且通过用户发送给攻击者来代替。
    通过提交一个在两个响应中产生的请求,这两个响应分别是从服务器来的响应和攻击者产生的响应,
    攻击者可以使一个中间的代码,比如一个共享的代理服务器,
    误导一个服务器产生的响应发送给攻击者。
    因为攻击者制造的请求可以产生两个响应,
    第一个被解释成一个回复攻击者的响应,当第二个还没有过来的时候。
    当用户通过相同的TCP连接产生一个合法的请求时,
    攻击者的请求通常正在等待,并且被解释为用户请求的响应。
    攻击者马上发送第二个请求给服务器,
    到代理服务器所产成的响应用户来的请求,
    从而,危及头信息中的敏感信息和发送给用户的响应体。
    24.4.RECOMMENDATIONS 建议
    The solution to HTTP response splitting is to ensure
    that input validation occurs in the correct places and checks for the correct properties.
    HTTP响应分离的解决方案是确认,
    输入验证存在正确的地方,并且是为关键属性检查使用的。
    Since HTTP response splitting vulnerabilities occur
    when an application includes malicious data in its output,
    one logical approach is to validate data immediately
    before it leaves the application. However,
    because web applications often have complex
    and intricate code for generating responses dynamically,
    this method is prone to errors of omission (missing validation).
    An effective way to mitigate this risk is to also perform input validation
    for HTTP response splitting.
    于是当应用程序在它的输出中包含恶意数据的时候,
    HTTP响应分离漏洞出现了,一个逻辑上的方法是,在它离开应用程序之前,
    马上验证数据。
    但是,因为web应用程序常常有为了产生动态响应的复杂和难于理解的代码,
    于是方法倾向于冗长的错误(缺少验证)。
    减少这个风险的一个有效的方法就是为HTTP响应分离执行输入验证。
    Web applications must validate their input to prevent other vulnerabilities,
    such as SQL injection, so augmenting an application's existing input validation mechanism
    to include checks for HTTP response splitting is generally relatively easy.
    Despite its value, input validation for HTTP response splitting
    does not take the place of rigorous output validation.
    An application may accept input through a shared data store or other trusted source,
    and that data store may accept input
    from a source that does not perform adequate input validation.
    Therefore, the application cannot implicitly rely on the safety of this or any other data.
    This means the best way to prevent HTTP response splitting vulnerabilities
    is to validate everything that enters the application or leaves the application destined
    for the user.
    web应用程序必须验证他们的输入,以预防其它漏洞,
    比如SQL注入,所以加强应用程序输入验证机制,
    包括HTTP响应分离检查一般是比较容易的。
    不管如何,对于HTTP响应分离的输入验证不能代替严格的输入验证。
    应用程序可以通过一个共享的输入存储或者其它的可信任的源接受输入,
    并且数据存储可以接受没有充分的执行输入验证的源的输入。
    所以,应用程序不能暗中依赖这些数据的安全。
    这个意思就是,预防HTTP响应分离的最好方法就是,验证进入应用程序的任何数据和
    离开应用程序发送给用户的数据。
    The most secure approach to validation for HTTP response splitting
    is to create a whitelist of safe characters
    that are allowed to appear in HTTP response headers
    and accept input composed exclusively of characters in the approved set.
    For example, a valid name might only include alpha-numeric characters or an account number
    might only include digits 0-9.
    验证HTTP响应最安全的方法是创建一个列入优良名单的安全字符串,
    这些字符串允许出现在HTTP响应头信息中,并且在经过核准的设置中接受专有的字符串。
    例如,一个合法的名字将仅仅包含阿拉伯字母或者一个帐户仅仅包含数字0~9。
    A more flexible, but less secure approach is known as blacklisting,
    which selectively rejects or escapes potentially dangerous characters before using the input.
    In order to form such a list,
    you first need to understand the set of characters
    that hold special meaning in HTTP response headers.
    Although the CR and LF characters are at the heart of an HTTP response splitting attack,
    other characters, such as ':' (colon) and '=' (equal),
    have special meaning in response headers as well.
    一个稍微灵活点的,但是不是那么安全的方法是建立黑名单,
    在使用输入之前,有选择性的拒绝嵌在的危险字符。
    未了匹配这样的一个列表,
    你首先需要去理解在HTTP响应的头中保存特殊含义字符的设置。
    当然CR和LF字符是一个HTTP响应分离攻击的关键字符,
    其它字符,比如':'和'=',一样在响应的头中有特殊的含义。
    Once you identify the correct points in an application
    to perform validation for HTTP response splitting attacks
    and what special characters the validation should consider,
    the next challenge is to identify how your validation handles special characters.
    The application should reject any input destined to be included in HTTP response headers
    that contains special characters, particularly CR and LF, as invalid.
    一旦你确认了一个应用程序中的正确输入,
    为HTTP响应分离攻击执行验证的输入,并且验证需要注意的特殊字符是什么,
    下一个挑战就是确认你的验证怎样处理特定的字符。
    Many application servers attempt to limit an application's exposure
    to HTTP response splitting vulnerabilities by providing implementations
    for the functions responsible for setting HTTP headers
    and cookies that perform validation for the characters essential
    to an HTTP response splitting attack.
    Do not rely on the server running your application to make it secure.
    When an application is developed there are no guarantees about
    what application servers it will run on during its lifetime.
    As standards and known exploits evolve, there are no guarantees
    that application servers will also stay in sync.
    许多应用程序打算去限制应用程序的HTTP响应分离漏洞的暴露,
    通过提供设置HTTP头和cookies的函数的实现,
    cookies为基本的字符执行验证。
    不要依赖服务器运行你的应用程序去确认。
    当应用程序还在开发的时候,不能保证在它的生命周期中,
    它将会运行在什么样的应用服务器上。
    当标准和公认的开发在发展中,不能保证,应用程序的服务器也会同步。
    24.5.TIPS 提示
    1. Many HttpServletRequest implementations return a URL-encoded string from getHeader(),
    will not cause a HTTP response splitting issue
    unless it is decoded first because the CR and LF characters
    will not carry a meta-meaning in their encoded form. However,
    this behavīor is not specified in the J2EE standard and varies by implementation.
    Furthermore, even encoded user input returned from getHeader()
    can lead to other vulnerabilities, including open redirects and other HTTP header tampering.
    许多HttpServletRequest实现从getHeader()中返回一个URL编码的字符串,
    将不会出现HTTP响应分离的情况,直到它被第一次解码,
    因为CR和LF字符在它们编码的过程中,将不支持一个meta样式的字符。
    但是,在J2EE标准和通过实现变化的应用程序中,这些行为不会详细说明的。
    此外,从getHeader()中返回的已经经过编码的用户输入可以导致其它的漏洞,
    包括打开的重定向路径和其它的HTTP头信息篡改。
    24.6.REFERENCES 引用
    [1] Divide and Conquer: HTTP Response Splitting, Web Cache Poisoning Attacks,
    and Related Topics, A. Klein,
    http://www.packetstormsecurity.org/papers/general/whitepaper_httpresponse.pdf
    [2] HTTP Response Splitting, D. Crab,
    http://www.infosecwriters.com/text_resources/pdf/HTTP_Response.pdf

  • Fortify分析翻译8

    2008-09-02 20:01:18

              Fortify分析翻译8

                           http://user.qzone.qq.com/281696143/blog/1219905860 Ronger

    22.Process Control(Data Flow):
    22.1.源文件:AgentServlet.java.
    代码:obj = this.getClass().getClassLoader().loadClass(servletName).newInstance();
    22.2.原文:Loading libraries from an untrusted source or in an untrusted environment
    can cause an application to execute malicious commands on behalf of an attacker.
    翻译:从一个不值得信任的库或者环境加载库将使得应用程序去执行一个恶意的攻击命令。
    理解:在次不值得信任的库指的就是参数servletName。
    22.3.EXPLANATION 解释
    Process control vulnerabilities take two forms:
    过程控制弱点可以归纳为两种模式:
    - An attacker can change the name of the library that the program loads:
    the attacker explicitly controls what the name of the library is.
    一个攻击者可以改变程序加载的库的名字:
    攻击者可以显式的控制库的名字是什么。
    - An attacker can change the environment in which the library loads:
    the attacker implicitly controls what the library name means.
    一个攻击者可以改变库加载的环境:
    攻击者可以隐式的控制库名字的用意。
    In this case we are primarily concerned with the first scenario,
    the possibility that an attacker may be able to control the name of the library that is loaded. Process control vulnerabilities of this type occur when:
    在这种情况下,我们首先关注最早的设定,
    可能是这样,攻击者能够控制加载的库的名字。
    22.3.1. Data enters the application from an untrusted source.
    In this case the data enters at getInitParameter()
    in web/common/monitor/AgentServlet.java at line 143.
    数据从一个不可信任的源进入应用程序。
    在这种情况下,在AgentServlet.java的143行数据通过getInitParameter()进入。
    22.3.2. The data is used as or as part of a string representing a library
    that is loaded by the application.
    In this case the library is loaded by loadClass()
    in web/common/monitor/AgentServlet.java at line 147.
    数据作为一个字符串或者字符串的一部分,这个字符串是用来描述通过应用程序导入的库的。
    在这种请款下,库是通过loadClass()来加载,在AgentServlet.java的147行。
    22.3.3. By executing code from the library,
    the application gives the attacker a privilege or capability
    that the attacker would not otherwise have.
    通过执行从库中的代码,
    应用程序给攻击者一个另外具有的特权或者能力。
    Example 1: The following code from a privileged system utility
    uses the system property APPHOME to determine the directory in
    which it is installed and then loads a native library based on a relative path
    from the specified directory.
    例子1:下面的代码,使用了系统特性,使用系统属性APPHOME决定
    安装的路径,并且基于这个路径的一个相对路径而加载一个临时的库。
    ...
    String home = System.getProperty("APPHOME");
    String lib = home + LIBNAME;
    java.lang.Runtime.getRuntime().load(lib);
    ...
    This code allows an attacker to load a library
    and potentially execute arbitrary code with the elevated privilege of the application
    by modifying the system property APPHOME to point
    to a different path containing a malicious version of LIBNAME.
    Because the program does not validate the value read from the environment,
    if an attacker can control the value of the system property APPHOME,
    then they can fool the application into running malicious code and take control of the system.
    这段代码允许攻击者加载一个库,并且通过修改系统属性APPHOME指向一个不同的
    包含恶意版本的LIBNAME,潜在的执行任意的代码。
    因为程序没有验证从环境中读入的值,
    如果攻击者可以控制系统属性APPHOME的值,
    那么他们可以使应用程序执行恶意的代码并且控制系统。
    Example 2: The following code uses System.loadLibrary() to load code
    from a native library named library.dll,
    which is normally found in a standard system directory.
    例子2:下面的代码使用System.loadLibrary(),从一个命名为library.dll的临时库
    中加载代码,library.dll通常可以在标准系统目录中可以找到。
    ...
    System.loadLibrary("library.dll");
    ...
    The problem here is that System.loadLibrary() accepts a library name,
    not a path, for the library to be loaded.
    From the Java 1.4.2 API documentation this function behaves as follows [1]:
    这儿的程序是这样的,System.loadLibrary()接受一个库的名字,
    不是一个路径,通过名字这个库被加载。
    从Java1.4.2的API文档中,这个函数行为和下面的[1]一样。
    A file containing native code is loaded from the local file system from a place
    where library files are conventionally obtained.
    The details of this process are implementation-dependent.
    The mapping from a library name to a specific filename is done in a system-specific manner.
    一个包含本地代码的文件是从本地文件系统加载的,这个本地文件系统是从库文件被包含的地方加载的。
    这个过程的细节是由实现决定的。
    从一个库名字到一个特定文件名的映射是由系统的样式决定的。
    If an attacker is able to place a malicious copy of library.dll higher
    in the search order than file the application intends to load,
    then the application will load the malicious copy instead of the intended file.
    Because of the nature of the application, it runs with elevated privileges,
    which means the contents of the attacker's library.dll will now be run with elevated privileges,
    possibly giving them complete control of the system.
    如果攻击者能够可以对library.dll进行一个恶意的拷贝,
    这个拷贝比应用程序加载的文件有更高的搜索顺序,
    那么应用程序将加载这个恶意的拷贝代替已经确定的文件。
    因为应用程序的本性,它将执行优先级更高的,
    这个意味着攻击者的library.dll的内容将拥有更高优先级而被运行,
    有可能让他们完全的控制系统。
    22.4.RECOMMENDATIONS 建议
    Do not allow users to control libraries loaded by the program.
    In cases where user input must affect the choice of the library to load,
    the application typically expects a particular input to take on only a very small set of values.
    Rather than relying on the input to be safe and non-malicious,
    the application should use the input only
    to make a selection from a predetermined set of safe libraries.
    If the input appears to be malicious,
    the library to be loaded should either default to some safe selection from this set
    or the program should gracefully decline to continue operation.
    不要允许用户去控制程序加载的库。
    在某种情况下,用户输入可以影响要加载的库的选择,
    应用程序期望特别的输入可以进来,这些合法的值仅仅有一个很小的范围。
    比依赖于输入更加安全和不会有恶意数据的是,
    应用程序可以使用选择输入,从预先定义的安全库中选择。
    如果输入显示为恶意的,
    加载的库可以使用安全选择的库中的默认库,
    或者程序可以拒绝继续执行。
    An attacker can indirectly control the libraries
    loaded by a program by modifying the environment.
    The environment should not be trusted
    and precautions should be taken to prevent an attacker
    from using some manipulation of the environment to perform an attack.
    Whenever possible,library names should be controlled by the application
    and loaded using an absolute path passed to System.load().
    System.loadLibrary() should be avoided because its behavīor is implementation dependent.
    In cases where the path is not known at compile time,
    an absolute path should be constructed from trusted values during execution.
    Library names and paths read from the environment
    should be sanity-checked against a set of invariants that define valid values.
    攻击者可以通过修改环境,间接的控制程序加载的库。
    环境是不可以信任的,并且要预防攻击者,使用对环境的处理来实施攻击。
    当可能的时候,库名字应该被应用程序控制,并且使用一个绝对路径加载给System.load().
    System.loadLibrary()最好避免使用,因为它的行为是依赖实现的。
    在一些情况下,路径在编译时是不直到的,
    在运行时一个绝对的路径可以从一个安全值构造。
    库名字和路径从环境中读入,应该理智检查一系列定义好有效值的变量。
    Other checks can sometimes be performed to detect
    if the environment may have been tampered with. For example,
    if a configuration file is world-writable, the program might refuse to run.
    In cases where information about the library to be loaded is known in advance,
    the program may perform checks to verify the identity of the file.
    If a library should always be owned by a particular user
    or have a particular set of access permissions assigned to it,
    these properties can be verified programmatically before it is loaded.
    其它的检查有时候也可以实施探测到,环境信息被篡改的时候。例如,
    如果一个配置文件是可以被随便改写的,程序将拒绝执行。
    在这种情况中,加载的库的信息是被预先知道的,
    程序将实施检查去合适文件的合法性。
    如果一个库总是被一个特殊的用户所拥有,或者有一个分配给它的特殊的存取许可,
    这些属性在它被加载之前,可以被程序检测到。
    In the end it may be impossible for a program to fully protect itself
    from an imaginative attacker bent on controlling the libraries it loads.
    You should strive to identify
    and protect against every conceivable manipulation of input values and the environment.
    The goal should be to shutdown as many attack vectors as possible.
    最后,对于一个程序来说,不可能完全的保护它,被一个想象的攻击者基于控制加载的库方面的攻击。
    你可以努力去核实,并且检查输入数据和环境的每一个可能的处理。
    22.5.REFERENCES 引用
    [1] Java 1.4.2 API Documentation, Sun Microsystems,
    http://java.sun.com/j2se/1.4.2/docs/api/index.html
    23.Password management(Data Flow):
    23.1.源文件:WLIContextHolder.java
    代码:env.put(Context.SECURITY_CREDENTIALS, passwd);
    23.2.原文:Storing a password in plaintext may result in a system compromise.
    翻译:基于折衷考虑用一个清晰的文本保存密码。
    理解:也是从项目的安全性(密码管理)方面来考虑,在次Fortify将次风险归纳为warning级别。
    23.3.EXPLANATION 解释
    Password management issues occur
    when a password is stored in plaintext in an application's properties or configuration file.
    密码管理情况出现在,当一个密码以明码保存在一个程序的属性或者配置文件中。
    In this case, the password is read into the program at executeQuery()
    in wf/common/WLIContextHolder.java at line 102 and used to access a resource at put()
    in wf/common/WLIContextHolder.java at line 206.
    在这种情况下,密码在WLIContextHolder.java的102行的executeQuery()被读入程序,
    并且在WLIContextHolder.java的206行使用put()方法进行存取。
    Example: The following code reads a password from a properties file
    and uses the password to connect to a database.
    例如:下面的代码使用一个属性文件读取密码,并且使用密码连接数据库。
    ...
    Properties prop = new Properties();
    prop.load(new FileInputStream("config.properties"));
    String password = prop.getProperty("password");
    DriverManager.getConnection(url, usr, password);
    ...
    This code will run successfully,
    but anyone who has access to config.properties can read the value of password.
    If a devious employee has access to this information,
    they can use it to break into the system.
    这个代码将运行的很成功,
    但是已经存取数据到config.properties的一些人可以读到密码的值。
    如果一个雇员获得这些信息,他们可以使用它中断系统。
    23.4.RECOMMENDATIONS 建议
    A password should never be stored in plaintext. Instead,
    the password should be entered by an administrator when the system starts.
    If that approach is impractical,
    a less secure but often adequate solution is to obfuscate the password
    and scatter the de-obfuscation material around the system so that an attacker
    has to obtain and correctly combine multiple system resources to decipher the password.
    密码不能使用明码来存储。可以这样来操作,
    当系统启动的时候,密码可以通过管理员输入。
    如果这个方法不可行,
    一个安全级别低点但是经常采用的解决方案是使密码模糊,
    并且分散令人迷惑的信息围绕系统,于是攻击者要去包含和正确的结合系统的多个资源,
    去译解密码。
    Some third party products claim the ability to manage passwords in a more secure way.
    For example, WebSphere Application Server 4.x uses a simple XOR encryption algorithm for obfuscating values,
    but be skeptical about such facilities.
    WebSphere and other application servers offer outdated and relatively weak encryption mechanisms
    that are insufficient for security-sensitive environments.
    For a secure solution,
    the only viable option today appears to be a proprietary mechanism that you create.
    一些第三方的产品以一些更加安全的方法,强化了管理密码的能力。
    例如,WebSphere应用服务器4.x使用一个简单的XOR编码法则,进行模糊数据,
    但是让人怀疑它的简易性。
    WebSphere和其它的应用服务器提供了过时的和相对的虚弱的编码机制,
    对一个安全敏感的环境来说,是不足的。
    对一个安全的解决方案来说,
    今天仅仅可行的选择是,显示你创建的私人拥有的密码的机制。
    23.5.TIPS 提示
    23.5.1. Fortify identifies password management issues by looking for functions
    that are known to take passwords as arguments.
    If a password is read in from outside the program
    and does not pass through an identified de-obfuscation routine
    before being used, then Fortify flags a password management issue.
    Fortify通过扫描函数来确定密码管理事件,这个函数将密码当成参数。
    如果一个密码从程序的外部读入,并且在被使用前,没有经过一个确定的模糊处理,
    那么Fortify将标示为一个密码管理器事件。
    23.5.2.To audit a password management issue,
    trace through the program from the point at
    which the password enters the system to the point at which it is used.
    Look for code that performs de-obfuscation. If no such code is present,
    then this issue has not been mitigated.
    If the password passes through a de-obfuscation function,
    verify that the algorithm used to protect the password is sufficiently robust.
    审计一个密码管理器事件,从密码进入系统的这一点,开始追踪程序。
    寻找实现了模糊处理的代码。如果没有这样的代码存在,
    那么这些事件就没有被减轻。
    如果密码通过一个模糊函数处理,
    验证表明,这个用来保护密码的规则不够强壮。
    23.5.3.Once you are convinced that the password is adequately protected,
    write a custom pass-through rule for the de-obfuscation routine
    that indicates that the password is protected with obfuscation.
    If you include this rule in future analyses of the application,
    passwords that pass through the identified de-obfuscation routine
    will no longer trigger password management vulnerabilities.
    一旦你确信,密码被充分的保护好了,
    为密码模糊写一个用户通过规则,表明密码被模糊规则保护。
    在未来对应用程序的分析中,如果你包含这个规则,
    通过模糊规则确定的密码将不会触发密码管理器漏洞。

  • Fortify分析翻译7

    2008-08-27 15:13:06

                   Fortify分析翻译7
                           http://user.qzone.qq.com/281696143/blog/1219735929  Ronger
    19.Missing XML validation(Control Flow):
    19.1.源文件:QueryPrivilegeConfig.java.
    代码:db = dbf.newDocumentBuilder();
    19.2.原文:Failure to enable validation
    when parsing XML gives an attacker the opportunity to supply malicious input..
    翻译:因为没有去验证,所以当解析XML的时候会给攻击者一个输入恶意数据的机会。
    19.3.EXPLANATION 解释
    Most successful attacks begin with a violation of the programmer's assumptions.
    By accepting an XML document without validating it against a DTD or XML schema,
    the programmer leaves a door open for attackers to provide unexpected, unreasonable,
    or malicious input.
    It is not possible for an XML parser to validate all aspects of a document's content;
    a parser cannot understand the complete semantics of the data.
    However, a parser can do a complete and thorough job of checking the document's structure
    and therefore guarantee to the code that processes the document that the content is well-formed.
    大多数成功的攻击开始于程序假设的违背。
    接受一个没有通过DTD或者是schema验证的XML文档,
    程序员为攻击者打开了一扇门,攻击者可以提供不可预期的,不合理的,或者是恶意的输入。
    对一个XML解析器来说不可能验证一个文档内容的所有预期;
    解析器不能理解数据的全部语义。
    但是,解析器可以为检查一个文档的结构,做一个完整的和彻底的工作,
    并且保证有合法结构的文档中的代码。
    In this case, validation is not enabled
    on the XML parser or parser factory allocated
    in common/bizservice/queryprivilege/impl/QueryPrivilegeConfig.java at line 86.
    在这个例子中,验证在XML解析器或者解析工厂中是不允许的,
    在QueryPrivilegeConfig.java的86行代码。
    19.4.RECOMMENDATIONS 建议
    Always enable validation when you create an XML parser or parser factory.
    If enabling validation causes problems
    because the rules for defining a well-formed document
    are Byzantine or altogether unknown, chances are good
    that there are security errors nearby.
    当你创建一个XML解析器或者解析工厂的时候,应该允许验证。
    如果有利的验证问题的原因,因为规则的定义以及形成的文件是完全未知的,
    有可能有安全性错误在附近。
    Below are examples that demonstrate
    how to enable validation for the Xerces parsers (both DOM and SAX):
    org.apache.xerces.framework.XMLParser: parser.setValidation(true);
    org.apache.xerces.framework.XMLParser: parser.setValidationSchema(true);
    下面是例子,示范对解析器来说如何去可以验证(DOM和SAX):
    The following examples demonstrate how to enable validation for the SAX
    and DOM parser factories in the javax library.
    下面的例子示范,在javax库中,如何对SAX和DOM解析器工厂进行验证。
    javax SAX parser factory:
    javax.xml.parsers.SAXParserFactory: factory.setValidating(true);
    javax.xml.parsers.SAXParserFactory: factory.setFeature("
    http://xml.org/sax/features/validation", true);
    javax DOM parser factory:
    javax.xml.parsers.DocumentBuilderFactory: factory.setValidating(true);
    The following examples demonstrate
    how to enable validation for individual parsers and XMLReaders in the javax library.
    下面的例子示范,在javax库中,如何对个人解析器和XMLReaders进行验证。
    Note: Fortify does not recommend enabling validation by this method.
    Instead, you should enable validation at the parser factory.
    注意:Fortify不推荐通过这个方法来进行验证。
    可以这样,你可以在解析工厂中验证。
    javax SAX parser and reader:
    javax.xml.parsers.SAXParser: parser.setProperty("
    http://xml.org/sax/features/validation",
    new Boolean(true));
    org.xml.sax.XMLReader: reader.setFeature("
    http://xml.org/sax/features/validation", true);
    19.5.TIPS 提示
    Fortify checks to ensure that javax parser factories enable validation
    before they are used to create parsers.
    By ensuring that the parser factory always creates validating parsers,
    there is less opportunity for error when creating and using a parser.
    在他们被用作创建解析器之前,Fortify检查确认javax解析工厂允许验证。
    通过确认解析工厂创建有验证功能的解析器,
    当创建和使用解析器的时候,很少有机会会发生错误。
    19.6.REFERENCES 引用
    19.6.1.Xerces parser features, The Apache Foundation,
    http://xml.apache.org/xerces2-j/features.html
    19.6.2.XML Validation in J2SE 1.5, Sun Microsystems,
    http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/validation/package-summary.html
    20.Code Correctness():Erroneous class compare(Data Flow):
    20.1.源文件:BizHandledQueryDAO.java
    代码:if(dataMap.get("comment_issuing_time").getClass().getName().
    equals("oracle.sql.DATE"))
    20.2.原文:Determining an object's type based on its class name
    can lead to unexpected behavīor or allow an attacker to inject a malicious class..
    翻译:根据类名来决定一个对象的类型将会引起不可预料的行为,例如攻击者注入一个恶意的类型。
    理解:在此处是从项目的安全性考虑,攻击者可以在dataMap中注入类型为"oracle.sql.DATE"来让这段程序执行。
    20.3.EXPLANATION 解释
    Attackers may deliberately duplicate class names
    in order to cause a program to execute malicious code.
    For this reason, class names are not good type identifiers
    and should not be used as the basis for granting trust to a given object.
    攻击者可以有意的复制类名,为了使程序执行恶意的代码。
    因为这个原因,类名不是好的身份标示,并且不能用作一个特定对象的信任依据。
    Example 1: The following code opts to trust
    or distrust input from an inputReader object based on its class name.
    If an attacker is able to supply an implementation of inputReader
    that executes malicious commands,
    this code will be unable to differentiate the benign and malicious versions of the object.
    例子1:下面的代码操作信任或者不信任从一个inputReader对象来的输入,
    这个inputReader对象是基于它的类名的。
    如果一个攻击这可以提供一个inputReader的实现,这个inputReader可以执行恶意的命令。
    这个代码不能区分对象的良好的和恶意的版本。
    if (inputReader.getClass().getName().equals("TrustedName"))
    {
       input = inputReader.getInput();
       ...
    }
    20.4.RECOMMENDATIONS 建议
    Always use a class-equivalence comparison to identify the type of an object.
    Do not rely on class names to convey type information.
    一直使用一个类比较器去确定对象的类型。不要依赖类名来传达类型信息。
    Example 2: The following code has been rewritten
    to use a class-equivalency comparison to determine whether inputReader object
    has the expected type.
    例子2:下面的代码使用类相等比较来进行重写,决定inputReader对象是否是期望的类型。
    if (inputReader.getClass() == TrustedClass)
    {
       input = inputReader.getInput();
       ...
    }

  • Fortify分析翻译6

    2008-08-27 15:11:21

                   Fortify分析翻译6
              http://user.qzone.qq.com/281696143/blog/1219655341  Ronger
    16. Code correctness:Erroneous String compare(Structural):
    16.1.源文件:BizApplicationApprovalBackingBean.java
    代码:  if ((briefBizTaskVO.getDeptCode() != null) && (briefBizTaskVO.getDeptCode() != "")) {
    16.2.原文:Strings should be compared with the equals() method, not == or !=.
    翻译:字符串的比较要用equals方法,而不是==或者!=.
    16.3.EXPLANATION 解释
    This program uses == or != to compare two strings for equality,
    which compares two objects for equality, not their values.
    Chances are good that the two references will never be equal.
    程序使用==或者!=来比较两个字符串是否相等,
    这个是比较两个对象是否相等,而不是他们的值。
    这两个引用是不会相等的。
    Example 1: The following branch will never be taken.
    例子1:下面的分支将不会发生。
      if (args[0] == STRING_CONSTANT) {
          logger.info("miracle");
      }
    The == and != operators will only behave as expected
    when they are used to compare strings contained in objects that are equal.
    The most common way for this to occur is for the strings to be interned,
    whereby the strings are added to a pool of objects maintained by the String class.
    Once a string is interned,
    all uses of that string will use the same object
    and equality operators will behave as expected.
    All string literals and string-valued constants are interned automatically.
    Other strings can be interned manually be calling String.intern(),
    which will return a canonical instance of the current string, creating one if necessary.
    这个==和!=操作符将有和期望一致的行为,
    当他们被使用,就是比较包含在对象中的字符串。
    对于这个出现最常见的方式是字符串被留住了,
    为何字符串被加到对象池中。
    一旦字符串被留住了,这个字符串的所用引用将使用相同的对象,
    并且相等操作符将和预想的行为一致。
    所有的字符串和字符串常量都被自动的留住。
    其它的字符串可以通过调用String.intern()来手工留住,
    将返回一个当前字符串的规范实例,如果需要就创建一个。
    16.4.RECOMMENDATIONS 建议
    Use equals() to compare strings.
    Example 2: The code in Example 1 could be rewritten in the following way:
    使用equals()比较字符串。
    例子2:例子1中的代码可以以下面的方式改写:
      if (STRING_CONSTANT.equals(args[0])) {
          logger.info("could happen");
      }
    16.5.TIPS 提示
    16.5.1. Developers will sometimes compare strings for reference equality
    in order to "avoid the inefficiency" of calling equals() right off the bat:
    开发者有时候会通过通过引用来比较字符串,
    为了"避免低效的"调用equals():
    if (args[0] == STRING_CONSTANT) {
        doWork(args[0]);
    } else if (STRING_CONSTANT.equals(args[0])) {
        doWork(args[0]);
    }
    16.5.2.In many circumstances this small performance gain comes at the cost of duplicated or convoluted code.
    Because String.equals() performs a == comparison before doing any deeper evaluation,
    the performance benefits of using == instead of String.equals()
    are limited to the overhead of performing a method call
    and are likely to be negligible in most environments.
    Do a performance comparison for your program.
    在许多情况下,这个小的性能增益是以成本重复或错综复杂的代码为代价的。
    因为String.equals()在做一些深层次的计算之前执行了==比较,
    使用==代替String.equals()的好处就是,
    在执行一个方法调用的头上是受限制的,并且在大多数的环境下是不受重视的。
    为你的程序做一个性能比较。
    17.System Information Leak(Semantic):
    17.1.源文件:AgentServlet.java.
    代码:catch (NamingException e) {
    e.printStackTrace();
    }
    17.2.原文:Revealing system data or debugging information
    helps an adversary learn about the system and form a plan of attack.
    翻译:展现系统数据或调试信息将帮助攻击者了解系统和制定攻击的计划。
    理解:在次还可以从另外一个角度考虑,就是异常被吃掉了。
    17.3.EXPLANATION 解释
    An information leak occurs
    when system data or debugging information
    leaves the program through an output stream or logging function.
    系统漏洞出现了,当系统数据或者调试信息从程序去一个输出流或者一个日志函数。
    In this case printStackTrace()
    is called in web/common/monitor/AgentServlet.java at line 69.
    在这里printStackTrace()在AgentServlet.java的69行被调用。
    Example: The following code prints an exception to the standard error stream:
    例如:下面的代码打印一个异常到标准错误流:
    try {
        ...
    } catch (Exception e) {
        e.printStackTrace();
    }
    Depending upon the system configuration, this information can be dumped to a console,
    written to a log file, or exposed to a remote user.
    In some cases the error message tells the attacker precisely
    what sort of an attack the system is vulnerable to. For example,
    a database error message can reveal
    that the application is vulnerable to a SQL injection attack.
    Other error messages can reveal more oblique clues about the system.
    In the example above,
    the search path could imply information about the type of operating system,
    the applications installed on the system,
    and the amount of care that the administrators have put into configuring the program.
    依靠系统配置,这些信息会倾卸到控制台上,
    写到一个日志文件中,或者暴露给远端用户。
    在一些情况下,错误信息告诉明确的告诉攻击者,
    系统易受攻击的类型。例如,一个数据库错误信息将暴露,
    应用程序易受SQL注入攻击。
    其它的错误信息将暴露更多的关于这个系统的间接信息。
    在上面的例子中,搜索路径将暗示关于操作系统类型的信息,
    应用程序安装在系统上的信息,和管理员已经设置进程序的一些重要的数量信息.
    17.4.RECOMMENDATIONS 建议
    Write error messages with security in mind. In production environments,
    turn off detailed error information in favor of brief messages.
    Restrict the generation and storage of detailed output
    that can help administrators and programmers diagnose problems.
    Be careful, debugging traces can sometimes appear in non-obvious places
    (embedded in comments in the HTML for an error page, for example).
    在头脑中写出安全的错误信息。在产品环境中,
    关闭详细错误信息,用摘要信息代替。
    限制详细输出的产生和存储可以帮助管理员和程序员诊断程序。
    小心,调试痕迹有时候会显示在确定的地方(HTML中错误页面的嵌入式的注释,例如)。
    Even brief error messages
    that do not reveal stack traces or database dumps can potentially aid an attacker.
    For example, an "Access Denied" message can reveal that a file or user exists on the system.
    甚至没有显示堆栈信息或者数据库的摘要错误信息会隐含的帮助攻击者。
    例如,一个"存取拒绝"消息可以显示一个文件或者用户存在系统中。
    17.5.TIPS 提示
    17.5.1. Do not rely on wrapper scrīpts, corporate IT policy,
    or quick-thinking system administrators to prevent system information leaks.
    Write software that is secure on its own.
    不要依赖包装的脚本,全部的IT政策,
    或者管理员的快速思考,来预防系统信息漏洞。
    17.5.2. This category of vulnerability does not apply to all types of programs.
    For example, if your application executes on a client machine
    where system information is already available to an attacker,
    or if you print system information only to a trusted log file,
    you can use AuditGuide to filter out this category.
    这些弱点的归类不是应用在所有类型的程序上面。
    例如,如果你的应用程序在一个客户端机器上面执行,
    系统信息对攻击者来说总是有效的,
    或者如果你仅仅将信息打印到可信任的日志文件上面,
    你可以使用AuditGuide去过滤掉这些归类。
    18. J2EE bad practices:Leftover threads(Semantic):   
    18.1.源文件:Metronome.java.
    代码:  tempCon= new Container(tempClassName,tempTime);
    18.2.原文:Thread management in a web application is forbidden in some circumstances and is always highly error prone..
    翻译:在wen应用程序中线程管理器在一些情况下会被禁止,并且总是有很高的错误倾向。
    18.3.EXPLANATION 解释
    Thread management in a web application is forbidden by the J2EE standard in some circumstances and is always highly error prone.
    Managing threads is difficult and is likely to interfere in unpredictable ways with the behavīor of the application container.
    Even without interfering with the container, thread management usually leads to bugs that are hard to detect and diagnose like deadlock,
    race conditions, and other synchronization errors.
    在web应用程序中线程管理器在一些情况下会被禁止,并且总是有很高的错误倾向。管理线程是困难的,
    并以不可预料的方式去妨碍应用程序容器的行为。即使没有妨碍容器,线程管理器通常也容易导致很难调试的bug
    ,死锁,程序紊乱,或者其它的线程错误。
    18.4.RECOMMENDATIONS 建议
    Avoid managing threads directly from within the web application.
    Instead use standards such as message driven beans
    and the EJB timer service that are provided by the application container.
    避免直接使用web应用程序来管理线程。
    使用标准的东西来代替,比如消息驱动bean和应用程序容器提供的EJB时间服务。
    18.5.TIPS 提示
    If you are auditing a non-J2EE Java application,
    the J2EE Bad Practices categories may not apply to your environment.
    If this is the case, you can use AuditGuide to suppress these issues.
    如果你审核一个非J2EE的应用程序,
    J2EE的坏习惯分类不可以应用到你的环境中。
    如果这儿是这种情况,你可以使用AuditGuide跳过这些情况。
    18.6.REFERENCES 引用
    [1] Java 2 Platform Enterprise Edition Specification, v1.4,
    Sun Microsystems,
    http://java.sun.com/j2ee/
  • Fortify分析翻译5

    2008-08-27 15:09:37

                                  Fortify分析翻译5
                           http://user.qzone.qq.com/281696143/blog/1219648603  Ronger
    13. Poor error handling:Overly broad catch(Structural):
    13.1.AcceptApplicationBackingBean.java
    catch(Exception e){
    13.2.原文:The catch block handles a broad swath of exceptions,
    potentially trapping dissimilar issues or problems
    that should not be dealt with at this point in the program..
    翻译:这个捕捉异常的块可以处理所有的异常,潜在的陷入了在这段程序中不能处理的不同问题。
    理解:如果捕捉exception,就不能让处理异常的逻辑细化,
    也就是所有的异常都按照同样的逻辑处理是不行的。
    13.3.EXPLANATION 解释
    Multiple catch blocks can get ugly and repetitive,
    but "condensing" catch blocks by catching a high-level class like Exception can obscure exceptions
    that deserve special treatment or that should not be caught at this point in the program.
    Catching an overly broad exception essentially defeats the purpose of Java's typed exceptions,
    and can become particularly dangerous
    if the program grows and begins to throw new types of exceptions.
    The new exception types will not receive any attention.
    多重的异常捕捉块可能会变得丑陋和重复的,
    但是通过一个高层异常(比如Exception)"浓缩"的捕捉块将模糊异常,
    这个异常应该有不同的处理,并且在程序的这个点上不能捕捉到。
    捕捉一个过分广泛的异常将从本质上违背了Java对异常分类的目的,
    如果程序修改并且增加一个新类型的异常,会变得特别的危险。
    新异常类型将不会接受异常处理。
    Example: The following code excerpt handles three types of exceptions in an identical fashion.
    例如:下面的代码摘录以同样的方式处理三种异常。
      try {
        doExchange();
      }
      catch (IOException e) {
        logger.error("doExchange failed", e);
      }
      catch (InvocationTargetException e) {
        logger.error("doExchange failed", e);
      }
      catch (SQLException e) {
        logger.error("doExchange failed", e);
      }
    At first blush, it may seem preferable to deal with these exceptions in a single catch block,
    as follows:
    马上,它可以使用一个单独的捕捉异常块更好的处理这些异常,像下面:
      try {
        doExchange();
      }
      catch (Exception e) {
        logger.error("doExchange failed", e);
      }
    However, if doExchange() is modified to throw a new type of exception
    that should be handled in some different kind of way,
    the broad catch block will prevent the compiler from pointing out the situation.
    Further, the new catch block
    will now also handle exceptions derived from RuntimeException such as ClassCastException,
    and NullPointerException, which is not the programmer's intent.
    但是,如果doExchange()被修改抛出一个新类型的异常,这个异常需要以一些不同的方式来处理,
    宽泛的捕捉块将防止编译器指向这种情况。
    更多的,新的捕捉块现在也可以处理起源于RuntimeException的异常,比如ClassCastException,
    和NullPointException,这些都不是程序员的意图。   
    13.4.RECOMMENDATIONS 建议
    Do not catch broad exception classes like Exception, Throwable, Error,
    or <RuntimeException> except at the very top level of the program or thread.
    除非在程序或者线程的顶部,不要捕捉宽泛的异常类,类似于:Exception,Throwable,Error,
    或者RuntimeException。
    13.5.TIPS 提示
    Fortify will not flag an overly broad catch block
    if the catch block in question immediately throws a new exception.
    Fortify不能标记一个过分宽泛的捕捉块,
    如果这个捕捉块有问题,马上就会抛出一个新异常。
    14. Poor logging practice:logger not declared static final(structual):
    14.1.CreditRatingApprovalDisplayUCCImpl.java
    private Logger logger = Logger.getLogger
    (CustomerManagerTeamBSImpl.class);
    原文:Declare loggers to be static and final..
    翻译:定义日志工具必须是static和final的。
    14.2.EXPLANATION 解释
    It is good programming practice to share a single logger object
    between all of the instances of a particular class
    and to use the same logger for the duration of the program.
    它是好的编程习惯,在所有特殊类的实例之间共享一个单独的日志对象,
    并且在程序的持续时间中使用相同的日志组件。
    Example 1: The following statement errantly declares a non-static logger.
    例子1:下面的语句定义了一个non-static日志组件。
    private final Logger logger =    
                Logger.getLogger(MyClass.class);
    14.3.RECOMMENDATIONS 建议
    Declare loggers to be static and final.
    Example 2: The code in Example 1 could be rewritten in the following way:
    定义日志组件为static和final类型。
    例子2:在例子1中的代码可以以下面的方式改写:
    private final static Logger logger =    
                Logger.getLogger(MyClass.class);
    15. Code correctness:null argument to equals(Structual):
    SystemCommonParameters.java
       if (obj==null||obj.equals(null)) {
    15.1.原文:The expression obj.equals(null) will always be false.
    翻译:表达式obj.equals(null)总是为false.
    15.2.EXPLANATION 解释
    The program uses the equals() method to compare an object with null.
    This comparison will always return false, since the object is not null.
    (If the object is null, the program will throw a NullPointerException).
    程序使用equals()方法来比较对象和null.
    这个比较将一直返回false,当然这是这个对象不是null的情况下.
    (如果这个对象是null,程序将抛出NullPointException).
    15.3.RECOMMENDATIONS 建议
    It is possible that the programmer intended to check to see if the object was null.
    可能是,程序员打算去检查,object对象是不是null.
    Instead of writing 更换下面的写法
    obj.equals(null)
    they intended 他们打算
    obj == null
    15.4.REFERENCES 引用
    [1] JavaDoc for Object, Sun Microsystems,
    http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)
    对象的Java文档地址
  • Fortify分析翻译4

    2008-08-27 15:06:20

                    Fortify分析翻译4
                                     http://user.qzone.qq.com/281696143/blog/1219395660
    10.System Information Leak(Data Flow):
    10.1.BizApplicationApprovalBackingBean.java.
         logger.error("BizApplicationApprovaBB 出错:" + e.getMessage());
    10.2.Revealing system data or debugging information helps an adversary learn about the system and form a plan of attack.
    展现系统数据或调试信息将帮助攻击者了解系统和制定攻击的计划。
    就是系统消息泄露。
    10.3.EXPLANATION 解释
    An information leak occurs
    when system data or debugging information leaves the program
    through an output stream or logging function.
    当系统数据或者调试数据离开程序进入输出流或者日志函数中的时候,信息漏洞就出现了。
    In this case printStackTrace() is called
    in bizprocess/loanorigination/bizapplication/starttask/bizservice/BizElementMapping.java
    at line 78.
    在这个例子中printStackTrace()在BizElementMapping.java的第78行被调用。
    Example: The following code prints an exception to the standard error stream:
    例如:下面的代码打印异常到标准的错误流中:
    try {
        ...
    } catch (Exception e) {
        e.printStackTrace();
    }
    Depending upon the system configuration,
    this information can be dumped to a console, written to a log file,
    or exposed to a remote user.
    In some cases the error message tells the attacker precisely
    what sort of an attack the system is vulnerable to.
    For example, a database error message can reveal
    that the application is vulnerable to a SQL injection attack.
    Other error messages can reveal more oblique clues about the system. In the example above,
    the search path could imply information about the type of operating system,
    the applications installed on the system,
    and the amount of care that the administrators have put into configuring the program.
    依靠系统配置,这些信息会被倾泻到控制台上,写入日志文件,或者暴露给一个远程的用户。
    在一些情况下,错误信息准确的告诉攻击者,系统弱点的类型。
    例如,一个数据库错误信息可以暴露出,应用程序容易受到SQL注入的攻击。
    其它的错误信息将暴露更多的关于系统的弱点的线索。在上面的例子中,
    搜索路径将暗示了如下信息,操作系统的类型,应用程序安装在系统中,
    和管理员设置进程序中的重要信息.
    10.4.RECOMMENDATIONS 建议
    Write error messages with security in mind. In production environments,
    turn off detailed error information in favor of brief messages.
    Restrict the generation and storage of detailed output
    that can help administrators and programmers diagnose problems.
    Be careful, debugging traces can sometimes
    appear in non-obvious places (embedded in comments in the HTML for an error page, for example).
    写错误信息的时候,头脑中应该有安全意识。在生产环境中,
    关掉详细错误信息,输出摘要信息。
    限制信息的产生和详细输出的存储可以帮助管理员和程序员诊断程序。
    小心,调试信息有时候也会显示在确定的地方(嵌在错误html页面中的注释,例如)。
    Even brief error messages that do not reveal stack traces or database dumps
    can potentially aid an attacker. For example,
    an "Access Denied" message can reveal that a file or user exists on the system.
    甚至没有暴露堆栈信息或者数据库信息的简短错误信息都可以隐含的帮助攻击者。例如,
    一个"存取拒绝"信息可以显示,一个文件或者用户存在系统中。
    10.5.TIPS 提示
    10.5.1. Do not rely on wrapper scrīpts, corporate IT policy,
    or quick-thinking system administrators to prevent system information leaks.
    Write software that is secure on its own.
    不要依赖包装的脚本,共同的IT政策,或者快速思考的管理员来预防系统信息漏洞。
    在软件中考虑它的安全。
    10.5.2. This category of vulnerability does not apply to all types of programs.
    For example, if your application executes on a client machine
    where system information is already available to an attacker,
    or if you print system information only to a trusted log file,
    you can use AuditGuide to filter out this category.
    这个弱点的分类不能应用在所有类型的程序中。
    例如,如果你的程序在一个客户端机器上执行,
    系统信息总是可以有效的显示给攻击者,
    或者如果你仅仅打印系统信息到一个可信任的日志文件,
    你可以通过审核过滤掉这些分类。
    11.Unreleased resource:Streams(Control Flow):
    11.1.ApproveCenterConfig.java.
    InputStream s = ApproveCenterConfig.class. getResourceAsStream
    ("/cn/ccb/clpm/common/rule/ApproveCenterConfigFile.xml");
    11.2.The program can potentially fail to release a system resource.
    程序有可能不能释放系统资源。
    在此处指变量s有可能没有释放资源。
    11.3.EXPLANATION 解释
    The program can potentially fail to release a system resource.
    In this case,
    there are program paths on which the resource allocated
    in rule/common/ApproveCenterConfig.java at line 28 is not released.
    程序有可能不能释放系统资源。
    在这个例子中,
    有一个程序路径不能释放,这个程序路径在ApproveCenterConfig.java的28行。
    Resource leaks have at least two common causes:
    资源漏洞至少有两个普通的原因:
    - Error conditions and other exceptional circumstances.
    错误条件和其它异常情况。
    - Confusion over which part of the program is responsible for releasing the resource.
    有责任释放资源的程序块是混乱的。
    Most unreleased resource issues result in general software reliability problems,
    but if an attacker can intentionally trigger a resource leak,
    the attacker might be able to launch a denial of service attack by depleting the resource pool.
    大多数没有释放资源的问题被归类为常见的软件可靠性问题,
    但是如果一个攻击者有意的引发一个资源漏洞,
    攻击者可以通过耗尽资源池来使服务停止。
    Example 1: The following method never closes the file handle it opens.
    The finalize() method for FileInputStream eventually calls close(),
    but there is no guarantee as to
    how long it will take before the finalize() method will be invoked.
    In a busy environment, this can result in the JVM using up all of its file handles.
    例子1:下面的方法没有关闭打开的文件。
    这个为FileInputStream服务的finalizi()方法最后会调用close(),
    但是没有保证,finalize()方法被调用需要多久。
    private void processFile(String fName) throws FileNotFoundException, IOException
    {
      FileInputStream fis = new FileInputStream(fName);
      int sz;
      byte[] byteArray = new byte[BLOCK_SIZE];
      while ((sz = fis.read(byteArray)) != -1) {
        processBytes(byteArray, sz);
      }
    }
    Example 2: Under normal conditions, the following code executes a database query,
    processes the results returned by the database, and closes the allocated statement object.
    But if an exception occurs while executing the SQL or processing the results,
    the statement object will not be closed. If this happens often enough,
    the database will run out of available cursors and not be able to execute any more SQL queries.
    例子2:正常的情况下,下面的代码执行一个数据库查询,
    通过数据库处理结果,并且关闭分配的statement对象。
    但是如果当执行SQL或者处理结果的时候,出现了异常,
    statement对象将无法关闭。如果这种情况经常发生,
    数据库将会在没有可用的游标下运行,并且不能去执行更多的SQL查询。
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery(CXN_SQL);
      harvestResults(rs);
      stmt.close();
    11.4.RECOMMENDATIONS 建议
    11.4.1. Never rely on finalize() to reclaim resources.
    In order for an object's finalize() method to be invoked,
    the garbage collector must determine that the object is eligible for garbage collection.
    Because the garbage collector is not required to run unless the JVM is low on memory,
    there is no guarantee that an object's finalize() method will be invoked in an expedient fashion.
    When the garbage collector finally does run,
    it may cause a large number of resources to be reclaimed in a short period of time,
    which can lead to "bursty" performance and lower overall system throughput.
    This effect becomes more pronounced as the load on the system increases.
    不要依赖于finalize()去收回资源。
    为了一个对象的finalize()被调用,垃圾回收器会决定对垃圾回收器来说,对象是合格的。
    因为直到JVM是在一个低内存状态的情况下,垃圾回收器才需要运行。
    一个对象的finalize()函数将以一种有利的方式运行,这是没有保证的。
    当垃圾回收器最后运行的时候,他将会使一大批资源在一个很短的时间内回收,
    此时将会导致系统吞吐量变低。
    当系统要加载的东西增多的时候,这些影响更加可以断定。
    Finally, if it is possible for a resource reclamation operation to hang
    (if it requires communicating over a network to a database, for example),
    then the thread that is executing the finalize() method will hang.
    最后,如果对于一个资源回收操作有可能挂起(如果它需要通过网络和数据库通信,例如),
    于是执行finalize()函数的线程将会挂起。
    11.4.2. Release resources in a finally block.
    The code for Example 2 should be rewritten as follows:
    在最后的语句块中释放资源。
    例子2的代码可以像下面一样重写:
      public void execCxnSql(Connection conn) {
        Statement stmt;
        try {
          stmt = conn.createStatement();
          ResultSet rs = stmt.executeQuery(CXN_SQL);
          ...
        }
        finally {
          if (stmt != null) {
            safeClose(stmt);
          }
        }
    }
    public static void safeClose(Statement stmt) {
      if (stmt != null) {
        try {
          stmt.close();
        } catch (SQLException e) {
          log(e);
        }
      }
    }
    This solution uses a helper function to log the exceptions that might occur
    when trying to close the statement. Presumably this helper function will be reused
    whenever a statement needs to be closed.
    当尝试关闭statement的时候,这个解决方案使用一个帮助函数记录异常。
    当一个statement需要关闭的时候,大概这个帮助函数将被重新使用。
    Also, the execCxnSql method does not initialize the stmt object to null.
    Instead, it checks to ensure that stmt is not null before calling safeClose().
    Without the null check, the Java compiler reports that stmt might not be initialized.
    This choice takes advantage of Java's ability to detect uninitialized variables.
    If  stmt is initialized to null in a more complex method,
    cases in which stmt is used without being initialized will not be detected by the compiler.
    当然,这个execCxnSql方法不能初始化stmt对象为null.
    首先,它将检查并确保,在调用safeClose()之前stmt不是null.
    没有null检查,Java编译器报告,stmt没有被初始化。
    这种选择,利用了Java编译器的能力,去检测没有初始化的变量。
    如果stmt在一个更加复杂的方法中被赋值为null,
    stmt没有被初始化就使用的这种情况,将不会被编译器探测到。
    12. Poor error handling:Overly broad throws(Structural):
    12.1.ArrangeMeetingBackingBean.java
    public String makeMeetingVOFromMeetingId() throws Exception{
    12.2.The method throws a generic exception making it harder for callers
    to do a good job of error handling and recovery..
    这个方法抛出一个一般的异常使得调用者很难做好错误处理和恢复。
    12.3.EXPLANATION 解释
    Declaring a method to throw Exception
    or Throwable makes it difficult for callers to do good error handling and error recovery.
    Java's exception mechanism is set up to make it easy for callers
    to anticipate what can go wrong
    and write code to handle each specific exceptional circumstance.
    Declaring that a method throws a generic form of exception defeats this system.
    定义一个抛出Exception或者Throwable的方法,对于调用者来说很难进行错误处理和错误恢复。
    Java的异常机制是建立在,使调用者更容易预期错误是什么和写代码处理每个特殊异常情况。
    定义一个抛出一般异常的方法打败了这个系统。
    Example: The following method throws three types of exceptions.
    例如:下面的方法抛出三种类型的异常.
    public void doExchange()
      throws IOException, InvocationTargetException,
             SQLException {
      ...
    }
    While it might seem tidier to write
    它看起来应该是处理异常的方法应该写的代码
    public void doExchange()
      throws Exception {
      ...
    }
    doing so hampers the caller's ability to understand and handle the exceptions that occur.
    Further, if a later revision of doExchange() introduces a new type of exception
    that should be treated differently than previous exceptions,
    there is no easy way to enforce this requirement.
    做这些,妨碍调用者理解和处理异常的能力。
    更深一层的,如果一个修改的doExchange()引入了一种新类型的异常,
    这个异常需要和以前的异常不同的处理方法,将不是那么容易来处理这个需求。
    12.4.RECOMMENDATIONS 建议
    Do not declare methods to throw Exception or Throwable.
    If the exceptions thrown by a method
    are not recoverable or should not generally be caught by the caller,
    consider throwing unchecked exceptions rather than checked exceptions.
    This can be accomplished by implementing exception classes
    that extend RuntimeException or Error instead of Exception,
    or add a try/catch wrapper in your method to convert checked exceptions to unchecked exceptions.
    不要定义方法抛出Exception或者Throwable.
    如果通过一个方法抛出的异常是不可恢复的,或者是不可捕捉的,
    考虑抛出不可检查异常比抛出可以检查异常好。
    这些可以通过实现继承RuntimeException或者Error的异常类来实现,
    或者是在你的方法中增加一个try/catch包装,
    来将可检查异常转化为不可检查异常。
     
  • Fortify分析翻译3

    2008-08-27 15:04:39

                     Fortify分析翻译3
                             http://user.qzone.qq.com/281696143/blog/1219389939  Ronger
    7. Poor style:Confusing naming(Structural):
    7.1.BPCodeConstants.java
        private static  final String RATING_BP_CODE = "WF001";
        public static String RATING_BP_CODE() {}
    7.2.The class contains a field and a method with the same name.
    该类包含相同名字的属性和方法。
    7.3.EXPLANATION 解释
    It is confusing to have a member field and a method with the same name.
    It makes it easy for a programmer to accidentally call the method
    when attempting to access the field or vice versa.
    它是让人迷惑的,一个成员属性和一个方法有相同的名字。
    当准备检查属性或者缺陷的时候,它可以使程序员调用方法更加容易。
    Example 1:
    public class Totaller {
      private int total;
      public int total() {
        ...
      }
    }
    7.4.RECOMMENDATIONS 建议
    Rename either the method or the field. If the method returns the field,
    consider following the standard getter/setter naming convention.
    Example 2: The code in Example 1 could be rewritten in the following way:
    不管是重命名方法还是属性,如果方法返回这个属性,
    考虑采用标准的getter/setter命名惯例。
    例子2:在例子1中的代码在下面将被覆盖:
    public class Totaller {
      private int total;
      public int getTotal() {
        ...
      }
    }
    8. Dead code:unused field(Structural):   
    8.1.BaseWFBO.java  
        BaseWFBO.java   private Map historyInfo;   
    8.2.This field is never used.   
        属性没有使用。   
    8.3.EXPLANATION 解释
    This field is never accessed, except perhaps by dead code.
    It is likely that the field is simply vestigial,
    but it is also possible that the unused field points out a bug.
    这个属性没有入口,应该是一段死代码。
    也有可能,这个属性是一个简单的属性,
    但是也有可能,这个没有用到的属性是一个缺陷。
    Example 1: The field named glue is not used in the following class.
    The author of the class has accidentally put quotes around the field name,
    transforming it into a string constant.
    例子1:这个叫glue的属性在下面的类中没有用到。
    类的作者,不小心使用一个引用来定义属性的名称,
    应该将它转换成一个字符串常量。
    public class Dead {
      String glue;
      public String getGlue() {
        return "glue";
      }
    }
    Example 2: The field named glue is used in the following class,
    but only from a method that is never called.
    例子2:在下面的类中,属性glue被使用了,
    但是仅仅用来一个从不被调用的类中。
    public class Dead {
      String glue;
      private String getGlue() {
        return glue;
      }
    }
    8.4.RECOMMENDATIONS 建议
    In general, you should repair or remove dead code.
    It causes additional complexity and maintenance burden
    without contributing to the functionality of the program.
    通常,你应该修改或者去掉死代码。
    它会使程序增加额外的复杂度,
    而且在对程序的功能没有任何贡献的情况下增加负担。
    9. Dead code:unused method(Structural):   
    9.1.BaseBackingBean.java  
        private static ValueBinding getValueBinding(String el)
    9.2.This method is not reachable from any method outside the class.   
        这个方法不能被类外面的方法调用。
    9.3.EXPLANATION 解释
    This method is never called or is only called from other dead code.
    这个方法是不能被调用的,或者只能从其它的死代码中调用。
    Example 1: In the following class, the method doWork() can never be called.
    例子1:在下面的类中,方法doWork()不能被调用。
    public class Dead {
      private void doWork() {
        System.out.println("doing work");
      }
      public static void main(String[] args) {
        System.out.println("running Dead");
      }
    }
    Example 2: In the following class, two private methods call each other,
    but since neither one is ever invoked from anywhere else, they are both dead code.
    例子2:在下面的类中,两个私有方法相互调用,
    但是没有一个可以从其它的地方来调用,它们都是死代码。
    public class DoubleDead {
      private void doTweedledee() {
        doTweedledumb();
      }
      private void doTweedledumb() {
        doTweedledee();
      }
      public static void main(String[] args) {
        System.out.println("running DoubleDead");
      }
    }
    (In this case it is a good thing that the methods are dead:
    invoking either one would cause an infinite loop.)
    (在这个例子中,方法是死的:调用任何一个都将导致死循环。)
    9.4.RECOMMENDATIONS 建议
    A dead method may indicate a bug in dispatch code.
    一个死方法暴露一个分支代码中的缺陷。
    Example 3: If method is flagged as dead named getWitch() in a class
    that also contains the following dispatch method,
    it may be because of a copy-and-paste error.
    The 'w' case should return getWitch() not getMummy().
    例子3:如果一个标记为死代码的方法getWitch(),并且getWitch()
    包含下面的调度方法。它可能是因为一个复制粘贴错误。
    这个'w'的情况会返回getWitch()而不是getMummy().
    public ScaryThing getScaryThing(char st) {
      switch(st) {
        case 'm':
          return getMummy();
        case 'w':
          return getMummy();
        default:
          return getBlob();
      }
    }
    In general, you should repair or remove dead code.
    It causes additional complexity and maintenance burden
    without contributing to the functionality of the program.
    通常,你应该修改或者去掉死代码。
    它会使程序增加额外的复杂度,
    而且在对程序的功能没有任何贡献的情况下增加负担。
    9.5.TIPS 提示
       This issue may be a false positive if the program uses reflection to access private methods.
    (This is a non-standard practice.
    Private methods that are only invoked via reflection should be well documented.)
    这个问题应该不是值得肯定的,如果程序使用反射来访问私有方法。
    (这是一个非标准的习惯。使用反射调用的私有方法可以被很好的记录下来。)
251/212>

数据统计

  • 访问量: 25943
  • 日志数: 25
  • 建立时间: 2008-08-27
  • 更新时间: 2008-09-02

RSS订阅

Open Toolbar