From 2586128f76c2a55e858709e1a5c213df30a76c81 Mon Sep 17 00:00:00 2001 From: Peter Verhas Date: Fri, 6 Dec 2024 11:18:22 +0100 Subject: [PATCH] debugger stops at the end of the process and command line version exits --- README.adoc | 2 +- README.jrf | 2 +- RODMAP.adoc => ROADMAP.adoc | 0 RODMAP.adoc.jam => ROADMAP.adoc.jam | 2 +- documentation/macros/debug.adoc | 5 ++- documentation/macros/debug.adoc.jam | 5 ++- .../main/java/javax0/jamal/api/Processor.java | 8 +++-- jamal-cmd/pom.jam | 2 +- jamal-cmd/pom.xml | 4 +++ .../main/java/javax0/jamal/cmd/JamalMain.java | 9 +++-- .../java/javax0/jamal/cmd/TestJamalMain.java | 10 ++++++ .../jamal/debugger/HttpServerDebugger.java | 32 ++++++++++++------ .../javax0/jamal/debugger/JsonConverter.java | 2 +- .../engine/debugger/DebuggerFactory.java | 4 +-- .../services/javax0.jamal.api.Debugger | 1 - jamal-packaging/docker/README.adoc | 2 +- jamal-snippet/README.adoc | 2 +- jamal-sql/demodb.mv.db | Bin 24576 -> 24576 bytes jamal-test/TEST_PLAYGROUND.adoc | 7 ++-- .../java/javax0/jamal/tools/NullDebugger.java | 5 ++- jamal-tools/src/main/java/module-info.java | 2 -- .../src/test/resources/demoConverted.docx | Bin 12792 -> 12792 bytes .../test/resources/includetestConverted.docx | Bin 34572 -> 34572 bytes .../src/test/resources/pictureConverted.docx | Bin 21869 -> 21869 bytes .../src/test/resources/sampleConverted.docx | Bin 40810 -> 40815 bytes jamal.sh | 1 + usage.txt | 2 +- 27 files changed, 74 insertions(+), 35 deletions(-) rename RODMAP.adoc => ROADMAP.adoc (100%) rename RODMAP.adoc.jam => ROADMAP.adoc.jam (99%) diff --git a/README.adoc b/README.adoc index 7b9e57ca2..0676987af 100644 --- a/README.adoc +++ b/README.adoc @@ -135,7 +135,7 @@ Usage: jamal [options] input output -close= the macro closing string -T7 use {% and %} as macro opening and closing -depth= directory traversal depth, default is infinite - -debug= type:port, usually http:8080 + -debug= type:port, http:8080 by default when the value is skipped -include= file name regex pattern to include into the processing -exclude= file name regex pattern to exclude from the processing -source= source directory to start the processing diff --git a/README.jrf b/README.jrf index 9688d24c5..64ac134a5 100644 --- a/README.jrf +++ b/README.jrf @@ -1,5 +1,5 @@ # This is a Jamal reference file containing serialized base64 encoded macros -# Created: 2024-11-19 15:01:30 +0100 +# Created: 2024-12-06 11:05:02 +0100 # id|openStr|closeStr|verbatim|tailParameter|pure|content|parameters # TOC VE9D|eyU=|JX0=|0|0|0|Ci4gPDxJbnN0YWxsYXRpb24+PgouIDw8R1M+PgouIDw8Q29uZmlndXJhdGlvbj4+Ci4gPDxGZWF0dXJlcz4+Ci4gPDxDb250cmlidXRpbmc+PgouIDw8RG9jdW1lbnRhdGlvbj4+Ci4gPDxMaWNlbnNlPj4KLiA8PENoYW5nZWxvZz4+Ci4gPDxSb2FkbWFwPj4KLiA8PFN1cHBvcnQ+PgouIDw8RkFRPj4KLiA8PE1haW50ZW5hbmNlPj4=| diff --git a/RODMAP.adoc b/ROADMAP.adoc similarity index 100% rename from RODMAP.adoc rename to ROADMAP.adoc diff --git a/RODMAP.adoc.jam b/ROADMAP.adoc.jam similarity index 99% rename from RODMAP.adoc.jam rename to ROADMAP.adoc.jam index 6b410f491..211c20ebf 100644 --- a/RODMAP.adoc.jam +++ b/ROADMAP.adoc.jam @@ -1,5 +1,5 @@ = JAMAL ROADMAP -{%@define a=1%} + Rudimentary description of features that are to be developed in the future. The list is not listed in order of priority, and the list is not a promise or guarantee. If you feel that there is some feature here missing, then open a GitHub ticket and suggest the missing feature. diff --git a/documentation/macros/debug.adoc b/documentation/macros/debug.adoc index 01850ec18..285192825 100644 --- a/documentation/macros/debug.adoc +++ b/documentation/macros/debug.adoc @@ -14,7 +14,7 @@ The macro has the following syntax: .Jamal source [source] ---- -{@debug on/off using="..."} +{@debug [on/off using="..."]} ---- It is important to note, it will only work if the debugger is on the module path or on the classpath. @@ -27,6 +27,9 @@ The macro has the following options: * `using` (aliases `debugger`, `selector`) can specify the debugger connection string. This is the same connection string that you can use in the environment variable `JAMAL_DEBUG` or system property. ++ +Currently, the only implemented debugger is the one using HTTP, and the connection string is `http:8080` or whatever port instead of 8080 you want to use. + + You can switch off and on the debugger inside the input using the options `on` and `off`. diff --git a/documentation/macros/debug.adoc.jam b/documentation/macros/debug.adoc.jam index 7cad1f47c..ec9a933c5 100644 --- a/documentation/macros/debug.adoc.jam +++ b/documentation/macros/debug.adoc.jam @@ -9,7 +9,7 @@ It is an extra way to start the debugger in case setting an environment variable The macro has the following syntax: {%sample/ -{@debug on/off using="..."} +{@debug [on/off using="..."]} %} It is important to note, it will only work if the debugger is on the module path or on the classpath. @@ -22,6 +22,9 @@ The macro has the following options: * `using` (aliases `debugger`, `selector`) can specify the debugger connection string. This is the same connection string that you can use in the environment variable {%JAMAL_DEBUG_ENV%} or system property. ++ +Currently, the only implemented debugger is the one using HTTP, and the connection string is `http:8080` or whatever port instead of 8080 you want to use. + + You can switch off and on the debugger inside the input using the options `on` and `off`. diff --git a/jamal-api/src/main/java/javax0/jamal/api/Processor.java b/jamal-api/src/main/java/javax0/jamal/api/Processor.java index 30d29e421..a33df2c4b 100644 --- a/jamal-api/src/main/java/javax0/jamal/api/Processor.java +++ b/jamal-api/src/main/java/javax0/jamal/api/Processor.java @@ -383,8 +383,12 @@ interface FileReader { * Tries to read the file, decides on redirect or do nothing. * * @param fileName the original name of the file - * @return the structure containing the result, which is nothing, the final name of the file or the content of - * the file + * @return the structure containing the result, which is + *
    + *
  • nothing, + *
  • the final name of the file, or + *
  • the content of the file + *
