+ * If the command line is "@file", then take the argument from the contents of the file. + * If there is no "@file", return the function parameter string array object. + *
+ * The file format is: + *
+ * # Example arguments file
+ * ## Another comment
+ * --arg1
+ * --arg2 value
+ * --arg3=value
+ * # Use --arg= for an empty string value
+ * --empty=
+ * -q
+ *
+ * # Previous line ignored
+ * ## --notAnArgument
+ *
+ * @return The command line for argument and values.
+ */
+ public static String[] argsPrepare(String[] argv) {
+ List argsList = Arrays.asList(argv);
+ // Count!
+ List indirects = argsList.stream().filter(s->s.startsWith("@")).toList();
+ if ( indirects.isEmpty() )
+ return argv;
+ if ( indirects.size() > 1 )
+ throw new CmdException("Multiple arguments files");
+ if ( argsList.size() > 1 )
+ // @args and something else
+ throw new CmdException("Arguments file must be the only item on the command line");
+ String indirect = indirects.get(0);
+ String fn = indirect.substring(1);
+ try {
+ if ( fn.isEmpty() )
+ throw new CmdException("Empty arguments file name");
+ Path path = Path.of(fn);
+ if ( ! Files.exists(path) )
+ throw new CmdException("No such file: "+fn);
+ List lines = Files.readAllLines(path);
+ String[] args2 = toArgsArray(lines);
+ return args2;
+ } catch (NoSuchFileException ex) {
+ throw new CmdException("No such file: "+fn);
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ throw new CmdException("Failed to process args file: "+ex.getMessage());
+ }
+ }
+
+ /** Convert the lines of the file to argument/value pairs. */
+ private static String[] toArgsArray(List lines) {
+ // Each line is "--arg" or "--arg SPC value"
+ List outcome = new ArrayList<>();
+ boolean positionalsStarted = false;
+ for ( String s : lines ) {
+ s = s.strip();
+ if ( s.startsWith("#") )
+ // Comment
+ continue;
+ if ( s.isEmpty() )
+ continue;
+ if ( positionalsStarted ) {
+ outcome.add(s);
+ continue;
+ }
+
+ if ( s.startsWith("@") )
+ throw new CmdException("Argument file may not contain an argument file reference");
+ if ( ! s.startsWith("-") ) {
+ // positional
+ //throw new CmdException("Command line in file does not start with a '-': "+s);
+ positionalsStarted = true;
+ outcome.add(s);
+ continue;
+ }
+
+ // argument or argument and value
+ // Split on first space after argument, if any.
+ int idx = s.indexOf(' ');
+ if ( idx == -1 ) {
+ outcome.add(s.stripTrailing());
+ continue;
+ }
+
+ String a = s.substring(0,idx);
+ String v = s.substring(idx+1).strip();
+ outcome.add(a);
+ outcome.add(v);
+ }
+ return outcome.toArray(new String[outcome.size()]);
+ }
+}
diff --git a/jena-cmds/src/main/java/org/apache/jena/cmd/CmdArgModule.java b/jena-cmds/src/main/java/org/apache/jena/cmd/CmdArgModule.java
index bc13b9dde6e..545e601beee 100644
--- a/jena-cmds/src/main/java/org/apache/jena/cmd/CmdArgModule.java
+++ b/jena-cmds/src/main/java/org/apache/jena/cmd/CmdArgModule.java
@@ -23,7 +23,7 @@
public abstract class CmdArgModule extends CmdMain
{
- List modules = new ArrayList<>();
+ private List modules = new ArrayList<>();
protected CmdArgModule(String[] argv) {
super(argv);
diff --git a/jena-cmds/src/main/java/org/apache/jena/cmd/CmdGeneral.java b/jena-cmds/src/main/java/org/apache/jena/cmd/CmdGeneral.java
index f917302b71b..6054b7c63c2 100644
--- a/jena-cmds/src/main/java/org/apache/jena/cmd/CmdGeneral.java
+++ b/jena-cmds/src/main/java/org/apache/jena/cmd/CmdGeneral.java
@@ -27,7 +27,6 @@ public abstract class CmdGeneral extends CmdArgModule
{
protected ModGeneral modGeneral = new ModGeneral(this::printHelp);
protected ModVersion modVersion = new ModVersion(true);
- // Could be turned into a module but these are convenient as inherited flags
protected CmdGeneral(String[] argv) {
super(argv);
diff --git a/jena-cmds/src/main/java/org/apache/jena/cmd/CmdLineArgs.java b/jena-cmds/src/main/java/org/apache/jena/cmd/CmdLineArgs.java
index 1d42c4eff00..73192f5310d 100644
--- a/jena-cmds/src/main/java/org/apache/jena/cmd/CmdLineArgs.java
+++ b/jena-cmds/src/main/java/org/apache/jena/cmd/CmdLineArgs.java
@@ -50,7 +50,7 @@ public void process() throws IllegalArgumentException {
// ---- Setting the ArgDecls
- /** Add an argument to those to be accepted on the command line.
+ /** Add an argument declaration sto those to be accepted on the command line.
* @param argName Name
* @param hasValue True if the command takes a (string) value
* @return The command line processor object
@@ -59,7 +59,7 @@ public CmdLineArgs add(String argName, boolean hasValue) {
return add(new ArgDecl(hasValue, argName));
}
- /** Add an argument to those to be accepted on the command line.
+ /** Add an argument declaration to those to be accepted on the command line.
* Argument order reflects ArgDecl.
* @param hasValue True if the command takes a (string) value
* @param argName Name
@@ -69,7 +69,7 @@ public CmdLineArgs add(boolean hasValue, String argName) {
return add(new ArgDecl(hasValue, argName));
}
- /** Add an argument object
+ /** Add an argument declaration
* @param argDecl Argument to add
* @return The command line processor object
*/
@@ -83,7 +83,7 @@ public CmdLineArgs add(ArgDecl argDecl) {
}
/**
- * Remove an argument and any values set for this argument.
+ * Remove an argument declaration and any values set for this argument.
* @param argDecl Argument to remove
* @return The command line processor object
*/
@@ -194,7 +194,7 @@ private CmdLineArgs addArgWorker(Arg arg, String value) {
// ---- Indirection
- static final String DefaultIndirectMarker = "@";
+ static final String DefaultIndirectMarker = "^";
public boolean matchesIndirect(String s) { return matchesIndirect(s, DefaultIndirectMarker); }
public boolean matchesIndirect(String s, String marker) { return s.startsWith(marker); }
@@ -243,7 +243,6 @@ public String indirect(String s, String marker) {
public boolean hasArg(ArgDecl argDecl) { return getArg(argDecl) != null; }
-
/** Get the argument associated with the argument declaration.
* Actually returns the LAST one seen
* @param argDecl Argument declaration to find
diff --git a/jena-cmds/src/main/java/org/apache/jena/cmd/Usage.java b/jena-cmds/src/main/java/org/apache/jena/cmd/Usage.java
index 766044313a5..8713c3dd5e9 100644
--- a/jena-cmds/src/main/java/org/apache/jena/cmd/Usage.java
+++ b/jena-cmds/src/main/java/org/apache/jena/cmd/Usage.java
@@ -27,7 +27,7 @@
public class Usage
{
- public static class Category {
+ private static class Category {
String desc;
List entries = new ArrayList<>();
Category(String desc) {
@@ -35,60 +35,53 @@ public static class Category {
}
}
- private static class Entry {
- String arg;
- String msg;
- Entry(String arg, String msg) {
- this.arg = arg;
- this.msg = msg;
- }
- }
+ private record Entry(String arg, String msg) {}
- private List categories = new ArrayList<>();
+ private List categories = new ArrayList<>();
- public Usage() {
- // Start with an unnamed category
- startCategory(null);
- }
+ public Usage() {
+ // Start with an unnamed category
+ startCategory(null);
+ }
- public void startCategory(String desc) {
- categories.add(new Category(desc));
- }
+ public void startCategory(String desc) {
+ categories.add(new Category(desc));
+ }
- public void addUsage(String argName, String msg) {
- current().entries.add(new Entry(argName, msg));
- }
+ public void addUsage(String argName, String msg) {
+ current().entries.add(new Entry(argName, msg));
+ }
- public void output(PrintStream out) {
- output(new IndentedWriter(out));
- }
+ public void output(PrintStream out) {
+ output(new IndentedWriter(out));
+ }
- public void output(IndentedWriter out) {
- int INDENT1 = 2;
- int INDENT2 = 4;
- out.incIndent(INDENT1);
+ public void output(IndentedWriter out) {
+ int INDENT1 = 2;
+ int INDENT2 = 4;
+ out.incIndent(INDENT1);
- Iter.reverseIterate(categories, c->{
- if ( c.desc != null ) {
- out.println(c.desc);
- }
- out.incIndent(INDENT2);
- for ( final Entry e : c.entries ) {
- out.print(e.arg);
- if ( e.msg != null ) {
- out.pad(20);
- out.print(" ");
- out.print(e.msg);
- }
- out.println();
- }
- out.decIndent(INDENT2);
- });
- out.decIndent(INDENT1);
- out.flush();
- }
+ Iter.reverseIterate(categories, c->{
+ if ( c.desc != null ) {
+ out.println(c.desc);
+ }
+ out.incIndent(INDENT2);
+ for ( final Entry e : c.entries ) {
+ out.print(e.arg);
+ if ( e.msg != null ) {
+ out.pad(20);
+ out.print(" ");
+ out.print(e.msg);
+ }
+ out.println();
+ }
+ out.decIndent(INDENT2);
+ });
+ out.decIndent(INDENT1);
+ out.flush();
+ }
- private Category current() {
- return categories.get(categories.size() - 1);
- }
+ private Category current() {
+ return categories.get(categories.size() - 1);
+ }
}
diff --git a/jena-cmds/src/main/java/shacl/shacl_parse.java b/jena-cmds/src/main/java/shacl/shacl_parse.java
index aabdf892775..d0ed0f06825 100644
--- a/jena-cmds/src/main/java/shacl/shacl_parse.java
+++ b/jena-cmds/src/main/java/shacl/shacl_parse.java
@@ -19,6 +19,7 @@
package shacl;
import java.io.PrintStream;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
@@ -96,10 +97,11 @@ protected void processModulesAndArgs() {
String[] a = x.split(",");
return Arrays.stream(a);
};
- List values = getValues(argOutput).stream()
+ List outputValues = getValues(argOutput).stream()
.flatMap(f)
.map(s->s.toLowerCase())
.toList();
+ List values = new ArrayList<>(outputValues); // Mutable.
printText = values.remove("text") || values.remove("t");
printCompact = values.remove("compact") || values.remove("c");
printRDF = values.remove("rdf") || values.remove("r") || values.remove("ttl");
diff --git a/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdLine.java b/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdLine.java
index 7555c552a1b..43cd231c7b7 100644
--- a/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdLine.java
+++ b/jena-cmds/src/test/java/org/apache/jena/cmds/TestCmdLine.java
@@ -18,20 +18,29 @@
package org.apache.jena.cmds;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import org.junit.jupiter.api.Test;
+
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import java.util.Arrays;
import java.util.Iterator;
-import org.junit.Test;
-
import org.apache.jena.cmd.Arg;
+import org.apache.jena.cmd.Args;
import org.apache.jena.cmd.ArgDecl;
import org.apache.jena.cmd.CmdException;
import org.apache.jena.cmd.CmdLineArgs;
public class TestCmdLine {
+
+ private static String DIR = "testing/cmd/";
+
@Test
public void test_Simple1() {
String args[] = {""};
@@ -117,7 +126,7 @@ public void test_addSetting() {
}
- @Test(expected = CmdException.class)
+ @Test
public void test_removeArg1() {
String args[] = {"--arg=V1", "-v"};
CmdLineArgs cl = new CmdLineArgs(args);
@@ -125,6 +134,79 @@ public void test_removeArg1() {
cl.add(argA);
cl.removeArg(argA);
// Exception.
- cl.process();
+ assertThrows(CmdException.class, ()->cl.process());
+ }
+
+
+ @Test
+ public void args_no_file_1() {
+ String[] args = {};
+ testArgsFileGood(args, new String[0]);
}
+
+ @Test
+ public void args_no_file_2() {
+ String[] args = {"-q", "-v", "positional"};
+ testArgsFileGood(args, "-q", "-v", "positional");
+ }
+
+ @Test
+ public void args_file_01() {
+ String[] args = {"@"+DIR+"args-good-1"};
+ testArgsFileGood(args, "--arg", "--arg1", "value1", "--arg2=value2", "--empty=", "--trailingspaces", "-q", "positional 1", "positional 2");
+ }
+
+ @Test
+ public void args_file_02() {
+ String[] args = {"@"+DIR+"args-good-2"};
+ testArgsFileGood(args, "-arg", "--", "positional");
+ }
+
+ @Test
+ public void args_file_03() {
+ String[] args = {"@"+DIR+"args-good-3"};
+ testArgsFileGood(args, "text");
+ }
+
+
+ @Test
+ public void args_file_bad_01() {
+ String[] args = {"@"+DIR+"args-good-1", "--another"};
+ testArgsFileBad(args);
+ }
+
+ @Test
+ public void args_file_bad_02() {
+ String[] args = {"@"+DIR+"args-good-1", "@"+DIR+"args-good-2"};
+ testArgsFileBad(args);
+ }
+
+ @Test
+ public void args_file_bad_03() {
+ String[] args = {"@"};
+ testArgsFileBad(args);
+ }
+
+ @Test
+ public void args_file_bad_04() {
+ String[] args = {"@ filename"};
+ testArgsFileBad(args);
+ }
+
+ @Test
+ public void args_file_bad_file_01() {
+ String[] args = {"@"+DIR+"args-bad-1"};
+ testArgsFileBad(args);
+ }
+
+ private void testArgsFileGood(String[] args, String...expected) {
+ String[] args2 = Args.argsPrepare(args);
+ //assertArrayEquals(expected, args2, ()->{ return "Expected: "+Arrays.asList(expected)+" Got: "+Arrays.asList(args2)});
+ assertArrayEquals(expected, args2, ()->("Expected: "+Arrays.asList(expected)+" Got: "+Arrays.asList(args2)));
+ }
+
+ private void testArgsFileBad(String[] args) {
+ assertThrows(CmdException.class, ()->Args.argsPrepare(args));
+ }
+
}
diff --git a/jena-cmds/testing/cmd/args-bad-1 b/jena-cmds/testing/cmd/args-bad-1
new file mode 100644
index 00000000000..b540d783ff3
--- /dev/null
+++ b/jena-cmds/testing/cmd/args-bad-1
@@ -0,0 +1,2 @@
+# Bad argument file.
+@another
diff --git a/jena-cmds/testing/cmd/args-good-1 b/jena-cmds/testing/cmd/args-good-1
new file mode 100644
index 00000000000..7eecbdaa603
--- /dev/null
+++ b/jena-cmds/testing/cmd/args-good-1
@@ -0,0 +1,12 @@
+# Comment. First blank line has zero chars the second has 4 spaces
+--arg
+
+--arg1 value1
+--arg2=value2
+--empty=
+
+ --trailingspaces
+-q
+ # comment
+positional 1
+positional 2
diff --git a/jena-cmds/testing/cmd/args-good-2 b/jena-cmds/testing/cmd/args-good-2
new file mode 100644
index 00000000000..5017ecff7c3
--- /dev/null
+++ b/jena-cmds/testing/cmd/args-good-2
@@ -0,0 +1,5 @@
+-arg
+--
+positional
+
+
diff --git a/jena-cmds/testing/cmd/args-good-3 b/jena-cmds/testing/cmd/args-good-3
new file mode 100644
index 00000000000..9c9cfbffa5f
--- /dev/null
+++ b/jena-cmds/testing/cmd/args-good-3
@@ -0,0 +1,2 @@
+# A word, no leading -
+text
diff --git a/jena-core/src/main/java/org/apache/jena/irix/SystemIRIx.java b/jena-core/src/main/java/org/apache/jena/irix/SystemIRIx.java
index 7fea3d4219f..747edc8b014 100644
--- a/jena-core/src/main/java/org/apache/jena/irix/SystemIRIx.java
+++ b/jena-core/src/main/java/org/apache/jena/irix/SystemIRIx.java
@@ -40,7 +40,6 @@ private enum ProviderImpl { IRI0, IRI3986 }
//private static final ProviderImpl providerImpl = ProviderImpl.IRI3986;
// -- System-wide provider.
-
private static IRIProvider provider = makeFreshSystemProvider();
/**
@@ -57,6 +56,7 @@ private enum ProviderImpl { IRI0, IRI3986 }
public static final String sysPropertyProvider = "jena.iriprovider";
public static IRIProvider makeFreshSystemProvider() {
+
ProviderImpl sysProviderImpl = getProviderImpl();
// ** This is the implementation choice point. **
@@ -90,13 +90,11 @@ private static ProviderImpl getProviderImpl() {
case "IRI0" -> ProviderImpl.IRI0;
default -> null;
};
- if ( impl != null ) {
- sysProviderImpl = impl;
- Log.info(SystemIRIx.class, "IRI Provider: "+impl);
- } else {
+ if ( impl == null ) {
Log.error(SystemIRIx.class, "IRI Provider not recognized: "+pNorm);
- System.exit(1);
+ return sysProviderImpl;
}
+ sysProviderImpl = impl;
}
return sysProviderImpl;
}
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/DSGSetup.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/DSGSetup.java
index 72a684b1189..763d33af7a1 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/DSGSetup.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/cmds/DSGSetup.java
@@ -107,7 +107,7 @@ private static void setupTDB2(Logger log, String directory, ServerArgs serverArg
serverArgs.datasetDescription = "in-memory, with files loaded";
serverArgs.dsg = DatasetGraphFactory.createTxnMem();
- for(String filename : filenames ) {
+ for ( String filename : filenames ) {
String pathname = filename;
if ( filename.startsWith("file:") )
pathname = filename.substring("file:".length());
diff --git a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java
index a0af6600d7c..8075d644d2b 100644
--- a/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java
+++ b/jena-fuseki2/jena-fuseki-main/src/main/java/org/apache/jena/fuseki/main/sys/FusekiModules.java
@@ -37,7 +37,7 @@ public class FusekiModules {
private static FusekiModules systemFusekiModules = autoLoadedFusekiModules;
/**
- * There is a system wide set of modules used when o other are indicated.
+ * There is a system wide set of modules used when no other modules are indicated.
* These default to the automatically discovered modules.
*/
public static void setSystemDefault(FusekiModules fusekiModules) {