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