This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/master by this push:
new 28402921 EMPIREDB-432 Exception message formatting and escaping
28402921 is described below
commit 28402921ae9bd292e8e7bd51896193ac33835e1a
Author: Rainer Döbele <[email protected]>
AuthorDate: Fri Jul 5 14:10:53 2024 +0200
EMPIREDB-432
Exception message formatting and escaping
---
.../empire/jakarta/controls/InputControl.java | 15 +--
.../empire/jakarta/impl/ResourceTextResolver.java | 16 ++-
.../org/apache/empire/jakarta/utils/HtmlUtils.java | 60 +++++++++
.../apache/empire/jsf2/controls/InputControl.java | 15 +--
.../empire/jsf2/impl/ResourceTextResolver.java | 16 ++-
.../org/apache/empire/jsf2/utils/HtmlUtils.java | 60 +++++++++
.../apache/empire/exceptions/EmpireException.java | 136 +++++++++++++--------
7 files changed, 239 insertions(+), 79 deletions(-)
diff --git
a/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/controls/InputControl.java
b/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/controls/InputControl.java
index 66d4e32d..4b690841 100644
---
a/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/controls/InputControl.java
+++
b/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/controls/InputControl.java
@@ -43,6 +43,7 @@ import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ItemNotFoundException;
import org.apache.empire.exceptions.UnexpectedReturnValueException;
import org.apache.empire.jakarta.app.TextResolver;
+import org.apache.empire.jakarta.utils.HtmlUtils;
import org.apache.empire.jakarta.utils.TagStyleClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -799,19 +800,7 @@ public abstract class InputControl
*/
protected String escapeHTML(String text)
{
- if (text==null || text.length()==0)
- return text;
- // &
- if (text.indexOf('&')>=0)
- text = StringUtils.replaceAll(text, "&", "&");
- // <
- if (text.indexOf('<')>=0)
- text = StringUtils.replaceAll(text, "<", "<");
- // >
- if (text.indexOf('>')>=0)
- text = StringUtils.replaceAll(text, ">", ">");
- // done
- return text;
+ return HtmlUtils.getInstance().escapeText(text);
}
/**
diff --git
a/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/impl/ResourceTextResolver.java
b/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/impl/ResourceTextResolver.java
index 7cea1be7..284be3ed 100644
---
a/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/impl/ResourceTextResolver.java
+++
b/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/impl/ResourceTextResolver.java
@@ -24,6 +24,7 @@ import java.util.ResourceBundle;
import org.apache.empire.exceptions.EmpireException;
import org.apache.empire.jakarta.app.TextResolver;
+import org.apache.empire.jakarta.utils.HtmlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -107,13 +108,13 @@ public class ResourceTextResolver implements TextResolver
String[] params = ee.getErrorParams();
if (params!=null)
{ for (int i=0; i<params.length; i++)
- params[i] = resolveText(params[i]);
+ params[i] = resolveExceptionParam(params[i]);
}
// Format message
return EmpireException.formatErrorMessage(ee.getErrorType(),
pattern, params);
}
else
- { // Other exception try to resolve by class name
+ { // Other exceptions: try to resolve by class name
String key = "exception."+e.getClass().getName();
if (resBundle.containsKey(key))
return resBundle.getString(key);
@@ -121,4 +122,15 @@ public class ResourceTextResolver implements TextResolver
return e.getLocalizedMessage();
}
}
+
+ protected String resolveExceptionParam(String param)
+ {
+ if (param==null || param.length()==0)
+ return param;
+ // Translate
+ if (param.startsWith(MSG_KEY_INDICATOR))
+ return resolveText(param);
+ // Encode
+ return HtmlUtils.getInstance().escapeText(param);
+ }
}
diff --git
a/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/utils/HtmlUtils.java
b/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/utils/HtmlUtils.java
new file mode 100644
index 00000000..ec194bf7
--- /dev/null
+++
b/empire-db-jakarta-faces/src/main/java/org/apache/empire/jakarta/utils/HtmlUtils.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.empire.jakarta.utils;
+
+import org.apache.empire.commons.StringUtils;
+
+public class HtmlUtils
+{
+ private static HtmlUtils htmlUtils = new HtmlUtils();
+
+ public static HtmlUtils getInstance()
+ {
+ return htmlUtils;
+ }
+
+ public static void setInstance(HtmlUtils htmlUtils)
+ {
+ HtmlUtils.htmlUtils = htmlUtils;
+ }
+
+ /**
+ * escapes a String for html
+ *
+ * @param text
+ * @return the escaped html String
+ */
+ public String escapeText(String text)
+ {
+ if (text==null || text.length()==0)
+ return text;
+ // &
+ if (text.indexOf('&')>=0)
+ text = StringUtils.replaceAll(text, "&", "&");
+ // <
+ if (text.indexOf('<')>=0)
+ text = StringUtils.replaceAll(text, "<", "<");
+ // >
+ if (text.indexOf('>')>=0)
+ text = StringUtils.replaceAll(text, ">", ">");
+ // done
+ return text;
+ }
+
+}
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java
index 84bdfda1..8f4452bf 100644
---
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java
+++
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/controls/InputControl.java
@@ -43,6 +43,7 @@ import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ItemNotFoundException;
import org.apache.empire.exceptions.UnexpectedReturnValueException;
import org.apache.empire.jsf2.app.TextResolver;
+import org.apache.empire.jsf2.utils.HtmlUtils;
import org.apache.empire.jsf2.utils.TagStyleClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -799,19 +800,7 @@ public abstract class InputControl
*/
protected String escapeHTML(String text)
{
- if (text==null || text.length()==0)
- return text;
- // &
- if (text.indexOf('&')>=0)
- text = StringUtils.replaceAll(text, "&", "&");
- // <
- if (text.indexOf('<')>=0)
- text = StringUtils.replaceAll(text, "<", "<");
- // >
- if (text.indexOf('>')>=0)
- text = StringUtils.replaceAll(text, ">", ">");
- // done
- return text;
+ return HtmlUtils.getInstance().escapeText(text);
}
/**
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java
index a32e40d4..0a0ba465 100644
---
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java
+++
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/impl/ResourceTextResolver.java
@@ -24,6 +24,7 @@ import java.util.ResourceBundle;
import org.apache.empire.exceptions.EmpireException;
import org.apache.empire.jsf2.app.TextResolver;
+import org.apache.empire.jsf2.utils.HtmlUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -107,13 +108,13 @@ public class ResourceTextResolver implements TextResolver
String[] params = ee.getErrorParams();
if (params!=null)
{ for (int i=0; i<params.length; i++)
- params[i] = resolveText(params[i]);
+ params[i] = resolveExceptionParam(params[i]);
}
// Format message
return EmpireException.formatErrorMessage(ee.getErrorType(),
pattern, params);
}
else
- { // Other exception try to resolve by class name
+ { // Other exceptions: try to resolve by class name
String key = "exception."+e.getClass().getName();
if (resBundle.containsKey(key))
return resBundle.getString(key);
@@ -121,4 +122,15 @@ public class ResourceTextResolver implements TextResolver
return e.getLocalizedMessage();
}
}
+
+ protected String resolveExceptionParam(String param)
+ {
+ if (param==null || param.length()==0)
+ return param;
+ // Translate
+ if (param.startsWith(MSG_KEY_INDICATOR))
+ return resolveText(param);
+ // Encode
+ return HtmlUtils.getInstance().escapeText(param);
+ }
}
diff --git
a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/HtmlUtils.java
b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/HtmlUtils.java
new file mode 100644
index 00000000..07d622d1
--- /dev/null
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/HtmlUtils.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.empire.jsf2.utils;
+
+import org.apache.empire.commons.StringUtils;
+
+public class HtmlUtils
+{
+ private static HtmlUtils htmlUtils = new HtmlUtils();
+
+ public static HtmlUtils getInstance()
+ {
+ return htmlUtils;
+ }
+
+ public static void setInstance(HtmlUtils htmlUtils)
+ {
+ HtmlUtils.htmlUtils = htmlUtils;
+ }
+
+ /**
+ * escapes a String for html
+ *
+ * @param text
+ * @return the escaped html String
+ */
+ public String escapeText(String text)
+ {
+ if (text==null || text.length()==0)
+ return text;
+ // &
+ if (text.indexOf('&')>=0)
+ text = StringUtils.replaceAll(text, "&", "&");
+ // <
+ if (text.indexOf('<')>=0)
+ text = StringUtils.replaceAll(text, "<", "<");
+ // >
+ if (text.indexOf('>')>=0)
+ text = StringUtils.replaceAll(text, ">", ">");
+ // done
+ return text;
+ }
+
+}
diff --git
a/empire-db/src/main/java/org/apache/empire/exceptions/EmpireException.java
b/empire-db/src/main/java/org/apache/empire/exceptions/EmpireException.java
index 8ccda191..9ad3aee7 100644
--- a/empire-db/src/main/java/org/apache/empire/exceptions/EmpireException.java
+++ b/empire-db/src/main/java/org/apache/empire/exceptions/EmpireException.java
@@ -30,66 +30,104 @@ import org.slf4j.LoggerFactory;
public class EmpireException extends RuntimeException
{
private static final long serialVersionUID = 1L;
-
+
// Logger
private static final Logger log =
LoggerFactory.getLogger(EmpireException.class);
-
- private final ErrorType errorType;
- private final String[] errorParams;
- // private final String errorSourceClassname;
-
- public static String formatErrorMessage(final ErrorType errType, String
pattern, final String[] params)
+
+ /**
+ * ExceptionMessageFormatter
+ * returns a message text for an Exception from a given pattern and
parameters
+ */
+ public static class ExceptionMessageFormatter
{
- // Log Error
- try {
- // the pattern
- if (pattern==null)
- pattern=errType.getMessagePattern();
- // init format args
- Object[] formatArgs = params;
- // Check parameter count
- int patParamCount = errType.getNumParams();
- int paramCount = (params!=null) ? params.length : 0;
- if (paramCount < patParamCount)
- { // Number of parameters does not match
- log.warn("Invalid Number of arguments supplied for error " +
errType.getKey()
- + "\nArguments supplied= " + String.valueOf(paramCount)
+ "; Arguments expected= " + String.valueOf(errType.getNumParams()));
- // Return the pattern
- return pattern;
- }
- // more params than expected
- else if (paramCount>patParamCount)
- { // check for wildcard
+ protected String missingArgument = "?";
+
+ public String format(final ErrorType errType, String pattern, String[]
params)
+ {
+ // format error message
+ try {
+ // the pattern
+ if (pattern==null)
+ pattern=errType.getMessagePattern();
+ // Check parameter count
+ int patParamCount = errType.getNumParams();
+ int extraParamIndex = -1;
+ // wildcard
if (pattern.contains("{*}"))
{ pattern = pattern.replace("{*}",
"{"+String.valueOf(patParamCount)+"}");
+ extraParamIndex = patParamCount;
patParamCount++;
}
- // Build new array
- if (patParamCount>0)
- { // reduce number of arguments
- formatArgs = new String[patParamCount];
- int i=0;
- for (; i<patParamCount-1; i++)
- formatArgs[i]=params[i];
- // Build a array for the rest
- StringBuilder b = new StringBuilder();
- for (;i<paramCount;i++)
- { if (b.length()>0)
- b.append(", ");
- b.append(String.valueOf(params[i]));
- }
- formatArgs[patParamCount-1]=b.toString();
+ // check params
+ int paramCount = (params!=null) ? params.length : 0;
+ if (paramCount < patParamCount)
+ { // Missing arguments
+ log.warn("Invalid Number of arguments supplied for error
{}: Arguments expected={} / Arguments supplied={}.", errType.getKey(),
patParamCount, paramCount);
}
+ // more params than expected
+ else if (paramCount>patParamCount && extraParamIndex<0)
+ { // Too many arguments
+ log.info("Additional arguments supplied for error {}:
Arguments expected={} / Arguments supplied={}.", errType.getKey(),
patParamCount, paramCount);
+ }
+ // Build format list
+ Object[] messageArgs = new String[patParamCount];
+ for (int i=0; i<messageArgs.length; i++)
+ {
+ if (i==extraParamIndex) {
+ // summary of remaining params
+ StringBuilder b = new StringBuilder();
+ for (int j=extraParamIndex;j<paramCount;j++)
+ { if (b.length()>0)
+ b.append(", ");
+ b.append(formatParam(errType, i, params[j]));
+ }
+ messageArgs[i] = b.toString();
+ }
+ else if (i<paramCount)
+ messageArgs[i] = formatParam(errType, i, params[i]);
+ else
+ messageArgs[i] = missingArgument;
+ }
+ // format now
+ String msg = MessageFormat.format(pattern, messageArgs);
+ return msg;
+ } catch(Exception e) {
+ log.error("Unable to format error message: "+pattern, e);
+ return pattern;
}
- // format now
- String msg = MessageFormat.format(pattern, formatArgs);
- return msg;
- } catch(Exception e) {
- log.error("Unable to format error message: "+pattern, e);
- return pattern;
+ }
+
+ protected Object formatParam(final ErrorType errType, int index,
String param)
+ {
+ return param;
}
}
+ private static ExceptionMessageFormatter messageFormatter = new
ExceptionMessageFormatter();
+
+ public static ExceptionMessageFormatter getMessageFormatter()
+ {
+ return messageFormatter;
+ }
+
+ public static void setMessageFormatter(ExceptionMessageFormatter
messageFormatter)
+ {
+ if (messageFormatter==null)
+ throw new InvalidArgumentException("messageFormatter",
messageFormatter);
+ // set formatter
+ EmpireException.messageFormatter = messageFormatter;
+ }
+
+ public static String formatErrorMessage(final ErrorType errType, String
pattern, final String[] params)
+ {
+ return messageFormatter.format(errType, pattern, params);
+ }
+
+ private final ErrorType errorType;
+ private final String[] errorParams;
+ // private final String errorSourceClassname;
+
+
/**
* Constructor for derived classes
* @param errType
@@ -98,7 +136,7 @@ public class EmpireException extends RuntimeException
*/
protected EmpireException(final ErrorType errType, final String[] params,
final Throwable cause)
{
- super(formatErrorMessage(errType, null, params), cause);
+ super(messageFormatter.format(errType, null, params), cause);
// save type and params for custom message formatting
this.errorType = errType;
this.errorParams = params;