001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.transaction.participant; 020 021import bsh.EvalError; 022import bsh.Interpreter; 023import org.jdom2.Element; 024import org.jpos.q2.QFactory; 025 026import java.io.FileReader; 027import java.io.IOException; 028import java.util.Collection; 029import java.util.HashMap; 030import java.util.Map; 031 032/** This is a utility class that makes it a bit easier to work with beanshell 033 * scripts. 034 * Check out the execute methods. 035 * 036 * @author AMarques 037 */ 038@SuppressWarnings("unchecked") 039public class BSHMethod { 040 041 private String bshData; 042 private boolean source; 043 044 045 /** Creates a BSHMethod from a JDom Element. 046 * 047 * The element is not requiered to have a specific name. 048 * 049 * If the given element defines an attribute named 'file' the file 050 * specified as its value will be sourced by the created BSHMethod. 051 * 052 * If the 'file' attribute is specified, a 'cache' 053 * attribute may be specified as well which can take the values true|false 054 * and indicates wether to load the script to memory or to read from the 055 * file for every script evaluation. 056 * 057 * If the 'file' attibute is not specified then the text contained by the 058 * element is set to be evaluated by the new BSHMethod. 059 * <pre> 060 * Example 1 : 061 * <prepare> 062 * import org.jpos.iso.*; 063 * import org.jpos.transaction.*; 064 * 065 * msg = context.get("txnRequest"); 066 * BaseChannel.getChannel("loop-channel").send(msg); 067 * result=TransactionConstants.PREPARED | TransactionConstants.READONLY; 068 * </prepare> 069 * 070 * Example 2 : 071 * <routing file='cfg\files\routing1.bsh' cache='false'/> 072 * </pre> 073 * Creates a BSHMethod from the given XML element configuration. 074 * @param e the XML element configuration (may be null) 075 * @return a configured BSHMethod, or null if element is null 076 * @throws IOException if the script file cannot be read 077 */ 078 public static BSHMethod createBshMethod(Element e) throws IOException { 079 if (e == null) { 080 return null; 081 } 082 String file = QFactory.getAttributeValue(e, "file"); 083 String bsh; 084 if (file != null) { 085 boolean cache = false; 086 String cacheAtt = QFactory.getAttributeValue(e, "cache"); 087 if (cacheAtt != null) { 088 cache = cacheAtt.equalsIgnoreCase("true"); 089 } 090 if (!cache) { 091 return new BSHMethod(file, true); 092 } else { 093 bsh = ""; 094 FileReader f = new FileReader(file); 095 int c; 096 while ( (c = f.read()) != -1) { 097 bsh += (char) c; 098 } 099 f.close(); 100 return new BSHMethod(bsh, false); 101 } 102 } else { 103 bsh = e.getTextTrim(); 104 if (bsh == null || bsh.equals("")) { 105 return null; 106 } 107 return new BSHMethod(bsh, false); 108 } 109 } 110 111 /** Creates a BSHMethod. 112 * @param bshData - May either be the file to source or the script itself to 113 * evaluate. 114 * @param source - If true indicates that the bshData passed is a file to 115 * source. Otherwise the string itself is evaluated. 116 */ 117 public BSHMethod(String bshData, boolean source) { 118 this.bshData = bshData; 119 this.source = source; 120 } 121 122 /** 123 * Sets the given arguments in the Interpreter, evaluates the script, 124 * and returns the object stored in the variable named {@code resultName}. 125 * @param arguments map of variable name to value pairs (all keys must be Strings) 126 * @param resultName the variable name whose value to return 127 * @return the value of resultName after script evaluation 128 * @throws bsh.EvalError on BeanShell evaluation error 129 * @throws IOException if the script cannot be read 130 */ 131 public Object execute(Map arguments, String resultName) throws EvalError, IOException { 132 Interpreter i = initInterpreter(arguments); 133 return i.get(resultName); 134 } 135 136 /** 137 * Sets the given arguments in the Interpreter, evaluates the script, 138 * and returns a map of named result variables. 139 * @param arguments map of variable name to value pairs (all keys must be Strings) 140 * @param returnNames collection of variable names to extract from the interpreter 141 * @return map of variable name to value pairs after script evaluation 142 * @throws bsh.EvalError on BeanShell evaluation error 143 * @throws IOException if the script cannot be read 144 */ 145 public Map execute(Map arguments, Collection returnNames) throws EvalError, IOException { 146 Interpreter i = initInterpreter(arguments); 147 Map result = new HashMap(); 148 String rName; 149 for (Object returnName : returnNames) { 150 rName = (String) returnName; 151 result.put(rName, i.get(rName)); 152 } 153 return result; 154 } 155 156 /** 157 * Initialises a BeanShell Interpreter with the given arguments and evaluates the script. 158 * @param arguments map of variable name to value pairs to set in the interpreter 159 * @return a configured Interpreter after script evaluation 160 * @throws EvalError on script evaluation error 161 * @throws IOException if the script cannot be read 162 */ 163 protected Interpreter initInterpreter(Map arguments) throws EvalError, IOException { 164 Interpreter i = new Interpreter(); 165 Map.Entry entry; 166 for (Object o : arguments.entrySet()) { 167 entry = (Map.Entry) o; 168 i.set((String) entry.getKey(), entry.getValue()); 169 } 170 if (source) { 171 i.source(bshData); 172 } else { 173 i.eval(bshData); 174 } 175 return i; 176 } 177 178 public String toString() { 179 return bshData; 180 } 181}