Reorganizing to a parent project, a light and a heavy (validating) library, a commandline application and the server
This commit is contained in:
51
Mustang-Server/src/main/java/api/ApiApplication.java
Normal file
51
Mustang-Server/src/main/java/api/ApiApplication.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package api;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||
import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
|
||||
|
||||
import io.dropwizard.Application;
|
||||
import io.dropwizard.auth.AuthDynamicFeature;
|
||||
import io.dropwizard.auth.AuthValueFactoryProvider;
|
||||
import io.dropwizard.auth.basic.BasicCredentialAuthFilter;
|
||||
import io.dropwizard.setup.Bootstrap;
|
||||
import io.dropwizard.setup.Environment;
|
||||
import io.federecio.dropwizard.swagger.SwaggerBundle;
|
||||
import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
|
||||
import mustang.MustangResource;
|
||||
|
||||
public class ApiApplication extends Application<ApiConfiguration> {
|
||||
public static void main(String[] args) throws Exception {
|
||||
new ApiApplication().run(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Mustang Server";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(Bootstrap<ApiConfiguration> bootstrap) {
|
||||
|
||||
bootstrap.addBundle(new SwaggerBundle<ApiConfiguration>() {
|
||||
@Override
|
||||
protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(ApiConfiguration configuration) {
|
||||
return configuration.swaggerBundleConfiguration;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(ApiConfiguration configuration, Environment environment) {
|
||||
final MustangResource resource = new MustangResource();
|
||||
|
||||
environment.jersey()
|
||||
.register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>()
|
||||
.setAuthenticator(new BasicAuthenticator()).setAuthorizer(new BasicAuthorizer())
|
||||
.setRealm("Rest API access").buildAuthFilter()));
|
||||
environment.jersey().register(RolesAllowedDynamicFeature.class);
|
||||
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
|
||||
environment.jersey().register(MultiPartFeature.class);
|
||||
environment.jersey().register(resource);
|
||||
}
|
||||
|
||||
}
|
||||
12
Mustang-Server/src/main/java/api/ApiConfiguration.java
Normal file
12
Mustang-Server/src/main/java/api/ApiConfiguration.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package api;
|
||||
import io.dropwizard.Configuration;
|
||||
import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class ApiConfiguration extends Configuration {
|
||||
|
||||
@JsonProperty("swagger")
|
||||
public SwaggerBundleConfiguration swaggerBundleConfiguration;
|
||||
|
||||
}
|
||||
18
Mustang-Server/src/main/java/api/BasicAuthenticator.java
Normal file
18
Mustang-Server/src/main/java/api/BasicAuthenticator.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package api;
|
||||
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import io.dropwizard.auth.AuthenticationException;
|
||||
import io.dropwizard.auth.Authenticator;
|
||||
import io.dropwizard.auth.basic.BasicCredentials;
|
||||
|
||||
public class BasicAuthenticator implements Authenticator<BasicCredentials, User> {
|
||||
@Override
|
||||
public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {
|
||||
if ("secret".equals(credentials.getPassword())) {
|
||||
return Optional.of(new User(credentials.getUsername()));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
11
Mustang-Server/src/main/java/api/BasicAuthorizer.java
Normal file
11
Mustang-Server/src/main/java/api/BasicAuthorizer.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package api;
|
||||
|
||||
|
||||
import io.dropwizard.auth.Authorizer;
|
||||
|
||||
public class BasicAuthorizer implements Authorizer<User> {
|
||||
@Override
|
||||
public boolean authorize(User user, String role) {
|
||||
return user.getName().equals("good-guy") && role.equals("ADMIN");
|
||||
}
|
||||
}
|
||||
15
Mustang-Server/src/main/java/api/User.java
Normal file
15
Mustang-Server/src/main/java/api/User.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package api;
|
||||
|
||||
import io.dropwizard.auth.PrincipalImpl;
|
||||
|
||||
public class User extends PrincipalImpl {
|
||||
String username;
|
||||
|
||||
public User(String name) {
|
||||
super(name);
|
||||
username=name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
146
Mustang-Server/src/main/java/mustang/MustangResource.java
Normal file
146
Mustang-Server/src/main/java/mustang/MustangResource.java
Normal file
@@ -0,0 +1,146 @@
|
||||
package mustang;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
import org.mustangproject.ZUGFeRD.ZUGFeRDConformanceLevel;
|
||||
import org.mustangproject.ZUGFeRD.ZUGFeRDExporter;
|
||||
import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromA1Factory;
|
||||
import org.mustangproject.ZUGFeRD.ZUGFeRDImporter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.itextpdf.text.Document;
|
||||
import com.itextpdf.text.DocumentException;
|
||||
import com.itextpdf.text.pdf.PdfWriter;
|
||||
import com.itextpdf.tool.xml.XMLWorkerHelper;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.annotations.License;
|
||||
import io.swagger.annotations.Info;
|
||||
import io.swagger.annotations.SwaggerDefinition;
|
||||
|
||||
@Path("/mustang")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Api(value = "Mustang")
|
||||
@SwaggerDefinition(info=@Info(
|
||||
description = "Rest API to read/write hybrid (ZUGFeRD/Factur-X) e-invoices with a Mustang Server",
|
||||
version = "V0.0.2",
|
||||
title = "Mustangproject API",
|
||||
license = @License(name = "Apache 2.0", url = "http://www.apache.org")
|
||||
|
||||
),
|
||||
schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS}
|
||||
)
|
||||
public class MustangResource {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(MustangResource.class.getName());
|
||||
|
||||
public MustangResource() {
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/extract")
|
||||
//@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Produces(MediaType.APPLICATION_XML)
|
||||
@ApiOperation(value="Extracts XML from a zf/fx PDF",notes="Input PDF must be ZUGFeRD or Factur-X")
|
||||
public String extractFile(@ApiParam(required=true,value="Input ZUGFeRD/Factur-X file") @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) {
|
||||
|
||||
ZUGFeRDImporter zi;
|
||||
logger.debug("Reading...");
|
||||
zi = new ZUGFeRDImporter(fileInputStream);
|
||||
return "<response>"+zi.getUTF8()+"</response>";
|
||||
}
|
||||
|
||||
|
||||
@POST
|
||||
@Path("/combine")
|
||||
@RolesAllowed("ADMIN")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
@ApiOperation(value="Combine PDF file and custom XML to zf/fx PDF",notes="Input PDF must be PDF/A-1, output PDF will be a ZUGFeRD/Factur-X PDF/A-3 file called invoice.pdf. Demo authentication good-guy:secret")
|
||||
public Response combineFile(@ApiParam(required=true,value="Input PDF/A-1 file") @FormDataParam("file") final InputStream fileInputStream,
|
||||
@FormDataParam("file") final FormDataContentDisposition contentDispositionHeader,
|
||||
@ApiParam(required=true, value="The zf/fx XML to add to the file") @FormDataParam("xml") String XML,
|
||||
@ApiParam(required=true, defaultValue="zf", value="zf|fx:zf for ZUGFeRD, fx for Factur-X") @FormDataParam("format") String format,
|
||||
@ApiParam(required=true, defaultValue="2", value="version, i.e. fx 1 or zf 1 or 2") @FormDataParam("version") int version,
|
||||
@ApiParam(required=true, defaultValue="EN16931", value="Profile: BASIC|COMFORT|EXTENDED for zf1, MINIMUM|BASICWL|BASIC|CIUS|EN16931|EXTENDED for zf2/fx1") @FormDataParam("profile") String profile
|
||||
) {
|
||||
|
||||
ZUGFeRDExporter ze;
|
||||
ByteArrayOutputStream output=new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
logger.debug("Converting to PDF/A-3u");
|
||||
|
||||
if ((version<1)||(version>2)) {
|
||||
// this should be checked with annotations but I did not get it to work
|
||||
throw new IllegalArgumentException("invalid version");
|
||||
}
|
||||
|
||||
// this should be restricted to the enum with annotations but I did not get it to work
|
||||
ZUGFeRDConformanceLevel prof=ZUGFeRDConformanceLevel.valueOf(profile);
|
||||
/*
|
||||
* Add .setZUGFeRDVersion and .setZUGFeRDConformanceLevel in the next lines to
|
||||
* set the ZUGFeRD version respective profile of the XML you are inserting.
|
||||
*/
|
||||
ze = new ZUGFeRDExporterFromA1Factory().setProducer("Mustang API")
|
||||
.setCreator(System.getProperty("user.name"))
|
||||
.setZUGFeRDVersion(version)
|
||||
.setZUGFeRDConformanceLevel(prof)
|
||||
.load(fileInputStream);
|
||||
logger.debug("Attaching ZUGFeRD-Data");
|
||||
if (format.equalsIgnoreCase("fx")) {
|
||||
ze.setFacturX();
|
||||
}
|
||||
ze.setZUGFeRDXMLData(XML.getBytes("UTF-8"));
|
||||
logger.debug("Writing ZUGFeRD-PDF");
|
||||
|
||||
ze.export(output);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
byte[] bytes = output.toByteArray();
|
||||
InputStream inputStream = new ByteArrayInputStream(bytes);
|
||||
|
||||
return Response.ok(inputStream)
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"invoice.pdf\"")
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/test")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@ApiOperation(value="Returns a hello world",notes="Just a test")
|
||||
public Response test() {
|
||||
|
||||
return Response.status(Response.Status.OK)
|
||||
.entity("{\"payload\":\"test\"}")
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
50
Mustang-Server/src/test/java/mustangAPI/IntegrationTest.java
Normal file
50
Mustang-Server/src/test/java/mustangAPI/IntegrationTest.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package mustangAPI;
|
||||
|
||||
import javax.ws.rs.client.Client;
|
||||
import javax.ws.rs.client.ClientBuilder;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
|
||||
import api.ApiApplication;
|
||||
|
||||
public class IntegrationTest {
|
||||
/*@ClassRule
|
||||
public static final DropwizardAppRule<ApiConfiguration> RULE
|
||||
= new DropwizardAppRule<>(ApiApplication.class,
|
||||
"config.yml");
|
||||
@Test
|
||||
public void testGetGreeting() {
|
||||
//test w/ssl
|
||||
* //Create SSL Configurator
|
||||
SslConfigurator sslConfigurator = SslConfigurator.newInstance();
|
||||
//Register a keystore
|
||||
sslConfigurator.trustStoreFile("dwstart.keystore")
|
||||
.trustStorePassword("crimson");
|
||||
//Create SSL Context
|
||||
SSLContext sSLContext = sslConfigurator.createSSLContext();
|
||||
//Obtain client
|
||||
Client client = ClientBuilder
|
||||
.newBuilder()
|
||||
.sslContext(sSLContext)
|
||||
.build();
|
||||
|
||||
|
||||
|
||||
|
||||
String expected = "Hello world!";
|
||||
//Obtain client
|
||||
Client client = ClientBuilder.newClient();
|
||||
//Build a feature in basic authentication mode
|
||||
HttpAuthenticationFeature feature
|
||||
= HttpAuthenticationFeature.basic("javaeeeee", "crimson");
|
||||
//Register the feature
|
||||
client.register(feature);
|
||||
//Get actual resul string
|
||||
String actual = client
|
||||
.target("http://localhost:8080/secured_hello")
|
||||
.request(MediaType.TEXT_PLAIN)
|
||||
.get(String.class);
|
||||
//Do an assertion
|
||||
assertEquals(expected, actual);
|
||||
}*/
|
||||
}
|
||||
Reference in New Issue
Block a user