Skip to content

Commit

Permalink
ZK-5393: Update ZK jars to jakarta-friendly uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
rebecca0201 committed Dec 6, 2023
1 parent d022d16 commit f2f3014
Show file tree
Hide file tree
Showing 18 changed files with 154 additions and 51 deletions.
Binary file removed dist/lib/ext/commons-fileupload.jar
Binary file not shown.
Binary file added dist/lib/ext/commons-fileupload2-javax.jar
Binary file not shown.
Binary file modified dist/lib/ext/commons-io.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion release.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ task prepareBin() {
include "**/bsh.jar"
include "**/closure-compiler-unshaded.jar"
include "**/commons-collections4.jar"
include "**/commons-fileupload.jar"
include "**/commons-fileupload2-javax.jar"
include "**/commons-io.jar"
include "**/commons-logging.jar"
include "**/Filters.jar"
Expand Down
2 changes: 1 addition & 1 deletion zhtml/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ idea {

dependencies {
api project(':zul')
api 'commons-io:commons-io:2.8.0'
api 'commons-io:commons-io:2.13.0'
api 'org.zkoss:zsoup:1.8.2.5'
}

Expand Down
8 changes: 4 additions & 4 deletions zk-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5</version>
<groupId>org.apache.commons</groupId>
<artifactId>commons-fileupload2-javax</artifactId>
<version>2.0.0-M1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
Expand Down
4 changes: 2 additions & 2 deletions zk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ java {
dependencies {
api project(':zweb')
api project(':zkwebfragment')
api 'commons-fileupload:commons-fileupload:1.5'
api 'commons-io:commons-io:2.8.0'
api 'org.apache.commons:commons-fileupload2-javax:2.0.0-M1'
api 'commons-io:commons-io:2.13.0'
compileOnly "javax.servlet:servlet-api:${servletVersion}"
compileOnly "javax.portlet:portlet-api:${portletVersion}"
compileOnly 'javax.websocket:javax.websocket-api:1.1'
Expand Down
92 changes: 70 additions & 22 deletions zk/src/main/java/org/zkoss/zk/au/http/AuMultipartUploader.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -36,14 +38,15 @@
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload2.core.AbstractFileUpload;
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
import org.apache.commons.fileupload2.core.FileItem;
import org.apache.commons.fileupload2.core.FileUploadException;
import org.apache.commons.fileupload2.core.FileUploadSizeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -77,12 +80,57 @@
public class AuMultipartUploader {
private static final String FILE_DATA = AuMultipartUploader.class.getName() + ".FILE_DATA";
private static final Logger log = LoggerFactory.getLogger(AuMultipartUploader.class);
private static final String JAVAX_UPLOAD_CLASS = "org.apache.commons.fileupload2.javax.JavaxServletFileUpload";
private static final String JAKARTA_UPLOAD_CLASS = "org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload";
private static final String JAVAX_DISK_UPLOAD_CLASS = "org.apache.commons.fileupload2.javax.JavaxServletDiskFileUpload";
private static final String JAKARTA_DISK_UPLOAD_CLASS = "org.apache.commons.fileupload2.jakarta.JakartaServletDiskFileUpload";

private static Class<?> getServletFileUploadClass() {
try {
return Class.forName(JAVAX_UPLOAD_CLASS);
} catch (ClassNotFoundException ex0) {
try {
return Class.forName(JAKARTA_UPLOAD_CLASS);
} catch (ClassNotFoundException ex1) {
throw new RuntimeException("Failed to find " + JAVAX_UPLOAD_CLASS + " or " + JAKARTA_UPLOAD_CLASS);
}
}
}

public static boolean isMultipartContent(HttpServletRequest request) {
Class<?> clazz = getServletFileUploadClass();
try {
Method method = clazz.getMethod("isMultipartContent", HttpServletRequest.class);
return (boolean) method.invoke(null, request);
} catch (Exception ex) {
throw new RuntimeException("Failed to invoke " + clazz.getName() + "#isMultipartContent(HttpServletRequest)", ex);
}
}

private static AbstractFileUpload newServletDiskFileUpload(DiskFileItemFactory factory) {
Class<?> clazz;
try {
clazz = Class.forName(JAVAX_DISK_UPLOAD_CLASS);
} catch (ClassNotFoundException ex0) {
try {
clazz = Class.forName(JAKARTA_DISK_UPLOAD_CLASS);
} catch (ClassNotFoundException ex1) {
throw new RuntimeException("Failed to find " + JAVAX_DISK_UPLOAD_CLASS + " or " + JAKARTA_DISK_UPLOAD_CLASS);
}
}
try {
return (AbstractFileUpload) clazz.getDeclaredConstructor(DiskFileItemFactory.class).newInstance(factory);
} catch (Exception ex) {
throw new RuntimeException("Failed to create a new instance of " + clazz.getName(), ex);
}
}

public static AuDecoder parseRequest(HttpServletRequest request, AuDecoder decoder) {
Map<String, Object> params = getFileuploadMetaPerWebApp(
WebApps.getCurrent());
ServletFileUpload upload = new ServletFileUpload(
new DiskFileItemFactory((Integer) params.get("sizeThreadHold"),
(File) params.get("repository")));
AbstractFileUpload upload = newServletDiskFileUpload(new DiskFileItemFactory.Builder()
.setBufferSize((Integer) params.get("sizeThreadHold"))
.setPath(((File) params.get("repository")).toPath()).get());
try {
List<FileItem> fileItems = upload.parseRequest(request);
Map<String, Object> dataMap = new HashMap<>(fileItems.size());
Expand Down Expand Up @@ -176,15 +224,15 @@ private static Map<String, Object> getFileuploadMetaPerWebApp(WebApp webApp) {

params.put("sizeThreadHold", sizeThreadHold);

File repository = null;

if (conf.getFileRepository() != null) {
ServletContext context = webApp.getServletContext();
File repository = (File) context.getAttribute("javax.servlet.context.tempdir");
if (repository == null)
repository = (File) context.getAttribute("jakarta.servlet.context.tempdir");
if (conf.getFileRepository() != null)
repository = new File(conf.getFileRepository());
if (!repository.isDirectory()) {
log.warn("The file repository is not a directory! [" + repository + "]");
}
params.put("repository", repository);
}
if (!repository.isDirectory())
log.warn("The file repository is not a directory! [" + repository + "]");
params.put("repository", repository);

org.zkoss.zk.ui.sys.DiskFileItemFactory dfiFactory = null;
if (conf.getFileItemFactoryClass() != null) {
Expand Down Expand Up @@ -269,8 +317,8 @@ public List<AuRequest> decode(Object request, Desktop desktop) {
reconstructPacket(auRequest.getData(), _reqData, desktop, params);
Long fileSize = (Long) params.get("fileSize");
if (maxSizeLong >= 0 && fileSize > maxSizeLong) {
String errorMessage = uploadErrorMessage(new FileUploadBase.SizeLimitExceededException(null, fileSize, maxSizeLong));
throw new FileUploadBase.SizeLimitExceededException(errorMessage, fileSize, maxSizeLong);
String errorMessage = uploadErrorMessage(new FileUploadSizeException(null, fileSize, maxSizeLong));
throw new FileUploadSizeException(errorMessage, fileSize, maxSizeLong);
}
} catch (Exception e) {
throw UiException.Aide.wrap(e);
Expand All @@ -285,11 +333,11 @@ public boolean isIgnorable(Object request, WebApp wapp) {
}
private static String uploadErrorMessage(Throwable ex) {
log.error("Failed to upload", ex);
if (ex instanceof FileUploadBase.SizeLimitExceededException) {
if (ex instanceof FileUploadSizeException) {
try {
FileUploadBase.SizeLimitExceededException fex = (FileUploadBase.SizeLimitExceededException) ex;
FileUploadSizeException fex = (FileUploadSizeException) ex;
long size = fex.getActualSize();
long limit = fex.getPermittedSize();
long limit = fex.getPermitted();
final Class<?> msgClass = Classes.forNameByThread("org.zkoss.zul.mesg.MZul");
Field msgField = msgClass.getField("UPLOAD_ERROR_EXCEED_MAXSIZE");
int divisor1 = 1024;
Expand Down Expand Up @@ -529,7 +577,7 @@ private static final Media processItem(Desktop desktop, FileItem fi, boolean alw
if (charset == null)
charset = conf.getUploadCharset();
}
return fi.isInMemory() ? new AMedia(name, null, ctype, fi.getString(charset))
return fi.isInMemory() ? new AMedia(name, null, ctype, fi.getString(Charset.forName(charset)))
: new ReaderMedia(name, null, ctype, fi, charset);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -446,7 +445,7 @@ public void process(Session sess, HttpServletRequest request, HttpServletRespons
final WebApp wapp = sess.getWebApp();
final WebAppCtrl wappc = (WebAppCtrl) wapp;
AuDecoder audec = getAuDecoder(wapp);
boolean multipartContent = ServletFileUpload.isMultipartContent(request);
boolean multipartContent = AuMultipartUploader.isMultipartContent(request);
if (multipartContent) {
audec = AuMultipartUploader.parseRequest(request, audec);
}
Expand Down
18 changes: 6 additions & 12 deletions zk/src/main/java/org/zkoss/zk/au/http/ServletRequestContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.UploadContext;
import org.apache.commons.fileupload2.core.AbstractFileUpload;
import org.apache.commons.fileupload2.core.RequestContext;

/**
* An implementation of RequestContext, for commons-fileupload.
Expand All @@ -42,7 +42,7 @@
* @author rudyhuang
* @since 9.6.0
*/
class ServletRequestContext implements UploadContext {
class ServletRequestContext implements RequestContext {
private final HttpServletRequest _request;

public ServletRequestContext(HttpServletRequest request) {
Expand All @@ -60,16 +60,10 @@ public String getContentType() {
}

@Override
@Deprecated
public int getContentLength() {
return _request.getContentLength();
}

@Override
public long contentLength() {
public long getContentLength() {
long size;
try {
size = Long.parseLong(_request.getHeader(FileUploadBase.CONTENT_LENGTH));
size = Long.parseLong(_request.getHeader(AbstractFileUpload.CONTENT_LENGTH));
} catch (NumberFormatException e) {
size = _request.getContentLength();
}
Expand All @@ -84,7 +78,7 @@ public InputStream getInputStream() throws IOException {
@Override
public String toString() {
return String.format("ContentLength=%s, ContentType=%s",
this.contentLength(),
this.getContentLength(),
this.getContentType());
}
}
4 changes: 2 additions & 2 deletions zk/src/main/java/org/zkoss/zk/ui/sys/DiskFileItemFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import java.io.File;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload2.core.FileItem;

import org.zkoss.util.media.Media;

Expand All @@ -22,7 +22,7 @@
* Factories can provide their own custom configuration, over and above that provided
* by the default file upload implementation.
* <br/>
* Unlike {@link org.apache.commons.fileupload.FileItemFactory}, this factory
* Unlike {@link org.apache.commons.fileupload2.core.FileItemFactory}, this factory
* needs two extra information, sizeThreshold and repository.
* </p>
* @author jumperchen
Expand Down
2 changes: 2 additions & 0 deletions zkdoc/release-note
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ ZK 10.0.0
* Features

* Bugs
ZK-5393: Update ZK jars to jakarta-friendly uploads

* Upgrade Notes
+ Upgrade commons-fileupload to commons-fileupload2-javax 2.0.0-M1 and commons-io to 2.13.0 to support jakarta-friendly uploads

--------
ZK 10.0.0-Beta
Expand Down
4 changes: 2 additions & 2 deletions zksandbox/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ repositories {
}

dependencies {
implementation 'commons-io:commons-io:2.8.0'
implementation 'commons-io:commons-io:2.13.0'
implementation 'commons-logging:commons-logging:1.1.1'
implementation 'commons-fileupload:commons-fileupload:1.5'
implementation 'org.apache.commons:commons-fileupload2-javax:2.0.0-M1'
implementation "org.zkoss.theme:breeze:${version}"
implementation "org.zkoss.theme:sapphire:${version}"
implementation "org.zkoss.theme:silvertail:${version}"
Expand Down
4 changes: 2 additions & 2 deletions zktest/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ dependencies {
implementation "org.zkoss.theme:sapphire:${version}"
implementation "org.zkoss.theme:atlantic:${version}"
implementation 'commons-logging:commons-logging:1.1.1'
implementation 'commons-fileupload:commons-fileupload:1.5'
implementation 'commons-io:commons-io:2.8.0'
implementation 'org.apache.commons:commons-fileupload2-javax:2.0.0-M1'
implementation 'commons-io:commons-io:2.13.0'
implementation "org.zkoss.zk:zk:${version}"
implementation "org.zkoss.zk:zkplus:${version}"
implementation "org.zkoss.zk:zkplus-legacy:${version}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class PackageData {
// opened
new DirectoryTreeNode(new PackageDataUnit("/ext",null),
new DirectoryTreeNode[] {
new DirectoryTreeNode(new PackageDataUnit("commons-fileupload.jar", "Upload Features")),
new DirectoryTreeNode(new PackageDataUnit("commons-fileupload2-javax.jar", "Upload Features")),
new DirectoryTreeNode(new PackageDataUnit("commons-io.jar", "Upload Features")),
new DirectoryTreeNode(new PackageDataUnit("jcommon.jar", "Chart Component")),
new DirectoryTreeNode(new PackageDataUnit("jfreechar.jar", "Chart Component")),
Expand Down
27 changes: 27 additions & 0 deletions zktest/src/main/webapp/test2/B100-ZK-5393.zul
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
B100-ZK-5393.zul
Purpose:
Description:
History:
Fri Dec 01 17:18:04 CST 2023, Created by rebeccalai
Copyright (C) 2023 Potix Corporation. All Rights Reserved.
-->
<zk>
<label multiline="true">
1. Open developer tools to observe network.
2. Dropupload a file, should observe an XMLHttpRequest and see its file name in zk log.
</label>
<dropupload content="Dropupload a file" detection="none">
<attribute name="onUpload"><![CDATA[
import org.zkoss.util.media.Media;
for (Media media : event.getMedias()) {
Clients.log(media.getName());
}
]]></attribute>
</dropupload>
</zk>
1 change: 1 addition & 0 deletions zktest/src/main/webapp/test2/config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3161,6 +3161,7 @@ B90-ZK-4431.zul=A,E,Multislider
##zats##B100-ZK-5035.zul=A,E,Listbox,Column,AddChild,Checkmark
##zats##B100-ZK-5453.zul=A,E,Chosenbox,XSS
##zats##B100-ZK-5025.zul=A,E,Menu,Menupopup,Menuitem,focus,hover
##zats##B100-ZK-5393.zul=A,E,FileUpload,JakartaEE

##
# Features - 3.0.x version
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* B100_ZK_5393Test.java
Purpose:
Description:
History:
Fri Dec 01 17:33:57 CST 2023, Created by rebeccalai
Copyright (C) 2023 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.zktest.zats.test2;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.nio.file.Paths;

import org.junit.jupiter.api.Test;

import org.zkoss.test.webdriver.WebDriverTestCase;

public class B100_ZK_5393Test extends WebDriverTestCase {
@Test
public void test() throws Exception {
connect();
waitResponse();
dropUploadFile(jq("@dropupload"), Paths.get("src/main/webapp/test2/img/sun.jpg"));
waitResponse();
assertNoAnyError();
assertEquals("sun.jpg", getZKLog());
}
}

0 comments on commit f2f3014

Please sign in to comment.