Skip to content

Commit

Permalink
Merge pull request #270 from digipost/remove-spring-dependency
Browse files Browse the repository at this point in the history
Remove spring dependency
  • Loading branch information
Simen Støa authored Feb 15, 2023
2 parents e494e00 + d672386 commit 0129c91
Show file tree
Hide file tree
Showing 14 changed files with 361 additions and 294 deletions.
15 changes: 8 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [ '1.8', '11' ]
java: [ '8', '11' ]

name: build java ${{ matrix.java }}
steps:
- uses: actions/checkout@v1
- name: Set up java
uses: actions/setup-java@v1
- uses: actions/checkout@v3
- uses: actions/[email protected]
with:
distribution: temurin
java-version: ${{ matrix.java }}
cache: "maven"
- name: Build with Maven
run: mvn -B package --no-transfer-progress --file pom.xml
run: mvn -B clean verify --no-transfer-progress --show-version

makeversion:
if: github.ref != 'refs/heads/main'
Expand All @@ -44,7 +45,7 @@ jobs:
name: Deploy snapshot
steps:
- uses: actions/checkout@v1
- uses: digipost/action-maven-publish@1.1.0
- uses: digipost/action-maven-publish@1.3.0
with:
sonatype_secrets: ${{ secrets.sonatype_secrets }}
release_version: ${{ needs.makeversion.outputs.version }}
Expand All @@ -59,7 +60,7 @@ jobs:
- name: Check out Git repository
uses: actions/checkout@v1
- name: Release to Central Repository
uses: digipost/action-maven-publish@1.1.0
uses: digipost/action-maven-publish@1.3.0
with:
sonatype_secrets: ${{ secrets.sonatype_secrets }}
release_version: ${{ needs.makeversion.outputs.version }}
Expand Down
45 changes: 11 additions & 34 deletions jaxb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,7 @@
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.8.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>5.3.13</version>
<version>5.9.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand All @@ -45,7 +38,7 @@
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.5</version>
<version>2.3.6</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -60,16 +53,6 @@
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand Down Expand Up @@ -101,37 +84,31 @@
<dependency>
<groupId>nl.jqno.equalsverifier</groupId>
<artifactId>equalsverifier</artifactId>
<version>3.8</version>
<version>3.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.javers</groupId>
<artifactId>javers-core</artifactId>
<version>6.5.3</version>
<version>6.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>no.digipost</groupId>
<artifactId>digg</artifactId>
<version>0.30</version>
<version>0.33</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.32</version>
<artifactId>slf4j-api</artifactId>
<version>2.0.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.32</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-xml</artifactId>
<version>3.1.1</version>
<version>2.0.5</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand All @@ -146,7 +123,7 @@
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.1</version>
<version>3.4.1</version>
<configuration>
<excludePackageNames>no.digipost.signature.api.xml.*</excludePackageNames>
<detectOfflineLinks>false</detectOfflineLinks>
Expand All @@ -163,7 +140,7 @@
<plugin>
<groupId>com.github.siom79.japicmp</groupId>
<artifactId>japicmp-maven-plugin</artifactId>
<version>0.15.4</version>
<version>0.17.1</version>
<configuration>
<oldVersion>
<dependency>
Expand Down Expand Up @@ -228,7 +205,7 @@
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.5</version>
<version>2.3.6</version>
</dependency>
</dependencies>
<configuration>
Expand Down
209 changes: 209 additions & 0 deletions jaxb/src/main/java/no/digipost/signature/jaxb/JaxbMarshaller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*
* Copyright (C) Posten Norge AS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package no.digipost.signature.jaxb;

import no.digipost.signature.xsd.SignatureApiSchemas;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.net.URL;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;

