001package com.ganteater.ae; 002 003import java.io.File; 004import java.util.HashMap; 005import java.util.List; 006import java.util.Map; 007 008import org.apache.commons.lang.ObjectUtils; 009import org.apache.commons.lang.StringEscapeUtils; 010import org.apache.commons.lang.StringUtils; 011import org.apache.commons.lang.math.NumberUtils; 012import org.apache.sling.commons.json.JSONArray; 013import org.apache.sling.commons.json.JSONException; 014import org.apache.sling.commons.json.JSONObject; 015 016import com.ganteater.ae.util.AEUtils; 017import com.ganteater.ae.util.xml.easyparser.Node; 018 019public class TemplateProcessor { 020 021 protected static final String MAPPED_VAR_DELIM = "::"; 022 023 public Map<String, Object> variables = new HashMap<String, Object>(); 024 025 protected static Map<String, Object> fGlobalVariables = new HashMap<String, Object>(); 026 027 private boolean fstoppedTest = false; 028 029 protected Node configNode; 030 031 private File fBaseDir; 032 033 protected TemplateProcessor() { 034 } 035 036 public TemplateProcessor(Map<String, Object> variables, Node configNode, File baseDir) { 037 super(); 038 this.variables = variables; 039 this.configNode = configNode; 040 setBaseDir(baseDir); 041 } 042 043 public File getBaseDir() { 044 return fBaseDir; 045 } 046 047 public void setBaseDir(File theBaseDir) { 048 this.fBaseDir = theBaseDir; 049 } 050 051 public String replaceProperties(String aValue) { 052 if (aValue == null) 053 return null; 054 055 do { 056 aValue = replaceProperties(aValue, false); 057 } while (aValue.indexOf("$var{") >= 0); 058 059 return aValue; 060 } 061 062 protected String replaceProperties(String value, boolean aUseDefaultValue) { 063 value = replaceFile(value); 064 String theStartKey = "$var{"; 065 String theEndKey = "}"; 066 int theBeginPos = 0; 067 int theEndPos = 0; 068 if (value == null) { 069 return value; 070 } 071 StringBuffer theStringBuffer = new StringBuffer(); 072 while (true) { 073 theBeginPos = value.indexOf(theStartKey, theEndPos); 074 if (theBeginPos < 0) { 075 break; 076 } 077 theStringBuffer.append(value.substring(theEndPos, theBeginPos)); 078 theEndPos = value.indexOf(theEndKey, theBeginPos); 079 if (theEndPos < 0) { 080 throw new RuntimeException( 081 "Variable getting incorrect syntax, absent symbol '" + theEndKey + "' for: " + value); 082 } 083 String theNameProperty = value.substring(theBeginPos + theStartKey.length(), theEndPos); 084 String theDefaultValue = null; 085 // default value checking 086 int defaultPos = theNameProperty.indexOf(','); 087 if (defaultPos >= 0) { 088 theDefaultValue = theNameProperty.substring(defaultPos + 1); 089 theNameProperty = theNameProperty.substring(0, defaultPos); 090 } 091 String theValue = null; 092 093 if ("THREAD_INFO".equals(theNameProperty)) { 094 theValue = Thread.currentThread().toString(); 095 096 } else if (StringUtils.startsWith(theNameProperty, "\\")) { 097 theValue = StringEscapeUtils.unescapeJava(theNameProperty); 098 099 } else if (StringUtils.startsWith(theNameProperty, "\\")) { 100 theValue = StringEscapeUtils.unescapeJava(theNameProperty); 101 102 } else { 103 Object o = null; 104 if (aUseDefaultValue == false || theDefaultValue == null) { 105 o = getVariableValue(theNameProperty); 106 } 107 if (AEUtils.isEmpty(o) && theDefaultValue != null) { 108 o = theDefaultValue; 109 } 110 111 if (o instanceof String) { 112 theValue = (String) o; 113 } else if (o instanceof List) { 114 if (!((List) o).isEmpty()) { 115 theValue = String.valueOf(((List) o).get(0)); 116 } else { 117 theValue = StringUtils.EMPTY; 118 } 119 120 } else if (o instanceof byte[]) { 121 theValue = new String((byte[]) o); 122 } else if (o instanceof String[]) { 123 theValue = StringUtils.join((String[]) o, "\n"); 124 } else { 125 theValue = ObjectUtils.toString(o); 126 } 127 128 } 129 130 remarkExtendsReplacer(theStringBuffer, theValue, "/*$var{" + theNameProperty + "}*/"); 131 theEndPos += theEndKey.length(); 132 } 133 theStringBuffer.append(value.substring(theEndPos)); 134 135 return replaceTag(replaceCall(theStringBuffer.toString())); 136 } 137 138 private void remarkExtendsReplacer(StringBuffer aStringBuffer, String aValue, String aRemark) { 139 String s = null; 140 if (aStringBuffer.length() >= 4) { 141 s = aStringBuffer.substring(aStringBuffer.length() - 4); 142 } 143 if ("';--".equals(s)) { 144 int theEnd = 0; 145 for (theEnd = aStringBuffer.length() - 5;; theEnd--) { 146 char c = aStringBuffer.charAt(theEnd); 147 if (c == '\'') { 148 break; 149 } 150 } 151 aStringBuffer.setLength(theEnd); 152 aStringBuffer.append('\''); 153 aStringBuffer.append(aValue); 154 aStringBuffer.append('\''); 155 aStringBuffer.append(';'); 156 if (aRemark != null) { 157 aStringBuffer.append(" " + aRemark); 158 } 159 } else { 160 s = null; 161 if (aStringBuffer.length() >= 3) { 162 s = aStringBuffer.substring(aStringBuffer.length() - 3); 163 } 164 if (";--".equals(s)) { 165 int theEnd = 0; 166 for (theEnd = aStringBuffer.length() - 4;; theEnd--) { 167 char c = aStringBuffer.charAt(theEnd); 168 if (c == ' ' || c == '=') { 169 break; 170 } 171 } 172 aStringBuffer.setLength(theEnd + 1); 173 aStringBuffer.append(aValue); 174 aStringBuffer.append(';'); 175 if (aRemark != null) { 176 aStringBuffer.append(" " + aRemark); 177 } 178 } else { 179 s = null; 180 if (aStringBuffer.length() >= 2) { 181 s = aStringBuffer.substring(aStringBuffer.length() - 2); 182 } 183 if ("--".equals(s)) { 184 aStringBuffer.setLength(aStringBuffer.length() - 2); 185 aStringBuffer.append(aValue); 186 } else { 187 aStringBuffer.append(aValue); 188 } 189 } 190 } 191 } 192 193 protected String replaceCall(String aValue) { 194 return aValue; 195 } 196 197 protected String replaceTag(String aValue) { 198 String theStartKey = "$tag{"; 199 String theEndKey = "}"; 200 int theBeginPos = 0; 201 int theEndPos = 0; 202 if (aValue == null) { 203 return aValue; 204 } 205 StringBuffer theStringBuffer = new StringBuffer(); 206 while (true) { 207 theBeginPos = aValue.indexOf(theStartKey, theEndPos); 208 if (theBeginPos < 0) { 209 break; 210 } 211 theStringBuffer.append(aValue.substring(theEndPos, theBeginPos)); 212 theEndPos = aValue.indexOf(theEndKey, theBeginPos); 213 if (theEndPos < 0) { 214 throw new RuntimeException("Tag created is incorrect syntax, absent symbol '" + theEndKey + "'."); 215 } 216 String theLine = aValue.substring(theBeginPos + theStartKey.length(), theEndPos); 217 int thePbrk = theLine.indexOf(','); 218 String theTagName = theLine; 219 String theNameVar = theLine; 220 if (thePbrk > 0) { 221 theTagName = theLine.substring(0, thePbrk); 222 theNameVar = theLine.substring(thePbrk + 1); 223 } 224 Object o = getVariableValue(theNameVar); 225 String theValue = null; 226 if (o instanceof String) { 227 theValue = (String) o; 228 } 229 if (o instanceof List && !((List) o).isEmpty()) { 230 theValue = String.valueOf(((List) o).get(0)); 231 } 232 if (theValue != null) { 233 theStringBuffer.append('<'); 234 theStringBuffer.append(theTagName); 235 theStringBuffer.append('>'); 236 theValue = theValue.replaceAll("\"", """); 237 theValue = theValue.replaceAll("\'", "'"); 238 theValue = theValue.replaceAll("<", "<"); 239 theValue = theValue.replaceAll(">", ">"); 240 theStringBuffer.append(theValue); 241 theStringBuffer.append("</"); 242 theStringBuffer.append(theTagName); 243 theStringBuffer.append('>'); 244 } else { 245 theStringBuffer.append('<'); 246 theStringBuffer.append(theTagName); 247 theStringBuffer.append("/>"); 248 } 249 theEndPos += theEndKey.length(); 250 } 251 theStringBuffer.append(aValue.substring(theEndPos)); 252 return theStringBuffer.toString(); 253 } 254 255 protected String replaceFile(String aValue) { 256 String theStartKey = "$file{"; 257 String theEndKey = "}"; 258 int theBeginPos = 0; 259 int theEndPos = 0; 260 if (aValue == null) { 261 return aValue; 262 } 263 StringBuffer theStringBuffer = new StringBuffer(); 264 while (true) { 265 theBeginPos = aValue.indexOf(theStartKey, theEndPos); 266 if (theBeginPos < 0) { 267 break; 268 } 269 theStringBuffer.append(aValue.substring(theEndPos, theBeginPos)); 270 theEndPos = aValue.indexOf(theEndKey, theBeginPos); 271 if (theEndPos < 0) { 272 throw new RuntimeException( 273 "Insert file marcer is incorrect syntax, absent symbol '" + theEndKey + "'."); 274 } 275 String theLine = aValue.substring(theBeginPos + theStartKey.length(), theEndPos); 276 int thePbrk = theLine.indexOf(','); 277 String theFileName = theLine; 278 String theEncodeVar = "UTF-8"; 279 if (thePbrk > 0) { 280 theFileName = theLine.substring(0, thePbrk); 281 theEncodeVar = theLine.substring(thePbrk + 1); 282 } 283 String theXML; 284 try { 285 theXML = AEUtils.loadResource(theFileName, getBaseDir(), theEncodeVar); 286 } catch (Exception e) { 287 throw new RuntimeException(e); 288 } 289 theXML = replaceProperties(theXML); 290 remarkExtendsReplacer(theStringBuffer, theXML, null); 291 theEndPos += theEndKey.length(); 292 } 293 theStringBuffer.append(aValue.substring(theEndPos)); 294 return theStringBuffer.toString(); 295 } 296 297 public Object getVariableValue(String aAttribut) { 298 if (aAttribut == null) 299 return null; 300 aAttribut = toUpperCaseName(aAttribut).trim(); 301 if ("BASEDIR".equals(aAttribut)) 302 return getBaseDir().getPath(); 303 return getVariableValue(aAttribut, true); 304 } 305 306 public String getVariableString(String aAttribut) { 307 Object variableValue = getVariableValue(aAttribut); 308 309 if (variableValue instanceof List) { 310 List theStringArr = (List) variableValue; 311 if (theStringArr.size() > 0) { 312 variableValue = theStringArr.get(0); 313 } 314 } 315 316 return ObjectUtils.toString(variableValue, null); 317 } 318 319 public String toUpperCaseName(String aAttribut) { 320 String result = null; 321 if (aAttribut.indexOf(MAPPED_VAR_DELIM) >= 0) { 322 result = StringUtils.substringBefore(aAttribut, MAPPED_VAR_DELIM).toUpperCase() + MAPPED_VAR_DELIM 323 + StringUtils.substringAfter(aAttribut, MAPPED_VAR_DELIM); 324 } else { 325 result = aAttribut.toUpperCase(); 326 } 327 return result; 328 } 329 330 public Object getVariableValue(String aAttribut, boolean aArrayTrimed) { 331 Object o = null; 332 aAttribut = toUpperCaseName(aAttribut); 333 Map<String, Object> theVariables = variables; 334 if (aAttribut.startsWith("!")) 335 theVariables = fGlobalVariables; 336 337 boolean isMappedVar = aAttribut.indexOf(MAPPED_VAR_DELIM) > 0; 338 if (isMappedVar) { 339 o = getValueByPath(aAttribut, theVariables); 340 341 } else { 342 o = theVariables.get(aAttribut); 343 } 344 345 if (o instanceof List) { 346 List theStringArr = (List) o; 347 if (theStringArr.size() == 1 && aArrayTrimed) { 348 o = theStringArr.get(0); 349 } 350 } 351 352 if (o instanceof JSONArray) { 353 JSONArray array = (JSONArray) o; 354 String[] value = new String[array.length()]; 355 for (int i = 0; i < value.length; i++) { 356 value[i] = ObjectUtils.toString(array.opt(i)); 357 } 358 o = value; 359 } 360 361 return o; 362 } 363 364 private Object getValueByPath(String aAttribut, Map<String, Object> theVariables) { 365 Object o = null; 366 String mapVarName = StringUtils.substringBefore(aAttribut, MAPPED_VAR_DELIM); 367 try { 368 Object object = theVariables.get(mapVarName); 369 if (object instanceof String && ((String) object).trim().startsWith("{")) { 370 object = new JSONObject(ObjectUtils.toString(object)); 371 } 372 373 @SuppressWarnings("unchecked") 374 Object mapVar = object; 375 376 mapVarName = StringUtils.substringAfter(aAttribut, MAPPED_VAR_DELIM); 377 378 if (mapVar instanceof Map) { 379 o = getNestedValue(mapVarName, (Map) mapVar); 380 } else if (mapVar instanceof JSONObject) { 381 JSONObject json = (JSONObject) object; 382 o = getNestedJsonValue(mapVarName, (JSONObject) json); 383 } 384 385 } catch (ClassCastException | JSONException e) { 386 e.printStackTrace(); 387 o = null; 388 } 389 return o; 390 } 391 392 private Object getNestedValue(String varName, Map<String, Object> mapVar) { 393 Object o; 394 if (mapVar != null) { 395 String mapVarName = StringUtils.substringBefore(varName, MAPPED_VAR_DELIM); 396 o = mapVar.get(mapVarName); 397 398 mapVarName = StringUtils.substringAfter(varName, MAPPED_VAR_DELIM); 399 if (StringUtils.isNotBlank(mapVarName) && o instanceof Map) { 400 o = getNestedValue(mapVarName, (Map<String, Object>) o); 401 } 402 403 } else { 404 o = null; 405 406 } 407 return o; 408 } 409 410 private Object getNestedJsonValue(String varName, Object json) throws JSONException { 411 Object o = null; 412 try { 413 if (json != null) { 414 String mapVarName = StringUtils.substringBefore(varName, MAPPED_VAR_DELIM); 415 if (json instanceof JSONObject) { 416 o = ((JSONObject) json).get(mapVarName); 417 } else if (json instanceof JSONArray) { 418 JSONArray array = (JSONArray) json; 419 if (NumberUtils.isNumber(mapVarName)) { 420 o = array.get(Integer.parseInt(mapVarName)); 421 } else { 422 o = null; 423 } 424 } 425 426 mapVarName = StringUtils.substringAfter(varName, MAPPED_VAR_DELIM); 427 if (StringUtils.isNotBlank(mapVarName)) { 428 o = getNestedJsonValue(mapVarName, o); 429 } 430 431 } else { 432 o = null; 433 434 } 435 } catch (JSONException e) { 436 o = null; 437 } 438 return o; 439 } 440 441 public File getFile(String theFileAttribut) { 442 return new File(theFileAttribut); 443 } 444 445 public static Map<String, Object> getGlobalVariables() { 446 return fGlobalVariables; 447 } 448 449 public void setVariableValue(String name, final Object value) { 450 451 if (name == null) { 452 return; 453 } 454 455 name = toUpperCaseName(name); 456 457 Map<String, Object> variables = this.variables; 458 if (name.startsWith("!")) { 459 variables = fGlobalVariables; 460 } 461 boolean isMappedVar = name.indexOf(MAPPED_VAR_DELIM) > 0; 462 463 if (value == null) { 464 if (isMappedVar) { 465 String mapVarName = StringUtils.substringBefore(name, MAPPED_VAR_DELIM); 466 Object mapVar = variables.get(mapVarName); 467 if (mapVar != null) { 468 if (mapVar instanceof Map) { 469 ((Map<?, ?>) mapVar).remove(name); 470 return; 471 } 472 } 473 474 } else { 475 variables.remove(name); 476 return; 477 } 478 } 479 480 if (isMappedVar) { 481 String mapVarName = StringUtils.substringBefore(name, MAPPED_VAR_DELIM); 482 483 Object valueObj = variables.get(mapVarName); 484 if (valueObj instanceof JSONObject) { 485 String varName = StringUtils.substringAfter(name, MAPPED_VAR_DELIM); 486 setJsonValue(valueObj, varName, value); 487 return; 488 489 } else if (!(valueObj instanceof Map)) { 490 variables.put(mapVarName, new HashMap()); 491 } 492 @SuppressWarnings("unchecked") 493 Map<String, Object> mapVar = (Map<String, Object>) variables.get(mapVarName); 494 495 if (mapVar == null) { 496 mapVar = new HashMap<String, Object>(); 497 variables.put(mapVarName, mapVar); 498 } 499 500 String varName = StringUtils.substringAfter(name, MAPPED_VAR_DELIM); 501 mapVar.put(varName, value); 502 503 } else { 504 variables.put(name, value); 505 } 506 507 } 508 509 private void setJsonValue(Object value, String name, final Object aValue) { 510 String varName = StringUtils.substringBefore(name, MAPPED_VAR_DELIM); 511 String nestedName = StringUtils.substringAfter(name, MAPPED_VAR_DELIM); 512 513 JSONObject json = (JSONObject) value; 514 try { 515 if (StringUtils.isEmpty(nestedName)) { 516 if (aValue instanceof String[]) { 517 JSONArray jsonArray = new JSONArray(); 518 String[] array = (String[]) aValue; 519 for (String item : array) { 520 jsonArray.put(new JSONObject(item)); 521 } 522 json.put(varName, jsonArray); 523 } else { 524 json.put(varName, aValue); 525 } 526 527 } else { 528 Object object = json.get(varName); 529 setJsonValue(object, nestedName, aValue); 530 } 531 532 } catch (JSONException e) { 533 // TODO Auto-generated catch block 534 e.printStackTrace(); 535 } 536 } 537 538 public void stop() { 539 this.setStopped(true); 540 } 541 542 public boolean isStopped() { 543 return fstoppedTest; 544 } 545 546 public void setStopped(boolean fstoppedTest) { 547 this.fstoppedTest = fstoppedTest; 548 } 549 550}