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 */ 074 public static BSHMethod createBshMethod(Element e) throws IOException { 075 if (e == null) { 076 return null; 077 } 078 String file = QFactory.getAttributeValue(e, "file"); 079 String bsh; 080 if (file != null) { 081 boolean cache = false; 082 String cacheAtt = QFactory.getAttributeValue(e, "cache"); 083 if (cacheAtt != null) { 084 cache = cacheAtt.equalsIgnoreCase("true"); 085 } 086 if (!cache) { 087 return new BSHMethod(file, true); 088 } else { 089 bsh = ""; 090 FileReader f = new FileReader(file); 091 int c; 092 while ( (c = f.read()) != -1) { 093 bsh += (char) c; 094 } 095 f.close(); 096 return new BSHMethod(bsh, false); 097 } 098 } else { 099 bsh = e.getTextTrim(); 100 if (bsh == null || bsh.equals("")) { 101 return null; 102 } 103 return new BSHMethod(bsh, false); 104 } 105 } 106 107 /** Creates a BSHMethod. 108 * @param bshData - May either be the file to source or the script itself to 109 * evaluate. 110 * @param source - If true indicates that the bshData passed is a file to 111 * source. Otherwise the string itself is evaluated. 112 */ 113 public BSHMethod(String bshData, boolean source) { 114 this.bshData = bshData; 115 this.source = source; 116 } 117 118 /** Sets the given arguments to the Interpreter, evaluates the script and 119 * returns the object stored on the variable named resultName. 120 * 121 * @param arguments Parameters to set to the Interpreter. For every 122 * Map.Entry (key, value), interpreter.set(key, value) 123 * is called. All keys must be Strings. 124 */ 125 public Object execute(Map arguments, String resultName) throws EvalError, IOException { 126 Interpreter i = initInterpreter(arguments); 127 return i.get(resultName); 128 } 129 130 /** Sets the given arguments to the Interpreter, evaluates the script and 131 * returns a map that has the Strings of the returnNames collection as keys 132 * and the objects stored in the variables thus named as values. 133 * 134 * @param arguments Parameters to set to the Interpreter. For every 135 * Map.Entry (key, value), interpreter.set(key, value) 136 * is called. All keys must be Strings. 137 * @param returnNames Collection of Strings. The names of the variables 138 * wich`s contents are to be returned. 139 */ 140 public Map execute(Map arguments, Collection returnNames) throws EvalError, IOException { 141 Interpreter i = initInterpreter(arguments); 142 Map result = new HashMap(); 143 String rName; 144 for (Object returnName : returnNames) { 145 rName = (String) returnName; 146 result.put(rName, i.get(rName)); 147 } 148 return result; 149 } 150 151 protected Interpreter initInterpreter(Map arguments) throws EvalError, IOException { 152 Interpreter i = new Interpreter(); 153 Map.Entry entry; 154 for (Object o : arguments.entrySet()) { 155 entry = (Map.Entry) o; 156 i.set((String) entry.getKey(), entry.getValue()); 157 } 158 if (source) { 159 i.source(bshData); 160 } else { 161 i.eval(bshData); 162 } 163 return i; 164 } 165 166 public String toString() { 167 return bshData; 168 } 169}