diff --git a/app/opensearch/build.gradle b/app/opensearch/build.gradle index 03fd75993..14b1bb393 100644 --- a/app/opensearch/build.gradle +++ b/app/opensearch/build.gradle @@ -16,15 +16,15 @@ sourceSets { } dependencies { - implementation 'org.opensearch.client:opensearch-java:2.10.1' - implementation 'org.apache.httpcomponents.client5:httpclient5:5.3.1' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0' + implementation 'org.opensearch.client:opensearch-java:2.16.0' + implementation 'org.apache.httpcomponents.client5:httpclient5:5.4' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.18.0' - implementation 'org.codelibs.opensearch:opensearch-runner:2.13.0.0' + implementation 'org.codelibs.opensearch:opensearch-runner:2.17.1.0' // updates for indirect dependencies - implementation 'io.netty:netty-codec:4.1.109.Final' - implementation 'io.netty:netty-codec-http:4.1.109.Final' + implementation 'io.netty:netty-codec:4.1.114.Final' + implementation 'io.netty:netty-codec-http:4.1.114.Final' } tasks.named('jar') { diff --git a/buildSrc/shared.gradle b/buildSrc/shared.gradle index b12bf450f..d64be1d6c 100644 --- a/buildSrc/shared.gradle +++ b/buildSrc/shared.gradle @@ -40,34 +40,34 @@ sourceSets { } dependencies { - implementation 'org.apache.logging.log4j:log4j-core:2.23.1' - implementation 'org.apache.logging.log4j:log4j-api:2.23.1' - implementation 'org.postgresql:postgresql:42.7.2' - implementation 'org.slf4j:slf4j-api:2.0.13' - implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.23.1' - implementation 'com.beust:jcommander:1.82' - implementation 'org.apache.commons:commons-lang3:3.14.0' - implementation 'org.springframework:spring-jdbc:5.3.32' + implementation 'org.apache.logging.log4j:log4j-core:2.24.1' + implementation 'org.apache.logging.log4j:log4j-api:2.24.1' + implementation 'org.postgresql:postgresql:42.7.4' + implementation 'org.slf4j:slf4j-api:2.0.16' + implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.1' + implementation 'org.jcommander:jcommander:2.0' + implementation 'org.apache.commons:commons-lang3:3.17.0' + implementation 'org.springframework:spring-jdbc:5.3.39' implementation ('org.apache.commons:commons-dbcp2:2.12.0') { exclude(module: 'commons-logging') } - implementation 'org.locationtech.jts:jts-core:1.19.0' + implementation 'org.locationtech.jts:jts-core:1.20.0' implementation 'com.sparkjava:spark-core:2.9.4' - implementation 'net.postgis:postgis-jdbc:2023.1.0' + implementation 'net.postgis:postgis-jdbc:2024.1.0' implementation 'org.json:json:20240303' - testImplementation(platform("org.junit:junit-bom:5.10.2")) - testImplementation 'com.h2database:h2:2.2.224' + testImplementation(platform("org.junit:junit-bom:5.11.3")) + testImplementation 'com.h2database:h2:2.3.232' testImplementation 'org.junit.jupiter:junit-jupiter' - testImplementation 'org.mockito:mockito-core:5.11.0' + testImplementation 'org.mockito:mockito-core:5.14.2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' // updates for indirect dependencies - implementation 'org.eclipse.jetty:jetty-server:9.4.54.v20240208' - implementation 'org.eclipse.jetty:jetty-webapp:9.4.54.v20240208' - implementation 'org.eclipse.jetty.websocket:websocket-server:9.4.54.v20240208' - implementation 'org.eclipse.jetty.websocket:websocket-servlet:9.4.54.v20240208' + implementation 'org.eclipse.jetty:jetty-server:9.4.56.v20240826' + implementation 'org.eclipse.jetty:jetty-webapp:9.4.56.v20240826' + implementation 'org.eclipse.jetty.websocket:websocket-server:9.4.56.v20240826' + implementation 'org.eclipse.jetty.websocket:websocket-servlet:9.4.56.v20240826' } tasks.named('test') { @@ -76,4 +76,4 @@ tasks.named('test') { test { systemProperty "sun.net.http.allowRestrictedHeaders", "true" -} \ No newline at end of file +} diff --git a/src/main/java/de/komoot/photon/App.java b/src/main/java/de/komoot/photon/App.java index 9517ac559..b432b2f0a 100644 --- a/src/main/java/de/komoot/photon/App.java +++ b/src/main/java/de/komoot/photon/App.java @@ -74,11 +74,6 @@ private static CommandLineArgs parseCommandLine(String[] rawArgs) { final JCommander jCommander = new JCommander(args); try { jCommander.parse(rawArgs); - - // Cors arguments are mutually exclusive. - if (args.isCorsAnyOrigin() && args.getCorsOrigin().length > 0) { - throw new ParameterException("Use only one cors configuration type"); - } } catch (ParameterException e) { LOGGER.warn("Could not start photon: {}", e.getMessage()); jCommander.usage(); diff --git a/src/main/java/de/komoot/photon/CommandLineArgs.java b/src/main/java/de/komoot/photon/CommandLineArgs.java index 241e5a4d1..724f48359 100644 --- a/src/main/java/de/komoot/photon/CommandLineArgs.java +++ b/src/main/java/de/komoot/photon/CommandLineArgs.java @@ -1,83 +1,87 @@ package de.komoot.photon; import com.beust.jcommander.Parameter; -import de.komoot.photon.utils.StringArrayConverter; +import com.beust.jcommander.Parameters; +import de.komoot.photon.utils.CorsMutuallyExclusiveValidator; import java.io.File; +import java.util.ArrayList; +import java.util.List; /** * Command Line Arguments parsed by {@link com.beust.jcommander.JCommander} and used to start photon. */ +@Parameters(parametersValidators = CorsMutuallyExclusiveValidator.class) public class CommandLineArgs { - @Parameter(names = "-structured", description = "Enable support for structured queries") + @Parameter(names = "-structured", description = "Enable support for structured queries.") private boolean supportStructuredQueries = false; - @Parameter(names = "-cluster", description = "Name of ElasticSearch cluster to put the server into") + @Parameter(names = "-cluster", description = "Name of ElasticSearch cluster to put the server into.") private String cluster = "photon"; - @Parameter(names = "-transport-addresses", description = "Comma-separated list of addresses of external ElasticSearch nodes the client can connect to (default is an empty string which forces an internal node to start)", converter = StringArrayConverter.class) - private String[] transportAddresses = new String[]{}; + @Parameter(names = "-transport-addresses", description = "Comma-separated list of addresses of external ElasticSearch nodes the client can connect to. An empty list (the default) forces an internal node to start.") + private List transportAddresses = new ArrayList<>(); - @Parameter(names = "-nominatim-import", description = "Import nominatim database into photon (this will delete previous index)") + @Parameter(names = "-nominatim-import", description = "Import nominatim database into photon (deleting the previous index).") private boolean nominatimImport = false; - @Parameter(names = "-nominatim-update-init-for", description = "Set up tracking of updates in the Nominatim database for the given user and exit") + @Parameter(names = "-nominatim-update-init-for", description = "Set up tracking of updates in the Nominatim database for the given user and exit.") private String nominatimUpdateInit = null; - @Parameter(names = "-nominatim-update", description = "Fetch updates from nominatim database into photon and exit (updates the index only without offering an API)") + @Parameter(names = "-nominatim-update", description = "Fetch updates from nominatim database into photon and exit (updates the index only without offering an API).") private boolean nominatimUpdate = false; - @Parameter(names = "-languages", description = "[import-only] Comma-separated list of languages for which names should be imported (default is 'en,fr,de,it')", converter = StringArrayConverter.class) - private String[] languages = new String[]{}; + @Parameter(names = "-languages", description = "Comma-separated list of languages to use. On import sets the name translations to use (default: de,en,fr,it). When running, the languages to be searched may be further restricted.") + private List languages = new ArrayList<>(); - @Parameter(names = "-default-language", description = "Language to return results in when no explicit language is chosen by the user") + @Parameter(names = "-default-language", description = "Language to return results in when no explicit language is chosen by the user.") private String defaultLanguage = "default"; - @Parameter(names = "-country-codes", description = "[import-only] Comma-separated list of country codes for countries the importer should import, comma separated (default is empty which imports the full database)", converter = StringArrayConverter.class) - private String[] countryCodes = new String[]{}; + @Parameter(names = "-country-codes", description = "[import-only] Comma-separated list of country codes for countries the importer should import, comma separated. An empty list means the full database is imported.") + private List countryCodes = new ArrayList<>(); - @Parameter(names = "-extra-tags", description = "Comma-separated list of additional tags to save for each place (default: None)", converter = StringArrayConverter.class) - private String[] extraTags = new String[]{}; + @Parameter(names = "-extra-tags", description = "Comma-separated list of additional tags to save for each place.") + private List extraTags = new ArrayList<>(); - @Parameter(names = "-synonym-file", description = "File with synonym and classification terms") + @Parameter(names = "-synonym-file", description = "File with synonym and classification terms.") private String synonymFile = null; @Parameter(names = "-query-timeout", description = "Time after which to cancel queries to the ES database (in seconds).") private int queryTimeout = 7; - @Parameter(names = "-json", description = "Read from nominatim database and dump it to the given file in a json-like format (useful for developing)") + @Parameter(names = "-json", description = "Read from nominatim database and dump it to the given file in a json-like format (useful for developing).") private String jsonDump = null; - @Parameter(names = "-host", description = "Hostname of the PostgreSQL database") + @Parameter(names = "-host", description = "Hostname of the PostgreSQL database.") private String host = "127.0.0.1"; - @Parameter(names = "-port", description = "Port of the PostgreSQL database") + @Parameter(names = "-port", description = "Port of the PostgreSQL database.") private Integer port = 5432; - @Parameter(names = "-database", description = "Database name of the Nominatim database") + @Parameter(names = "-database", description = "Database name of the Nominatim database.") private String database = "nominatim"; - @Parameter(names = "-user", description = "Username in the PostgreSQL database") + @Parameter(names = "-user", description = "Username in the PostgreSQL database.") private String user = "nominatim"; - @Parameter(names = "-password", description = "Password for the PostgreSQL database") + @Parameter(names = "-password", description = "Password for the PostgreSQL database.") private String password = null; - @Parameter(names = "-data-dir", description = "Photon data directory") + @Parameter(names = "-data-dir", description = "Photon data directory.") private String dataDirectory = new File(".").getAbsolutePath(); - @Parameter(names = "-listen-port", description = "Port for the Photon server to listen to") + @Parameter(names = "-listen-port", description = "Port for the Photon server to listen to.") private int listenPort = 2322; - @Parameter(names = "-listen-ip", description = "Address for the Photon server to listen to") + @Parameter(names = "-listen-ip", description = "Address for the Photon server to listen to.") private String listenIp = "0.0.0.0"; - @Parameter(names = "-cors-any", description = "Enable cross-site resource sharing for any origin") + @Parameter(names = "-cors-any", description = "Enable cross-site resource sharing for any origin.") private boolean corsAnyOrigin = false; - @Parameter(names = "-cors-origin", description = "Enable cross-site resource sharing for the specified origins, comma separated", converter = StringArrayConverter.class) - private String[] corsOrigin = new String[]{}; + @Parameter(names = "-cors-origin", description = "Comma-separated list of origins for which to enable cross-site resource sharing.") + private List corsOrigin = new ArrayList<>(); @Parameter(names = "-enable-update-api", description = "Enable the additional endpoint /nominatim-update, which allows to trigger updates from a nominatim database") private boolean enableUpdateApi = false; @@ -92,11 +96,11 @@ public class CommandLineArgs { private int maxReverseResults = 50; public String[] getLanguages(boolean useDefaultIfEmpty) { - if (useDefaultIfEmpty && languages.length == 0) { + if (useDefaultIfEmpty && languages.isEmpty()) { return new String[]{"en", "de", "fr", "it"}; } - return languages; + return languages.toArray(new String[0]); } public String[] getLanguages() { @@ -108,7 +112,7 @@ public String getCluster() { } public String[] getTransportAddresses() { - return this.transportAddresses; + return this.transportAddresses.toArray(new String[0]); } public boolean isNominatimImport() { @@ -128,11 +132,11 @@ public String getDefaultLanguage() { } public String[] getCountryCodes() { - return this.countryCodes; + return this.countryCodes.toArray(new String[0]); } public String[] getExtraTags() { - return this.extraTags; + return this.extraTags.toArray(new String[0]); } public String getSynonymFile() { @@ -184,7 +188,7 @@ public boolean isCorsAnyOrigin() { } public String[] getCorsOrigin() { - return this.corsOrigin; + return this.corsOrigin.toArray(new String[0]); } public boolean isEnableUpdateApi() { diff --git a/src/main/java/de/komoot/photon/utils/CorsMutuallyExclusiveValidator.java b/src/main/java/de/komoot/photon/utils/CorsMutuallyExclusiveValidator.java new file mode 100644 index 000000000..efd1d07b9 --- /dev/null +++ b/src/main/java/de/komoot/photon/utils/CorsMutuallyExclusiveValidator.java @@ -0,0 +1,18 @@ +package de.komoot.photon.utils; + +import com.beust.jcommander.IParametersValidator; +import com.beust.jcommander.ParameterException; + +import java.util.List; +import java.util.Map; + +import static java.lang.Boolean.TRUE; + +public class CorsMutuallyExclusiveValidator implements IParametersValidator { + @Override + public void validate(Map parameters) throws ParameterException { + if (parameters.get("-cors-any") == TRUE && parameters.get("-cors-origin") != null) { + throw new ParameterException("Use only one cors configuration type."); + } + } +} diff --git a/src/main/java/de/komoot/photon/utils/StringArrayConverter.java b/src/main/java/de/komoot/photon/utils/StringArrayConverter.java deleted file mode 100644 index 377d739b0..000000000 --- a/src/main/java/de/komoot/photon/utils/StringArrayConverter.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.komoot.photon.utils; - -import com.beust.jcommander.IStringConverter; - -import java.util.Arrays; - -/** - * Converter function for JCommand that creates a String array from a comma separated list. - */ -public class StringArrayConverter implements IStringConverter { - @Override - public String[] convert(String value) { - if (value == null) { - return new String[]{}; - } - - return Arrays.stream(value.split(",")) - .map(s -> s.trim()) - .filter(s -> !s.isEmpty()) - .toArray(String[]::new); - } -} diff --git a/src/test/java/de/komoot/photon/utils/StringArrayConverterTest.java b/src/test/java/de/komoot/photon/utils/StringArrayConverterTest.java deleted file mode 100644 index 813dacbfc..000000000 --- a/src/test/java/de/komoot/photon/utils/StringArrayConverterTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.komoot.photon.utils; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.params.provider.Arguments.arguments; - -class StringArrayConverterTest { - - @ParameterizedTest - @MethodSource("convertArgumentProvider") - void testConvert(String arg, String[] expected) { - assertArrayEquals(expected, new StringArrayConverter().convert(arg)); - } - - static Stream convertArgumentProvider() { - return Stream.of( - arguments("foo", new String[]{"foo"}), - arguments("with space", new String[]{"with space"}), - arguments(" 123", new String[]{"123"}), - arguments("", new String[]{}), - arguments(",", new String[]{}), - arguments("1,2,3", new String[]{"1", "2", "3"}), - arguments("1, 2, 3", new String[]{"1", "2", "3"}), - arguments("a,,b", new String[]{"a", "b"}), - arguments("a, ,b", new String[]{"a", "b"}) - ); - } -} \ No newline at end of file