From 4364c63ce3652baa79fa39f0cc26e77810390fea Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sun, 2 Aug 2020 08:32:06 +1000 Subject: [PATCH 01/63] Allow developer to specify ECJ compiler options #1353 --- CHANGELOG.md | 3 +++ pom.xml | 2 +- src/main/java/act/app/AppCompiler.java | 1 + src/main/java/act/route/Router.java | 2 -- src/test/java/act/handler/builtin/StaticFileGetterTest.java | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3c57037f..525b5f2d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # ActFramework Change Log +**1.9.1** +* Allow developer to specify ECJ compiler options #1353 + **1.9.0a** 28/Jun/2020 * Add `@Inject` to CliDispatcher constructor - allow it be injected in - e.g. - HelpPage * The error triggered during rendering response get warned twice #1341 diff --git a/pom.xml b/pom.xml index 2837620c7..a47635949 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ org.actframework act jar - 1.9.1a-SNAPSHOT + 1.9.1-SNAPSHOT ACT Framework The ACT full stack MVC framework diff --git a/src/main/java/act/app/AppCompiler.java b/src/main/java/act/app/AppCompiler.java index e8a53dd9b..d610e3bfb 100644 --- a/src/main/java/act/app/AppCompiler.java +++ b/src/main/java/act/app/AppCompiler.java @@ -72,6 +72,7 @@ protected void releaseResources() { private void configureCompilerOptions() { Map map = new HashMap<>(); + map.putAll((Map)System.getProperties()); opt(map, OPTION_ReportMissingSerialVersion, IGNORE); opt(map, OPTION_LineNumberAttribute, GENERATE); opt(map, OPTION_SourceFileAttribute, GENERATE); diff --git a/src/main/java/act/route/Router.java b/src/main/java/act/route/Router.java index d78ad18c1..6e1795fd0 100644 --- a/src/main/java/act/route/Router.java +++ b/src/main/java/act/route/Router.java @@ -1018,7 +1018,6 @@ private Node(int id, AppConfig config) { this.id = keyword.hashCode(); this.root = parent.root; this.macroLookup = parent.macroLookup; - this.varNames.addAll(parent.varNames); } Node(String name, Node parent) { @@ -1027,7 +1026,6 @@ private Node(int id, AppConfig config) { this.id = name.hashCode(); this.root = parent.root; this.macroLookup = parent.macroLookup; - this.varNames.addAll(parent.varNames); parseDynaName(name); } diff --git a/src/test/java/act/handler/builtin/StaticFileGetterTest.java b/src/test/java/act/handler/builtin/StaticFileGetterTest.java index d69b0a515..a436d0683 100644 --- a/src/test/java/act/handler/builtin/StaticFileGetterTest.java +++ b/src/test/java/act/handler/builtin/StaticFileGetterTest.java @@ -61,13 +61,13 @@ public File answer(InvocationOnMock invocation) throws Throwable { when(req.method()).thenReturn(H.Method.GET); ctx = ActionContext.create(mockApp, req, resp); when(req.context()).thenReturn(ctx); + when(req.accept()).thenReturn(H.Format.HTML); pathHandler = new FileGetter("/public", mockApp); fileHandler = new FileGetter("/public/foo/bar.txt", mockApp); } @Test public void invokePathHandlerOnNonExistingResource() { - when(ctx.accept()).thenReturn(H.Format.HTML); ctx.param(ParamNames.PATH, "/some/where/non_exists.txt"); pathHandler.handle(ctx); eq(resp.status, 404); From afea18f88470d47ba414e3a65d58ef856f58dc8b Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sun, 2 Aug 2020 08:51:42 +1000 Subject: [PATCH 02/63] Support Java 14 Record #1354 --- CHANGELOG.md | 1 + src/main/java/act/util/SimpleBean.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 525b5f2d8..d028a543e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # ActFramework Change Log **1.9.1** +* Support Java 14 Record class #1354 * Allow developer to specify ECJ compiler options #1353 **1.9.0a** 28/Jun/2020 diff --git a/src/main/java/act/util/SimpleBean.java b/src/main/java/act/util/SimpleBean.java index 0beda8944..01aceb3ef 100644 --- a/src/main/java/act/util/SimpleBean.java +++ b/src/main/java/act/util/SimpleBean.java @@ -35,6 +35,7 @@ import org.osgl.util.E; import org.osgl.util.S; +import java.lang.reflect.Modifier; import java.util.*; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @@ -190,6 +191,9 @@ public void scanFinished(String className) { private static class SimpleBeanByteCodeVisitor extends ByteCodeVisitor { + private static final String RECORD = "java/lang/Record"; + private static final String SIMPLE_BEAN = "act/util/SimpleBean"; + private static final String ALIAS_DESC = Type.getType(Alias.class).getDescriptor(); private static final String LABEL_DESC = Type.getType(Label.class).getDescriptor(); private String className; @@ -198,18 +202,24 @@ private static class SimpleBeanByteCodeVisitor extends ByteCodeVisitor { private Map> publicFields = new LinkedHashMap<>(); private Map aliases = new LinkedHashMap<>(); private Map labels = new LinkedHashMap<>(); + private boolean isRecord; @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { if (isPublic(access)) { isPublicClass = true; className = Type.getObjectType(name).getClassName(); + isRecord = RECORD.equals(superName); + if (isRecord) { + interfaces = new String[] {SIMPLE_BEAN}; + } } super.visit(version, access, name, signature, superName, interfaces); } @Override public FieldVisitor visitField(int access, final String name, String desc, String signature, Object value) { + if (isRecord) access = Modifier.PUBLIC; FieldVisitor fv = super.visitField(access, name, desc, signature, value); if (isPublicClass && AsmTypes.isPublic(access) && !AsmTypes.isStatic(access)) { publicFields.put(name, $.T2(desc, signature)); From c4197a3363c8aa9950283bebfc057d2f63ff04cf Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Wed, 12 Aug 2020 12:39:38 +1000 Subject: [PATCH 03/63] WIP --- .../builtin/controller/impl/ReflectedHandlerInvoker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/act/handler/builtin/controller/impl/ReflectedHandlerInvoker.java b/src/main/java/act/handler/builtin/controller/impl/ReflectedHandlerInvoker.java index 4dd3a5d61..da8698d6d 100644 --- a/src/main/java/act/handler/builtin/controller/impl/ReflectedHandlerInvoker.java +++ b/src/main/java/act/handler/builtin/controller/impl/ReflectedHandlerInvoker.java @@ -1167,7 +1167,7 @@ private static Result transform(Object retVal, ReflectedHandlerInvoker invoker, invoker.checkTemplate(context); return result; } - HandlerMethodMetaInfo handlerMetaInfo = invoker.handler; + final HandlerMethodMetaInfo handlerMetaInfo = invoker.handler; final boolean hasReturn = handlerMetaInfo.hasReturn() && !handlerMetaInfo.returnTypeInfo().isResult(); if (null == retVal && hasReturn) { // ActFramework respond 404 Not Found when From dfe230ec803a2af85dcc352a1382c87acec07ff7 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Tue, 18 Aug 2020 19:42:45 +1000 Subject: [PATCH 04/63] * 500 Error but not error stack in console log #1358 --- CHANGELOG.md | 1 + .../java/act/handler/builtin/controller/RequestHandlerProxy.java | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d028a543e..dabec040a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # ActFramework Change Log **1.9.1** +* 500 Error but not error stack in console log #1358 * Support Java 14 Record class #1354 * Allow developer to specify ECJ compiler options #1353 diff --git a/src/main/java/act/handler/builtin/controller/RequestHandlerProxy.java b/src/main/java/act/handler/builtin/controller/RequestHandlerProxy.java index 2bb76361e..8265505b3 100644 --- a/src/main/java/act/handler/builtin/controller/RequestHandlerProxy.java +++ b/src/main/java/act/handler/builtin/controller/RequestHandlerProxy.java @@ -254,6 +254,7 @@ public void handle(ActionContext context) { if (context.resp().isClosed()) { logger.error(e, "Error committing result"); } else { + logger.error(e, "Error handling request: " + context.req().url()); if (null == result) { if (e instanceof IllegalArgumentException) { String errorMsg = e.getLocalizedMessage(); From 72978fba847ab7850b41ca15ed70adf8417220b5 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Tue, 18 Aug 2020 20:58:35 +1000 Subject: [PATCH 05/63] fix ut issue --- src/test/java/act/handler/builtin/StaticFileGetterTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/act/handler/builtin/StaticFileGetterTest.java b/src/test/java/act/handler/builtin/StaticFileGetterTest.java index a436d0683..493456ad5 100644 --- a/src/test/java/act/handler/builtin/StaticFileGetterTest.java +++ b/src/test/java/act/handler/builtin/StaticFileGetterTest.java @@ -39,6 +39,7 @@ import static org.mockito.Mockito.when; public class StaticFileGetterTest extends ActTestBase { + RequestImplBase req; ActionContext ctx; MockResponse resp; FileGetter pathHandler; @@ -57,13 +58,14 @@ public File answer(InvocationOnMock invocation) throws Throwable { } }); when(mockAppConfig.errorTemplatePathResolver()).thenCallRealMethod(); - RequestImplBase req = mock(RequestImplBase.class); + req = mock(RequestImplBase.class); when(req.method()).thenReturn(H.Method.GET); ctx = ActionContext.create(mockApp, req, resp); when(req.context()).thenReturn(ctx); when(req.accept()).thenReturn(H.Format.HTML); pathHandler = new FileGetter("/public", mockApp); fileHandler = new FileGetter("/public/foo/bar.txt", mockApp); + ctx.saveLocal(); } @Test From afc4ff34ff76a0825128cf4f9f91df8cb10f35b6 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Tue, 18 Aug 2020 21:11:00 +1000 Subject: [PATCH 06/63] update fastjson to 1.2.73 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a47635949..f02094132 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 1.2 1.3.3 3.22.0 - 1.2.71 + 1.2.73 1.1.2 0.7 1.18 From 25409d1b324e201efe81264803632bbaf9aed0fe Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Thu, 20 Aug 2020 08:55:04 +1000 Subject: [PATCH 07/63] new fix for GH-1341 without causing GH-1358 --- src/main/java/act/view/ActErrorResult.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/act/view/ActErrorResult.java b/src/main/java/act/view/ActErrorResult.java index a935cd1e9..8cc87770a 100644 --- a/src/main/java/act/view/ActErrorResult.java +++ b/src/main/java/act/view/ActErrorResult.java @@ -163,14 +163,12 @@ protected void populateSourceInfo(AsmContext context) { $.Function unsupported = new $.Transformer() { @Override public Result transform(Throwable throwable) { - Act.LOGGER.warn(throwable, "Error:"); return ActNotImplemented.create(throwable); } }; x.put(ToBeImplemented.class, new $.Transformer() { @Override public Result transform(Throwable throwable) { - Act.LOGGER.warn(throwable, "Error:"); return ActToBeImplemented.create(); } }); @@ -179,28 +177,24 @@ public Result transform(Throwable throwable) { x.put(IllegalStateException.class, new $.Transformer() { @Override public Result transform(Throwable throwable) { - Act.LOGGER.warn(throwable, "Error:"); return ActConflict.create(throwable); } }); x.put(ResourceNotFoundException.class, new $.Transformer() { @Override public Result transform(Throwable throwable) { - Act.LOGGER.warn(throwable, "Error:"); return ActNotFound.create(throwable); } }); x.put(AccessDeniedException.class, new $.Transformer() { @Override public Result transform(Throwable throwable) { - Act.LOGGER.warn(throwable, "Error:"); return ActForbidden.create(throwable); } }); $.Transformer badRequest = new $.Transformer() { @Override public Result transform(Throwable throwable) { - Act.LOGGER.warn(throwable, "Error:"); return ActBadRequest.create(throwable); } }; From c232906f61328aa24f195dfa38c15bd263e29f4e Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Thu, 20 Aug 2020 10:17:40 +1000 Subject: [PATCH 08/63] Error encountered requesting `/asset/extjs-all.js` #1359 --- CHANGELOG.md | 1 + pom.xml | 2 +- .../act/handler/builtin/ResourceGetter.java | 3 ++- src/main/java/act/util/StringUtils.java | 27 ++++++++++++++++--- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dabec040a..fd25ada1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # ActFramework Change Log **1.9.1** +* Error encountered requesting `/asset/extjs-all.js` #1359 * 500 Error but not error stack in console log #1358 * Support Java 14 Record class #1354 * Allow developer to specify ECJ compiler options #1353 diff --git a/pom.xml b/pom.xml index f02094132..87c998ad0 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 4.7.2 - 1.25.0 + 1.25.2 1.8.1 1.13.2 1.13.2 diff --git a/src/main/java/act/handler/builtin/ResourceGetter.java b/src/main/java/act/handler/builtin/ResourceGetter.java index 635c3c768..5ada53687 100644 --- a/src/main/java/act/handler/builtin/ResourceGetter.java +++ b/src/main/java/act/handler/builtin/ResourceGetter.java @@ -33,6 +33,7 @@ import act.handler.RequestHandler; import act.handler.builtin.controller.FastRequestHandler; import act.util.$$; +import act.util.StringUtils; import org.osgl.$; import org.osgl.http.H; import org.osgl.mvc.result.NotFound; @@ -273,7 +274,7 @@ protected void handle(String path, ActionContext context) { resp.send(file); } else { String content = IO.readContentAsString(file); - content = $$.processStringSubstitution(content); + content = StringUtils.processStringSubstitution(content, true); resp.writeContent(content); } } else if (largeResource.contains(path)) { diff --git a/src/main/java/act/util/StringUtils.java b/src/main/java/act/util/StringUtils.java index dbfd6c34b..29b3bd64f 100644 --- a/src/main/java/act/util/StringUtils.java +++ b/src/main/java/act/util/StringUtils.java @@ -32,7 +32,7 @@ import java.util.List; import java.util.Map; -class StringUtils { +public class StringUtils { static $.Transformer evaluator = new $.Transformer() { @Override @@ -44,10 +44,18 @@ public String transform(String s) { public static String processStringSubstitution(String s) { - return processStringSubstitution(s, evaluator); + return processStringSubstitution(s, evaluator, false); + } + + public static String processStringSubstitution(String s, boolean ignoreError) { + return processStringSubstitution(s, evaluator, ignoreError); } public static String processStringSubstitution(String s, $.Func1 evaluator) { + return processStringSubstitution(s, evaluator, false); + } + + public static String processStringSubstitution(String s, $.Func1 evaluator, boolean ignoreError) { if (S.blank(s)) { return ""; } @@ -59,11 +67,22 @@ public static String processStringSubstitution(String s, $.Func1 int z = n; StringBuilder buf = S.builder(); while (true) { - buf.append(s.substring(a, z)); + buf.append(s, a, z); n = s.indexOf("}", z); a = n + 1; String key = s.substring(z + 2, a - 1); - buf.append(evaluator.apply(key)); + if (S.notEmpty(key)) { + String val = key; + try { + val = evaluator.apply(key); + } catch (RuntimeException e) { + if (!ignoreError) throw e; + buf.append("${").append(key).append("}"); + } + buf.append(val); + } else { + buf.append("${}"); + } n = s.indexOf("${", a); if (n < 0) { buf.append(s.substring(a)); From aef8dd7af992bed676b53b2cee8bc67078ba47a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Oct 2020 10:38:04 +0000 Subject: [PATCH 09/63] Bump junit from 4.11 to 4.13.1 in /legacy-testapp Bumps [junit](https://github.com/junit-team/junit4) from 4.11 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.11.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.11...r4.13.1) Signed-off-by: dependabot[bot] --- legacy-testapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy-testapp/pom.xml b/legacy-testapp/pom.xml index d601c3a99..734c858ba 100644 --- a/legacy-testapp/pom.xml +++ b/legacy-testapp/pom.xml @@ -178,7 +178,7 @@ junit junit - 4.11 + 4.13.1 test From 0587872719eac44edbc85da0840e05575394611e Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sat, 7 Nov 2020 21:46:15 +1100 Subject: [PATCH 10/63] ApacheMultipartParser NullPointerException #1369 --- CHANGELOG.md | 1 + .../java/act/data/ApacheMultipartParser.java | 6 ++++-- .../act/xio/undertow/UndertowNetwork.java | 3 ++- testapps/GHIssues/pom.xml | 6 +++--- .../src/main/java/ghissues/Gh1369.java | 20 +++++++++++++++++++ .../src/main/resources/rythm/1369.html | 20 +++++++++++++++++++ 6 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 testapps/GHIssues/src/main/java/ghissues/Gh1369.java create mode 100644 testapps/GHIssues/src/main/resources/rythm/1369.html diff --git a/CHANGELOG.md b/CHANGELOG.md index fd25ada1a..629a847ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # ActFramework Change Log **1.9.1** +* ApacheMultipartParser NullPointerException #1369 * Error encountered requesting `/asset/extjs-all.js` #1359 * 500 Error but not error stack in console log #1358 * Support Java 14 Record class #1354 diff --git a/src/main/java/act/data/ApacheMultipartParser.java b/src/main/java/act/data/ApacheMultipartParser.java index c1e0b0293..e320d0973 100644 --- a/src/main/java/act/data/ApacheMultipartParser.java +++ b/src/main/java/act/data/ApacheMultipartParser.java @@ -29,6 +29,7 @@ import org.osgl.http.H; import org.osgl.storage.ISObject; import org.osgl.util.E; +import org.osgl.util.IO; import java.io.IOException; import java.io.InputStream; @@ -54,7 +55,6 @@ public Map parse(ActionContext context) { FileItemIteratorImpl iter = new FileItemIteratorImpl(body, request.header("content-type"), request.characterEncoding()); while (iter.hasNext()) { FileItemStream item = iter.next(); - ISObject sobj = UploadFileStorageService.store(item, context.app()); String fieldName = item.getFieldName(); if (item.isFormField()) { // must resolve encoding @@ -66,8 +66,10 @@ public Map parse(ActionContext context) { _encoding = contentTypeEncoding.encoding; } } - mergeValueInMap(result, fieldName, sobj.asString(Charset.forName(_encoding))); + String val = IO.read(item.openStream()).encoding(Charset.forName(_encoding)).toString(); + mergeValueInMap(result, fieldName, val); } else { + ISObject sobj = UploadFileStorageService.store(item, context.app()); context.addUpload(item.getFieldName(), sobj); mergeValueInMap(result, fieldName, fieldName); } diff --git a/src/main/java/act/xio/undertow/UndertowNetwork.java b/src/main/java/act/xio/undertow/UndertowNetwork.java index 7b6370e74..0cfcfde3f 100644 --- a/src/main/java/act/xio/undertow/UndertowNetwork.java +++ b/src/main/java/act/xio/undertow/UndertowNetwork.java @@ -146,7 +146,8 @@ private XnioWorker createWorker() throws IOException { .set(Options.CONNECTION_LOW_WATER, 1000000) .set(Options.TCP_NODELAY, true) .set(Options.CORK, true) - .getMap()); + .getMap() + ); } private OptionMap createSocketOptions() { diff --git a/testapps/GHIssues/pom.xml b/testapps/GHIssues/pom.xml index b89abe6a2..49175fd25 100644 --- a/testapps/GHIssues/pom.xml +++ b/testapps/GHIssues/pom.xml @@ -5,14 +5,14 @@ 4.0.0 act-ghissues - 1.9.0-SNAPSHOT + 1.9.1-SNAPSHOT ActFramework Github Issue Reproduce App org.actframework act-starter-parent - 1.8.33.0 + 1.9.0.1 @@ -30,7 +30,7 @@ org.actframework act - 1.9.0-SNAPSHOT + 1.9.1-SNAPSHOT org.actframework diff --git a/testapps/GHIssues/src/main/java/ghissues/Gh1369.java b/testapps/GHIssues/src/main/java/ghissues/Gh1369.java new file mode 100644 index 000000000..2fe542ab6 --- /dev/null +++ b/testapps/GHIssues/src/main/java/ghissues/Gh1369.java @@ -0,0 +1,20 @@ +package ghissues; + +import act.controller.Controller; +import org.osgl.mvc.annotation.GetAction; +import org.osgl.mvc.annotation.PostAction; +import org.osgl.storage.impl.SObject; + +public class Gh1369 extends BaseController { + + @GetAction("1369") + public void form() { + Controller.Util.renderTemplate("/1369.html"); + } + + @PostAction("1369") + public String test(SObject file, String name) { + return name + ": " + (null == file ? "null object" : file.asString()); + } + +} diff --git a/testapps/GHIssues/src/main/resources/rythm/1369.html b/testapps/GHIssues/src/main/resources/rythm/1369.html new file mode 100644 index 000000000..0380d19ad --- /dev/null +++ b/testapps/GHIssues/src/main/resources/rythm/1369.html @@ -0,0 +1,20 @@ + + + GH 1369 Test Form + + +
+
+ + +
+
+ + +
+
+ +
+
+ + \ No newline at end of file From dff0e1361f6ef89420277cfb96f534c6c0f1c7d3 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sun, 29 Nov 2020 14:41:58 +1100 Subject: [PATCH 11/63] EhCache raised `ClassCastException` after reload in dev mode #1368 --- CHANGELOG.md | 1 + src/main/java/act/app/App.java | 2 ++ src/main/java/act/cli/builtin/Help.java | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 629a847ac..1e9db9c88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # ActFramework Change Log **1.9.1** +* EhCache raised `ClassCastException` after reload in dev mode #1368 * ApacheMultipartParser NullPointerException #1369 * Error encountered requesting `/asset/extjs-all.js` #1359 * 500 Error but not error stack in console log #1358 diff --git a/src/main/java/act/app/App.java b/src/main/java/act/app/App.java index a401ae4c0..b2160f746 100644 --- a/src/main/java/act/app/App.java +++ b/src/main/java/act/app/App.java @@ -84,6 +84,7 @@ import org.osgl.$; import org.osgl.Lang; import org.osgl.cache.CacheService; +import org.osgl.cache.CacheServiceProvider; import org.osgl.http.HttpConfig; import org.osgl.logging.LogManager; import org.osgl.logging.Logger; @@ -1616,6 +1617,7 @@ private void initSessionManager() { private void initCache() { if (isDev()) { + CacheServiceProvider.Impl.setClassLoader(this.classLoader); config().cacheServiceProvider().reset(); } cache = cache(config().cacheName()); diff --git a/src/main/java/act/cli/builtin/Help.java b/src/main/java/act/cli/builtin/Help.java index 719a085f8..5164561d0 100644 --- a/src/main/java/act/cli/builtin/Help.java +++ b/src/main/java/act/cli/builtin/Help.java @@ -20,8 +20,6 @@ * #L% */ -import static org.osgl.$.T2; - import act.cli.CliCmdInfo; import act.cli.CliContext; import act.cli.CliDispatcher; @@ -39,6 +37,8 @@ import java.util.List; import java.util.SortedSet; +import static org.osgl.$.T2; + public class Help extends CliHandlerBase { public static final Help INSTANCE = new Help(); From 66169a510da297ecc45d2ab3fb8448ed16ddbb4c Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sun, 27 Dec 2020 20:10:08 +1100 Subject: [PATCH 12/63] bulk updates towards 1.9.1 --- .gitignore | 1 + CHANGELOG.md | 9 +- pom.xml | 4 +- src/main/java/act/app/ActionContext.java | 1 + src/main/java/act/app/App.java | 3 + .../java/act/app/AppInterceptorManager.java | 8 +- src/main/java/act/app/CliServer.java | 4 + src/main/java/act/conf/AppConfig.java | 79 +- .../act/data/ContentTypeWithEncoding.java | 2 +- src/main/java/act/i18n/I18n.java | 1 + .../act/inject/param/CollectionLoader.java | 25 +- src/main/java/act/test/RequestBuilder.java | 84 +- src/main/java/act/test/TestSession.java | 33 +- .../act/xio/undertow/UndertowNetwork.java | 7 + testapps/GH1364/.gitignore | 19 + testapps/GH1364/pom.xml | 33 + testapps/GH1364/run_dev | 3 + testapps/GH1364/run_dev.bat | 2 + testapps/GH1364/run_e2e | 3 + testapps/GH1364/run_e2e.bat | 2 + testapps/GH1364/run_prod | 10 + .../GH1364/src/main/java/test/AppEntry.java | 24 + .../src/main/resources/conf/app.properties | 801 ++++++++++++++++++ .../main/resources/conf/prod/app.properties | 5 + .../main/resources/conf/uat/app.properties | 5 + .../GH1364/src/main/resources/logback.xml | 115 +++ .../src/main/resources/messages.properties | 1 + .../src/test/resources/scenarios/test.yml | 11 + testapps/GHIssues/pom.xml | 10 +- .../src/main/java/ghissues/Gh1352.java | 23 + .../src/main/java/ghissues/Gh1361.java | 26 + .../GHIssues/src/main/resources/1361.json | 44 + .../src/test/resources/scenarios/1352.yml | 17 + .../src/test/resources/scenarios/1361.yml | 11 + .../src/test/resources/upload/test.txt | 1 + 35 files changed, 1364 insertions(+), 63 deletions(-) create mode 100644 testapps/GH1364/.gitignore create mode 100644 testapps/GH1364/pom.xml create mode 100755 testapps/GH1364/run_dev create mode 100755 testapps/GH1364/run_dev.bat create mode 100755 testapps/GH1364/run_e2e create mode 100755 testapps/GH1364/run_e2e.bat create mode 100755 testapps/GH1364/run_prod create mode 100644 testapps/GH1364/src/main/java/test/AppEntry.java create mode 100644 testapps/GH1364/src/main/resources/conf/app.properties create mode 100644 testapps/GH1364/src/main/resources/conf/prod/app.properties create mode 100644 testapps/GH1364/src/main/resources/conf/uat/app.properties create mode 100644 testapps/GH1364/src/main/resources/logback.xml create mode 100644 testapps/GH1364/src/main/resources/messages.properties create mode 100644 testapps/GH1364/src/test/resources/scenarios/test.yml create mode 100644 testapps/GHIssues/src/main/java/ghissues/Gh1352.java create mode 100644 testapps/GHIssues/src/main/java/ghissues/Gh1361.java create mode 100644 testapps/GHIssues/src/main/resources/1361.json create mode 100644 testapps/GHIssues/src/test/resources/scenarios/1352.yml create mode 100644 testapps/GHIssues/src/test/resources/scenarios/1361.yml create mode 100644 testapps/GHIssues/src/test/resources/upload/test.txt diff --git a/.gitignore b/.gitignore index 2899decbc..cc2d857cf 100755 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ deploy **/.act* git.log +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9db9c88..36270e211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,17 @@ # ActFramework Change Log **1.9.1** -* EhCache raised `ClassCastException` after reload in dev mode #1368 +* It reports `UNKNOWN` for OS when running act on macOS #1373 +* Hot reload not working for Bundle Resource properties #1372 +* Cannot start ActFramework: port xxxxx is occupied #1370 * ApacheMultipartParser NullPointerException #1369 +* EhCache raised `ClassCastException` after reload in dev mode #1368 +* act-test: number verification logic error #1361 * Error encountered requesting `/asset/extjs-all.js` #1359 * 500 Error but not error stack in console log #1358 * Support Java 14 Record class #1354 -* Allow developer to specify ECJ compiler options #1353 +* Allow the developers to specify ECJ compiler options #1353 +* `null` file object inject from form field into the request handler argument list #1352 **1.9.0a** 28/Jun/2020 * Add `@Inject` to CliDispatcher constructor - allow it be injected in - e.g. - HelpPage diff --git a/pom.xml b/pom.xml index 87c998ad0..e21a9ebd9 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 4.7.2 - 1.25.2 + 1.26.1-SNAPSHOT 1.8.1 1.13.2 1.13.2 @@ -77,7 +77,7 @@ 1.5.1 0.0.1 1.11.9 - 1.3.0 + 1.3.1-SNAPSHOT 1.1.0.Final 2.1.3.Final 1.26 diff --git a/src/main/java/act/app/ActionContext.java b/src/main/java/act/app/ActionContext.java index 0d7f7e031..ec70c4137 100644 --- a/src/main/java/act/app/ActionContext.java +++ b/src/main/java/act/app/ActionContext.java @@ -73,6 +73,7 @@ public class ActionContext extends ActContext.Base implements Des private static final Logger LOGGER = LogManager.get(ActionContext.class); public static final String ATTR_EXCEPTION = "__exception__"; + // used along with CollectionLoader to load multi-file uploads public static final String ATTR_CURRENT_FILE_INDEX = "__file_id__"; public static final String REQ_BODY = "_body"; diff --git a/src/main/java/act/app/App.java b/src/main/java/act/app/App.java index b2160f746..856e67332 100644 --- a/src/main/java/act/app/App.java +++ b/src/main/java/act/app/App.java @@ -667,10 +667,13 @@ protected void releaseResources() { listener.preHotReload(); } if (null != classLoader && config().i18nEnabled()) { + debug("clearing resource bundle with classLoader: %s", classLoader); + ResourceBundle.clearCache(App.class.getClassLoader()); // clear resource bundle cache for Act I18n ResourceBundle.clearCache(classLoader); // clear resource bundle cache for Rythm I18n ResourceBundle.clearCache(I18N.class.getClassLoader()); + I18N.clearBundleCache(); } } diff --git a/src/main/java/act/app/AppInterceptorManager.java b/src/main/java/act/app/AppInterceptorManager.java index da72bbad2..f1325d40c 100644 --- a/src/main/java/act/app/AppInterceptorManager.java +++ b/src/main/java/act/app/AppInterceptorManager.java @@ -40,10 +40,10 @@ * Manage interceptors at App level */ public class AppInterceptorManager extends AppServiceBase { - private List beforeInterceptors = new ArrayList<>(); - private List afterInterceptors = new ArrayList<>(); - private List exceptionInterceptors = new ArrayList<>(); - private List finallyInterceptors = new ArrayList<>(); + private final List beforeInterceptors = new ArrayList<>(); + private final List afterInterceptors = new ArrayList<>(); + private final List exceptionInterceptors = new ArrayList<>(); + private final List finallyInterceptors = new ArrayList<>(); final GroupInterceptorWithResult BEFORE_INTERCEPTOR = new GroupInterceptorWithResult(beforeInterceptors); final GroupAfterInterceptor AFTER_INTERCEPTOR = new GroupAfterInterceptor(afterInterceptors); diff --git a/src/main/java/act/app/CliServer.java b/src/main/java/act/app/CliServer.java index 9fe740147..b6af40b74 100644 --- a/src/main/java/act/app/CliServer.java +++ b/src/main/java/act/app/CliServer.java @@ -23,6 +23,7 @@ import act.Act; import act.Destroyable; import act.cli.CliSession; +import act.conf.AppConfig; import act.exception.PortOccupiedException; import org.osgl.exception.ConfigurationException; import org.osgl.exception.UnexpectedException; @@ -127,6 +128,9 @@ void start() { return; } try { + if (Act.isTest()) { + AppConfig.clearRandomServerSocket(port); + } serverSocket = new ServerSocket(port); running.set(true); // start server thread diff --git a/src/main/java/act/conf/AppConfig.java b/src/main/java/act/conf/AppConfig.java index 147a93a66..2fa060148 100644 --- a/src/main/java/act/conf/AppConfig.java +++ b/src/main/java/act/conf/AppConfig.java @@ -547,12 +547,14 @@ protected T confPrivateKey(String key) { this.confPrivateKey = key; return me(); } + private String confPrivateKey() { if (S.blank(confPrivateKey)) { confPrivateKey = get(CONF_PRIVATE_KEY, ""); } return confPrivateKey; } + private void _mergeConfPrivateId(AppConfig conf) { if (!hasConfiguration(CONF_PRIVATE_KEY)) { confPrivateKey = conf.confPrivateKey; @@ -629,7 +631,7 @@ protected T corsHeadersExpose(String s) { public String corsExposeHeaders() { if (null == corsHeadersExpose) { - corsHeadersExpose = get(CORS_HEADERS_EXPOSE,""); + corsHeadersExpose = get(CORS_HEADERS_EXPOSE, ""); if (S.blank(corsHeadersExpose)) { corsHeadersExpose = corsHeaders(); if (S.notBlank(corsHeadersExpose)) { @@ -1285,16 +1287,19 @@ private void _mergeXForwardedProtocol(AppConfig conf) { } private String xmlRootTag; + protected T xmlRootTag(String tag) { this.xmlRootTag = tag; return me(); } + public String xmlRootTag() { if (null == xmlRootTag) { xmlRootTag = get(XML_ROOT, "xml"); } return xmlRootTag; } + private void _mergeXmlRootTag(AppConfig conf) { if (!hasConfiguration(XML_ROOT)) { this.xmlRootTag = conf.xmlRootTag; @@ -1634,16 +1639,19 @@ private void _mergeLocaleCookieName(AppConfig conf) { } private Boolean mockServer; + protected T mockServer(boolean enabled) { mockServer = enabled; return me(); } + public boolean mockServer() { if (null == mockServer) { mockServer = get(MOCK_SERVER_ENABLED, app.isDev()); } return mockServer; } + private void _mergeMockServer(AppConfig config) { if (!hasConfiguration(MOCK_SERVER_ENABLED)) { mockServer = config.mockServer; @@ -1912,16 +1920,19 @@ private void _mergeJobPoolSize(AppConfig conf) { } private Boolean jsonBodyPatch; + protected T jsonBodyPatch(boolean enabled) { jsonBodyPatch = enabled; return me(); } + public boolean allowJsonBodyPatch() { if (null == jsonBodyPatch) { jsonBodyPatch = get(JSON_BODY_PATCH, true); } return jsonBodyPatch; } + private void _mergeJsonBodyPatch(AppConfig conf) { if (!hasConfiguration(JSON_BODY_PATCH)) { jsonBodyPatch = conf.jsonBodyPatch; @@ -2000,8 +2011,8 @@ protected T httpPort(int port) { public int httpPort() { if (-1 == httpPort) { - if ("test".equalsIgnoreCase(Act.profile())) { - httpPort = randomPort(); + if (Act.isTest()) { + httpPort = chooseRandomDefaultHttpPort(); } else { httpPort = get(HTTP_PORT, 5460); } @@ -2015,6 +2026,47 @@ private void _mergeHttpPort(AppConfig conf) { } } + private static void clearRandomServerSockets() { + for (ServerSocket ss : randomServerSockets.values()) { + IO.close(ss); + } + randomServerSockets.clear(); + } + + public static void clearRandomServerSocket(int port) { + ServerSocket ss = randomServerSockets.remove(port); + IO.close(ss); + } + + private static Map randomServerSockets = new HashMap<>(); + + private static int chooseRandomDefaultHttpPort() { + int maxTry = 10; + while (maxTry-- > 0) { + clearRandomServerSockets(); + boolean ok = true; + int httpPort = randomPort(); + Act.LOGGER.debug("Random port detected: " + httpPort); + for (int i = 1; i < 4; ++i) { + int port = httpPort + i; + ServerSocket ss = null; + try { + ss = new ServerSocket(port); + randomServerSockets.put(port, ss); + Act.LOGGER.debug("Successfully bind to port: " + port); + } catch (IOException e) { + ok = false; + break; + } + } + if (ok) { + Act.LOGGER.info("Default port allocated for testing: " + httpPort); + return httpPort; + } + } + throw new IllegalStateException("Unable to find random HTTP port"); + } + private static int randomPort() { ServerSocket ss = null; try { @@ -2590,16 +2642,19 @@ private void _mergeSourceVersion(AppConfig conf) { } private Boolean selfHealing; + protected T selfHealing(boolean on) { selfHealing = on; return me(); } + public boolean selfHealing() { if (null == selfHealing) { selfHealing = get(SYS_SELF_HEALING, false); } return selfHealing; } + private void _mergeSelfHealing(AppConfig conf) { if (!hasConfiguration(SYS_SELF_HEALING)) { selfHealing = conf.selfHealing; @@ -2654,7 +2709,7 @@ public boolean test(String s) { return false; } if (s.contains("$")) { - for (String pkg: scanList) { + for (String pkg : scanList) { if (s.startsWith(pkg + "$")) { return true; } @@ -2967,6 +3022,7 @@ private void _mergeRenderJsonOutputCharset(AppConfig config) { private String serverHeader; private static final String DEF_SERVER_HEADER = "act/" + Act.VERSION.getProjectVersion(); private static String DEF_APP_SERVER_HEADER = appServerHeader(); + private static String appServerHeader() { App app = Act.app(); if (null == app) { @@ -2999,16 +3055,19 @@ private void _mergeServerHeader(AppConfig config) { } private Boolean serverHeaderUseApp; + protected T serverHeaderUseApp(boolean b) { serverHeaderUseApp = b; return me(); } + private boolean serverHeaderUseApp() { if (null == serverHeaderUseApp) { serverHeaderUseApp = get(AppConfigKey.SERVER_HEADER_USE_APP, true); } return serverHeaderUseApp; } + private void _mergeServerHeaderUseApp(AppConfig config) { if (!hasConfiguration(SERVER_HEADER_USE_APP)) { serverHeaderUseApp = config.serverHeaderUseApp; @@ -3135,16 +3194,19 @@ private void _mergeSessionTtl(AppConfig conf) { private boolean sessionPassThrough; private boolean sessionPassThroughSet; // use this to save auto-box of sessionPassThrough flag + protected T sessionPassThrough(boolean b) { sessionPassThrough = b; return me(); } + public boolean sessionPassThrough() { if (!sessionPassThroughSet) { sessionPassThrough = get(SESSION_PASS_THROUGH, false); } return sessionPassThrough; } + private void _mergeSessionPassThrough(AppConfig config) { if (!hasConfiguration(SESSION_PASS_THROUGH)) { sessionPassThrough = config.sessionPassThrough; @@ -3310,16 +3372,19 @@ private void _mergeSessionHeaderPayloadPrefix(AppConfig config) { } private String sessionQueryParamName; + protected T sessionQueryParamName(String paramName) { sessionQueryParamName = paramName; return me(); } + public String getSessionQueryParamName() { if (null == sessionQueryParamName) { sessionQueryParamName = get(SESSION_QUERY_PARAM_NAME, sessionHeader()); } return sessionQueryParamName; } + private void _mergeSessionQueryParamName(AppConfig config) { if (!hasConfiguration(SESSION_QUERY_PARAM_NAME)) { sessionQueryParamName = config.sessionQueryParamName; @@ -3395,8 +3460,7 @@ private void _mergeSecretRotate(AppConfig config) { /** * Set `secret.rotate.period` in terms of minute * - * @param period - * the minutes between two secret rotate happening + * @param period the minutes between two secret rotate happening * @return this config object * @see AppConfigKey#SECRET_ROTATE_PERIOD */ @@ -3892,8 +3956,7 @@ private void loadJarProperties(Properties p) { * settings has lower priority as it's hardcoded thus only when configuration file * does not provided the settings, the app configurator will take effect * - * @param conf - * the application configurator + * @param conf the application configurator */ public void _merge(AppConfigurator conf) { app.emit(SysEventId.CONFIG_PREMERGE); diff --git a/src/main/java/act/data/ContentTypeWithEncoding.java b/src/main/java/act/data/ContentTypeWithEncoding.java index b8e4a905f..520a89a0c 100644 --- a/src/main/java/act/data/ContentTypeWithEncoding.java +++ b/src/main/java/act/data/ContentTypeWithEncoding.java @@ -33,7 +33,7 @@ public ContentTypeWithEncoding(String contentType, String encoding) { public static ContentTypeWithEncoding parse(String contentType) { if( contentType == null ) { - return new ContentTypeWithEncoding("text/html".intern(), null); + return new ContentTypeWithEncoding("text/html", null); } else { String[] contentTypeParts = contentType.split(";"); String _contentType = contentTypeParts[0].trim().toLowerCase(); diff --git a/src/main/java/act/i18n/I18n.java b/src/main/java/act/i18n/I18n.java index 0377ffa34..45301dcb2 100644 --- a/src/main/java/act/i18n/I18n.java +++ b/src/main/java/act/i18n/I18n.java @@ -98,6 +98,7 @@ private static String _i18n(boolean ignoreError, Locale locale, String bundleNam if (null != app && null != app.classLoader()) { classLoader = app.classLoader(); } + logger.debug("loading resource bundle[%s] with classLoader[%s]", bundleName, classLoader); bundle = ResourceBundle.getBundle(bundleName, $.requireNotNull(locale), classLoader); } catch (MissingResourceException e) { if (!ignoreError) { diff --git a/src/main/java/act/inject/param/CollectionLoader.java b/src/main/java/act/inject/param/CollectionLoader.java index ed37ad274..6f3c0e0c5 100644 --- a/src/main/java/act/inject/param/CollectionLoader.java +++ b/src/main/java/act/inject/param/CollectionLoader.java @@ -97,20 +97,19 @@ public Object load(Object bean, ActContext context, boolean noDefaultValue) { List nodes = node.list(); if (nodes.size() > 0) { String value = nodes.get(0).value(); - //if (S.notBlank(value)) { - for (int i = 0; i < nodes.size(); ++i) { - ParamTreeNode elementNode = nodes.get(i); - if (!elementNode.isLeaf()) { - throw new BadRequest("cannot parse param: expect leaf node, found: \n%s", node.debug()); - } - context.attribute(ActionContext.ATTR_CURRENT_FILE_INDEX, i); - if (null != binder) { - collection.add(binder.resolve(null, elementNode.value(), context)); - } else { - collection.add(resolver.resolve(elementNode.value())); - } + for (int i = 0; i < nodes.size(); ++i) { + ParamTreeNode elementNode = nodes.get(i); + if (!elementNode.isLeaf()) { + throw new BadRequest("cannot parse param: expect leaf node, found: \n%s", node.debug()); + } + context.attribute(ActionContext.ATTR_CURRENT_FILE_INDEX, i); + if (null != binder) { + collection.add(binder.resolve(null, elementNode.value(), context)); + } else { + collection.add(resolver.resolve(elementNode.value())); } - //} + } + context.removeAttribute(ActionContext.ATTR_CURRENT_FILE_INDEX); } } else if (node.isMap()) { Set childrenKeys = node.mapKeys(); diff --git a/src/main/java/act/test/RequestBuilder.java b/src/main/java/act/test/RequestBuilder.java index efb053488..3cdcf3bf0 100644 --- a/src/main/java/act/test/RequestBuilder.java +++ b/src/main/java/act/test/RequestBuilder.java @@ -155,32 +155,66 @@ class RequestBuilder { MultipartBody.Builder formBuilder = new MultipartBody.Builder(); for (Map.Entry entry : requestSpec.parts.entrySet()) { String key = entry.getKey(); - String val = S.string(entry.getValue()); - byte[] content = null; - H.Format fileFormat = null; - String path = S.pathConcat("upload", '/', val); - File uploadFile = Act.app().testResource(path); - if (uploadFile.exists()) { - fileFormat = FileGetter.contentType(path); - content = IO.readContent(uploadFile); - } else { - path = S.pathConcat("test/upload", '/', val); - URL fileUrl = Act.getResource(path); - if (null != fileUrl) { - String filePath = fileUrl.getFile(); - fileFormat = FileGetter.contentType(filePath); - content = $.convert(fileUrl).to(byte[].class); + Object obj = entry.getValue(); + if (obj instanceof String) { + String val = S.string(entry.getValue()); + byte[] content = null; + H.Format fileFormat = null; + String path = S.pathConcat("upload", '/', val); + File uploadFile = Act.app().testResource(path); + if (uploadFile.exists()) { + fileFormat = FileGetter.contentType(path); + content = IO.readContent(uploadFile); + } else { + path = S.pathConcat("test/upload", '/', val); + URL fileUrl = Act.getResource(path); + if (null != fileUrl) { + String filePath = fileUrl.getFile(); + fileFormat = FileGetter.contentType(filePath); + content = $.convert(fileUrl).to(byte[].class); + } + } + if (null != content) { + String checksum = IO.checksum(content); + RequestBody fileBody = RequestBody.create(MediaType.parse(fileFormat.contentType()), content); + String attachmentName = val.contains("/") ? S.cut(val).afterLast("/") : val; + formBuilder.addFormDataPart(key, attachmentName, fileBody); + session.cache("checksum-last", checksum); + session.cache("checksum-" + val, checksum); + } else { + formBuilder.addFormDataPart(key, val); + } + } else if (obj instanceof Collection) { + Collection col = (Collection) obj; + for (Object element : col) { + String val = S.string(element); + byte[] content = null; + H.Format fileFormat = null; + String path = S.pathConcat("upload", '/', val); + File uploadFile = Act.app().testResource(path); + if (uploadFile.exists()) { + fileFormat = FileGetter.contentType(path); + content = IO.readContent(uploadFile); + } else { + path = S.pathConcat("test/upload", '/', val); + URL fileUrl = Act.getResource(path); + if (null != fileUrl) { + String filePath = fileUrl.getFile(); + fileFormat = FileGetter.contentType(filePath); + content = $.convert(fileUrl).to(byte[].class); + } + } + if (null != content) { + String checksum = IO.checksum(content); + RequestBody fileBody = RequestBody.create(MediaType.parse(fileFormat.contentType()), content); + String attachmentName = val.contains("/") ? S.cut(val).afterLast("/") : val; + formBuilder.addFormDataPart(key, attachmentName, fileBody); + session.cache("checksum-last", checksum); + session.cache("checksum-" + val, checksum); + } else { + formBuilder.addFormDataPart(key, val); + } } - } - if (null != content) { - String checksum = IO.checksum(content); - RequestBody fileBody = RequestBody.create(MediaType.parse(fileFormat.contentType()), content); - String attachmentName = val.contains("/") ? S.cut(val).afterLast("/") : val; - formBuilder.addFormDataPart(key, attachmentName, fileBody); - session.cache("checksum-last", checksum); - session.cache("checksum-" + val, checksum); - } else { - formBuilder.addFormDataPart(key, val); } } body = formBuilder.build(); diff --git a/src/main/java/act/test/TestSession.java b/src/main/java/act/test/TestSession.java index 3fcbddb71..918c27b62 100644 --- a/src/main/java/act/test/TestSession.java +++ b/src/main/java/act/test/TestSession.java @@ -66,7 +66,7 @@ */ public class TestSession extends LogSupport { - private static ThreadLocal current = new ThreadLocal<>(); + private final static ThreadLocal current = new ThreadLocal<>(); static TestSession current() { return current.get(); @@ -644,6 +644,30 @@ void verifyValue(String name, Object value, Object test) { } verifyValue(name, value, test); } + } else if (value instanceof Long) { + Long lng = (Long) value; + Long expected = null; + if (test instanceof Long) { + expected = (Long) test; + } else { + String s = S.string(test); + s = S.isIntOrLong(s) ? s : processStringSubstitution(s); + ErrorMessage.errorIfNot(S.isIntOrLong(s), "Cannot verify %s value [%s] against test", name, value, test); + expected = $.convert(s).toLong(); + } + ErrorMessage.errorIfNot(lng.equals(expected), "Cannot verify %s value [%s] against test [%s]", name, value, test); + } else if (value instanceof Integer) { + Integer integer = (Integer) value; + Integer expected = null; + if (test instanceof Integer) { + expected = (Integer) test; + } else { + String s = S.string(test); + s = S.isInt(s) ? s : processStringSubstitution(s); + ErrorMessage.errorIfNot(S.isInt(s), "Cannot verify %s value [%s] against test", name, value, test); + expected = $.convert(s).toInteger(); + } + ErrorMessage.errorIfNot(integer.equals(expected), "Cannot verify %s value [%s] against test [%s]", name, value, test); } else if (value instanceof Number) { Number found = (Number) value; Number expected = null; @@ -652,11 +676,8 @@ void verifyValue(String name, Object value, Object test) { } else { String s = S.string(test); s = S.isNumeric(s) ? s : processStringSubstitution(s); - if (S.isNumeric(S.string(s))) { - expected = $.convert(s).to(Double.class); - } else { - ErrorMessage.error("Cannot verify %s value [%s] against test [%s]", name, value, test); - } + ErrorMessage.errorIfNot(S.isNumeric(S.string(s)), "Cannot verify %s value [%s] against test [%s]", name, value, test); + expected = $.convert(s).to(Double.class); } double delta = Math.abs(expected.doubleValue() - found.doubleValue()); if ((delta / found.doubleValue()) > 0.001) { diff --git a/src/main/java/act/xio/undertow/UndertowNetwork.java b/src/main/java/act/xio/undertow/UndertowNetwork.java index 0cfcfde3f..8404e9c87 100644 --- a/src/main/java/act/xio/undertow/UndertowNetwork.java +++ b/src/main/java/act/xio/undertow/UndertowNetwork.java @@ -21,6 +21,7 @@ */ import act.Act; +import act.conf.AppConfig; import act.controller.meta.ActionMethodMetaInfo; import act.ws.WebSocketConnectionManager; import act.xio.Network; @@ -33,6 +34,7 @@ import io.undertow.server.DefaultByteBufferPool; import io.undertow.server.HttpHandler; import io.undertow.server.protocol.http.HttpOpenListener; +import org.osgl.$; import org.osgl.logging.LogManager; import org.osgl.logging.Logger; import org.osgl.util.E; @@ -45,6 +47,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; +import java.net.ServerSocket; import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyStore; @@ -95,6 +98,10 @@ protected void setUpClient(NetworkHandler client, int port, boolean secure) thro openListener.setRootHandler(handler); ChannelListener> acceptListener = ChannelListeners.openListenerAdapter(openListener); + if (Act.isTest()) { + info("Try clearing random server socket: " + port); + AppConfig.clearRandomServerSocket(port); + } if (!secure) { AcceptingChannel server = worker.createStreamConnectionServer(new InetSocketAddress(port), acceptListener, socketOptions); server.resumeAccepts(); diff --git a/testapps/GH1364/.gitignore b/testapps/GH1364/.gitignore new file mode 100644 index 000000000..3b8194b3f --- /dev/null +++ b/testapps/GH1364/.gitignore @@ -0,0 +1,19 @@ +*.iml +target +.idea +classes +*.log +*.DS_Store +*all.sql +tmp/ +**/.act* +**/.classpath +**/.settings +**/.project +**/.settings/ +store1/ +test.mv.db +test.trace.db +act.pid +.workspace +*.geany diff --git a/testapps/GH1364/pom.xml b/testapps/GH1364/pom.xml new file mode 100644 index 000000000..7f62122b4 --- /dev/null +++ b/testapps/GH1364/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + gh1364-test + 1.9.0 + + ActFramework Test App for Github Issue 1364 + + + org.actframework + act-starter-parent + 1.9.0.2 + + + + + 1.8 + test.AppEntry + + + + + + org.actframework + act + 1.9.1-SNAPSHOT + + + + diff --git a/testapps/GH1364/run_dev b/testapps/GH1364/run_dev new file mode 100755 index 000000000..56d7f76cd --- /dev/null +++ b/testapps/GH1364/run_dev @@ -0,0 +1,3 @@ +#!/bin/sh +echo building ... +mvn -q compile act:run \ No newline at end of file diff --git a/testapps/GH1364/run_dev.bat b/testapps/GH1364/run_dev.bat new file mode 100755 index 000000000..28b0270e1 --- /dev/null +++ b/testapps/GH1364/run_dev.bat @@ -0,0 +1,2 @@ +echo building ... +mvn -q compile act:run \ No newline at end of file diff --git a/testapps/GH1364/run_e2e b/testapps/GH1364/run_e2e new file mode 100755 index 000000000..39a6606d6 --- /dev/null +++ b/testapps/GH1364/run_e2e @@ -0,0 +1,3 @@ +#!/bin/sh +echo building ... +mvn -q compile act:e2e \ No newline at end of file diff --git a/testapps/GH1364/run_e2e.bat b/testapps/GH1364/run_e2e.bat new file mode 100755 index 000000000..ea9f51de7 --- /dev/null +++ b/testapps/GH1364/run_e2e.bat @@ -0,0 +1,2 @@ +echo building ... +mvn -q compile act:e2e \ No newline at end of file diff --git a/testapps/GH1364/run_prod b/testapps/GH1364/run_prod new file mode 100755 index 000000000..006c86ed4 --- /dev/null +++ b/testapps/GH1364/run_prod @@ -0,0 +1,10 @@ +#!/bin/sh +if [ ! -f target/dist/start ]; then + echo building ... + mvn -q clean package + cd target/dist + tar xzf *.tar.gz +else + cd target/dist +fi +./run $* \ No newline at end of file diff --git a/testapps/GH1364/src/main/java/test/AppEntry.java b/testapps/GH1364/src/main/java/test/AppEntry.java new file mode 100644 index 000000000..ce1b9385b --- /dev/null +++ b/testapps/GH1364/src/main/java/test/AppEntry.java @@ -0,0 +1,24 @@ +package test; + +import act.Act; +import act.controller.Controller; +import act.util.JsonView; +import org.joda.time.LocalDate; +import org.osgl.mvc.annotation.GetAction; + + +@SuppressWarnings("unused") +@JsonView +public class AppEntry extends Controller.Util { + + @GetAction + public LocalDate test(LocalDate date) { + return date; + } + + + public static void main(String[] args) throws Exception { + Act.start(); + } + +} diff --git a/testapps/GH1364/src/main/resources/conf/app.properties b/testapps/GH1364/src/main/resources/conf/app.properties new file mode 100644 index 000000000..1e146d868 --- /dev/null +++ b/testapps/GH1364/src/main/resources/conf/app.properties @@ -0,0 +1,801 @@ +i18n=true +############################################## +# Application configuration +# act-1.8.8-RC12-SNAPSHOT +############################################## + +# When `api_doc` is enabled it can navigate to +# http://localhost:5460/~/apidoc +# for API Document. +# +# API doc is enabled by default +# +# uncomment to disable API doc +#api_doc=false + +# When `api_doc.built_in.hide` is enabled the API document +# will not display built-in endpoints, e.g. +# `/~/info` +# +# built-in endpoints is visible in API doc by default +# +# uncomment to hide built-in endpoints in API doc +#api_doc.built_in.hide=true + +# `basic_authentication` is not used by actframework +# core, however plugins like `act-aaa-plugin` use +# this configuration to check if HTTP basic +# authentication is allowed. +# +# basic authentication is disabled by default +# +# uncomment to enable basic authentication +#basic_authentication=true + +# When `built_in_req_handler` is disabled it will +# not be able to access framework built-in endpoints +# including `/~/info`, `/~/version` etc. +# However the following built-in endpoints is still +# available: +# * GET /~/job/{id}/progress - required by runtime application +# * GET /~/api/book/** - only available in dev mode +# +# built-in endpoints is enabled by default +# +# uncomment to disable built endpoints +#built_in_req_handler=false + +# Configure the cache implementation used by ActFramework. +# The cache class specified must implement +# `org.osgl.cache.CacheServiceProvider` interface. +# +# If not specified cache implementation is determined by +# osgl-cache library automatically depending on the +# libraries available in the following order: +# 1. Memcached service +# 2. EhCache service +# 3. OSGL implemented Simple Cache service based on concurrent hash map +# +# uncomment to set your own cache implementation +#cache.impl= + +# By default @CacheFor annotation is not effective in `dev` mode. +# the `cacheFor.dev` configuration can be used to turn on +# @CacheFor in `dev` mode. +# +# uncomment to enable @CacheFor annotation in `dev` mode +#cacheFor.dev=true + +# CLI service listens to local ip addresses to provide telent +# access for command line access to the running app. +# +# CLI service is enabled by default +# +# uncomment to disable CLI service +#cli=false + +# By default CLI port is `5461` +# +# uncomment to set CLI port +#cli.port= + +# `cli.page.size.json` specifies the number of records to display +# per page for CLI JSON view. +# +# Default CLI JSON view page size is 10 records +# +# uncomment to set CLI JSON view page size +#cli.page.size.json= + +# `cli.page.size.table` specifies the number of records to display +# per page for CLI tabular view. +# +# Default CLI table view page size is 22 records +# +# uncomment to set CLI table view page size +#cli.page.size.table= + +# `cli.session.ttl` specifies the number of seconds a CLI +# session will be terminated without interaction. +# +# The default CLI session ttl is 300 seconds, i.e. 5 minutes +# +# uncomment to set CLI session ttl +#cli.session.ttl + +# `cli.session.max.int` specifies the maximum concurrent CLI session +# +# The default limits is 3 +# +# uncomment to set CLI session max +#cli.session.max.int + +# `cookie.prefix` specifies the session/flash cookie prefix. +# +# The default cookie prefix is the `shortId` of the application. +# +# uncomment to customize session/flash cookie prefix. +#cookie.prefix= + +# When `cors` is enabled ActFramework will automatically populate the +# CORS relevant headers in HTTP response. +# +# When `cors` is disabled all other `cors` relevant settings is not effective. +# +# By default `CORS` is disabled +# +# uncomment to enable CORS support +#cors=true + + +# `cors.origin` set the `Access-Control-Allow-Origin` response header. +# +# Default CORS origin header value is `*` +#cors.origin= + +# `cors.headers` set the `Access-Control-Expose-Headers` response header. +# +# Default value is `Content-Type, X-HTTP-Method-Override` +#cors.headers= + +# `cors.headers.expose` set the `Access-Control-Expose-Headers` response header. +# +# Default value is empty. +#cors.headers.expose= + +# `cors.headers.allowed` set the `Access-Control-Allow-Headers` response header. +# +# Default value is empty. +#cors.headers.allowed= + +# `cors.max_age` set the `Access-Control-Max-Age` response header +# +# Default value is `30*60` i.e. 30 minutes +#cors.max_age + +# `cors.allow_credentials.enabled` set the `Access-Control-Allow-Credential` response header +# +# By default this setting is disabled +# +# Uncomment the set `Access-Control-Allow-Credential` to `true` +#cors.allow_credentials=true + +# If `content_suffix.aware` is enabled the framework adjust Request `Accept` +# header based on URL suffix. +# +# E.g. `/customer/123/json` will match the route `/customer/123` +# and set the `Accept` header of the incoming request to `application/json` +# +# By default `content_suffix.aware` is disabled. +# +# Uncomment to enable `content_suffix.aware.enabled` +#content_suffix.aware.enabled=true + +# `csp` set the `Content-Security-Policy` response header value. +# +# By default `csp` is not set. +#csp= + +# `csrf` turn on/off the CSRF protection. +# See https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) +# +# By default `csrf` protection is disabled +# +# uncomment to turn on CSRF protection. +#csrf=true + +# `csrf.param_name` specifies the http request param name +# used to convey the csrf token. +# +# Default value: `__csrf__` +#csrf.param_name + +# `csrf.header.name` specifies name of the http request header +# used to convey the csrf token sent from AJAX client. +# +# Default value: `X-Xsrf-Token` +#csrf.header_name= + +# `csrf.cookie_name` specify the name of the cookie used to +# convey the csrf token generated on the server for the first GET +# request coming from a client. +# +# Default value: `XSRF-TOKEN` +#csrf.cookie_name + +# `csrf.protector` specifies the implementation of `act.security.CSRFProtector`. +# +# Default protector implementation is `HMAC` +# +# uncomment to set csrf protector implementation +#csrf.protector=RANDOM|className + +# `db.seq_gen` specifies the implementation of `act.db.util._SequenceNumberGenerator` +# +# Default value is `null` or an implementation specified by db plugin +#db.seq_gen= + +# `dsp.token` specifies the name of "double submission protect token" +# +# Default value: `act_dsp_token` +#dsp.token= + +# `enum.resolving.exact_match` specify whether it shall resolve enum value +# in exact matching way or Keyword based variation way. +# +# Keyword based variation matching explain: +# +# Suppose we have an enum defination: `enum TestEnum {FOO_BAR} +# All the following string variations can be resolved to `TestEnum.FOO_BAR`: +# +# * FOO_BAR +# * Foo-Bar +# * Foo.Bar +# * foo-bar +# * foo_bar +# * FooBar +# * fooBar +# +# Default value is `false` meaning enum type value resolving is +# non-exact matching +# +# uncomment to make Enum type parameter resolving be exact matching +#enum.resolving.exact_match=false + +# `fmt.date` specifies the pattern for Date type value resolving +# +# The setting can be any one of +# - long +# - medium +# - short +# - custom pattern, e.g. `EEE yyyy MMM dd` +# +# Note custom pattern shall not contain any symbol for time, e.g. `H` or `m` +# Default value: `medium` +fmt.date=dd:MM:yyyy + +# `fmt..date` specifies the pattern for Date type for specific locale +# +# It can specify date formats for multiple locales +# +# Default value: `medium` +# see also: `fmt.date` +#fmt.zh_cn.date=yyyy\u5E74MM\u6708dd\u65E5 + + +# `fmt.data_time` specifies the pattern for DataTime type value resolving. +# +# The setting can be any one of +# - long +# - medium +# - short +# - custom pattern, e.g. `EEE yyyy MMM dd` +# +# Default value: `medium` +#fmt.date_time= + +# `fmt..date_time` specifies the pattern for DateTime type for specific locale +# +# It can specify date_time formats for multiple locales +# +# Default value: `medium` +# see also: `fmt.date_time` +#fmt.zh_cn.date_time=yyyy\u5E74MM\u6708dd\u65E5 HH:mm + +# `fmt.time` specifies the pattern for Time type value resolving +# +# The setting can be any one of +# - long +# - medium +# - short +# - custom pattern, e.g. `HHmmss` +# +# Note custom pattern shall not contain any symbol for date, e.g. `y` or `M` +# Default value: `medium` +#fmt.time= + +# `fmt..time` specifies the pattern for Time type for specific locale. +# +# It can specify time formats for multiple locales +# +# Default value: `medium` +# see also: `fmt.time` +#fmt.zh_cn.time=HH:mm + +# `handler.csrf_check_failure` specifies the implemetation of `MissingAuthenticationHandler` +# to be called when CSRF checking failed. +# +# Default value is the setting of `handler.missing_authentication` +#handler.csrf_check_failure= + +# `handler.missing_authentication` specifies the implemetation of `MissingAuthenticationHandler` +# to be called when authentication is failed on an non-AJAX request. +# +# Default value is `act.util.RedirectToLoginUrl` if login URL is in the route table. +# otherwise it is `act.util.ReturnUnauthorized` +#handler.missing_authentication= + +# `handler.missing_authentication` specifies the implemetation of `MissingAuthenticationHandler` +# to be called when authentication is failed on an AJAX request. +# +# Default value is the setting of `handler.missing_authentication` +#handler.missing_authentication.ajax= + +# `handler.unknown_http_method` specifies the handler implementation to be called +# when ActFramework found the HTTP method of an incoming request is not supported +# +# Default value is `UnknownHttpMethodProcessor.METHOD_NOT_ALLOWED`, i.e. +# respond `405 Method Not Allowed` response. +#handler.unknown_http_method= + +# `act.header.overwrite` turn on/off HTTP HEADER overwrite. +# +# Once this config is turned on, then it can overwrite header +# with HTTP Query parameter or HTTP post form field. The naming +# convention of the param/field is: +# +# ``` +# act_header_ +# ``` +# +# For example, if it needs to overwrite `Content-Type`, use +# `act_header_content_type` as the query parameter name. +# +# Default value: `false` +#header.overwrite=true + + +# `header.session.expiration` specifies name of the HTTP response header to be +# used to convey the JWT/session cookie expiration time. +# +# Default value is `Act-Session-Expires` +#header.session.expiration= + +# `host` specifies the hostname of the application. +# +# This setting is often used to concatentate full URL including host +# in email template. +# +# Default value: `localhost` +#host= + +# `http.external_server` specify if the app is running behind a frontend +# http server, e.g. nginx. +# +# Default value: `true` when running in `prod` mode or `false` when running in `dev` mode +#http.external_server=true|false + +# `http.params.max` specifies the maximum number of http parameters. +# +# This setting can be to prevent the hash collision DOS attack. +# +# Default value: 128 +#http.params.max= + +# `http.port` specifies the default HTTP port number +# +# Default value: 5460 +#http.port= + +# `http.port.external` specifies the default HTTP port number of +# frontend HTTP server (if exists). +# +# Default value: 80 +#http.port.external= + +# `http.port.external.secure` specifies the default HTTPS port number of +# the frontend HTTP server (if exists) +# +# Default value: 443 +#http.port.external.secure= + +# `http.secure` specifies whether the default http port is running in +# an secure HTTP channel +# +# Default value: `true` when running in `prod` mode or `false` in `dev` mode +#http.secure=true|false + +# `https.port` specify the https port - only effect +# when `ssl` is enabled. +# +# Default value: `5443` +#https.port= + +# `i18n` turn on/off i18n support in ActFramework. +# +# Default value: false +#i18n=true|false + +# `i18n.locale.param_name` specifies the param name to set client locale +# in http request +# +# Default value: `act_locale` +#i18n.locale.param_name= + +# `i18n.locale.cookie_name` specifies the name for the locale cookie +# +# Default value: `act_locale` +#i18n.locale.cookie_name= + +# `idgen.node_id.provider` specifies the implementation of +# `act.util.IdGenerator.NodeIdProvider` which is called when generating the +# CUID (Custer Unique Identifier) +# +# Default value: `act.util.IdGenerator.NodeIdProvider.IpProvider` +#idgen.node_id.provider= + +# `idgen.node_id.effective_ip_bytes.size` specifies how many bytes in the ip address +# will be used to calculate node ID. Usually in a cluster environment, the ip address will +# be different at only (last) one byte or (last) two bytes, in which case it could set this +# configuration to `1` or `2`. When the configuration is set to `4` then it means all 4 IP +# bytes will be used to calculate the node ID +# +# Default value: 4 +#idgen.node_id.effective_ip_bytes.size=1|2|3|4 + +# `idgen.start_id.provider` specifies the `act.util.IdGenerator.StartIdProvider` +# implementation which is called when generating the CUID +# +# Default value: `act.util.IdGenerator.StartIdProvider.DefaultStartIdProvider` +# which read/write the file specified by `idgen.start_id.file` setting in +# the project dir. +#idgen.start_id.provider= + +# `idgen.start_id.file` specifies the start id persistent file. +# This setting is used by `act.util.IdGenerator.StartIdProvider.DefaultStartIdProvider` +# +# Default value: `.act.id-app` +#idgen.start_id.file= + +# `idgen.seq_id.provider` specifies the `act.util.IdGenerator.SequenceProvider` +# implementation which is called when generating the CUID. +# +# Default value: `act.util.IdGenerator.SequenceProvider.AtomicLongSeq` +#idgen.seq_id.provider= + +# `idgen.encoder` specifies the `act.util.IdGenerator.LongEncoder` implementation +# which is called when generating the CUID. +# +# Default value: `act.util.IdGenerator.SafeLongEncoder` which generates URL +# safe and slighty longer string for long value encoding. +#idgen.encoder=act.util.IdGenerator.SafeLongEncoder|act.util.IdGenerator.UnsafeLongEncoder + +# `job.pool.size` specifies the maximum number of threads +# can exists in the application's job manager's thread pool +# +# Default value: 10 +#job.pool.size= + +# `jwt` enable/disable JWT support. +# This is actually a combination of the following settings: +# * session.codec=act.session.JsonWebTokenSessionCodec +# * session.header.payload.prefix="Bearer " # note the space after `Bearer` +# * session.header=Authorization +#jwt=true|false + +# `jwt.algo` specifies the algorithm used to encrypt/decrypt JWT. +# +# Default value: SHA256 +#jwt.algo=SHA256|SHA384|SHA512 + +# `jwt.issuer` specify `iss` payload of JWT +# +# Default value: the setting of `cookie.prefix` +#jwt.issuer= + +# `locale` specifies the application default locale +# +# Default value: the result of calling `java.util.Locale#getDefault()` +#locale= + +# `metric` turn on/off internal metrics. +# +# Default value: true +#metric=true|false + +# `modules` declare additional app base (for multi-module maven projects) +#modules= + +# `namedPorts` specifies a list of port names this +# application listen to. These are additional ports other than +# the default `http.port` setting. +# +# Default value: null +#namedPorts=admin:8888;ipc:8899;... + +# `password.spec` specify default password spec which is used to +# validate user password. +# +# Default value: +# * dev mode: `a[3,]`, meaning require lower case letter and min length is 3 characters. +# * prod mode: `aA0[6,]`, meaning require lower case letter, uppercase letter, digit and min length is 6 characters. +# +# Developer can also specify a `Password.Validator` implementation +# class for this configuration, in which case, the framework will instantiate the user +# specified validator instead of `act.validation.PasswordSpec` as the default +# password validator. +# +#password.spec= + +# `ping.path` specify the ping path. +# If this setting is specified, then when session resolving, system +# will check if the current URL matches the setting. If matched +# then session cookie expiration time will not be changed. Otherwise +# the expiration time will refresh +# +# Default value: `null` +#ping.path= + +# `req.throttle` specifies the maximum number of requests +# that can be handled per second from the same ip address +# when `@Throttled` annotation is presented without `value` +# specified on a request handler method. +# +# Default value: 2 +#req.throttle= + +# `req.throttle.expire.scale` turn on/off request throttle +# expiry time increment. +# +# Default value: `false` +#req.throttle.expire.scale=true|false + +# `render.json.content_type.ie` specify whether the content type +# of JSON response on request initiated from an IE browser. +# +# Note early IE browser does not support the `application/json` content type. +# +# Default value: `null` +#render.json.content_type.ie= + +# `resolver.template_path` specifies the class that extends +# `TemplatePathResolver`. Application developer could use this +# configuration to add some flexibility to +# template path resolving logic, e.g. different home +# for different locale or different home for different device +# type etc +# +# Defautl value: `TemplatePathResolver` +#resolver.template_path + +# `resource.preload.size.limit` Specifies the maximum number of bytes of +# a resource that can be preload into memory. Specify the setting to +# `0` or negative value disable resource preload feature. +# +# Default value: `1024 * 10`, i.e. 10KB +#resource.preload.size.limit= + +# `scan_package` specify the app package in which all classes is subject +# to bytecode processing, e.g enhancement and injection. +# +# By default ActFramework will infer the scan package +# from the app entry class which contains the main method +# starting act. +# +#scan_package= + +# `act.secret` Specifies the secret key the application used to do general +# encrypt/decrypt/sign etc +# +# Note application must set this configuration to secure the communication +act.secret=xcgXKMICkvZ3k3uLj2AIiarXjLt2Lr6nHzvkBs9o1a9eKyspfvSd1eKYYSYNAhu8 + +# `secret.rotate` turn on app secret rotation for session/flash +# token signing and encrypt. This feature makes it even harder +# to crack as secret changes regularly. +# +# Default value: false +#secret.rotate=true|false + +# `secret.rotate.period` set the secret rotate period in terms of minute. +# +# **Note** the number of minute must be a factor of 60. Any number that +# is not the factor of 60 then it will be up rounded: +# +# * 1 -> 1 +# * 2 -> 2 +# * 3 -> 4 +# * 4 -> 4 +# * 5 -> 5 +# * 6 -> 6 +# * 7 -> 10 +# * 8 -> 10 +# * 33 -> 30 +# * 50 -> 60 +# +# the rotation period less than hour will be count from the beginning of +# the current hour. +# +# If the number minutes exceeds 60, then it must be a factor of 60 * 24. Any +# number if not will be rounded: +# +# * 65 -> 60 +# * 60 * 3 -> 60 * 3 +# * 60 * 5 -> 60 * 6 +# * 60 * 7 -> 60 * 6 +# * 60 * 10 -> 60 * 12 (half day) +# +# if the number of minutes equals of exceeds 120, the rotation period will +# be counted from the beginning of the day. +# +# The maximum period is `60 * 24`, i.e. 24 hours. Any setting exceed that number +# will be cut off down to 24 hours. +# +# Default value: `30` minutes, ie. half an hour +#secret.rotate.period= + +# `server.header` specifies the server header to be output to the response +# +# Default value: `act/${act-version}` +#server.header= + +#`session.outputExpiration.enabled` turn on/off expiration output to +# response header. +# +# This setting only effective when it is using token to +# map session payload. +# +# Default value: `true` +#session.outputExpiration=true|false + +# `session.ttl` specifies the session duration in seconds. +# If user failed to interact with server for amount of time that +# exceeds the setting then the session will be destroyed +# +# Default value: `60 * 30` i.e half an hour +#session.ttl= + +# `session.persistent` specify whether the system +# should treat session cookie as persistent cookie. If this setting +# is enabled, then the user's session will not be destroyed after +# browser closed. +# +# Refer to http://en.wikipedia.org/wiki/HTTP_cookie#Persistent_cookie +# +# Default value: `false` +#session.persistent=true|false + +# `session.encrypted` specify whether the system should +# encrypt the key/value pairs in the session cookie. Enable session +# encryption will greatly improve the security but with the cost +# of additional CPU usage and a little bit longer time on request +# processing. +# +# Default value: `false` +#session.encrypted=true|false + +# `session.key.username` specifies the session key for username +# +# Default value: `username` +#session.key.username= + +# `session.mapper` specifies the implementation of `act.session.SessionMapper` +# Predefined session mappers: +# * `act.session.CookieSessionMapper` - map session data to session cookie +# * `act.session.HeaderTokenSessionMapper` - map session data to header token +# * `act.session.CookieAndHeaderSessionMapper` - map session data to both cookie and header +# +# Default value:`act.session.CookieSessionMapper` +#session.mapper= + +# `session.codec` specifies the implementation of `act.session.SessionCodec` +# Predefined session codec: +# * `act.session.DefaultSessionCodec` +# * `act.session.JsonWebTokenSessionCodec` +# +# Default value: `act.session.DefaultSessionCodec` when `jwt` is `false` +# or `act.session.JsonWebTokenSessionCodec` when `jwt` is `true` +#session.codec= + +# `session.header` - specify the session header name. +# +# Effective only when `act.session.SessionMapper` is `act.session.HeaderTokenSessionMapper` +# +# Default value: X-Act-Session when `jwt` is `false` +# or `Authorization` when `jwt` is `true` +#session.header= + +# `session.header.payload.prefix` set the session payload prefix, e.g. `Bearer ` +# +# Default value: `null` when `jwt` is `false` +# or `Bearer ` when `jwt` is `true` +#session.header.payload.prefix= + +# `session.secure` specifies whether the session cookie should +# be set as secure. Enable secure session will cause session cookie only +# effective in https connection. Literally this will enforce the web site to run +# default by https. +# +# Default value: `true` +# +# **Note** when {@link Act Act server} is running in {@link Act.Mode#DEV mode} +# session http only will be disabled without regarding to the `session.secure.enabled` +# setting +#session.secure=true|false + +# `source.version` specifies the java version +# of the src code. This configuration is used only +# in dev mode. +# +# Default value: 1.7 +#source.version= + +# `ssl` turn on/off SSL support. +# +# Default value: `false` +# +# **Note** this is experimental feature +#ssl=true|false + +# `target.version` specifies the java version of the compile +# target code. This configuration is used only in dev mode. +# +# Default value: 1.7 +#target.version= + +# `template.home` specifies where the view templates resides. +# If not specified then will use the {@link View#name() view name +# in lower case} as the template home if that view is used. +# +# Default value: the result of `View.name()` +#template.home= + +# `threadlocal_buf.limit` set the maximum buffer size of thread local instance +# of `org.osgl.util.S.Buffer` and `org.osgl.util.ByteArrayBuffer`. If the buffer +# size exceeds the limit, the thread local instance will be dropped and new +# instance will be created as the thread local instance. +# +# Default value: 1024 * 8 (i.e. 8k) +#threadlocal_buf.limit= + +# `trace.handler` turn on/off handle invocation calls. +# +# When this configuration is turned on, every call to the +# action handler/job handler/mail sender method will be logged. +# +# Default value: `false` +#trace.handler=true|false + +# `trace.request` turn on/off incoming request log +# +# When this configuration is turned on, every incoming request +# will be logged +# +# default value: `false` +#trace.request=true|false + +# `upload.in_memory.threshold` +# +# If file upload content length is less than this configuration then +# the file will not get written into disk, instead it will get cached +# into a in memory byte array +# +# Default value: `1024 * 10` +#upload.in_memory.threshold + +# `url.context` specifies the app global URL context. +# +# If this configuration is specified then all route configured will +# be attached to the configured context path. +# +# Default value: `null` +#url.context= + +# `url.login` specifies the login URL which is used +# by {@link act.util.RedirectToLoginUrl} +# +# Default value: `/login` +#url.login= + +# `url.login.ajax` specifies the login URL which is used +# by {@link act.util.RedirectToLoginUrl} when request is AJAX +# +# Default value: the value of `url.login` setting +#url.login.ajax + +# `view.default` specifies the default view solution. If there +# are multiple views registered and default view are available, then +# it will be used at priority to load the templates +# +# Default value: `rythm` +#view.default= diff --git a/testapps/GH1364/src/main/resources/conf/prod/app.properties b/testapps/GH1364/src/main/resources/conf/prod/app.properties new file mode 100644 index 000000000..5f0017b9a --- /dev/null +++ b/testapps/GH1364/src/main/resources/conf/prod/app.properties @@ -0,0 +1,5 @@ +############################################## +# Application configuration for prod profile +# act-1.8.8-RC12-SNAPSHOT +############################################## +act.secret=clypiSZ9qOFMZ8JgAdutcvPctiPYRhC4HFkjcvwhf9j3YQrAUxAx9cUL0FzmnlRB \ No newline at end of file diff --git a/testapps/GH1364/src/main/resources/conf/uat/app.properties b/testapps/GH1364/src/main/resources/conf/uat/app.properties new file mode 100644 index 000000000..844739167 --- /dev/null +++ b/testapps/GH1364/src/main/resources/conf/uat/app.properties @@ -0,0 +1,5 @@ +############################################## +# Application configuration for uat profile +# act-1.8.8-RC12-SNAPSHOT +############################################## +act.secret=AkrRnS5yuyq98LmEBRwoQom9nCIj8oLlXEKRUjXiBlbjPc0phCf7VL3yJOJqjjbC \ No newline at end of file diff --git a/testapps/GH1364/src/main/resources/logback.xml b/testapps/GH1364/src/main/resources/logback.xml new file mode 100644 index 000000000..83909e662 --- /dev/null +++ b/testapps/GH1364/src/main/resources/logback.xml @@ -0,0 +1,115 @@ + + + + + + + + + true + + %date %highlight(%-5level) %cyan(%logger{5}@[%-4.30thread]) - %msg%n + + + + + + + true + + %msg%n + + + + + + act.log + + %d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + /act.%i.log.zip + 1 + 10 + + + + 2MB + + + + + + e2e.log + + %msg%n + + + + + act-db.log + + %d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + /act-db.%i.log.zip + 1 + 10 + + + + 2MB + + + + + act-metric.log + + %d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + /act-metric.%i.log.zip + 1 + 10 + + + + 2MB + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testapps/GH1364/src/main/resources/messages.properties b/testapps/GH1364/src/main/resources/messages.properties new file mode 100644 index 000000000..853b8995a --- /dev/null +++ b/testapps/GH1364/src/main/resources/messages.properties @@ -0,0 +1 @@ +osgl.result.unauthorized=Please login \ No newline at end of file diff --git a/testapps/GH1364/src/test/resources/scenarios/test.yml b/testapps/GH1364/src/test/resources/scenarios/test.yml new file mode 100644 index 000000000..5e3ef819d --- /dev/null +++ b/testapps/GH1364/src/test/resources/scenarios/test.yml @@ -0,0 +1,11 @@ +Scenario(1255): + description: "I18n - date format setting not effective" + interactions: + - description: test + request: + headers: + Accept-Language: en + get: ?date=12:12:2019 + response: + result: + - before: ${today} \ No newline at end of file diff --git a/testapps/GHIssues/pom.xml b/testapps/GHIssues/pom.xml index 49175fd25..3b167701c 100644 --- a/testapps/GHIssues/pom.xml +++ b/testapps/GHIssues/pom.xml @@ -12,7 +12,7 @@ org.actframework act-starter-parent - 1.9.0.1 + 1.9.0.2 @@ -57,13 +57,19 @@ cn.hutool hutool-all - [4.1.12,) + 5.5.4 org.actframework act-aaa + + com.warrenstrange + googleauth + 1.5.0 + + From c7d13524edfb50de8ee19d713f91e63c708d7c66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jun 2022 01:46:09 +0000 Subject: [PATCH 37/63] Bump fastjson from 1.2.75 to 1.2.83 Bumps [fastjson](https://github.com/alibaba/fastjson) from 1.2.75 to 1.2.83. - [Release notes](https://github.com/alibaba/fastjson/releases) - [Commits](https://github.com/alibaba/fastjson/compare/1.2.75...1.2.83) --- updated-dependencies: - dependency-name: com.alibaba:fastjson dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index abf61e323..2c9d028fc 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 1.2 1.3.3 3.22.0 - 1.2.75 + 1.2.83 1.1.2 0.7 1.18 From 244321ac1f8f7f5da8d422d92283c6d573a3ac77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Sep 2022 22:58:09 +0000 Subject: [PATCH 38/63] Bump jsoup from 1.14.2 to 1.15.3 Bumps [jsoup](https://github.com/jhy/jsoup) from 1.14.2 to 1.15.3. - [Release notes](https://github.com/jhy/jsoup/releases) - [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES) - [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.14.2...jsoup-1.15.3) --- updated-dependencies: - dependency-name: org.jsoup:jsoup dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index abf61e323..c0dd92855 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ 2.14.6 1.0.0.Final 2.10.6 - 1.14.2 + 1.15.3 4.7.2 From 2e90cdca0352755c26aa80bacf144c22c9cb3a76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Sep 2022 03:35:07 +0000 Subject: [PATCH 39/63] Bump snakeyaml from 1.26 to 1.31 in /legacy-testapp Bumps [snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 1.26 to 1.31. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-1.31..snakeyaml-1.26) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- legacy-testapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy-testapp/pom.xml b/legacy-testapp/pom.xml index 1036b988a..9c9ea1402 100644 --- a/legacy-testapp/pom.xml +++ b/legacy-testapp/pom.xml @@ -210,7 +210,7 @@ org.yaml snakeyaml - 1.26 + 1.31 From 4a26c6e1bd6f60af5e8271e9f70286271cf50ecd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Sep 2022 03:35:09 +0000 Subject: [PATCH 40/63] Bump snakeyaml from 1.26 to 1.31 Bumps [snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 1.26 to 1.31. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-1.31..snakeyaml-1.26) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index abf61e323..89e5295cd 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 1.3.1 1.1.0.Final 2.1.6.Final - 1.26 + 1.31 3.4.0 From 9b15871bb32327a31d83855d4234baa2bc635abf Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Sat, 19 Nov 2022 02:07:53 +0000 Subject: [PATCH 41/63] vuln-fix: Temporary File Information Disclosure This fixes temporary file information disclosure vulnerability due to the use of the vulnerable `File.createTempFile()` method. The vulnerability is fixed by using the `Files.createTempFile()` method which sets the correct posix permissions. Weakness: CWE-377: Insecure Temporary File Severity: Medium CVSSS: 5.5 Detection: CodeQL & OpenRewrite (https://public.moderne.io/recipes/org.openrewrite.java.security.SecureTempFileCreation) Reported-by: Jonathan Leitschuh Signed-off-by: Jonathan Leitschuh Bug-tracker: https://github.com/JLLeitschuh/security-research/issues/18 Co-authored-by: Moderne --- src/main/java/act/app/AppClassLoader.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/act/app/AppClassLoader.java b/src/main/java/act/app/AppClassLoader.java index 67afa07c4..d1a841b45 100644 --- a/src/main/java/act/app/AppClassLoader.java +++ b/src/main/java/act/app/AppClassLoader.java @@ -51,6 +51,7 @@ import java.io.*; import java.lang.annotation.Annotation; import java.net.*; +import java.nio.file.Files; import java.util.*; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @@ -514,7 +515,7 @@ private Class loadAppClass(String name, boolean resolve) throws ClassNotFound } return c; } catch (VerifyError e) { - File f = File.createTempFile(name, ".class"); + File f = Files.createTempFile(name, ".class").toFile(); IO.write(baNew, f); throw e; } From a7af84968c0a811af5cfbdeea06f9dce1ac66846 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 20:21:28 +0000 Subject: [PATCH 42/63] Bump undertow-core from 2.1.6.Final to 2.2.19.Final Bumps [undertow-core](https://github.com/undertow-io/undertow) from 2.1.6.Final to 2.2.19.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.1.6.Final...2.2.19.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a4252884b..8ef7f4bf3 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ 1.11.9 1.3.1 1.1.0.Final - 2.1.6.Final + 2.2.19.Final 1.31 3.4.0 From f0704ecb403af1d5fe6ae58d615d97505ca68a41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Aug 2021 21:00:28 +0000 Subject: [PATCH 43/63] Bump jsoup from 1.12.1 to 1.14.2 Bumps [jsoup](https://github.com/jhy/jsoup) from 1.12.1 to 1.14.2. - [Release notes](https://github.com/jhy/jsoup/releases) - [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES) - [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.12.1...jsoup-1.14.2) --- updated-dependencies: - dependency-name: org.jsoup:jsoup dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7491bce11..ca8d30488 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ 2.14.6 1.0.0.Final 2.10.6 - 1.12.1 + 1.14.2 4.7.2 From 2581faa1f89776bd9f08d8e6911857c0b9c2b68a Mon Sep 17 00:00:00 2001 From: benstone Date: Mon, 28 Jun 2021 21:38:29 +0800 Subject: [PATCH 44/63] fix index error when process string substitution --- src/main/java/act/test/TestSession.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/act/test/TestSession.java b/src/main/java/act/test/TestSession.java index 918c27b62..9f19c7786 100644 --- a/src/main/java/act/test/TestSession.java +++ b/src/main/java/act/test/TestSession.java @@ -312,8 +312,9 @@ String processStringSubstitution(String s) { buf.append(getVal(key, payload)); } n = s.indexOf("${", a); + a++; if (n < 0) { - buf.append(s.substring(a + 1)); + buf.append(s.substring(a)); return buf.toString(); } z = n; From 032d4efec125a684dd0b8b891e8bc2604607cc6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Aug 2021 22:52:32 +0000 Subject: [PATCH 45/63] Bump undertow-core from 2.1.3.Final to 2.1.6.Final Bumps [undertow-core](https://github.com/undertow-io/undertow) from 2.1.3.Final to 2.1.6.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.1.3.Final...2.1.6.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ca8d30488..1224ebf23 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ 1.11.9 1.3.1 1.1.0.Final - 2.1.3.Final + 2.1.6.Final 1.26 3.4.0 From 40e0127e86a188363d5f7f1d6ed84ab07289eae7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Jun 2021 22:03:45 +0000 Subject: [PATCH 46/63] Bump snakeyaml from 1.17 to 1.26 in /legacy-testapp Bumps [snakeyaml](https://bitbucket.org/asomov/snakeyaml) from 1.17 to 1.26. - [Commits](https://bitbucket.org/asomov/snakeyaml/branches/compare/snakeyaml-1.26..v1.17) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- legacy-testapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy-testapp/pom.xml b/legacy-testapp/pom.xml index 336b6a7c4..1036b988a 100644 --- a/legacy-testapp/pom.xml +++ b/legacy-testapp/pom.xml @@ -210,7 +210,7 @@ org.yaml snakeyaml - 1.17 + 1.26 From 0fbe8fc722cb207a819630b150e22a37db06e253 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Sat, 19 Nov 2022 02:07:53 +0000 Subject: [PATCH 47/63] vuln-fix: Temporary File Information Disclosure This fixes temporary file information disclosure vulnerability due to the use of the vulnerable `File.createTempFile()` method. The vulnerability is fixed by using the `Files.createTempFile()` method which sets the correct posix permissions. Weakness: CWE-377: Insecure Temporary File Severity: Medium CVSSS: 5.5 Detection: CodeQL & OpenRewrite (https://public.moderne.io/recipes/org.openrewrite.java.security.SecureTempFileCreation) Reported-by: Jonathan Leitschuh Signed-off-by: Jonathan Leitschuh Bug-tracker: https://github.com/JLLeitschuh/security-research/issues/18 Co-authored-by: Moderne --- src/main/java/act/app/AppClassLoader.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/act/app/AppClassLoader.java b/src/main/java/act/app/AppClassLoader.java index 67afa07c4..d1a841b45 100644 --- a/src/main/java/act/app/AppClassLoader.java +++ b/src/main/java/act/app/AppClassLoader.java @@ -51,6 +51,7 @@ import java.io.*; import java.lang.annotation.Annotation; import java.net.*; +import java.nio.file.Files; import java.util.*; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @@ -514,7 +515,7 @@ private Class loadAppClass(String name, boolean resolve) throws ClassNotFound } return c; } catch (VerifyError e) { - File f = File.createTempFile(name, ".class"); + File f = Files.createTempFile(name, ".class").toFile(); IO.write(baNew, f); throw e; } From 686e89eacfe8872a5a8557a3c36965cc492147e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Sep 2022 03:35:09 +0000 Subject: [PATCH 48/63] Bump snakeyaml from 1.26 to 1.31 Bumps [snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 1.26 to 1.31. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-1.31..snakeyaml-1.26) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1224ebf23..4c2e8a436 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 1.3.1 1.1.0.Final 2.1.6.Final - 1.26 + 1.31 3.4.0 From 92001dda8cd0890c00b7ac36d4aee844a432e5a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Sep 2022 03:35:07 +0000 Subject: [PATCH 49/63] Bump snakeyaml from 1.26 to 1.31 in /legacy-testapp Bumps [snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 1.26 to 1.31. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-1.31..snakeyaml-1.26) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- legacy-testapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy-testapp/pom.xml b/legacy-testapp/pom.xml index 1036b988a..9c9ea1402 100644 --- a/legacy-testapp/pom.xml +++ b/legacy-testapp/pom.xml @@ -210,7 +210,7 @@ org.yaml snakeyaml - 1.26 + 1.31 From 8d51b646b4fbd5ccc18cf86309bfb3ad2cad3f9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Sep 2022 22:58:09 +0000 Subject: [PATCH 50/63] Bump jsoup from 1.14.2 to 1.15.3 Bumps [jsoup](https://github.com/jhy/jsoup) from 1.14.2 to 1.15.3. - [Release notes](https://github.com/jhy/jsoup/releases) - [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES) - [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.14.2...jsoup-1.15.3) --- updated-dependencies: - dependency-name: org.jsoup:jsoup dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4c2e8a436..761ff2c70 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ 2.14.6 1.0.0.Final 2.10.6 - 1.14.2 + 1.15.3 4.7.2 From b922637aebb182ff09a5365f4be4cf84e84bfd99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 20:21:28 +0000 Subject: [PATCH 51/63] Bump undertow-core from 2.1.6.Final to 2.2.19.Final Bumps [undertow-core](https://github.com/undertow-io/undertow) from 2.1.6.Final to 2.2.19.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.1.6.Final...2.2.19.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 761ff2c70..bdc0a86c9 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ 1.11.9 1.3.1 1.1.0.Final - 2.1.6.Final + 2.2.19.Final 1.31 3.4.0 From 1b50ebd45227076306187bdab762742631f95219 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Jun 2022 01:46:09 +0000 Subject: [PATCH 52/63] Bump fastjson from 1.2.75 to 1.2.83 Bumps [fastjson](https://github.com/alibaba/fastjson) from 1.2.75 to 1.2.83. - [Release notes](https://github.com/alibaba/fastjson/releases) - [Commits](https://github.com/alibaba/fastjson/compare/1.2.75...1.2.83) --- updated-dependencies: - dependency-name: com.alibaba:fastjson dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bdc0a86c9..1062be863 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,7 @@ 1.2 1.3.3 3.22.0 - 1.2.75 + 1.2.83 1.1.2 0.7 1.18 From ce255015ecf11d2409a5f07a0acd93f3d780aac9 Mon Sep 17 00:00:00 2001 From: Benstone Zhang Date: Mon, 10 May 2021 19:45:36 +0800 Subject: [PATCH 53/63] fix #1392: GetTimeTest failed for non-english locale Default DateTime formats are only for english locale. --- src/main/java/act/test/verifier/DateTimeVerifier.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/act/test/verifier/DateTimeVerifier.java b/src/main/java/act/test/verifier/DateTimeVerifier.java index 87a85c3ca..2ea835221 100644 --- a/src/main/java/act/test/verifier/DateTimeVerifier.java +++ b/src/main/java/act/test/verifier/DateTimeVerifier.java @@ -31,6 +31,7 @@ import java.text.DateFormat; import java.util.Date; +import java.util.Locale; public abstract class DateTimeVerifier extends Verifier { @@ -112,12 +113,12 @@ private static Long tryWithFormat(String s, String pattern, String... otherPatte if (null != l) { return l; } - l = tryWithFormat(s, DateTimeFormat.forPattern(pattern)); + l = tryWithFormat(s, DateTimeFormat.forPattern(pattern).withLocale(Locale.ENGLISH)); if (null != l) { return l; } for (String op : otherPatterns) { - l = tryWithFormat(s, DateTimeFormat.forPattern(op)); + l = tryWithFormat(s, DateTimeFormat.forPattern(op).withLocale(Locale.ENGLISH)); if (null != l) { return l; } From 3745329d4274e62c6997a09ece3356a49ef60d32 Mon Sep 17 00:00:00 2001 From: Benstone Zhang Date: Mon, 10 May 2021 19:08:34 +0800 Subject: [PATCH 54/63] fix bug of url.context not show in e404 page Make act.route.Router.ensureUrlContext as public, then we can patch the path string in e404 template. --- src/main/java/act/route/Router.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/act/route/Router.java b/src/main/java/act/route/Router.java index a099c4b41..0f91867a2 100644 --- a/src/main/java/act/route/Router.java +++ b/src/main/java/act/route/Router.java @@ -620,7 +620,7 @@ public String urlBase(ActionContext context) { } } - private String ensureUrlContext(String path) { + public String ensureUrlContext(String path) { String urlContext = appConfig.urlContext(); if (null == urlContext || path.startsWith(urlContext)) { if ("/".equals(path)) { From 0f802d3fa0157c554bec0840cbdeadb7a7b2ea9e Mon Sep 17 00:00:00 2001 From: Benstone Zhang Date: Mon, 10 May 2021 19:11:30 +0800 Subject: [PATCH 55/63] fix bug of url.context not show in e404 page add url.context prefix to all path --- src/main/resources/rythm/error/dev/e404.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/resources/rythm/error/dev/e404.html b/src/main/resources/rythm/error/dev/e404.html index 74a20bd07..a0bea81f5 100644 --- a/src/main/resources/rythm/error/dev/e404.html +++ b/src/main/resources/rythm/error/dev/e404.html @@ -54,10 +54,13 @@ @r.method() + @{ + String path = _action.router().ensureUrlContext(r.path()); + } @if (r.method() == "GET") { - @r.path() + @path } else { - @r.path() + @path } @r.compactHandler() From 3231c87ea8dc33484b705ceee22390c879f58ebb Mon Sep 17 00:00:00 2001 From: benstone Date: Tue, 11 May 2021 15:15:49 +0800 Subject: [PATCH 56/63] update title of td to make all the paths are consistent --- src/main/resources/rythm/error/dev/e404.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/rythm/error/dev/e404.html b/src/main/resources/rythm/error/dev/e404.html index a0bea81f5..e38875eec 100644 --- a/src/main/resources/rythm/error/dev/e404.html +++ b/src/main/resources/rythm/error/dev/e404.html @@ -53,10 +53,10 @@ @def tr(RouteInfo r, String parity) { @r.method() - - @{ - String path = _action.router().ensureUrlContext(r.path()); - } + @{ + String path = _action.router().ensureUrlContext(r.path()); + } + @if (r.method() == "GET") { @path } else { From 716a67d0b6b33c6f6b47ed303eab40b0ea9560ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Oct 2020 10:38:04 +0000 Subject: [PATCH 57/63] Bump junit from 4.11 to 4.13.1 in /legacy-testapp Bumps [junit](https://github.com/junit-team/junit4) from 4.11 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.11.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.11...r4.13.1) Signed-off-by: dependabot[bot] --- legacy-testapp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/legacy-testapp/pom.xml b/legacy-testapp/pom.xml index 9c9ea1402..39ebf2069 100644 --- a/legacy-testapp/pom.xml +++ b/legacy-testapp/pom.xml @@ -178,7 +178,7 @@ junit junit - 4.11 + 4.13.1 test From 881214acf15d4e2329ae81a28fd7d1525159db5f Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sat, 26 Nov 2022 13:35:24 +1100 Subject: [PATCH 58/63] fix #1427, #1407, #1399 --- CHANGELOG.md | 3 ++ README.md | 2 +- legacy-testapp/pom.xml | 2 +- legacy-testapp/run.sh | 2 +- pom.xml | 4 +-- src/main/java/act/apidoc/Endpoint.java | 20 ++++++++++--- src/main/java/act/app/AppClassLoader.java | 3 +- .../meta/InterceptorMethodMetaInfo.java | 5 ++-- src/main/java/act/test/RequestBuilder.java | 2 +- src/main/java/act/test/TestSession.java | 3 +- .../xio/undertow/UndertowCookieAdaptor.java | 27 +++++++++++++++++ testapps/GHIssues/pom.xml | 10 ------- .../src/main/java/ghissues/Gh1407.java | 30 +++++++++++++++++++ .../src/main/java/ghissues/gh532/Foo.java | 7 +++++ .../main/java/ghissues/gh532/FooService.java | 12 ++++++++ .../src/test/resources/scenarios/1407.yml | 8 +++++ 16 files changed, 114 insertions(+), 26 deletions(-) create mode 100644 testapps/GHIssues/src/main/java/ghissues/Gh1407.java create mode 100644 testapps/GHIssues/src/main/java/ghissues/gh532/Foo.java create mode 100644 testapps/GHIssues/src/main/java/ghissues/gh532/FooService.java create mode 100644 testapps/GHIssues/src/test/resources/scenarios/1407.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 22188c973..72727dccd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # ActFramework Change Log **1.9.2** +* Act-test: It shall not prepend url context when specified url starts from `http` #1427 +* packaging project stuck when ehcache has been added into project dependency #1399 +* @Before priority BUG #1407 * Add "The Wall of Coding Wisdoms" into default Zen list #1388 * Response content type get overridden - case 2 #1387 * Response content type get overridden #1386 diff --git a/README.md b/README.md index 30433616a..a91dde081 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ mvn archetype:generate -DarchetypeGroupId=org.actframework -DarchetypeArtifactId - **[Powerful view architecture with multiple render engine support](http://actframework.org/doc/templating.md)** -- **[An unbelievable automate testing framework that never presented in any other MVC frameworks](https://thinking.studio/blog/declarative-testing-with-act-framework/)** +- **[An unbelievable automate testing framework that never presented in any other MVC frameworks](https://www.youtube.com/watch?v=_UyfsdY4pSU&t=783s)** - **Commonly used tools** diff --git a/legacy-testapp/pom.xml b/legacy-testapp/pom.xml index 39ebf2069..3f646430e 100644 --- a/legacy-testapp/pom.xml +++ b/legacy-testapp/pom.xml @@ -75,7 +75,7 @@ UTF-8 UTF-8 - 1.9.1-SNAPSHOT + 1.9.2-SNAPSHOT [0.16.0, 2.0.0) 1.10.0 testapp.TestApp diff --git a/legacy-testapp/run.sh b/legacy-testapp/run.sh index aadf7eecf..12820c4b8 100755 --- a/legacy-testapp/run.sh +++ b/legacy-testapp/run.sh @@ -1,5 +1,5 @@ #!/bin/sh -mvn2 clean package +mvn -Dmaven.test.skip=true clean package cd target/dist unzip *.zip ./start & diff --git a/pom.xml b/pom.xml index 1062be863..dbaac77d6 100644 --- a/pom.xml +++ b/pom.xml @@ -68,8 +68,8 @@ 4.7.2 - 1.26.2 - 1.8.1 + 1.30.0 + 1.8.2 1.13.2 1.13.4 1.13.3 diff --git a/src/main/java/act/apidoc/Endpoint.java b/src/main/java/act/apidoc/Endpoint.java index bbadd9fb4..529254785 100644 --- a/src/main/java/act/apidoc/Endpoint.java +++ b/src/main/java/act/apidoc/Endpoint.java @@ -467,7 +467,7 @@ private void explore(RequestHandler handler) { } catch (Exception e) { // so we don't have an overwritten method, that's fine, just ignore the exception } - Map typeParamLookup = C.Map(); + Map typeParamLookup = C.newMap(); if (controllerClass.getGenericSuperclass() instanceof ParameterizedType) { typeParamLookup = Generics.buildTypeParamImplLookup(controllerClass); } @@ -528,9 +528,13 @@ private void exploreParamInfo(Method method, Map typeParamLookup, sample = resolver.resolve(info.defaultValue, info.beanSpec.rawType()); } if (H.Method.GET == this.httpMethod) { - String query = generateSampleQuery(info.beanSpec.withoutName(), typeParamLookup, info.bindName, new HashSet(), C.newList()); - if (S.notBlank(query)) { - sampleQuery.add(query); + try { + String query = generateSampleQuery(info.beanSpec.withoutName(), typeParamLookup, info.bindName, new HashSet(), C.newList()); + if (S.notBlank(query)) { + sampleQuery.add(query); + } + } catch (Exception e) { + LOGGER.warn("error generating sample query for method: %s", info.beanSpec); } } else { sampleData.put(info.bindName, sample); @@ -642,6 +646,8 @@ private String generateSampleJson(BeanSpec spec, Map typeParamLoo private String generateSampleQuery(BeanSpec spec, Map typeParamLookup, String bindName, Set typeChain, List nameChain) { Class type = spec.rawType(); + typeParamLookup = new HashMap<>(typeParamLookup); + Generics.buildTypeParamImplLookup(type, typeParamLookup); String specName = spec.name(); if (S.notBlank(specName)) { nameChain.add(specName); @@ -776,6 +782,12 @@ public static Object generateSampleData( return o; } Class classType = spec.rawType(); + if (type instanceof ParameterizedType) { + ParameterizedType ptype = (ParameterizedType) type; + Type[] actualTypeArguments = ptype.getActualTypeArguments(); + TypeVariable[] typeVariables = classType.getTypeParameters(); + Generics.buildTypeParamImplLookup("", actualTypeArguments, typeVariables, typeParamLookup); + } SampleDataProviderManager sampleDataProviderManager = Act.getInstance(SampleDataProviderManager.class); SampleData.Category anno = spec.getAnnotation(SampleData.Category.class); SampleDataCategory category = null != anno ? anno.value() : null; diff --git a/src/main/java/act/app/AppClassLoader.java b/src/main/java/act/app/AppClassLoader.java index d1a841b45..0daa65919 100644 --- a/src/main/java/act/app/AppClassLoader.java +++ b/src/main/java/act/app/AppClassLoader.java @@ -51,7 +51,6 @@ import java.io.*; import java.lang.annotation.Annotation; import java.net.*; -import java.nio.file.Files; import java.util.*; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @@ -515,7 +514,7 @@ private Class loadAppClass(String name, boolean resolve) throws ClassNotFound } return c; } catch (VerifyError e) { - File f = Files.createTempFile(name, ".class").toFile(); + File f = java.nio.file.Files.createTempFile(name, ".class").toFile(); IO.write(baNew, f); throw e; } diff --git a/src/main/java/act/controller/meta/InterceptorMethodMetaInfo.java b/src/main/java/act/controller/meta/InterceptorMethodMetaInfo.java index d80a9762e..2ccefedc3 100644 --- a/src/main/java/act/controller/meta/InterceptorMethodMetaInfo.java +++ b/src/main/java/act/controller/meta/InterceptorMethodMetaInfo.java @@ -22,6 +22,7 @@ import act.Constants; import act.handler.builtin.controller.Handler; +import org.osgl.mvc.annotation.Before; import org.osgl.util.C; import org.osgl.util.S; @@ -35,7 +36,7 @@ public class InterceptorMethodMetaInfo extends HandlerMethodMetaInfo whiteList = C.newSet(); private Set blackList = C.newSet(); - private Integer priority; + private int priority = 0; protected InterceptorMethodMetaInfo(InterceptorMethodMetaInfo copy, ControllerClassMetaInfo clsInfo) { super(copy, clsInfo); @@ -119,7 +120,7 @@ public String toString() { @Override protected S.Buffer toStrBuffer(S.Buffer sb) { S.Buffer prependix = S.newBuffer(); - if (null != priority) { + if (0 != priority) { prependix.append("p[") .append(priority).append("] "); } diff --git a/src/main/java/act/test/RequestBuilder.java b/src/main/java/act/test/RequestBuilder.java index 3cdcf3bf0..f7f813da4 100644 --- a/src/main/java/act/test/RequestBuilder.java +++ b/src/main/java/act/test/RequestBuilder.java @@ -100,7 +100,7 @@ class RequestBuilder { } String reqUrl = requestSpec.url; if (null != session) { - if (S.notBlank(session.scenario().urlContext) && !reqUrl.startsWith("/")) { + if (S.notBlank(session.scenario().urlContext) && !reqUrl.startsWith("/") && !reqUrl.startsWith("http")) { reqUrl = S.pathConcat(session.scenario().urlContext, '/', reqUrl); } } diff --git a/src/main/java/act/test/TestSession.java b/src/main/java/act/test/TestSession.java index 9f19c7786..918c27b62 100644 --- a/src/main/java/act/test/TestSession.java +++ b/src/main/java/act/test/TestSession.java @@ -312,9 +312,8 @@ String processStringSubstitution(String s) { buf.append(getVal(key, payload)); } n = s.indexOf("${", a); - a++; if (n < 0) { - buf.append(s.substring(a)); + buf.append(s.substring(a + 1)); return buf.toString(); } z = n; diff --git a/src/main/java/act/xio/undertow/UndertowCookieAdaptor.java b/src/main/java/act/xio/undertow/UndertowCookieAdaptor.java index 9d6ddb677..227c5f0a7 100644 --- a/src/main/java/act/xio/undertow/UndertowCookieAdaptor.java +++ b/src/main/java/act/xio/undertow/UndertowCookieAdaptor.java @@ -150,4 +150,31 @@ public Cookie setComment(String comment) { hc.comment(comment); return this; } + + // TODO - remove this method when we moved to Java 8 + @Override + public int compareTo(final Object other) { + final Cookie o = (Cookie) other; + int retVal = 0; + + // compare names + if (getName() == null && o.getName() != null) return -1; + if (getName() != null && o.getName() == null) return 1; + retVal = (getName() == null && o.getName() == null) ? 0 : getName().compareTo(o.getName()); + if (retVal != 0) return retVal; + + // compare paths + if (getPath() == null && o.getPath() != null) return -1; + if (getPath() != null && o.getPath() == null) return 1; + retVal = (getPath() == null && o.getPath() == null) ? 0 : getPath().compareTo(o.getPath()); + if (retVal != 0) return retVal; + + // compare domains + if (getDomain() == null && o.getDomain() != null) return -1; + if (getDomain() != null && o.getDomain() == null) return 1; + retVal = (getDomain() == null && o.getDomain() == null) ? 0 : getDomain().compareTo(o.getDomain()); + if (retVal != 0) return retVal; + + return 0; // equal + } } diff --git a/testapps/GHIssues/pom.xml b/testapps/GHIssues/pom.xml index ac0551c40..d9ba8cb88 100644 --- a/testapps/GHIssues/pom.xml +++ b/testapps/GHIssues/pom.xml @@ -22,16 +22,6 @@ - - org.osgl - osgl-tool - 1.26.2 - - - org.osgl - aaa-core - 1.10.0 - org.actframework act diff --git a/testapps/GHIssues/src/main/java/ghissues/Gh1407.java b/testapps/GHIssues/src/main/java/ghissues/Gh1407.java new file mode 100644 index 000000000..2c34df78e --- /dev/null +++ b/testapps/GHIssues/src/main/java/ghissues/Gh1407.java @@ -0,0 +1,30 @@ +package ghissues; + +import act.controller.annotation.UrlContext; +import org.osgl.mvc.annotation.Before; +import org.osgl.mvc.annotation.GetAction; + +@UrlContext("1407") +public class Gh1407 extends BaseController { + + @Before + public String before0() { + return "before0"; + } + + @Before(priority = -1) + public String before1() { + return "before1"; + } + + @Before(priority = 1) + public String before2() { + return "before2"; + } + + @GetAction + public String service() { + return "service"; + } + +} diff --git a/testapps/GHIssues/src/main/java/ghissues/gh532/Foo.java b/testapps/GHIssues/src/main/java/ghissues/gh532/Foo.java new file mode 100644 index 000000000..29bf8b152 --- /dev/null +++ b/testapps/GHIssues/src/main/java/ghissues/gh532/Foo.java @@ -0,0 +1,7 @@ +package ghissues.gh532; + +import java.util.List; + +public class Foo { + public List items; +} diff --git a/testapps/GHIssues/src/main/java/ghissues/gh532/FooService.java b/testapps/GHIssues/src/main/java/ghissues/gh532/FooService.java new file mode 100644 index 000000000..27be2f294 --- /dev/null +++ b/testapps/GHIssues/src/main/java/ghissues/gh532/FooService.java @@ -0,0 +1,12 @@ +package ghissues.gh532; + +import act.controller.annotation.UrlContext; +import ghissues.BaseController; +import org.osgl.mvc.annotation.GetAction; + +@UrlContext("532") +public class FooService extends BaseController { + @GetAction + public void test(Foo foo) { + } +} diff --git a/testapps/GHIssues/src/test/resources/scenarios/1407.yml b/testapps/GHIssues/src/test/resources/scenarios/1407.yml new file mode 100644 index 000000000..5945d9f23 --- /dev/null +++ b/testapps/GHIssues/src/test/resources/scenarios/1407.yml @@ -0,0 +1,8 @@ +Scenario(1407): + description: "@Before priority BUG" + interactions: + - description: test + request: + get: 1407 + response: + result: before1 From 4503c8a08753bb39575673a9d79d6b24aeaaa80a Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sat, 26 Nov 2022 13:38:45 +1100 Subject: [PATCH 59/63] update CHANGELOG for 1.9.2 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72727dccd..d199ba896 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ **1.9.2** * Act-test: It shall not prepend url context when specified url starts from `http` #1427 +* 716a67d0 2020-10-13 | Bump junit from 4.11 to 4.13.1 in /legacy-testapp [dependabot[bot]] +* 3231c87e 2021-05-11 | update title of td to make all the paths are consistent [benstone] +* 3745329d 2021-05-10 | fix bug of url.context not show in e404 page [Benstone Zhang] +* ce255015 2021-05-10 | fix #1392: GetTimeTest failed for non-english locale [Benstone Zhang] +* 1b50ebd4 2022-06-17 | Bump fastjson from 1.2.75 to 1.2.83 [dependabot[bot]] +* b922637a 2022-11-25 | Bump undertow-core from 2.1.6.Final to 2.2.19.Final [dependabot[bot]] +* 8d51b646 2022-09-01 | Bump jsoup from 1.14.2 to 1.15.3 [dependabot[bot]] +* 92001dda 2022-09-15 | Bump snakeyaml from 1.26 to 1.31 in /legacy-testapp [dependabot[bot]] +* 686e89ea 2022-09-15 | Bump snakeyaml from 1.26 to 1.31 [dependabot[bot]] +* 0fbe8fc7 2022-11-19 | vuln-fix: Temporary File Information Disclosure [Jonathan Leitschuh] +* 40e0127e 2021-06-04 | Bump snakeyaml from 1.17 to 1.26 in /legacy-testapp [dependabot[bot]] +* 032d4efe 2021-08-24 | Bump undertow-core from 2.1.3.Final to 2.1.6.Final [dependabot[bot]] +* 2581faa1 2021-06-28 | fix index error when process string substitution [benstone] +* f0704ecb 2021-08-23 | Bump jsoup from 1.12.1 to 1.14.2 [dependabot[bot]] * packaging project stuck when ehcache has been added into project dependency #1399 * @Before priority BUG #1407 * Add "The Wall of Coding Wisdoms" into default Zen list #1388 From c4fe6d1b00ad0c5c81f62122e94dd090c761a288 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sat, 26 Nov 2022 14:25:43 +1100 Subject: [PATCH 60/63] [maven-release-plugin] prepare release act-1.9.2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dbaac77d6..f78117b31 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ org.actframework act jar - 1.9.2-SNAPSHOT + 1.9.2 ACT Framework The ACT full stack MVC framework From bdc2ada4bb730dd77c38f2ca7dbeffaa38f52903 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sat, 26 Nov 2022 14:25:49 +1100 Subject: [PATCH 61/63] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f78117b31..ab3ee4f18 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ org.actframework act jar - 1.9.2 + 1.9.3-SNAPSHOT ACT Framework The ACT full stack MVC framework From 8d3e1334a9b8564337a6f785f703bb50aaedb9a5 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sat, 26 Nov 2022 14:50:43 +1100 Subject: [PATCH 62/63] merge from 1.9 --- README.md | 4 ++-- src/main/java/act/test/TestSession.java | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0572976eb..133551e0d 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,14 @@ ## Install -Add `act-starter-parent` into into your pom.xml file +Add `act-starter-parent` into your pom.xml file ```xml org.actframework act-starter-parent 1.9.1.0 - A + ``` Or use maven archetype to start a new project: diff --git a/src/main/java/act/test/TestSession.java b/src/main/java/act/test/TestSession.java index 9f19c7786..918c27b62 100644 --- a/src/main/java/act/test/TestSession.java +++ b/src/main/java/act/test/TestSession.java @@ -312,9 +312,8 @@ String processStringSubstitution(String s) { buf.append(getVal(key, payload)); } n = s.indexOf("${", a); - a++; if (n < 0) { - buf.append(s.substring(a)); + buf.append(s.substring(a + 1)); return buf.toString(); } z = n; From b3a0b97f4354054bbe6d71d29eaadb5cf483dc3b Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Sat, 26 Nov 2022 17:30:33 +1100 Subject: [PATCH 63/63] Update README for act-1.9.2 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 133551e0d..4fe0c13eb 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Add `act-starter-parent` into your pom.xml file org.actframework act-starter-parent - 1.9.1.0 + 1.9.2.0 ``` @@ -28,13 +28,13 @@ mvn archetype:generate -B \ -DartifactId=helloworld \ -DarchetypeGroupId=org.actframework \ -DarchetypeArtifactId=archetype-quickstart \ - -DarchetypeVersion=1.9.1.0 + -DarchetypeVersion=1.9.2.0 ``` **tips** don't forget replace the `groupId`, `artifactId` and `appName` in the above script, or you can use interactive mode to generate your project: ``` -mvn archetype:generate -DarchetypeGroupId=org.actframework -DarchetypeArtifactId=archetype-quickstart -DarchetypeVersion=1.9.1.0 +mvn archetype:generate -DarchetypeGroupId=org.actframework -DarchetypeArtifactId=archetype-quickstart -DarchetypeVersion=1.9.2.0 ``` **Note** There are more ActFramework application archetypes for use. Please get them [here](ARCHETYPES.md).