This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v3
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/v3 by this push:
new b2118706420 CAUSEWAY-3958: Clob content is required to be UTF-8
b2118706420 is described below
commit b211870642025358370d78ab321c8beb6f00ea99
Author: andi-huber <[email protected]>
AuthorDate: Sun Jan 18 16:58:07 2026 +0100
CAUSEWAY-3958: Clob content is required to be UTF-8
for other use-cases use Blob
---
.../attributes/blobclob/ClobAttributePanel.java | 16 ++--
.../viewer/wicket/ui/exec/LobRequestHandler.java | 102 +++++++++++++++++++++
2 files changed, 111 insertions(+), 7 deletions(-)
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/ClobAttributePanel.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/ClobAttributePanel.java
index c4251c6610b..150d500f7b9 100644
---
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/ClobAttributePanel.java
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/blobclob/ClobAttributePanel.java
@@ -23,20 +23,19 @@
import org.apache.wicket.markup.html.form.upload.FileUpload;
import org.apache.wicket.model.IModel;
-import org.apache.wicket.request.resource.CharSequenceResource;
+import org.apache.wicket.request.resource.ByteArrayResource;
import org.apache.wicket.request.resource.IResource;
+import org.apache.causeway.applib.value.Blob;
import org.apache.causeway.applib.value.Clob;
import org.apache.causeway.viewer.wicket.model.models.FileUploadModels;
import org.apache.causeway.viewer.wicket.model.models.UiAttributeWkt;
/**
* Panel for rendering scalars of type {@link Clob}.
- *
- * <p>
- * TODO: for now, this only handles {@link Clob}s encoded as UTF-8.
- * One option might be to 'guess' the character encoding, eg akin to
cpdetector?
- * </p>
+ *
+ * <p>WARNING only handles {@link Clob}s encoded as UTF-8.
+ * For different use-cases use {@link Blob} instead.
*/
class ClobAttributePanel extends BlobOrClobAttributePanel<Clob> {
@@ -53,7 +52,10 @@ protected IModel<List<FileUpload>> fileUploadModel() {
@Override
protected IResource newResource(final Clob clob) {
- return new CharSequenceResource(clob.mimeType().getBaseType(),
clob.chars(), clob.name());
+ var blob = clob.toBlobUtf8();
+ return new ByteArrayResource(blob.mimeType().getBaseType(),
blob.bytes(), blob.name());
+ //[CAUSEWAY-3958] has issues with CSV files
+ //return new CharSequenceResource(clob.mimeType().getBaseType(),
clob.chars(), clob.name());
}
}
diff --git
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/exec/LobRequestHandler.java
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/exec/LobRequestHandler.java
new file mode 100644
index 00000000000..4264a5bc45e
--- /dev/null
+++
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/exec/LobRequestHandler.java
@@ -0,0 +1,102 @@
+/*
+ * 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.causeway.viewer.wicket.ui.exec;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.time.Duration;
+
+import org.apache.wicket.request.IRequestCycle;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
+import org.apache.wicket.request.resource.ContentDisposition;
+import org.apache.wicket.util.resource.AbstractResourceStream;
+import org.apache.wicket.util.resource.IResourceStream;
+import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
+import org.jspecify.annotations.Nullable;
+
+import org.apache.causeway.applib.value.Blob;
+import org.apache.causeway.applib.value.Clob;
+import org.apache.causeway.applib.value.NamedWithMimeType;
+import org.apache.causeway.commons.internal.exceptions._Exceptions;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
+
+public record LobRequestHandler(
+ NamedWithMimeType lob,
+ /**
+ * Duration for which the resource will be cached by the browser.
+ * Set to Duration.ZERO to disable browser caching.
+ */
+ @Nullable Duration cacheDuration) implements IRequestHandler, Serializable
{
+
+ public static LobRequestHandler downloadHandler(
+ final ObjectAction action,
+ final Object value) {
+ if(value instanceof NamedWithMimeType lob) {
+ return new LobRequestHandler(lob,
action.getSemantics().isIdempotentOrCachable()
+ ? null
+ : Duration.ZERO);
+ }
+ return null;
+ }
+
+ @Override
+ public void respond(IRequestCycle requestCycle) {
+ var handler = new ResourceStreamRequestHandler(
+ lob instanceof Blob blob
+ ? resourceStream(blob)
+ : lob instanceof Clob clob
+ ? resourceStream(clob)
+ : resourceStreamUnmatched(),
+ lob.name());
+ handler.setContentDisposition(ContentDisposition.ATTACHMENT);
+ handler.setCacheDuration(cacheDuration);
+ handler.respond(requestCycle);
+ }
+
+ // -- HELPER
+
+ private IResourceStream resourceStream(Blob blob) {
+ final IResourceStream resourceStream = new AbstractResourceStream() {
+ private static final long serialVersionUID = 1L;
+ @Override public InputStream getInputStream() throws
ResourceStreamNotFoundException {
+ return new ByteArrayInputStream(blob.bytes());
+ }
+ @Override public String getContentType() {
+ return blob.mimeType().toString();
+ }
+ @Override public void close() throws IOException {
+ }
+ };
+ return resourceStream;
+ }
+
+ private IResourceStream resourceStream(Clob clob) {
+ return resourceStream(clob.toBlobUtf8());
+ // [CAUSEWAY-3958] has issues with CSV files
+ // return new StringResourceStream(clob.chars(),
clob.mimeType().toString());
+ }
+
+ private IResourceStream resourceStreamUnmatched() {
+ throw _Exceptions.unmatchedCase(lob);
+ }
+
+}