Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugs/5973 alter to use logo #64

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
9 changes: 8 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,17 @@ COPY ./geonetwork-core/target/classes/log4j-imos-index.xml ${GN_DIR}/WEB-INF/cla
# Copy our jar to the lib folder so that scan can happens
COPY ./geonetwork-core/target/geonetwork4-*.jar ${GN_DIR}/WEB-INF/lib/
COPY ./geonetwork-api/target/geonetwork-api-*.jar ${GN_DIR}/WEB-INF/lib/
# Copy deps that missing
COPY ./geonetwork-core/target/dependency/jackson-dataformat-xml-*.jar ${GN_DIR}/WEB-INF/lib/
COPY ./geonetwork-core/target/dependency/stax2-api-*.jar ${GN_DIR}/WEB-INF/lib/
COPY ./geonetwork-core/target/dependency/spring-boot-actuator-*.jar ${GN_DIR}/WEB-INF/lib/
COPY ./geonetwork-core/target/dependency/spring-boot-actuator-autoconfigure-*.jar ${GN_DIR}/WEB-INF/lib/
COPY ./geonetwork-core/target/dependency/underscore-*.jar ${GN_DIR}/WEB-INF/lib/

COPY ./geonetwork-core/target/dependency/* ${GN_DIR}/WEB-INF/lib/
COPY ./geonetwork-core/target/classes/schema_plugins/converter/*.xsl ${GN_DIR}/WEB-INF/data/config/schema_plugins/iso19139/process/
COPY ./geonetwork-core/target/classes/schema_plugins/converter/*.xsl ${GN_DIR}/WEB-INF/data/config/schema_plugins/iso19115-3.2018/process/

COPY ./geonetwork-core/target/classes/schema_plugins/iso19115-3.2018/formatter/*.xsl ${GN_DIR}/WEB-INF/data/config/schema_plugins/iso19115-3.2018/formatter/xsl-view/

# Config override
COPY ./geonetwork-core/target/classes/gnconfig/config-overrides.xml ${GN_DIR}/WEB-INF/
93 changes: 52 additions & 41 deletions geonetwork-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,58 +79,69 @@
</resource>
</resources>
<plugins>
<!-- Copy missing jar to the target/dependency folder, the Dockerfile will copy everything from there-->
<!-- Copy missing single jar to the target/dependency folder, the Dockerfile will copy everything from there-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<id>copy-jar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>stax2-api</artifactId>
<version>${stax2.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<version>${springboot.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<version>${springboot.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>com.github.javadev</groupId>
<artifactId>underscore</artifactId>
<version>${underscore.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>copy-deps</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<includeTypes>jar</includeTypes> <!-- Specify types to include -->
</configuration>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>stax2-api</artifactId>
<version>${stax2.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<version>${springboot.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<version>${springboot.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>com.github.javadev</groupId>
<artifactId>underscore</artifactId>
<version>${underscore.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package au.org.aodn.geonetwork4;

import au.org.aodn.geonetwork_api.openapi.invoker.ApiClient;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.fao.geonet.api.records.formatters.FormatterParams;

import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;

import javax.annotation.PostConstruct;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

/**
* This class is used to add AspectJ support to the geonetwork. Mainly override or intercept function call
* that is not possible without alter the code of geonetwork.
*/
@Aspect
@Configuration
@EnableAspectJAutoProxy
public class AspectConfig {

protected Logger logger = LoggerFactory.getLogger(AspectConfig.class);

@Pointcut("execution(public * org.fao.geonet.api.records.formatters.XsltFormatter.format(org.fao.geonet.api.records.formatters.FormatterParams))")
public void interceptFormatter() {}
/**
* Use aspectJ to intercept all call that ends with WithHttpInfo, we must always use geonetwork api call
* ends with WithHttpInfo because the way geonetworks works is you must present an X-XSRF-TOKEN and session
* in the call with username password, otherwise it will fail.
* You need to make an init call to get the X-XSRF-TOKEN, the call will have status forbidden
* and comes back with the token in cookie, then you need to set the token before next call.
*/
@Pointcut("execution(public * au.org.aodn.geonetwork_api.openapi.api..*.*WithHttpInfo(..))")
public void interceptWithHttpInfo() {}

@Around("interceptWithHttpInfo()")
public ResponseEntity<?> aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
try {
return (ResponseEntity<?>) joinPoint.proceed();
}
catch(HttpClientErrorException.Forbidden e) {
// cookie format is like this
// XSRF-TOKEN=634f5b0d-49b6-43a6-a995-c7cb0db9eb64; Path=/geonetwork
String cookie = e.getResponseHeaders().getFirst(HttpHeaders.SET_COOKIE);
String token = cookie.split(";")[0].split("=")[1].trim();

// All these api object have the getApiClient() method
Method method = joinPoint.getTarget().getClass().getMethod("getApiClient");
ApiClient apiClient = (ApiClient)method.invoke(joinPoint.getTarget());

logger.info("Setting X-XSRF-TOKEN for {} to {}", joinPoint.getTarget().getClass(), token);
apiClient.addDefaultHeader("X-XSRF-TOKEN", token);
apiClient.addDefaultCookie("XSRF-TOKEN", token);

return (ResponseEntity<?>)joinPoint.proceed();
}
}
/**
* Use to intercept the formatter to provide a post-processing transformation. That is after the original transform
* you got a chance to do additional transformation based on the output content. By doing so you just need to
* add a post-processing.xsl in the same folder, and it will work without duplicate or create new view.xsl
* @param joinPoint - Aspect call param for @Around
* @return - A post-processed string
* @throws Throwable - Not expect to have this throw
*/
@Around("interceptFormatter()")
public Object afterProcessingXslt(ProceedingJoinPoint joinPoint) throws Throwable {
if(joinPoint.getArgs()[0] instanceof FormatterParams) {
FormatterParams params = (FormatterParams)joinPoint.getArgs()[0];

// Expect a string of html after processing
Object value = joinPoint.proceed();

Path p = Paths.get(params.formatDir + "/post-processing.xsl");
if(Files.exists(p)) {
try {
Source xslt = new StreamSource(p.toFile());
// Input source (XHTML), but need to remove the extra tag as this is not valid during transformation
Source text = new StreamSource(
new StringReader(value.toString().replaceAll("<!DOCTYPE[^>]*>", ""))
);

TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xslt);

// Set the parameter value
transformer.setParameter("xml", params.metadataInfo.asXml());

// Output destination
StringWriter outputWriter = new StringWriter();

// Perform the transformation
transformer.transform(text, new StreamResult(outputWriter));
// Add back the tag
return "<!DOCTYPE div\n SYSTEM \"html\">" + outputWriter;
}
catch(Exception e) {
logger.error("Error in post-processing", e);
}
}
return value;
}
else {
throw new RuntimeException("Format function call expected FormatterParams args");
}
}

