Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 52 additions & 36 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>

<spring-framework.version>6.2.10</spring-framework.version>
</properties>

<licenses>
Expand Down Expand Up @@ -50,6 +52,19 @@
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
<arg>-Xlint:deprecation</arg>
<arg>-Werror</arg>
</compilerArgs>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
Expand Down Expand Up @@ -102,66 +117,67 @@
</dependency>

<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.9</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.6.0.Final</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>2.0.17</version>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.13.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.17.0</version>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.11.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>code.google.com</groupId>
<artifactId>jspf.core</artifactId>
<version>1.0.2</version>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.3.232</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.6.0.Final</version>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-framework.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.3</version>
<scope>test</scope>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-framework.version}</version>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.13.0</version>
<scope>test</scope>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-framework.version}</version>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.3.232</version>
<scope>test</scope>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>3.0.0</version>
</dependency>

<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>7.0.2</version>
</dependency>
</dependencies>

Expand Down
69 changes: 69 additions & 0 deletions src/main/java/fr/insalyon/creatis/gasw/DatabaseConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package fr.insalyon.creatis.gasw;

import com.zaxxer.hikari.HikariDataSource;
import fr.insalyon.creatis.gasw.plugin.DatabasePlugin;
import jakarta.persistence.EntityManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.Properties;