/**
* @see JaxbMarshaller.ForResponsesOfAllApis
* @see JaxbMarshaller.ForRequestsOfAllApis
*/
public class JaxbMarshaller {

/**
* Marshaller for creating requests for both the Direct and Portal API.
* This marshaller will validate if the XML generated from marshalled Java objects
* adheres to the API schemas.
*/
public static class ForRequestsOfAllApis extends JaxbMarshaller {

public static JaxbMarshaller singleton() {
return SingletonHolder.instance;
}

private static final class SingletonHolder {
private static final JaxbMarshaller instance = new JaxbMarshaller.ForRequestsOfAllApis();
}

public ForRequestsOfAllApis() {
super(SignatureMarshalling.allApiRequestClasses(), SignatureApiSchemas.DIRECT_AND_PORTAL_API);
}
}


/**
* Marshaller (unmarshaller) for reading responses from both the Direct and Portal API.
* This marshaller does <em>not</em> validate the XML before attempting to unmarshal it to Java objects.
*/
public static class ForResponsesOfAllApis extends JaxbMarshaller {

public static JaxbMarshaller singleton() {
return SingletonHolder.instance;
}

private static final class SingletonHolder {
private static final JaxbMarshaller instance = new JaxbMarshaller.ForResponsesOfAllApis();
}

public ForResponsesOfAllApis() {
super(SignatureMarshalling.allApiResponseClasses());
}
}



/**
* Marshaller for both the Direct and Portal API.
* <p><strong>
* This marshaller is intended only to be used internally by Posten signering, as both
* requests and responses are validated against schemas. A 3rd party client should <em>not</em>
* validate responses from the API.
* </strong>
*
* @see JaxbMarshaller.ForResponsesOfAllApis
* @see JaxbMarshaller.ForRequestsOfAllApis
*/
public static class ForAllApis extends JaxbMarshaller {

public static JaxbMarshaller singleton() {
return SingletonHolder.instance;
}

private static final class SingletonHolder {
private static final JaxbMarshaller instance = new JaxbMarshaller.ForAllApis();
}

public ForAllApis() {
super(SignatureMarshalling.allApiClasses(), SignatureApiSchemas.DIRECT_AND_PORTAL_API);
}
}

private static InputSource createInputSource(String resource) {
URL resourceUrl = requireNonNull(JaxbMarshaller.class.getResource(resource), resource);
try (InputStream inputStream = resourceUrl.openStream()) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

final int bufLen = 1024;
byte[] buf = new byte[bufLen];
int readLen;
while ((readLen = inputStream.read(buf, 0, bufLen)) != -1)
outputStream.write(buf, 0, readLen);

InputSource source = new InputSource(new ByteArrayInputStream(outputStream.toByteArray()));
source.setSystemId(resourceUrl.toString());
return source;
} catch (IOException e) {
throw new UncheckedIOException(
"Unable to resolve " + resource + " from " + resourceUrl + ", " +
"because " + e.getClass().getSimpleName() + " '" + e.getMessage() + "'", e);
}
}

private static Schema createSchema(Collection<String> resources) {
try {
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
parserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);

SAXParser saxParser = parserFactory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
Source[] schemaSources = resources.stream()
.map(resource -> new SAXSource(xmlReader, createInputSource(resource)))
.toArray(Source[]::new);

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(schemaSources);
return schema;
} catch (Exception e) {
throw new RuntimeException("Could not create schema from resources [" + String.join(", ", resources) + "]", e);
}
}

private static JAXBContext initContext(Collection<Class<?>> classes) {
Class<?>[] classesToBeBound = classes.toArray(new Class[classes.size()]);
try {
return JAXBContext.newInstance(classesToBeBound);
} catch (JAXBException e) {
throw new RuntimeException("Could not create JAXBContext for classes [" + Stream.of(classesToBeBound).map(Class::getSimpleName).collect(joining(",")) + "]" , e);
}
}

private final JAXBContext jaxbContext;
private final Optional<Schema> schema;

public JaxbMarshaller(Set<Class<?>> classes, Set<String> schemaResources) {
this.jaxbContext = initContext(classes);
this.schema = Optional.ofNullable(schemaResources).filter(s -> !s.isEmpty()).map(JaxbMarshaller::createSchema);
}

public JaxbMarshaller(Set<Class<?>> classes) {
this(classes, null);
}

public void marshal(Object object, OutputStream outputStream){
try {
Marshaller marshaller = jaxbContext.createMarshaller();
schema.ifPresent(marshaller::setSchema);
marshaller.marshal(object, outputStream);
} catch (Exception e) {
throw new SignatureMarshalException("Failed marshalling " + (object != null ? object.getClass().getName() : "null") + " to XML", e);
}
}

public <T> T unmarshal(InputStream inputStream, Class<T> type){
try {
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
schema.ifPresent(unmarshaller::setSchema);
return type.cast(unmarshaller.unmarshal(inputStream));
} catch (Exception e) {
throw new SignatureMarshalException("Failed unmarshalling XML to " + type.getName(), e);
}
}

public <T> T unmarshal(byte[] bytes, Class<T> type) {
return unmarshal(new ByteArrayInputStream(bytes), type);
}

}
Loading

0 comments on commit 0129c91

Please sign in to comment.