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);
+    }
+
+}

Reply via email to