diff --git a/announcements/src/org/labkey/announcements/model/AnnouncementManager.java b/announcements/src/org/labkey/announcements/model/AnnouncementManager.java index 74997bb57a8..b843d213f08 100644 --- a/announcements/src/org/labkey/announcements/model/AnnouncementManager.java +++ b/announcements/src/org/labkey/announcements/model/AnnouncementManager.java @@ -1063,7 +1063,7 @@ public static HtmlString getUserDetailsLink(Container container, User currentUse if (includeGroups) { HtmlString groupList = SecurityManager.getGroupList(container, UserManager.getUser(formattedUserId)); - if (groupList.length() > 0) + if (!groupList.isEmpty()) { builder.append(" (").append(groupList).append(")"); } diff --git a/api/build.gradle b/api/build.gradle index 56a14fa7d58..067629305c7 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -381,7 +381,7 @@ dependencies { BuildUtils.addExternalDependency( project, new ExternalDependency( - "org.hamcrest:hamcrest-core:${hamcrestVersion}", + "org.hamcrest:hamcrest:${hamcrestVersion}", "Hamcrest", "Java Hamcrest", "http://hamcrest.org/JavaHamcrest/", diff --git a/api/schemas/queryCustomView.xsd b/api/schemas/queryCustomView.xsd index 55de1de2689..b0abe2a107d 100644 --- a/api/schemas/queryCustomView.xsd +++ b/api/schemas/queryCustomView.xsd @@ -133,6 +133,8 @@ + + diff --git a/api/src/org/labkey/api/admin/AdminBean.java b/api/src/org/labkey/api/admin/AdminBean.java index 35f2c8cc25d..3f3439d60da 100644 --- a/api/src/org/labkey/api/admin/AdminBean.java +++ b/api/src/org/labkey/api/admin/AdminBean.java @@ -170,20 +170,20 @@ public static Map getPropertyMap() public static HtmlString getPropertyGridHtml(Map propertyMap) { HtmlStringBuilder builder = HtmlStringBuilder.of() - .append(HtmlString.unsafe("")) - .append(HtmlString.unsafe("")) + .unsafeAppend("
PropertyCurrent Value
") + .unsafeAppend("") .append ( propertyMap.entrySet().stream() .map(e -> HtmlStringBuilder.of(HtmlString.unsafe("\n")) + .unsafeAppend("\n") .getHtmlString()) .collect(LabKeyCollectors.joining(HtmlString.unsafe("\n"))) ) - .append(HtmlString.unsafe("
PropertyCurrent Value
")) .append(e.getKey()) - .append(HtmlString.unsafe("")) + .unsafeAppend("") .append(formatValue(e.getKey(), e.getValue())) - .append(HtmlString.unsafe("
\n")); + .unsafeAppend("\n"); return builder.getHtmlString(); } @@ -192,6 +192,6 @@ private static HtmlString formatValue(String key, String value) { // Format GUID properties with monospace font return StringUtils.endsWithIgnoreCase(key, "GUID") ? HtmlStringBuilder.of(HtmlString.unsafe("")) - .append(value).append(HtmlString.unsafe("")).getHtmlString() : HtmlString.of(value); + .append(value).unsafeAppend("").getHtmlString() : HtmlString.of(value); } } diff --git a/api/src/org/labkey/api/assay/AssayProtocolSchema.java b/api/src/org/labkey/api/assay/AssayProtocolSchema.java index 98fbc51def6..a2a466079a5 100644 --- a/api/src/org/labkey/api/assay/AssayProtocolSchema.java +++ b/api/src/org/labkey/api/assay/AssayProtocolSchema.java @@ -926,7 +926,7 @@ public HtmlString getFormattedHtml(RenderContext ctx) } for (Map.Entry decodedVal : decodedVals.entrySet()) { - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); sb.append(StringUtils.substringAfter(decodedVal.getKey(), ThawListResolverType.NAMESPACE_PREFIX)); sb.append(" : "); sb.append(decodedVal.getValue()); diff --git a/api/src/org/labkey/api/data/DataColumn.java b/api/src/org/labkey/api/data/DataColumn.java index bf455df54a4..1da8fd4b1e2 100644 --- a/api/src/org/labkey/api/data/DataColumn.java +++ b/api/src/org/labkey/api/data/DataColumn.java @@ -569,14 +569,14 @@ public HtmlString getFormattedHtml(RenderContext ctx) if (getRequiresHtmlFiltering()) formatted = PageFlowUtil.filter(formatted); - if (formatted.length() == 0) + if (formatted.isEmpty()) formatted = " "; else if (isPreserveNewlines()) formatted = formatted.replaceAll("\\n", "
\n"); else if (value instanceof Date) formatted = "" + formatted + ""; - hsb.append(HtmlString.unsafe(formatted)); + hsb.unsafeAppend(formatted); } return hsb.getHtmlString(); diff --git a/api/src/org/labkey/api/data/DbSchema.java b/api/src/org/labkey/api/data/DbSchema.java index 458d886ce86..e5722aa661d 100644 --- a/api/src/org/labkey/api/data/DbSchema.java +++ b/api/src/org/labkey/api/data/DbSchema.java @@ -858,19 +858,19 @@ OrphanedContainer VARCHAR(60) NULL { new SqlSelector(coreSchema, " SELECT * FROM " + tempTableName + " WHERE OrphanedContainer IS NOT NULL ORDER BY 1,3").forEach(rs -> { - sbOut.append(HtmlString.unsafe("
   ")) + sbOut.unsafeAppend("
   ") .append("ERROR: ") .append(rs.getString(1)) - .append(HtmlString.unsafe("      ")) + .unsafeAppend("      ") .append(rs.getString(2)) .append("." ) .append(rs.getString(3)) .append(" = ") .append(rs.getString(4)) - .append(HtmlString.unsafe("   ")) + .unsafeAppend("   ") .append("Module: ") .append(rs.getString(5)) - .append(HtmlString.unsafe("   ")) + .unsafeAppend("   ") .append("Container: ") .append(rs.getString(6)) .append("\n"); diff --git a/api/src/org/labkey/api/data/MVDisplayColumn.java b/api/src/org/labkey/api/data/MVDisplayColumn.java index aa8e673e0e0..f9546577c36 100644 --- a/api/src/org/labkey/api/data/MVDisplayColumn.java +++ b/api/src/org/labkey/api/data/MVDisplayColumn.java @@ -73,10 +73,10 @@ public void renderGridCellContents(RenderContext ctx, Writer out) throws IOExcep // If we have a raw value, include it in the popup HtmlString value = super.getFormattedHtml(ctx); - if (value.length() != 0) - popupText.append(HtmlString.unsafe("

The value as originally entered was: '")) + if (!value.isEmpty()) + popupText.unsafeAppend("

The value as originally entered was: '") .append(value) - .append(HtmlString.unsafe("'.

")); + .unsafeAppend("'.

"); out.write(""); PageFlowUtil.popupHelp(popupText.getHtmlString(), "Missing Value Indicator: " + mvIndicator).link(HtmlString.of(mvIndicator)).appendTo(out); diff --git a/api/src/org/labkey/api/data/RenderContext.java b/api/src/org/labkey/api/data/RenderContext.java index a4302c7d4f1..0ffbb7ce0a4 100644 --- a/api/src/org/labkey/api/data/RenderContext.java +++ b/api/src/org/labkey/api/data/RenderContext.java @@ -905,8 +905,8 @@ public HtmlString getErrors(String paramName) } uniqueErrorStrs.add(errStr); } - if (builder.toString().length() > 0) - builder.append(HtmlString.unsafe("")); + if (!builder.isEmpty()) + builder.unsafeAppend(""); return builder.getHtmlString(); } diff --git a/api/src/org/labkey/api/data/views/DataViewInfo.java b/api/src/org/labkey/api/data/views/DataViewInfo.java index f361866972e..65b101b7c33 100644 --- a/api/src/org/labkey/api/data/views/DataViewInfo.java +++ b/api/src/org/labkey/api/data/views/DataViewInfo.java @@ -59,6 +59,7 @@ public interface DataViewInfo @Nullable String getSchemaName(); @Nullable String getQueryName(); @Nullable String getViewName(); + @Nullable String getDataRegionName(); boolean isVisible(); // specifies whether this view is hidden boolean showInDashboard(); // an optional visibility level diff --git a/api/src/org/labkey/api/data/views/DataViewService.java b/api/src/org/labkey/api/data/views/DataViewService.java index 453512b0217..8987aff98ee 100644 --- a/api/src/org/labkey/api/data/views/DataViewService.java +++ b/api/src/org/labkey/api/data/views/DataViewService.java @@ -197,6 +197,8 @@ public JSONObject toJSON(User user, DataViewInfo info) o.put("queryName", info.getQueryName()); if (info.getViewName() != null) o.put("viewName", info.getViewName()); + if (info.getDataRegionName() != null) + o.put("dataRegionName", info.getDataRegionName()); if (info.getDefaultIconCls() != null) o.put("defaultIconCls", info.getDefaultIconCls()); diff --git a/api/src/org/labkey/api/data/views/DefaultViewInfo.java b/api/src/org/labkey/api/data/views/DefaultViewInfo.java index 9d284ab9aa0..9c6fc0b2756 100644 --- a/api/src/org/labkey/api/data/views/DefaultViewInfo.java +++ b/api/src/org/labkey/api/data/views/DefaultViewInfo.java @@ -72,6 +72,7 @@ public class DefaultViewInfo implements DataViewInfo private String _schemaName; private String _queryName; private String _viewName; + private String _dataRegionName; private int _displayOrder; @@ -436,6 +437,18 @@ public void setQueryName(String queryName) public void setViewName(String viewName) { _viewName = viewName; } + @Nullable + @Override + public String getDataRegionName() + { + return _dataRegionName; + } + + public void setDataRegionName(String dataRegionName) + { + _dataRegionName = dataRegionName; + } + @Override public int getDisplayOrder() {return _displayOrder; } diff --git a/api/src/org/labkey/api/exp/OntologyManager.java b/api/src/org/labkey/api/exp/OntologyManager.java index bff82b80f8e..8377f584e04 100644 --- a/api/src/org/labkey/api/exp/OntologyManager.java +++ b/api/src/org/labkey/api/exp/OntologyManager.java @@ -3748,7 +3748,7 @@ private static void doProjectColumnCheck(final String descriptorTable, final Str { fixProjectColumn(descriptorTable, uriColumn, idColumn, container, projectId, newProjectId); msgBuilder - .append(HtmlString.unsafe("
   ")) + .unsafeAppend("
   ") .append("Fixed inconsistent project ids found for ") .append(descriptorTable).append(" in folder ") .append(ContainerManager.getForId(containerId).getPath()); @@ -3756,7 +3756,7 @@ private static void doProjectColumnCheck(final String descriptorTable, final Str } else msgBuilder - .append(HtmlString.unsafe("
   ")) + .unsafeAppend("
   ") .append("ERROR: Inconsistent project ids found for ") .append(descriptorTable).append(" in folder ").append(container.getPath()); } diff --git a/api/src/org/labkey/api/jsp/JspBase.java b/api/src/org/labkey/api/jsp/JspBase.java index 88ddfdd3e14..6f9b3522af2 100644 --- a/api/src/org/labkey/api/jsp/JspBase.java +++ b/api/src/org/labkey/api/jsp/JspBase.java @@ -16,7 +16,6 @@ package org.labkey.api.jsp; -import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.json.JSONArray; @@ -71,9 +70,8 @@ import static org.labkey.api.util.PageFlowUtil.filter; /** - * Base class for nearly all JSP pages that we use. - * This is the place to put methods that will be useful to lots - * of pages, regardless of what they do, or what module they are in. + * Base class for nearly all JSP pages that we use. This is the place to put methods that will be useful to lots of + * pages, regardless of what they do, or what module they are in. *

* BE VERY CAREFUL NOT TO ADD POORLY NAMED METHODS TO THIS CLASS!!!! *

@@ -120,7 +118,7 @@ public User getUser() // Encoded version of the context path public HtmlString getContextPath() { - return HtmlString.of(_viewContext.getContextPath()); + return h(_viewContext.getContextPath()); } /** @@ -132,7 +130,7 @@ public HtmlString getContextPath() */ public HtmlString getWebappURL(String path) { - return HtmlString.of(PageFlowUtil.staticResourceUrl(path)); + return h(PageFlowUtil.staticResourceUrl(path)); } /** @@ -195,7 +193,7 @@ public HtmlString unsafe(CharSequence cs) * Html escape a string. * The name comes from Embedded Ruby. */ - public HtmlString h(String str) + public static HtmlString h(String str) { return HtmlString.of(str); } @@ -204,32 +202,32 @@ public HtmlString h(String str) * Html escape an object.toString(). * The name comes from Embedded Ruby. */ - public HtmlString h(Object o) + public static HtmlString h(Object o) { - return HtmlString.of(o == null ? null : o.toString()); + return h(o == null ? null : o.toString()); } /** * Html escape a string. * The name comes from Embedded Ruby. */ - public HtmlString h(String str, boolean encodeSpace) + public static HtmlString h(String str, boolean encodeSpace) { return HtmlString.of(str, encodeSpace); } - public HtmlString h(URLHelper url) + public static HtmlString h(URLHelper url) { - return HtmlString.of(url == null ? null : url.toString()); + return h(url == null ? null : url.toString()); } // Note: If you have a stream, use LabKeyCollectors.toJsonArray() - public JSONArray toJsonArray(Collection c) + public static JSONArray toJsonArray(Collection c) { return new JSONArray(c); } - public JSONObject toJsonObject(Map c) + public static JSONObject toJsonObject(Map c) { return new JSONObject(c); } @@ -239,7 +237,7 @@ public JSONObject toJsonObject(Map c) * @param indentFactor Number of spaces to add to each level of indentation * @return JavaScriptFragment holding the JSON representation */ - public JavaScriptFragment json(JSONArray array, int indentFactor) + public static JavaScriptFragment json(JSONArray array, int indentFactor) { return JavaScriptFragment.unsafe(array.toString(indentFactor)); } @@ -249,7 +247,7 @@ public JavaScriptFragment json(JSONArray array, int indentFactor) * @param indentFactor Number of spaces to add to each level of indentation * @return JavaScriptFragment holding the JSON representation */ - public JavaScriptFragment json(JSONObject jsonObject, int indentFactor) + public static JavaScriptFragment json(JSONObject jsonObject, int indentFactor) { return JavaScriptFragment.unsafe(jsonObject.toString(indentFactor)); } @@ -333,7 +331,7 @@ public JavaScriptFragment jsURL(@NotNull URLHelper url) } - private static final HtmlString CHECKED = HtmlString.of(" checked"); + private static final HtmlString CHECKED = h(" checked"); /** Returns " checked" (if true) or "" (false) */ public HtmlString checked(boolean checked) @@ -667,22 +665,16 @@ public List getErrorsForPath(String path) return l; } - public String formatErrorsForPathStr(String path) + public @NotNull HtmlString formatErrorsForPath(String path) { List l = getErrorsForPath(path); return _formatErrorList(l, false); } - public HtmlString formatErrorsForPath(String path) - { - return HtmlString.unsafe(formatErrorsForPathStr(path)); - } - - //Set _returnedErrors = new HashSet(); - IdentityHashMap _returnedErrors = new IdentityHashMap<>(); + private final IdentityHashMap _returnedErrors = new IdentityHashMap<>(); // For extra credit, return list of errors not returned by formatErrorsForPath() or formatErrorForPath() - public List getMissedErrors(String bean) + public @NotNull List getMissedErrors(String bean) { Errors errors = getErrors(bean); ArrayList missed = new ArrayList<>(); @@ -701,60 +693,51 @@ public List getMissedErrors(String bean) return missed; } - protected String formatMissedErrorsStr(String bean) + protected @NotNull HtmlString formatMissedErrors(String bean) { List l = getMissedErrors(bean); // fieldNames==true is ugly, but these errors are probably not displayed in the right place on the form return _formatErrorList(l, true); } - protected HtmlString formatMissedErrors(String bean) - { - return HtmlString.unsafe(formatMissedErrorsStr(bean)); - } - - protected HtmlString formatMissedErrors(String bean, String prefix, String suffix) - { - String str = formatMissedErrorsStr(bean); - if (StringUtils.isEmpty(str)) - return HtmlString.of(str); - else - return HtmlString.unsafe(prefix + str + suffix); - } - // If errors exist, returns formatted errors in a with the specified colspan (or no colspan, for 0 or 1) followed by a blank line - // If no errors, returns an empty string - protected HtmlString formatMissedErrorsInTable(String bean, int colspan) + // If no errors, returns an empty HtmlString + protected @NotNull HtmlString formatMissedErrorsInTable(String bean, int colspan) { - String errorHTML = formatMissedErrorsStr(bean); + HtmlString errorHTML = formatMissedErrors(bean); - if (StringUtils.isEmpty(errorHTML)) - return HtmlString.of(errorHTML); + if (errorHTML.isEmpty()) + return errorHTML; else - return HtmlString.unsafe("\n 1 ? " colspan=" + colspan : "") + ">" + errorHTML + "\n 1 ? " colspan=" + colspan : "") + "> "); + return HtmlStringBuilder.of(HtmlString.unsafe("\n 1 ? " colspan=" + colspan : "") + ">")) + .append(errorHTML) + .unsafeAppend("\n 1 ? " colspan=" + colspan : "") + "> ") + .getHtmlString(); } - // TODO: Should return HtmlString! - protected String _formatErrorList(List l, boolean fieldNames) + private @NotNull HtmlString _formatErrorList(List l, boolean fieldNames) { - if (l.size() == 0) - return ""; + if (l.isEmpty()) + return EMPTY_STRING; + ViewContext context = getViewContext(); - StringBuilder message = new StringBuilder(); - String br = ""; - message.append("

"); + HtmlStringBuilder message = HtmlStringBuilder.of(HtmlString.unsafe("
")); + HtmlString br = EMPTY_STRING; for (ObjectError e : l) { message.append(br); - br = "
"; + br = HtmlString.BR; if (fieldNames && e instanceof FieldError) { - message.append("").append(h(((FieldError) e).getField())).append(": "); + message.unsafeAppend("") + .append(((FieldError) e).getField()) + .unsafeAppend(": "); } - message.append(h(context.getMessage(e))); + message.append(context.getMessage(e)); } - message.append("
"); - return message.toString(); + message.unsafeAppend("
"); + + return message.getHtmlString(); } protected enum Method @@ -831,7 +814,10 @@ protected HtmlString getTroubleshooterWarning(boolean canUpdate, HtmlString pref if (canUpdate) return EMPTY_STRING; else - return HtmlStringBuilder.of(prefix).append(HtmlString.unsafe("Note: You have permission to read these settings but not modify them. Changes will not be saved.
")).append(suffix).getHtmlString(); + return HtmlStringBuilder.of(prefix) + .unsafeAppend("Note: You have permission to read these settings but not modify them. Changes will not be saved.
") + .append(suffix) + .getHtmlString(); } protected HtmlString getScriptNonce() diff --git a/api/src/org/labkey/api/reports/report/python/IpynbReport.java b/api/src/org/labkey/api/reports/report/python/IpynbReport.java index db47d0b58f7..08a529f63a4 100644 --- a/api/src/org/labkey/api/reports/report/python/IpynbReport.java +++ b/api/src/org/labkey/api/reports/report/python/IpynbReport.java @@ -1,6 +1,5 @@ package org.labkey.api.reports.report.python; -import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; @@ -404,7 +403,7 @@ public int execute(ViewContext context, String apiKey, File working, File ipynb) List files = null == listFiles ? List.of() : Arrays.asList(listFiles); for (var file : files) { - ArchiveEntry entry = tar.createArchiveEntry(file, file.getName()); + TarArchiveEntry entry = tar.createArchiveEntry(file, file.getName()); tar.putArchiveEntry(entry); try(FileInputStream fis = new FileInputStream(file)) { diff --git a/api/src/org/labkey/api/reports/report/r/view/IpynbOutput.java b/api/src/org/labkey/api/reports/report/r/view/IpynbOutput.java index b0944e08e1d..21a21bef0d5 100644 --- a/api/src/org/labkey/api/reports/report/r/view/IpynbOutput.java +++ b/api/src/org/labkey/api/reports/report/r/view/IpynbOutput.java @@ -156,13 +156,13 @@ protected String renderInternalAsString(File file) throws Exception { final JSONObject obj = new JSONObject(result); HtmlStringBuilder sb = HtmlStringBuilder.of(); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); JSONArray arr = obj.optJSONArray("cells"); if (null == arr) { JSONArray worksheets = obj.optJSONArray("worksheets"); - if (null != worksheets && worksheets.length() > 0) + if (null != worksheets && !worksheets.isEmpty()) arr = worksheets.getJSONObject(0).optJSONArray("cells"); } @@ -180,10 +180,10 @@ else if (cell.has("prompt_number")) execution_count = String.valueOf(cell.get("prompt_number")); HtmlString executionCountDiv = HtmlString.unsafe("
" + (execution_count != null ? "[ " + execution_count + " ]" : "") + "
"); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); sb.append(executionCountDiv); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); switch (cell_type) { @@ -193,37 +193,37 @@ else if (cell.has("prompt_number")) case "header" -> renderHeaderCell(sb, cell); // old format } - sb.append(HtmlString.unsafe("
")); // ipynb-cell-source + sb.unsafeAppend("
"); // ipynb-cell-source JSONArray outputs = cell.optJSONArray("outputs"); - if (outputs != null && outputs.length() > 0) + if (outputs != null && !outputs.isEmpty()) { sb.append(executionCountDiv); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); for (int outputindex = 0; outputindex < outputs.length(); outputindex++) { renderOutput(sb, outputs.getJSONObject(outputindex)); } - sb.append(HtmlString.unsafe("
")); // ipynb-cell-outputs + sb.unsafeAppend("
"); // ipynb-cell-outputs } - sb.append(HtmlString.unsafe("
")); // ipynb-cell + sb.unsafeAppend("
"); // ipynb-cell } - sb.append(HtmlString.unsafe("
")); // labkey-wiki + sb.unsafeAppend("
"); // labkey-wiki return sb.toString(); } catch (Exception ex) { HtmlStringBuilder sb = HtmlStringBuilder.of(); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); sb.append(HtmlString.of(ex.getMessage())); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); if (ex instanceof JSONException) { - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); sb.append(HtmlString.of(result)); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); } return sb.toString(); } @@ -231,7 +231,7 @@ else if (cell.has("prompt_number")) private void renderStylesheet(HtmlStringBuilder sb) { - sb.append(HtmlString.unsafe( + sb.unsafeAppend( """ """ - )); + ); } @@ -288,9 +288,9 @@ private void renderOutput(HtmlStringBuilder sbOutput, @NotNull JSONObject output case "error": case "pyerr": // old format { - sb.append(HtmlString.unsafe("
")); - sb.append(HtmlString.unsafe("
\n"));
-                    sb.append(HtmlString.unsafe("")).append((String)output.get("ename")).append(": ").append((String)output.get("evalue")).append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); + sb.unsafeAppend("
\n");
+                    sb.unsafeAppend("").append((String)output.get("ename")).append(": ").append((String)output.get("evalue")).unsafeAppend("
"); JSONArray traceback = output.optJSONArray("traceback"); if (null != traceback) { @@ -298,10 +298,10 @@ private void renderOutput(HtmlStringBuilder sbOutput, @NotNull JSONObject output { String line = ((String) traceback.get(i)); String clean = stripAnsiColors(line); - sb.append(" ").append(clean).append("\n") ; + sb.append(" ").append(clean).append("\n"); } } - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); sbOutput.append(sb); return; } @@ -314,16 +314,16 @@ private void renderOutput(HtmlStringBuilder sbOutput, @NotNull JSONObject output data = output.getJSONObject("data"); if (null != data) { - String imagePng = StringUtils.defaultString(data.optString("image/png", null), data.optString("png", null)); + String imagePng = Objects.toString(data.optString("image/png", null), data.optString("png", null)); if (null != imagePng) { // let's validate that this at least might be base64 if (StringUtils.containsNone(imagePng, "<&-\"'%\\")) { - sb.append(HtmlString.unsafe("
")); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); + sb.unsafeAppend("
"); sbOutput.append(sb); return; } @@ -331,10 +331,10 @@ private void renderOutput(HtmlStringBuilder sbOutput, @NotNull JSONObject output if (data.has("image/svg+xml")) { var textArray = data.getJSONArray("image/svg+xml"); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); for (int i = 0; i < textArray.length(); i++) - sb.append(HtmlString.unsafe((String)textArray.get(i))); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend((String)textArray.get(i)); + sb.unsafeAppend("
"); sbOutput.append(sb); return; } @@ -342,11 +342,11 @@ private void renderOutput(HtmlStringBuilder sbOutput, @NotNull JSONObject output { boolean isError = "stderr".equals(data.opt("name")); var textArray = Objects.requireNonNullElse(data.optJSONArray("text/plain"), data.optJSONArray("text")); - sb.append(HtmlString.unsafe("
")); - sb.append(HtmlString.unsafe("
\n"));
+                            sb.unsafeAppend("
"); + sb.unsafeAppend("
\n");
                             for (int i=0 ; i
")); + sb.unsafeAppend("
"); sbOutput.append(sb); return; } @@ -363,10 +363,10 @@ private void renderCodeSource(HtmlStringBuilder sb, JSONObject cell) String source = getSource(cell); if (null != source) { - sb.append(HtmlString.unsafe("
")); - sb.append(HtmlString.unsafe("
\n"));
+                sb.unsafeAppend("
"); + sb.unsafeAppend("
\n");
                 sb.append(HtmlString.of(source, false));
-                sb.append(HtmlString.unsafe("\n
")); + sb.unsafeAppend("\n
"); } } @@ -376,10 +376,10 @@ private void renderRawSource(HtmlStringBuilder sb, JSONObject cell) String source = getSource(cell); if (null != source) { - sb.append(HtmlString.unsafe("
")); - sb.append(HtmlString.unsafe("
\n"));
+                sb.unsafeAppend("
"); + sb.unsafeAppend("
\n");
                 sb.append(HtmlString.of(source, false));
-                sb.append(HtmlString.unsafe("\n
")); + sb.unsafeAppend("\n
"); } } @@ -389,9 +389,9 @@ private void renderMarkdownSource(HtmlStringBuilder sb, JSONObject cell) throws String source = getSource(cell); if (null != source) { - sb.append(HtmlString.unsafe("
")); - sb.append(HtmlString.unsafe(MarkdownService.get().toHtml(source, Map.of(MarkdownService.Options.html,true)))); - sb.append(HtmlString.unsafe("
")); + sb.unsafeAppend("
"); + sb.unsafeAppend(MarkdownService.get().toHtml(source, Map.of(MarkdownService.Options.html,true))); + sb.unsafeAppend("
"); } } diff --git a/api/src/org/labkey/api/security/AuthenticationManager.java b/api/src/org/labkey/api/security/AuthenticationManager.java index 50f442fc439..cbc7506b4ec 100644 --- a/api/src/org/labkey/api/security/AuthenticationManager.java +++ b/api/src/org/labkey/api/security/AuthenticationManager.java @@ -1584,9 +1584,9 @@ public HtmlString getImg(AuthLogoType logoType) { HtmlString message = HtmlString.of("Sign in using " + _configuration.getDescription()); return HtmlStringBuilder.of(HtmlString.unsafe("\"")).append(message)")).getHtmlString(); + .unsafeAppend("\" alt=\"").append(message) + .unsafeAppend("\" title=\"").append(message) + .unsafeAppend("\" height=\"").append(logoType.getHeight()).unsafeAppend("px\">").getHtmlString(); } } catch (RuntimeSQLException e) diff --git a/api/src/org/labkey/api/security/SecurityManager.java b/api/src/org/labkey/api/security/SecurityManager.java index fdb510629ba..1540f005b4b 100644 --- a/api/src/org/labkey/api/security/SecurityManager.java +++ b/api/src/org/labkey/api/security/SecurityManager.java @@ -2534,9 +2534,9 @@ else if (sendMail) if (currentUser.hasSiteAdminPermission()) { message.append(" Click "); - message.append(HtmlString.unsafe("here")); + message.unsafeAppend("\" target=\"_blank\">here"); message.append(" to change the password from the random one that was assigned."); } @@ -2547,9 +2547,9 @@ else if (sendMail) { message.append(HtmlString.BR); message.append(email.getEmailAddress()); - message.append(HtmlString.unsafe(" was added successfully, but could not be emailed due to a failure:
"));
+            message.unsafeAppend(" was added successfully, but could not be emailed due to a failure:
");
             message.append(e.getMessage());
-            message.append(HtmlString.unsafe("
")); + message.unsafeAppend("
"); appendMailHelpText(message, messageContentsURL, currentUser.hasRootPermission(AddUserPermission.class)); User newUser = UserManager.getUser(email); @@ -2638,8 +2638,8 @@ private static void appendMailHelpText(HtmlStringBuilder builder, ActionURL mess builder.append(" into an email client and send it to the user manually."); } - builder.append(HtmlString.unsafe("

")); - builder.append(HtmlString.unsafe("

For help on fixing your mail server settings, please consult the SMTP section of the ")); + builder.unsafeAppend("

"); + builder.unsafeAppend("

For help on fixing your mail server settings, please consult the SMTP section of the "); builder.append(new HelpTopic("labkeyxml").getSimpleLinkHtml("LabKey documentation on modifying your configuration file")); builder.append(".").append(HtmlString.BR); } @@ -2958,7 +2958,7 @@ public static void adminRotatePassword(ValidEmail email, BindException errors, C catch (ConfigurationException | MessagingException e) { String message = "Failed to send email due to: " + e.getMessage(); - errors.addError(mailErrorHtml.length() != 0 ? new LabKeyErrorWithHtml(message, mailErrorHtml) : new LabKeyError(message)); + errors.addError(!mailErrorHtml.isEmpty() ? new LabKeyErrorWithHtml(message, mailErrorHtml) : new LabKeyError(message)); UserManager.addToUserHistory(UserManager.getUser(email), user.getEmail() + " " + pastVerb + " the password, but sending the email failed."); } } diff --git a/api/src/org/labkey/api/study/query/PublishResultsQueryView.java b/api/src/org/labkey/api/study/query/PublishResultsQueryView.java index 4e48a6d58f8..aa33e99440c 100644 --- a/api/src/org/labkey/api/study/query/PublishResultsQueryView.java +++ b/api/src/org/labkey/api/study/query/PublishResultsQueryView.java @@ -707,11 +707,11 @@ public Pair getSampleMatchStatus(RenderContext ctx) } } - HtmlStringBuilder builder = HtmlStringBuilder.of(); - builder.append(HtmlString.unsafe("

The Sample ID in this row does")); + HtmlStringBuilder builder = HtmlStringBuilder.of() + .unsafeAppend("

The Sample ID in this row does"); if (!isSampleMatched) - builder.append(HtmlString.unsafe(" not")); - builder.append(HtmlString.unsafe(" match a sample in the study.

")); + builder.unsafeAppend(" not"); + builder.unsafeAppend(" match a sample in the study.

"); return new Pair<>(isSampleMatched, builder.getHtmlString()); } diff --git a/api/src/org/labkey/api/util/HtmlString.java b/api/src/org/labkey/api/util/HtmlString.java index 759efb3560d..9bcea30833e 100644 --- a/api/src/org/labkey/api/util/HtmlString.java +++ b/api/src/org/labkey/api/util/HtmlString.java @@ -172,4 +172,9 @@ public String toText() { return JSoupUtil.convertHtmlToText(_s); } + + public boolean isEmpty() + { + return length() == 0; + } } diff --git a/api/src/org/labkey/api/util/PageFlowUtil.java b/api/src/org/labkey/api/util/PageFlowUtil.java index e3ff7530573..097993838c3 100644 --- a/api/src/org/labkey/api/util/PageFlowUtil.java +++ b/api/src/org/labkey/api/util/PageFlowUtil.java @@ -1691,12 +1691,12 @@ public static HtmlString getFaviconIncludes(Container c) ResourceURL faviconURL = TemplateResourceHandler.FAVICON.getURL(c); HtmlStringBuilder builder = HtmlStringBuilder.of() - .append(HtmlString.unsafe("\n")) - .append(HtmlString.unsafe("\n") + .unsafeAppend("\n")); + .unsafeAppend("\">\n"); return builder.getHtmlString(); } @@ -1805,14 +1805,14 @@ private static void writeCss(Container c, SafeToRenderBuilder builder, LinkedHas { for (String script : r.getCssPaths(c)) { - html.append(HtmlString.unsafe("")); + html.unsafeAppend("\" type=\"text/css\" rel=\"stylesheet\">"); cssFiles.add(script); } @@ -1822,7 +1822,7 @@ private static void writeCss(Container c, SafeToRenderBuilder builder, LinkedHas builder.append(html); //cache list of CSS files to prevent double-loading - if (cssFiles.size() > 0) + if (!cssFiles.isEmpty()) { SafeToRenderBuilder scriptBuilder = SafeToRenderBuilder.of(); scriptBuilder.append(HttpView.currentPageConfig().getScriptTagStart()); @@ -1967,9 +1967,9 @@ public static HtmlString getScriptTag(String path) { HtmlString nonce = HttpView.currentPageConfig().getScriptNonce(); return HtmlStringBuilder.of() - .append(HtmlString.unsafe("\n")) + .unsafeAppend("\" type=\"text/javascript\" nonce=\"").append(nonce).unsafeAppend("\">\n") .getHtmlString(); } @@ -2005,8 +2005,8 @@ private static SafeToRender getJavaScriptIncludes(Container c, LinkedHashSet\n")); + .append(HtmlString.of(path)) + .append(HtmlString.unsafe("\" type=\"text/javascript\" nonce=\"")).append(nonce).append(HtmlString.unsafe("\">\n")); } return builder.getSafeToRender(); diff --git a/api/src/org/labkey/api/view/HtmlView.java b/api/src/org/labkey/api/view/HtmlView.java index 7f58acf2b74..16992ecfe52 100644 --- a/api/src/org/labkey/api/view/HtmlView.java +++ b/api/src/org/labkey/api/view/HtmlView.java @@ -66,9 +66,10 @@ public static HtmlView of(String msg) public static HtmlView err(String error) { return new HtmlView( - HtmlStringBuilder.of(HtmlString.unsafe("")) - .append(error) - .append(HtmlString.unsafe(""))); + HtmlStringBuilder.of(HtmlString.unsafe("")) + .append(error) + .unsafeAppend("") + ); } public static HtmlView unsafe(String html) diff --git a/api/src/org/labkey/api/view/template/PageConfig.java b/api/src/org/labkey/api/view/template/PageConfig.java index 9d7ed05c997..bf12198fcd6 100644 --- a/api/src/org/labkey/api/view/template/PageConfig.java +++ b/api/src/org/labkey/api/view/template/PageConfig.java @@ -436,7 +436,10 @@ public HtmlString getPreloadTags() HtmlStringBuilder sb = HtmlStringBuilder.of(); //noinspection RedundantOperationOnEmptyContainer fonts.stream().map(PageFlowUtil::staticResourceUrl).forEach(url-> - sb.append(HtmlString.unsafe(""))); + sb.unsafeAppend("") + ); return sb.getHtmlString(); } @@ -451,17 +454,17 @@ public HtmlString getMetaTags(URLHelper url) String canonical = getCanonicalLink(url); if (null != canonical) { - sb.append(HtmlString.unsafe("\n")); + sb.unsafeAppend("\n"); } if (!_meta.isEmpty()) { for (Map.Entry> e : _meta.asMap().entrySet()) { - sb.append(HtmlString.unsafe("\n")); + sb.unsafeAppend("\n"); } } return sb.getHtmlString(); @@ -516,7 +519,7 @@ public HtmlStringBuilder renderSiteMessages(ViewContext context) if (_template != Template.Print) { // Keep an empty div for re-addition of dismissible messages onto the page - messages.append(HtmlString.unsafe("
")); + messages.unsafeAppend("
"); if (context != null && context.getRequest() != null) { Warnings warnings = WarningService.get().getWarnings(context); @@ -536,12 +539,12 @@ else if (!(boolean) session.getAttribute(SESSION_WARNINGS_BANNER_KEY) && warning messages.append(WarningService.get().getWarningsHtml(warnings, context)); } } - messages.append(HtmlString.unsafe("
")); + messages.unsafeAppend("
"); // Display a