@Configuration
public class DatabaseConfiguration {

private final Logger logger = LoggerFactory.getLogger(getClass());

private final DatabasePlugin dbPlugin;

public DatabaseConfiguration(DatabasePlugin dbPlugin) {

Check warning on line 25 in src/main/java/fr/insalyon/creatis/gasw/DatabaseConfiguration.java

View workflow job for this annotation

GitHub Actions / all

Parameter 'dbPlugin' is not assigned and could be declared final

Reports method and constructor parameters that can be made final because they are never reassigned within the body of the method. This rule ignores unused parameters so as not to overlap with the rule {% rule java/bestpractices/UnusedFormalParameter %}. It will also ignore the parameters of abstract methods. MethodArgumentCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#methodargumentcouldbefinal
this.dbPlugin = dbPlugin;
}

@Bean
public DataSource dataSource() {
logger.info("Loading database plugin '{}' version '{}'",
dbPlugin.getName(), dbPlugin.getClass().getPackage().getImplementationVersion());

HikariDataSource dataSource = new HikariDataSource();

Check warning on line 34 in src/main/java/fr/insalyon/creatis/gasw/DatabaseConfiguration.java

View workflow job for this annotation

GitHub Actions / all

Local variable 'dataSource' could be declared final

A local variable assigned only once can be declared final. LocalVariableCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#localvariablecouldbefinal
dataSource.setDriverClassName(dbPlugin.getDriverClass());
dataSource.setUsername(dbPlugin.getUserName());
dataSource.setPassword(dbPlugin.getPassword());
dataSource.setJdbcUrl(dbPlugin.getConnectionUrl());
return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {

Check warning on line 43 in src/main/java/fr/insalyon/creatis/gasw/DatabaseConfiguration.java

View workflow job for this annotation

GitHub Actions / all

Parameter 'dataSource' is not assigned and could be declared final

Reports method and constructor parameters that can be made final because they are never reassigned within the body of the method. This rule ignores unused parameters so as not to overlap with the rule {% rule java/bestpractices/UnusedFormalParameter %}. It will also ignore the parameters of abstract methods. MethodArgumentCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#methodargumentcouldbefinal
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();

Check warning on line 44 in src/main/java/fr/insalyon/creatis/gasw/DatabaseConfiguration.java

View workflow job for this annotation

GitHub Actions / all

Local variable 'emf' could be declared final

A local variable assigned only once can be declared final. LocalVariableCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#localvariablecouldbefinal
emf.setDataSource(dataSource);
emf.setPackagesToScan(
"fr.insalyon.creatis.gasw.bean",
"fr.insalyon.creatis.gasw.plugin"
);

emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emf.setJpaProperties(hibernateProperties());
return emf;
}

private Properties hibernateProperties() {
Properties properties = new Properties();

Check warning on line 57 in src/main/java/fr/insalyon/creatis/gasw/DatabaseConfiguration.java

View workflow job for this annotation

GitHub Actions / all

Local variable 'properties' could be declared final

A local variable assigned only once can be declared final. LocalVariableCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#localvariablecouldbefinal
properties.setProperty("hibernate.default_schema", dbPlugin.getSchema());
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.show_sql", "false");
properties.setProperty("hibernate.format_sql", "false");
return properties;
}

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {

Check warning on line 66 in src/main/java/fr/insalyon/creatis/gasw/DatabaseConfiguration.java

View workflow job for this annotation

GitHub Actions / all

Parameter 'emf' is not assigned and could be declared final

Reports method and constructor parameters that can be made final because they are never reassigned within the body of the method. This rule ignores unused parameters so as not to overlap with the rule {% rule java/bestpractices/UnusedFormalParameter %}. It will also ignore the parameters of abstract methods. MethodArgumentCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#methodargumentcouldbefinal
return new JpaTransactionManager(emf);
}
}
153 changes: 113 additions & 40 deletions src/main/java/fr/insalyon/creatis/gasw/Gasw.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,70 +32,143 @@
*/
package fr.insalyon.creatis.gasw;

import fr.insalyon.creatis.gasw.bean.SEEntryPoint;
import fr.insalyon.creatis.gasw.bean.SEEntryPointID;
import fr.insalyon.creatis.gasw.dao.DAOException;
import fr.insalyon.creatis.gasw.dao.SEEntryPointsDAO;
import fr.insalyon.creatis.gasw.execution.ExecutorFactory;
import fr.insalyon.creatis.gasw.execution.FailOver;
import fr.insalyon.creatis.gasw.plugin.ExecutorPlugin;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import fr.insalyon.creatis.gasw.plugin.ListenerPlugin;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
public class Gasw {

Check warning on line 59 in src/main/java/fr/insalyon/creatis/gasw/Gasw.java

View workflow job for this annotation

GitHub Actions / all

Avoid short class names like Gasw

Short Classnames with fewer than e.g. five characters are not recommended. ShortClassName (Priority: 4, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#shortclassname
private static final Logger logger = LoggerFactory.getLogger(Gasw.class);
private static Gasw instance;
private GaswNotification notification;

/**
* Gets a default instance of GASW.
*
* @return Instance of GASW
*/
public synchronized static Gasw getInstance() throws GaswException {

if (instance == null) {
instance = new Gasw();

private final Logger logger = LoggerFactory.getLogger(getClass());

private final GaswConfiguration config;
private final GaswNotification gaswNotification;
private final ExecutorFactory executorFactory;
private final SEEntryPointsDAO seEntryPointsDAO;
private final List<ExecutorPlugin> executorPlugins;
private final List<ListenerPlugin> listenerPlugins;

public Gasw(GaswConfiguration config, GaswNotification gaswNotification, ExecutorFactory executorFactory,

Check warning on line 70 in src/main/java/fr/insalyon/creatis/gasw/Gasw.java

View workflow job for this annotation

GitHub Actions / all

Parameter 'executorFactory' is not assigned and could be declared final

Reports method and constructor parameters that can be made final because they are never reassigned within the body of the method. This rule ignores unused parameters so as not to overlap with the rule {% rule java/bestpractices/UnusedFormalParameter %}. It will also ignore the parameters of abstract methods. MethodArgumentCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#methodargumentcouldbefinal

Check warning on line 70 in src/main/java/fr/insalyon/creatis/gasw/Gasw.java

View workflow job for this annotation

GitHub Actions / all

Parameter 'gaswNotification' is not assigned and could be declared final

Reports method and constructor parameters that can be made final because they are never reassigned within the body of the method. This rule ignores unused parameters so as not to overlap with the rule {% rule java/bestpractices/UnusedFormalParameter %}. It will also ignore the parameters of abstract methods. MethodArgumentCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#methodargumentcouldbefinal

Check warning on line 70 in src/main/java/fr/insalyon/creatis/gasw/Gasw.java

View workflow job for this annotation

GitHub Actions / all

Parameter 'config' is not assigned and could be declared final

Reports method and constructor parameters that can be made final because they are never reassigned within the body of the method. This rule ignores unused parameters so as not to overlap with the rule {% rule java/bestpractices/UnusedFormalParameter %}. It will also ignore the parameters of abstract methods. MethodArgumentCouldBeFinal (Priority: 3, Ruleset: Code Style) https://docs.pmd-code.org/snapshot/pmd_rules_java_codestyle.html#methodargumentcouldbefinal
SEEntryPointsDAO seEntryPointsDAO, List<ExecutorPlugin> executorPlugins, List<ListenerPlugin> listenerPlugins) {
this.config = config;
this.gaswNotification = gaswNotification;
this.executorFactory = executorFactory;
this.seEntryPointsDAO = seEntryPointsDAO;
this.executorPlugins = executorPlugins;
this.listenerPlugins = listenerPlugins;
}

@PostConstruct
public void init() throws GaswException {
if (config.isFailOverEnabled()) {
loadSEEntryPoints();
}
return instance;
}

private Gasw() throws GaswException {
try {
logger.info("Initializing GASW.");
GaswConfiguration.getInstance().loadHibernate();
// Log loaded plugins after all beans creation
@EventListener(ContextRefreshedEvent.class)
public void logPlugins() {
executorPlugins.forEach(p ->
logger.info("Loaded executor plugin '{}' version '{}'",
p.getName(), p.getClass().getPackage().getImplementationVersion()));
listenerPlugins.forEach(p ->
logger.info("Loaded listener plugin '{}' version '{}'",
p.getName(), p.getClass().getPackage().getImplementationVersion()));
}

notification = GaswNotification.getInstance();
@PreDestroy
public void terminate() throws GaswException {
terminate(false);
}

} catch (IllegalArgumentException ex) {
throw new GaswException(ex);
public void terminate(boolean force) throws GaswException {
gaswNotification.terminate();
for (ExecutorPlugin executorPlugin : executorPlugins) {
executorPlugin.terminate(force);
}
}

public synchronized void setNotificationClient(Object client) {
notification.setClient(client);
for (ListenerPlugin listenerPlugin : listenerPlugins) {
listenerPlugin.terminate();
}
}

public synchronized String submit(GaswInput gaswInput) throws GaswException {

ExecutorPlugin executor = ExecutorFactory.getExecutor(gaswInput);
executor.load(gaswInput);
return executor.submit();
public void setNotificationClient(Object client) {
gaswNotification.setNotificationClient(client);
}

public synchronized List<GaswOutput> getFinishedJobs() {
return notification.getFinishedJobs();
public String submit(GaswInput gaswInput) throws GaswException {
return executorFactory.getExecutor().submit(gaswInput);
}

public synchronized void waitForNotification() {
notification.waitForNotification();
public List<GaswOutput> getFinishedJobs() {
return gaswNotification.getFinishedJobs();
}

public synchronized void terminate(boolean force) throws GaswException {
notification.terminate();
private void loadSEEntryPoints() throws GaswException {
try {
logger.info("Loading SEs entry points.");
ProcessBuilder builder = new ProcessBuilder("lcg-info", "--list-service",
"--vo", config.getVoName(), "--attrs", "ServiceEndpoint");

builder.redirectErrorStream(true);
Process process = builder.start();

BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s = null;
StringBuilder cout = new StringBuilder();

while ((s = r.readLine()) != null) {
cout.append(s);
if (s.startsWith("- Service: httpg://")) {
try {
URI service = new URI(s.split(" ")[2]);
seEntryPointsDAO.add(
new SEEntryPoint(new SEEntryPointID(
service.getHost(), service.getPort()),
service.getPath()));

} catch (URISyntaxException ex) {
logger.warn("Unable to read end point from: {}", s);
} catch (DAOException ex) {
if (!ex.getMessage().contains("duplicate key value")) {
logger.warn("Unable to save end point: {}", ex.getMessage());
}
}
}
}
r.close();
process.waitFor();

if (process.exitValue() != 0) {
logger.error(cout.toString());
throw new GaswException("Unable to load SEs entry points.");
}
} catch (InterruptedException ex) {
logger.error("Error:", ex);
throw new GaswException(ex);

if (GaswConfiguration.getInstance().isFailOverEnabled()) {
FailOver.getInstance().terminate();
} catch (IOException ex) {
logger.error("Error:", ex);
throw new GaswException(ex);
}

GaswConfiguration.getInstance().terminate(force);
}
}
Loading
Loading