001 /* 002 @license.text@ 003 */ 004 package biz.hammurapi.eval; 005 006 import java.io.FilterWriter; 007 import java.io.IOException; 008 import java.io.Writer; 009 import java.util.HashSet; 010 import java.util.Iterator; 011 import java.util.Set; 012 013 import org.apache.log4j.Logger; 014 015 import biz.hammurapi.config.Context; 016 import biz.hammurapi.convert.Converter; 017 018 019 /** 020 * @author Pavel Vlasov 021 * @version $Revision$ 022 */ 023 public class EvaluatingFilterWriter extends FilterWriter { 024 private int mode; 025 026 private Context context; 027 028 private Converter converter; 029 030 private static final Logger logger = Logger.getLogger(EvaluatingFilterWriter.class); 031 032 private Set keySet; 033 034 public EvaluatingFilterWriter( 035 Writer out, 036 int mode, 037 Context context, 038 Converter converter) { 039 this(out,mode,context, converter,new HashSet()); 040 } 041 042 private EvaluatingFilterWriter( 043 Writer out, 044 int mode, 045 Context context, 046 Converter converter, 047 Set keySet) { 048 super(out); 049 this.mode = mode; 050 this.context = context; 051 this.converter = converter; 052 this.keySet=keySet; 053 } 054 055 private int lastChar; 056 057 private StringBuffer expressionBuffer; 058 059 private static final int STATE_NORMAL = 0; 060 061 private static final int STATE_DOLLAR = 1; 062 063 private static final int STATE_EXPRESSION = 2; 064 065 private static final int STATE_QUOTE = 3; 066 067 public static final int MODE_LENIENT = 0; 068 069 public static final int MODE_MESSAGE = 1; 070 071 public static final int MODE_STRICT = 2; 072 073 private int state = STATE_NORMAL; 074 075 public void write(int c) throws IOException { 076 switch (c) { 077 case '$': 078 switch (state) { 079 case STATE_NORMAL: 080 state = STATE_DOLLAR; 081 break; 082 case STATE_DOLLAR: 083 state = STATE_NORMAL; 084 out.write(c); 085 // out.write(b); 086 break; 087 case STATE_EXPRESSION: 088 case STATE_QUOTE: 089 toBuffer(c); 090 break; 091 default: 092 throw new IOException("Invalid lexer state: " + state); 093 } 094 break; 095 case '{': 096 switch (state) { 097 case STATE_EXPRESSION: 098 case STATE_QUOTE: 099 toBuffer(c); 100 break; 101 case STATE_NORMAL: 102 out.write(c); 103 break; 104 case STATE_DOLLAR: 105 state = STATE_EXPRESSION; 106 break; 107 default: 108 throw new IOException("Invalid lexer state: " + state); 109 } 110 break; 111 case '}': 112 switch (state) { 113 case STATE_NORMAL: 114 out.write(c); 115 break; 116 case STATE_DOLLAR: 117 state = STATE_NORMAL; 118 out.write(c); 119 case STATE_EXPRESSION: 120 state = STATE_NORMAL; 121 if (expressionBuffer == null) { 122 out.write('$'); 123 out.write('{'); 124 out.write('}'); 125 } else { 126 String expression = expressionBuffer.toString(); 127 expressionBuffer = null; 128 try { 129 Evaluator evaluator = new Evaluator(expression, null, converter); 130 Iterator it = evaluator.evaluate(context).iterator(); 131 while (it.hasNext()) { 132 Object object = it.next(); 133 if (object == null) { 134 out.write("(null)"); 135 } else { 136 out.write(object.toString()); 137 if (it.hasNext()) { 138 out.write(' '); 139 } 140 } 141 } 142 } catch (EvaluationException e) { 143 switch (mode) { 144 case MODE_LENIENT: 145 logger.warn("Evaluation failed for: " + expression, e); 146 out.write("${"+expression+"}"); 147 break; 148 case MODE_MESSAGE: 149 logger.warn("Evaluation failed for: " + expression, e); 150 out.write(" *** Evaluation failed for: " + expression+" *** "); 151 break; 152 case MODE_STRICT: 153 logger.error("Evaluation failed for: " + expression, e); 154 throw new IOException("Evaluation failed for: '" + expression+"' - " + e); 155 default: 156 throw new IOException("Invalid mode: "+mode); 157 } 158 } 159 } 160 break; 161 case STATE_QUOTE: 162 toBuffer(c); 163 break; 164 default: 165 throw new IOException("Invalid lexer state: " + state); 166 } 167 break; 168 case '"': 169 switch (state) { 170 case STATE_NORMAL: 171 out.write(c); 172 break; 173 case STATE_DOLLAR: 174 state=STATE_NORMAL; 175 out.write(c); 176 break; 177 case STATE_EXPRESSION: 178 state=STATE_QUOTE; 179 toBuffer(c); 180 break; 181 case STATE_QUOTE: 182 if (lastChar!='\\') { 183 state=STATE_EXPRESSION; 184 } 185 toBuffer(c); 186 break; 187 default: 188 throw new IOException("Invalid lexer state: " + state); 189 } 190 break; 191 default: 192 switch (state) { 193 case STATE_NORMAL: 194 out.write(c); 195 break; 196 case STATE_DOLLAR: 197 state=STATE_NORMAL; 198 out.write(c); 199 break; 200 case STATE_EXPRESSION: 201 case STATE_QUOTE: 202 toBuffer(c); 203 break; 204 default: 205 throw new IOException("Invalid lexer state: " + state); 206 } 207 } 208 lastChar = c; 209 } 210 211 /** 212 * @param b 213 */ 214 private void toBuffer(int b) { 215 if (expressionBuffer == null) { 216 expressionBuffer = new StringBuffer(); 217 } 218 expressionBuffer.append((char) b); 219 } 220 221 public void close() throws IOException { 222 if (state == STATE_DOLLAR) { 223 out.write('$'); 224 } else if (state == STATE_EXPRESSION || state == STATE_QUOTE) { 225 out.write('$'); 226 out.write('{'); 227 } 228 229 if (expressionBuffer != null) { 230 out.write(expressionBuffer.toString()); 231 expressionBuffer = null; 232 } 233 out.close(); 234 super.close(); 235 } 236 237 public void write(char[] cbuf, int off, int len) throws IOException { 238 for (int i=0; i<len; i++) { 239 write(cbuf[i+off]); 240 } 241 } 242 243 public void write(String str, int off, int len) throws IOException { 244 for (int i=0; i<len; i++) { 245 write(str.charAt(i+off)); 246 } 247 } 248 }