Skip to content

Commit ef2fc42

Browse files
authored
Merge branch 'development' into renovate/org.apache.tika-tika-core-3.x
2 parents e92410d + 923efcb commit ef2fc42

33 files changed

+263
-1170
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ dependencies {
7474

7575
// monitoring
7676
implementation 'io.micronaut.micrometer:micronaut-micrometer-registry-prometheus:5.10.2'
77-
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.3.4'
77+
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.4.5'
7878

7979
// springdoc
8080
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:${springDocVersion}"

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
44
networkTimeout=10000
55
validateDistributionUrl=true
66
zipStoreBase=GRADLE_USER_HOME

src/main/java/edu/kit/datamanager/mappingservice/MappingServiceApplication.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package edu.kit.datamanager.mappingservice;
22

3-
import com.google.common.collect.ImmutableSet;
4-
import com.google.common.reflect.ClassPath;
53
import edu.kit.datamanager.mappingservice.configuration.ApplicationProperties;
64
import edu.kit.datamanager.mappingservice.plugins.PluginManager;
75
import io.micrometer.core.instrument.MeterRegistry;
@@ -11,29 +9,22 @@
119
import edu.kit.datamanager.security.filter.KeycloakJwtProperties;
1210
import edu.kit.datamanager.security.filter.KeycloakTokenFilter;
1311
import edu.kit.datamanager.security.filter.KeycloakTokenValidator;
14-
import java.io.IOException;
15-
import org.slf4j.Logger;
16-
import org.slf4j.LoggerFactory;
1712
import org.springframework.beans.factory.annotation.Autowired;
1813
import org.springframework.boot.SpringApplication;
1914
import org.springframework.boot.autoconfigure.SpringBootApplication;
2015
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2116
import org.springframework.boot.autoconfigure.domain.EntityScan;
2217
import org.springframework.context.ConfigurableApplicationContext;
2318
import org.springframework.context.annotation.Bean;
24-
import org.springframework.context.annotation.ComponentScan;
2519
import org.springframework.context.annotation.Configuration;
2620
import org.springframework.scheduling.annotation.EnableAsync;
2721

2822
@SpringBootApplication
29-
@ComponentScan({"edu.kit.datamanager.mappingservice"})
3023
@EntityScan("edu.kit.datamanager")
3124
@Configuration
3225
@EnableAsync
3326
public class MappingServiceApplication {
3427

35-
private static final Logger LOG = LoggerFactory.getLogger(MappingServiceApplication.class);
36-
3728
@Autowired
3829
private final MeterRegistry meterRegistry;
3930

@@ -68,7 +59,7 @@ public KeycloakJwtProperties keycloakProperties() {
6859
value = "mapping-service.authEnabled",
6960
havingValue = "true",
7061
matchIfMissing = false)
71-
public KeycloakTokenFilter keycloaktokenFilterBean() throws Exception {
62+
public KeycloakTokenFilter keycloakTokenFilterBean() {
7263
return new KeycloakTokenFilter(KeycloakTokenValidator.builder()
7364
.readTimeout(keycloakProperties().getReadTimeoutms())
7465
.connectTimeout(keycloakProperties().getConnectTimeoutms())
@@ -77,17 +68,17 @@ public KeycloakTokenFilter keycloaktokenFilterBean() throws Exception {
7768
.build(keycloakProperties().getJwkUrl(), keycloakProperties().getResource(), keycloakProperties().getJwtClaim()));
7869
}
7970

80-
public static void main(String[] args) throws IOException {
71+
public static void main(String[] args) {
8172
ConfigurableApplicationContext ctx = SpringApplication.run(MappingServiceApplication.class, args);
8273

8374
PluginManager mgr = ctx.getBean(PluginManager.class);
8475
System.out.println("Found plugins: ");
8576
mgr.getPlugins().forEach((k, v) -> {
86-
System.out.println(String.format(" - %s (%s)", k, v));
77+
System.out.printf(" - %s (%s)%n", k, v);
8778
});
8879
System.out.println("Using Python Version: ");
8980
PythonRunnerUtil.printPythonVersion();
9081
String port = ctx.getEnvironment().getProperty("server.port");
91-
System.out.println(String.format("Mapping service is running on port %s.", port));
82+
System.out.printf("Mapping service is running on port %s.%n", port);
9283
}
9384
}

src/main/java/edu/kit/datamanager/mappingservice/configuration/WebSecurityConfig.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3535
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
3636
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
37+
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
38+
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
3739
import org.springframework.security.config.http.SessionCreationPolicy;
3840
import org.springframework.security.config.Customizer;
3941
import org.springframework.security.web.SecurityFilterChain;
@@ -50,13 +52,13 @@
5052
*/
5153
@Configuration
5254
@EnableWebSecurity
53-
@EnableMethodSecurity(prePostEnabled = true)
55+
@EnableMethodSecurity
5456
public class WebSecurityConfig {
5557

5658
private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
5759

5860
@Autowired
59-
private Optional<KeycloakTokenFilter> keycloaktokenFilterBean;
61+
private Optional<KeycloakTokenFilter> keycloakTokenFilterBean;
6062
@Autowired
6163
private ApplicationProperties applicationProperties;
6264

@@ -89,7 +91,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
8991
);
9092
} else {
9193
logger.trace("Authentication is DISABLED. Not securing endpoints.");
92-
securedEndpointMatchers = Arrays.asList();
94+
securedEndpointMatchers = List.of();
9395
}
9496

9597
HttpSecurity httpSecurity = http.authorizeHttpRequests(
@@ -112,11 +114,11 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
112114
session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
113115

114116
logger.info("CSRF disabled!");
115-
httpSecurity = httpSecurity.csrf(csrf -> csrf.disable());
117+
httpSecurity.csrf(AbstractHttpConfigurer::disable);
116118

117-
if (keycloaktokenFilterBean.isPresent()) {
119+
if (keycloakTokenFilterBean.isPresent()) {
118120
logger.trace("Adding Keycloak filter to filter chain.");
119-
httpSecurity.addFilterAfter(keycloaktokenFilterBean.get(), BasicAuthenticationFilter.class);
121+
httpSecurity.addFilterAfter(keycloakTokenFilterBean.get(), BasicAuthenticationFilter.class);
120122
} else {
121123
logger.trace("Keycloak not configured. Skip adding keycloak filter to filter chain.");
122124
}
@@ -130,7 +132,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
130132
}
131133

132134
logger.trace("Turning off cache control.");
133-
httpSecurity.headers(headers -> headers.cacheControl(cache -> cache.disable()));
135+
httpSecurity.headers(headers -> headers.cacheControl(HeadersConfigurer.CacheControlConfig::disable));
134136

135137
return httpSecurity.build();
136138
}

src/main/java/edu/kit/datamanager/mappingservice/dao/IMappingRecordDao.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public interface IMappingRecordDao extends JpaRepository<MappingRecord, String>,
3737
* Find a MappingRecords by the given ID.
3838
*
3939
* @param mappingId The id to search for.
40-
* @return A optional of the matching MappingRecord.
40+
* @return An optional of the matching MappingRecord.
4141
*/
4242
Optional<MappingRecord> findByMappingId(String mappingId);
4343

src/main/java/edu/kit/datamanager/mappingservice/impl/MappingService.java

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import edu.kit.datamanager.mappingservice.exception.MappingNotFoundException;
2828
import edu.kit.datamanager.mappingservice.exception.MappingServiceException;
2929
import edu.kit.datamanager.mappingservice.exception.MappingServiceUserException;
30+
import edu.kit.datamanager.mappingservice.plugins.IMappingPlugin;
3031
import edu.kit.datamanager.mappingservice.plugins.MappingPluginException;
3132
import edu.kit.datamanager.mappingservice.plugins.MappingPluginState;
3233
import edu.kit.datamanager.mappingservice.plugins.PluginManager;
@@ -50,9 +51,7 @@
5051
import java.security.MessageDigest;
5152
import java.security.NoSuchAlgorithmException;
5253
import java.text.SimpleDateFormat;
53-
import java.util.Collections;
54-
import java.util.Date;
55-
import java.util.Optional;
54+
import java.util.*;
5655
import java.util.concurrent.CompletableFuture;
5756
import java.util.regex.Matcher;
5857
import java.util.regex.Pattern;
@@ -91,7 +90,6 @@ public class MappingService {
9190
*/
9291
private Path jobsOutputDirectory;
9392

94-
private ApplicationProperties applicationProperties;
9593
private final MeterRegistry meterRegistry;
9694

9795
/**
@@ -101,9 +99,8 @@ public class MappingService {
10199

102100
@Autowired
103101
public MappingService(ApplicationProperties applicationProperties, MeterRegistry meterRegistry) {
104-
this.applicationProperties = applicationProperties;
105102
this.meterRegistry = meterRegistry;
106-
init(this.applicationProperties);
103+
init(applicationProperties);
107104
}
108105

109106
/**
@@ -118,32 +115,35 @@ public MappingService(ApplicationProperties applicationProperties, MeterRegistry
118115
*/
119116
public MappingRecord createMapping(String content, MappingRecord mappingRecord) throws IOException {
120117
LOGGER.trace("Creating mapping with id {}.", mappingRecord.getMappingId());
121-
// Check for valid mapping ID (should contain at least one non whitespace.
118+
// Check for valid mapping ID (should contain at least one non whitespace).
122119
String mappingId = mappingRecord.getMappingId();
123120
if ((mappingId == null) || (mappingId.isBlank())) {
124-
String message = String.format("MappingID shouldn't be empty or contain only whitespaces. You provide '%s'", mappingId);
121+
String message = String.format("MappingID shouldn't be empty or contain only whitespaces. You provided '%s'", mappingId);
125122
LOGGER.error(message);
126123
throw new BadArgumentException(message);
127124
}
128125

129126
String mappingType = mappingRecord.getMappingType();
130127
if ((mappingType == null) || (mappingType.isBlank() || !pluginManager.getPlugins().containsKey(mappingType))) {
131-
String message = String.format("MappingType shouldn't be empty or contain only whitespaces and must be a registered plugin id. You provide '%s'", mappingType);
128+
String message = String.format("MappingType shouldn't be empty or contain only whitespaces and must be a registered plugin id. You provided '%s'", mappingType);
132129
LOGGER.error(message);
130+
Set<Map.Entry<String, IMappingPlugin>> entries = pluginManager.getPlugins().entrySet();
131+
LOGGER.info("Registered plugins: ");
132+
for(Map.Entry<String, IMappingPlugin> entry : entries) {
133+
LOGGER.info(" * {}", entry.getKey());
134+
}
135+
133136
throw new BadArgumentException(message);
134137
}
135138

136139
Iterable<MappingRecord> findMapping = mappingRepo.findByMappingIdIn(Collections.singletonList(mappingRecord.getMappingId()));
137140
if (findMapping.iterator().hasNext()) {
138-
LOGGER.error("Unable to create mapping with id {}. Mapping id is alreadyy used.", mappingRecord.getMappingId());
141+
LOGGER.error("Unable to create mapping with id {}. Mapping id is already used.", mappingRecord.getMappingId());
139142
mappingRecord = findMapping.iterator().next();
140143
throw new DuplicateMappingException("Error: Mapping '" + mappingRecord.getMappingType() + "_" + mappingRecord.getMappingId() + "' already exists!");
141144
}
142145

143-
LOGGER.trace("Saving mapping file.");
144-
saveMappingFile(content, mappingRecord);
145-
LOGGER.trace("Persisting mapping record.");
146-
MappingRecord result = mappingRepo.save(mappingRecord);
146+
MappingRecord result = persistMapping(content, mappingRecord);
147147
LOGGER.trace("Mapping with id {} successfully created.", result.getMappingId());
148148
return mappingRecord;
149149
}
@@ -163,10 +163,7 @@ public void updateMapping(String content, MappingRecord mappingRecord) throws Ma
163163

164164
LOGGER.trace("Updating mapping with id {}.", mappingRecord.getMappingId());
165165
mappingRecord.setMappingDocumentUri(findMapping.get().getMappingDocumentUri());
166-
LOGGER.trace("Saving mapping file.");
167-
saveMappingFile(content, mappingRecord);
168-
LOGGER.trace("Persisting mapping record.");
169-
mappingRepo.save(mappingRecord);
166+
persistMapping(content, mappingRecord);
170167
LOGGER.trace("Mapping with id {} successfully updated.", mappingRecord.getMappingId());
171168
}
172169

@@ -189,7 +186,7 @@ public void deleteMapping(MappingRecord mappingRecord) {
189186
try {
190187
deleteMappingFile(mappingRecord);
191188
} catch (IOException e) {
192-
LOGGER.error(String.format("Failed to delete mapping file at %s. Please remove it manually.", mappingRecord.getMappingDocumentUri()), e);
189+
LOGGER.error("Failed to delete mapping file at {}. Please remove it manually.", mappingRecord.getMappingDocumentUri(), e);
193190
}
194191
}
195192

@@ -432,7 +429,11 @@ public JobStatus deleteJobAndAssociatedData(String jobId) {
432429
//delete output file if file still exists (even after the job was removed from the queue)
433430
File outputFile = getOutputFile(jobId);
434431
if (outputFile.exists()) {
435-
outputFile.delete();
432+
if(outputFile.delete()){
433+
LOGGER.trace("Output file {} deleted.", outputFile);
434+
}else{
435+
LOGGER.warn("Output file {} could not be deleted.", outputFile);
436+
}
436437
} else {
437438
LOGGER.debug("No output file for job {} found.", jobId);
438439
}
@@ -458,7 +459,11 @@ public JobStatus deleteJobAndAssociatedData(String jobId) {
458459

459460
if (jobOutput.exists()) {
460461
LOGGER.trace(" - Deleting job output");
461-
jobOutput.delete();
462+
if(jobOutput.delete()){
463+
LOGGER.trace(" - Output file {} deleted.", jobOutput);
464+
}else{
465+
LOGGER.warn(" ! Output file {} could not be deleted.", jobOutput);
466+
}
462467
}
463468
LOGGER.trace("Removing job from queue.");
464469
jobManager.removeJob(jobId);
@@ -488,7 +493,7 @@ private File getOutputFile(String jobId) {
488493
}
489494

490495
/**
491-
* Initalize mappings directory and mappingUtil instance.
496+
* Initialize mappings directory and mappingUtil instance.
492497
*
493498
* @param applicationProperties Properties holding mapping directory
494499
* setting.
@@ -578,4 +583,11 @@ private String date2String() {
578583
SimpleDateFormat sdf = new SimpleDateFormat("_yyyyMMdd_HHmmss");
579584
return sdf.format(new Date());
580585
}
586+
587+
private MappingRecord persistMapping(String content, MappingRecord mappingRecord) throws IOException {
588+
LOGGER.trace("Saving mapping file.");
589+
saveMappingFile(content, mappingRecord);
590+
LOGGER.trace("Persisting mapping record.");
591+
return mappingRepo.save(mappingRecord);
592+
}
581593
}

src/main/java/edu/kit/datamanager/mappingservice/plugins/AbstractPythonMappingPlugin.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
import org.apache.maven.artifact.versioning.ComparableVersion;
3434
import org.slf4j.Logger;
3535
import org.slf4j.LoggerFactory;
36-
import org.springframework.beans.factory.annotation.Autowired;
37-
import org.springframework.stereotype.Component;
3836

3937
/**
4038
*
@@ -47,17 +45,17 @@ public abstract class AbstractPythonMappingPlugin implements IMappingPlugin {
4745
/**
4846
* The plugin name.
4947
*/
50-
private String name;
48+
private final String name;
5149
/**
5250
* The URL of the Git repository where the plugin code is located.
5351
*/
54-
private String repositoryUrl;
52+
private final String repositoryUrl;
5553

5654
/**
57-
* The tag which should be used to checkout a specific version from
55+
* The tag which should be used to check out a specific version from
5856
* repositoryUrl.
5957
*/
60-
private String tag;
58+
private final String tag;
6159

6260
/**
6361
* The minimal python version required by the plugin
@@ -69,8 +67,8 @@ public abstract class AbstractPythonMappingPlugin implements IMappingPlugin {
6967
*/
7068
private Path dir;
7169

72-
private String pluginVenv = "venv/PluginVenv";
73-
private String venvInterpreter;
70+
private final String pluginVenv = "venv/PluginVenv";
71+
private final String venvInterpreter;
7472

7573
/**
7674
* Default constructor for instantiating a Python-based mapping plugin. It
@@ -82,10 +80,9 @@ public abstract class AbstractPythonMappingPlugin implements IMappingPlugin {
8280
* the root of the Jar file. The properties file must contain one property
8381
* 'version' which represents an existing Git tag matching a released
8482
* version of the Python plugin code, e.g., version=v1.0.0
85-
*
8683
* Furthermore, the properties file may contain a minimal Python version
8784
* that is required by the plugin to work. The minimal Python version is set
88-
* via the 'min.python' property, e.g.., min.python=3.10.0 If the minimal
85+
* via the 'min.python' property, e.g., min.python=3.10.0 If the minimal
8986
* Python version is not met, the plugin will be ignored.
9087
*
9188
* @param pluginName The name of the plugin.
@@ -129,20 +126,17 @@ public AbstractPythonMappingPlugin(String pluginName, String repositoryUrl) {
129126
* plugin to gather all information required for starting a Python process
130127
* executing the mapping script. The returned array must contain at least
131128
* the following information:
132-
*
133129
* &lt;ul&gt; &lt;li&gt;The absolute path of the main script. It must start
134130
* with the working dir received as argument, where all checked-out code is
135131
* located.&lt;/li&gt; &lt;li&gt;Script-specific parameters to provide
136132
* mappingFile, inputFile, and outputFile to the script execution. Depending
137133
* on the script implementation, the number and kind of required arguments
138134
* may differ.&lt;/li&gt; &lt;/ul&gt;
139-
*
140135
* Example: In standalone mode, a script is called via `plugin_wrapper.py
141136
* sem -m mappingFile -i inputFile -o outputFile -debug`. In that case, the
142137
* resulting array should look as follows: [workingDir +
143138
* "plugin_wrapper.py", "sem", "-m", mappingFile.toString(), "-i",
144139
* inputFile.toString(), "-o", outputFile.toString(), "-debug"].
145-
*
146140
* The Python call itself will be added according to the Venv used for
147141
* plugin execution and must not be included.
148142
*
@@ -244,7 +238,6 @@ public MappingPluginState mapFile(Path mappingFile, Path inputFile, Path outputF
244238
* This method checks if the local Python installation version is larger or
245239
* equal the provided version number. The version should be provided as
246240
* semantic version number, i.e., 3.13.2
247-
*
248241
* The method will return TRUE if the minimal requirements are met and false
249242
* otherwise. False is also returned if obtaining/parsing the local python
250243
* version fails. for any reason.
@@ -266,7 +259,7 @@ private boolean hasMinimalPythonVersion(String versionString) {
266259
LOGGER.error("Failed to obtain Python version. python --version returned with status {}.", state.getState());
267260
} else {
268261

269-
LOGGER.trace("Version command output: {}", bout.toString());
262+
LOGGER.trace("Version command output: {}", bout);
270263

271264
String[] split = bout.toString().split(" ");
272265

0 commit comments

Comments
 (0)