@PostConstruct
public void init() {
logger.info("Init XsltConfig completed");
}
}
59 changes: 21 additions & 38 deletions geonetwork-core/src/main/java/au/org/aodn/geonetwork4/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import org.fao.geonet.api.records.formatters.XsltFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.*;
Expand All @@ -28,21 +25,16 @@
import org.fao.geonet.ApplicationContextHolder;

import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.util.DefaultUriBuilderFactory;

import java.lang.reflect.Method;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;

@Aspect
@Configuration
/*
* EnableAutoConfiguration so that Actuator can config automatically, however, the
Expand All @@ -54,7 +46,6 @@
org.springdoc.webmvc.core.SpringDocWebMvcConfiguration.class,
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration.class
})
@EnableAspectJAutoProxy
@PropertySources({
@PropertySource("classpath:application.properties"),
@PropertySource(
Expand All @@ -73,43 +64,32 @@ public class Config {

@Autowired
protected GenericEntityListener genericEntityListener;
/**
* This is an aspectj based formatter in the parent context.
*/
@Autowired
protected XsltFormatter aspectJXsltFormatter;

/**
* Use aspectJ to intercept all call that ends with WithHttpInfo, we must always use geonetwork api call
* ends with WithHttpInfo because the way geonetworks works is you must present an X-XSRF-TOKEN and session
* in the call with username password, otherwise it will fail.
* You need to make an init call to get the X-XSRF-TOKEN, the call will have status forbidden
* and comes back with the token in cookie, then you need to set the token before next call.
* This is used to swap a bean in the real context that operated which is not current parent context!
*
* @param beanName - The name of the bean you want to swap
* @param bean - Replace by this bean
*/
@Pointcut("execution(public * au.org.aodn.geonetwork_api.openapi.api..*.*WithHttpInfo(..))")
public void interceptWithHttpInfo() {}
public <T> void swapBean(String beanName, T bean) {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ApplicationContextHolder.get().getBeanFactory();

@Around("interceptWithHttpInfo()")
public ResponseEntity<?> aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
try {
return (ResponseEntity<?>) joinPoint.proceed();
// Remove the old bean
if (beanFactory.containsBean(beanName)) {
beanFactory.destroySingleton(beanName);
}
catch(HttpClientErrorException.Forbidden e) {
// cookie format is like this
// XSRF-TOKEN=634f5b0d-49b6-43a6-a995-c7cb0db9eb64; Path=/geonetwork
String cookie = e.getResponseHeaders().getFirst(HttpHeaders.SET_COOKIE);
String token = cookie.split(";")[0].split("=")[1].trim();

// All these api object have the getApiClient() method
Method method = joinPoint.getTarget().getClass().getMethod("getApiClient");
ApiClient apiClient = (ApiClient)method.invoke(joinPoint.getTarget());

logger.info("Setting X-XSRF-TOKEN for {} to {}", joinPoint.getTarget().getClass(), token);
apiClient.addDefaultHeader("X-XSRF-TOKEN", token);
apiClient.addDefaultCookie("XSRF-TOKEN", token);

return (ResponseEntity<?>)joinPoint.proceed();
}
// Register the new singleton instance
beanFactory.registerSingleton(beanName, bean);
}

@PostConstruct
public void init() throws NoSuchAlgorithmException, KeyManagementException {
logger.info("AODN - Done set logger info");
logger.info("Using git branch {} for setup", gitBranch);

/*
Expand All @@ -125,6 +105,9 @@ public void init() throws NoSuchAlgorithmException, KeyManagementException {
*/
ConfigurableApplicationContext jeevesContext = ApplicationContextHolder.get();
jeevesContext.getBeanFactory().registerSingleton("genericEntityListener", genericEntityListener);

// We need to swap with the aspectj bean
swapBean("xsltFormatter", aspectJXsltFormatter);
}
/**
* The reason we need is to set the WEB_ROOT context to be used by Actuator. In springboot application it is
Expand Down
5 changes: 5 additions & 0 deletions geonetwork-core/src/main/resources/log4j-imos.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@
<AppenderRef ref="File"/>
</Logger>

<Logger name="org.aspectj.weaver" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Logger>

<Logger name="au.org.aodn.geonetwork_api" level="debug" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
Expand Down
Loading
Loading