This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
The following commit(s) were added to refs/heads/master by this push:
new 3a1083c688 expose use of freemarker cache and object unwrapping
3a1083c688 is described below
commit 3a1083c6886ea6b5cbd06cb3df486900f8d809d8
Author: Alex Heneveld <[email protected]>
AuthorDate: Thu Aug 3 11:14:44 2023 +0100
expose use of freemarker cache and object unwrapping
---
.../core/workflow/WorkflowExpressionResolution.java | 8 ++++++--
.../brooklyn/util/core/text/TemplateProcessor.java | 19 ++++++++++++-------
2 files changed, 18 insertions(+), 9 deletions(-)
diff --git
a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExpressionResolution.java
b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExpressionResolution.java
index 14dde15a3a..947eac6a54 100644
---
a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExpressionResolution.java
+++
b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExpressionResolution.java
@@ -130,7 +130,7 @@ public class WorkflowExpressionResolution {
return null;
}
- class WorkflowFreemarkerModel implements TemplateHashModel,
TemplateProcessor.UnwrappableTemplateModel {
+ public class WorkflowFreemarkerModel implements TemplateHashModel,
TemplateProcessor.UnwrappableTemplateModel {
@Override
public Maybe<Object> unwrap() {
return Maybe.of(context);
@@ -585,6 +585,10 @@ public class WorkflowExpressionResolution {
return
Tasks.resolving(expression).as(Object.class).deep().context(context.getEntity()).get();
}
+ public WorkflowFreemarkerModel newWorkflowFreemarkerModel() {
+ return new WorkflowFreemarkerModel();
+ }
+
public Object processTemplateExpressionString(String expression,
AllowBrooklynDslMode allowBrooklynDsl) {
if (expression==null) return null;
if (expression.startsWith("$brooklyn:") &&
allowBrooklynDsl.isAllowedHere()) {
@@ -599,7 +603,7 @@ public class WorkflowExpressionResolution {
return expressionTemplateAndDslResolved;
}
- TemplateHashModel model = new WorkflowFreemarkerModel();
+ TemplateHashModel model = newWorkflowFreemarkerModel();
Object result;
boolean ourWait = interruptSetIfNeededToPreventWaiting();
diff --git
a/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
b/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
index ba65c16f7a..8a51d7c1b4 100644
---
a/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
+++
b/core/src/main/java/org/apache/brooklyn/util/core/text/TemplateProcessor.java
@@ -83,8 +83,17 @@ public class TemplateProcessor {
}
static BrooklynFreemarkerUnwrappableObjectWrapper BROOKLYN_WRAPPER = new
BrooklynFreemarkerUnwrappableObjectWrapper();
+ public static TemplateModel wrapAsTemplateModel(Object o) throws
TemplateModelException { return BROOKLYN_WRAPPER.wrap(o); }
+ public static Maybe<Object> unwrapTemplateModelMaybe(TemplateModel
templateModel) { return BROOKLYN_WRAPPER.unwrapMaybe(templateModel); }
static ThreadLocalStack<Map<TemplateModel,Object>>
TEMPLATE_MODEL_UNWRAP_CACHE = new ThreadLocalStack<>(true);
+ /** A cache is used to be able to retrieve the object from which a
TemplateModel was created, if needed,
+ * because Freemarker doesn't support that except on selected
UnwrappableTemplateModel subclasses.
+ * Use wrap and unwrap methods above to access.
+ * Calls to this must be balanced with a 'close' to avoid memory leaks */
+ public static void openLocalTemplateModelCache() {
TEMPLATE_MODEL_UNWRAP_CACHE.push(MutableMap.of()); }
+ public static void closeLocalTemplateModelCache() {
TEMPLATE_MODEL_UNWRAP_CACHE.pop(); }
+
static ThreadLocalStack<String> TEMPLATE_FILE_WANTING_LEGACY_SYNTAX = new
ThreadLocalStack<>(true);
static ThreadLocalStack<Boolean> IS_FOR_WORKFLOW = new
ThreadLocalStack<>(true);
@@ -256,10 +265,6 @@ public class TemplateProcessor {
}
}
- public static TemplateModel wrapAsTemplateModel(Object o) throws
TemplateModelException {
- return BROOKLYN_WRAPPER.wrap(o);
- }
-
/** As per {@link #processTemplateContents(String, Map)}, but taking a
file. */
public static String processTemplateFile(String templateFileName,
Map<String, ? extends Object> substitutions) {
String templateContents;
@@ -948,7 +953,7 @@ public class TemplateProcessor {
Environment env =
template.createProcessingEnvironment(substitutions, null);
Maybe<Method> evalMethod =
Reflections.findMethodMaybe(Expression.class, "eval", Environment.class);
try {
- TEMPLATE_MODEL_UNWRAP_CACHE.push(MutableMap.of());
+ openLocalTemplateModelCache();
Maybe<Object> model = evalMethod.isAbsent() ?
Maybe.Absent.castAbsent(evalMethod) : escapedExpression.map(expr -> {
try {
return Reflections.invokeMethodFromArgs(expr,
@@ -968,7 +973,7 @@ public class TemplateProcessor {
});
if (model.isPresent()) {
if (model.get() instanceof TemplateModel) {
- return
BROOKLYN_WRAPPER.unwrapMaybe((TemplateModel) model.get()).get();
+ return unwrapTemplateModelMaybe((TemplateModel)
model.get()).get();
} else if (model.get()==null) {
// key not found, fall through to below for proper
error handling
} else {
@@ -978,7 +983,7 @@ public class TemplateProcessor {
log.warn("Unable to access FreeMarker internals to
resolve " + templateContents + "; will cast argument as string");
}
} finally {
- TEMPLATE_MODEL_UNWRAP_CACHE.pop();
+ closeLocalTemplateModelCache();
}
}