*/ IOHookResult read(final String fileName); diff --git a/jamal-cmd/pom.jam b/jamal-cmd/pom.jam index 238b233a1..8e5ac41d1 100644 --- a/jamal-cmd/pom.jam +++ b/jamal-cmd/pom.jam @@ -36,7 +36,7 @@ } {dependencies# - {#for MODULE in ({modules:DEFAULT_JAMAL_MODULES},word)= + {#for MODULE in ({modules:DEFAULT_JAMAL_MODULES},word,{modules:DEBUG})= {dependency|{GROUPID}|jamal-MODULE}} {dependency :{GROUPID}:jamal-testsupport} {#for MODULE in (api,engine)= diff --git a/jamal-cmd/pom.xml b/jamal-cmd/pom.xml index fbeff5e39..bc84948f4 100644 --- a/jamal-cmd/pom.xml +++ b/jamal-cmd/pom.xml @@ -140,6 +140,10 @@ com.javax0.jamal jamal-word + + com.javax0.jamal + jamal-debug + com.javax0.jamal jamal-testsupport diff --git a/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java b/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java index e91c16321..1db44c907 100644 --- a/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java +++ b/jamal-cmd/src/main/java/javax0/jamal/cmd/JamalMain.java @@ -81,7 +81,7 @@ public static void main(String[] args) { " -close= the macro closing string\n" + " -T7 use {% and %} as macro opening and closing\n" + " -depth= directory traversal depth, default is infinite\n" + - " -debug= type:port, usually http:8080\n" + + " -debug= type:port, http:8080 by default when the value is skipped\n" + " -include= file name regex pattern to include into the processing\n" + " -exclude= file name regex pattern to exclude from the processing\n" + " -source= source directory to start the processing\n" + @@ -98,7 +98,12 @@ public static void main(String[] args) { return; } if (params.get("debug").isPresent()) { - EnvironmentVariables.setenv(EnvironmentVariables.JAMAL_DEBUG_ENV, params.get("debug").get()); + final var value = params.get("debug").get(); + if( "true".equals(value) || value.isEmpty() ){ + EnvironmentVariables.setenv(EnvironmentVariables.JAMAL_DEBUG_ENV, "http:8080"); + } else { + EnvironmentVariables.setenv(EnvironmentVariables.JAMAL_DEBUG_ENV, value); + } } if (Arrays.stream("include,exclude,source,target,from,to,depth".split(",")).map(params::get).anyMatch(Optional::isPresent)) { final var sourceDirectory = params.get("source").orElse("."); diff --git a/jamal-cmd/src/test/java/javax0/jamal/cmd/TestJamalMain.java b/jamal-cmd/src/test/java/javax0/jamal/cmd/TestJamalMain.java index 08d537906..c27c3f998 100644 --- a/jamal-cmd/src/test/java/javax0/jamal/cmd/TestJamalMain.java +++ b/jamal-cmd/src/test/java/javax0/jamal/cmd/TestJamalMain.java @@ -72,6 +72,7 @@ public void testConvertMultipleFiles() { () -> Assertions.assertTrue(Files.exists(Paths.get("target/test-classes/test3"))) ); } + @Test @DisplayName("Command line converts a single docx file") public void testConvertSingleDocFile() { @@ -80,4 +81,13 @@ public void testConvertSingleDocFile() { () -> Assertions.assertTrue(Files.exists(Paths.get("target/test-classes/test1.docx"))) ); } + + @DisplayName("AdHoc test to support debugging") + public void testAdHocTest() { + final var out = jamal("-debug=", "../jamal-test/TEST_PLAYGROUND.md.jam", "../jamal-test/TEST_PLAYGROUND.markdown").replaceAll("\\\\", "/"); + Assertions.assertAll( + () -> Assertions.assertTrue(Files.exists(Paths.get("target/test-classes/test1.docx"))) + ); + } + } diff --git a/jamal-debug/src/main/java/javax0/jamal/debugger/HttpServerDebugger.java b/jamal-debug/src/main/java/javax0/jamal/debugger/HttpServerDebugger.java index 9c7004f4b..56a1ccd6f 100644 --- a/jamal-debug/src/main/java/javax0/jamal/debugger/HttpServerDebugger.java +++ b/jamal-debug/src/main/java/javax0/jamal/debugger/HttpServerDebugger.java @@ -15,6 +15,12 @@ import static java.net.HttpURLConnection.*; +/** + * Implementation of the {@link Debugger} interface using an HTTP server to interact with + * a debugging client. This debugger allows controlling the execution of a Jamal processor + * via HTTP requests, enabling features like stepping through macros, viewing internal + * states, and setting breakpoints. + */ public class HttpServerDebugger implements Debugger, AutoCloseable { private static final String MIME_PLAIN = "text/plain"; public static final String MIME_APPLICATION_JSON = "application/json"; @@ -25,6 +31,10 @@ private enum Method { GET, POST } + /** + * Enum representing the available debugger commands, their corresponding URL endpoints, + * and the HTTP method required to invoke them. + */ private enum Command { ALL("all", Method.GET), VERSION("version", Method.GET), @@ -53,7 +63,7 @@ private enum Command { } /** - * The thread that manages an HTTP request utilizes this queue to dispatch a task to the Jamal main thread. + * The thread that manages an HTTP request uses this queue to dispatch a task to the Jamal main thread. *

* Given that this server is not designed for heavy-duty use, the queue size is limited to one. * There is no need to increase this capacity, as the server is intended to handle only one client, with each @@ -96,8 +106,8 @@ boolean isCancelled() { } /** - * After the debugger was done it may wait for acknowledgement. For example asking the debugger to quit or run - * may result the main Jamal thread to finish before the http server thread services the client sending the + * After the debugger was done, it may wait for acknowledgement. For example, asking the debugger to quit or run + * may result in the main Jamal thread to finish before the http server thread services the client sending the * response. In that case the client would not get the response. To avoid that these commands call this {@code * #waitForAck()} method that will wait until the other thread invokes {@link #acknowledge()}. That is called by * the HTTP server when the content was sent to the client and the channel was closed. @@ -113,7 +123,7 @@ void waitForAck() { /** * The web service thread will call this method to wait for the debugger thread to call {@link #done()}. The * method {@link #done()} is invoked when the debugger has finished the processing, put all the result into the - * task and the http server can serve the client with this information. + * task, and the http server can serve the client with this information. * * @throws InterruptedException if the thread was interrupted */ @@ -209,7 +219,7 @@ private void addToResponse(Task task, Map response, Command comm private void handle() { if (state == RunState.RUN && handleState.equals("BEFORE")) { for (final var breakpoint : breakpoints) { - if (breakpoint != null && breakpoint.length() > 0 && macros.contains(breakpoint)) { + if (breakpoint != null && !breakpoint.isEmpty() && macros.contains(breakpoint)) { state = RunState.STEP_IN; break; } @@ -454,6 +464,7 @@ public int affinity(String s) { } private HttpServer server; + private final ExecutorService executor = Executors.newSingleThreadExecutor(); private final Properties mimeTypes = new Properties(); @Override @@ -483,7 +494,7 @@ public void init(Debugger.Stub stub) throws Exception { createContext(server, Command.STEP_OUT); createContext(server, Command.QUIT); server.createContext("/client", e -> { - if (client == null || client.length() == 0) { + if (client == null || client.isEmpty()) { respond(e, HTTP_OK, MIME_PLAIN, e.getRemoteAddress().getHostString()); } else { respond(e, HTTP_NOT_FOUND, MIME_PLAIN, "404"); @@ -491,18 +502,19 @@ public void init(Debugger.Stub stub) throws Exception { } ); createStaticContext(server); - server.setExecutor(Executors.newSingleThreadExecutor()); + server.setExecutor(executor); server.start(); } @Override public void close() { server.stop(1); + executor.shutdownNow(); } private void createStaticContext(HttpServer server) { server.createContext("/", (e) -> { - if (client != null && client.length() > 0 && !Objects.equals(e.getRemoteAddress().getHostString(), client)) { + if (client != null && !client.isEmpty() && !Objects.equals(e.getRemoteAddress().getHostString(), client)) { respond(e, HTTP_UNAUTHORIZED, MIME_PLAIN, ""); return; } @@ -511,7 +523,7 @@ private void createStaticContext(HttpServer server) { return; } var file = e.getRequestURI().toString().substring(1); - if (file.length() == 0) { + if (file.isEmpty()) { file = "index.html"; } final var extensionStart = file.lastIndexOf('.'); @@ -550,7 +562,7 @@ private void createContext(HttpServer server, Command command) { respond(e, HTTP_NOT_FOUND, MIME_PLAIN, ""); return; } - if (client != null && client.length() > 0 && !Objects.equals(e.getRemoteAddress().getHostString(), client)) { + if (client != null && !client.isEmpty() && !Objects.equals(e.getRemoteAddress().getHostString(), client)) { respond(e, HTTP_UNAUTHORIZED, MIME_PLAIN, ""); return; } diff --git a/jamal-debug/src/main/java/javax0/jamal/debugger/JsonConverter.java b/jamal-debug/src/main/java/javax0/jamal/debugger/JsonConverter.java index cbda00bec..d87407431 100644 --- a/jamal-debug/src/main/java/javax0/jamal/debugger/JsonConverter.java +++ b/jamal-debug/src/main/java/javax0/jamal/debugger/JsonConverter.java @@ -22,7 +22,7 @@ public class JsonConverter { *

* When you are developing a library, you should consider the same costs. However, there is a multiplication factor * when you think of the library version change and security screening and follow-up in this case. This part of the - * cost, which uses an external library heavier, should be multiplied by the number of installation users will + * cost, which uses an external library heavily, should be multiplied by the number of installation users will * utilize your library. It means that you should consider using an external library *

  • if you intend to use a lot of features (the development is not 30min), *
  • you expect the library to be highly stable, rarely changing, not even for security reasons, diff --git a/jamal-engine/src/main/java/javax0/jamal/engine/debugger/DebuggerFactory.java b/jamal-engine/src/main/java/javax0/jamal/engine/debugger/DebuggerFactory.java index 473059f4f..57f3960f1 100644 --- a/jamal-engine/src/main/java/javax0/jamal/engine/debugger/DebuggerFactory.java +++ b/jamal-engine/src/main/java/javax0/jamal/engine/debugger/DebuggerFactory.java @@ -37,11 +37,9 @@ public class DebuggerFactory { */ public static Debugger build(Processor processor) { final var s = EnvironmentVariables.getenv(EnvironmentVariables.JAMAL_DEBUG_ENV).orElse(""); - if (s.length() == 0) { + if (s.isEmpty()) { return new ProxyDebugger(); } - int min = Integer.MAX_VALUE; - boolean unique = true; Debugger selected = MinimumAffinityDebuggerSelector.select(Debugger.getInstances(), s); try { if (processor.getDebuggerStub().isPresent()) { diff --git a/jamal-engine/src/main/resources/META-INF/services/javax0.jamal.api.Debugger b/jamal-engine/src/main/resources/META-INF/services/javax0.jamal.api.Debugger index e47eec04c..e69de29bb 100644 --- a/jamal-engine/src/main/resources/META-INF/services/javax0.jamal.api.Debugger +++ b/jamal-engine/src/main/resources/META-INF/services/javax0.jamal.api.Debugger @@ -1 +0,0 @@ -javax0.jamal.tools.NullDebugger \ No newline at end of file diff --git a/jamal-packaging/docker/README.adoc b/jamal-packaging/docker/README.adoc index c4e89302d..bc302058b 100644 --- a/jamal-packaging/docker/README.adoc +++ b/jamal-packaging/docker/README.adoc @@ -43,6 +43,6 @@ The final step is to display how to push the container to Docker Hub. To execute Jamal from the container, you should execut ethe command - docker run --rm -v $(pwd):/workspace verhas/jamal:2.6.1-SNAPSHOT jamal_command_line_arguments + docker run --rm -v $(pwd):/workspace verhas/jamal:2.8.2-SNAPSHOT jamal_command_line_arguments to work on files that are in the current working directory. \ No newline at end of file diff --git a/jamal-snippet/README.adoc b/jamal-snippet/README.adoc index 2c3861f35..bd03c9c67 100644 --- a/jamal-snippet/README.adoc +++ b/jamal-snippet/README.adoc @@ -3816,7 +3816,7 @@ will result in the output .output [source] ---- -2024-11-19 15:01:30 +2024-12-06 11:05:03 ---- diff --git a/jamal-sql/demodb.mv.db b/jamal-sql/demodb.mv.db index 8fce0f4442e6b56e67bbc9c222c4a577409c6129..23514d8a01f4fcc6def42b9dc92813b2f50e7944 100644 GIT binary patch literal 24576 zcmeHO&u`nv6($`!X1vW71zNPd6pU;qHoywx3}=SqX=PixRx8VaC8y4!g)tc zWZ8{-+Fp9@51`lP)LYSB7T5y4wD$sw9{MNr@91zyN<&$x?Icd(bOe|~QZt;#Z$>lU zd*AbB0IaavkDdi6E87RZV1Z-XwiP`+={*Y^6ccJiT}FF>V?_f-hb#^pFL7fM+BU^j z(jOesVF0aDHaI@$^J=0=(q+TwDH{ZY0EZyV7Buxy2q**;0tx|zfI>hapb$_9CR3V@cPzWdl6aoqXg@8gpA)pXY2q**;0&f$6vB;0DE=wi; zBl?6L^K5`a`aEFR=H*d1y;24MwtDP& znieqZM?vf-=9~GXSp>U3`?dDPKlMABK67h!?)JQKN4wV;^4^?^D8Qm9;F2iZWl^B} zqQDPCK~_ZJt%}0ew7IVzztCrXpc#&hqX_#ZD?a;s^c03jn1N%6!fddR~H$q;7 z4a^`4Bgk7ZMq`E}11FA8BgZ!g@}ZqzWOxY$2-xm?>^h0(V1v<+*?_o4;=06keQ&Wp zcv5`|s)wh?!~TF(2@E{?g`tVL)tkzVye#D!N-~yi{bO?qb%Eo#bQ9x!C3l~ zMtr2smM1Fnf!pc-ycn{g*6dui&P>)G@+Vc-&W5Zu7|^q#)nx|y8jPH|l^S`O&Q+ba zGZW2;$t9*sv)_Aim6-x29>Qm6vmdtks7Cl;8>-NJPmaqZqMQkaZ+&{cblPxx+ zqPC{#Uw!_)nYp=ai_q?w_xIZMj=8>5uXXDCYrBo+h6#XMF)MdLcGKK#*LTdur)F!r zW7hW??M~aQRLpj**)bnHFgI)M&9tm-Y&BYorg`@?Z?;}r->h$#o!VNnZdM-dt~DF$ zm1^ZjwXIrnV|#sftKRC=I*sjCWo04V0xOM;irHv&>YwrM(!N@|&8C%o)!yE!?|15Z zor<}>S=*_tcX*vgwVlU})@LgKq1A=eCG+0hoxJOZJB=;=rTOFfW2xu-?moY}?^Mj~ zmh{~;t5Snjm(At7zts7=@(wTYDjbFlbA7wj?(Ed~yGT8ZZ>F6~7OseX_?vIk_oVt| zYc*|V?EG7oIPa(eafITC#1R|mea=Vh;)E0@o~S^?F+2Bf_vj(3?teoRd`hKr z^rPZ}&$H1vpKIR{_xnez*BQ{>F<(k~F5_|5bV$Q4tJ?Af{HCZsWQRw5>hfoOEUr&_ zalhGrQgzCgKv)v&i%x>cPVT2ogS->#89NJ#-Pt;&-Jl>0%c2^84c^=NTE(^RsT9Tm}Z^a@iNC*>+&T9wtzfDtfL`pb#W=!H1^qE^8{#A_FnCqpM6 zy_Y{s2fD9g-P56tX446xle7>AkI$>Gc2{OKL;FZD-fEho>PY8MI!E(|d>yGC#J5w* zTXnJmWCgk-Zl)c4sgK#SlV{O_5{q`N?!hU0C>V9hq@M?rGwSr-7C)cDts_@(YXD`xuWeoe;(L_>!CDVeR`bIRCMJ#SdR-TJ7I_U;9MUzxT#sfzY+k&WhSB&0HBb21Hrt<|q3+74`$MOCq*-3Ici`^`XCZC6w zGp}icQiP1jXsd}cUdaiXD-$&0*b}^x?>!e=Pcnk$Fv)s5CusSm#(TOVK}(64X8krJ z9sl_KjUpe)ScQN>Kp~(IPzWdl-U$Nd{cqX-_s0G|Vch=@uhIW6$I{$UwDP?FKRrfC zU{d0We&+vYQ86Bad`-W5)@HX^9;2^YT#I%LA;AAZe*cQ z7pR(C-C0c4P4!U-CirY~3ITy)5Ksu*bOgr!f8l@2{y!c2|Cr)1dGr4Ne*tqG8#4d^ literal 24576 zcmeHPO>f)C877@LX1q=I(mnK2FtVM*fGW%kIl~X2KxA9HRx8VaB?nFyTZ13N#E2{z zvh2n^Z7)TOUWy)i?y0u|y%g92J@wklqK5+g1N|L+IV7c_?8F}%XOrv*Fo!do;rsI8 zaOQbG;B}u=!`>iz;nS?_?ERAa7$H=Ro*(sJ_?SkFRHGgb`aZ5kLmrHH>|-~vV<$u? zVAW(W+z&>+RXygz!@U7?6GM_7A4Sjk&?gLW+qU9)P5l%C3ITy)5Kssx1QY@a z0fm4sD@Y3fDL3!Xa8uRLKFc|sN!Hx^r0f>ZNOsb>3eePR{Vo z+^^4HrfC7ALFC6?V!oLlWD(4M{q)D$%nvmKBNj!L<<4P?a1=!bc4E(AE;oo31QxS` zIpW3KrjcRAUWBcX8aDJN4s@~Y&|-*%hV8{xIhwG?)`(m&cC5JeDAW zi2-_3>PF09+@fJ*!6?pyn6t=W3HE{rdxk?j3nh#iZW0hmkUbaMIB_vEco1?#9NS22 z+d;PHE)0gxYR^e+|M+k;81h;i*4jtC-jkqr#MgpR&^LM@t8kC&5 zkt%r+;i}KunTh7qqtX4h=&G&|jnS*e(vdaG+bcwnyAJL_p#U)yN57fkccaXxIdzPjF6GrRSb zR>Q13-d<@nS1Yy3PwE@>*4pOk_C}-Kt#_N7?aIUXbhoNB*D7YS-EDjZ;!;`d?N+Or zUFvLZGZkU9WG|SG&;XNqy^Sv;EmaLh17S@}ha~&Q>n^@m6yKE}B1WJe4Hp zt-H{=i!0`4Te^0ZR;fbEOXkv@U+M6yAn*c@0x+zZtDEgkcdHK1B1xDurotr+9|}3} zvykeCcLZ zp0Js3Kxt;C9i1LpaG8o2I(~%HgQ-*Q0*Rp_Aym3Qb(S*)#=x8*FK1KZ2Lkv-uY%Z! z$1ZqOhED$WUVSs2=$_7WSGRO}Go2v1lNND$;4rVg>S{MNL;FZD-Wni5J?T7@&f~d# zSe$Bm@vW5d)^Jvktf03=V=CZp`h-1uc@`}xv1q&6+dJlu1*1-x^h-YgMxC~8!1)>6 zn%RO|6Dvj~ZjHR^QUB-=GH)kjJ8P(qWboq>1@{E^4jft?MA6Yf(2q`hl*np_x!P_? zZFq<&wHf3CzfSEaRU1XbE1Lv3x{BJNP@9I9thObq9p`F$CAINo)pi8hh(sPMp-tFT z)Q*MPHdsXx+E~YTCpHtjS2C#z!ILTukcTE!g1F0Ik^NHBs(*w{@{y+h>G#?Xj=t1p z?*1CuA89iS|ArE#_TRHoRMg?ULSV9j6!!P=B#Rzw=y4Xk8`%l67R?T+8}A8q z0BR;Jckd*1__M?>dCqufNo}Z&iJB!=?9^jh5H%Ohv(@`z-rKVXWg@TXupi~lT#4df z_aBm;Nv3JGnU|wTAB`w94;f%K$C*zes(CiXHv*Ia&27Ax>+9w%7!(7rHhXA)pXY2q**;0t$iGBXHXOmh6AvZ)5u(BN}=hv%aDE zJT+Xh|AC`PgxD5rGWAxTw*Oz@qlCV)?l`mmsUTh8gPf9l)oK?1pHcCD75{%X^BS%p zw65a+Dx>8J**x!2{QqYv{{LRa|37}?@qhh)+qZ9MbFvdwa+e$YSr$4swwuwtQh8l)-Iwk{d4Iag26 zB6aye{6=<~ku0h? + * Note that this implementation is used when there is no other debugger configured, and it is NOT provided as a + * service via the service loader mechanism. If you do so it will throw an exception during the service loading. */ public class NullDebugger implements Debugger { @Override @@ -28,7 +31,7 @@ public void close() { @Override public int affinity(String s) { - return Integer.MAX_VALUE-1; + throw new RuntimeException("This debugger must not be included in the META-INF list or as a service."); } @Override diff --git a/jamal-tools/src/main/java/module-info.java b/jamal-tools/src/main/java/module-info.java index bb03f8dd0..3040a92c9 100644 --- a/jamal-tools/src/main/java/module-info.java +++ b/jamal-tools/src/main/java/module-info.java @@ -2,7 +2,6 @@ import javax0.jamal.api.ResourceReader; import javax0.jamal.tools.HttpsInput; import javax0.jamal.tools.ResourceInput; -import javax0.jamal.tools.NullDebugger; module jamal.tools { uses ResourceReader; @@ -11,6 +10,5 @@ exports javax0.jamal.tools.param; requires java.scripting; requires levenshtein; - provides Debugger with NullDebugger; provides ResourceReader with ResourceInput, HttpsInput; } \ No newline at end of file diff --git a/jamal-word/src/test/resources/demoConverted.docx b/jamal-word/src/test/resources/demoConverted.docx index 13d2eed54f995acf260a61770c48c6e987ae194e..01654f75fdeb61c6b936c4401bcf339dd3a03834 100644 GIT binary patch delta 216 zcmey7{3Dq+z?+#xgn@&DgJEw(+eY3!jLblK^BG2E2;&n|JA_fgG6~F>EXZ~OtmF=x z2{)J_EMy8%;w?N4!gwOGlo>45BLOwfTk1G3SVUCgCL4$``J@fMy2VLTC8$_$q3k${@#Ep?n1EF!9LlMTd}{87&iOdIK&f$400YcRc1 o-v&&-(1*xt8bJ6N2JT?-O$N4L`V*8kGK9z%8d`zH*BN>N0E5X%wEzGB diff --git a/jamal-word/src/test/resources/includetestConverted.docx b/jamal-word/src/test/resources/includetestConverted.docx index 255066f1af4a2f92e4577aa91c107b7ee9a119f8..ace29e79212187e6fe4926c0b2f557dc5b87c53c 100644 GIT binary patch delta 221 zcmeC_W9sQ+;tlX-W)WfF;NW1`8_~9rcLpOfklwt4Q4+#9!t@Qo*vnD~VHmPSae~$K z@q0i-ZVIR{fkZY5Uk(A$lMUI#Hor-K&jwa@FK-tQm@&KhIz*(jsROKWQi~l}xnqkN wn67HE2GcuQY{2w)C~em24(2zs+Jfl=t&U)tr46Faxy=e9-{t_O54U*&019JRga7~l delta 221 zcmeC_W9sQ+;tlX-W)WfF;NV~gt0>;cJA;uKNN--jC<$R4VfqGP>}4s0FbvtEIKgWA z_&p#ZHw9FfKq8xjFNc8W$%brVo8P3rX9Fv{m$!=t%$Qw$9U@ZN)B)Bwsl^Vg+_A+B vOjos7gXtYDHemWYls0R12lE?RZNc<`R!1<+(gsoI+-3!lZ*u_Chub^>rw>pR diff --git a/jamal-word/src/test/resources/pictureConverted.docx b/jamal-word/src/test/resources/pictureConverted.docx index 0934f15dd55cb4008dfe2bb055d99682867300d9..4ceeb1d85f3fc3f959bd685375d8ff96791f03f4 100644 GIT binary patch delta 304 zcmaF6it+6#M&1B#W)=|!4h{~6y%B92dCxO41L@888T}y)L*~Cw25Sj~v4SlT!rXfkIe7!fEkBfu0urTdK*HtU-aRE zFz)$QLl`ms9bm@f=K*#gO_MbO&A@bGpf#ADA7}%n?*&5S<%1ynxFC11_=+G~F#RIP o5lrg@L-;wt5Ou4AtswHj4q#e4#2ZXkhJ=CXOCkPXS|!vI0G|qXJpcdz delta 304 zcmaF6it+6#M&1B#W)=|!4h{~6u!`c1yyqF2f%NA4jQ$XYA@g4-gS7<0SizPEVeoLY zaDWw076^feyb_$k1Qux&5tINkrs}w|f*E%Wnb^RLN9OlLE#*C8Tvy$vDSFZysn z825auA&eOR4lrZ#^8h=LrpX$CW?(uo&>Bq753~W(_W~jE@<9-OT#!3hd_|Bgn0^uD o2&Q#{A^e&E z1P%O}x!_H91%ufRKrLHO_b?WDI#1?Q`FLa=oF;d*&upxVHr_?+GT+&7E0E2ZXiRxg z=l`u-zqK#Qf9>hiwJ)rdp>o4*_ON-vn2y(Elv0RJRS4T3b{t)MG5!oi8je>3C0JE& zBgme)KNT%u=7-kWJ~a`L6dl`O)0{137>7|5JS2x559`hD#hBRJ0yAfpgL*un% zD??BJG78>RrJl(;U4c|Nsm};%ByeZ}w0aG_U@rnIwjjl`F4IBL{N$nSGjyZ|{v*7g zw)I9QaaeWZ`XcOCB%C>2!frd`}d(RXH4A_*3{UJCq0z?bOkhZdHeD?)#Rh?B8AYo+MLrp9J@1XLe*r~c%0FvX z0?5Z<-b~r-Mmg}#aF*U3$O^x$KEVebD583^AJU?gwv|_4l5&fp1A)|B|Kglyp=Mr- z&KZd`S@KYd96Ga+w-9tXOxPPM+s6tig3g;xJm*+9y=il_f5Zh-IOy%AcgqxC$|`Gj z`>HNNuYLIPblDwt(2+@0D`I`tqtcKY8y)&^S|Y4$mxGG#&T1i%dVSm)H^UX%)G1Ad z40@=_i^i>}0ipJq=&`EJ-lp%?ZTFhzxKl+-L4k-pXUz0&y`0SlCT`(xM^_vF(Z3up zdvkJPJ=u7xrW%&Sq2yN&$QJP%AY@NNsIrmeP>xdH+Ldn;$f`z1#DiO#L`J=HYzH!H zF{(wgwKeiJ(?Kv^5hhA})~$4#B4f*J@P-5mvojnfJz-9}cYjPp0^DwiAD~z24$Z-W zjah(F*NVgUICi@vT_Q`KI!;?6L_xBhHZ~t2Kp);p_$OtzCcwPlX_qv^6Fhe$;uxc? zjhb(1E?wMI5d?yfSi7BT{`T$y9Tz#V%zTnMedCofuu7{4-QndoJ!GtvwgS0=_py9G z>djyMQ+S}_mB0Dwj#tGa#B?y#yBd-7)uo2onh=`ye93{c)fbYqM3()iJUutJAl_Zl zhCSBwKC;(a-aO*Ov^;dVUz&EhRsaMTun)fgJb6<_EC2zPml3mLs)Hg5pB_CAT1cHY zN(Od?gTqaeu4Y~X01x8w)6A+Yy=j_}W^T=xr_4Sn|IUcy7BiLw_||=u9=mH9%G$XA zao1#BopaFeLNJMY;6iej_&wORq?*faNFw{)<~Gm>B!p= zC;d#Ni8C4&LQxKUHY+yEknCrBvv70G+s_?-@G|4|bODW!E3hd_N zJd-X3s?qjQx|!miE^DWlgOSxQC?&;YlwHdgbk0r0wZ-&sR1BV*g*Zy|ASLg>GW^?| z)pPo&Y@!3{G&0%1D(1(71p974x@4`i@qooR+i$e}=S!Ux3P01U+3DQ9^tpg@s+q2c zsr#g@GSUI6*y^TGl5|XS7=JD(8~#Z2@XUxzw&>zj+vc2=BAoqUD}CK>wR!V#=X1b- zBIO&Mhu=j3HT>K}kTSpdngi$xR!dP}_C~{7&G)vWTppRJy#+Do^eAQ z*qY4b(XT^d8*fpZORDN=-GWlXZK0n^3`{9eT20C{zyAte>3obmh&CI1 zR$05N_p%tX;@*3;j#+K5YGC_`xDxv~qX?Y7qksY}*Ir;&kNV()Du0ht-rM4oUYm$f z8^D3%!WMFuJJ{^1mqPZdgDrW~h<>VTID;OLs;>C(fS08V2D>^@4OHmbFuI6H#v|Hf zIa1WrDl6`l&3>nvy^Ha#*~eVHYC>{-sO!CjKSP_Y##)lR*MHIyR*> z1NCm{5dO1XDqbg6MEUvM9 z%GPMBGao6FLB@f@FQ6EUR)h(6H9(};X`Lx6e+`E_!m z4UfwY(ovAzdLcNn_7v^i;F#;N0OQ_-JYT~{7b<+N-F_C9!@;7RPp$Vp>sCwMRO_*P z$ZdbT7pkSHB>y-qC@OX>*4V`7NNCfLW6P4&~-mW00ip!BVBHJXjBoCIitSg!8Se~bSauMoG(hmY^u*vij z*geG`i(D6b5mCmJq$o~=kMErvAK(Ag2?8snc@)9y(;9Pu=d&@^JdR+@c|3~U&pog$0sN|nod5s; delta 2419 zcmY+GcRbbq7so&3%QY{eD5G)BuWt4ph1{Q%85tqrDz5EXmwS`4_f5*ZD6=wdw#=`H ztVH*^ZkKFw8+Nw)t?T#rJ^G!0p06|C=fC$^YGtOiGIN`o9AOavKp+rc6B<~_{g&y- zFIJP7gb&3E^ZtJY3z8wQ6THW&F|6avj5=rbz(YaeOgR*Ap5Q|B&&kqSpWVnluq#mb<;7+Zuhk!`kxWf>`e-u4el%) zF19O?6q!AJlYp(1YJayFVSw7q8~SBl<6{4V&8SJr-R-l*mE9?P+*GxwyVg z#g=`DCx;PA@t|Xx0y;(R2X`xTGt3?wpRap(#gtRnU3BFr^w_%RA>LT*Wn&=TYiSxP^wJom~QR{M_ z``t2HrGJPmV4zo0==r`lIaEveXPxE)$oK(yd1h#$xoOu=yrt>;4_&|gyn*j1J;(St z+;B}NTGrMAzLebTds&Z4ScM@8qhF7g@QwT&ZFF}~ji+pi9VO7ijPgCb5R1VZ9hDDw zHMdTxbQ7iuEgjj~h4azOQIAThJ_KK@%}J=5BWL$vbQjsR6ke)%I=^PCwb%TpKOyzk z>8y2u!VOcVcvGr-=?HILr}F!3Pulgzn_Uv->E{HJuwCYPgXMD#u)9VDp3Ahvok$Ok zajk~>xlNC+h!Z)>eWx*cX;Gs6%qPM7#Wg|Qmlr1Ys`j|I1Wz+!YDBIKV9=fv5xrM15G2Qy|vSCdn_8Wt*?9)}r! zNzMKFMR-MM@T>@*;yXV>eo0G#_}gc61mcZpa~SpMYWywGN}+hc4DaQDn6v4}L1XsQ ziH~oBinMtwL}^%g*n+`>L785jWEUe5*mLn|F^E1~Jp=XRyh5jxqKiU;{4vAlY`Rzo zS6ft^5P7O~onIhbUXee47_ z9TU6L1(A}`6qlS+Q@?q7K)P3&^EJqS!m{T~kgf>7ZGQR;@hF$09ll3k&=4A$`|QSA zT)1#AQ|cZu(HydY1>9l07eOiJ*}GrV-$-3hP5B^iM8@C!_IBp1`e|WWEl9eZjE_^# z`qIl^Im=Hr){gSXT#xcn)>WMCgq0glVzTqa-r0hp;Bi+@MVfzxT>E@sGLBcI9C{Hl zEHaRGD*d$B>r?JwF+0cHoPHFDuxP{!^*W^Oy4>qhzF*#BKw+Ok$POie+2`1^wN7VI z)Vk8silu#Bh`x*J%q#6kezS0CEf*SUD|h32q}Dx0PI5dbbwwokxtmO{1MxbBh^dc5 z@#*GCuVw(7=gwpl45cWh!y0Pwk}MnNB(*z321ZLXE-5L@qoG6FolHIa$_CT-7r4kh z&#zdBs$0%(?HCJzrR@nvd&1)89hlv^Z(qUM%7ewFHX@o6B%Z7W+#+}KqX)a#IKi81m6TfYCb{2kVI1L3QI$0VeEpTL+SygfQgwqDCd z?+XlWT?rk7d09)^-dhT^14%)HitRdGwFB%R5izK=Er>p)M{%@zd3$yYYypYoj((an z|AuqrC7$!qRLRDTfI(QGRIHLXObG&hX8TkH5?g)L3AL6aC8KK!omSSyj3B4UD*0LLhE%*Jp$T6OZ+zxC<`H6~G2F~L*q9(~Z%t?o= zw3I&A7EQgd77t2Wsn+d%1?&DtPGHS73EbQxejWa>-Czy#VeHJqWQc{783o+7~xB zVFSsJ*jeM*0H8w{0RHcas9t-}$i?{IUuBS486x3H+~M^gh|~QYz}nzc8BE1#F*tzJ zW{?YiNE5sv!_UAQF-XPhF({gIn7@$&WBA26It the macro closing string -T7 use {% and %} as macro opening and closing -depth= directory traversal depth, default is infinite - -debug= type:port, usually http:8080 + -debug= type:port, http:8080 by default when the value is skipped -include= file name regex pattern to include into the processing -exclude= file name regex pattern to exclude from the processing -source= source directory to start the processing