diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..f2a4093411b9d987ba9caaef3a061f4f9dedf125 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +**/target \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..526c8a38d4a53c339833267bbf86577f023ec507 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf \ No newline at end of file diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..bf82ff01c6cdae4a1bb754a6e062954d77ac5c11 Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..dc3affce3dd4f4021b9e9564ceab2f5985746d7b --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# https://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. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/COPYING.LGPL b/COPYING.LGPL new file mode 100644 index 0000000000000000000000000000000000000000..02bbb60bc49afc2d6a1bedf96288eab236d80fbd --- /dev/null +++ b/COPYING.LGPL @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000000000000000000000000000000000000..5b8051e864ec4404fa01b71c778f048d38618275 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,19 @@ +Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + +Licensed under the EUPL, Version 1.1 or – as soon they +will be approved by the European Commission - subsequent +versions of the EUPL (the "Licence"); + +You may not use this work except in compliance with the Licence. + +You may obtain a copy of the Licence at: + +https://joinup.ec.europa.eu/community/eupl/og_page/eupl + +Unless required by applicable law or agreed to in +writing, software distributed under the Licence is +distributed on an "AS IS" basis, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +express or implied. +See the Licence for the specific language governing +permissions and limitations under the Licence. \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9e0cb064170cee79825ca89b16c44f29b0aefc5a --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +Copyright 2023 Danish Business Authority (ERST) + +This software is licensed under the terms of the European Union Public License 1.1 or any later version. + +This software is a derivative work of the Oxalis Access Point (available from https://www.oxalis.network/downloads-and-support ), which is licensed under EUPL 1.1 or later + +This software additionally contains components or utilizes dependencies licensed under: +Apache License 2.0 https://www.apache.org/licenses/LICENSE-2.0 +Eclipse Distribution License 1.0 http://www.eclipse.org/org/documents/edl-v10.p +The MIT License https://github.com/mockito/mockito/blob/master/LICENSE +The 2-clause BSD License https://opensource.org/license/bsd-2-clause/ +Common Public License 1.0 https://opensource.org/license/cpl1-0-txt/ +Mozilla Public License 2.0 https://mozilla.org/MPL/2.0/ + +all of which licenses permit the licensing of combined or derivative works under EUPL 1.1. \ No newline at end of file diff --git a/README.md b/README.md index 1941887ef8888a6b959830ee052fedc3d39f957f..bf1911468071502ec1e80e08e9bfb0a37a0d4e5f 100644 --- a/README.md +++ b/README.md @@ -1,92 +1,67 @@ -# oxalis +# Oxalis +This repository contains a fork of the [PEPPOL](http://www.peppol.eu/) Access Point, named [Oxalis](http://en.wikipedia.org/wiki/Common_wood_sorrel), +which was originally developed by Steinar Overbeck Cook, [SendRegning](http://www.sendregning.no/) +and now looked after by the Norwegian agency for Public Management and eGovernment (Difi). -## Getting started +The Oxalis system is an enhancement of the PEPPOL Sample Implementation and can be used used as +a complete standalone PEPPOL solution or as an API component from your own code. -To make it easy for you to get started with GitLab, here's a list of recommended next steps. +Out of the box it persists inbound messages to the filesystem. +Persistence have been modularized so you can provide your own implementation if you need to +send inbound messages to a message queue, a workflow engine, a document archive or others. -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! +It comes with a basic command line tool for sending messages (```oxalis-standalone```), which has been improved and +is now capable of sending multiple files. -## Add your files +Binary distributions are available at Maven Central. -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: +As of version 4.x Oxalis no longer has any dependency on SQL databases. -``` -cd existing_repo -git remote add origin https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis.git -git branch -M master -git push -uf origin master -``` +This fork is intended for used in combination with the fork of [Oxalis-AS4](https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis-as4) to support Nemhandel e-Delivery. -## Integrate with your tools +## The Latest version is Oxalis 5.5.0 -- [ ] [Set up project integrations](https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis/-/settings/integrations) +Refer detailed documentation at : [main.adoc](/doc/main.adoc) -## Collaborate with your team +--- +## Oxalis components -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) +| Component | Type | Description | +| --------- | ---- | ----------- | +| oxalis-inbound | war | Inbound access point implementation which runs on Tomcat (1) | +| oxalis-outbound | jar | Outbound component for sending PEPPOL business documents (2) | +| oxalis-standalone | main | Command line application for sending PEPPOL business documents (3) | -## Test and Deploy +(1) Receives messages and stores them in the filesystem as default (Note: the AS2 protocol has been removed). -Use the built-in continuous integration in GitLab. +(2) Can be incorporated into any system which needs to send PEPPOL documents. -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) +(3) Serves as example code on how to send a business documents using the oxalis-outbound component. -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. ## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. +See [installation instructions](https://nemhandel.dk/vejledning-nemhandel-edelivery). -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. +## Build from source -## Contributing -State if you are open to contributions and what your requirements are for accepting them. +* make sure [Maven 3](http://maven.apache.org/) is installed +* make sure [JDK 8](https://adoptium.net/temurin/releases/?version=8) is installed (the version we have tested with) +* pull the version of interest from [GitLab](https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis). +* from `oxalis` root directory run : `mvn clean install` -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. +## Securing Oxalis -## License -For open source projects, say how it is licensed. +By default Oxalis publish the web addresss listed in the table below. +The table describes their use and give some hints on how to secure those addresses. +A pretty standard scenario is to use some kind of load balancer and SSL offloader in front of the appserver running Oxalis. +This could be free/open software like [Nginx](http://nginx.org/) and Apache or commercial software like NetScaler and BigIP. +All such front end software should be able to enforce security like the one suggested below. -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. +| URL | Function | Transport | Security | +| --- | -------- | --------- | -------- | +| oxalis/status | Status information, for internal use and debugging | HTTP/HTTPS | Internet access can be blocked | +| oxalis/statistics | RAW statistics for DIFI | HTTPS with proper certificates | Used by DIFI to collect statistics | diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md new file mode 100644 index 0000000000000000000000000000000000000000..1eda30de07ac83006b6a5397d404470023c0dfe0 --- /dev/null +++ b/RELEASE-NOTES.md @@ -0,0 +1,5 @@ +# Nemhandel e-Delivery Oxalis release notes + +## 0.9.0 +Beta release of the Nemhandel e-Delivery reference implementation based on Oxalis 5.5.0. + diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2d19fc766d98a08d9d1437896bfb008a7b15f340 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/doc/configuration.adoc b/doc/configuration.adoc new file mode 100644 index 0000000000000000000000000000000000000000..21f9285479b34c2d4d7a89fa74829b70f2476c9a --- /dev/null +++ b/doc/configuration.adoc @@ -0,0 +1,308 @@ += Configuration [[config]] + +*NOTE: This information is related to upstream Oxalis and may not be accurate for this fork.* + +== Upgrading to 5.0 +Oxalis already supporting default CNAME lookup, so configuration 'lookup.locator.class' is Not required in ```oxalis.conf```. +If it exist then either remove it or comment it out: +#lookup.locator.class=network.oxalis.vefa.peppol.lookup.locator.BusdoxLocator + +HTTP Client parameters (validate_after_inactivity & time_to_live) made configurable +---- +oxalis.http.pool.validate_after_inactivity = 1000 +oxalis.http.pool.time_to_live = 30 +---- + +== Upgrading to 4.0 [[config-upgrade-4]] + +This is an overview of keys used for configuration when converting from Oxalis version 2.x/3.x to Oxalis version 4.x. + +As of version 4.0 is the configuration file named ```oxalis.conf```. + +[cols="3*",options="header"] +|=== +| oxalis-globals.properties (pre 4.0) +| oxalis.conf (4.0+) +| Default value (4.0+) + +3+h| _Database_ + +| oxalis.datasource.jndi.name +| oxalis.database.jndi.resource +| jdbc/oxalis + +| oxalis.jdbc.driver.class +| oxalis.database.driver.class +| org.h2.Driver + +| oxalis.jdbc.class.path +| oxalis.database.driver.path +| _null_ + +| oxalis.jdbc.connection.uri +| oxalis.database.jdbc.connection +| jdbc:h2:file:data/oxalis + +| oxalis.jdbc.dialect +2+^| _Removed_ + +| oxalis.jdbc.user +| oxalis.database.jdbc.username +| sa + +| oxalis.jdbc.password +| oxalis.database.jdbc.password +| _blank_ + +| oxalis.jdbc.validation.query +| oxalis.database.dbcp.validation +| select 1 + +3+h| _HTTP_ + +| oxalis.connection.timeout +| oxalis.http.timeout.connect +| 0 + +| oxalis.read.timeout +| oxalis.http.timeout.read +| 0 + +3+h| _Keystore_ + +| oxalis.keystore +| oxalis.keystore.path +| oxalis-keystore.jks + +| oxalis.keystore.password +| oxalis.keystore.password +| changeit + +^| _New_ +| oxalis.keystore.key.alias +| ap + +^| _New_ +| oxalis.keystore.key.password +| changeit + +3+h| _Logging_ + +| oxalis.app.log.config +2+^| _Removed_ + +| oxalis.inbound.log.config +| oxalis.logging.config +| logback.xml + +3+h| _Lookup_ + +| oxalis.sml.hostname +2+^| _Removed - Depending on mode_ + +3+h| _Mode_ + +| oxalis.operation.mode +2+^| _Removed - Detected using certificate_ + +3+h| _Proxy_ + +| oxalis.httpProxyHost +2.4+^.^| _See link:#_proxy[Proxy]._ + +| oxalis.httpProxyPort + +| oxalis.proxyUser + + +| oxalis.proxyPassword + + +3+h| _Storage_ + +| oxalis.inbound.message.store +| oxalis.path.inbound +| inbound + +1.2+<.^| oxalis.persistence.class.path +| oxalis.persister.payload.service +| default + +| oxalis.persister.receipt.service +| default + +3+h| _Truststore_ + +| oxalis.truststore.password +2+^| _Removed_ + +|=== + +== Database [[config-database]] + +=== Data Source [[config-database-datasource]] + +Oxalis supports two different datasources out of the box; + +* ```dbcp``` - link:https://commons.apache.org/proper/commons-dbcp/[DBCP] +* ```jndi``` - JNDI + +[source,conf] +.Default configuration +---- +oxalis.database.datasource = dbcp +---- + +=== Driver [[config-database-driver]] + +_This is used when setting Data Source to ```dbcp```._ + +[source,conf] +.Default configuration +---- +oxalis.database.driver.class = org.h2.Driver +# oxalis.database.driver.path = (not set) +---- + +=== JDBC [[config-database-jdbc]] + +_This is used when setting Data Source to ```dbcp```._ + +[source,conf] +.Default configuration +---- +oxalis.database.jdbc.connection = "jdbc:h2:file:./data/oxalis" +oxalis.database.jdbc.username = sa +oxalis.database.jdbc.password = "" # (blank) +---- + +=== DBCP [[config-database-dbcp]] + +_This is used when setting Data Source to ```dbcp```._ + +[source,conf] +.Default configuration +---- +oxalis.database.dbcp.max.idle = 30 +oxalis.database.dbcp.max.total = 100 +oxalis.database.dbcp.validation = select 1 +---- + +=== JNDI [[config-database-jndi]] + +_This is used when setting Data Source to ```jndi```._ + +[source,conf] +.Default configuration +---- +oxalis.database.jndi.resource = jdbc/oxalis +---- + +== File system [[config-filesystem]] + +=== Home folder [[config-filesystem-home]] + +Home folder is set as the first occurance in this list: + +. Path specified in JDNI context with key ```java:comp/env/OXALIS_HOME```. +. Path specified as a Java property with key ```OXALIS_HOME```. +. Path specified as an environment variable with key ```OXALIS_HOME```. +. Path ```.oxalis``` in home folder. + +=== Other folders [[config-filesystem-others]] + +[source,conf] +.Default configuration +---- +oxalis.path.conf = "" # Blank +oxalis.path.inbound = inbound +# oxalis.path.plugin = (not set) +---- + +== HTTP outbound [[config-http]] + +Outbound HTTP connections use link:https://hc.apache.org/[Apache HttpComponents]. + + +=== Connection pool [[config-http-pool]] + +Oxalis uses a shared connection pool of keep-alive connections to speed up transmission. + +[source,conf] +.Default configuration +---- +oxalis.http.pool.max_route = 2 +oxalis.http.pool.total = 20 +oxalis.http.pool.validate_after_inactivity = 1000 +oxalis.http.pool.time_to_live = 30 +---- + +=== Proxy [[config-http-proxy]] + +Proxy is configured using link:#config-java[Java properties] as described in the link:https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html[Java 8 documentation]. + +.Some relevant properties +* java.net.useSystemProxies +* http.proxyHost +* http.proxyPort +* http.nonProxyHosts +* https.proxyHost +* https.proxyPort +* http.proxyUser +* http.proxyPassword + +=== Timeouts [[config-http-timeout]] + +[source,conf] +.Default configuration +---- +oxalis.http.timeout.connect = 0 +oxalis.http.timeout.read = 0 +---- + +== Java properties [[config-java]] + +It is recommended to set Java properties as part of running Oxalis - not having Oxalis set Java properties. + +[source,concole] +.The recommended way of setting properties on command line. +---- +java -Dhttp.proxyHost=10.0.0.50 -Dhttp.proxyPort=8080 ... +---- + +In some situations may it be needed to put Java properties in the configuration file. Java propterties in the configuration file will be set just after configuration is loaded. + +Properties are added by simple prefixing them with ```oxalis.java```. + +[source,conf] +.Example Java properties in Oxalis configuration file. +---- +oxalis.java.http.proxyHost = 10.0.0.50 +oxalis.java.http.proxyPort = 80 +---- + + +== Key store [[config-keystore]] + +keystore.path:: +Path to file containing key store. JKS is the historical format used, however PKCS#12 has shown to be possible to use as a replacement without changes to the code. +keystore.password:: +Password used to unlock the provided key store. +keystore.key.alias:: +Alias identifying the private key inside the key store to be used. +keystore.key.password:: +Password used to unlock the private key to be used. + +NOTE: All configuration of key store and key is case sensitive. + +[source,conf] +.Default configuration (review carefully) +---- +oxalis.keystore.path = oxalis-keystore.jks +oxalis.keystore.password = changeit +oxalis.keystore.key.alias = ap +oxalis.keystore.key.password = changeit +---- + + +== Logging [[config-logging]] diff --git a/doc/customizing.adoc b/doc/customizing.adoc new file mode 100644 index 0000000000000000000000000000000000000000..f56503a4498326820e3a3ff4dc11009ddbf3610f --- /dev/null +++ b/doc/customizing.adoc @@ -0,0 +1,29 @@ += Customizing Oxalis [[customizing]] + +*NOTE: This information is related to upstream Oxalis and may not be accurate for this fork.* + +== Plugin [[plugin]] + +[source,xml,subs="verbatim,attributes"] +.Maven depencency +---- + + network.oxalis + oxalis-api + {techversion} + provided + +---- + +== Extension [[extension]] + +[source,xml,subs="verbatim,attributes"] +.Maven depencency +---- + + network.oxalis + oxalis-commons + {techversion} + provided + +---- diff --git a/doc/extension-points.adoc b/doc/extension-points.adoc new file mode 100644 index 0000000000000000000000000000000000000000..fe9b311ada0a8a5227e9a64d027ebd4cc4c423b0 --- /dev/null +++ b/doc/extension-points.adoc @@ -0,0 +1,72 @@ += Extension points + +*NOTE: This information is related to upstream Oxalis and may not be accurate for this fork.* + +[cols="1,1,1", options="header"] +|=== + +| Configuration +| Interface +| Default implementation + +3+h| Common + +| oxalis.error.handler +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/error/ErrorTracker.java[ErrorTracker] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/error/QuietErrorTracker.java[QuietErrorTracker] + +| oxalis.evidence.service +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/evidence/EvidenceFactory.java[EvidenceFactory] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/evidence/RemEvidenceFactory.java[RemEvidenceFactory] + +| oxalis.header.parser +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/header/HeaderParser.java[HeaderParser] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/header/SbdhHeaderParser.java[SbdhHeaderParser] + +| oxalis.lookup.service +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/lookup/LookupService.java[LookupService] +| link:../oxalis-outbound/src/main/java/no/difi/oxalis/outbound/lookup/CachedLookupService.java[CachedLookupService] + +| oxalis.persister.payload +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/persist/PayloadPersister.java[PayloadPersister] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/persist/DefaultPersister.java[DefaultPersister] + +| oxalis.persister.receipt +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/persist/ReceiptPersister.java[ReceiptPersister] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/persist/DefaultPersister.java[DefaultPersister] + +| oxalis.persister.handler +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/persist/PersisterHandler.java[PersisterHandler] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/persist/DefaultPersisterHandler.java[DefaultPersisterHandler] + +| oxalis.statistics.service +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/statistics/StatisticsService.java[StatisticsService] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/statistics/NoopStatisticsService.java[NoopStatisticsService] + +| oxalis.tag.generator +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/tag/TagGenerator.java[TagGenerator] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/tag/NoopTagGenerator.java[NoopTagGenerator] + +| oxalis.timestamp.service +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/timestamp/TimestampProvider.java[TimestampProvider] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/timestamp/SystemTimestampProvider.java[SystemTimestampProvider] + +| oxalis.transformer.detector +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/transformer/ContentDetector.java[ContentDetector] +| link:../oxalis-outbound/src/main/java/no/difi/oxalis/outbound/transformer/XmlContentWrapper.java[XmlContentWrapper] + +| oxalis.transformer.wrapper +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/transformer/ContentWrapper.java[ContentWrapper] +| link:../oxalis-legacy/oxalis-document-sniffer/src/main/java/no/difi/oxalis/sniffer/document/NoSbdhParser.java[NoSbdhParser] + +| oxalis.transmission.verifier +| link:../oxalis-api/src/main/java/no/difi/oxalis/api/transmission/TransmissionVerifier.java[TransmissionVerifier] +| link:../oxalis-commons/src/main/java/no/difi/oxalis/commons/transmission/DefaultTransmissionVerifier.java[DefualtTransmissionVerifier] + +3+h| AS2 + +| oxalis.as2.msgidgen +| link:../oxalis-as2/src/main/java/no/difi/oxalis/as2/api/MessageIdGenerator.java[MessageIdGenerator] +| link:../oxalis-as2/src/main/java/no/difi/oxalis/as2/common/DefaultMessageIdGenerator.java[DefaultMessageIdGenerator] + +|=== \ No newline at end of file diff --git a/doc/install.adoc b/doc/install.adoc new file mode 100644 index 0000000000000000000000000000000000000000..ed849202f2500338fe9bec25b17b4d82fb1a68e1 --- /dev/null +++ b/doc/install.adoc @@ -0,0 +1,68 @@ += Installation [[install]] + +*NOTE: This information is related to upstream Oxalis and may not be accurate for this fork.* + +*This documentation is not yet done. Please see the other link:installation.md[installation document].* + + + +Jump directly to link:#install-docker[Docker] for relevant information if you are using Docker. + + +== Prerequisites [[install-prerequisites]] + + +== Oxalis home folder [[install-oxalis-home]] + + +== Download [[download]] + +[cols="1,1,1,1,1",options="header"] +|=== +| Version +| Inbound +| Distribution +| Server +| Standalone + +| 5.0.0.RC2 +| link:https://repo1.maven.org/maven2/network/oxalis/oxalis-inbound/5.0.0.RC2/oxalis-inbound-5.0.0.RC2.war[war] +| link:https://repo1.maven.org/maven2/network/oxalis/oxalis-distribution/5.0.0.RC2/oxalis-distribution-5.0.0.RC2-distro.tar.gz[tar.gz] +link:https://repo1.maven.org/maven2/network/oxalis/oxalis-distribution/5.0.0.RC2/oxalis-distribution-5.0.0.RC2-distro.zip[zip] +| link:https://repo1.maven.org/maven2/network/oxalis/oxalis-server/5.0.0.RC2/oxalis-server-5.0.0.RC2-full.tar.gz[tar.gz] +link:https://repo1.maven.org/maven2/network/oxalis/oxalis-server/5.0.0.RC2/oxalis-server-5.0.0.RC2-full.zip[zip] +| link:https://repo1.maven.org/maven2/network/oxalis/oxalis-standalone/5.0.0.RC2/oxalis-standalone-5.0.0.RC2.jar[jar] + +| 4.0.0-RC2 +| link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-inbound/4.0.0-RC2/oxalis-inbound-4.0.0-RC2.war[war] +| link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-distribution/4.0.0-RC2/oxalis-distribution-4.0.0-RC2-distro.tar.gz[tar.gz] +link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-distribution/4.0.0-RC2/oxalis-distribution-4.0.0-RC2-distro.zip[zip] +| link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-server/4.0.0-RC2/oxalis-server-4.0.0-RC2-full.tar.gz[tar.gz] +link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-server/4.0.0-RC2/oxalis-server-4.0.0-RC2-full.zip[zip] +| link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-standalone/4.0.0-RC2/oxalis-standalone-4.0.0-RC2.jar[jar] + +| 4.0.0-RC1 +| link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-inbound/4.0.0-RC1/oxalis-inbound-4.0.0-RC1.war[war] +| link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-distribution/4.0.0-RC1/oxalis-distribution-4.0.0-RC1-distro.zip[zip] +| +| link:http://repo1.maven.org/maven2/no/difi/oxalis/oxalis-standalone/4.0.0-RC1/oxalis-standalone-4.0.0-RC1.jar[jar] + +|=== + +== Oxalis Distribution [[distribution]] + +== Oxalis server [[install-server]] +Oxalis as an application only require Java 8 to run it. This Server distribution is used to create the Docker image. + +== Standalone [[install-standalone]] +Simple client for sending message to Peppol network. It is provided as a single java archive (jar). Suited for testing and small manual tasks. + +== Oxalis WAR [[install-inbound]] +The traditional war distribution for application servers created to use Java Servlet 3.0 functionality. This distribution is made available as `oxalis.war` in `oxalis-distribution`. + +== Docker [[install-docker]] +With Oxalis 5.0.0.RC2, docker images for different architecture is now available at : https://hub.docker.com/repositories +* Oxalis : https://hub.docker.com/r/norstella/oxalis/tags +* Oxalis-AS4 : https://hub.docker.com/r/norstella/oxalis-as4/tags + +== Configuration of HTTPS [[install-https]] diff --git a/doc/installation.md b/doc/installation.md new file mode 100644 index 0000000000000000000000000000000000000000..5dd1b6507e62c5022387682c6411fad60103164b --- /dev/null +++ b/doc/installation.md @@ -0,0 +1,126 @@ +# Oxalis installation + +> Note: These are instruction related to upstream Oxalis and may not be entirely accurate for this fork. +> Please refer to the installation instructions in [readme.md](../readme.md) for more accurate installation instructions. + +The purpose of this document is to document how to install Oxalis as simple as possible. + +## Prerequisites + +* Java JDK 1.8 (newer versions should also work) +* [Maven 3+](http://maven.apache.org/download.cgi) (if you plan to build Oxalis yourself) +* [Tomcat 9+](https://tomcat.apache.org/download-90.cgi) (if you have a different JEE container, you need to figure out the differences on your own, sorry :-) +* Create `OXALIS_HOME` directory to hold configuration files, certificates etc +* Add `OXALIS_HOME` environment variable to reference that directory + +All of these must be installed properly, i.e. make sure the binaries are available from your command line. + + +## Checklist +When running the following commands you should expect output similar to the one shown + +| Verify | Command | Expected output | +| ------ | ------- | --------------- | +| JDK 1.8 | `javac -version` | javac 1.8.0_45 | +| Maven 3 | `mvn -version` | Apache Maven 3.2.1 | +| OXALIS_HOME | `echo $OXALIS_HOME` | /Users/arunkum/.oxalis | + + +## Installation steps + +1. Install Tomcat and configure it for SSL on port 443 or make sure you terminate SSL in front of Tomcat on port 443 (using nginx or similar). Please, do not change this port. Most other access points need to communicate with you and their operations department usually don't like opening non-standard ports. **Do not use your PEPPOL certificate as an SSL certificate!**. You can refer additional documentation "[Default trusted root certificates and the Peppol policy for Transport Security](https://ionite.net/newsblog/2020-06-29_peppol_tls_certificates/)" - Disclaimer: this external documentation not cross-verified, so please take your own wise decision + +2. Obtain the binary artifacts for Oxalis by either: + 1. Downloading the binary artifacts from [Maven Central](https://search.maven.org/#search%7Cga%7C1%7Coxalis) and unpack the distribution. + 1. Building yourself from the source at [GitHub](https://github.com/OxalisCommunity/oxalis) + +3. Create an Oxalis home directory in which you place files that do not change between new releases of Oxalis. + We recommend that you name the Oxalis home directory `.oxalis` in what is considered the home directory of the user running Oxalis. If you + are using Tomcat, it should be the home directory of the tomcat user. + Remember to set the `$OXALIS_HOME` environment variable referencing your Oxalis home directory in your shell startup + script. + + Example: + ``` + export OXALIS_HOME=~/.oxalis + ``` + +4. See the [Oxalis keystore guide](/doc/keystore.adoc) for details on how to crete your keystore. During the startup, your certificate validated towards the proper certificate chain. Please note that Oxalis will not work non-PEPPOL or expired certificates. + +5. Create the file `oxalis.conf`. Here is an example of how it might look: + + ``` + oxalis.keystore { + # Relative to OXALIS_HOME + path=peppol-keystore.jks + password = peppol + key.alias = ap + key.password = peppol + } + + # The relative name of the directory holding plugin + oxalis.path.plugin = oxalis-plugin + + # Signals to Oxalis that we should look for plugin + oxalis.persister.receipt = plugin + + # Where to store inbound files + oxalis.path.inbound = /var/peppol/IN + ``` + + More information may be find in the [configuration document](../doc/configuration.adoc). + +6. Copy the file `oxalis.war` into your Tomcat deployment directory, example : + + ``` + cp oxalis-dist/oxalis-distribution/target/oxalis-distribution-x.y.z/jee/oxalis.war /users/oxalis/apache-tomcat-7.0.56/webapps + ``` + +7. Start Tomcat, check the logs for any errors and make sure the [oxalis status page](http://localhost/oxalis/status) seems right (the URL could be different for your setup). + Note! If you intend to terminate TLS in your Tomcat instance, the status pages resides at `https://localhost:443/oxalis/status` + +8. Attempt to send a sample invoice using the file `example.sh` file located in `oxalis-dist/oxalis-standalone`. + Do not forget to review the script first! + + +## Testing and verifying your installation + +Testing and verification of your installation assume that you have performed above listed actions. + +* You have obtained a PEPPOL test certificate. + +(The running mode will be detected by Oxalis by validating your certificate - no need to maintain that setting anymore.) + + +### Sending a sample invoice to Difi's test access point + +This is how you send a sample invoice to remote test access point using the test SML (SMK): +``` +java -jar target/oxalis-standalone.jar \ + -f src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml \ + -r 9908:810418052 \ + -s 9909:810418052 +``` +Make sure endpoint exists and support respective profile. + +Verify that your sample invoice received at remote destination access point + + +### Sending a sample invoice to your own local access point + +You need to override the use of the SML/SMP in order to send directly to your own access point. +This is done by specifying a) the URL, b) the protocol and the c) AS2 system identifier. + +Here is how to send a sample invoice in PEPPOOL Bis 4A profile to your own local access point: + +```` +java -jar target/oxalis-standalone.jar \ + -f src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml \ + -u http://localhost:8080/oxalis/as2 \ + -cert /path/to/your/certificate.cer +```` + + + + +Good luck!!! diff --git a/doc/introduction.adoc b/doc/introduction.adoc new file mode 100644 index 0000000000000000000000000000000000000000..4386d6cce9321cc9eec3460f5e6bb745772c47cc --- /dev/null +++ b/doc/introduction.adoc @@ -0,0 +1,51 @@ += Introduction [[introduction]] + +*NOTE: This information is related to upstream Oxalis and may not be accurate for this fork.* + +== Oxalis + +​This repository is core of complete Oxalis software package. This repository also provides AS2 support, standalone module, and some legacy software. The Oxalis system is an enhancement of the Peppol Sample Implementation and can be used as a complete standalone Peppol solution or as an API component from your own code. This is based on plugin-based architecture, so you are free to customized it according to your own system requirement like e.g., sending messages to a message queue, a workflow engine, a document archive, or others. Oxalis comes with a basic command line tool for sending messages (oxalis-standalone) and it can send multiple files. All artifacts are available in maven repository so you can easily add dependencies to your project. + +Repo: https://github.com/OxalisCommunity/oxalis + +== Oxalis-AS4 + +AS4 Plugin support OpenPeppol AS4 pMode. AS4 plugin passed CEF conformance test (excluding tests requiring multiple payloads). AS4 messages is triggered by setting the transport profile identifier of one of your endpoints to "peppol-transport-as4-v2_0" in the SMP. No further configuration is needed beyond the standard Oxalis setup. + +Starting with version 5.0.0.RC1, Oxalis-AS4 artifact is now available in maven repository. + +Repo: https://github.com/OxalisCommunity/Oxalis-AS4 + +== Vefa-peppol + +This project implements some aspects of Peppol for inclusion in other projects. +Common - Data model for Peppol functionality. +Evidence - Implementation of ETSI REM Evidence. +ICD - Handling of ICDs as used in Peppol. +Lookup - Functionality for looking up participants in Peppol. +Mode - Feature to configure a Peppol application based on a Peppol certificate. +Publisher - Generic implementation of SMP interface. +SBDH - Optimized library for handling of envelope. +Security - Security features for Peppol. + +Vefa-peppol artifacts are also available in maven so you can use them within your product for required functionality + +Repo: https://github.com/OxalisCommunity/vefa-peppol + +== Note for API Integrators +*Upcoming Oxalis released version require package refactoring because of organization change, so you need to use latest packages in your product in addition to including dependency if you are using API version* + +== What is expected from you – Developers and Integrator of Oxalis Software? +- Oxalis is open-source software so you can contribute either by replying to known issues or raising pull request +- Report problem with full context containing complete logs, oxalis version, JDK version, scenario tested etc. Please go through issue history and documentation before reporting any problem. +- Discussion can also be started for any other important topic which may or may not be an issue in implementation. Consider it as an open forum to share ideas, concerns, remarks. + +=== Report problem +- Report Oxalis issues: https://github.com/OxalisCommunity/oxalis/issues +- Report Oxalis AS4 issues: https://github.com/OxalisCommunity/Oxalis-AS4/issues +- Report Vefa-Peppol Issues: https://github.com/OxalisCommunity/vefa-peppol/issues + +=== Discussion Channel +- Oxalis discussion Channel: https://github.com/OxalisCommunity/oxalis/discussions +- Oxalis-AS4 discussion Channel: https://github.com/OxalisCommunity/Oxalis-AS4/discussions +- Vefa-Peppol discussion Channel: https://github.com/OxalisCommunity/vefa-peppol/discussions \ No newline at end of file diff --git a/doc/keystore.adoc b/doc/keystore.adoc new file mode 100644 index 0000000000000000000000000000000000000000..600b25ddb3ea7cd4833edde8f166785284295eaf --- /dev/null +++ b/doc/keystore.adoc @@ -0,0 +1,55 @@ += Certificates, keys and key stores in Oxalis + +*NOTE: This information is related to upstream Oxalis and may not be accurate for this fork.* + +The purpose of this document is to guide you in how to set up your PEPPOL certificates in order to make Oxalis "tick". + + +== What are certificates used for? + +PEPPOL has defined a PKI structure which allows for prudent governance of the access points, the SMP's and so on. + +Every low level message passed between access points and between the access point and the SMP, are signed with digital certificates. + +There is a "test" and "production" hierarchy of certificates. + +When your certificate is issued by PEPPOL, it will be signed with the *intermediate* AP certificate. + + +== How are they used in Oxalis? + +Oxalis validates your certificate as part of startup, and configures your installation accordingly. + +You need only to supply your own key store, holding the private key and the corresponding PEPPOL certificate with your public key embedded. + + +== How do I obtain a PEPPOL certificate for my Access point? + +1. Request PKI certificate in the link:https://openpeppol.atlassian.net/servicedesk/customer/portal/1[OpenPEPPOL Service Desk] (OpenPEPPOL members only). + +1. Follow instruction on the link:https://openpeppol.atlassian.net/wiki/spaces/OPMA/pages/193069072/Introduction+to+the+revised+PKI+Certificate+infrastructure+and+issuing+process[PKI issuing information page] or updated link provided by OpenPEPPOL Support Team. + +1. Copy the generated JKS or PKCS#12 keystore to your ```$OXALIS_HOME``` directory. + +1. Update the configuration entry in link:/doc/configuration.adoc#key-store[`oxalis.conf`] (**Key store** part). + +1. Start Oxalis. + +== Example configuration + +[source,conf] +---- +oxalis.keystore: { + path: my-keystore.p12 <1> + password: "1uHGTjM7kHi7!CG" <2> + + key: { + alias: "pno000001-s openpeppol aisbl id" <3> + password: "@1F6m53NVJBOp!n" <4> + } +} +---- +<1> Key store filename. +<2> Password of key store provided during export from browser. +<3> Key alias found during inspection of key store. +<4> Password of key, normally the same as password for key store unless manually changed. diff --git a/doc/main.adoc b/doc/main.adoc new file mode 100644 index 0000000000000000000000000000000000000000..d2c19891de4e753357491e4a3b822751fd1e6d69 --- /dev/null +++ b/doc/main.adoc @@ -0,0 +1,23 @@ +:version: 5.0.0 +:techversion: 5.0.0 + += Oxalis +v{version} +:doctype: book +:icons: font +:toc: left +:toclevels: 2 +:source-highlighter: coderay +:source-language: xml +:sectanchors: +:sectnums: + +:leveloffset: +1 + +include::introduction.adoc[] + +include::install.adoc[] + +include::configuration.adoc[] + +include::customizing.adoc[] diff --git a/doc/usefull-openssl-commands.md b/doc/usefull-openssl-commands.md new file mode 100644 index 0000000000000000000000000000000000000000..6e5c7c4df8ecc8abaa345d3f778f7de1fe83249e --- /dev/null +++ b/doc/usefull-openssl-commands.md @@ -0,0 +1,17 @@ + +## Base64 decoding an AS2 MDN + +Given the AS2 MDN encoded in Base64 on a single line, extracted from the ETSI REM evidence: + + openssl enc -base64 -d -in receipt-b64.mdn -out receipt.mdn -A + +The `-A` option is used when the entire base64 encoded MDN is held on a single line. + +To extract the certificate used to sign the MDN into file `certificate.pem`: + + openssl cms -verify -in receipt.mdn -noverify -signer certificate.pem + +Inspect the contents of the certificate: + + openssl x509 -in certificate.pem -inform PEM -text + \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100644 index 0000000000000000000000000000000000000000..b7f064624f8911a9d50912d2c3e163a1eb685209 --- /dev/null +++ b/mvnw @@ -0,0 +1,287 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.1.1 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="`/usr/libexec/java_home`"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + printf '%s' "$(cd "$basedir"; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname $0)") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) wrapperUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $wrapperUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + QUIET="--quiet" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + QUIET="" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" + fi + [ $? -eq 0 ] || rm -f "$wrapperJarPath" + elif command -v curl > /dev/null; then + QUIET="--silent" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + QUIET="" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L + fi + [ $? -eq 0 ] || rm -f "$wrapperJarPath" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaSource="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=`cygpath --path --windows "$javaSource"` + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000000000000000000000000000000000000..474c9d6b74cd3201de028ccee0332a53dc993d56 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,187 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.1.1 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/oxalis-api/pom.xml b/oxalis-api/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..8e093d86ba6daf88fed295e70fbc667a729b2c8b --- /dev/null +++ b/oxalis-api/pom.xml @@ -0,0 +1,149 @@ + + + + + + 4.0.0 + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + + oxalis-api + + Oxalis :: Core :: API + + Holds the stuff required by external components, which may be hooked into Oxalis. + Classes and resources in this module should be made available to oxalis-inbound + by placing it into a shared library in the web container. + + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + ${maven.build.timestamp} + false + + + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + test + + + + + + network.oxalis.vefa + peppol-common + + + + + io.opentracing + opentracing-api + + + + + org.testng + testng + test + + + + + javax.inject + javax.inject + + + + + + + pl.project13.maven + git-commit-id-plugin + 4.9.10 + + + + revision + + + + + git + dd.MM.yyyy '@' HH:mm:ss z + true + ${project.basedir}/.git + true + false + src/main/resources/git.properties + false + false + + + + + + ${git.shallow} + + true + + 7 + + -dirty + + true + + + + + + + src/main/resources + true + + + + + src/test/resources + true + + + + + + diff --git a/oxalis-api/src/main/java/network/oxalis/api/error/ErrorTracker.java b/oxalis-api/src/main/java/network/oxalis/api/error/ErrorTracker.java new file mode 100644 index 0000000000000000000000000000000000000000..63f67db58cf2b2e7cba30a102927831ee5dfe52d --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/error/ErrorTracker.java @@ -0,0 +1,25 @@ +package network.oxalis.api.error; + +import network.oxalis.api.model.Direction; + +/** + * Defining interface for tracking of exceptions received as result of external communication, both + * inbound and outbound. + * + * @author erlend + * @since 4.0.2 + */ +public interface ErrorTracker { + + /** + * Method called where errors are gathered. + * + * @param direction Direction of transmission where error occurred. + * @param e The exception triggered. + * @param handled Whether Oxalis were able to gracefully handle the exception using own relevant exception handling. + * @return Identifier uniquely identifying the error in the error handling system or logging. + * @since 4.0.2 + */ + String track(Direction direction, Exception e, boolean handled); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/evidence/EvidenceFactory.java b/oxalis-api/src/main/java/network/oxalis/api/evidence/EvidenceFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..6ba3d8da462668b1e59daf0e5dced72281797b46 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/evidence/EvidenceFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.evidence; + +import network.oxalis.api.lang.EvidenceException; +import network.oxalis.api.transmission.TransmissionResult; + +import java.io.*; + +/** + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface EvidenceFactory { + + void write(OutputStream outputStream, TransmissionResult transmissionResult) throws IOException, EvidenceException; + + /** + * @since 4.0.3 + */ + default InputStream write(TransmissionResult transmissionResult) throws IOException, EvidenceException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + write(byteArrayOutputStream, transmissionResult); + return new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/filesystem/HomeDetector.java b/oxalis-api/src/main/java/network/oxalis/api/filesystem/HomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..89196f80475d927fcd44cb5edb02258ab0ea6fcc --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/filesystem/HomeDetector.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.filesystem; + +import java.io.File; + +/** + * @author erlend + */ +public interface HomeDetector { + + File detect(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/header/HeaderParser.java b/oxalis-api/src/main/java/network/oxalis/api/header/HeaderParser.java new file mode 100644 index 0000000000000000000000000000000000000000..07db7ceaca6883906952938c7a21764582af5476 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/header/HeaderParser.java @@ -0,0 +1,16 @@ +package network.oxalis.api.header; + +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.2 + */ +public interface HeaderParser { + + Header parse(InputStream inputStream) throws OxalisContentException; + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/identifier/MessageIdGenerator.java b/oxalis-api/src/main/java/network/oxalis/api/identifier/MessageIdGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..32cbd0fb5bb46f722fdf62394c96204f87beb3d1 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/identifier/MessageIdGenerator.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.identifier; + +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.inbound.InboundMetadata; + +/** + * @author erlend + * @since 4.0.4 + */ +public interface MessageIdGenerator { + + String generate(TransmissionRequest transmissionRequest); + + String generate(InboundMetadata inboundMetadata); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/inbound/InboundMetadata.java b/oxalis-api/src/main/java/network/oxalis/api/inbound/InboundMetadata.java new file mode 100644 index 0000000000000000000000000000000000000000..32674a0a8d5f0f60e7c3ba0ef13f33e1921b8a17 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/inbound/InboundMetadata.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.inbound; + +import network.oxalis.api.tag.Tag; +import network.oxalis.api.transmission.TransmissionResult; + +import java.security.cert.X509Certificate; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface InboundMetadata extends TransmissionResult { + + /** + * Fetch sender's certificate. + * + * @return Certificate. + */ + X509Certificate getCertificate(); + + Tag getTag(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/inbound/InboundService.java b/oxalis-api/src/main/java/network/oxalis/api/inbound/InboundService.java new file mode 100644 index 0000000000000000000000000000000000000000..0a5a291e35246056b6c642f12ab4ff56c14ed0ab --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/inbound/InboundService.java @@ -0,0 +1,11 @@ +package network.oxalis.api.inbound; + +/** + * @author erlend + * @since 4.0.2 + */ +public interface InboundService { + + void complete(InboundMetadata inboundMetadata); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/inject/NamedImpl.java b/oxalis-api/src/main/java/network/oxalis/api/inject/NamedImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..721501df22f324cdbc38a3c69b64fb45373b76bc --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/inject/NamedImpl.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.inject; + +import javax.inject.Named; +import java.lang.annotation.Annotation; + +/** + * @author erlend + */ +public class NamedImpl implements Named { + + private String value; + + public NamedImpl(String value) { + this.value = value; + } + + @Override + public String value() { + return value; + } + + public int hashCode() { + // This is specified in java.lang.Annotation. + return (127 * "value".hashCode()) ^ value.hashCode(); + } + + public boolean equals(Object o) { + if (!(o instanceof Named)) { + return false; + } + + Named other = (Named) o; + return value.equals(other.value()); + } + + @Override + public Class annotationType() { + return Named.class; + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/EvidenceException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/EvidenceException.java new file mode 100644 index 0000000000000000000000000000000000000000..b90e27a708a2031c30b81e8b31605b19556faf18 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/EvidenceException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +/** + * @author erlend + * @since 4.0.0 + */ +public class EvidenceException extends OxalisException { + + public EvidenceException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisContentException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisContentException.java new file mode 100644 index 0000000000000000000000000000000000000000..25512b25b09bd48a692e0c3b1a21ea460cc1c48a --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisContentException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +/** + * @author erlend + */ +public class OxalisContentException extends OxalisException { + + public OxalisContentException(String message) { + super(message); + } + + public OxalisContentException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisException.java new file mode 100644 index 0000000000000000000000000000000000000000..6be738695918fe03a2cc511c2431be7b8fcd4f91 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +/** + * Base exception of the Oxalis exception hierarchy. Thrown exceptions must use a subclass of this to indicate type + * of exception for better handling. + */ +public abstract class OxalisException extends Exception { + + public OxalisException(String message) { + super(message); + } + + public OxalisException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisLoadingException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisLoadingException.java new file mode 100644 index 0000000000000000000000000000000000000000..3dd16d2d354ae7c5b34eac8acfdaa32da1e938d2 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisLoadingException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +public class OxalisLoadingException extends OxalisRuntimeException { + + public OxalisLoadingException(String message) { + super(message); + } + + public OxalisLoadingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisPluginException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisPluginException.java new file mode 100644 index 0000000000000000000000000000000000000000..8c1659c953d4b9e02443dfc096af8dbcd8dbf6aa --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisPluginException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +public class OxalisPluginException extends OxalisRuntimeException { + + public OxalisPluginException(String message) { + super(message); + } + + public OxalisPluginException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisRuntimeException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisRuntimeException.java new file mode 100644 index 0000000000000000000000000000000000000000..1580a828d02a3e6f93973a9497c88c9438b0b157 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisRuntimeException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +public abstract class OxalisRuntimeException extends RuntimeException { + + public OxalisRuntimeException(String message) { + super(message); + } + + public OxalisRuntimeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisSecurityException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisSecurityException.java new file mode 100644 index 0000000000000000000000000000000000000000..13f03af453cab4e9947e4051ae7c7087730a47f0 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisSecurityException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +/** + * Security exceptions are always thrown to indicate a certain action would involve stepping outside + * current security domain, and forcing such action must be seen as a no-go. + */ +public class OxalisSecurityException extends OxalisException { + + public OxalisSecurityException(String message) { + super(message); + } + + public OxalisSecurityException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisTransmissionException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisTransmissionException.java new file mode 100644 index 0000000000000000000000000000000000000000..697ec79e5a41ac7af2750d509e8198e4e115a8b7 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/OxalisTransmissionException.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import java.net.URI; + +/** + * Thrown when there is a problem related to the actual transmission protocol. + *

+ * Created by soc on 17.06.2016. + */ +public class OxalisTransmissionException extends OxalisException { + + public OxalisTransmissionException(String message) { + super(message); + } + + public OxalisTransmissionException(String message, Throwable cause) { + super(message, cause); + } + + public OxalisTransmissionException(URI url, Throwable cause) { + super(String.format("Transmission failed to endpoint '%s'.", url), cause); + } + + public OxalisTransmissionException(String msg, URI url, Throwable e) { + super(String.format("%s - Transmission failed to endpoint '%s' ", msg, url), e); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/TimestampException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/TimestampException.java new file mode 100644 index 0000000000000000000000000000000000000000..4384fa84fd2632cfc437bf5bc5e18ea83517ad8e --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/TimestampException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +/** + * @author erlend + * @since 4.0.0 + */ +public class TimestampException extends OxalisException { + + public TimestampException(String message) { + super(message); + } + + public TimestampException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lang/VerifierException.java b/oxalis-api/src/main/java/network/oxalis/api/lang/VerifierException.java new file mode 100644 index 0000000000000000000000000000000000000000..ea714ceeae42153b9041fad049b340e7425fa354 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lang/VerifierException.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +/** + * @author erlend + * @since 4.0.0 + */ +public class VerifierException extends OxalisTransmissionException { + + private final Reason reason; + + public static VerifierException becauseOf(Reason reason, String message) { + return new VerifierException(reason, message); + } + + private VerifierException(Reason reason, String message) { + super(message); + this.reason = reason; + } + + public Reason getReason() { + return reason; + } + + public enum Reason { + PARTICIPANT, + DOCUMENT_TYPE, + PROCESS + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/logging/Configurator.java b/oxalis-api/src/main/java/network/oxalis/api/logging/Configurator.java new file mode 100644 index 0000000000000000000000000000000000000000..e21f865da95be1891b6593f5fb10ef8555c8eb4d --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/logging/Configurator.java @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.logging; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface Configurator { + + void execute(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/lookup/LookupService.java b/oxalis-api/src/main/java/network/oxalis/api/lookup/LookupService.java new file mode 100644 index 0000000000000000000000000000000000000000..395be5e32e6e43195faf2942907663201beb46ba --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/lookup/LookupService.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lookup; + +import io.opentracing.Span; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; + +/** + * Defines a standardized lookup service for use in Oxalis. + * + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface LookupService { + + /** + * Performs lookup using metadata from content to be sent. + * + * @param header Metadata from content. + * @return Endpoint information to be used when transmitting content. + * @throws OxalisTransmissionException Thrown if no endpoint metadata were detected using metadata. + */ + Endpoint lookup(Header header) throws OxalisTransmissionException; + + /** + * Performs lookup using metadata from content to be sent. + * + * @param header Metadata from content. + * @param root Current trace. + * @return Endpoint information to be used when transmitting content. + * @throws OxalisTransmissionException Thrown if no endpoint metadata were detected using metadata. + */ + default Endpoint lookup(Header header, Span root) throws OxalisTransmissionException { + return lookup(header); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/model/AccessPointIdentifier.java b/oxalis-api/src/main/java/network/oxalis/api/model/AccessPointIdentifier.java new file mode 100644 index 0000000000000000000000000000000000000000..740e989727d09c7949412e97e66f8b310d970980 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/model/AccessPointIdentifier.java @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.model; + +import java.io.Serializable; + +/** + * Unique identifier for a PEPPOL Access Point. + *

+ * This identifier is typically represented by the Common Name (CN) attribute of the distinguished name of the + * certificate of the Subject. + *

+ * However; the usage of the common name is only a recommendation, not a mandatory rule. + * + * @author steinar + * Date: 10.02.13 + * Time: 21:00 + */ +public class AccessPointIdentifier implements Serializable { + + private static final long serialVersionUID = 9092401962608401791L; + + private final String accessPointIdentifierValue; + + /** + * Creates an instance using whatever text value is supplied. + * + * @param accessPointIdentifierValue the textual representation of the identifier + */ + public AccessPointIdentifier(String accessPointIdentifierValue) { + this.accessPointIdentifierValue = accessPointIdentifierValue; + } + + @Override + public String toString() { + return accessPointIdentifierValue; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AccessPointIdentifier that = (AccessPointIdentifier) o; + + return accessPointIdentifierValue.equals(that.accessPointIdentifierValue); + } + + @Override + public int hashCode() { + return accessPointIdentifierValue.hashCode(); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/model/Direction.java b/oxalis-api/src/main/java/network/oxalis/api/model/Direction.java new file mode 100644 index 0000000000000000000000000000000000000000..8c8016031abe8516bfa00e8aa1be3d8fb401380e --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/model/Direction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.model; + +/** + * Indicates whether the message sent was inbound or outbound with respect to the PEPPOL network. + * I.e. an outbound message is sent from this access point into the PEPPOL network, while an inbound + * message is received from the PEPPOL network by this access point. + * +* @author steinar +* Date: 25.03.13 +* Time: 14:44 +*/ +public enum Direction { + IN, OUT +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/model/MessageDigestResult.java b/oxalis-api/src/main/java/network/oxalis/api/model/MessageDigestResult.java new file mode 100644 index 0000000000000000000000000000000000000000..d2792b86e285ae59c201f79683e6e96ba613c620 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/model/MessageDigestResult.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.model; + + +import java.util.Base64; + +/** + * Holds the digest and the algorithm name for some arbitrary contents like for instance the payload of a message, + * the message itself etc. + * + * @author steinar + * Date: 31.10.2015 + * Time: 12.49 + */ +@Deprecated +public class MessageDigestResult { + + private byte[] digest; + + private String algorithmName; + + public MessageDigestResult(byte[] digest, String algorithmName) { + this.digest = digest; + this.algorithmName = algorithmName; + } + + public String getDigestAsString() { + return new String(Base64.getEncoder().encode(digest)); + } + + public byte[] getDigest() { + return digest; + } + + public String getAlgorithmName() { + return algorithmName; + } + + @Override + public String toString() { + return "MessageDigestResult{" + + "digest=" + getDigestAsString() + + ", algorithmName='" + algorithmName + '\'' + + '}'; + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/model/TransmissionIdentifier.java b/oxalis-api/src/main/java/network/oxalis/api/model/TransmissionIdentifier.java new file mode 100644 index 0000000000000000000000000000000000000000..c0dd82dca243245d99afe71dd657fa65d2a69b98 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/model/TransmissionIdentifier.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.model; + +import network.oxalis.vefa.peppol.common.model.AbstractSimpleIdentifier; + +import java.io.Serializable; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author erlend + */ +public class TransmissionIdentifier extends AbstractSimpleIdentifier implements Serializable { + + private static final long serialVersionUID = 5280858533226027168L; + + private static final Pattern RFC2822 = Pattern.compile("^<(.+?)>$"); + + public static TransmissionIdentifier generateUUID() { + return of(UUID.randomUUID().toString()); + } + + public static TransmissionIdentifier of(String value) { + return new TransmissionIdentifier(value); + } + + public static TransmissionIdentifier fromHeader(String value) { + Matcher matcher = RFC2822.matcher(value); + if (matcher.matches()) + return of(matcher.group(1)); + + return of(value); + } + + private TransmissionIdentifier(String value) { + super(value); + } + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/outbound/MessageSender.java b/oxalis-api/src/main/java/network/oxalis/api/outbound/MessageSender.java new file mode 100644 index 0000000000000000000000000000000000000000..338a189063feba65315fcdef73fcabb28110e90f --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/outbound/MessageSender.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.outbound; + +import io.opentracing.Span; +import network.oxalis.api.lang.OxalisTransmissionException; + +/** + * MessageSender is implemented by a specific protocol implementation. + * + * @author steinar + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface MessageSender { + + /** + * Protocol specific transmission of transmission requested. (Without tracing.) + * + * @param transmissionRequest Requested transmission to take place. + * @return Response content of a successful transmission. + * @throws OxalisTransmissionException Thrown when transmission was not sent according to protocol specific rules or + * because something went wrong during transmission. + */ + TransmissionResponse send(TransmissionRequest transmissionRequest) throws OxalisTransmissionException; + + /** + * Protocol specific transmission of transmission requested. (With tracing.) + * + * @param transmissionRequest Requested transmission to take place. + * @param root Current trace. + * @return Response content of a successful transmission. + * @throws OxalisTransmissionException Thrown when transmission was not sent according to protocol specific rules or + * because something went wrong during transmission. + */ + default TransmissionResponse send(TransmissionRequest transmissionRequest, Span root) + throws OxalisTransmissionException { + return send(transmissionRequest); + } + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionMessage.java b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..d00df2da9dd540fac104e65e3dae0e0540ae04c8 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionMessage.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.outbound; + +import network.oxalis.api.tag.Tag; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface TransmissionMessage { + + /** + * Returns a tag set by client. + * + * @return Tag + * @since 4.0.2 + */ + default Tag getTag() { + return Tag.NONE; + } + + Header getHeader(); + + InputStream getPayload(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionRequest.java b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..c3fb3ec41a81ee9155788d19adbf875654632423 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionRequest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.outbound; + +import network.oxalis.vefa.peppol.common.model.Endpoint; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface TransmissionRequest extends TransmissionMessage { + + Endpoint getEndpoint(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionResponse.java b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..14ac07b70e9f716c15e4e7b738c6e607ba2d10b1 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionResponse.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.outbound; + +import network.oxalis.api.tag.Tag; +import network.oxalis.api.transmission.TransmissionResult; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.TransportProfile; + +/** + * @author steinar + * @author thore + * @author erlend + * @since 4.0.0 + */ +public interface TransmissionResponse extends TransmissionResult { + + /** + * Returns a tag set by client. + * + * @return Tag + * @since 4.0.2 + */ + default Tag getTag() { + return Tag.NONE; + } + + Endpoint getEndpoint(); + + /** + * {@inheritDoc} + */ + @Override + default TransportProfile getProtocol() { + return getEndpoint().getTransportProfile(); + } + + + /** + * Provides access to the native transmission evidence like for instance the MDN for AS2 + */ + @Deprecated + default byte[] getNativeEvidenceBytes() { + return primaryReceipt().getValue(); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionService.java b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionService.java new file mode 100644 index 0000000000000000000000000000000000000000..7b56fccba9469380a56f9e4d9b0b372fcc3da474 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/outbound/TransmissionService.java @@ -0,0 +1,111 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.outbound; + +import io.opentracing.Span; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.tag.Tag; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Defines a standardized transmission service interface accepting the InputStream of the content to be sent. + *

+ * Typical implementation: + *

+ * {@code
+ * public TransmissionResponse send(InputStream inputStream) throws IOException, OxalisTransmissionException {
+ *      TransmissionRequestFactory transmissionRequestFactory = // Fetch or find locally.
+ *      TransmissionRequest transmissionRequest = transmissionRequestFactory.newInstance(inputStream);
+ *
+ *      Transmitter transmitter = // Fetch or find locally.
+ *      TransmissionResponse transmissionResponse = transmitter.transmit(transmissionRequest)
+ *
+ *      return transmissionResponse;
+ * }
+ * }
+ * 
+ * + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface TransmissionService { + + /** + * Sends content found in the InputStream. + * + * @param inputStream InputStream containing content to be sent. + * @return Transmission response containing information from the performed transmission. + * @throws IOException Thrown on any IO exception. + * @throws OxalisTransmissionException Thrown if there were any problems making Oxalis unable to send the content. + */ + default TransmissionResponse send(InputStream inputStream) + throws IOException, OxalisTransmissionException, OxalisContentException { + return send(inputStream, Tag.NONE); + } + + /** + * Sends content found in the InputStream. + * + * @param inputStream InputStream containing content to be sent. + * @param tag Tag defined by client. + * @return Transmission response containing information from the performed transmission. + * @throws IOException Thrown on any IO exception. + * @throws OxalisTransmissionException Thrown if there were any problems making Oxalis unable to send the content. + */ + TransmissionResponse send(InputStream inputStream, Tag tag) + throws IOException, OxalisTransmissionException, OxalisContentException; + + /** + * Sends content found in the InputStream. + * + * @param inputStream InputStream containing content to be sent. + * @param root Current trace. + * @return Transmission response containing information from the performed transmission. + * @throws IOException Thrown on any IO exception. + * @throws OxalisTransmissionException Thrown if there were any problems making Oxalis unable to send the content. + */ + default TransmissionResponse send(InputStream inputStream, Span root) + throws IOException, OxalisTransmissionException, OxalisContentException { + return send(inputStream, Tag.NONE); + } + + /** + * Sends content found in the InputStream. + * + * @param inputStream InputStream containing content to be sent. + * @param tag Tag defined by client. + * @param root Current trace. + * @return Transmission response containing information from the performed transmission. + * @throws IOException Thrown on any IO exception. + * @throws OxalisTransmissionException Thrown if there were any problems making Oxalis unable to send the content. + */ + default TransmissionResponse send(InputStream inputStream, Tag tag, Span root) + throws IOException, OxalisTransmissionException, OxalisContentException { + return send(inputStream, tag); + } + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/outbound/Transmitter.java b/oxalis-api/src/main/java/network/oxalis/api/outbound/Transmitter.java new file mode 100644 index 0000000000000000000000000000000000000000..01c4208143452229d1329aaa19eca7cef8d04da3 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/outbound/Transmitter.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.outbound; + +import io.opentracing.Span; +import network.oxalis.api.lang.OxalisTransmissionException; + +/** + * Interface defining contract of Transmitter. A transmitter instance is multi-protocol, and transmits content of + * transmission request based on requested transport profile. + * + * @author steinar + * Date: 18.11.2016 + * Time: 16.21 + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface Transmitter { + + /** + * Transmit content of transmission request. (No tracing.) + * + * @param transmissionMessage Content to be transmitted. + * @return Result of transmission. + * @throws OxalisTransmissionException Thrown when transmission fails. + */ + TransmissionResponse transmit(TransmissionMessage transmissionMessage) throws OxalisTransmissionException; + + /** + * Transmit content of transmission request. (With tracing.) + * + * @param transmissionMessage Content to be transmitted. + * @param root Current trace. + * @return Result of transmission. + * @throws OxalisTransmissionException Thrown when transmission fails. + */ + default TransmissionResponse transmit(TransmissionMessage transmissionMessage, Span root) + throws OxalisTransmissionException { + return transmit(transmissionMessage); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/persist/ExceptionPersister.java b/oxalis-api/src/main/java/network/oxalis/api/persist/ExceptionPersister.java new file mode 100644 index 0000000000000000000000000000000000000000..7a576505b9c8f5f98534286dc97c07f77e112516 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/persist/ExceptionPersister.java @@ -0,0 +1,17 @@ +package network.oxalis.api.persist; + +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.3 + */ +@FunctionalInterface +public interface ExceptionPersister { + + void persist(TransmissionIdentifier transmissionIdentifier, Header header, Path payloadPath, Exception exception); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/persist/PayloadPersister.java b/oxalis-api/src/main/java/network/oxalis/api/persist/PayloadPersister.java new file mode 100644 index 0000000000000000000000000000000000000000..b246687e0d06859a6f4fd01a58ef9d10e6b9d515 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/persist/PayloadPersister.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.persist; + +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface PayloadPersister { + + Path persist(TransmissionIdentifier transmissionIdentifier, Header header, InputStream inputStream) + throws IOException; + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/persist/PersisterHandler.java b/oxalis-api/src/main/java/network/oxalis/api/persist/PersisterHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..9682037e367a9841de3e51248141574ec6da129a --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/persist/PersisterHandler.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.persist; + +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface PersisterHandler extends PayloadPersister, ReceiptPersister, ExceptionPersister { + + @Override + default void persist(TransmissionIdentifier transmissionIdentifier, Header header, + Path payloadPath, Exception exception) { + // No action. + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/persist/ReceiptPersister.java b/oxalis-api/src/main/java/network/oxalis/api/persist/ReceiptPersister.java new file mode 100644 index 0000000000000000000000000000000000000000..3af5edf61d74024e891942c22dc42401e4b36a32 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/persist/ReceiptPersister.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.persist; + +import network.oxalis.api.inbound.InboundMetadata; + +import java.io.IOException; +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface ReceiptPersister { + + void persist(InboundMetadata inboundMetadata, Path payloadPath) throws IOException; + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/plugin/PluginFactory.java b/oxalis-api/src/main/java/network/oxalis/api/plugin/PluginFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..92bc0d2769b04c6b060015be756bfcb9fc7c3a2f --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/plugin/PluginFactory.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.plugin; + +/** + * Interface describing a factory for creation of implementation of specific provided interface. + * + * @author erlend + * @since 4.0.0 + */ +public interface PluginFactory { + + T newInstance(Class cls); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/settings/DefaultValue.java b/oxalis-api/src/main/java/network/oxalis/api/settings/DefaultValue.java new file mode 100644 index 0000000000000000000000000000000000000000..db4bd27dc1a1e6828ed043e338db486cae1bf6bc --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/settings/DefaultValue.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.settings; + +import java.lang.annotation.*; + +/** + * @author erlend + * @since 4.0.0 + */ +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface DefaultValue { + + String value(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/settings/Nullable.java b/oxalis-api/src/main/java/network/oxalis/api/settings/Nullable.java new file mode 100644 index 0000000000000000000000000000000000000000..93fc880d2c82eb866149fbf0999f0b59adde983a --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/settings/Nullable.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.settings; + +import java.lang.annotation.*; + +/** + * @author erlend + * @since 4.0.0 + */ +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Nullable { + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/settings/Path.java b/oxalis-api/src/main/java/network/oxalis/api/settings/Path.java new file mode 100644 index 0000000000000000000000000000000000000000..fc36bff639ce6209bee0376c2633d393cca8af36 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/settings/Path.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.settings; + +import java.lang.annotation.*; + +/** + * @author erlend + * @since 4.0.0 + */ +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Path { + + String value(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/settings/Secret.java b/oxalis-api/src/main/java/network/oxalis/api/settings/Secret.java new file mode 100644 index 0000000000000000000000000000000000000000..d0361b98fc7e7903fd6c28c36122e736e2d3a7d3 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/settings/Secret.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.settings; + +import java.lang.annotation.*; + +/** + * @author erlend + * @since 4.0.0 + */ +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Secret { +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/settings/Settings.java b/oxalis-api/src/main/java/network/oxalis/api/settings/Settings.java new file mode 100644 index 0000000000000000000000000000000000000000..6024654ae0b66a8dafa128994ff8ff693eed55e5 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/settings/Settings.java @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.settings; + +import network.oxalis.api.inject.NamedImpl; + +import javax.inject.Named; +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface Settings { + + String getString(T key); + + int getInt(T key); + + default Named getNamed(T key) { + return new NamedImpl(getString(key)); + } + + default Path getPath(T key, Path path) { + String value = getString(key); + if (value == null) + return null; + + return path.resolve(value); + } + + default String toLogSafeString(T key) { + return getString(key); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/settings/Title.java b/oxalis-api/src/main/java/network/oxalis/api/settings/Title.java new file mode 100644 index 0000000000000000000000000000000000000000..702dad148e1e4fe8e6e78b37ef6bfef00904f461 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/settings/Title.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.settings; + +import java.lang.annotation.*; + +/** + * @author erlend + */ +@Documented +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Title { + + String value(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/statistics/StatisticsService.java b/oxalis-api/src/main/java/network/oxalis/api/statistics/StatisticsService.java new file mode 100644 index 0000000000000000000000000000000000000000..7ae2a95e22b89442c823885d04ab0b3c5013a2a1 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/statistics/StatisticsService.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.statistics; + +import io.opentracing.Span; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.inbound.InboundMetadata; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface StatisticsService { + + void persist(TransmissionRequest transmissionRequest, TransmissionResponse transmissionResponse, Span root); + + void persist(InboundMetadata inboundMetadata); +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/tag/Tag.java b/oxalis-api/src/main/java/network/oxalis/api/tag/Tag.java new file mode 100644 index 0000000000000000000000000000000000000000..bfe4787e47de6c6b9082f5c71308fb5139d2fea7 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/tag/Tag.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.tag; + +import java.util.Objects; + +/** + * @author erlend + * @since 4.0.2 + */ +public interface Tag { + + Tag NONE = of("NONE"); + + String getIdentifier(); + + static Tag of(String identifier) { + return new DefaultTag(identifier); + } + + class DefaultTag implements Tag { + private String identifier; + + private DefaultTag(String identifier) { + this.identifier = identifier; + } + + @Override + public String getIdentifier() { + return identifier; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DefaultTag that = (DefaultTag) o; + return Objects.equals(identifier, that.identifier); + } + + @Override + public int hashCode() { + return Objects.hash(identifier); + } + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/tag/TagGenerator.java b/oxalis-api/src/main/java/network/oxalis/api/tag/TagGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..890c98b6f8213a49ee4e79c9666a74aa16b683d6 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/tag/TagGenerator.java @@ -0,0 +1,17 @@ +package network.oxalis.api.tag; + +import network.oxalis.api.model.Direction; + +/** + * @author erlend + * @since 4.0.2 + */ +public interface TagGenerator { + + default Tag generate(Direction direction, Tag original) { + return original != Tag.NONE ? original : generate(direction); + } + + Tag generate(Direction direction); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/timestamp/Timestamp.java b/oxalis-api/src/main/java/network/oxalis/api/timestamp/Timestamp.java new file mode 100644 index 0000000000000000000000000000000000000000..888def2f861eadc99710a2676601bd5d5ec84ba6 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/timestamp/Timestamp.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.timestamp; + +import network.oxalis.vefa.peppol.common.model.Receipt; + +import java.io.Serializable; +import java.util.Date; +import java.util.Optional; + +/** + * Class used to hold a provided timestamp and a potential receipt as a result of fetching timestamp. + * + * @author erlend + * @since 4.0.0 + */ +public class Timestamp implements Serializable { + + private static final long serialVersionUID = -748252484013456945L; + + /** + * Timestamp to be presented. + */ + private final Date date; + + /** + * Receipt to be presented + */ + private final Optional receipt; + + /** + * Constructor accepting a timestamp and potentially a receipt. + * + * @param date Timestamp to be available. + * @param receipt Receipt to be available. + */ + public Timestamp(Date date, Receipt receipt) { + this.date = date; + this.receipt = Optional.ofNullable(receipt); + } + + /** + * Fetch timestamp. + * + * @return Timestamp. + */ + public Date getDate() { + return date; + } + + /** + * Fetch receipt. + * + * @return Optional receipt. + */ + public Optional getReceipt() { + return receipt; + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/timestamp/TimestampProvider.java b/oxalis-api/src/main/java/network/oxalis/api/timestamp/TimestampProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..d14d893e1400645af6df12a8551bde49d865c95e --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/timestamp/TimestampProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.timestamp; + +import io.opentracing.Span; +import network.oxalis.api.lang.TimestampException; +import network.oxalis.api.model.Direction; + +/** + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface TimestampProvider { + + Timestamp generate(byte[] content, Direction direction) throws TimestampException; + + default Timestamp generate(byte[] content, Direction direction, Span span) throws TimestampException { + return generate(content, direction); + } +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/transformer/ContentDetector.java b/oxalis-api/src/main/java/network/oxalis/api/transformer/ContentDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..6816131dedc17dac75d471f91769c06d5500f219 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/transformer/ContentDetector.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.transformer; + +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.1 + */ +public interface ContentDetector { + + Header parse(InputStream inputStream) throws OxalisContentException; + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/transformer/ContentWrapper.java b/oxalis-api/src/main/java/network/oxalis/api/transformer/ContentWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..87526ad379670716ac77b012de5a27697ecaa917 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/transformer/ContentWrapper.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.transformer; + +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.1 + */ +public interface ContentWrapper { + + InputStream wrap(InputStream inputStream, Header header) throws IOException, OxalisContentException; + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/transmission/TransmissionResult.java b/oxalis-api/src/main/java/network/oxalis/api/transmission/TransmissionResult.java new file mode 100644 index 0000000000000000000000000000000000000000..7f6d8dbf944dd8cf330d8ca5be69fccda9bc24c5 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/transmission/TransmissionResult.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.transmission; + +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.vefa.peppol.common.model.*; + +import java.util.Date; +import java.util.List; + +/** + * @author erlend + * @since 4.0.0 + */ +public interface TransmissionResult { + + /** + * Transmission id assigned during transmission + */ + TransmissionIdentifier getTransmissionIdentifier(); + + Header getHeader(); + + Date getTimestamp(); + + Digest getDigest(); + + TransportProtocol getTransportProtocol(); + + /** + * The protocol used for the transmission + */ + TransportProfile getProtocol(); + + List getReceipts(); + + Receipt primaryReceipt(); + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/transmission/TransmissionVerifier.java b/oxalis-api/src/main/java/network/oxalis/api/transmission/TransmissionVerifier.java new file mode 100644 index 0000000000000000000000000000000000000000..519da5a565c606314a1a13c6233ba29dd125d381 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/transmission/TransmissionVerifier.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.transmission; + +import network.oxalis.api.lang.VerifierException; +import network.oxalis.api.model.Direction; +import network.oxalis.vefa.peppol.common.model.Header; + +/** + * @author erlend + * @since 4.0.0 + */ +@FunctionalInterface +public interface TransmissionVerifier { + + void verify(Header header, Direction direction) throws VerifierException; + +} diff --git a/oxalis-api/src/main/java/network/oxalis/api/util/Sort.java b/oxalis-api/src/main/java/network/oxalis/api/util/Sort.java new file mode 100644 index 0000000000000000000000000000000000000000..48e27dadded2778608a8d7ed7ef166c055a9b371 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/util/Sort.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation for declaring a value used for comparison. + * + * @author erlend + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Sort { + + /** + * Value used to compare. + * + * @return Value used to compare. + */ + int value() default 0; +} \ No newline at end of file diff --git a/oxalis-api/src/main/java/network/oxalis/api/util/Type.java b/oxalis-api/src/main/java/network/oxalis/api/util/Type.java new file mode 100644 index 0000000000000000000000000000000000000000..7de56636d54ed77d72c03999cf6c958437ab9579 --- /dev/null +++ b/oxalis-api/src/main/java/network/oxalis/api/util/Type.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation works as a replacement of {@link javax.inject.Named} to allow for multiple + * names for a given implementation. Used in combination with OxalisModule. + * + * @author erlend + * @since 4.0.1 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Type { + + String[] value(); + +} diff --git a/oxalis-api/src/main/resources/oxalis-version.properties b/oxalis-api/src/main/resources/oxalis-version.properties new file mode 100644 index 0000000000000000000000000000000000000000..556dd8b399b06baf35907382b21aeea6d8fe8335 --- /dev/null +++ b/oxalis-api/src/main/resources/oxalis-version.properties @@ -0,0 +1,42 @@ +# +# Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) +# +# Licensed under the EUPL, Version 1.1 or – as soon they +# will be approved by the European Commission - subsequent +# versions of the EUPL (the "Licence"); +# +# You may not use this work except in compliance with the Licence. +# +# You may obtain a copy of the Licence at: +# +# https://joinup.ec.europa.eu/community/eupl/og_page/eupl +# +# Unless required by applicable law or agreed to in +# writing, software distributed under the Licence is +# distributed on an "AS IS" basis, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. +# See the Licence for the specific language governing +# permissions and limitations under the Licence. +# + +# +# Property values are injected by Maven filtering at build time +# The SCM build info relies on the git-commit-id-plugin +# +oxalis.version=${project.version} +oxalis.user=${env.USER} +build.tstamp=${build.timestamp} + +git.branch=${git.branch} +git.commit.id.describe=${git.commit.id.describe} +git.build.user.name=${git.build.user.name} +git.build.user.email=${git.build.user.email} +git.build.time=${git.build.time} +git.commit.id=${git.commit.id} +git.commit.id.abbrev=${git.commit.id.abbrev} +git.commit.user.name=${git.commit.user.name} +git.commit.user.email=${git.commit.user.email} +git.commit.message.full=${git.commit.message.full} +git.commit.message.short=${git.commit.message.short} +git.commit.time=${git.commit.time} \ No newline at end of file diff --git a/oxalis-api/src/test/java/network/oxalis/api/inject/NamedImplTest.java b/oxalis-api/src/test/java/network/oxalis/api/inject/NamedImplTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a44f3f380c9eb9a1e715434d6afd6232d4f8ae94 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/inject/NamedImplTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.inject; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import javax.inject.Named; + +/** + * @author erlend + */ +public class NamedImplTest { + + @Test + public void simple() { + NamedImpl named = new NamedImpl("test"); + + Assert.assertEquals(named.value(), "test"); + Assert.assertNotNull(named.hashCode()); + Assert.assertEquals(named.annotationType(), Named.class); + Assert.assertFalse(named.equals(new Object())); + Assert.assertTrue(named.equals(new NamedImpl("test"))); + Assert.assertFalse(named.equals(new NamedImpl("other"))); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/lang/EvidenceExceptionTest.java b/oxalis-api/src/test/java/network/oxalis/api/lang/EvidenceExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c8e373add57e061964a31c44d7a41d6ec6868c19 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/lang/EvidenceExceptionTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class EvidenceExceptionTest { + + @Test + public void simple() { + new EvidenceException("Test", new Exception()); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisLoadingExceptionTest.java b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisLoadingExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..71689ae63aff3bebef834ff76e4755ee3e7294ee --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisLoadingExceptionTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class OxalisLoadingExceptionTest { + + @Test + public void simple() { + new OxalisLoadingException("Test"); + new OxalisLoadingException("Test", new Exception()); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisPluginExceptionTest.java b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisPluginExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..941984a49814acb6c72ae0ae4836ceb089f35ec4 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisPluginExceptionTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class OxalisPluginExceptionTest { + + @Test + public void simple() { + new OxalisPluginException("Test"); + new OxalisPluginException("Test", new Exception()); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisSecurityExceptionTest.java b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisSecurityExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..997d68fc571f1f395336217a268c39a9c5d95a16 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisSecurityExceptionTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class OxalisSecurityExceptionTest { + + @Test + public void simple() { + new OxalisSecurityException("Test"); + new OxalisSecurityException("Test", new Exception()); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisTransmissionExceptionTest.java b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisTransmissionExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9a5881ea4c5952070bc497695ddd49c339844b8d --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/lang/OxalisTransmissionExceptionTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import org.testng.annotations.Test; + +import java.net.URI; + +/** + * @author erlend + */ +public class OxalisTransmissionExceptionTest { + + @Test + public void simple() { + new OxalisTransmissionException("Test"); + new OxalisTransmissionException("Test", new Exception()); + new OxalisTransmissionException(URI.create("http://test.com/"), new Exception()); + new OxalisTransmissionException("Test", URI.create("http://test.com/"), new Exception()); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/lang/TimestampExceptionTest.java b/oxalis-api/src/test/java/network/oxalis/api/lang/TimestampExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..934ee5683a4278bebc21cdc5d98adc2f5e97b947 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/lang/TimestampExceptionTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class TimestampExceptionTest { + + @Test + public void simple() { + new TimestampException("Test"); + new TimestampException("Test", new Exception()); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/lang/VerifierExceptionTest.java b/oxalis-api/src/test/java/network/oxalis/api/lang/VerifierExceptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f98d9d3cbbf491ad2417cea2aae81f16f0410f7e --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/lang/VerifierExceptionTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.lang; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class VerifierExceptionTest { + + @Test + public void simple() { + VerifierException verifierException = VerifierException + .becauseOf(VerifierException.Reason.PARTICIPANT, "Unknown"); + + Assert.assertEquals(verifierException.getReason(), VerifierException.Reason.PARTICIPANT); + + Assert.assertNotNull(VerifierException.Reason.valueOf("PARTICIPANT")); + } + +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/model/AccessPointIdentifierTest.java b/oxalis-api/src/test/java/network/oxalis/api/model/AccessPointIdentifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e4f22d052bb0f3f289a806d5c81a6467809df1d9 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/model/AccessPointIdentifierTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.model; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class AccessPointIdentifierTest { + + @Test + public void simple() { + AccessPointIdentifier accessPointIdentifier = new AccessPointIdentifier("TEST"); + + Assert.assertEquals(accessPointIdentifier.toString(), "TEST"); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/model/DirectionTest.java b/oxalis-api/src/test/java/network/oxalis/api/model/DirectionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2d269555b220d8368f764fc8233a9d7c0fb06000 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/model/DirectionTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.model; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class DirectionTest { + + @Test + public void simple() { + Assert.assertEquals(Direction.values().length, 2); + Assert.assertEquals(Direction.valueOf("IN"), Direction.IN); + Assert.assertEquals(Direction.valueOf("OUT"), Direction.OUT); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/model/TransmissionIdentifierTest.java b/oxalis-api/src/test/java/network/oxalis/api/model/TransmissionIdentifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ad811897464335fcbb4ac4e867360c7dfcfe557d --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/model/TransmissionIdentifierTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.model; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class TransmissionIdentifierTest { + + @Test + public void simple() { + Assert.assertEquals(TransmissionIdentifier.of("Test").getIdentifier(), "Test"); + Assert.assertNotNull(TransmissionIdentifier.generateUUID().getIdentifier()); + + Assert.assertEquals(TransmissionIdentifier.fromHeader("").getIdentifier(), "Test"); + Assert.assertEquals(TransmissionIdentifier.fromHeader("Test").getIdentifier(), "Test"); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/timestamp/TimestampProviderTest.java b/oxalis-api/src/test/java/network/oxalis/api/timestamp/TimestampProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a04825c08f9f5b16d0a991ee4f8ff5bf7eb7121a --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/timestamp/TimestampProviderTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.timestamp; + +import network.oxalis.api.lang.TimestampException; +import network.oxalis.vefa.peppol.common.model.Receipt; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.Date; + +public class TimestampProviderTest { + + @Test + public void simple() throws TimestampException { + TimestampProvider timestampProvider = (content, direction) -> new Timestamp(new Date(), Receipt.of(content)); + + Timestamp timestamp = timestampProvider.generate("Hello World!".getBytes(), null); + + Assert.assertNotNull(timestamp.getDate()); + Assert.assertNotNull(timestamp.getReceipt().get()); + Assert.assertEquals(timestamp.getReceipt().get().getValue(), "Hello World!".getBytes()); + } +} diff --git a/oxalis-api/src/test/java/network/oxalis/api/timestamp/TimestampTest.java b/oxalis-api/src/test/java/network/oxalis/api/timestamp/TimestampTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8f20dad0954290db9ecf6113e29d9e92cbc9e1e3 --- /dev/null +++ b/oxalis-api/src/test/java/network/oxalis/api/timestamp/TimestampTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.api.timestamp; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.util.Date; + +public class TimestampTest { + + @Test + public void simple() { + Timestamp timestamp = new Timestamp(new Date(), null); + + Assert.assertNotNull(timestamp.getDate()); + Assert.assertFalse(timestamp.getReceipt().isPresent()); + } +} diff --git a/oxalis-api/src/test/resources/META-INF/services/eu.peppol.persistence.api.DataSourceProvider b/oxalis-api/src/test/resources/META-INF/services/eu.peppol.persistence.api.DataSourceProvider new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/oxalis-api/src/test/resources/META-INF/services/eu.peppol.persistence.api.DataSourceProvider @@ -0,0 +1 @@ + diff --git a/oxalis-api/src/test/resources/META-INF/services/eu.peppol.statistics.StatisticsRepository b/oxalis-api/src/test/resources/META-INF/services/eu.peppol.statistics.StatisticsRepository new file mode 100644 index 0000000000000000000000000000000000000000..1ef8025fb62a105e25f371e74a6c791331b96e0f --- /dev/null +++ b/oxalis-api/src/test/resources/META-INF/services/eu.peppol.statistics.StatisticsRepository @@ -0,0 +1 @@ +eu.peppol.statistics.StatisticsRepositoryTestImpl diff --git a/oxalis-api/src/test/resources/oxalis-statistics.properties b/oxalis-api/src/test/resources/oxalis-statistics.properties new file mode 100644 index 0000000000000000000000000000000000000000..163e4d51f88c958731e459e10401231215ddcbc5 --- /dev/null +++ b/oxalis-api/src/test/resources/oxalis-statistics.properties @@ -0,0 +1,27 @@ +# +# Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) +# +# Licensed under the EUPL, Version 1.1 or – as soon they +# will be approved by the European Commission - subsequent +# versions of the EUPL (the "Licence"); +# +# You may not use this work except in compliance with the Licence. +# +# You may obtain a copy of the Licence at: +# +# https://joinup.ec.europa.eu/community/eupl/og_page/eupl +# +# Unless required by applicable law or agreed to in +# writing, software distributed under the Licence is +# distributed on an "AS IS" basis, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. +# See the Licence for the specific language governing +# permissions and limitations under the Licence. +# + +# +oxalis.statistics.url=file://${project.build.testOutputDirectory}/ + + + diff --git a/oxalis-commons/doc/Obtaining-database-connection.puml b/oxalis-commons/doc/Obtaining-database-connection.puml new file mode 100644 index 0000000000000000000000000000000000000000..412b766ad99df615e045728bdd3407eeb6382872 --- /dev/null +++ b/oxalis-commons/doc/Obtaining-database-connection.puml @@ -0,0 +1,40 @@ +@startuml +participant Client +participant GuiceModule as GM +participant RawStatisticsRepositoryFactoryProvider as RSRFP +participant "RawStatisticsRepositoryFactoryProvider.\nStatisticsRepositoryFactoryHolder" as SRFH +participant ServiceLoader +participant RawStatisticsRepositoryFactoryJdbcImpl <> + +Client -> GM : provideStatisticsRepository +activate GM +GM -> RSRFP : getInstance() +activate RSRFP +RSRFP -> SRFH : static initalization +SRFH -> RSRFP : loadInstance() +activate RSRFP +RSRFP -> ServiceLoader: load(RawStatisticsRepositoryFactory.class) +activate ServiceLoader +ServiceLoader -> ServiceLoader : Iterates over \nMETA-INF/services entries +ServiceLoader -> RawStatisticsRepositoryFactoryJdbcImpl : new +RSRFP <-- ServiceLoader : jdbcImpl:RawStatisticsRepositoryFactory +deactivate ServiceLoader +SRFH <-- RSRFP : jdbcImpl:RawStatisticsRepositoryFactory +deactivate RSRFP + +RSRFP <-- SRFH : jdbcImpl:RawStatisticsRepositoryFactory +GM <-- RSRFP : jdbcImpl:RawStatisticsRepositoryFactory +deactivate RSRFP +GM -> RawStatisticsRepositoryFactoryJdbcImpl : getInstanceForRawStatistics() +activate RawStatisticsRepositoryFactoryJdbcImpl + RawStatisticsRepositoryFactoryJdbcImpl -> OxalisDataSourceFactoryProvider : getInstance + activate OxalisDataSourceFactoryProvider + OxalisDataSourceFactoryProvider -> OxalisDataSourceFactoryProvider: loadInstance() + deactivate OxalisDataSourceFactoryProvider + + RawStatisticsRepositoryFactoryJdbcImpl -> RawStatisticsRepositoryMySqlImpl : switch on JdbcDialect and new() + GM <-- RawStatisticsRepositoryFactoryJdbcImpl : :RawStatisticsRepository +deactivate RawStatisticsRepositoryFactoryJdbcImpl +Client <-- GM : :RawStatisticsRepository +deactivate GM +@enduml \ No newline at end of file diff --git a/oxalis-commons/pom.xml b/oxalis-commons/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..95eb4324701b41ccc2a7e58642d0ca3b9060f212 --- /dev/null +++ b/oxalis-commons/pom.xml @@ -0,0 +1,150 @@ + + + + + 4.0.0 + + + dk.erst.oxalis + oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + + oxalis-commons + + Oxalis :: Core :: Commons + + Holds the stuff which is common for both inbound and outbound messages and should be shared between them. + + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + + + dk.erst.oxalis + oxalis-api + + + dk.erst.oxalis + oxalis-test + test + + + + + org.slf4j + jcl-over-slf4j + + + ch.qos.logback + logback-classic + provided + + + + + com.google.inject + guice + + + + + network.oxalis.vefa + peppol-mode + + + network.oxalis.vefa + peppol-sbdh + + + network.oxalis.vefa + peppol-evidence + + + + org.apache.httpcomponents + httpclient + + + + + io.zipkin.brave + brave + + + io.zipkin.reporter2 + zipkin-sender-urlconnection + + + + + + io.opentracing + opentracing-noop + + + io.opentracing.contrib + opentracing-apache-httpclient + + + io.opentracing.contrib + opentracing-spanmanager + + + io.opentracing.brave + brave-opentracing + + + + + + + + + src/main/resources + true + + **/*.jks + **/*.key + + + + src/main/resources + false + + **/*.jks + **/*.key + + + + + + diff --git a/oxalis-commons/src/main/java/dk/erst/oxalis/commons/filesystem/detector/RelativePropertyHomeDetector.java b/oxalis-commons/src/main/java/dk/erst/oxalis/commons/filesystem/detector/RelativePropertyHomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..5649f6f91773a58b46a001de3f20b458b8631ccd --- /dev/null +++ b/oxalis-commons/src/main/java/dk/erst/oxalis/commons/filesystem/detector/RelativePropertyHomeDetector.java @@ -0,0 +1,33 @@ +package dk.erst.oxalis.commons.filesystem.detector; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.filesystem.HomeDetector; +import network.oxalis.api.util.Sort; +import org.kohsuke.MetaInfServices; + +import java.io.File; + +@Slf4j +@Sort(2500) +@MetaInfServices +public class RelativePropertyHomeDetector implements HomeDetector { + + protected static final String VARIABLE = "RELATIVE_OXALIS_HOME"; + + @Override + public File detect() { + String value = System.getProperty(VARIABLE); + if (value == null || value.isEmpty()) + return null; + + if(value.startsWith("/")){ + value = value.substring(1); + } + + String catalinaBase = System.getProperty("catalina.base"); + + log.info("Using Oxalis folder specified as Java System Property '-D {}' with value '{}/{}'.", + VARIABLE, catalinaBase, value); + return new File(catalinaBase, value); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/bouncycastle/BCHelper.java b/oxalis-commons/src/main/java/network/oxalis/commons/bouncycastle/BCHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..00924143d3df36c45ffe64bbbf239fa4b169716b --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/bouncycastle/BCHelper.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.bouncycastle; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; + +/** + * Collection of functionality related to BouncyCastle. + * + * @author erlend + * @since 4.0.0 + */ +public class BCHelper { + + static { + registerProvider(); + } + + /** + * Registers BouncyCastle as provider if not already registered. + */ + public static void registerProvider() { + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) + Security.addProvider(new BouncyCastleProvider()); + } + + /** + * Creates a MessageDigest object using the BouncyCastle provider. Exception {@link NoSuchProviderException} is + * disguised as {@link NoSuchAlgorithmException}. + * + * @param algorithm Algorithm to be use to create the MessageDigest object. + * @return MessageDigest object ready for use. + * @throws NoSuchAlgorithmException Thrown in cases when unknown algorithms are requestes. + */ + public static MessageDigest getMessageDigest(String algorithm) throws NoSuchAlgorithmException { + try { + return MessageDigest.getInstance(algorithm, BouncyCastleProvider.PROVIDER_NAME); + } catch (NoSuchProviderException e) { + throw new NoSuchAlgorithmException(e.getMessage(), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/config/ConfigModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/config/ConfigModule.java new file mode 100644 index 0000000000000000000000000000000000000000..9880fed89605c1818f5f4f0eefc841b7f6179aec --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/config/ConfigModule.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.config; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import com.google.inject.name.Named; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.commons.guice.OxalisModule; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Set; + +/** + * @author erlend + * @since 4.0.0 + */ +@Slf4j +public class ConfigModule extends OxalisModule { + + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), PostConfig.class); + multibinder.addBinding().to(JavaPropertiesPostConfig.class); + } + + @Provides + @Singleton + @Named("file") + protected Config loadConfigurationFile(@Named("conf") Path homePath) { + Path configPath = homePath.resolve("oxalis.conf"); + log.info("Configuration file: {}", configPath); + + return Files.exists(configPath) && Files.isReadable(configPath) ? + ConfigFactory.parseFile(configPath.toFile()).resolve() : + ConfigFactory.empty(); + } + + @Provides + @Singleton + @Named("reference") + protected Config loadConfigurationReference() { + Config referenceConfig = ConfigFactory.defaultReference(); + + return referenceConfig + .withFallback(referenceConfig.getConfig("defaults")); + } + + @Provides + @Singleton + protected Config loadConfiguration(@Named("file") Config config, @Named("reference") Config referenceConfig, + Set postConfigs) { + Config result = ConfigFactory.systemProperties() + .withFallback(config) + .withFallback(referenceConfig); + + // Performs actions when configuration is loaded. + postConfigs.forEach(pc -> pc.perform(result)); + + return result; + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/config/JavaPropertiesPostConfig.java b/oxalis-commons/src/main/java/network/oxalis/commons/config/JavaPropertiesPostConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..97e46055fc23419b111065e59ae19d39a1fdd595 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/config/JavaPropertiesPostConfig.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.config; + +import com.typesafe.config.Config; +import lombok.extern.slf4j.Slf4j; + +/** + * @author erlend + * @since 4.0.0 + */ +@Slf4j +public class JavaPropertiesPostConfig implements PostConfig { + + @Override + public void perform(Config config) { + if (!config.hasPath("oxalis.java")) + return; + + config.getConfig("oxalis.java").entrySet().stream() + .peek(e -> log.info("Property '{}' => '{}'", e.getKey(), String.valueOf(e.getValue().unwrapped()))) + .forEach(e -> System.setProperty(e.getKey(), String.valueOf(e.getValue().unwrapped()))); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/config/PostConfig.java b/oxalis-commons/src/main/java/network/oxalis/commons/config/PostConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..841361b601ba3498c08f2ffa0f2eb51c182c4597 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/config/PostConfig.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.config; + +import com.typesafe.config.Config; + +/** + * Implementations of this interface part of Guice Multibinder will be triggered just after Oxalis has + * loaded configurations. + * + * @author erlend + * @since 4.0.0 + */ +public interface PostConfig { + + void perform(Config config); + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/error/ErrorConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/error/ErrorConf.java new file mode 100644 index 0000000000000000000000000000000000000000..9e4535595b04c1d0d53856f7cac049cca0c7eef7 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/error/ErrorConf.java @@ -0,0 +1,18 @@ +package network.oxalis.commons.error; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.2 + */ +@Title("Error") +public enum ErrorConf { + + @Path("oxalis.error.handler") + @DefaultValue("quiet") + TRACKER, + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/error/ErrorModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/error/ErrorModule.java new file mode 100644 index 0000000000000000000000000000000000000000..bebdd7c8ed648fd37e1a769c3484e42cf59f9c04 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/error/ErrorModule.java @@ -0,0 +1,31 @@ +package network.oxalis.commons.error; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.2 + */ +public class ErrorModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(ErrorTracker.class, FullErrorTracker.class); + bindTyped(ErrorTracker.class, QuietErrorTracker.class); + bindTyped(ErrorTracker.class, SilentErrorTracker.class); + + bindSettings(ErrorConf.class); + } + + @Provides + @Singleton + protected ErrorTracker getErrorTracker(Injector injector, Settings settings) { + return ImplLoader.get(injector, ErrorTracker.class, settings, ErrorConf.TRACKER); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/error/FullErrorTracker.java b/oxalis-commons/src/main/java/network/oxalis/commons/error/FullErrorTracker.java new file mode 100644 index 0000000000000000000000000000000000000000..181129fb63dccbf21157d6b9a4dc8169b4b80374 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/error/FullErrorTracker.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.error; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.model.Direction; +import network.oxalis.api.util.Type; + +import javax.inject.Singleton; +import java.util.UUID; + +/** + * @author erlend + * @since 4.0.2 + */ +@Slf4j +@Type("full") +@Singleton +public class FullErrorTracker implements ErrorTracker { + + @Override + public String track(Direction direction, Exception e, boolean handled) { + String identifier = UUID.randomUUID().toString(); + + if (handled) + log.warn("[{}] {}", identifier, e.getMessage(), e); + else + log.error("[{}] {}", identifier, e.getMessage(), e); + + return identifier; + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/error/QuietErrorTracker.java b/oxalis-commons/src/main/java/network/oxalis/commons/error/QuietErrorTracker.java new file mode 100644 index 0000000000000000000000000000000000000000..f864a426cf90b7fd6d7628d03a33532622120176 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/error/QuietErrorTracker.java @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.error; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.model.Direction; +import network.oxalis.api.util.Type; + +import javax.inject.Singleton; +import java.util.UUID; + +/** + * Quiet error tracker which logs only exceptions left unhandled by Oxalis. + * + * @author erlend + * @since 4.0.2 + */ +@Slf4j +@Type("quiet") +@Singleton +public class QuietErrorTracker implements ErrorTracker { + + @Override + public String track(Direction direction, Exception e, boolean handled) { + String identifier = UUID.randomUUID().toString(); + + if (handled) + identifier = String.format("untracked:%s", identifier); + else + log.error("[{}] {}", identifier, e.getMessage(), e); + + return identifier; + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/error/SilentErrorTracker.java b/oxalis-commons/src/main/java/network/oxalis/commons/error/SilentErrorTracker.java new file mode 100644 index 0000000000000000000000000000000000000000..305c40f84419a3e60881fa2932e401a63bded111 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/error/SilentErrorTracker.java @@ -0,0 +1,25 @@ +package network.oxalis.commons.error; + +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.model.Direction; +import network.oxalis.api.util.Type; + +import javax.inject.Singleton; +import java.util.UUID; + +/** + * Silent error tracker with no logging and returning untracked identifiers. + * + * @author erlend + * @since 4.0.2 + */ +@Type("silent") +@Singleton +public class SilentErrorTracker implements ErrorTracker { + + @Override + public String track(Direction direction, Exception e, boolean handled) { + // No logging. + return String.format("untracked:%s", UUID.randomUUID().toString()); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/evidence/EvidenceConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/EvidenceConf.java new file mode 100644 index 0000000000000000000000000000000000000000..7cc52c48584539e3dfe84d47cbaa5e25ea8c2240 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/EvidenceConf.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.evidence; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("Evidence") +public enum EvidenceConf { + + @Path("oxalis.evidence.service") + @DefaultValue("rem") + SERVICE +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/evidence/EvidenceModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/EvidenceModule.java new file mode 100644 index 0000000000000000000000000000000000000000..08ce6600b52c1c36b6967bc85952ad96dc430b8a --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/EvidenceModule.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.evidence; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.0 + */ +public class EvidenceModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(EvidenceConf.class); + + bindTyped(EvidenceFactory.class, PrimaryEvidenceFactory.class); + bindTyped(EvidenceFactory.class, RemEvidenceFactory.class); + } + + @Provides + @Singleton + protected EvidenceFactory getEvidenceFactory(Injector injector, Settings settings) { + return ImplLoader.get(injector, EvidenceFactory.class, settings, EvidenceConf.SERVICE); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/evidence/PrimaryEvidenceFactory.java b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/PrimaryEvidenceFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..75317b480ddb28fb329b890d28c75e453e985c7c --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/PrimaryEvidenceFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.evidence; + +import com.google.common.io.ByteStreams; +import com.google.inject.Singleton; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.transmission.TransmissionResult; +import network.oxalis.api.util.Type; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Evidence factory writing only primary receipt to stream. + * + * @author erlend + * @since 4.0.2 + */ +@Singleton +@Type("primary") +public class PrimaryEvidenceFactory implements EvidenceFactory { + + @Override + public void write(OutputStream outputStream, TransmissionResult transmissionResult) throws IOException { + ByteStreams.copy(new ByteArrayInputStream(transmissionResult.primaryReceipt().getValue()), outputStream); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/evidence/RemEvidenceFactory.java b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/RemEvidenceFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..febf28ed04a18574c8320dba967c406485ba4329 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/evidence/RemEvidenceFactory.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.evidence; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.lang.EvidenceException; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.transmission.TransmissionResult; +import network.oxalis.api.util.Type; +import network.oxalis.commons.util.OxalisVersion; +import network.oxalis.vefa.peppol.common.model.InstanceIdentifier; +import network.oxalis.vefa.peppol.evidence.jaxb.receipt.TransmissionRole; +import network.oxalis.vefa.peppol.evidence.lang.RemEvidenceException; +import network.oxalis.vefa.peppol.evidence.rem.EventCode; +import network.oxalis.vefa.peppol.evidence.rem.Evidence; +import network.oxalis.vefa.peppol.evidence.rem.EvidenceTypeInstance; +import network.oxalis.vefa.peppol.evidence.rem.SignedEvidenceWriter; +import network.oxalis.vefa.peppol.security.lang.PeppolSecurityException; + +import java.io.OutputStream; +import java.security.KeyStore; + +/** + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("rem") +public class RemEvidenceFactory implements EvidenceFactory { + + private static final String ISSUER = String.format("Oxalis %s", OxalisVersion.getVersion()); + + private final KeyStore.PrivateKeyEntry privateKeyEntry; + + @Inject + public RemEvidenceFactory(KeyStore.PrivateKeyEntry privateKeyEntry) { + this.privateKeyEntry = privateKeyEntry; + } + + @Override + public void write(OutputStream outputStream, TransmissionResult transmissionResult) throws EvidenceException { + try { + Evidence evidence = Evidence.newInstance() + .type(EvidenceTypeInstance.DELIVERY_NON_DELIVERY_TO_RECIPIENT) + .eventCode(EventCode.DELIVERY) + // Missing optional "EventReason" + .issuer(ISSUER) + .evidenceIdentifier(InstanceIdentifier.generateUUID()) + .timestamp(transmissionResult.getTimestamp()) + .header(transmissionResult.getHeader()) + // Missing optional "IssuerPolicy" + .digest(transmissionResult.getDigest()) + .messageIdentifier(transmissionResult.getTransmissionIdentifier()) + .transportProtocol(transmissionResult.getTransportProtocol()) + .transmissionRole(transmissionResult instanceof TransmissionResponse ? + TransmissionRole.C_2 : TransmissionRole.C_3) + .originalReceipts(transmissionResult.getReceipts()); + + SignedEvidenceWriter.write(outputStream, privateKeyEntry, evidence); + } catch (RemEvidenceException | PeppolSecurityException e) { + throw new EvidenceException(e.getMessage(), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/executor/ExecutorConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/executor/ExecutorConf.java new file mode 100644 index 0000000000000000000000000000000000000000..4fa3b75972b3cf31b800536d084f51e3fbb385f6 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/executor/ExecutorConf.java @@ -0,0 +1,22 @@ +package network.oxalis.commons.executor; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.3 + */ +@Title("Executor") +public enum ExecutorConf { + + @Path("oxalis.executor.default") + @DefaultValue("50") + DEFAULT, + + @Path("oxalis.executor.statistics") + @DefaultValue("50") + STATISTICS + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/executor/ExecutorModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/executor/ExecutorModule.java new file mode 100644 index 0000000000000000000000000000000000000000..66410ae36befa05121e390e6ad990958b3cbc1ba --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/executor/ExecutorModule.java @@ -0,0 +1,36 @@ +package network.oxalis.commons.executor; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.OxalisModule; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author erlend + * @since 4.0.3 + */ +public class ExecutorModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(ExecutorConf.class); + } + + @Provides + @Singleton + @Named("default") + public ExecutorService getExecutorService(Settings settings) { + return Executors.newFixedThreadPool(settings.getInt(ExecutorConf.DEFAULT)); + } + + @Provides + @Singleton + @Named("statistics") + public ExecutorService getStatisticsExecutorService(Settings settings) { + return Executors.newFixedThreadPool(settings.getInt(ExecutorConf.STATISTICS)); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/ClassLoaderUtils.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/ClassLoaderUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..fe7c6ec322161ac4f7a854cf6ff46b697bf16743 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/ClassLoaderUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import network.oxalis.api.lang.OxalisPluginException; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.StreamSupport; + +/** + * Util class used to support use of class loader in Oxalis. + * + * @author erlend + * @since 4.0.0 + */ +public class ClassLoaderUtils { + + /** + * Inititiates a {@link ClassLoader} from {@link Path}. Behaviour changes based upon input: + *

+ *

    + *
  • Path is `null` - Returns current class loader.
  • + *
  • Path is a file - Returns class loader using that file only.
  • + *
  • Path is a directory - Returns class loader using all jar-files in directory.
  • + *
  • Otherwise is exception thrown.
  • + *
+ * + * @param path Path to be used when initiating class loader. + * @return Class loader ready for use. + */ + public static ClassLoader initiate(Path path) { + // `null` -> Return current class loader. + if (path == null) + return Thread.currentThread().getContextClassLoader(); + + // Is directory -> Return class loader with all jars in directory. + else if (Files.isDirectory(path)) + return new URLClassLoader( + findJarFiles(path), + Thread.currentThread().getContextClassLoader() + ); + + // Is file -> Return class loader using file. + else if (Files.isRegularFile(path)) + return new URLClassLoader( + new URL[]{FileUtils.toUrl(path)}, + Thread.currentThread().getContextClassLoader() + ); + + // Otherwise throw exception. + else + throw new OxalisPluginException(String.format("Unable to load class loader for '%s'.", path)); + } + + protected static URL[] findJarFiles(Path directory) { + String glob = "*.{jar}"; + + try (DirectoryStream stream = Files.newDirectoryStream(directory, glob)) { + return StreamSupport.stream(stream.spliterator(), false) + .map(FileUtils::toUrl) + .toArray(URL[]::new); + } catch (IOException e) { + throw new OxalisPluginException( + String.format("Error during list of '%s' files in '%s'.", glob, directory)); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileSystemConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileSystemConf.java new file mode 100644 index 0000000000000000000000000000000000000000..1c9ee928ed0b50c2a162c82915e82885b688907c --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileSystemConf.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Nullable; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("File system") +public enum FileSystemConf { + + @Path("oxalis.path.conf") + @DefaultValue("") + CONF, + + @Path("oxalis.path.inbound") + @DefaultValue("inbound") + INBOUND, + + @Path("oxalis.path.plugin") + @Nullable + PLUGIN, + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileSystemModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileSystemModule.java new file mode 100644 index 0000000000000000000000000000000000000000..d90c59e6faa9199cb48adb1432a8c8b6a60992c9 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileSystemModule.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.OxalisModule; + +import java.nio.file.Path; +import java.util.Map; + +/** + * @author erlend + * @since 4.0.0 + */ +@Slf4j +public class FileSystemModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(FileSystemConf.class); + } + + @Provides + @Singleton + @Named("home") + protected Path getHomeFolder(OxalisHomeDirectory oxalisHomeDirectory) { + Path path = oxalisHomeDirectory.detect().toPath(); + log.info("Home folder: {}", path); + return path; + } + + @Provides + @Singleton + @Named("conf") + protected Path getConfFolder(@Named("reference") Config referenceConfig, @Named("home") Path homeFolder) { + Config config = ConfigFactory.systemProperties() + .withFallback(referenceConfig); + + Path path = homeFolder; + + if (config.hasPath("oxalis.path.conf")) + path = homeFolder.resolve(config.getString("oxalis.path.conf")); + + log.info("Configuration folder: {}", path); + return path; + } + + @Provides + @Singleton + @Named("inbound") + protected Path getInboundFolder(Settings settings, @Named("home") Path homeFolder) { + Path path = settings.getPath(FileSystemConf.INBOUND, homeFolder); + log.info("Inbound folder: {}", path); + return path; + } + + @Provides + @Named("environment") + protected Map getSystemEnvironment() { + return System.getenv(); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileUtils.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..b06ce00113299cb92aa782633ea4f556ddc63f3d --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/FileUtils.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Path; + +/** + * Class holding some utils related to file handling. + * + * @author erlend + * @since 4.0.0 + */ +public class FileUtils { + + /** + * Filter string to make it better fit use as filename. + * + * @param s Unfiltered string. + * @return Filtered string. + */ + public static String filterString(String s) { + return s.replaceAll("[^a-zA-Z0-9.\\-]", "_"); + } + + public static URL toUrl(Path path) { + try { + return path.toUri().toURL(); + } catch (MalformedURLException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/OxalisHomeDirectory.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/OxalisHomeDirectory.java new file mode 100644 index 0000000000000000000000000000000000000000..e02f2b5d1d18e7850f539c172bc9fba489cf6e21 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/OxalisHomeDirectory.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.filesystem.HomeDetector; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.commons.util.Sortables; + +import java.io.File; +import java.util.List; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +/** + * Represents the Oxalis Home directory, which is located by inspecting various + * places in the system in this order: + *

+ *

    + *
  1. Directory referenced by Local JNDI Context java:comp/env/OXALIS_HOME
  2. + *
  3. Directory referenced by Java System Property -D OXALIS_HOME
  4. + *
  5. Directory referenced by Environment Variable OXALIS_HOME
  6. + *
  7. Directory .oxalis inside the home directory of the user
  8. + *
+ * + * @author steinar + * @author thore + */ +@Slf4j +public class OxalisHomeDirectory { + + private List homeDetectors; + + public OxalisHomeDirectory(List homeDetectors) { + this.homeDetectors = homeDetectors; + } + + @SuppressWarnings("unused") + public OxalisHomeDirectory() { + this(StreamSupport.stream(ServiceLoader.load(HomeDetector.class).spliterator(), false) + .sorted(Sortables.comparator()) + .collect(Collectors.toList())); + } + + public File detect() { + File directory = homeDetectors.stream() + .sequential() + .map(HomeDetector::detect) + .filter(Objects::nonNull) + .findFirst() + .orElseThrow(() -> new OxalisLoadingException( + "Unable to detect Oxalis home folder.")); + + try { + validateOxalisHomeDirectory(directory); + } catch (OxalisLoadingException ex) { + log.error(ex.getMessage()); + throw ex; + } + + return directory; + } + + private static void validateOxalisHomeDirectory(File oxalisHomeDirectory) { + if (!oxalisHomeDirectory.exists()) { + throw new OxalisLoadingException(oxalisHomeDirectory + " does not exist!"); + } else if (!oxalisHomeDirectory.isDirectory()) { + throw new OxalisLoadingException(oxalisHomeDirectory + " is not a directory"); + } else if (!oxalisHomeDirectory.canRead()) { + throw new OxalisLoadingException(oxalisHomeDirectory + " exists, is a directory but can not be read"); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/CurrentHomeDetector.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/CurrentHomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..95742287e8f9c76809a47309ac357b2db1703438 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/CurrentHomeDetector.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import network.oxalis.api.filesystem.HomeDetector; +import network.oxalis.api.util.Sort; +import org.kohsuke.MetaInfServices; + +import java.io.File; + +/** + * @author erlend + */ +@Sort(10000) +@MetaInfServices +public class CurrentHomeDetector implements HomeDetector { + + @Override + public File detect() { + return new File("").getAbsoluteFile(); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/EnvironmentHomeDetector.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/EnvironmentHomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..275c01cc242072dc2196376c05a4783cbd2450ff --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/EnvironmentHomeDetector.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.filesystem.HomeDetector; +import network.oxalis.api.util.Sort; +import org.kohsuke.MetaInfServices; + +import java.io.File; +import java.util.Map; + +/** + * @author erlend + */ +@Slf4j +@Sort(3000) +@MetaInfServices +public class EnvironmentHomeDetector implements HomeDetector { + + protected static final String VARIABLE = "OXALIS_HOME"; + + private Map environment; + + public EnvironmentHomeDetector(Map environment) { + this.environment = environment; + } + + @SuppressWarnings("unused") + public EnvironmentHomeDetector() { + this(System.getenv()); + } + + @Override + public File detect() { + if (!environment.containsKey(VARIABLE)) + return null; + + String value = environment.get(VARIABLE); + log.info("Using Oxalis folder specified as environment variable '{}' with value '{}'.", + VARIABLE, value); + return new File(value); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/JndiHomeDetector.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/JndiHomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..45ec3006e2e8c82f68b60d2c095a2731fd6348c9 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/JndiHomeDetector.java @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.filesystem.HomeDetector; +import network.oxalis.api.util.Sort; +import org.kohsuke.MetaInfServices; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import java.io.File; + +/** + * @author erlend + */ +@Slf4j +@Sort(1000) +@MetaInfServices +public class JndiHomeDetector implements HomeDetector { + + protected static final String VARIABLE = "java:comp/env/OXALIS_HOME"; + + @Override + public File detect() { + try { + String value = (String) new InitialContext().lookup(VARIABLE); + if (value == null || value.isEmpty()) + return null; + + log.info("Using Oxalis folder specified as JNDI path '{}' with value '{}'.", + VARIABLE, value); + return new File(value); + } catch (NamingException ex) { + return null; + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/PropertyHomeDetector.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/PropertyHomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..aa17d7db8440622893b2b0c8ff27e47b199442d7 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/PropertyHomeDetector.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.filesystem.HomeDetector; +import network.oxalis.api.util.Sort; +import org.kohsuke.MetaInfServices; + +import java.io.File; + +/** + * @author erlend + */ +@Slf4j +@Sort(2000) +@MetaInfServices +public class PropertyHomeDetector implements HomeDetector { + + protected static final String VARIABLE = "OXALIS_HOME"; + + @Override + public File detect() { + String value = System.getProperty(VARIABLE); + if (value == null || value.isEmpty()) + return null; + + log.info("Using Oxalis folder specified as Java System Property '-D {}' with value '{}'.", + VARIABLE, value); + return new File(value); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/UserHomeDetector.java b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/UserHomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..d4628787c6558bb9dc635b1f5adad29b8c72d72f --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/filesystem/detector/UserHomeDetector.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.filesystem.HomeDetector; +import network.oxalis.api.util.Sort; +import org.kohsuke.MetaInfServices; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @author erlend + */ +@Slf4j +@Sort(4000) +@MetaInfServices +public class UserHomeDetector implements HomeDetector { + + @Override + public File detect() { + Path path = Paths.get(System.getProperty("user.home"), ".oxalis"); + if (Files.notExists(path)) + return null; + + log.info("Using Oxalis folder relative to home folder: {}", path); + return path.toFile(); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/guice/GuiceModuleLoader.java b/oxalis-commons/src/main/java/network/oxalis/commons/guice/GuiceModuleLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..3eb4503f10bd3c8e95ee2f6cafcd6ddff6157419 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/guice/GuiceModuleLoader.java @@ -0,0 +1,143 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.guice; + +import com.google.inject.*; +import com.google.inject.spi.Message; +import com.google.inject.util.Modules; +import com.typesafe.config.Config; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.commons.config.ConfigModule; +import network.oxalis.commons.filesystem.FileSystemModule; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * Implementation for loading of Guice modules on same principles discussed on + * StackOverflow, however this implementation uses + * Typesafe Config instead of Java ServiceLoader to allow for + * further configuration than only "detected". + * + * @author erlend + */ +@Slf4j +public class GuiceModuleLoader extends AbstractModule { + + private static final String PREFIX = "oxalis.module"; + + private static final String CLS = "class"; + + private static final String ENABLED = "enabled"; + + private static final String OVERRIDE = "override"; + + private static final String DEPENDENCY = "dependency"; + + public static Injector initiate(Module... modules) { + List moduleList = new ArrayList<>(); + moduleList.addAll(getModules()); + moduleList.addAll(Arrays.asList(modules)); + + try { + return Guice.createInjector(moduleList); + } catch (CreationException e) { + if (e.getErrorMessages().stream() + .map(Message::getCause) + .allMatch(OxalisLoadingException.class::isInstance)) { + e.getErrorMessages().stream() + .map(Message::getCause) + .filter(distinctByKey(Throwable::getMessage)) + .forEach(c -> log.error(c.getMessage(), c)); + + throw new OxalisLoadingException("Unable to load Oxalis due to errors during loading."); + } + + throw e; + } + } + + @Override + protected void configure() { + getModules().forEach(binder()::install); + } + + protected static List getModules() { + // Initial loading of configuration. + Injector initialInjector = Guice.createInjector(new FileSystemModule(), new ConfigModule()); + Config config = initialInjector.getInstance(Config.class); + + // List to gather configurations for modules. + Map moduleConfigs = new HashMap<>(); + + // Go through the two levels of identifiers for module configurations. + for (String group : config.getObject(PREFIX).keySet()) { + for (String module : config.getObject(String.format("%s.%s", PREFIX, group)).keySet()) { + + // Fetch configuration for the combination of group and module identifiers. + Config moduleConfig = config.getConfig(String.format("%s.%s.%s", PREFIX, group, module)); + + // Do not include disabled modules. + if (!moduleConfig.hasPath(ENABLED) || moduleConfig.getBoolean(ENABLED)) + moduleConfigs.put(String.format("%s.%s", group, module), moduleConfig); + } + } + + return moduleConfigs.values().stream() + // Verify depending module is enabled. + .filter(mc -> !mc.hasPath(DEPENDENCY) || moduleConfigs.containsKey(mc.getString(DEPENDENCY))) + // Create Module instances from configuration. + .map(GuiceModuleLoader::load) + // Collect into list. + .collect(Collectors.toList()); + } + + protected static Module load(Config config) { + // Loading with override. + if (config.hasPath(OVERRIDE)) { + log.debug("Loading module '{}' with override.", config.getString(CLS)); + return Modules.override(loadModule(config.getString(CLS))) + .with(loadModule(config.getString(OVERRIDE))); + } + + // Loading without override. + log.debug("Loading module '{}'.", config.getString(CLS)); + return loadModule(config.getString(CLS)); + } + + protected static Module loadModule(String className) { + try { + return (Module) Class.forName(className).newInstance(); + } catch (Exception e) { + throw new OxalisLoadingException(e.getMessage(), e); + } + } + + protected static Predicate distinctByKey(Function function) { + Set set = new HashSet<>(); + return t -> set.add(function.apply(t)); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/guice/GuiceServiceLoader.java b/oxalis-commons/src/main/java/network/oxalis/commons/guice/GuiceServiceLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..032f5d06b5a255ea19abcfc4e3e2fc183d44d28c --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/guice/GuiceServiceLoader.java @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.guice; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import network.oxalis.api.lang.OxalisPluginException; +import network.oxalis.commons.util.ClassUtils; + +import java.io.*; +import java.net.URL; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * This class works by the same principles as {@link java.util.ServiceLoader}, however this implementation loads each + * detected class using the Guice injector. + * + * @author erlend + */ +public class GuiceServiceLoader { + + private static final String PREFIX = "META-INF/services/"; + + private final Injector injector; + + @Inject + public GuiceServiceLoader(Injector injector) { + this.injector = injector; + } + + public List load(Class cls, ClassLoader classLoader) { + try { + // Find all instances of files in class loader. + return Collections.list(classLoader.getResources(PREFIX + cls.getName())).stream() + // Fetch all lines in all detected files. + .map(this::getLines) + // Convert stream of lists to stream. + .flatMap(Collection::stream) + // Load classes referenced in detected files. + .map(s -> (Class) ClassUtils.load(s, classLoader)) + // Load each class using Guice magic. + .map(injector::getInstance) + // Collect all instances to a list. + .collect(Collectors.toList()); + } catch (IOException e) { + throw new OxalisPluginException("Unable to load resources.", e); + } + } + + /** + * Extracts all lines in the provided target. + */ + private List getLines(URL url) { + try (InputStream inputStream = url.openStream(); + Reader reader = new InputStreamReader(inputStream); + BufferedReader bufferedReader = new BufferedReader(reader)) { + + // Read all lines. + return bufferedReader.lines() + // Trim all lines. + .map(String::trim) + // Collect all lines. + .collect(Collectors.toList()); + } catch (IOException e) { + throw new OxalisPluginException("Unable to read.", e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/guice/ImplLoader.java b/oxalis-commons/src/main/java/network/oxalis/commons/guice/ImplLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..367c4970cffec98942594eb78bedcfdbd3d4176f --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/guice/ImplLoader.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.guice; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Settings; + +import java.lang.reflect.Field; +import java.util.stream.Collectors; + +/** + * Helper class to allow for better information when invalid configuration is provided. + * + * @author erlend + * @since 4.0.1 + */ +public class ImplLoader { + + public static T get(Injector injector, Class cls, Settings settings, C conf) { + Key key = Key.get(cls, settings.getNamed(conf)); + + if (injector.getAllBindings().keySet().contains(key)) + return injector.getInstance(key); + + String available = injector.getAllBindings().keySet().stream() + .filter(k -> k.getTypeLiteral().getRawType().equals(cls)) + .filter(k -> k.getAnnotation() != null) + .map(Key::getAnnotation) + .map(Named.class::cast) + .map(Named::value) + .collect(Collectors.joining(", ")); + + try { + Field field = conf.getClass().getField(((Enum) conf).name()); + + throw new OxalisLoadingException(String.format( + "Implementation named '%s' for '%s' (%s) is not found. Available implementations: %s", + settings.getString(conf), + field.getAnnotation(Path.class).value(), + cls.getName(), + available + )); + } catch (NoSuchFieldException e) { + throw new OxalisLoadingException(e.getMessage(), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/guice/OxalisModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/guice/OxalisModule.java new file mode 100644 index 0000000000000000000000000000000000000000..a0966997e1ede13b0296c26dfa8963ab5ec17e14 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/guice/OxalisModule.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.guice; + +import com.google.inject.AbstractModule; +import com.google.inject.Key; +import com.google.inject.name.Names; +import network.oxalis.api.util.Type; +import network.oxalis.commons.settings.SettingsBuilder; + +/** + * Specialized Guice module class with some extra methods heavily used by Oxalis. + * + * @author erlend + * @since 4.0.1 + */ +public abstract class OxalisModule extends AbstractModule { + + /** + * Binds an implementation to an interface using the {@link Type} annotation as replacement + * for {@link javax.inject.Named}. + * + * @param cls Interface used for binding. + * @param impl Implementation with {@link Type} annotation. + */ + protected void bindTyped(Class cls, Class impl) { + bindTyped(cls, impl, impl.getAnnotation(Type.class).value()); + } + + /** + * Binds an implementation to an interface with names. + * + * @param cls Interface used for binding. + * @param impl Implementation of interface.. + * @param names Names used to identify + */ + protected void bindTyped(Class cls, Class impl, String... names) { + for (String type : names) + binder().skipSources(OxalisModule.class) + .bind(Key.get(cls, Names.named(type))) + .to(impl); + } + + /** + * Binds a configuration enum for use. + * + * @param cls Enum expressing configurations. + */ + protected void bindSettings(Class cls) { + SettingsBuilder.with(binder(), cls); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/header/HeaderConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/header/HeaderConf.java new file mode 100644 index 0000000000000000000000000000000000000000..e4906a1d19adfb5340ad33c215fc82d0a28168c1 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/header/HeaderConf.java @@ -0,0 +1,17 @@ +package network.oxalis.commons.header; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.2 + */ +@Title("Header") +public enum HeaderConf { + + @Path("oxalis.header.parser") + @DefaultValue("sbdh") + PARSER +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/header/HeaderModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/header/HeaderModule.java new file mode 100644 index 0000000000000000000000000000000000000000..0331e9722374684021733264624b73210f1eaf5e --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/header/HeaderModule.java @@ -0,0 +1,29 @@ +package network.oxalis.commons.header; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.header.HeaderParser; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.2 + */ +public class HeaderModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(HeaderParser.class, SbdhHeaderParser.class); + + bindSettings(HeaderConf.class); + } + + @Provides + @Singleton + protected HeaderParser getHeaderParser(Injector injector, Settings settings) { + return ImplLoader.get(injector, HeaderParser.class, settings, HeaderConf.PARSER); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/header/SbdhHeaderParser.java b/oxalis-commons/src/main/java/network/oxalis/commons/header/SbdhHeaderParser.java new file mode 100644 index 0000000000000000000000000000000000000000..2ac689fda025cfb05db7f4d440181ab6690f9b45 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/header/SbdhHeaderParser.java @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.header; + +import com.google.inject.Singleton; +import network.oxalis.api.header.HeaderParser; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.sbdh.SbdReader; +import network.oxalis.vefa.peppol.sbdh.lang.SbdhException; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.2 + */ +@Type("sbdh") +@Singleton +public class SbdhHeaderParser implements HeaderParser { + + /** + * Simple wrapper around peppol-sbdh module. + * + * @param inputStream the inputstream containing the XML + * @return an instance of Header if found, otherwise null. + */ + @Override + public Header parse(InputStream inputStream) throws OxalisContentException { + try (SbdReader sbdReader = SbdReader.newInstance(inputStream)) { + return sbdReader.getHeader(); + } catch (SbdhException | IOException e) { + throw new OxalisContentException(e.getMessage(), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/http/ApacheHttpModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/http/ApacheHttpModule.java new file mode 100644 index 0000000000000000000000000000000000000000..8fe6911302a88f1c7bdf8d73e89347ac0ee74759 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/http/ApacheHttpModule.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.http; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import io.opentracing.Tracer; +import io.opentracing.contrib.apache.http.client.TracingHttpClientBuilder; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.commons.util.OxalisVersion; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; + +import java.util.concurrent.TimeUnit; + +/** + * @author erlend + * @since 4.0.0 + */ +public class ApacheHttpModule extends OxalisModule { + + private static final String USER_AGENT = String.format("Oxalis %s", OxalisVersion.getVersion()); + + @Override + protected void configure() { + bindSettings(HttpConf.class); + } + + @Provides + @Singleton + protected PoolingHttpClientConnectionManager getPoolingHttpClientConnectionManager(Settings settings) { + PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(settings.getInt(HttpConf.POOL_TIME_TO_LIVE), TimeUnit.SECONDS); + httpClientConnectionManager.setDefaultMaxPerRoute(settings.getInt(HttpConf.POOL_MAX_ROUTE)); + httpClientConnectionManager.setMaxTotal(settings.getInt(HttpConf.POOL_TOTAL)); + httpClientConnectionManager.setValidateAfterInactivity(settings.getInt(HttpConf.POOL_VALIDATE_AFTER_INACTIVITY)); + + return httpClientConnectionManager; + } + + @Provides + @Singleton + protected RequestConfig getRequestConfig(Settings settings) { + return RequestConfig.custom() + .setConnectTimeout(settings.getInt(HttpConf.TIMEOUT_CONNECT)) + .setConnectionRequestTimeout(settings.getInt(HttpConf.TIMEOUT_READ)) + .setSocketTimeout(settings.getInt(HttpConf.TIMEOUT_SOCKET)) + .build(); + } + + @Provides + protected CloseableHttpClient getHttpClient(PoolingHttpClientConnectionManager connectionManager, + RequestConfig requestConfig, Tracer tracer) { + HttpClientBuilder httpClientBuilder = new TracingHttpClientBuilder().withTracer(tracer); + + httpClientBuilder.setUserAgent(USER_AGENT); + + // Request configuration + httpClientBuilder.setDefaultRequestConfig(requestConfig); + + // Connection pool + httpClientBuilder.setConnectionManager(connectionManager); + httpClientBuilder.setConnectionManagerShared(true); + + // Use system default for proxy + httpClientBuilder.useSystemProperties(); + + return httpClientBuilder.build(); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/http/HttpConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/http/HttpConf.java new file mode 100644 index 0000000000000000000000000000000000000000..af829f00755232e6c4855456e0b033f2594d4b0d --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/http/HttpConf.java @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.http; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.0 + */ +@Title("HTTP") +public enum HttpConf { + + @Path("oxalis.http.pool.total") + @DefaultValue("20") + POOL_TOTAL, + + @Path("oxalis.http.pool.max_route") + @DefaultValue("2") + POOL_MAX_ROUTE, + + @Path("oxalis.http.pool.validate_after_inactivity") + @DefaultValue("1000") + POOL_VALIDATE_AFTER_INACTIVITY, + + @Path("oxalis.http.pool.time_to_live") + @DefaultValue("30") + POOL_TIME_TO_LIVE, + + @Path("oxalis.http.timeout.connect") + @DefaultValue("0") + TIMEOUT_CONNECT, + + @Path("oxalis.http.timeout.read") + @DefaultValue("0") + TIMEOUT_READ, + + @Path("oxalis.http.timeout.socket") + @DefaultValue("0") + TIMEOUT_SOCKET, +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/identifier/DefaultMessageIdGenerator.java b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/DefaultMessageIdGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..a2f9eec812cae31b33e514ec18f9dee6aa31cc85 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/DefaultMessageIdGenerator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.identifier; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import network.oxalis.api.identifier.MessageIdGenerator; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.util.Type; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * @author erlend + * @since 4.0.4 + */ +@Singleton +@Type("default") +public class DefaultMessageIdGenerator implements MessageIdGenerator { + + private String hostname; + + private AtomicLong atomicLong = new AtomicLong(); + + @Inject + public DefaultMessageIdGenerator(@Named("hostname") String hostname) { + this.hostname = hostname; + } + + @Override + public String generate(TransmissionRequest transmissionRequest) { + return String.format("<%s.%s.%s.Oxalis@%s>", System.currentTimeMillis(), + atomicLong.incrementAndGet(), transmissionRequest.hashCode(), hostname); + } + + @Override + public String generate(InboundMetadata inboundMetadata) { + return String.format("<%s.%s.%s.Oxalis@%s>", System.currentTimeMillis(), + atomicLong.incrementAndGet(), inboundMetadata.hashCode(), hostname); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/identifier/HostnameProvider.java b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/HostnameProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..444a7f612ee041dbe96ed36b99c6eeacc6bcc924 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/HostnameProvider.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.identifier; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import network.oxalis.api.settings.Settings; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * @author erlend + * @since 4.0.4 + */ +public class HostnameProvider implements Provider { + + @Inject + private Settings settings; + + @Override + public String get() { + try { + String hostname = settings.getString(IdentifierConf.HOSTNAME); + if (hostname.trim().isEmpty()) + hostname = InetAddress.getLocalHost().getHostName(); + + return hostname; + } catch (UnknownHostException e) { + throw new IllegalStateException("Unable to get local hostname.", e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/identifier/IdentifierConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/IdentifierConf.java new file mode 100644 index 0000000000000000000000000000000000000000..0b14c1bee62799f6a655ed94c775f2e9de0c651e --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/IdentifierConf.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.identifier; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.4 + */ +@Title("Identifiers") +public enum IdentifierConf { + + @Path("oxalis.identifier.hostname") + @DefaultValue("") + HOSTNAME, + + @Path("oxalis.identifier.msgidgen") + @DefaultValue("default") + MSGID_GENERATOR, + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/identifier/IdentifierModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/IdentifierModule.java new file mode 100644 index 0000000000000000000000000000000000000000..7ce19692bc9f78914227945745a2ebbcbfb4ac91 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/identifier/IdentifierModule.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.identifier; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Names; +import network.oxalis.api.identifier.MessageIdGenerator; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.4 + */ +public class IdentifierModule extends OxalisModule { + + @Override + protected void configure() { + bind(Key.get(String.class, Names.named("hostname"))) + .toProvider(HostnameProvider.class) + .in(Singleton.class); + + bindTyped(MessageIdGenerator.class, DefaultMessageIdGenerator.class); + + bindSettings(IdentifierConf.class); + } + + @Provides + @Singleton + public MessageIdGenerator getMessageIdGenerator(Injector injector, Settings settings) { + return ImplLoader.get(injector, MessageIdGenerator.class, settings, IdentifierConf.MSGID_GENERATOR); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/io/PeekingInputStream.java b/oxalis-commons/src/main/java/network/oxalis/commons/io/PeekingInputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..a787a9ceeba5c9c87b12f9fe001fef817cb59bda --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/io/PeekingInputStream.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.io; + +import com.google.common.io.ByteStreams; + +import java.io.*; + +/** + * Caching InputStream to be used when reading the beginning of a stream is needed before the stream is "reset" when + * the exact amount of data is unknown and support for marking of is irrelevant. + * + * @author erlend + * @since 4.0.0 + */ +public class PeekingInputStream extends InputStream { + + private final byte[] content; + + private final InputStream internlaInputStream; + + public PeekingInputStream(InputStream sourceInputStream) throws IOException { + this.content = ByteStreams.toByteArray(sourceInputStream); + this.internlaInputStream = new ByteArrayInputStream(content); + + } + + @Override + public int read() throws IOException { + // Return byte + return this.internlaInputStream.read(); + } + + public byte[] getContent() { + return content; + } + + public InputStream newInputStream() throws IOException { + return new ByteArrayInputStream(content); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/io/UnclosableInputStream.java b/oxalis-commons/src/main/java/network/oxalis/commons/io/UnclosableInputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..58966545e8775262dd93bf2343893332317eab0a --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/io/UnclosableInputStream.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.io; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Simple wrapper of an InputStream making sure the close method on the encapsulated InputStream is never called. + * + * @author erlend + * @since 4.0.0 + */ +public class UnclosableInputStream extends InputStream { + + private final InputStream inputStream; + + public UnclosableInputStream(InputStream inputStream) { + this.inputStream = inputStream; + } + + @Override + public int read() throws IOException { + return inputStream.read(); + } + + @Override + public void close() throws IOException { + // No action. + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/logging/LogbackConfigurator.java b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LogbackConfigurator.java new file mode 100644 index 0000000000000000000000000000000000000000..71a18f2f5716a6c1273785d29f85554ee276a957 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LogbackConfigurator.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.logging; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.logging.Configurator; +import network.oxalis.api.settings.Settings; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.nio.file.Path; + +/** + * Configures the Logback logging configuration. Is triggered only in the case of explicit override. + * + * @author steinar + * Date: 04.10.12 + * Time: 13:43 + * @author erlend + */ +@Slf4j +@SuppressWarnings("unused") +public class LogbackConfigurator implements Configurator { + + private final Settings settings; + + private final Path confPath; + + /** + * Simply uses the default configuration + */ + @Inject + public LogbackConfigurator(Settings settings, @Named("conf") Path confPath) { + this.settings = settings; + this.confPath = confPath; + } + + public void execute() { + File file = settings.getPath(LoggingConf.CONFIG, confPath).toFile(); + + System.out.println("Configuring Logback with configuration: " + file.getAbsolutePath()); + LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); + + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(loggerContext); + // Call context.reset() to clear any previous configuration, e.g. default + // configuration. For multi-step configuration, omit calling context.reset(). + loggerContext.reset(); + try { + configurator.doConfigure(file); + + // Not needed as this is the default behaviour from logback + // StatusPrinter.print(loggerContext); + } catch (JoranException e) { + log.error(e.getMessage(), e); + } + + StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingConf.java new file mode 100644 index 0000000000000000000000000000000000000000..e424b868fa54a9e64738cee6758f2e7bbb97b288 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingConf.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.logging; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Nullable; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("Logging") +public enum LoggingConf { + + @Path("oxalis.logging.config") + @Nullable + CONFIG, + + @Path("oxalis.logging.service") + @DefaultValue("logback") + SERVICE + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingHandler.java b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..b1e69a253c47cb1a8104d05556ea66c3d6d8d58a --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingHandler.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.logging; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.logging.Configurator; +import network.oxalis.api.settings.Settings; + +/** + * This class triggers {@link Configurator} only in the case of {@link LoggingConf#CONFIG} being set. This makes is + * possible to both configure logging very early in startup and remove coupling towards Logback. + * + * @author erlend + */ +@Slf4j +class LoggingHandler { + + @Inject + @SuppressWarnings("unchecked") + public void load(Injector injector, Settings settings) { + log.debug("Logger config: {}", settings.getString(LoggingConf.CONFIG)); + + if (settings.getString(LoggingConf.CONFIG) == null) + return; + + log.info("Logging service: {}", settings.getString(LoggingConf.SERVICE)); + + injector.getInstance(Key.get(Configurator.class, settings.getNamed(LoggingConf.SERVICE))).execute(); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingModule.java new file mode 100644 index 0000000000000000000000000000000000000000..1e1afa5ed13d949e23963f2d83631e787164e2cf --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/logging/LoggingModule.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.logging; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.name.Named; +import network.oxalis.api.logging.Configurator; +import network.oxalis.commons.util.ClassUtils; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + */ +public class LoggingModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(LoggingConf.class); + + binder().requestInjection(new LoggingHandler()); + } + + @Provides + @Named("logback") + @SuppressWarnings("unchecked") + protected Configurator provideLogbackConfigurator(Injector injector) { + // Loads class using string to make sure the class is not automatically loaded. + return injector.getInstance((Class) + ClassUtils.load("network.oxalis.commons.logging.LogbackConfigurator")); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/mode/ModeModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/mode/ModeModule.java new file mode 100644 index 0000000000000000000000000000000000000000..c3ac507213a2220433ee4a007b984e431bd04f6d --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/mode/ModeModule.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.mode; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.pkix.ocsp.api.OcspFetcher; +import network.oxalis.commons.certvalidator.api.CrlCache; +import network.oxalis.commons.certvalidator.api.CrlFetcher; +import network.oxalis.commons.certvalidator.util.SimpleCrlCache; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.vefa.peppol.common.lang.PeppolLoadingException; +import network.oxalis.vefa.peppol.mode.Mode; +import network.oxalis.vefa.peppol.security.api.CertificateValidator; +import org.apache.http.client.config.RequestConfig; + +import javax.inject.Named; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +/** + * @author erlend + * @since 4.0.0 + * + * @author aaron-kumar + * @since 5.0.0 + * + */ +@Slf4j +public class ModeModule extends OxalisModule { + + @Override + protected void configure() { + bind(OcspFetcher.class).to(OxalisOcspFetcher.class); + bind(CrlCache.class).toInstance(new SimpleCrlCache()); + bind(CrlFetcher.class).to(OxalisCrlFetcher.class); + + bind(Mode.class) + .toProvider(ModeProvider.class) + .asEagerSingleton(); + } + + @Provides + @Singleton + protected CertificateValidator getCertificateValidator(Mode mode) throws PeppolLoadingException { + return mode.initiate("security.validator.class", CertificateValidator.class); + } + + @Provides + @Singleton + @Named("certificate") + protected RequestConfig getRequestConfig() { + return RequestConfig.custom() + .setConnectTimeout(10 * 1000) + .setConnectionRequestTimeout(10 * 1000) + .setSocketTimeout(10 * 1000) + .build(); + } + + /** + * @since 4.0.3 + */ + @Provides + @Singleton + @Named("truststore-ap") + protected KeyStore getTruststoreAp(Mode mode) { + try (InputStream inputStream = getClass().getResourceAsStream(mode.getString("security.truststore.ap"))) { + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(inputStream, mode.getString("security.truststore.password").toCharArray()); + return keyStore; + } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException e) { + throw new OxalisLoadingException("Unable to load truststore for AP.", e); + } + } + + /** + * @since 4.0.3 + */ + @Provides + @Singleton + @Named("truststore-smp") + protected KeyStore getTruststoreSmp(Mode mode) { + try (InputStream inputStream = getClass().getResourceAsStream(mode.getString("security.truststore.smp"))) { + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(inputStream, mode.getString("security.truststore.password").toCharArray()); + return keyStore; + } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException e) { + throw new OxalisLoadingException("Unable to load truststore for SMP.", e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/mode/ModeProvider.java b/oxalis-commons/src/main/java/network/oxalis/commons/mode/ModeProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..d45041b5ed0dca2fc64358f45bfeca68886a9e86 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/mode/ModeProvider.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.mode; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.typesafe.config.Config; +import io.opentracing.Span; +import io.opentracing.Tracer; +import io.opentracing.contrib.spanmanager.DefaultSpanManager; +import network.oxalis.pkix.ocsp.api.OcspFetcher; +import network.oxalis.commons.certvalidator.api.CrlFetcher; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.vefa.peppol.common.lang.PeppolLoadingException; +import network.oxalis.vefa.peppol.mode.Mode; +import network.oxalis.vefa.peppol.security.ModeDetector; + +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; + +/** + * @author erlend + * @since 4.0.4 + * + * @author aaron-kumar + * @since 5.0.0 + */ +public class ModeProvider implements Provider { + + @Inject + private X509Certificate certificate; + + @Inject + private Config config; + + @Inject + private OcspFetcher ocspFetcher; + + @Inject + private CrlFetcher crlFetcher; + + @Inject + private Tracer tracer; + + @Override + public Mode get() { + Span span = tracer.buildSpan("Mode detection").start(); + DefaultSpanManager.getInstance().activate(span); + try { + Map objectStorage = new HashMap<>(); + objectStorage.put("ocsp_fetcher", ocspFetcher); + objectStorage.put("crlFetcher", crlFetcher); + + return ModeDetector.detect(certificate, config, objectStorage); + } catch (PeppolLoadingException e) { + throw new OxalisLoadingException("Unable to detect mode.", e); + } finally { + span.finish(); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisCertificateValidator.java b/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisCertificateValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..fc4cd6e15944ab2870d053d1e199a78d292ae68a --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisCertificateValidator.java @@ -0,0 +1,53 @@ +package network.oxalis.commons.mode; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import io.opentracing.Span; +import io.opentracing.Tracer; +import io.opentracing.contrib.spanmanager.DefaultSpanManager; +import network.oxalis.vefa.peppol.common.code.Service; +import network.oxalis.vefa.peppol.security.api.CertificateValidator; +import network.oxalis.vefa.peppol.security.lang.PeppolSecurityException; + +import java.security.cert.X509Certificate; + +/** + * @author erlend + */ +@Singleton +public class OxalisCertificateValidator implements CertificateValidator { + + private CertificateValidator certificateValidator; + + private Tracer tracer; + + @Inject + public OxalisCertificateValidator(CertificateValidator certificateValidator, Tracer tracer) { + this.certificateValidator = certificateValidator; + this.tracer = tracer; + } + + @Override + public void validate(Service service, X509Certificate certificate) throws PeppolSecurityException { + Span span = tracer.buildSpan("Validate certificate").start(); + perform(service, certificate, span); + } + + public void validate(Service service, X509Certificate certificate, Span root) throws PeppolSecurityException { + Span span = tracer.buildSpan("Validate certificate").asChildOf(root).start(); + perform(service, certificate, span); + } + + private void perform(Service service, X509Certificate certificate, Span span) throws PeppolSecurityException { + DefaultSpanManager.getInstance().activate(span); + + try { + span.setTag("subject", certificate.getSubjectX500Principal().toString()); + span.setTag("issuer", certificate.getIssuerX500Principal().toString()); + + this.certificateValidator.validate(service, certificate); + } finally { + span.finish(); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisCrlFetcher.java b/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisCrlFetcher.java new file mode 100644 index 0000000000000000000000000000000000000000..2ec416690989c6fa80edd579f14e298461ea92e7 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisCrlFetcher.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.mode; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import io.opentracing.contrib.apache.http.client.Constants; +import io.opentracing.contrib.spanmanager.DefaultSpanManager; +import io.opentracing.contrib.spanmanager.SpanManager; +import network.oxalis.commons.certvalidator.api.CertificateValidationException; +import network.oxalis.commons.certvalidator.api.CrlCache; +import network.oxalis.commons.certvalidator.util.CrlUtils; +import network.oxalis.commons.certvalidator.util.SimpleCachingCrlFetcher; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.protocol.BasicHttpContext; + +import javax.inject.Named; +import java.io.IOException; +import java.net.URI; +import java.security.cert.CRLException; +import java.security.cert.X509CRL; + +/** + * @author erlend + * @since 4.0.0 + * + * @author aaron-kumar + * @since 5.0.0 + * + */ +@Singleton +public class OxalisCrlFetcher extends SimpleCachingCrlFetcher { + + @Inject + private Provider httpClientProvider; + + @Inject + @Named("certificate") + private RequestConfig requestConfig; + + @Inject + public OxalisCrlFetcher(CrlCache crlCache) { + super(crlCache); + } + + @Override + protected X509CRL httpDownload(String url) throws CertificateValidationException { + try { + SpanManager.ManagedSpan span = DefaultSpanManager.getInstance().current(); + + BasicHttpContext basicHttpContext = new BasicHttpContext(); + if (span.getSpan() != null) + basicHttpContext.setAttribute(Constants.PARENT_CONTEXT, span.getSpan().context()); + + HttpGet httpGet = new HttpGet(URI.create(url)); + httpGet.setConfig(requestConfig); + + try (CloseableHttpResponse response = httpClientProvider.get().execute(httpGet, basicHttpContext)) { + X509CRL crl = CrlUtils.load(response.getEntity().getContent()); + crlCache.set(url, crl); + return crl; + } + } catch (IOException | CRLException e) { + throw new CertificateValidationException( + String.format("Failed to download CRL '%s' (%s)", url, e.getMessage()), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisOcspFetcher.java b/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisOcspFetcher.java new file mode 100644 index 0000000000000000000000000000000000000000..43ccec45fd081744f01d104d985e920a9178dc3c --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/mode/OxalisOcspFetcher.java @@ -0,0 +1,108 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.mode; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import io.opentracing.contrib.apache.http.client.Constants; +import io.opentracing.contrib.spanmanager.DefaultSpanManager; +import io.opentracing.contrib.spanmanager.SpanManager; +import network.oxalis.pkix.ocsp.api.OcspFetcher; +import network.oxalis.pkix.ocsp.api.OcspFetcherResponse; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.protocol.BasicHttpContext; + +import javax.inject.Named; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +/** + * @author erlend + * @since 4.0.0 + * + * @author aaron-kumar + * @since 5.0.0 + */ +@Singleton +public class OxalisOcspFetcher implements OcspFetcher { + + @Inject + private Provider httpClientProvider; + + @Inject + @Named("certificate") + private RequestConfig requestConfig; + + @Override + public OcspFetcherResponse fetch(URI uri, byte[] content) throws IOException { + SpanManager.ManagedSpan span = DefaultSpanManager.getInstance().current(); + + BasicHttpContext basicHttpContext = new BasicHttpContext(); + if (span.getSpan() != null) + basicHttpContext.setAttribute(Constants.PARENT_CONTEXT, span.getSpan().context()); + + HttpPost httpPost = new HttpPost(uri); + httpPost.setHeader("Content-Type", "application/ocsp-request"); + httpPost.setHeader("Accept", "application/ocsp-response"); + httpPost.setEntity(new ByteArrayEntity(content)); + httpPost.setConfig(requestConfig); + + return new ApacheOcspFetcherResponse(httpClientProvider.get().execute(httpPost, basicHttpContext)); + } + + private class ApacheOcspFetcherResponse implements OcspFetcherResponse { + + private CloseableHttpResponse response; + + public ApacheOcspFetcherResponse(CloseableHttpResponse response) { + this.response = response; + } + + @Override + public int getStatus() { + return response.getStatusLine().getStatusCode(); + } + + @Override + public String getContentType() { + return response.getFirstHeader("Content-Type").getValue(); + } + + @Override + public InputStream getContent() throws IOException { + return response.getEntity().getContent(); + } + + @Override + public void close() throws IOException { + response.close(); + response = null; + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/persist/DefaultPersister.java b/oxalis-commons/src/main/java/network/oxalis/commons/persist/DefaultPersister.java new file mode 100644 index 0000000000000000000000000000000000000000..8bd75d7d70c6cb09404dc27691223095dee0dd23 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/persist/DefaultPersister.java @@ -0,0 +1,109 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persist; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.lang.EvidenceException; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.util.Type; +import network.oxalis.commons.filesystem.FileUtils; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Singleton; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.0 + */ +@Slf4j +@Singleton +@Type("default") +public class DefaultPersister implements PersisterHandler { + + private final EvidenceFactory evidenceFactory; + + private final Path inboundFolder; + + @Inject + public DefaultPersister(@Named("inbound") Path inboundFolder, EvidenceFactory evidenceFactory) { + this.inboundFolder = inboundFolder; + this.evidenceFactory = evidenceFactory; + } + + @Override + public Path persist(TransmissionIdentifier transmissionIdentifier, Header header, InputStream inputStream) + throws IOException { + Path path = PersisterUtils.createArtifactFolders(inboundFolder, header).resolve( + String.format("%s.doc.xml", FileUtils.filterString(transmissionIdentifier.getIdentifier()))); + + try (OutputStream outputStream = Files.newOutputStream(path)) { + ByteStreams.copy(inputStream, outputStream); + } + + log.debug("Payload persisted to: {}", path); + + return path; + } + + @Override + public void persist(InboundMetadata inboundMetadata, Path payloadPath) throws IOException { + Path path = PersisterUtils.createArtifactFolders(inboundFolder, inboundMetadata.getHeader()).resolve( + String.format("%s.receipt.dat", + FileUtils.filterString(inboundMetadata.getTransmissionIdentifier().getIdentifier()))); + + try (OutputStream outputStream = Files.newOutputStream(path)) { + evidenceFactory.write(outputStream, inboundMetadata); + } catch (EvidenceException e) { + throw new IOException("Unable to persist receipt.", e); + } + + log.debug("Receipt persisted to: {}", path); + } + + /** + * @since 4.0.3 + */ + @Override + public void persist(TransmissionIdentifier transmissionIdentifier, Header header, + Path payloadPath, Exception exception) { + try { + log.warn("Transmission '{}' failed duo to {}.", transmissionIdentifier, exception.getMessage()); + + // Delete temp file + Files.delete(payloadPath); + } catch (IOException e) { + log.warn("Unable to delete file: {}", payloadPath, e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/persist/DefaultPersisterHandler.java b/oxalis-commons/src/main/java/network/oxalis/commons/persist/DefaultPersisterHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..dc5159821f26a0a7f3ed5a11817cdfdb308e61f3 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/persist/DefaultPersisterHandler.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persist; + +import com.google.inject.Inject; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.persist.ExceptionPersister; +import network.oxalis.api.persist.PayloadPersister; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.persist.ReceiptPersister; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Singleton; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("default") +public class DefaultPersisterHandler implements PersisterHandler { + + private PayloadPersister payloadPersister; + + private ReceiptPersister receiptPersister; + + private ExceptionPersister exceptionPersister; + + @Inject + public DefaultPersisterHandler(PayloadPersister payloadPersister, ReceiptPersister receiptPersister, + ExceptionPersister exceptionPersister) { + this.payloadPersister = payloadPersister; + this.receiptPersister = receiptPersister; + this.exceptionPersister = exceptionPersister; + } + + @Override + public void persist(InboundMetadata inboundMetadata, Path payloadPath) throws IOException { + receiptPersister.persist(inboundMetadata, payloadPath); + } + + @Override + public Path persist(TransmissionIdentifier transmissionIdentifier, Header header, InputStream inputStream) + throws IOException { + return payloadPersister.persist(transmissionIdentifier, header, inputStream); + } + + @Override + public void persist(TransmissionIdentifier transmissionIdentifier, Header header, + Path payloadPath, Exception exception) { + exceptionPersister.persist(transmissionIdentifier, header, payloadPath, exception); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/persist/NoopPersister.java b/oxalis-commons/src/main/java/network/oxalis/commons/persist/NoopPersister.java new file mode 100644 index 0000000000000000000000000000000000000000..c5ef709b525ac1c4a08d2a473a30b11e19d9d72f --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/persist/NoopPersister.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persist; + +import com.google.common.io.ByteStreams; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Singleton; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; + +/** + * Implementation to be used in protocol benchmarking. This implementation does not store incoming content and metadata. + * + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("noop") +public class NoopPersister implements PersisterHandler { + + @Override + public Path persist(TransmissionIdentifier transmissionIdentifier, Header header, InputStream inputStream) + throws IOException { + ByteStreams.exhaust(inputStream); + return null; + } + + @Override + public void persist(InboundMetadata inboundMetadata, Path payloadPath) { + // No operation (intended) + } + + /** + * @since 4.0.3 + */ + @Override + public void persist(TransmissionIdentifier transmissionIdentifier, Header header, + Path payloadPath, Exception exception) { + // No operation (intended) + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterConf.java new file mode 100644 index 0000000000000000000000000000000000000000..fc283d7690519703b7d44fd3979ca5548cf37147 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterConf.java @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persist; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.0 + */ +@Title("Persister") +public enum PersisterConf { + + @Path("oxalis.persister.payload") + @DefaultValue("default") + PAYLOAD, + + @Path("oxalis.persister.receipt") + @DefaultValue("default") + RECEIPT, + + /** + * @since 4.0.3 + */ + @Path("oxalis.persister.exception") + @DefaultValue("default") + EXCEPTION, + + @Path("oxalis.persister.handler") + @DefaultValue("default") + HANDLER, + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterModule.java new file mode 100644 index 0000000000000000000000000000000000000000..e2a80fd751ffcc7268ebbc2a53e7422e1388a04e --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterModule.java @@ -0,0 +1,115 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persist; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import network.oxalis.api.persist.ExceptionPersister; +import network.oxalis.api.persist.PayloadPersister; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.persist.ReceiptPersister; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.api.plugin.PluginFactory; + +/** + * @author erlend + * @since 4.0.0 + */ +public class PersisterModule extends OxalisModule { + + @Override + protected void configure() { + // Creates bindings between the annotated PersisterConf items and external type safe config + bindSettings(PersisterConf.class); + + // Default + bindTyped(PayloadPersister.class, DefaultPersister.class); + bindTyped(ReceiptPersister.class, DefaultPersister.class); + bindTyped(ExceptionPersister.class, DefaultPersister.class); + bindTyped(PersisterHandler.class, DefaultPersisterHandler.class); + + // Noop + bindTyped(PayloadPersister.class, NoopPersister.class); + bindTyped(ReceiptPersister.class, NoopPersister.class); + bindTyped(ExceptionPersister.class, NoopPersister.class); + bindTyped(PersisterHandler.class, NoopPersister.class); + + // Temp + bindTyped(PayloadPersister.class, TempPersister.class); + bindTyped(ReceiptPersister.class, TempPersister.class); + bindTyped(ExceptionPersister.class, TempPersister.class); + bindTyped(PersisterHandler.class, TempPersister.class); + } + + @Provides + @Singleton + @Named("plugin") + protected PayloadPersister getPluginPayloadPersister(PluginFactory pluginFactory) { + return pluginFactory.newInstance(PayloadPersister.class); + } + + @Provides + @Singleton + @Named("plugin") + protected ReceiptPersister getPluginReceiptPersister(PluginFactory pluginFactory) { + return pluginFactory.newInstance(ReceiptPersister.class); + } + + @Provides + @Singleton + @Named("plugin") + protected PersisterHandler getPluginPersisterHandler(PluginFactory pluginFactory) { + return pluginFactory.newInstance(PersisterHandler.class); + } + + @Provides + @Singleton + protected PayloadPersister getPayloadPersister(Injector injector, Settings settings) { + return ImplLoader.get(injector, PayloadPersister.class, settings, PersisterConf.PAYLOAD); + } + + @Provides + @Singleton + protected ReceiptPersister getReceiptPersister(Injector injector, Settings settings) { + return ImplLoader.get(injector, ReceiptPersister.class, settings, PersisterConf.RECEIPT); + } + + /** + * @since 4.0.3 + */ + @Provides + @Singleton + protected ExceptionPersister getExceptionPersister(Injector injector, Settings settings) { + return ImplLoader.get(injector, ExceptionPersister.class, settings, PersisterConf.EXCEPTION); + } + + @Provides + @Singleton + protected PersisterHandler getPersisterHandler(Injector injector, Settings settings) { + return ImplLoader.get(injector, PersisterHandler.class, settings, PersisterConf.HANDLER); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterUtils.java b/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..83e7c090c5874b50d6fb55e09e9d14fb80e935fa --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/persist/PersisterUtils.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persist; + +import network.oxalis.commons.filesystem.FileUtils; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @author erlend + * @since 4.0.0 + */ +public class PersisterUtils { + + /** + * Computes the Path for a directory into which your file artifacts associated with + * the supplied header may be written. Any intermediate directories are created for you. + * + * @param baseFolder the root folder to use as the basis for appending additional folders. + * @param header meta data to be used as input for computation. + * @return a path to a directory into which you may store your artifacts. + * @throws IOException + */ + public static Path createArtifactFolders(Path baseFolder, Header header) throws IOException { + Path folder = baseFolder.resolve(Paths.get( + FileUtils.filterString(header.getReceiver().getIdentifier()), + FileUtils.filterString(header.getSender().getIdentifier()))); + + Files.createDirectories(folder); + + return folder; + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/persist/TempPersister.java b/oxalis-commons/src/main/java/network/oxalis/commons/persist/TempPersister.java new file mode 100644 index 0000000000000000000000000000000000000000..e5908853e523a737a4762d457649779216c4e67b --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/persist/TempPersister.java @@ -0,0 +1,108 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persist; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.lang.EvidenceException; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.util.Type; +import network.oxalis.commons.filesystem.FileUtils; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Singleton; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("temp") +@Slf4j +public class TempPersister implements PersisterHandler { + + private final EvidenceFactory evidenceFactory; + + private final Path folder; + + @Inject + public TempPersister(EvidenceFactory evidenceFactory) throws IOException { + this.evidenceFactory = evidenceFactory; + this.folder = Files.createTempDirectory("oxalis-inbound"); + } + + @Override + public Path persist(TransmissionIdentifier transmissionIdentifier, Header header, InputStream inputStream) + throws IOException { + // Create temp file + Path path = PersisterUtils.createArtifactFolders(folder, header) + .resolve(String.format("%s.xml", FileUtils.filterString(transmissionIdentifier.getIdentifier()))); + + // Copy content to temp file + try (OutputStream outputStream = Files.newOutputStream(path)) { + ByteStreams.copy(inputStream, outputStream); + } + + // Return file name + return path; + } + + @Override + public void persist(InboundMetadata inboundMetadata, Path payloadPath) throws IOException { + // Create temp file + Path path = PersisterUtils.createArtifactFolders(folder, inboundMetadata.getHeader()).resolve( + String.format("%s.evidence.dat", + FileUtils.filterString(inboundMetadata.getTransmissionIdentifier().getIdentifier()))); + + // Copy content to temp file + try (OutputStream outputStream = Files.newOutputStream(path)) { + evidenceFactory.write(outputStream, inboundMetadata); + } catch (EvidenceException e) { + throw new IOException(e.getMessage(), e); + } + } + + /** + * @since 4.0.3 + */ + @Override + public void persist(TransmissionIdentifier transmissionIdentifier, Header header, + Path payloadPath, Exception exception) { + try { + // Delete temp file + if (Files.exists(payloadPath)) + Files.delete(payloadPath); + } catch (IOException e) { + log.warn("Unable to delete temp file: {}", payloadPath, e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/plugin/PluginFactoryImpl.java b/oxalis-commons/src/main/java/network/oxalis/commons/plugin/PluginFactoryImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..afb88e60161d3bfea6f984c4b003093e574cdb81 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/plugin/PluginFactoryImpl.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.plugin; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisPluginException; +import network.oxalis.api.plugin.PluginFactory; +import network.oxalis.commons.guice.GuiceServiceLoader; + +import java.util.List; + +/** + * Implementation of {@link PluginFactory} making available type-specific objects for requested + * classes implementing specific interfaces. + * + * @author steinar + * @author erlend + * @since 4.0.0 + */ +class PluginFactoryImpl implements PluginFactory { + + private final GuiceServiceLoader guiceServiceLoader; + + private final ClassLoader classLoader; + + @Inject + public PluginFactoryImpl(GuiceServiceLoader guiceServiceLoader, @Named("plugin") ClassLoader classLoader) { + this.guiceServiceLoader = guiceServiceLoader; + this.classLoader = classLoader; + } + + /** + * Receives a new instance of the implementation implementing the requested interface. + * + * @param cls Interface implemented by the implementation. + * @param Same as {@param cls}. + * @return Initiated implementation of requested interface. + */ + @Override + public T newInstance(Class cls) { + List instances = guiceServiceLoader.load(cls, classLoader); + + if (instances.size() != 1) + throw new OxalisPluginException(String.format("Found %s implementations of '%s'.", + instances.size(), cls.getCanonicalName())); + + return instances.get(0); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/plugin/PluginModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/plugin/PluginModule.java new file mode 100644 index 0000000000000000000000000000000000000000..f354d021e9fbe49557a79292a290c1c052892de2 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/plugin/PluginModule.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.plugin; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.plugin.PluginFactory; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.filesystem.ClassLoaderUtils; +import network.oxalis.commons.filesystem.FileSystemConf; +import network.oxalis.commons.guice.OxalisModule; + +import java.nio.file.Path; + +/** + * This module enables extension of Oxalis using jar-files outside classpath. + * + * @author steinar + * @author erlend + * @since 4.0.0 + */ +@Slf4j +public class PluginModule extends OxalisModule { + + @Override + protected void configure() { + bind(PluginFactory.class) + .to(PluginFactoryImpl.class) + .in(Singleton.class); + } + + @Provides + @Singleton + @Named("plugin") + public ClassLoader providesClassLoader(@Named("home") Path homeDirectory, Settings settings) { + final Path pluginPath = settings.getPath(FileSystemConf.PLUGIN, homeDirectory); + log.info("Loading plugins from '{}'.", pluginPath); + return ClassLoaderUtils.initiate(pluginPath); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/plugin/package-info.java b/oxalis-commons/src/main/java/network/oxalis/commons/plugin/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..4770f3b6ba286e5e0de926d0469801fb024dd06c --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/plugin/package-info.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +/** + * This package contains functionality to support loading of extensions to Oxalis found in jar-files outside classpath + * of Oxalis. + *

+ * Please see ServiceLoader + * documentation on how to implement extensions to be loaded using this pacakge. + * + * @author steinar + * @author erlend + * @since 4.0.0 + */ +package network.oxalis.commons.plugin; \ No newline at end of file diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/security/CertificateModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/security/CertificateModule.java new file mode 100644 index 0000000000000000000000000000000000000000..0cf7db7713aaa5960dbd49cfb18e61634b286973 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/security/CertificateModule.java @@ -0,0 +1,130 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.security; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.api.model.AccessPointIdentifier; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.OxalisModule; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * @author erlend + * @since 4.0.0 + */ +@Slf4j +public class CertificateModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(KeyStoreConf.class); + + bind(KeyStore.PrivateKeyEntry.class) + .toProvider(PrivateKeyEntryProvider.class) + .asEagerSingleton(); + } + + @Provides + @Singleton + protected KeyStore getKeyStore(Settings settings, @Named("conf") Path confFolder) { + Path path = settings.getPath(KeyStoreConf.PATH, confFolder); + + try { + KeyStore keystore = KeyStore.getInstance("JKS"); + + if (Files.notExists(path)) + throw new OxalisLoadingException(String.format("Unable to find keystore at '%s'.", path)); + + try (InputStream inputStream = Files.newInputStream(path)) { + keystore.load(inputStream, settings.getString(KeyStoreConf.PASSWORD).toCharArray()); + } + return keystore; + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException e) { + throw new OxalisLoadingException("Something went wrong during handling of key store.", e); + } catch (IOException e) { + throw new OxalisLoadingException(String.format("Error during reading of '%s'.", path), e); + } + } + + @Provides + @Singleton + protected PrivateKey getPrivateKeyEntry(KeyStore keyStore, Settings settings) { + try { + if (!keyStore.containsAlias(settings.getString(KeyStoreConf.KEY_ALIAS))) + throw new OxalisLoadingException(String.format( + "Key alias '%s' is not found in the key store.", + settings.getString(KeyStoreConf.KEY_ALIAS))); + + PrivateKey privateKey = (PrivateKey) keyStore.getKey( + settings.getString(KeyStoreConf.KEY_ALIAS), + settings.getString(KeyStoreConf.KEY_PASSWORD).toCharArray()); + + if (privateKey == null) + throw new OxalisLoadingException("Unable to load private key due to wrong password."); + + return privateKey; + } catch (UnrecoverableKeyException e) { + throw new OxalisLoadingException("Unable to load private key due to wrong password.", e); + } catch (KeyStoreException | NoSuchAlgorithmException e) { + throw new OxalisLoadingException("Something went wrong during handling of key store.", e); + } + } + + @Provides + @Singleton + protected X509Certificate getCertificate(KeyStore keyStore, Settings settings) { + try { + if (!keyStore.containsAlias(settings.getString(KeyStoreConf.KEY_ALIAS))) + throw new OxalisLoadingException(String.format( + "Key alias '%s' is not found in the key store.", settings.getString(KeyStoreConf.KEY_ALIAS))); + + X509Certificate certificate = (X509Certificate) keyStore. + getCertificate(settings.getString(KeyStoreConf.KEY_ALIAS)); + + log.info("Certificate subject: {}", certificate.getSubjectX500Principal().toString()); + log.info("Certificate issuer: {}", certificate.getIssuerX500Principal().toString()); + // log.info("Certificate: {}", BaseEncoding.base64().encode(certificate.getEncoded())); + + return certificate; + } catch (KeyStoreException e) { + throw new OxalisLoadingException("Something went wrong during handling of key store.", e); + } + } + + @Provides + @Singleton + protected AccessPointIdentifier provideOurAccessPointIdentifier(X509Certificate certificate) { + return new AccessPointIdentifier(CertificateUtils.extractCommonName(certificate)); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/security/CertificateUtils.java b/oxalis-commons/src/main/java/network/oxalis/commons/security/CertificateUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..de6859c883d0803d49677f7d5445fa62ba27653c --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/security/CertificateUtils.java @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.security; + +import org.bouncycastle.asn1.x500.RDN; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x500.style.BCStyle; +import org.bouncycastle.asn1.x500.style.IETFUtils; + +import javax.security.auth.x500.X500Principal; +import java.io.ByteArrayInputStream; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * @author erlend + * @since 4.0.0 + */ +public class CertificateUtils { + + private static final CertificateFactory CERTIFICATE_FACTORY; + + static { + try { + CERTIFICATE_FACTORY = CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + + /** + * From https://stackoverflow.com/a/8322929/135001 + * + * @param cert X.509 Certificate + * @return Extracted Common Name from certificate. + */ + public static String extractCommonName(X509Certificate cert) { + X500Principal principal = cert.getSubjectX500Principal(); + + return extractCommonName(new X500Name(principal.getName())); + } + + /** + * @since 4.0.3 + */ + public static String extractCommonName(X500Name x500name) { + RDN cn = x500name.getRDNs(BCStyle.CN)[0]; + + return IETFUtils.valueToString(cn.getFirst().getValue()); + } + + /** + * Compare a provided Common Name with a given certificate. + * + * @since 4.0.3 + */ + public static boolean containsCommonName(X509Certificate cert, String commonName) { + return commonName == null || commonName.trim().equalsIgnoreCase(extractCommonName(cert)); + } + + /** + * Compare a provided Common Name with a given certificate. + * + * @since 4.0.3 + */ + public static boolean containsCommonName(X500Name x500name, String commonName) { + return commonName == null || commonName.trim().equalsIgnoreCase(extractCommonName(x500name)); + } + + /** + * @since 4.0.3 + */ + public static X509Certificate parseCertificate(byte[] encoded) throws CertificateException { + return (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(new ByteArrayInputStream(encoded)); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/security/KeyStoreConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/security/KeyStoreConf.java new file mode 100644 index 0000000000000000000000000000000000000000..dc59eea78cee286a248987149b03587678792ab3 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/security/KeyStoreConf.java @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.security; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Secret; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.0 + */ +@Title("Key store") +public enum KeyStoreConf { + + @Path("oxalis.keystore.path") + @DefaultValue("oxalis-keystore.jks") + PATH, + + @Path("oxalis.keystore.password") + @DefaultValue("changeit") + @Secret + PASSWORD, + + @Path("oxalis.keystore.key.alias") + @DefaultValue("ap") + KEY_ALIAS, + + @Path("oxalis.keystore.key.password") + @DefaultValue("changeit") + @Secret + KEY_PASSWORD + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/security/PrivateKeyEntryProvider.java b/oxalis-commons/src/main/java/network/oxalis/commons/security/PrivateKeyEntryProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..1c471652ceb547b9945e2c55a809de8d30b7ba85 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/security/PrivateKeyEntryProvider.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.security; + +import com.google.inject.Inject; +import com.google.inject.Provider; + +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; + +/** + * @author erlend + * @since 4.0.4 + */ +public class PrivateKeyEntryProvider implements Provider { + + @Inject + private PrivateKey privateKey; + + @Inject + private X509Certificate certificate; + + @Override + public KeyStore.PrivateKeyEntry get() { + return new KeyStore.PrivateKeyEntry( + privateKey, + new Certificate[]{certificate} + ); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/settings/SettingsBuilder.java b/oxalis-commons/src/main/java/network/oxalis/commons/settings/SettingsBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..04e0ee0bba64838d5df53e42fcce4f285ea325e3 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/settings/SettingsBuilder.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.settings; + +import com.google.inject.*; +import com.google.inject.util.Types; +import com.typesafe.config.Config; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.settings.Title; +import network.oxalis.commons.persist.PersisterConf; +import network.oxalis.commons.guice.OxalisModule; + +import java.util.HashMap; +import java.util.Map; + +/** + * Binds the parameterized configuration values described in annotations on enums to the configuration values + * found in the supplied type safe config. + * + * @author erlend + * @since 4.0.0 + */ +@Slf4j +public class SettingsBuilder implements Provider> { + + private Config config; + + private final Map settings = new HashMap<>(); + + private final String title; + + /** + * Binds the annotations of the supplied configuration enum as guice names with the values obtained from + * typesafe config. + * + * @param binder current Guice binder + * @param cls the enum class with annotations + * @param the type literal of the enum for instance {@link PersisterConf} + * @return instance of SettingsBuilder + */ + @SuppressWarnings("unchecked") + public static SettingsBuilder with(Binder binder, Class cls) { + + // Grabs the value of the @Title annotation and creates instance of SettingsBuilder of the enum + SettingsBuilder settingsBuilder = new SettingsBuilder<>(cls.getAnnotation(Title.class).value()); + + binder.skipSources(SettingsBuilder.class, OxalisModule.class) + .bind((Key>) Key.get(Types.newParameterizedType(Settings.class, cls))) + .toProvider(settingsBuilder) + .in(Singleton.class); + + binder.skipSources(SettingsBuilder.class, OxalisModule.class).requestInjection(settingsBuilder); + + for (T t : cls.getEnumConstants()) + settingsBuilder.add(t); + + return settingsBuilder; + } + + private SettingsBuilder(String title) { + this.title = title; + } + + private void add(T key) { + settings.put(key, TypesafeSettings.getField(key).getAnnotation(Path.class).value()); + } + + @Inject + public void setConfig(Config config) { + this.config = config; + + Settings result = get(); + + settings.keySet().stream() + .sorted() + .forEach(key -> log.info("{} => {}: {}", + title, key, result.toLogSafeString(key))); + } + + @Override + public Settings get() { + return new TypesafeSettings<>(config, settings); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/settings/TypesafeSettings.java b/oxalis-commons/src/main/java/network/oxalis/commons/settings/TypesafeSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..80eda5565fb0db1a219c52853f4ba5d43c7d92b5 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/settings/TypesafeSettings.java @@ -0,0 +1,108 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.settings; + +import com.google.inject.Inject; +import com.typesafe.config.Config; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.api.settings.Secret; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Nullable; + +import java.lang.reflect.Field; +import java.util.Map; + +/** + * @author erlend + * @since 4.0.0 + */ +class TypesafeSettings implements Settings { + + private final Config config; + + private final Map settings; + + @Inject + public TypesafeSettings(Config config, Map settings) { + this.config = config; + this.settings = settings; + } + + @Override + public String getString(T key) { + if (config.hasPath(settings.get(key))) { + return config.getString(settings.get(key)); + } else { + Field field = getField(key); + + if (field.getAnnotation(Nullable.class) != null) + return null; + else if (field.getAnnotation(DefaultValue.class) != null) + return field.getAnnotation(DefaultValue.class).value(); + + throw new OxalisLoadingException(String.format("Setting '%s' not found.", settings.get(key))); + } + } + + @Override + public int getInt(T key) { + if (config.hasPath(settings.get(key))) { + return config.getInt(settings.get(key)); + } else { + return Integer.parseInt(getString(key)); + } + } + + @Override + public String toLogSafeString(T key) { + Field field = getField(key); + boolean isSecret = field.getAnnotation(Secret.class) != null; + + if (config.hasPath(settings.get(key))) { + String value = config.getString(settings.get(key)); + return maskIfSecret(value, isSecret); + } else if (field.getAnnotation(DefaultValue.class) != null) { + return field.getAnnotation(DefaultValue.class).value(); + } else if (field.getAnnotation(Nullable.class) != null) { + return ""; + } else { + throw new OxalisLoadingException(String.format("Setting '%s' not found.", settings.get(key))); + } + } + + private String maskIfSecret(String value, boolean isSecret ) { + if(isSecret){ + return value.replaceAll(".", "*"); + } + return value; + } + + protected static Field getField(T key) { + try { + return key.getClass().getField(((Enum) key).name()); + } catch (NoSuchFieldException e) { + throw new OxalisLoadingException(e.getMessage(), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/statistics/NoopStatisticsService.java b/oxalis-commons/src/main/java/network/oxalis/commons/statistics/NoopStatisticsService.java new file mode 100644 index 0000000000000000000000000000000000000000..1471ff8cd1f1155098f775f62674ae7a76dc46fd --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/statistics/NoopStatisticsService.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.statistics; + +import com.google.inject.Singleton; +import io.opentracing.Span; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.statistics.StatisticsService; +import network.oxalis.api.util.Type; + +/** + * NOOP implementation of {@link StatisticsService}. + */ +@Singleton +@Type("noop") +public class NoopStatisticsService implements StatisticsService { + + @Override + public void persist(TransmissionRequest transmissionRequest, + TransmissionResponse transmissionResponse, Span root) { + // No action. + } + + @Override + public void persist(InboundMetadata inboundMetadata) { + // No action. + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/statistics/StatisticsConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/statistics/StatisticsConf.java new file mode 100644 index 0000000000000000000000000000000000000000..46df673d062ca02f22972e72a95c08c5922fcf0a --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/statistics/StatisticsConf.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.statistics; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.0 + */ +@Title("Statistics") +public enum StatisticsConf { + + @Path("oxalis.statistics.service") + @DefaultValue("noop") + SERVICE + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/statistics/StatisticsModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/statistics/StatisticsModule.java new file mode 100644 index 0000000000000000000000000000000000000000..09ee47ded4ccd44c64c4e68e9d7956f1074abb86 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/statistics/StatisticsModule.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.statistics; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.statistics.StatisticsService; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +public class StatisticsModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(StatisticsConf.class); + + bindTyped(StatisticsService.class, NoopStatisticsService.class); + } + + @Provides + @Singleton + protected StatisticsService getStatisticsService(Injector injector, Settings settings) { + return ImplLoader.get(injector, StatisticsService.class, settings, StatisticsConf.SERVICE); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tag/NoopTagGenerator.java b/oxalis-commons/src/main/java/network/oxalis/commons/tag/NoopTagGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..94d498b6c22522ab1a9ae4df4707c70119abc3be --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tag/NoopTagGenerator.java @@ -0,0 +1,19 @@ +package network.oxalis.commons.tag; + +import network.oxalis.api.model.Direction; +import network.oxalis.api.tag.Tag; +import network.oxalis.api.tag.TagGenerator; +import network.oxalis.api.util.Type; + +/** + * @author erlend + * @since 4.0.2 + */ +@Type("noop") +public class NoopTagGenerator implements TagGenerator { + + @Override + public Tag generate(Direction direction) { + return Tag.NONE; + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tag/TagConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/tag/TagConf.java new file mode 100644 index 0000000000000000000000000000000000000000..ddf45fe678d7484f80614eb8a1652883f14a0fe4 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tag/TagConf.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tag; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.0 + */ +@Title("Tag") +public enum TagConf { + + @Path("oxalis.tag.generator") + @DefaultValue("noop") + GENERATOR + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tag/TagModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/tag/TagModule.java new file mode 100644 index 0000000000000000000000000000000000000000..07a6f060f7e53f81a6ec1d078a8bc1fb00beccdc --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tag/TagModule.java @@ -0,0 +1,29 @@ +package network.oxalis.commons.tag; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.tag.TagGenerator; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.2 + */ +public class TagModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(TagGenerator.class, NoopTagGenerator.class); + + bindSettings(TagConf.class); + } + + @Provides + @Singleton + protected TagGenerator getTagGenerator(Injector injector, Settings settings) { + return ImplLoader.get(injector, TagGenerator.class, settings, TagConf.GENERATOR); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/SystemTimestampProvider.java b/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/SystemTimestampProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..a92e7198019da07654f56e1ac934918f6eb10fa3 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/SystemTimestampProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.timestamp; + +import com.google.inject.Singleton; +import network.oxalis.api.model.Direction; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.api.timestamp.TimestampProvider; +import network.oxalis.api.util.Type; + +import java.util.Date; + +/** + * Implementation of {@link TimestampProvider} simply providing timestamps using internal computer clock. + * + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("system") +class SystemTimestampProvider implements TimestampProvider { + + @Override + public Timestamp generate(byte[] content, Direction direction) { + return new Timestamp(new Date(), null); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/TimestampConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/TimestampConf.java new file mode 100644 index 0000000000000000000000000000000000000000..9ee35e235db97e3095df50958807c77efd86fc56 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/TimestampConf.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.timestamp; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.0 + */ +@Title("Timestamp") +public enum TimestampConf { + + @Path("oxalis.timestamp.service") + @DefaultValue("system") + SERVICE +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/TimestampModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/TimestampModule.java new file mode 100644 index 0000000000000000000000000000000000000000..f96b18ee84ed7e3bc250b3cef617830390396f51 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/timestamp/TimestampModule.java @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.timestamp; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.timestamp.TimestampProvider; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * Guice module making a default implementation of {@link TimestampProvider} available. + *

+ * Available services (timestamp.service): + *

    + *
  • system
  • + *
+ * + * @author erlend + * @since 4.0.0 + */ +public class TimestampModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(TimestampProvider.class, SystemTimestampProvider.class); + + bindSettings(TimestampConf.class); + } + + @Provides + @Singleton + protected TimestampProvider getTimestampProvider(Injector injector, Settings settings) { + return ImplLoader.get(injector, TimestampProvider.class, settings, TimestampConf.SERVICE); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tracing/BraveConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/BraveConf.java new file mode 100644 index 0000000000000000000000000000000000000000..33722cf26cb9705f388f142722a72633a96b3413 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/BraveConf.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tracing; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Nullable; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("Tracing") +public enum BraveConf { + + @Path("oxalis.tracing.brave.reporter") + @DefaultValue("noop") + REPORTER, + + @Path("oxalis.tracing.brave.http") + @Nullable + HTTP + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tracing/BraveTracerProvider.java b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/BraveTracerProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..ecf85db6152d6b9307a658ed0814c5106b52025b --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/BraveTracerProvider.java @@ -0,0 +1,27 @@ +package network.oxalis.commons.tracing; + +import brave.Tracing; +import brave.opentracing.BraveTracer; +import com.google.inject.Inject; +import com.google.inject.Provider; +import io.opentracing.Tracer; +import zipkin2.reporter.Reporter; + +/** + * @author erlend + */ +public class BraveTracerProvider implements Provider { + + @Inject + private Reporter reporter; + + @Override + public Tracer get() { + Tracing tracing = Tracing.newBuilder() + .localServiceName("Oxalis") + .spanReporter(reporter) + .build(); + + return BraveTracer.create(tracing); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tracing/Slf4jReporter.java b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/Slf4jReporter.java new file mode 100644 index 0000000000000000000000000000000000000000..721affef610f88b0bce80e6c0ebba6d85efef75e --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/Slf4jReporter.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tracing; + +import com.google.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.util.Type; +import zipkin2.Span; +import zipkin2.reporter.Reporter; + +/** + * Implementation of ZipKin Reporter putting tracing data in SLF4J logger. + * + * @author erlend + * @since 4.0.0 + */ +@Slf4j +@Singleton +@Type("slf4j") +public class Slf4jReporter implements Reporter { + + /** + * {@inheritDoc} + */ + @Override + public void report(Span span) { + log.info("{}", span); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tracing/Traceable.java b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/Traceable.java new file mode 100644 index 0000000000000000000000000000000000000000..f139006b100216e07e07d114341f6b18a6002bbd --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/Traceable.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tracing; + +import io.opentracing.Tracer; + +/** + * Simple abstract class making {@link Tracer} object available in a standardized manner for classes extending this + * class. + * + * @author erlend + * @since 4.0.0 + */ +public abstract class Traceable { + + /** + * Zipkin tracer implementation. + */ + protected final Tracer tracer; + + /** + * Default constructor accepting a tracer. + * + * @param tracer Tracer from application context. + */ + protected Traceable(Tracer tracer) { + this.tracer = tracer; + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tracing/TracingConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/TracingConf.java new file mode 100644 index 0000000000000000000000000000000000000000..db7de14e4a0fb8c503298c1b02eb61acb517065f --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/TracingConf.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tracing; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("Tracing") +public enum TracingConf { + + @Path("oxalis.tracing.tracer") + @DefaultValue("noop") + TRACER, + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/tracing/TracingModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/TracingModule.java new file mode 100644 index 0000000000000000000000000000000000000000..b971eab1c82897eeedefa0da408913c0cbfc6ef4 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/tracing/TracingModule.java @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tracing; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import com.google.inject.name.Names; +import io.opentracing.Tracer; +import io.opentracing.noop.NoopTracerFactory; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; +import zipkin2.reporter.AsyncReporter; +import zipkin2.reporter.Reporter; +import zipkin2.reporter.urlconnection.URLConnectionSender; + +/** + *

+ * Available reports (brave.reporter): + *

    + *
  • console
  • + *
  • http
  • + *
  • slf4j
  • + *
+ * + * @author erlend + * @since 4.0.0 + */ +public class TracingModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(BraveConf.class); + bindSettings(TracingConf.class); + + bind(Key.get(Tracer.class, Names.named("noop"))) + .toProvider(NoopTracerFactory::create); + bind(Key.get(Tracer.class, Names.named("brave"))) + .toProvider(BraveTracerProvider.class); + + bind(Key.get(Reporter.class, Names.named("console"))) + .toProvider(() -> Reporter.CONSOLE); + bindTyped(Reporter.class, Slf4jReporter.class); + } + + @Provides + @Singleton + @Named("http") + protected Reporter getHttpReporter(Settings settings) { + return AsyncReporter + .builder(URLConnectionSender.create(settings.getString(BraveConf.HTTP))) + .build(); + } + + @Provides + @Singleton + protected Reporter getReporter(Injector injector, Settings settings) { + return ImplLoader.get(injector, Reporter.class, settings, BraveConf.REPORTER); + } + + @Provides + @Singleton + protected Tracer getTracer(Injector injector, Settings settings) { + return ImplLoader.get(injector, Tracer.class, settings, TracingConf.TRACER); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/transformer/NoopContentDetector.java b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/NoopContentDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..b3d0820fa0dfaa84f944a4af19cada07504f1a98 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/NoopContentDetector.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transformer; + +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.transformer.ContentDetector; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Singleton; +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.1 + */ +@Singleton +@Type("noop") +public class NoopContentDetector implements ContentDetector { + + @Override + public Header parse(InputStream inputStream) throws OxalisContentException { + throw new OxalisContentException("Content does not contain SBDH."); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/transformer/NoopContentWrapper.java b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/NoopContentWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..ee8e54915ad907581f8a4db4c1828ec61e32004b --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/NoopContentWrapper.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transformer; + +import com.google.inject.Singleton; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.transformer.ContentWrapper; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.1 + */ +@Singleton +@Type("noop") +public class NoopContentWrapper implements ContentWrapper { + + @Override + public InputStream wrap(InputStream inputStream, Header header) throws OxalisContentException { + throw new OxalisContentException("No content wrapper is available."); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/transformer/TransformerConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/TransformerConf.java new file mode 100644 index 0000000000000000000000000000000000000000..04a0c419beacefe81310ff6b5206bee75570a9c7 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/TransformerConf.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transformer; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.1 + */ +@Title("Transformer") +public enum TransformerConf { + + @Path("oxalis.transformer.detector") + @DefaultValue("noop") + DETECTOR, + + @Path("oxalis.transformer.wrapper") + @DefaultValue("xml") + WRAPPER + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/transformer/TransformerModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/TransformerModule.java new file mode 100644 index 0000000000000000000000000000000000000000..6995329a958a1e416bd592893c8142ea355c09a9 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/transformer/TransformerModule.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transformer; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.transformer.ContentDetector; +import network.oxalis.api.transformer.ContentWrapper; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.1 + */ +public class TransformerModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(ContentDetector.class, NoopContentDetector.class); + bindTyped(ContentWrapper.class, NoopContentWrapper.class); + + bindSettings(TransformerConf.class); + } + + @Provides + @Singleton + protected ContentDetector getContentDetector(Injector injector, Settings settings) { + return ImplLoader.get(injector, ContentDetector.class, settings, TransformerConf.DETECTOR); + } + + @Provides + @Singleton + protected ContentWrapper getContentWrapper(Injector injector, Settings settings) { + return ImplLoader.get(injector, ContentWrapper.class, settings, TransformerConf.WRAPPER); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/transmission/DefaultTransmissionVerifier.java b/oxalis-commons/src/main/java/network/oxalis/commons/transmission/DefaultTransmissionVerifier.java new file mode 100644 index 0000000000000000000000000000000000000000..d9a59fdc8a1d8be2018b5b3885064dd3d4b68fea --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/transmission/DefaultTransmissionVerifier.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transmission; + +import com.google.inject.Singleton; +import network.oxalis.api.model.Direction; +import network.oxalis.api.transmission.TransmissionVerifier; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; + +/** + * Default implementation allowing all incoming transmissions. + * + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("default") +public class DefaultTransmissionVerifier implements TransmissionVerifier { + + @Override + public void verify(Header header, Direction direction) { + // No action. + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/transmission/TransmissionConf.java b/oxalis-commons/src/main/java/network/oxalis/commons/transmission/TransmissionConf.java new file mode 100644 index 0000000000000000000000000000000000000000..faf1c6872f4aed8881e36ad7e57f6e133fdc12ca --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/transmission/TransmissionConf.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transmission; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("Transmission") +public enum TransmissionConf { + + @Path("oxalis.transmission.verifier") + @DefaultValue("default") + VERIFIER + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/transmission/TransmissionModule.java b/oxalis-commons/src/main/java/network/oxalis/commons/transmission/TransmissionModule.java new file mode 100644 index 0000000000000000000000000000000000000000..e20cfaf5eb5c383629636d2701fcbed0da60d625 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/transmission/TransmissionModule.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transmission; + +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.transmission.TransmissionVerifier; +import network.oxalis.commons.guice.ImplLoader; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.0 + */ +public class TransmissionModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(TransmissionConf.class); + + bindTyped(TransmissionVerifier.class, DefaultTransmissionVerifier.class); + } + + @Provides + @Singleton + protected TransmissionVerifier getInboundVerifier(Injector injector, Settings settings) { + return ImplLoader.get(injector, TransmissionVerifier.class, settings, TransmissionConf.VERIFIER); + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/util/ClassUtils.java b/oxalis-commons/src/main/java/network/oxalis/commons/util/ClassUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..5c20c3e6e3fe4b779f41746f9fe4cc40e095eb24 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/util/ClassUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.util; + +import network.oxalis.api.lang.OxalisLoadingException; + +/** + * @author erlend + */ +public class ClassUtils { + + /** + * Loads a class from current class loader. + */ + public static Class load(String className) { + return load(className, Thread.currentThread().getContextClassLoader()); + } + + /** + * Loads a class from the given class loader. + */ + public static Class load(String className, ClassLoader classLoader) { + try { + return classLoader.loadClass(className); + } catch (ClassNotFoundException e) { + throw new OxalisLoadingException(String.format("Unable to load class '%s'.", classLoader), e); + } + } +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/util/OxalisVersion.java b/oxalis-commons/src/main/java/network/oxalis/commons/util/OxalisVersion.java new file mode 100644 index 0000000000000000000000000000000000000000..8f1d977ad6faf7c51e915324f4836e4de7e8aeb4 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/util/OxalisVersion.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.util; + +import network.oxalis.api.lang.OxalisLoadingException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * Provides access to selected Maven injected properties in the oxalis-version.properties file. + * + * @author steinar + * @author thore + * @author erlend + */ +public class OxalisVersion { + + private static Properties properties; + + static { + try (InputStream inputStream = OxalisVersion.class.getResourceAsStream("/oxalis-version.properties")) { + properties = new Properties(); + properties.load(inputStream); + } catch (IOException e) { + throw new OxalisLoadingException(e.getMessage(), e); + } + } + + /** + * The Oxalis version, taken from the POM + */ + public static String getVersion() { + return properties.getProperty("oxalis.version"); + } + + /** + * The OS user (from environment) running the build + */ + public static String getUser() { + return properties.getProperty("oxalis.user"); + } + + /** + * Describes the build SCM version + */ + public static String getBuildDescription() { + return properties.getProperty("git.commit.id.describe"); + } + + /** + * Git SCM version, full format + */ + public static String getBuildId() { + return properties.getProperty("git.commit.id"); + } + + /** + * The build commit time stamp + */ + public static String getBuildTimeStamp() { + return properties.getProperty("git.commit.time"); + } + +} diff --git a/oxalis-commons/src/main/java/network/oxalis/commons/util/Sortables.java b/oxalis-commons/src/main/java/network/oxalis/commons/util/Sortables.java new file mode 100644 index 0000000000000000000000000000000000000000..b6b19ddeb863d5bba3088c72af22e91f6b8184c2 --- /dev/null +++ b/oxalis-commons/src/main/java/network/oxalis/commons/util/Sortables.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.util; + +import network.oxalis.api.util.Sort; + +import java.util.Comparator; + +/** + * Class containing methods to make Sortable interface and Sort + * annotation useful. + * + * @author erlend + */ +public class Sortables { + + /** + * Method extracting order value from a given object. + * + * @param The type of the elements to be sorted. + * @param o Object to extract value for comparison. + * @return Value used to compare. + */ + public static int extract(T o) { + if (o.getClass().isAnnotationPresent(Sort.class)) + return o.getClass().getAnnotation(Sort.class).value(); + + return 0; + } + + /** + * Returns a comparator. + * + * @param The type of the elements to be sorted. + * @return Comparator to be used for sorting. + */ + public static Comparator comparator() { + return Comparator.comparingInt(Sortables::extract); + } +} \ No newline at end of file diff --git a/oxalis-commons/src/main/resources/reference.conf b/oxalis-commons/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..938d752bcac1e068f8a70418f01d0f56706564c9 --- /dev/null +++ b/oxalis-commons/src/main/resources/reference.conf @@ -0,0 +1,21 @@ +oxalis.module.core = { + config.class = network.oxalis.commons.config.ConfigModule + error.class = network.oxalis.commons.error.ErrorModule + evidence.class = network.oxalis.commons.evidence.EvidenceModule + executor.class = network.oxalis.commons.executor.ExecutorModule + filesystem.class = network.oxalis.commons.filesystem.FileSystemModule + header.class = network.oxalis.commons.header.HeaderModule + http.class = network.oxalis.commons.http.ApacheHttpModule + identifier.class = network.oxalis.commons.identifier.IdentifierModule + logging.class = network.oxalis.commons.logging.LoggingModule + mode.class = network.oxalis.commons.mode.ModeModule + persist.class = network.oxalis.commons.persist.PersisterModule + plugin.class = network.oxalis.commons.plugin.PluginModule + security.class = network.oxalis.commons.security.CertificateModule + statistics.class = network.oxalis.commons.statistics.StatisticsModule + tag.class = network.oxalis.commons.tag.TagModule + timestamp.class = network.oxalis.commons.timestamp.TimestampModule + tracing.class = network.oxalis.commons.tracing.TracingModule + transformer.class = network.oxalis.commons.transformer.TransformerModule + transmission.class = network.oxalis.commons.transmission.TransmissionModule +} diff --git a/oxalis-commons/src/test/java/dk/erst/oxalis/commons/filesystem/detector/RelativePropertyHomeDetectorTest.java b/oxalis-commons/src/test/java/dk/erst/oxalis/commons/filesystem/detector/RelativePropertyHomeDetectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ec4cbb449bb111342e95f811af7991b705e68a4e --- /dev/null +++ b/oxalis-commons/src/test/java/dk/erst/oxalis/commons/filesystem/detector/RelativePropertyHomeDetectorTest.java @@ -0,0 +1,53 @@ +package dk.erst.oxalis.commons.filesystem.detector; + +import network.oxalis.api.filesystem.HomeDetector; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.File; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +public class RelativePropertyHomeDetectorTest { + + private HomeDetector homeDetector = new RelativePropertyHomeDetector(); + + @BeforeClass + public void setup(){ + System.setProperty("catalina.base", "/catalina"); + } + + @AfterClass + public void cleanup(){ + System.clearProperty("catalina.base"); + } + + @Test + public void testFromJavaSystemProperty() { + String path = new File("/catalina/some/system/path2").getAbsolutePath(); + String backup = System.getProperty(RelativePropertyHomeDetector.VARIABLE); + + try { + System.clearProperty(RelativePropertyHomeDetector.VARIABLE); + File oxalis_home = homeDetector.detect(); + assertNull(oxalis_home); + + System.setProperty(RelativePropertyHomeDetector.VARIABLE, ""); + oxalis_home = homeDetector.detect(); + assertNull(oxalis_home); + + System.setProperty(RelativePropertyHomeDetector.VARIABLE, "some/system/path2"); + oxalis_home = homeDetector.detect(); + assertEquals(oxalis_home.getAbsolutePath(), path); + + System.setProperty(RelativePropertyHomeDetector.VARIABLE, "/some/system/path2"); + oxalis_home = homeDetector.detect(); + assertEquals(oxalis_home.getAbsolutePath(), path); + } finally { + if (backup == null) backup = ""; // prevent null pointer exception + System.setProperty(RelativePropertyHomeDetector.VARIABLE, backup); + } + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/bouncycastle/BCHelperTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/bouncycastle/BCHelperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c8e090c71db977d7940d243e8ec1045ab61afe45 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/bouncycastle/BCHelperTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.bouncycastle; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; + +/** + * @author erlend + */ +public class BCHelperTest { + + @Test + public void simpleConstructor() { + new BCHelper(); + } + + @Test + public void simpleRegisterProvider() { + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) != null) + Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); + + Assert.assertNull(Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)); + + BCHelper.registerProvider(); + + Provider provider = Security.getProvider(BouncyCastleProvider.PROVIDER_NAME); + Assert.assertNotNull(provider); + + BCHelper.registerProvider(); + + Assert.assertTrue(provider == Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)); + } + + @Test + public void createMessageDigest() throws Exception { + BCHelper.registerProvider(); + + Assert.assertNotNull(BCHelper.getMessageDigest("SHA-1")); + } + + @Test(expectedExceptions = NoSuchAlgorithmException.class) + public void triggerExceptionWhenProviderIsNotFound() throws Exception { + Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME); + + BCHelper.getMessageDigest("SHA-512"); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/commons/JavaPropertiesPostConfigTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/commons/JavaPropertiesPostConfigTest.java new file mode 100644 index 0000000000000000000000000000000000000000..df8137d6460124061de29e756f7de90d6cdcb9c0 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/commons/JavaPropertiesPostConfigTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.commons; + +import com.google.common.collect.ImmutableMap; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import network.oxalis.commons.config.JavaPropertiesPostConfig; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class JavaPropertiesPostConfigTest { + + @Test + public void simple() { + Assert.assertNull(System.getProperty("oxalis.test")); + + Config config = ConfigFactory.parseMap(ImmutableMap.of("oxalis.java.oxalis.test", "Value")); + + new JavaPropertiesPostConfig().perform(config); + + Assert.assertEquals(System.getProperty("oxalis.test"), "Value"); + + System.clearProperty("oxalis.test"); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/evidence/RemEvidenceFactoryTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/evidence/RemEvidenceFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5180f566effb6884b306dddf791f39c9c8452c6b --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/evidence/RemEvidenceFactoryTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.evidence; + +import com.google.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.lang.EvidenceException; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.test.identifier.PeppolDocumentTypeIdAcronym; +import network.oxalis.vefa.peppol.common.code.DigestMethod; +import network.oxalis.vefa.peppol.common.model.*; +import org.mockito.Mockito; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Collections; +import java.util.Date; + +/** + * @author erlend + */ +@Slf4j +@Guice(modules = {GuiceModuleLoader.class}) +public class RemEvidenceFactoryTest { + + @Inject + private EvidenceFactory evidenceFactory; + + @Test + public void simple() throws IOException, EvidenceException { + Assert.assertNotNull(evidenceFactory); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + evidenceFactory.write(outputStream, createMockTransmissionResponse()); + + log.info(new String(outputStream.toByteArray())); + } + + @Test(expectedExceptions = EvidenceException.class) + public void triggerException() throws IOException, EvidenceException { + evidenceFactory.write(null, createMockTransmissionResponse()); + } + + private TransmissionResponse createMockTransmissionResponse() { + TransmissionResponse transmissionResponse = Mockito.mock(TransmissionResponse.class); + + Date timestamp = new Date(); + Mockito.when(transmissionResponse.getTimestamp()).thenReturn(timestamp); + + Header header = Header.newInstance() + .sender(ParticipantIdentifier.of("9908:987654321")) + .receiver(ParticipantIdentifier.of("9908:123456789")) + .documentType(PeppolDocumentTypeIdAcronym.INVOICE.toVefa()) + .identifier(InstanceIdentifier.generateUUID()); + Mockito.when(transmissionResponse.getHeader()).thenReturn(header); + + Digest digest = Digest.of(DigestMethod.SHA1, "Hello World".getBytes()); + Mockito.when(transmissionResponse.getDigest()).thenReturn(digest); + + TransmissionIdentifier transmissionIdentifier = TransmissionIdentifier.generateUUID(); + Mockito.when(transmissionResponse.getTransmissionIdentifier()).thenReturn(transmissionIdentifier); + + Mockito.when(transmissionResponse.getTransportProtocol()).thenReturn(TransportProtocol.INTERNAL); + + Mockito.when(transmissionResponse.getReceipts()).thenReturn(Collections.emptyList()); + + return transmissionResponse; + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/ClassLoaderUtilsTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/ClassLoaderUtilsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d20192f1d4a1a8c0b2f3cc01f8e9dcc07bc287ad --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/ClassLoaderUtilsTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import network.oxalis.api.lang.OxalisPluginException; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @author erlend + */ +public class ClassLoaderUtilsTest { + + private ClassLoader current = Thread.currentThread().getContextClassLoader(); + + @Test + public void simpleConstructor() { + new ClassLoaderUtils(); + } + + @Test + public void simpleNull() { + Assert.assertEquals(ClassLoaderUtils.initiate(null), current); + } + + @Test + public void simpleJavaHome() { + Path path = Paths.get(System.getProperty("java.home"), "lib"); + Assert.assertNotEquals(ClassLoaderUtils.initiate(path), current); + } + + @Test + public void simpleRT() { + Path path = Paths.get(System.getProperty("java.home"), "lib", "rt.jar"); + Assert.assertNotEquals(ClassLoaderUtils.initiate(path), current); + } + + @Test(expectedExceptions = OxalisPluginException.class) + public void triggerException() { + Path path = Paths.get(System.getProperty("java.home"), "completely", "invalid", "folder"); + ClassLoaderUtils.initiate(path); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileSystemConfTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileSystemConfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7d3e312f27e0810e2ccb090d622ffb97a2bb3333 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileSystemConfTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class FileSystemConfTest { + + @Test + public void simpleValueOf() { + Assert.assertEquals(FileSystemConf.valueOf("CONF"), FileSystemConf.CONF); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileSystemModuleTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileSystemModuleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5a86756b591a118e8d805830bdf6309455a2831d --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileSystemModuleTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Names; +import com.google.inject.util.Modules; +import network.oxalis.commons.config.ConfigModule; +import network.oxalis.test.filesystem.TestFileSystemModule; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.nio.file.Path; + +public class FileSystemModuleTest { + + @Inject + private Injector injector = Guice.createInjector( + new ConfigModule(), + Modules.override(new FileSystemModule()).with(new TestFileSystemModule())); + + @Test + public void verifyHomeFolder() { + Assert.assertNotNull(injector.getInstance(Key.get(Path.class, Names.named("home")))); + } + + @Test + public void verifyConfFolder() { + Assert.assertNotNull(injector.getInstance(Key.get(Path.class, Names.named("conf")))); + } + + @Test + public void verifyInboundFolder() { + Assert.assertNotNull(injector.getInstance(Key.get(Path.class, Names.named("inbound")))); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileUtilsTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileUtilsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6819615373846469cd9bcf8a47b80f0cece8ec58 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/FileUtilsTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class FileUtilsTest { + + @Test + public void simpleConstructor() { + new FileUtils(); + } + + @Test + public void simpleFilterString() { + String result = FileUtils.filterString("<1811836472.7.1486495191281.JavaMail.ebe@L-EBE-X260>"); + Assert.assertEquals(result, "_1811836472.7.1486495191281.JavaMail.ebe_L-EBE-X260_"); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/OxalisHomeDirectoryTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/OxalisHomeDirectoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a09a47941594d8744c4097aee959d64f05a267db --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/OxalisHomeDirectoryTest.java @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem; + +import com.google.inject.Inject; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.io.File; +import java.nio.file.Path; +import java.util.Collections; + +/** + * @author steinar + * @author thore + * @author erlend + */ +@Guice(modules = GuiceModuleLoader.class) +public class OxalisHomeDirectoryTest { + + @Inject + private OxalisHomeDirectory oxalisHomeDirectory; + + private Path fakeHome; + + @BeforeClass + public void beforeClass() throws Exception { + this.fakeHome = new File(getClass().getResource("/oxalis_home/fake-oxalis.conf").toURI()) + .toPath().getParent(); + } + + @Test + public void simple() { + Assert.assertNotNull(oxalisHomeDirectory); + } + + @Test + public void mockingFound() { + OxalisHomeDirectory oxalisHomeDirectory = new OxalisHomeDirectory( + Collections.singletonList(() -> fakeHome.toFile())); + + Assert.assertNotNull(oxalisHomeDirectory.detect()); + } + + @Test(expectedExceptions = OxalisLoadingException.class) + public void mockingNotFound() { + OxalisHomeDirectory oxalisHomeDirectory = new OxalisHomeDirectory( + Collections.singletonList(() -> null)); + oxalisHomeDirectory.detect(); + } + + @Test(expectedExceptions = OxalisLoadingException.class) + public void mockingInvalid() { + OxalisHomeDirectory oxalisHomeDirectory = new OxalisHomeDirectory( + Collections.singletonList(() -> new File("/invalid"))); + oxalisHomeDirectory.detect(); + } + + @Test(expectedExceptions = OxalisLoadingException.class) + public void mockingFile() { + OxalisHomeDirectory oxalisHomeDirectory = new OxalisHomeDirectory( + Collections.singletonList(() -> fakeHome.resolve("fake-oxalis.conf").toFile())); + oxalisHomeDirectory.detect(); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/EnvironmentHomeDetectorTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/EnvironmentHomeDetectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..589cfba7b9bb60692a3ba909ea4a0baabe3f021f --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/EnvironmentHomeDetectorTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import network.oxalis.api.filesystem.HomeDetector; +import org.testng.annotations.Test; + +import java.util.Collections; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; + +/** + * @author erlend + */ +public class EnvironmentHomeDetectorTest { + + @Test + public void notFound() { + HomeDetector homeDetector = new EnvironmentHomeDetector(Collections.emptyMap()); + + assertNull(homeDetector.detect()); + } + + @Test + public void found() { + HomeDetector homeDetector = new EnvironmentHomeDetector( + Collections.singletonMap(EnvironmentHomeDetector.VARIABLE, "/tmp")); + + assertNotNull(homeDetector.detect()); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/JndiHomeDetectorTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/JndiHomeDetectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..14282ff1b7715af702d2bb8f16e73a9b150cb79b --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/JndiHomeDetectorTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import network.oxalis.api.filesystem.HomeDetector; +import org.testng.annotations.Test; + +import javax.naming.Context; +import javax.naming.InitialContext; +import java.io.File; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * @author erlend + */ +public class JndiHomeDetectorTest { + + private HomeDetector homeDetector = new JndiHomeDetector(); + + @Test + public void testFromJndi() throws Exception { + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, TestableInitialContextFactory.class.getName()); + new InitialContext().unbind(JndiHomeDetector.VARIABLE); + + String path = new File("/some/system/path1").getAbsolutePath(); + + // + File oxalis_home = homeDetector.detect(); + assertNull(oxalis_home); + + // bind value to JNDI and read + new InitialContext().bind(JndiHomeDetector.VARIABLE, path); + oxalis_home = homeDetector.detect(); + assertEquals(oxalis_home.getAbsolutePath(), path); + + // Removes the JNDI entry for OXALIS_HOME + new InitialContext().unbind(JndiHomeDetector.VARIABLE); + } + + @Test + public void testEmpty() throws Exception { + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, TestableInitialContextFactory.class.getName()); + new InitialContext().unbind(JndiHomeDetector.VARIABLE); + + File oxalis_home = homeDetector.detect(); + assertNull(oxalis_home); + + // bind value to JNDI and read + new InitialContext().bind(JndiHomeDetector.VARIABLE, ""); + assertNull(homeDetector.detect()); + + // Removes the JNDI entry for OXALIS_HOME + new InitialContext().unbind(JndiHomeDetector.VARIABLE); + } + + @Test + public void testNotSet() throws Exception { + System.clearProperty(Context.INITIAL_CONTEXT_FACTORY); + + assertNull(homeDetector.detect()); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/ProperyHomeDetectorTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/ProperyHomeDetectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a8ffb6a2575f8ff43f559ae99ae600ea18cf1c6f --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/ProperyHomeDetectorTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import network.oxalis.api.filesystem.HomeDetector; +import org.testng.annotations.Test; + +import java.io.File; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * @author erlend + */ +public class ProperyHomeDetectorTest { + + private HomeDetector homeDetector = new PropertyHomeDetector(); + + @Test + public void testFromJavaSystemProperty() { + String path = new File("/some/system/path2").getAbsolutePath(); + String backup = System.getProperty(PropertyHomeDetector.VARIABLE); + + try { + System.clearProperty(PropertyHomeDetector.VARIABLE); + File oxalis_home = homeDetector.detect(); + assertNull(oxalis_home); + + System.setProperty(PropertyHomeDetector.VARIABLE, ""); + oxalis_home = homeDetector.detect(); + assertNull(oxalis_home); + + System.setProperty(PropertyHomeDetector.VARIABLE, path); + oxalis_home = homeDetector.detect(); + assertEquals(oxalis_home.getAbsolutePath(), path); + } finally { + if (backup == null) backup = ""; // prevent null pointer exception + System.setProperty(PropertyHomeDetector.VARIABLE, backup); + } + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/TestableInitialContextFactory.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/TestableInitialContextFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..d2289916b0809656fa25554a2211c9b7d758537a --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/TestableInitialContextFactory.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +/** + * Define a fake JNDI context factory, holding a scaled down Context with just enough power to make the test cases work. + * + * @author thore + */ +public class TestableInitialContextFactory implements InitialContextFactory { + + private static Context context; + + static { + try { + context = new InitialContext(true) { + Map bindings = new HashMap<>(); + + @Override + public void bind(String name, Object obj) { + bindings.put(name, obj); + } + + @Override + public Object lookup(String name) { + return bindings.get(name); + } + + @Override + public void unbind(String name) { + bindings.remove(name); + } + + }; + } catch (NamingException ex) { + throw new IllegalStateException(ex); + } + } + + @Override + public Context getInitialContext(Hashtable environment) { + return context; + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/UserHomeDetectorTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/UserHomeDetectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..61e5a1d000a371f7dc322e3c406feb7d41bff701 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/filesystem/detector/UserHomeDetectorTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.filesystem.detector; + +import network.oxalis.api.filesystem.HomeDetector; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @author erlend + */ +public class UserHomeDetectorTest { + + private HomeDetector homeDetector = new UserHomeDetector(); + + private String backup; + + @BeforeClass + public void beforeClass() { + backup = System.getProperty("user.home"); + } + + @AfterClass + public void afterClass() { + System.setProperty("user.home", backup); + } + + @Test + public void valid() throws Exception { + Path path = Paths.get(getClass().getResource("/.oxalis").toURI()).getParent(); + System.setProperty("user.home", path.toAbsolutePath().toString()); + + Assert.assertNotNull(homeDetector.detect()); + } + + @Test + public void invalid() { + System.setProperty("user.home", "/invalid"); + + Assert.assertNull(homeDetector.detect()); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/guice/GuiceModuleLoaderTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/guice/GuiceModuleLoaderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..40e1ef8e65eca1ac8fe3a83b9c833f375355ef59 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/guice/GuiceModuleLoaderTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.guice; + +import org.testng.annotations.Test; + +public class GuiceModuleLoaderTest { + + @Test + public void simpleConstructor() { + new GuiceModuleLoader(); + } + + @Test + public void simple() { + GuiceModuleLoader.initiate(); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/guice/GuiceServiceLoaderTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/guice/GuiceServiceLoaderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..539e9803b2b9bfa4ca8d3f93c35a8ff09ece5084 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/guice/GuiceServiceLoaderTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.guice; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.api.persist.PayloadPersister; +import network.oxalis.api.persist.ReceiptPersister; +import network.oxalis.api.timestamp.TimestampProvider; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.util.List; + +/** + * @author erlend + */ +public class GuiceServiceLoaderTest { + + private GuiceServiceLoader serviceLoader; + + private ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + @BeforeClass + public void beforeClass() { + Injector injector = Guice.createInjector(); + serviceLoader = injector.getInstance(GuiceServiceLoader.class); + } + + @Test + public void simple() { + List providers = serviceLoader.load(TimestampProvider.class, classLoader); + + Assert.assertEquals(providers.size(), 1); + Assert.assertTrue(providers.get(0) instanceof SampleTimestampProvider); + } + + @Test + public void noneDetected() { + Assert.assertEquals(serviceLoader.load(PayloadPersister.class, classLoader).size(), 0); + } + + @Test(expectedExceptions = OxalisLoadingException.class) + public void triggerException() { + serviceLoader.load(ReceiptPersister.class, classLoader); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/guice/SampleTimestampProvider.java b/oxalis-commons/src/test/java/network/oxalis/commons/guice/SampleTimestampProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..a262de9e38ef9f2b400598a49dae60db239a92ec --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/guice/SampleTimestampProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.guice; + +import network.oxalis.api.lang.TimestampException; +import network.oxalis.api.model.Direction; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.api.timestamp.TimestampProvider; + +/** + * Class used by {@link GuiceServiceLoaderTest}. + * + * @author erlend + */ +public class SampleTimestampProvider implements TimestampProvider { + + @Override + public Timestamp generate(byte[] content, Direction direction) throws TimestampException { + return null; + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/http/ApacheHttpModuleTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/http/ApacheHttpModuleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e7266215c347e2292e52a2e4c48f3fb25bc79628 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/http/ApacheHttpModuleTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.http; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.apache.http.impl.client.CloseableHttpClient; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.io.IOException; + +@Guice(modules = {GuiceModuleLoader.class}) +public class ApacheHttpModuleTest { + + @Inject + private Provider httpClientProvider; + + @Test + public void simple() throws IOException { + try (CloseableHttpClient httpClient1 = httpClientProvider.get(); + CloseableHttpClient httpClient2 = httpClientProvider.get()) { + + Assert.assertNotNull(httpClient1); + Assert.assertNotNull(httpClient2); + + Assert.assertNotSame(httpClient1, httpClient2); + } + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/http/HttpConfTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/http/HttpConfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..33c278b442bcf5f716600e8a9274dfe1548fda7f --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/http/HttpConfTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.http; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class HttpConfTest { + + @Test + public void simpleValueOf() { + Assert.assertEquals(HttpConf.valueOf("POOL_TOTAL"), HttpConf.POOL_TOTAL); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/io/PeekingInputStreamTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/io/PeekingInputStreamTest.java new file mode 100644 index 0000000000000000000000000000000000000000..96160d3a9a9ec042dd07e56775ccadcb399c8aea --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/io/PeekingInputStreamTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.io; + +import com.google.common.io.ByteStreams; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +public class PeekingInputStreamTest { + + @Test + public void simple() throws IOException { + PeekingInputStream peekingInputStream = new PeekingInputStream( + new ByteArrayInputStream("Hello World!".getBytes())); + + byte[] bytes1 = new byte[5]; + peekingInputStream.read(bytes1); + Assert.assertEquals(new String(bytes1), "Hello"); + + Assert.assertEquals(new String(ByteStreams.toByteArray(peekingInputStream.newInputStream())), "Hello World!"); + } +} + diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/io/UnclosableInputStreamTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/io/UnclosableInputStreamTest.java new file mode 100644 index 0000000000000000000000000000000000000000..02e88b9e7047496acd2382e854d31867dc6ffa0f --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/io/UnclosableInputStreamTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.io; + +import com.google.common.io.ByteStreams; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class UnclosableInputStreamTest { + + @Test + public void simple() throws IOException { + InputStream inputStream = new ByteArrayInputStream("Hello World!".getBytes()); + + try (InputStream content = new UnclosableInputStream(inputStream)) { + ByteStreams.exhaust(content); + } // close() is called here. + + Assert.assertEquals(inputStream.read(), -1); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/logging/LogbackConfiguratorTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/logging/LogbackConfiguratorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9c830102cb6d23b1b660f6260b50c1cb56c5c98c --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/logging/LogbackConfiguratorTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.logging; + +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.io.PrintStream; + +/** + * User: steinar + * Date: 04.10.12 + * Time: 13:42 + */ +@Guice(modules = {GuiceModuleLoader.class}) +public class LogbackConfiguratorTest { + + public static final String FILE_NAME = "logback-test.xml"; + + private PrintStream out; + + @BeforeMethod + public void redirectStdoutAndStderr() { + out = System.out; + } + + @AfterTest + public void restoreOutputStreams() { + System.setOut(out); + } + + @Test + public void locateConfigurationFileInClassPath() { + // TODO + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/logging/LoggingConfTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/logging/LoggingConfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a7bffa8c13f4085523149e820a7bc71a4c37f160 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/logging/LoggingConfTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.logging; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class LoggingConfTest { + + @Test + public void simpleValueOf() { + Assert.assertEquals(LoggingConf.valueOf("CONFIG"), LoggingConf.CONFIG); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/mode/ModeModuleTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/mode/ModeModuleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ce01a4e2639abc25e9092fe11f2b43c676810734 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/mode/ModeModuleTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.mode; + +import com.google.inject.Inject; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.vefa.peppol.common.code.Service; +import network.oxalis.vefa.peppol.security.api.CertificateValidator; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.security.cert.X509Certificate; + +@Guice(modules = {GuiceModuleLoader.class}) +public class ModeModuleTest { + + @Inject + private CertificateValidator certificateValidator; + + @Inject + private X509Certificate certificate; + + @Test + public void simple() throws Exception { + certificateValidator.validate(Service.AP, certificate); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/persister/DefaultPersisterHandlerTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/persister/DefaultPersisterHandlerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6c67974a18f38f34436e372852187f89b2cb087a --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/persister/DefaultPersisterHandlerTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persister; + +import com.google.inject.Inject; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +@Guice(modules = GuiceModuleLoader.class) +public class DefaultPersisterHandlerTest { + + @Inject + private PersisterHandler persisterHandler; + + @Test + public void simple() { + Assert.assertNotNull(persisterHandler); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/persister/DefaultPersisterTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/persister/DefaultPersisterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7f8c1ca101bdbb46f3852d9cb53a3a8686efd44b --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/persister/DefaultPersisterTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persister; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.api.persist.PayloadPersister; +import network.oxalis.api.persist.ReceiptPersister; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +@Guice(modules = GuiceModuleLoader.class) +public class DefaultPersisterTest { + + @Inject + @Named("default") + private PayloadPersister payloadPersister; + + @Inject + @Named("default") + private ReceiptPersister receiptPersister; + + @Test + public void simple() { + Assert.assertNotNull(payloadPersister); + Assert.assertNotNull(receiptPersister); + } + +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/persister/NoopPersisterTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/persister/NoopPersisterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b37987d685ab26b010b8711b4a5d39b0c6ff5c6d --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/persister/NoopPersisterTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persister; + +import network.oxalis.commons.persist.NoopPersister; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; + +/** + * @author erlend + */ +public class NoopPersisterTest { + + private NoopPersister persister = new NoopPersister(); + + @Test + public void simple() throws Exception { + Assert.assertNull(persister.persist(null, null, new ByteArrayInputStream("Hello World".getBytes()))); + persister.persist(null, null); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/persister/TempPersisterTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/persister/TempPersisterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..79dd285177306a86970fb2a06a00d70067ed88f6 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/persister/TempPersisterTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.persister; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.api.persist.PayloadPersister; +import network.oxalis.api.persist.ReceiptPersister; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +@Guice(modules = GuiceModuleLoader.class) +public class TempPersisterTest { + + @Inject + @Named("temp") + private PayloadPersister payloadPersister; + + @Inject + @Named("temp") + private ReceiptPersister receiptPersister; + + @Test + public void simple() { + Assert.assertNotNull(payloadPersister); + Assert.assertNotNull(receiptPersister); + } + +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/plugin/PluginTestModule.java b/oxalis-commons/src/test/java/network/oxalis/commons/plugin/PluginTestModule.java new file mode 100644 index 0000000000000000000000000000000000000000..4bbec81b39b656f8340f0f3c4b17fb71f77ad6cc --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/plugin/PluginTestModule.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.plugin; + +import com.google.inject.Inject; +import network.oxalis.api.lang.OxalisPluginException; +import network.oxalis.api.persist.PayloadPersister; +import network.oxalis.api.plugin.PluginFactory; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author steinar + * Date: 24.01.2017 + * Time: 10.45 + * @author erlend + */ +@Guice(modules = {GuiceModuleLoader.class}) +public class PluginTestModule { + + @Inject + private PluginFactory pluginFactory; + + @Test(expectedExceptions = OxalisPluginException.class) + public void pluginNotFound() throws Exception { + pluginFactory.newInstance(PayloadPersister.class); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/sbdh/SbdhHeaderParserTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/sbdh/SbdhHeaderParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6eb5e71b19c21e0cd8227889a8b9128034ced495 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/sbdh/SbdhHeaderParserTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.sbdh; + +import network.oxalis.api.header.HeaderParser; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.commons.header.SbdhHeaderParser; +import network.oxalis.vefa.peppol.common.model.Header; +import org.testng.annotations.Test; + +import java.io.InputStream; + +import static org.testng.Assert.assertNull; + +/** + * @author steinar + * Date: 24.06.15 + * Time: 15.58 + */ +public class SbdhHeaderParserTest { + + public static final String EHF_INVOICE_NO_SBDH_XML = "/ehf-invoice-no-sbdh.xml"; + + private static final HeaderParser PARSER = new SbdhHeaderParser(); + + @Test + public void simpleConstructor() { + new SbdhHeaderParser(); + } + + @Test(expectedExceptions = OxalisContentException.class) + public void parseXmlFileWithoutSBDH() throws OxalisContentException { + InputStream resourceAsStream = getClass().getResourceAsStream(EHF_INVOICE_NO_SBDH_XML); + + Header sbdh = PARSER.parse(resourceAsStream); + assertNull(sbdh); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/security/CertificateUtilsTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/security/CertificateUtilsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3c160d6b235e68f981e4638b8b7ac9447bc92761 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/security/CertificateUtilsTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.security; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class CertificateUtilsTest { + + @Test + public void simpleConstructor() { + new CertificateUtils(); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/security/KeyStoreConfTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/security/KeyStoreConfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a9569bf479d36d913b16889b42c9cb319411edb3 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/security/KeyStoreConfTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.security; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class KeyStoreConfTest { + + @Test + public void simpleValueOf() { + Assert.assertEquals(KeyStoreConf.valueOf("PATH"), KeyStoreConf.PATH); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/settings/SettingsTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/settings/SettingsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..80ae0486ce199b950e54c2f7da14f6504f1f5f8e --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/settings/SettingsTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.settings; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.CreationException; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.util.Types; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Settings; +import network.oxalis.api.settings.Title; +import network.oxalis.commons.guice.OxalisModule; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class SettingsTest { + + private Injector injector; + + private Settings settings; + + private static final int INT_VALUE = 200; + + @BeforeClass + @SuppressWarnings("unchecked") + public void beforeClass() { + injector = Guice.createInjector(new OxalisModule() { + @Override + protected void configure() { + SettingsBuilder.with(binder(), TestConf.class); + + bind(Config.class).toInstance(ConfigFactory.parseMap( + ImmutableMap.of("test.value", String.valueOf(INT_VALUE)))); + } + }); + + settings = injector.getInstance((Key>) + Key.get(Types.newParameterizedType(Settings.class, TestConf.class))); + } + + @Test + public void simple() { + Assert.assertEquals(settings.getInt(TestConf.WITH_VALUE), INT_VALUE); + Assert.assertEquals(settings.getString(TestConf.WITH_DEFAULT), "Test"); + Assert.assertNull(settings.getString(TestConf.WITH_NULLABLE)); + Assert.assertEquals("Test", settings.getNamed(TestConf.WITH_DEFAULT).value()); + } + + /** + * Make sure exception is triggered if required configuration is not found. + */ + @Test(expectedExceptions = CreationException.class) + public void invalidKey() { + injector.createChildInjector(new OxalisModule() { + @Override + protected void configure() { + SettingsBuilder.with(binder(), TestWithErrorConf.class); + } + }); + } + + @Title("Testing without valid key") + public enum TestWithErrorConf { + + @Path("oxalis.common.testing.invalid.key") + KEY + + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/settings/TestConf.java b/oxalis-commons/src/test/java/network/oxalis/commons/settings/TestConf.java new file mode 100644 index 0000000000000000000000000000000000000000..14ccdd1072243308ec1d8c43cde3165f7c59b3d3 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/settings/TestConf.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.settings; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Nullable; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("Testing") +public enum TestConf { + + @Path("test.nullable") + @Nullable + WITH_NULLABLE, + + @Path("test.default") + @DefaultValue("Test") + WITH_DEFAULT, + + @Path("test.value") + WITH_VALUE, + +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/statistics/NoopStatisticsServiceTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/statistics/NoopStatisticsServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4a6f1106382d29efa4e390da31622685c4658422 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/statistics/NoopStatisticsServiceTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.statistics; + +import network.oxalis.api.statistics.StatisticsService; +import org.testng.annotations.Test; + +public class NoopStatisticsServiceTest { + + private StatisticsService statisticsService = new NoopStatisticsService(); + + @Test + public void simple() { + statisticsService.persist(null, null, null); + statisticsService.persist(null); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/statistics/StatisticsConfTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/statistics/StatisticsConfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d44ebfd99bcf4235c1522fee8bafbd0a8bc2e147 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/statistics/StatisticsConfTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.statistics; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class StatisticsConfTest { + + @Test + public void simpleValueOf() { + Assert.assertEquals(StatisticsConf.valueOf("SERVICE"), StatisticsConf.SERVICE); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/statistics/StatisticsModuleTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/statistics/StatisticsModuleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..66547fff5f9231bdc7782a155ae395a85b5b3765 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/statistics/StatisticsModuleTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.statistics; + +import com.google.inject.Inject; +import network.oxalis.api.statistics.StatisticsService; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +@Guice(modules = GuiceModuleLoader.class) +public class StatisticsModuleTest { + + @Inject + private StatisticsService statisticsService; + + @Test + public void simple() { + Assert.assertNotNull(statisticsService); + } + +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/timestamp/SystemTimestampProviderTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/timestamp/SystemTimestampProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..da153ad7941d6a9e210d9e7eeca53bc1551c9791 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/timestamp/SystemTimestampProviderTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.timestamp; + +import com.google.inject.Inject; +import io.opentracing.Tracer; +import network.oxalis.api.model.Direction; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.api.timestamp.TimestampProvider; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +@Guice(modules = {GuiceModuleLoader.class}) +public class SystemTimestampProviderTest { + + @Inject + private TimestampProvider timestampProvider; + + @Inject + private Tracer tracer; + + @Test + public void simpleWithoutTracer() throws Exception { + Timestamp timestamp = timestampProvider.generate("Hello World!".getBytes(), Direction.IN); + + Assert.assertNotNull(timestamp.getDate()); + Assert.assertFalse(timestamp.getReceipt().isPresent()); + } + + @Test + public void simpleWithTracer() throws Exception { + Timestamp timestamp = timestampProvider.generate("Hello World!".getBytes(), Direction.IN, + tracer.buildSpan("test").start()); + + Assert.assertNotNull(timestamp.getDate()); + Assert.assertFalse(timestamp.getReceipt().isPresent()); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/timestamp/TimestampConfTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/timestamp/TimestampConfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..22c4666590227fdb992c22d0ba86cbe6ef929494 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/timestamp/TimestampConfTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.timestamp; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class TimestampConfTest { + + @Test + public void simpleValueOf() { + Assert.assertEquals(TimestampConf.valueOf("SERVICE"), TimestampConf.SERVICE); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/tracing/Slf4jReporterTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/tracing/Slf4jReporterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5cc5a0ab6f9a04a8893c27d4cb206bceb5d3dc2e --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/tracing/Slf4jReporterTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tracing; + +import org.testng.annotations.Test; + +public class Slf4jReporterTest { + + @Test + public void simple() { + new Slf4jReporter().report(null); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/tracing/TraceableTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/tracing/TraceableTest.java new file mode 100644 index 0000000000000000000000000000000000000000..368e29bb8de5aad7c4163ba54cc9910c3a8cbe41 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/tracing/TraceableTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.tracing; + +import io.opentracing.Tracer; +import io.opentracing.noop.NoopTracerFactory; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class TraceableTest { + + @Test + public void simple() { + Tracer tracer = NoopTracerFactory.create(); + + Traceable traceable = new Traceable(tracer) { + }; + + Assert.assertTrue(tracer == traceable.tracer); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/transmission/DefaultTransmissionVerifierTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/transmission/DefaultTransmissionVerifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..059364be97e6b0f75095b9a829d159680db9d6ee --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/transmission/DefaultTransmissionVerifierTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.transmission; + +import com.google.inject.Inject; +import network.oxalis.api.lang.VerifierException; +import network.oxalis.api.model.Direction; +import network.oxalis.api.transmission.TransmissionVerifier; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +@Guice(modules = GuiceModuleLoader.class) +public class DefaultTransmissionVerifierTest { + + @Inject + private TransmissionVerifier transmissionVerifier; + + @Test + public void simple() throws VerifierException { + Assert.assertNotNull(transmissionVerifier); + transmissionVerifier.verify(null, Direction.IN); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/util/ClassUtilsTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/util/ClassUtilsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ee093d3947548c3b5c9b38fab43ed24590ac593e --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/util/ClassUtilsTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.util; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class ClassUtilsTest { + + @Test + public void simpleConstructor() { + new ClassUtils(); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/util/OxalisVersionTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/util/OxalisVersionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7424e70694e04b4578d034dcb897b08ec8051727 --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/util/OxalisVersionTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.util; + +import lombok.extern.slf4j.Slf4j; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertNotNull; + +/** + * @author steinar + * Date: 10.04.13 + * Time: 10:50 + */ +@Slf4j +public class OxalisVersionTest { + + @Test + public void simpleConstructor() { + new OxalisVersion(); + } + + @Test + public void simple() { + assertNotNull(OxalisVersion.getVersion()); + assertNotNull(OxalisVersion.getUser()); + assertNotNull(OxalisVersion.getBuildDescription()); + assertNotNull(OxalisVersion.getBuildId()); + assertNotNull(OxalisVersion.getBuildTimeStamp()); + } + + @Test + public void testGetVersion() throws Exception { + String currentVersion = OxalisVersion.getVersion(); + assertNotNull(currentVersion); + log.info("Current version is '{}'.", currentVersion); + } + + @Test + public void testGetBuildDescription() throws Exception { + String buildDescription = OxalisVersion.getBuildDescription(); + assertNotNull(buildDescription); + log.info("Description is '{}'.", buildDescription); + } + + @Test + public void testBuildTimeStamp() { + String buildTimeStamp = OxalisVersion.getBuildTimeStamp(); + assertNotNull(buildTimeStamp, "Build time stamp not set"); + log.info("Build time stamp is '{}'.", buildTimeStamp); + } +} diff --git a/oxalis-commons/src/test/java/network/oxalis/commons/util/SortablesTest.java b/oxalis-commons/src/test/java/network/oxalis/commons/util/SortablesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..de4a8a2d22da7b092e6f981cf2925b7a72c27afa --- /dev/null +++ b/oxalis-commons/src/test/java/network/oxalis/commons/util/SortablesTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.commons.util; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class SortablesTest { + + @Test + public void simpleConstructor() { + new Sortables(); + } +} diff --git a/oxalis-commons/src/test/resources/.oxalis/.gitkeep b/oxalis-commons/src/test/resources/.oxalis/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-commons/src/test/resources/META-INF/services/network.oxalis.api.persist.ReceiptPersister b/oxalis-commons/src/test/resources/META-INF/services/network.oxalis.api.persist.ReceiptPersister new file mode 100644 index 0000000000000000000000000000000000000000..443d9ab34e6d126f5a03cea379ee410a83960d8d --- /dev/null +++ b/oxalis-commons/src/test/resources/META-INF/services/network.oxalis.api.persist.ReceiptPersister @@ -0,0 +1 @@ +some.test.Class \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/META-INF/services/network.oxalis.api.timestamp.TimestampProvider b/oxalis-commons/src/test/resources/META-INF/services/network.oxalis.api.timestamp.TimestampProvider new file mode 100644 index 0000000000000000000000000000000000000000..5d6b6a9d67e1a0dabd12c0c955550ef71d6ba133 --- /dev/null +++ b/oxalis-commons/src/test/resources/META-INF/services/network.oxalis.api.timestamp.TimestampProvider @@ -0,0 +1 @@ +network.oxalis.commons.guice.SampleTimestampProvider \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/difi-smp-result.xml b/oxalis-commons/src/test/resources/difi-smp-result.xml new file mode 100644 index 0000000000000000000000000000000000000000..0b48b018d4f53c1bb1e55ff0f65cfe308ccca81c --- /dev/null +++ b/oxalis-commons/src/test/resources/difi-smp-result.xml @@ -0,0 +1,67 @@ + + +9908:810418052urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol5a:ver1.0::2.0urn:www.cenbii.eu:profile:bii05:ver1.0https://test-aksesspunkt.difi.no/as2true12013-11-08T01:00:00.000+01:002015-11-08T01:00:00.000+01:00MIIEYzCCA0ugAwIBAgIQdsW7SZfoTYtho20e1yuuXTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQG +EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQLExZG +T1IgVEVTVCBQVVJQT1NFUyBPTkxZMSQwIgYDVQQDExtQRVBQT0wgQUNDRVNTIFBPSU5UIFRFU1Qg +Q0EwHhcNMTQxMTMwMDAwMDAwWhcNMTYxMTI5MjM1OTU5WjA1MQswCQYDVQQGEwJOTzENMAsGA1UE +CgwERElGSTEXMBUGA1UEAwwOQVBQXzEwMDAwMDAwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDWKst/fUruM6MsOsFeoH57wpxPzvm9vfQIu4jtmmGxrJQCx4Ddici7gPWblFwSoJhj +p2jee0ck/BFGGXa/FFMLh30AfdgFRSSrriwV7p45PyqzMJM63lg2vb2OYRV4uDZRp7dCBgdNOXsP +LeSyJUGFqbAEFhcw3sDNTrF0WkDysKwX/KiNDcCrOXbhhKweawrxp6N4ayupCbhzd/MAOqbSaSTg +8jysLPRs80LRFfLt88oiBcJxRBQzbkedU9e3WFs0UnzEdkQn2Ea6YKyXKtK/GbaetBrYbH2sAtYo +RnqEKls1fsFNicPJnmjwePc8R+hNOXWUTwGGxJvuG91uCLdXAgMBAAGjggElMIIBITAJBgNVHRME +AjAAMAsGA1UdDwQEAwIDuDB2BgNVHR8EbzBtMGugaaBnhmVodHRwOi8vcGlsb3RvbnNpdGVjcmwu +dmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNlblBpbG90T3BlblBFUFBPTEFDQ0VT +U1BPSU5UQ0EvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBT3losZTK7iViEAvob9ekesncoFdTAd +BgNVHQ4EFgQUbc5WCBfsQS2KkznlkU83EtHvb7MwOgYIKwYBBQUHAQEELjAsMCoGCCsGAQUFBzAB +hh5odHRwOi8vcGlsb3Qtb2NzcC52ZXJpc2lnbi5jb20wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJ +KoZIhvcNAQELBQADggEBAAHzziSeejvdFuQQfYTsHq8cqPBxHXHmD783HFIhEJ0PEBbI8IGGsolp +W3DeKzmteK3SmrLYNoKRoGi3bklIRlujTSt8fwvMrEFAbQ4o14/OFXvp3NA6heOKhzU4Lqh3DGGW +z/bVbZnl/nDQ8ynm4MeJvzqksfsyXlTpWTf64NgOZ2ntZq/ifbbISk5kRqKiX2zC/0RNe+Cwdj+q +aJQvwE2MwmauGABolFH/dUTjECZY23Ho4CcIa1NzvAp25S2w9rn8/FfBEdcnVnzXAlBEU3bCBcfG +2m0+Cy6Y8C5OI0mF83Xa/sYS86Ie+jZPRc1L9LYIhhD3gU8/7fZ3DvMFFPk=Access point for testingaksesspunkt@difi.noERhE31+o810iHOh9vqmbRrR6/ys=kqJN0jekn+ksDklaldoHdE5tgS1CNTE73+gaV66drkTjZJ6cuwMfQGVqxbdniwVwesSZOIiaZJV+ +JCDsSL6qq2FIo7qmp5zklDlNaGZzkyPOQH+DzCASQ2Vpd0Bg4IKYjH6tXww5UM1oogco6V7OOxfg +TddB21KlF+vaWsvkh64srzHHb43giOcki1cGE0wtH2BSzqsd97SI3enb9cIrsrTxgCHze+6KBXaQ +ybIfydqr4gjvfB/wlENPaZPpskKDzEEdcaDpzhwCBUyUKdXaIBehllk24kc30+CWSUbJIYDd7eHa ++umV0r/I6vHSo+AKox8ry0iugDYt+UCW83Estw==CN=SMP_1000000005,O=DIFI,C=NOMIIEgDCCA2igAwIBAgIQMrLCi6vy9yCkE4koH/oh5zANBgkqhkiG9w0BAQsFADCBizELMAkGA1UE +BhMCREsxJzAlBgNVBAoTHk5BVElPTkFMIElUIEFORCBURUxFQ09NIEFHRU5DWTEfMB0GA1UECxMW +Rk9SIFRFU1QgUFVSUE9TRVMgT05MWTEyMDAGA1UEAxMpUEVQUE9MIFNFUlZJQ0UgTUVUQURBVEEg +UFVCTElTSEVSIFRFU1QgQ0EwHhcNMTQxMTMwMDAwMDAwWhcNMTYxMTI5MjM1OTU5WjA1MQswCQYD +VQQGEwJOTzENMAsGA1UECgwERElGSTEXMBUGA1UEAwwOU01QXzEwMDAwMDAwMDUwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCszgRipz35U32rbjCqdfHDYbiMqx5CF4Fs66hwpDUXwTay +qANvbIHo0+RW69opD9tm5Y7Gx+f0jjzYC5QOlHVXpTOPJwdozaJgqlJrlTvgktqYD1bOo+7d6ORS +szfEZSTAKRE3N3BvaTvIecDvo8UKHrFQEwdOu1tvJxN0pt9/PyFpByGMh8xJS6ThcEyePDI4PTsH +5hEzi/XLBuX0ZM6Uc0MTkyOIKzPtI//0eBFBGOzTtAXT/hclpUbX6qDhbbtnDfD+Agti45fqotb7 +TrmNGwqNepks1kEsvNVNA0ui+1zIsMlp/hL/xHdKS9Ar+ozkia2iU6qJLYFPbHy+4NZ5AgMBAAGj +ggEzMIIBLzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDuDCBgwYDVR0fBHwwejB4oHagdIZyaHR0cDov +L3BpbG90b25zaXRlY3JsLnZlcmlzaWduLmNvbS9EaWdpdGFsaXNlcmluZ3NzdHlyZWxzZW5QaWxv +dE9wZW5QRVBQT0xTRVJWSUNFTUVUQURBVEFQVUJMSVNIRVJDQS9MYXRlc3RDUkwuY3JsMB8GA1Ud +IwQYMBaAFODHhUA1Ov0c8/Zewh8w0PJkoQJ3MB0GA1UdDgQWBBRRGp0gAxOFHgEhOdEg0/tZHMjB +qDA6BggrBgEFBQcBAQQuMCwwKgYIKwYBBQUHMAGGHmh0dHA6Ly9waWxvdC1vY3NwLnZlcmlzaWdu +LmNvbTATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAV3eQPNF71xQtwc8C +GdcIsahP3iVmqEpQH2av5gkKNBLqMjwZ+i8h1tjZPZyfG54C7tTpMeH7XwS/sEO6Xhc48HabreLt +lDAzGv4kjQPHQJvOdkNrBn4wOC7bZag5DO6lDAKVsSwBJbhHJL9uI2EPSqrI/H7mSj9exAwi15FW +Y3HeEay6p+47DMdt3V1pZ1hyYVAuUCVkPqdV0g9ADHjCdHRAn73KXqJHM6siMp7ekWo+poCmwiMC +tV0oro/6G/aIdDXxDVE37HogaBA8MqyeQL9KTx7VfXjqWi1bHWJlbzvmnQCjCqtPklch3VbI9V0r +Y7WcmklvEl3flp7lJd9FAw== \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/ehf-invoice-no-sbdh.xml b/oxalis-commons/src/test/resources/ehf-invoice-no-sbdh.xml new file mode 100644 index 0000000000000000000000000000000000000000..cafbc9aff063b36ccab7881fd40227d1ca02227f --- /dev/null +++ b/oxalis-commons/src/test/resources/ehf-invoice-no-sbdh.xml @@ -0,0 +1,289 @@ + + + + + + + 2.0 + + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + 3456 + 2013-11-05 + Levering: NAV HMS Nord-Trøndelag - Kikrkegata 2 C - 7600 Levanger + NOK + + 1671018 + + + + 9908:991974466 + + Comfort Audio AS + + + Postboks 304 + SANDEFJORD + 3201 + + NO + + + + 991974466MVA + + + VAT + + + + Comfort Audio AS + 991974466 + + + 3462 + 95987910 + alexander.delgado@comfortaudio.com + + + + + + 9908:889640782 + + 10019 + + + NAV Økonomitjeneste + + + Sognefjordveien 56 + LEIKANGER + 6863 + + NO + + + + NAV Økonomitjeneste + 889640782 + + + SRA4711 + + + + + 2013-11-05 + + + Sognefjordveien 56 + LEIKANGER + 6863 + + NO + + + + + + 31 + 2013-12-05 + + 60210741723 + + + + + 4105.00 + + 16420.00 + 4105.00 + + S + 25.00 + + VAT + + + + + + 16420.00 + 16420.00 + 20525.00 + 0.00 + 20525.00 + + + + 1 + 1.00 + 5890.00 + + Comfort Digisystem DM10 (HMS nr. 160723) + + F00209 + + + S + 25.00 + + VAT + + + + + 5890.00 + + + + + 2 + 1.00 + 425.00 + + Veske Digisystem (HMS nr. 161381) + + F00493 + + + S + 25.00 + + VAT + + + + + 425.00 + + + + + 3 + 1.00 + 190.00 + + Nettadapter A11 1-2 enheter (HMS nr. 161752) + + F00359 + + + S + 25.00 + + VAT + + + + + 190.00 + + + + + 4 + 1.00 + 1795.00 + + Hodebøylemikrofon (HMS nr. 161759) + + F00243 + + + S + 25.00 + + VAT + + + + + 1795.00 + + + + + 5 + 2.00 + 950.00 + + Ladestativ DM/DH (HMS nr. 161760) + + F00254 + + + S + 25.00 + + VAT + + + + + 475.00 + + + + + 6 + 1.00 + 7170.00 + + Comfort Digisystem DM90 m/BT (HMS nr. 193853) + + F00684 + + + S + 25.00 + + VAT + + + + + 7170.00 + + + diff --git a/oxalis-commons/src/test/resources/logback-oxalis-inbound.xml b/oxalis-commons/src/test/resources/logback-oxalis-inbound.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-commons/src/test/resources/logback-oxalis-inbound.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-commons/src/test/resources/logback-test.xml b/oxalis-commons/src/test/resources/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-commons/src/test/resources/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-commons/src/test/resources/oxalis-web.properties b/oxalis-commons/src/test/resources/oxalis-web.properties new file mode 100644 index 0000000000000000000000000000000000000000..1aaa909e1816cb868129585e483eac523acbf53f --- /dev/null +++ b/oxalis-commons/src/test/resources/oxalis-web.properties @@ -0,0 +1,27 @@ +# +# Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) +# +# Licensed under the EUPL, Version 1.1 or – as soon they +# will be approved by the European Commission - subsequent +# versions of the EUPL (the "Licence"); +# +# You may not use this work except in compliance with the Licence. +# +# You may obtain a copy of the Licence at: +# +# https://joinup.ec.europa.eu/community/eupl/og_page/eupl +# +# Unless required by applicable law or agreed to in +# writing, software distributed under the Licence is +# distributed on an "AS IS" basis, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. +# See the Licence for the specific language governing +# permissions and limitations under the Licence. +# + +# +# Test version of oxalis-web.properties +# +oxalis.inbound.message.store TEST +oxalis.keystore TEST-KEY-STORE \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/oxalis_home/fake-oxalis.conf b/oxalis-commons/src/test/resources/oxalis_home/fake-oxalis.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-commons/src/test/resources/oxalis_home/logback-test.xml b/oxalis-commons/src/test/resources/oxalis_home/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-commons/src/test/resources/oxalis_home/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-commons/src/test/resources/peppol-bis-invoice-sbdh.xml b/oxalis-commons/src/test/resources/peppol-bis-invoice-sbdh.xml new file mode 100644 index 0000000000000000000000000000000000000000..9881f31d5e31663225451cede9c5e11b8112b7fc --- /dev/null +++ b/oxalis-commons/src/test/resources/peppol-bis-invoice-sbdh.xml @@ -0,0 +1,150 @@ + + + + 1.0 + + 0007:5567125082 + + + 0007:4455454480 + + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + 2.0 + 1070e7f0-3bae-11e3-aa6e-0800200c9a66 + Invoice + 2013-02-19T05:10:10 + + + + DOCUMENTID + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + + PROCESSID + urn:www.cenbii.eu:profile:bii04:ver1.0 + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 1 + 2012-06-08 + 380 + 2012-06-08 + SEK + SOPE + + + + 5567125082 + + + Ecru Consulting + + + Gamla Brogatan + 29 + Stockholm + 11120 + + SE + + + + SE556712508201 + + VAT + + + + 810418052 + + + Martin + Forsberg + + + + + + + 4455454480 + + + EKONOMISTYRNINGSVERKET (NATIONAL FINANCIAL MANAGEMENT AUTHORITY) + + + 45316 + EFFEKTIV ADMINISTRATION + STOCKHOLM + 104 30 + + SE + + + + 976098897 + + + 08 - 123456 + 08-123457 + infomail@esv.se + + + SOREN + PEDERSEN + + + + + 31 + 2012-06-23 + + 5955559 + + + BGABSESS + + + + + + 0.25 + + 1 + 0.25 + + S + 25 + + VAT + + + + + + 1 + 1 + 1.25 + 1.25 + + + 1 + 1 + 1 + + 1 + + + TEST AV PEPPOL-FAKTURA + + + 1 + 1 + + + + diff --git a/oxalis-commons/src/test/resources/reference.conf b/oxalis-commons/src/test/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..ca3af1f6a24b7efef9fb638d6edde338932bd5ee --- /dev/null +++ b/oxalis-commons/src/test/resources/reference.conf @@ -0,0 +1 @@ +defaults = {} diff --git a/oxalis-commons/src/test/resources/sample-sbd-with-asic.xml b/oxalis-commons/src/test/resources/sample-sbd-with-asic.xml new file mode 100644 index 0000000000000000000000000000000000000000..234bbb9e3fc53bee183c4ba5537566ccf00d6514 --- /dev/null +++ b/oxalis-commons/src/test/resources/sample-sbd-with-asic.xml @@ -0,0 +1,154 @@ + + + + 1.0 + + 9908:810018909 + + + 9908:810418052 + + + urn:oasis:names:specification:ubl:schema:xsd:Tender-2 + 2.1 + FA4A6819-6149-4134-95C3-C53A65338EB6 + Tender + 2015-07-26T20:08:00+01:00 + + + 1 + + application/vnd.etsi.asic-e+zip + #asic + ASiC archive containing the business documents. + + + + + PROCESSID + urn:www.cenbii.eu:profile:bii46:ver3.0 + + + DOCUMENTID + + urn:oasis:names:specification:ubl:schema:xsd:Tender-2::Tender##urn:www.cenbii.eu:transaction:biitrdm090:ver3.0::2.1 + + + + + + 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 + QS1JTkYvbWFuaWZlc3QueG1srZHBasMwDIbveQrj63CS3jaTtLc9wfYAaqyuBls2llKSPf2clMFg + MHqYbhK/vv8XGk5LDOqGhX2iUR/aXiukKTlPH6N+f3s1z1qxADkIiXDUK7I+HZuB+GAjkL8gi6oM + YltHo54L2QTsawsR2cpkU0ZyaZojkti79HvTbobHRtXaiRcf0FRZWdXeziGYDHIddaf3SUTnwcia + axTIOfgJpCbvbuRaFPZttZ4MPn36rLuHwHx217am+pu/CR7jSXGxf+kNz+foxUi9HYthiDngf/rc + iaYguIitLPIbLLhIlwN42phD9/Nnx+YLUEsHCFuZArnqAAAA+wEAAFBLAQIKAAoAAAgAAI1ZMEeK + IflFHwAAAB8AAAAIAAAAKAAAAAAAAAAAAAAAAABtaW1ldHlwZW1pbWV0eXBlPWFwcGxpY2F0aW9u + L3ZuZC5ldHNpLmFzaWMtZSt6aXBQSwECFAAUAAgICACNWTBH1R7KSasEAADfCwAACAAAAAAAAAAA + AAAAAABFAAAAc2JkaC54bWxQSwECFAAUAAgICACNWTBHqhrKndAGAABLEwAAIAAAAAAAAAAAAAAA + AAAmBQAAdHJkbTA5MC1zdWJtaXQtdGVuZGVyLXNhbXBsZS54bWxQSwECFAAUAAgICACNWTBHGHwq + qDcAAAA5AAAAEQAAAAAAAAAAAAAAAABEDAAAc2FtcGxlLXJlYWRtZS50eHRQSwECFAAUAAgICACN + WTBHjEPERu8BAABwBAAAGQAAAAAAAAAAAAAAAAC6DAAATUVUQS1JTkYvYXNpY21hbmlmZXN0Lnht + bFBLAQIUABQACAgIAI1ZMEeS19UY5gUAAGEHAAA7AAAAAAAAAAAAAAAAAPAOAABNRVRBLUlORi9z + aWduYXR1cmUtNGFjMjIwYTUtYzVkMi00YmFlLTliZmItODVhNjdhMDY3ZTZjLnA3c1BLAQIUABQA + CAgIAI1ZMEdbmQK56gAAAPsBAAAVAAAAAAAAAAAAAAAAAD8VAABNRVRBLUlORi9tYW5pZmVzdC54 + bWxQSwUGAAAAAAcABwAUAgAAbBYAACgAbWltZXR5cGU9YXBwbGljYXRpb24vdm5kLmV0c2kuYXNp + Yy1lK3ppcA== + + + diff --git a/oxalis-commons/src/test/resources/sample-stats-response.xml b/oxalis-commons/src/test/resources/sample-stats-response.xml new file mode 100644 index 0000000000000000000000000000000000000000..9fa68e231e59ff78f049359d8a51931e6245718f --- /dev/null +++ b/oxalis-commons/src/test/resources/sample-stats-response.xml @@ -0,0 +1,56 @@ + + + + + + AP0001 + IN + 2013-01-29T13 + 9908:810418052 + CH1 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 123 + + + AP0001 + IN + 2013-01-29T13 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 321 + + + xledger + OUT + 2013-04-17T02 + 9908:880526642 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + + + \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/smp-response-for-971033533.xml b/oxalis-commons/src/test/resources/smp-response-for-971033533.xml new file mode 100644 index 0000000000000000000000000000000000000000..9fe23d8c983e4aa1b111d0fc0ddfc96132145ad2 --- /dev/null +++ b/oxalis-commons/src/test/resources/smp-response-for-971033533.xml @@ -0,0 +1,43 @@ +9908:971033533urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0::2.1urn:www.cenbii.eu:profile:bii04:ver2.0https://peppol.itella.net/peppol-ap-inbound/as2false12013-03-01Z2022-03-01ZMIIEPjCCAyagAwIBAgIQbrlUH4LjKvChN2dbzWpkIjANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQG +EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQDExZQ +RVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTEzMTAyMjAwMDAwMFoXDTE1MTAyMjIzNTk1OVowQzEL +MAkGA1UEBhMCRkkxFzAVBgNVBAMMDkFQUF8xMDAwMDAwMDIxMRswGQYDVQQKDBJJdGVsbGEgSW5m +b3JtYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw0JBmkDm2GXKwQRKOrjEr +yRSdxDJBsO4lozQ/IthaTj+2UYZqS6umouYaD5/Ig6f43LlrtmhgViQN95+2IDcdF2X5H93joDUt +M2JgwwSrSy//IBdVJgdIOY0LW+pGSIBaN4WbkZ0UkpPOyuW/2JPggwhxIghfyiJqm6ThLc6nz67z +FwRcFj+Kua/1FZ6APMVq+WE2vKvnMF0JToZxVlyi5CyGBKXDW9uJWneK+6idiztlQ91Z+6Jl2Phs +csNo3chT5N+L9vXX+bSgKhkv9OBPODK1k+x+4+P9Mh9rJLg2AgyNIeXd1iLcnmknERrmRpfigbMz +5ECpNZqlTJrL1fJhAgMBAAGjggEYMIIBFDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDuDBsBgNVHR8E +ZTBjMGGgX6BdhltodHRwOi8vb25zaXRlY3JsLnZlcmlzaWduLmNvbS9EaWdpdGFsaXNlcmluZ3Nz +dHlyZWxzZW5PcGVuUEVQUE9MQUNDRVNTUE9JTlRDQS9MYXRlc3RDUkwuY3JsMB8GA1UdIwQYMBaA +FE32PgBQKIZtNaD872aq+iKhJNuNMB0GA1UdDgQWBBQmvMVXU7zzLpX8yi7wNoeaLJozmjA3Bggr +BgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9wa2ktb2NzcC5zeW1hdXRoLmNvbTATBgNV +HSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEASncvgkVR10IpjuwzIDuZDWS+KKya +ccIa+FOCzaJ/w0seHmOqOztOmMIVenKc7ORXK3yljCO/8WmS8WDNX/ATyH2OfHfN5dsRUGcUAsiE +W0jdg72zVH2XxZ5whsWumxEIR+PhSFuH/Wm9GjH9gUUYNpwD0TvgOZfTFXJouorLpx6hPMUa6FuD +7L9pZ3Rk9JUarAdZ+NZIPCThrsJgrNGfaM0uXQ5lyNtnqLuaEtrvSPKejf7tWnhM6TERnCt2P/zJ +6YmtGUTZOErefLoWsBFSMzC3uzXySceI+ymn1AL7tvBwCvk6s7iF80/ecO5iyqPzbglldRXZ311g +vHe48x5EiQ==OpusCapita AP servicesinfo.no@itella.comrEMb2qN2G0OJAK1ZOSHt/Zt1ki4=FoQczfHqywR48FPkb2Mi0L8iUwWZaOjgXC06RO0NO8CiEk17ZNvwTd3t17J1IUVpPL/Ui+mjGU5w +pCGeiCAhHn5Cp4ddBz6n0/Mgi4Y56u9bx0088MeRFiGSdRbIdYrn1mynRhmBpkKHNk9cU6uuMmua +U8TzhQQ/bmm/v8nc/5NENoDQb/UC03ty7456ZuuMVUAtknDFkj5yaLveVevrT2+9mFBH5w7loJYE +Do81PmvPejEofKzqTwq+antj4FPwnposjIc0EOJfCByGMpwYtpfv9Yh1/WE3ywFPdUeuB8/o18hW +DnOFSjyyw8/YYFoIwI2k/5ZrNfsbytcOLGHhnQ==O=DIFI,CN=SMP_2000000105,C=NOMIIESzCCAzOgAwIBAgIQUu6qu0V/C1UfCp6umaq1VTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMS0wKwYDVQQDEyRQ +RVBQT0wgU0VSVklDRSBNRVRBREFUQSBQVUJMSVNIRVIgQ0EwHhcNMTUwNDEzMDAwMDAwWhcNMTcw +NDEyMjM1OTU5WjA1MQswCQYDVQQGEwJOTzEXMBUGA1UEAwwOU01QXzIwMDAwMDAxMDUxDTALBgNV +BAoMBERJRkkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp4ktGxC8ZYoSgjXI0e79N +aYMeSNBR0/qCWkucx3AXxL4KPCV+oKHoQEO+7mi1Bj8nKBDql08v1dHWT6yF+IZkKREB8GBPon2P +35r3J0VXPCAgTmQ9IezG7r0JAPueIn6VCHkYKtPAHhDyNZLaNwNRkVcF9jsJQf2M63/1vY8srohV +tQ/9mogFpe9DN8DTf47flENqn2gT70dGXm9+XSRh0JfWjb5NqtMVe06/33ON9VAisqzPNS50qcPH +PkwMB8uuKBT0pYh6u7XZ1N6xWla6HHCM/ksDZGI8MzMDCVeb14n5SwC/dQayjFf+Xv+hEzY0aKIt +3DS4eE2bD78isSmfAgMBAAGjggElMIIBITAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDuDB5BgNVHR8E +cjBwMG6gbKBqhmhodHRwOi8vb25zaXRlY3JsLnZlcmlzaWduLmNvbS9EaWdpdGFsaXNlcmluZ3Nz +dHlyZWxzZW5PcGVuUEVQUE9MU0VSVklDRU1FVEFEQVRBUFVCTElTSEVSQ0EvTGF0ZXN0Q1JMLmNy +bDAfBgNVHSMEGDAWgBR5y7W0EOuUtfV6wKwuVaHbijffFDAdBgNVHQ4EFgQUOhoCtatRUFglqARw +aBqhJW3GDCcwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3lt +YXV0aC5jb20wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAKMNFsNLVJeq +3jDv1QxdzMqHkpIUKC91Y4DHUAD9VVLjo5gk1XGd4BzasxvzGiwQmtcgBr0Uy5T54VdcfJIGcQ5D +QPszNz5kT6it0sSawIGsJUm1h4+NCOoF15mT5/i1DpGiYuPoJBpB2XI2YknOgCHtneW4zxskzk0F +7FgShSvrfl6VScipCHarNpB7aBGuPRMNBOLotym2J+Fb9zG/XJo2pcWkox5ZHZqt9uMht4qFCZG5 +RcUG2rf3q97WSvDFHtq31DYAxx9yNjiGNTo3KywNiLhMIZBDEND6tJ5XCQGPMI49V8Pc8Ikea+4q +kQpEYQQJsEAVfh2nQAnWJtKxaS0= \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/smp-response-with-as2.xml b/oxalis-commons/src/test/resources/smp-response-with-as2.xml new file mode 100644 index 0000000000000000000000000000000000000000..175eba5ee9063abed1096f7586699217db5e3dde --- /dev/null +++ b/oxalis-commons/src/test/resources/smp-response-with-as2.xml @@ -0,0 +1,118 @@ + + + + + + + 9908:991825827 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + + + urn:www.cenbii.eu:profile:bii04:ver1.0 + + + + https://ap.ergogroup.no/oxalis/as2 + + + + false + 1 + 2012-03-16T00:00:00Z + 2014-02-28T00:00:00Z + MIIEMzCCAxugAwIBAgIQU05M5k6dpbee1puonWt5vzANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQDExZQ + RVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTEzMTAxNzAwMDAwMFoXDTE1MTAxNzIzNTk1OVowODEL + MAkGA1UEBhMCTk8xFzAVBgNVBAMMDkFQUF8xMDAwMDAwMDI1MRAwDgYDVQQKDAdFVlJZIEFTMIIB + IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArHQ6z7INUf2+9NvLV0NvmMg4HDk8fVAh+Hvy + wLAXRzSvpefszhz5eQAmd5fxuQfOyevHGBiopU+mVspqSn1CyuD2eYUYG29djgSmIOQlqaj9Ixk4 + aF0hYmDvyWyyw4PfzDT3j8ur+TYhtEegzUYbWbN2r6ZVcA85kEfssr70JxwVqS7y3IXX+r5r5/vY + 3SyUhDQbftG75yeVnj/1AvityfSTTjMlloWRAyDlue+vo+uyKj2zfueUhyWZaxq5EMjgHguDVqIg + I74uY5Ho/DIb0A2mEm6urXtk+XxsgMz18zEebD6eH/dFTV7PqraPFAyn866EcT8CWYubvf86XnUo + /wIDAQABo4IBGDCCARQwCQYDVR0TBAIwADALBgNVHQ8EBAMCA7gwbAYDVR0fBGUwYzBhoF+gXYZb + aHR0cDovL29uc2l0ZWNybC52ZXJpc2lnbi5jb20vRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuT3Bl + blBFUFBPTEFDQ0VTU1BPSU5UQ0EvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBRN9j4AUCiGbTWg + /O9mqvoioSTbjTAdBgNVHQ4EFgQU/0So1rHiz4+sceK7P18eVpnBhjgwNwYIKwYBBQUHAQEEKzAp + MCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3ltYXV0aC5jb20wEwYDVR0lBAwwCgYIKwYB + BQUHAwIwDQYJKoZIhvcNAQELBQADggEBAImyiGHjqEb9Jql2J7ITBmdm6c22E3y5xrR0Ib1UPvYV + 7ETQHj/BrCZkSEqJz5akPoEmqHeWDomMYdJLxFQyEqX2gmErggHQZ/PqROZ13TG2f5AuMBmN57H3 + hXs3TAMpNnk24uGDLSRLkV8JOsZkIYXd+ykKzU4xfxEQe98UWOsgabwt8e6Ak4AJ3T1wpN/YyP+8 + oQ0lsQ6ZbuWbTf5cPUNO5VwYLEnJKYgDMxJEcx0BfzOXpcTt9EGcm7QRPowIAEXvfXU7mPdwJif6 + Y8sUbyqRYoG8b1ItBMsTD92ESdKpZzY6AafzSlRkLkD/bBxAqjYuL7RA9poFa5YA4bHSRrM= + Aksesspunkt for EEGs meldingssentral + leveranse@ergogroup.no + www.edbergogroup.no + + + + + + + + + + + + + + + + +I/JnSsqMlpm2YZWWZikUz10ZQI= + + + 0Tl9Fyt/DH2UeIdRocU8/OnDWTruaivmbQnbRkInQ0kBRjrrDO1816OHN6pO5z+lSe3lByb7d0FM + 8HF34YVFAJtmzCJ1Bdd9a60C1eTyRaHvkBV0k6M0epPR9hE/6ci0YMtVDTTAq72XJ7xM+3LS77Ca + jq8wbODl2LSZb5AiRmAU6YciurCqGbD3Ti1lbn/F/vmlLuRDD3yd//KM2S0fTGAB47Oym+V+0fja + gTfbHFFHs+ADvxnu7m7WXK6B9Klh/+WCMwYOIdkzzdSeM60Ge4l1LNMZwpdkTQOtVAq8wxtJgm/g + dhdNp+nGmStQ/ztW0UBAXxCo6UnP9e34e3P0ww== + + + O=Agency for Public Management and eGovernment (DIFI),CN=SMP_2000000005,C=NO + MIIEejCCA2KgAwIBAgIQUZcLJS2IyAyxZzsMNqh5UTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMS0wKwYDVQQDEyRQ + RVBQT0wgU0VSVklDRSBNRVRBREFUQSBQVUJMSVNIRVIgQ0EwHhcNMTMwNDE4MDAwMDAwWhcNMTUw + NDE4MjM1OTU5WjBkMQswCQYDVQQGEwJOTzEXMBUGA1UEAwwOU01QXzIwMDAwMDAwMDUxPDA6BgNV + BAoMM0FnZW5jeSBmb3IgUHVibGljIE1hbmFnZW1lbnQgYW5kIGVHb3Zlcm5tZW50IChESUZJKTCC + ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN23HvOaLOcYOi4gTlX1ElVi7joQla/Km9yL + k57W8cdfmPu2I6GTo14rO7SSjEEq+m2p0pmNrmCWICstBy3/v9/EvCHW3vDv8xS1UcImwypvRguR + 1ATACiR5NeKPUbifjRGUx2rdj3BGnQxb3peDuMDwLifQE/KQxVoyeAyB64th2bUidTuEQRxWPiag + 5F556UWZyYXrwja5K0Lj8PVDQ8F099EQBQ5p/6/x/DAZBiukc293Z3UyE2b6JskgVeY2MGhpRYtT + 1eelLcGvH+jn6Ehs1c6GcJJFE2vxdwwmyET5J/t2+iJrjsq9pNymZySFtix6JiXhliPm2AkGR501 + jK0CAwEAAaOCASUwggEhMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgO4MHkGA1UdHwRyMHAwbqBsoGqG + aGh0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNlbk9w + ZW5QRVBQT0xTRVJWSUNFTUVUQURBVEFQVUJMSVNIRVJDQS9MYXRlc3RDUkwuY3JsMB8GA1UdIwQY + MBaAFHnLtbQQ65S19XrArC5VoduKN98UMB0GA1UdDgQWBBQ0CizSDL8+dfT85fLEtXr/SeMIBzA3 + BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9wa2ktb2NzcC5zeW1hdXRoLmNvbTAT + BgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAVNmOc+OhdDhlFEIKjXMvUPeq + h8ln15scrn0OhjHW2wreD5+x7zwLjsA7N1KV4+QzSFQS9AskY7ESpyuM0Zpqjr62f+3VgFg+hLWY + A++u75lg+Sr34fCUpXBJlM43hbNE9jva5HvmfG0k23Ez+WdjTLSDfIkIYcZUa60ZBrlAbgcnauRW + oDYLw77GBrfSkVCGgt+81lVWyZm9vQMX5zf2NZk3x9Crlqdo26L0WWJEd+cgppR9PHuS/8CJpf7M + hnOfFDG5NvkPwVIxSFTgAhwDxRgYCCJhXlJmuMtUCmTMmzvCxJ2MDMTdimswVgZiAWr/IIiqHcsv + LRzT3bMAGFE1ZQ== + + + + diff --git a/oxalis-commons/src/test/resources/smp-response-with-unknown-protocol.xml b/oxalis-commons/src/test/resources/smp-response-with-unknown-protocol.xml new file mode 100644 index 0000000000000000000000000000000000000000..a874f2a06862895160329b8a9bfe4fc0d0c7bd12 --- /dev/null +++ b/oxalis-commons/src/test/resources/smp-response-with-unknown-protocol.xml @@ -0,0 +1,163 @@ + + + + + 9908:991825827 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + + + urn:www.cenbii.eu:profile:bii04:ver1.0 + + + + https://ap.ergogroup.no/oxalis/accessPointService + + + + false + 1 + 2012-03-16T00:00:00Z + 2014-02-28T00:00:00Z + MIIEMzCCAxugAwIBAgIQU05M5k6dpbee1puonWt5vzANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQDExZQ + RVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTEzMTAxNzAwMDAwMFoXDTE1MTAxNzIzNTk1OVowODEL + MAkGA1UEBhMCTk8xFzAVBgNVBAMMDkFQUF8xMDAwMDAwMDI1MRAwDgYDVQQKDAdFVlJZIEFTMIIB + IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArHQ6z7INUf2+9NvLV0NvmMg4HDk8fVAh+Hvy + wLAXRzSvpefszhz5eQAmd5fxuQfOyevHGBiopU+mVspqSn1CyuD2eYUYG29djgSmIOQlqaj9Ixk4 + aF0hYmDvyWyyw4PfzDT3j8ur+TYhtEegzUYbWbN2r6ZVcA85kEfssr70JxwVqS7y3IXX+r5r5/vY + 3SyUhDQbftG75yeVnj/1AvityfSTTjMlloWRAyDlue+vo+uyKj2zfueUhyWZaxq5EMjgHguDVqIg + I74uY5Ho/DIb0A2mEm6urXtk+XxsgMz18zEebD6eH/dFTV7PqraPFAyn866EcT8CWYubvf86XnUo + /wIDAQABo4IBGDCCARQwCQYDVR0TBAIwADALBgNVHQ8EBAMCA7gwbAYDVR0fBGUwYzBhoF+gXYZb + aHR0cDovL29uc2l0ZWNybC52ZXJpc2lnbi5jb20vRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuT3Bl + blBFUFBPTEFDQ0VTU1BPSU5UQ0EvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBRN9j4AUCiGbTWg + /O9mqvoioSTbjTAdBgNVHQ4EFgQU/0So1rHiz4+sceK7P18eVpnBhjgwNwYIKwYBBQUHAQEEKzAp + MCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3ltYXV0aC5jb20wEwYDVR0lBAwwCgYIKwYB + BQUHAwIwDQYJKoZIhvcNAQELBQADggEBAImyiGHjqEb9Jql2J7ITBmdm6c22E3y5xrR0Ib1UPvYV + 7ETQHj/BrCZkSEqJz5akPoEmqHeWDomMYdJLxFQyEqX2gmErggHQZ/PqROZ13TG2f5AuMBmN57H3 + hXs3TAMpNnk24uGDLSRLkV8JOsZkIYXd+ykKzU4xfxEQe98UWOsgabwt8e6Ak4AJ3T1wpN/YyP+8 + oQ0lsQ6ZbuWbTf5cPUNO5VwYLEnJKYgDMxJEcx0BfzOXpcTt9EGcm7QRPowIAEXvfXU7mPdwJif6 + Y8sUbyqRYoG8b1ItBMsTD92ESdKpZzY6AafzSlRkLkD/bBxAqjYuL7RA9poFa5YA4bHSRrM= + Aksesspunkt for EEGs meldingssentral + leveranse@ergogroup.no + www.edbergogroup.no + + + + + https://ap.ergogroup.no/oxalis/accessPointService + + + + false + 1 + 2012-03-16T00:00:00Z + 2014-02-28T00:00:00Z + MIIEMzCCAxugAwIBAgIQU05M5k6dpbee1puonWt5vzANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQDExZQ + RVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTEzMTAxNzAwMDAwMFoXDTE1MTAxNzIzNTk1OVowODEL + MAkGA1UEBhMCTk8xFzAVBgNVBAMMDkFQUF8xMDAwMDAwMDI1MRAwDgYDVQQKDAdFVlJZIEFTMIIB + IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArHQ6z7INUf2+9NvLV0NvmMg4HDk8fVAh+Hvy + wLAXRzSvpefszhz5eQAmd5fxuQfOyevHGBiopU+mVspqSn1CyuD2eYUYG29djgSmIOQlqaj9Ixk4 + aF0hYmDvyWyyw4PfzDT3j8ur+TYhtEegzUYbWbN2r6ZVcA85kEfssr70JxwVqS7y3IXX+r5r5/vY + 3SyUhDQbftG75yeVnj/1AvityfSTTjMlloWRAyDlue+vo+uyKj2zfueUhyWZaxq5EMjgHguDVqIg + I74uY5Ho/DIb0A2mEm6urXtk+XxsgMz18zEebD6eH/dFTV7PqraPFAyn866EcT8CWYubvf86XnUo + /wIDAQABo4IBGDCCARQwCQYDVR0TBAIwADALBgNVHQ8EBAMCA7gwbAYDVR0fBGUwYzBhoF+gXYZb + aHR0cDovL29uc2l0ZWNybC52ZXJpc2lnbi5jb20vRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuT3Bl + blBFUFBPTEFDQ0VTU1BPSU5UQ0EvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBRN9j4AUCiGbTWg + /O9mqvoioSTbjTAdBgNVHQ4EFgQU/0So1rHiz4+sceK7P18eVpnBhjgwNwYIKwYBBQUHAQEEKzAp + MCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3ltYXV0aC5jb20wEwYDVR0lBAwwCgYIKwYB + BQUHAwIwDQYJKoZIhvcNAQELBQADggEBAImyiGHjqEb9Jql2J7ITBmdm6c22E3y5xrR0Ib1UPvYV + 7ETQHj/BrCZkSEqJz5akPoEmqHeWDomMYdJLxFQyEqX2gmErggHQZ/PqROZ13TG2f5AuMBmN57H3 + hXs3TAMpNnk24uGDLSRLkV8JOsZkIYXd+ykKzU4xfxEQe98UWOsgabwt8e6Ak4AJ3T1wpN/YyP+8 + oQ0lsQ6ZbuWbTf5cPUNO5VwYLEnJKYgDMxJEcx0BfzOXpcTt9EGcm7QRPowIAEXvfXU7mPdwJif6 + Y8sUbyqRYoG8b1ItBMsTD92ESdKpZzY6AafzSlRkLkD/bBxAqjYuL7RA9poFa5YA4bHSRrM= + Aksesspunkt for EEGs meldingssentral + leveranse@ergogroup.no + www.edbergogroup.no + + + + https://ap.ergogroup.no/oxalis/as2 + + + + false + 1 + 2012-03-16T00:00:00Z + 2014-02-28T00:00:00Z + MIIEMzCCAxugAwIBAgIQU05M5k6dpbee1puonWt5vzANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQDExZQ + RVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTEzMTAxNzAwMDAwMFoXDTE1MTAxNzIzNTk1OVowODEL + MAkGA1UEBhMCTk8xFzAVBgNVBAMMDkFQUF8xMDAwMDAwMDI1MRAwDgYDVQQKDAdFVlJZIEFTMIIB + IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArHQ6z7INUf2+9NvLV0NvmMg4HDk8fVAh+Hvy + wLAXRzSvpefszhz5eQAmd5fxuQfOyevHGBiopU+mVspqSn1CyuD2eYUYG29djgSmIOQlqaj9Ixk4 + aF0hYmDvyWyyw4PfzDT3j8ur+TYhtEegzUYbWbN2r6ZVcA85kEfssr70JxwVqS7y3IXX+r5r5/vY + 3SyUhDQbftG75yeVnj/1AvityfSTTjMlloWRAyDlue+vo+uyKj2zfueUhyWZaxq5EMjgHguDVqIg + I74uY5Ho/DIb0A2mEm6urXtk+XxsgMz18zEebD6eH/dFTV7PqraPFAyn866EcT8CWYubvf86XnUo + /wIDAQABo4IBGDCCARQwCQYDVR0TBAIwADALBgNVHQ8EBAMCA7gwbAYDVR0fBGUwYzBhoF+gXYZb + aHR0cDovL29uc2l0ZWNybC52ZXJpc2lnbi5jb20vRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuT3Bl + blBFUFBPTEFDQ0VTU1BPSU5UQ0EvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBRN9j4AUCiGbTWg + /O9mqvoioSTbjTAdBgNVHQ4EFgQU/0So1rHiz4+sceK7P18eVpnBhjgwNwYIKwYBBQUHAQEEKzAp + MCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3ltYXV0aC5jb20wEwYDVR0lBAwwCgYIKwYB + BQUHAwIwDQYJKoZIhvcNAQELBQADggEBAImyiGHjqEb9Jql2J7ITBmdm6c22E3y5xrR0Ib1UPvYV + 7ETQHj/BrCZkSEqJz5akPoEmqHeWDomMYdJLxFQyEqX2gmErggHQZ/PqROZ13TG2f5AuMBmN57H3 + hXs3TAMpNnk24uGDLSRLkV8JOsZkIYXd+ykKzU4xfxEQe98UWOsgabwt8e6Ak4AJ3T1wpN/YyP+8 + oQ0lsQ6ZbuWbTf5cPUNO5VwYLEnJKYgDMxJEcx0BfzOXpcTt9EGcm7QRPowIAEXvfXU7mPdwJif6 + Y8sUbyqRYoG8b1ItBMsTD92ESdKpZzY6AafzSlRkLkD/bBxAqjYuL7RA9poFa5YA4bHSRrM= + Aksesspunkt for EEGs meldingssentral + leveranse@ergogroup.no + www.edbergogroup.no + + + + + + + + + + + + + + + + +I/JnSsqMlpm2YZWWZikUz10ZQI= + + + 0Tl9Fyt/DH2UeIdRocU8/OnDWTruaivmbQnbRkInQ0kBRjrrDO1816OHN6pO5z+lSe3lByb7d0FM + 8HF34YVFAJtmzCJ1Bdd9a60C1eTyRaHvkBV0k6M0epPR9hE/6ci0YMtVDTTAq72XJ7xM+3LS77Ca + jq8wbODl2LSZb5AiRmAU6YciurCqGbD3Ti1lbn/F/vmlLuRDD3yd//KM2S0fTGAB47Oym+V+0fja + gTfbHFFHs+ADvxnu7m7WXK6B9Klh/+WCMwYOIdkzzdSeM60Ge4l1LNMZwpdkTQOtVAq8wxtJgm/g + dhdNp+nGmStQ/ztW0UBAXxCo6UnP9e34e3P0ww== + + + O=Agency for Public Management and eGovernment (DIFI),CN=SMP_2000000005,C=NO + MIIEejCCA2KgAwIBAgIQUZcLJS2IyAyxZzsMNqh5UTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMS0wKwYDVQQDEyRQ + RVBQT0wgU0VSVklDRSBNRVRBREFUQSBQVUJMSVNIRVIgQ0EwHhcNMTMwNDE4MDAwMDAwWhcNMTUw + NDE4MjM1OTU5WjBkMQswCQYDVQQGEwJOTzEXMBUGA1UEAwwOU01QXzIwMDAwMDAwMDUxPDA6BgNV + BAoMM0FnZW5jeSBmb3IgUHVibGljIE1hbmFnZW1lbnQgYW5kIGVHb3Zlcm5tZW50IChESUZJKTCC + ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN23HvOaLOcYOi4gTlX1ElVi7joQla/Km9yL + k57W8cdfmPu2I6GTo14rO7SSjEEq+m2p0pmNrmCWICstBy3/v9/EvCHW3vDv8xS1UcImwypvRguR + 1ATACiR5NeKPUbifjRGUx2rdj3BGnQxb3peDuMDwLifQE/KQxVoyeAyB64th2bUidTuEQRxWPiag + 5F556UWZyYXrwja5K0Lj8PVDQ8F099EQBQ5p/6/x/DAZBiukc293Z3UyE2b6JskgVeY2MGhpRYtT + 1eelLcGvH+jn6Ehs1c6GcJJFE2vxdwwmyET5J/t2+iJrjsq9pNymZySFtix6JiXhliPm2AkGR501 + jK0CAwEAAaOCASUwggEhMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgO4MHkGA1UdHwRyMHAwbqBsoGqG + aGh0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNlbk9w + ZW5QRVBQT0xTRVJWSUNFTUVUQURBVEFQVUJMSVNIRVJDQS9MYXRlc3RDUkwuY3JsMB8GA1UdIwQY + MBaAFHnLtbQQ65S19XrArC5VoduKN98UMB0GA1UdDgQWBBQ0CizSDL8+dfT85fLEtXr/SeMIBzA3 + BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9wa2ktb2NzcC5zeW1hdXRoLmNvbTAT + BgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAVNmOc+OhdDhlFEIKjXMvUPeq + h8ln15scrn0OhjHW2wreD5+x7zwLjsA7N1KV4+QzSFQS9AskY7ESpyuM0Zpqjr62f+3VgFg+hLWY + A++u75lg+Sr34fCUpXBJlM43hbNE9jva5HvmfG0k23Ez+WdjTLSDfIkIYcZUa60ZBrlAbgcnauRW + oDYLw77GBrfSkVCGgt+81lVWyZm9vQMX5zf2NZk3x9Crlqdo26L0WWJEd+cgppR9PHuS/8CJpf7M + hnOfFDG5NvkPwVIxSFTgAhwDxRgYCCJhXlJmuMtUCmTMmzvCxJ2MDMTdimswVgZiAWr/IIiqHcsv + LRzT3bMAGFE1ZQ== + + + + diff --git a/oxalis-commons/src/test/resources/sr-smp-result.xml b/oxalis-commons/src/test/resources/sr-smp-result.xml new file mode 100644 index 0000000000000000000000000000000000000000..e04aaeb461c2b09faef0a08472728955d1b34c35 --- /dev/null +++ b/oxalis-commons/src/test/resources/sr-smp-result.xml @@ -0,0 +1,119 @@ + + + + + + + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0::2.1 + + + + urn:www.cenbii.eu:profile:bii04:ver2.0 + + + + https://ap.unit4.com/oxalis/as2 + + + + false + 1 + 2013-05-06Z + 2015-05-06Z + MIIENzCCAx+gAwIBAgIQKnxe+4PA67ZgidwVQleWTzANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQDExZQ + RVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTEzMDUwNjAwMDAwMFoXDTE1MDUwNjIzNTk1OVowPDEL + MAkGA1UEBhMCTk8xFzAVBgNVBAMMDkFQUF8xMDAwMDAwMDA2MRQwEgYDVQQKDAtTZW5kUmVnbmlu + ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5z9spSTvaKXN3M8AYRq6cYQ2LUeyQR + 1dWhvQloRIWBreMu/vgAXwA7dKXOFxUZTKV0sPKb1OpG4s+e5N62nv8ztphB4YyR2Tik3SEXh7Zv + MHQHD2QYPn/a+LX48AFQWBO4SKqvGaOqtjzcEkDXBO4cs4w1cRKCfZaHGzkHfiTv76BziNDHpwTE + QEtaY6ikQUtm8HxSmzD/FQhELeeq8usXAr3S6hVq08mmgICb8/Z+fkp/8Xnis7U6cLxqCWsqb2dh + r9Dg6qHEtWs6VD8z6XEq6dttxyB5S5kJVZGG6TM5pcxSakBb3qM8p/yLRrcPGveA660o3LhYB7YS + 0yUQfzkCAwEAAaOCARgwggEUMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgO4MGwGA1UdHwRlMGMwYaBf + oF2GW2h0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNl + bk9wZW5QRVBQT0xBQ0NFU1NQT0lOVENBL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgwFoAUTfY+AFAo + hm01oPzvZqr6IqEk240wHQYDVR0OBBYEFE5m0gB7Jw7kc+ltliSG0c4pOnq7MDcGCCsGAQUFBwEB + BCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3BraS1vY3NwLnN5bWF1dGguY29tMBMGA1UdJQQMMAoG + CCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQB0AHTSoKEasnB7lcYSzcMOu+bH5HLSAhCW9Vq0 + /HcCe9EutwIK2jIHzDS/Gpyfl0MURonA1/OWOdhyClGmgPiQBZKkE0Ir15C6MRhrLHmUMnU9bRIs + T8uEoxiXH6biUVw2SrAS69Tt6Xv3ydNhDiFGdxsD+Yfka1ciH6TxOflisqtRuOewSkV0kveQ5LmM + X595Br3CImmimNnBjXyqoRbZtNQmOgD85/zmW7BX8JAyCL9b+2aLmUTFQyIiGWiNOk+pdOLtpdhk + 9SKEo+hfXQVMWWRPM1S/M+kNJYzjlcC/zL2v2x6JocoBkQSsjhEwcEkIF9UWmiqGKwL3qAKsONni + + SendRegning Access Point Service + ap.support@unit4.com + + + + + + + + + + + + + + + + jHX3nq8v2dD8GBVmziI1a0MIJIw= + + + VjmDRVXWGDKt7o1tTyHiOXyfo7HOyEndmzuiNKYayhlpVxywz3351YA5VuEeg6TUYAFDwBLKBVnn + Eo1C1DYbRkLJ4RcWyg0SG8CPU5orjVfLIrPM0o+USJkKSqxO1k+KIQ1p651RqhplFfdAzRwkMxi0 + LAwgglpiUDqxsUNe7Rqu0CXxuhTVL+plKPaoIfkmlTKaFJBc47GquXuZHjbIhHRt15OHm5175NUr + PuLg/SW6OAJfA8iQWJZfUbeEKyc75mxruxlFsqHANTTrkyxe3EaODOmLm98rvFryKqTSQLaE+NQp + rLqFRv2NZHoETJ7CpmcT7mKfmoHKpxAs8q8vOA== + + + + O=DIFI,CN=SMP_2000000105,C=NO + MIIESzCCAzOgAwIBAgIQUu6qu0V/C1UfCp6umaq1VTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMS0wKwYDVQQDEyRQ + RVBQT0wgU0VSVklDRSBNRVRBREFUQSBQVUJMSVNIRVIgQ0EwHhcNMTUwNDEzMDAwMDAwWhcNMTcw + NDEyMjM1OTU5WjA1MQswCQYDVQQGEwJOTzEXMBUGA1UEAwwOU01QXzIwMDAwMDAxMDUxDTALBgNV + BAoMBERJRkkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp4ktGxC8ZYoSgjXI0e79N + aYMeSNBR0/qCWkucx3AXxL4KPCV+oKHoQEO+7mi1Bj8nKBDql08v1dHWT6yF+IZkKREB8GBPon2P + 35r3J0VXPCAgTmQ9IezG7r0JAPueIn6VCHkYKtPAHhDyNZLaNwNRkVcF9jsJQf2M63/1vY8srohV + tQ/9mogFpe9DN8DTf47flENqn2gT70dGXm9+XSRh0JfWjb5NqtMVe06/33ON9VAisqzPNS50qcPH + PkwMB8uuKBT0pYh6u7XZ1N6xWla6HHCM/ksDZGI8MzMDCVeb14n5SwC/dQayjFf+Xv+hEzY0aKIt + 3DS4eE2bD78isSmfAgMBAAGjggElMIIBITAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDuDB5BgNVHR8E + cjBwMG6gbKBqhmhodHRwOi8vb25zaXRlY3JsLnZlcmlzaWduLmNvbS9EaWdpdGFsaXNlcmluZ3Nz + dHlyZWxzZW5PcGVuUEVQUE9MU0VSVklDRU1FVEFEQVRBUFVCTElTSEVSQ0EvTGF0ZXN0Q1JMLmNy + bDAfBgNVHSMEGDAWgBR5y7W0EOuUtfV6wKwuVaHbijffFDAdBgNVHQ4EFgQUOhoCtatRUFglqARw + aBqhJW3GDCcwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3lt + YXV0aC5jb20wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAKMNFsNLVJeq + 3jDv1QxdzMqHkpIUKC91Y4DHUAD9VVLjo5gk1XGd4BzasxvzGiwQmtcgBr0Uy5T54VdcfJIGcQ5D + QPszNz5kT6it0sSawIGsJUm1h4+NCOoF15mT5/i1DpGiYuPoJBpB2XI2YknOgCHtneW4zxskzk0F + 7FgShSvrfl6VScipCHarNpB7aBGuPRMNBOLotym2J+Fb9zG/XJo2pcWkox5ZHZqt9uMht4qFCZG5 + RcUG2rf3q97WSvDFHtq31DYAxx9yNjiGNTo3KywNiLhMIZBDEND6tJ5XCQGPMI49V8Pc8Ikea+4q + kQpEYQQJsEAVfh2nQAnWJtKxaS0= + + + + + \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/sr-utf8.xml b/oxalis-commons/src/test/resources/sr-utf8.xml new file mode 100644 index 0000000000000000000000000000000000000000..97f26d85e7aa50f81ba469458c8e3c185efac374 --- /dev/null +++ b/oxalis-commons/src/test/resources/sr-utf8.xml @@ -0,0 +1,119 @@ + + + + + + + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0::2.1 + + + + urn:www.cenbii.eu:profile:bii04:ver2.0 + + + + https://ap.unit4.com/oxalis/as2 + + + + false + 1 + 2013-05-06Z + 2015-05-06Z + MIIENzCCAx+gAwIBAgIQKnxe+4PA67ZgidwVQleWTzANBgkqhkiG9w0BAQsFADBXMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMR8wHQYDVQQDExZQ + RVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTEzMDUwNjAwMDAwMFoXDTE1MDUwNjIzNTk1OVowPDEL + MAkGA1UEBhMCTk8xFzAVBgNVBAMMDkFQUF8xMDAwMDAwMDA2MRQwEgYDVQQKDAtTZW5kUmVnbmlu + ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5z9spSTvaKXN3M8AYRq6cYQ2LUeyQR + 1dWhvQloRIWBreMu/vgAXwA7dKXOFxUZTKV0sPKb1OpG4s+e5N62nv8ztphB4YyR2Tik3SEXh7Zv + MHQHD2QYPn/a+LX48AFQWBO4SKqvGaOqtjzcEkDXBO4cs4w1cRKCfZaHGzkHfiTv76BziNDHpwTE + QEtaY6ikQUtm8HxSmzD/FQhELeeq8usXAr3S6hVq08mmgICb8/Z+fkp/8Xnis7U6cLxqCWsqb2dh + r9Dg6qHEtWs6VD8z6XEq6dttxyB5S5kJVZGG6TM5pcxSakBb3qM8p/yLRrcPGveA660o3LhYB7YS + 0yUQfzkCAwEAAaOCARgwggEUMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgO4MGwGA1UdHwRlMGMwYaBf + oF2GW2h0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNl + bk9wZW5QRVBQT0xBQ0NFU1NQT0lOVENBL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgwFoAUTfY+AFAo + hm01oPzvZqr6IqEk240wHQYDVR0OBBYEFE5m0gB7Jw7kc+ltliSG0c4pOnq7MDcGCCsGAQUFBwEB + BCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3BraS1vY3NwLnN5bWF1dGguY29tMBMGA1UdJQQMMAoG + CCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQB0AHTSoKEasnB7lcYSzcMOu+bH5HLSAhCW9Vq0 + /HcCe9EutwIK2jIHzDS/Gpyfl0MURonA1/OWOdhyClGmgPiQBZKkE0Ir15C6MRhrLHmUMnU9bRIs + T8uEoxiXH6biUVw2SrAS69Tt6Xv3ydNhDiFGdxsD+Yfka1ciH6TxOflisqtRuOewSkV0kveQ5LmM + X595Br3CImmimNnBjXyqoRbZtNQmOgD85/zmW7BX8JAyCL9b+2aLmUTFQyIiGWiNOk+pdOLtpdhk + 9SKEo+hfXQVMWWRPM1S/M+kNJYzjlcC/zL2v2x6JocoBkQSsjhEwcEkIF9UWmiqGKwL3qAKsONni + + SendRegning Access Point Service ÆØÅ + ap.support@unit4.com + + + + + + + + + + + + + + + + T0XeBTl44QVUM+GSKcm3n8TyA1Q= + + + YSPxSS4tq1O/gqABCFDdfSpvEbD86OIZcaSbiEfDyLrRVZGC44A2ffo5VwYtuH8P+zYyhM5Cwbbo + XT2KjZ7aAXTZGDXarGelrwoVHnQBGQ/EyDKGZbdtOaEDSWyAJsJwcQanCy2izm53S5TZMZRM9glx + ODUPoWY16xaUlZ7ji2+mPVUrRIEbbwtSnUz8zXMf/szce3vfaExmT2Buysiqqx7rednL6IM7G69k + j9AljhZnFfAFMQFJGXAOjE+SMQPJ/4rtVlJr8I/2uUX6ZAaqaDseEvt2Gt1JyurrfoPYCsFw4YWn + pOes8ME0qR5zFMJJL4gyIpmBl9tkegH6rulqQw== + + + + O=DIFI,CN=SMP_2000000105,C=NO + MIIESzCCAzOgAwIBAgIQUu6qu0V/C1UfCp6umaq1VTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG + EwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00gQUdFTkNZMS0wKwYDVQQDEyRQ + RVBQT0wgU0VSVklDRSBNRVRBREFUQSBQVUJMSVNIRVIgQ0EwHhcNMTUwNDEzMDAwMDAwWhcNMTcw + NDEyMjM1OTU5WjA1MQswCQYDVQQGEwJOTzEXMBUGA1UEAwwOU01QXzIwMDAwMDAxMDUxDTALBgNV + BAoMBERJRkkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp4ktGxC8ZYoSgjXI0e79N + aYMeSNBR0/qCWkucx3AXxL4KPCV+oKHoQEO+7mi1Bj8nKBDql08v1dHWT6yF+IZkKREB8GBPon2P + 35r3J0VXPCAgTmQ9IezG7r0JAPueIn6VCHkYKtPAHhDyNZLaNwNRkVcF9jsJQf2M63/1vY8srohV + tQ/9mogFpe9DN8DTf47flENqn2gT70dGXm9+XSRh0JfWjb5NqtMVe06/33ON9VAisqzPNS50qcPH + PkwMB8uuKBT0pYh6u7XZ1N6xWla6HHCM/ksDZGI8MzMDCVeb14n5SwC/dQayjFf+Xv+hEzY0aKIt + 3DS4eE2bD78isSmfAgMBAAGjggElMIIBITAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDuDB5BgNVHR8E + cjBwMG6gbKBqhmhodHRwOi8vb25zaXRlY3JsLnZlcmlzaWduLmNvbS9EaWdpdGFsaXNlcmluZ3Nz + dHlyZWxzZW5PcGVuUEVQUE9MU0VSVklDRU1FVEFEQVRBUFVCTElTSEVSQ0EvTGF0ZXN0Q1JMLmNy + bDAfBgNVHSMEGDAWgBR5y7W0EOuUtfV6wKwuVaHbijffFDAdBgNVHQ4EFgQUOhoCtatRUFglqARw + aBqhJW3GDCcwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3lt + YXV0aC5jb20wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAKMNFsNLVJeq + 3jDv1QxdzMqHkpIUKC91Y4DHUAD9VVLjo5gk1XGd4BzasxvzGiwQmtcgBr0Uy5T54VdcfJIGcQ5D + QPszNz5kT6it0sSawIGsJUm1h4+NCOoF15mT5/i1DpGiYuPoJBpB2XI2YknOgCHtneW4zxskzk0F + 7FgShSvrfl6VScipCHarNpB7aBGuPRMNBOLotym2J+Fb9zG/XJo2pcWkox5ZHZqt9uMht4qFCZG5 + RcUG2rf3q97WSvDFHtq31DYAxx9yNjiGNTo3KywNiLhMIZBDEND6tJ5XCQGPMI49V8Pc8Ikea+4q + kQpEYQQJsEAVfh2nQAnWJtKxaS0= + + + + + \ No newline at end of file diff --git a/oxalis-commons/src/test/resources/statistics-response-multiple-entries.xml b/oxalis-commons/src/test/resources/statistics-response-multiple-entries.xml new file mode 100644 index 0000000000000000000000000000000000000000..0791b88f0ff2b8ca2ac39c5126e4a20c199cab01 --- /dev/null +++ b/oxalis-commons/src/test/resources/statistics-response-multiple-entries.xml @@ -0,0 +1,205 @@ + + + + + + AP001 + OUT + 2013-02-24T07 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH01 + 1 + + + SendRegning + IN + 2013-02-24T12 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH1 + 1 + + + SendRegning + OUT + 2013-02-24T12 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH1 + 1 + + + SendRegning + OUT + 2013-03-08T02 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + TEST + 1 + + + AP001 + OUT + 2013-03-11T01 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH01 + 1 + + + SendRegning + OUT + 2013-03-19T06 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH1 + 5 + + + SendRegning + OUT + 2013-03-19T07 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH1 + 6 + + + SendRegning + OUT + 2013-03-19T08 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH1 + 5 + + + SendRegning + OUT + 2013-03-19T09 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH1 + 1 + + + AP001 + OUT + 2013-03-20T11 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH01 + 1 + + + SendRegning + OUT + 2013-03-20T11 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH1 + 1 + + + AP001 + OUT + 2013-03-22T05 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH01 + 1 + + + AP001 + OUT + 2013-03-25T03 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH01 + 2 + + + AP001 + OUT + 2013-03-25T04 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH01 + 1 + + + AP001 + OUT + 2013-03-26T11 + 9908:810418052 + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + CH01 + 1 + + diff --git a/oxalis-commons/src/test/resources/unit4-accesspoint.cer b/oxalis-commons/src/test/resources/unit4-accesspoint.cer new file mode 100644 index 0000000000000000000000000000000000000000..64b82687f9943a4146945f7339cee2e426111d23 --- /dev/null +++ b/oxalis-commons/src/test/resources/unit4-accesspoint.cer @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIENDCCAxygAwIBAgIQA5SFQ9IMsNUJholTX9QEUzANBgkqhkiG9w0BAQsFADBX +MQswCQYDVQQGEwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00g +QUdFTkNZMR8wHQYDVQQDExZQRVBQT0wgQUNDRVNTIFBPSU5UIENBMB4XDTE3MDMy +OTAwMDAwMFoXDTE5MDMyOTIzNTk1OVowOTELMAkGA1UEBhMCTk8xFzAVBgNVBAMM +DkFQUF8xMDAwMDAwMzEyMREwDwYDVQQKDAhVbml0NCBBUzCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALx3ZcnnhdMKsWPeTkL8elP66maXShuq2El7KcM8 +wbhvhLCGfaEft/aQZ17SBGOQrhZXVyEhubEWaddVPVatsPmPgiAeU/JOctsf1sy2 +JbI217C3DijG1/+hmu7Wor6VIurbEvQKfe699HPznTcA5Vgg5UbVLroK6Vp8CAJy +v0M2YYUMOaJDyyQxrU2YTyyfk4h0OhJ8iUPKd69STJTYlLcoH+5xT05hABI0Tozu +kFB/3ajGsYILyF7p0ur5XM3t9k7Jhwf/h6a0SrFXDDqIP5rp7pSNuaQYF4nbaTZD +/Vw1wdrwcMYNS5G4WYM2UK1F1WTOtV6F1WuiI8mpzMon54ECAwEAAaOCARgwggEU +MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgO4MGwGA1UdHwRlMGMwYaBfoF2GW2h0dHA6 +Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNl +bk9wZW5QRVBQT0xBQ0NFU1NQT0lOVENBL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgw +FoAUTfY+AFAohm01oPzvZqr6IqEk240wHQYDVR0OBBYEFFYe3zPaoLZHLAx3vYoV +0tOB4eClMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3BraS1v +Y3NwLnN5bWF1dGguY29tMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEB +CwUAA4IBAQA9KKlOju3BkHEOqev155f/RcaA56PnSG+T1tp8KQyAQDr1DT/+5CsK +50Qbw4lfP3aERUH0FmnBKLLWi6EFLAxXRmaRZj84KoPAXmgtI5OHHsiTMHhY5vgP +8eRKs9x5Alo424ZQN8vbPJs1H1AfJIUPD9VoCJQp4ELMpN7Rd7bU+HkNOET9uZfl +APH4OuFlb95APIaVRuE8syt1ngNt8TmjKTGfUpDfkRiyoLrQY213fVlJXqUKXeGj +3Uk840qta3NHuwDUgv2loSsnlHg7+RvAghBM2zgztTJjMxaG7NSC9gMf4q1jMJUJ +3mGoHZweGWWaI7ue4AuCe5TusOWpwO7/ +-----END CERTIFICATE----- diff --git a/oxalis-commons/src/test/resources/xledger-2013-04-19T16_02_54_281.xml b/oxalis-commons/src/test/resources/xledger-2013-04-19T16_02_54_281.xml new file mode 100644 index 0000000000000000000000000000000000000000..8287ba6596ff252f9fe37aaa7986c5e9d75a6515 --- /dev/null +++ b/oxalis-commons/src/test/resources/xledger-2013-04-19T16_02_54_281.xml @@ -0,0 +1,144 @@ + + + + + + xledger + OUT + 2013-04-17T02 + 9908:880526642 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + + + xledger + OUT + 2013-04-17T02 + 9908:898307492 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + + + xledger + OUT + 2013-04-17T02 + 9908:993884871 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 2 + + + xledger + OUT + 2013-04-17T03 + 9908:877380092 + urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0:#urn:www.cenbii.eu:profile:biixx:ver1.0#urn:www.difi.no:ehf:kreditnota:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + + + xledger + OUT + 2013-04-18T05 + 9908:983669409 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + + + xledger + OUT + 2013-04-18T12 + 9908:980562484 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 2 + + + xledger + IN + 2013-04-19T02 + 9908:987290986 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + + 1 + + + xledger + IN + 2013-04-19T03 + 9908:848072222 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + + 1 + + + xledger + IN + 2013-04-19T08 + 9908:980374068 + urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0:#urn:www.cenbii.eu:profile:biixx:ver1.0#urn:www.difi.no:ehf:kreditnota:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + + + xledger + IN + 2013-04-19T09 + 9908:895189642 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + + 1 + + + xledger + OUT + 2013-04-19T10 + 9908:898307492 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + + + xledger + OUT + 2013-04-19T11 + 9908:993884871 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1::2.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + + 1 + \ No newline at end of file diff --git a/oxalis-dist/README.md b/oxalis-dist/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7fe5817e11af4079d8d66aa921b4b23d49484590 --- /dev/null +++ b/oxalis-dist/README.md @@ -0,0 +1,20 @@ +# Oxalis Distributions + +Oxalis is provided in different distributions to allow users to easily adopt Oxalis into their environment. + +The following distributions are available: + +* **[Oxalis Distribution](/oxalis-dist/oxalis-distribution)** - + The traditional distribution package of Oxalis. + +* **[Oxalis Server](/oxalis-dist/oxalis-server)** - + Oxalis as an application needing only Java 8 to run. + This is the distribution used to create the Docker image. + +* **[Oxalis Standalone](/oxalis-dist/oxalis-standalone)** - + Simple client for sending provided as a single java archive (jar). + Suited for testing and small manual tasks. + +* **[Oxalis WAR](/oxalis-dist/oxalis-war)** - + The traditional war distribution for application servers recreated to use Java Servlet 3.0 functionality. + This is the distribution made available as `oxalis.war` in `oxalis-distribution`. \ No newline at end of file diff --git a/oxalis-dist/oxalis-distribution/pom.xml b/oxalis-dist/oxalis-distribution/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..fb4c82e2c68cd2407616c17ca829287a5a97a446 --- /dev/null +++ b/oxalis-dist/oxalis-distribution/pom.xml @@ -0,0 +1,112 @@ + + + + + + 4.0.0 + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + ../../pom.xml + + + oxalis-distribution + pom + + Oxalis :: Dist :: Distribution + Creates a complete distribution which may be uploaded and made available. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + dk.erst.oxalis + oxalis-standalone + + + dk.erst.oxalis + oxalis-statistics + + + + + + dist + + + + maven-assembly-plugin + + + target + + src/main/assembly/distribution.xml + + + + + make-distribution + + package + + + single + + + + + + maven-resources-plugin + + + copy-resources + package + + copy-resources + + + ../../target/distribution + + + ${project.build.directory}/${project.build.finalName}-distro + + false + + + + + + + + + + + + + diff --git a/oxalis-dist/oxalis-distribution/src/main/assembly/distribution.xml b/oxalis-dist/oxalis-distribution/src/main/assembly/distribution.xml new file mode 100644 index 0000000000000000000000000000000000000000..65a48c9633f9e0d7a5cc748a58a90fcad0e6bc48 --- /dev/null +++ b/oxalis-dist/oxalis-distribution/src/main/assembly/distribution.xml @@ -0,0 +1,115 @@ + + + + + distro + false + + + + dir + tar.gz + zip + + + + + + ../oxalis-distribution/src/main/resources + etc + + *.xml + *.properties + + windows + + + + + ../../doc + doc + + */** + + + + + + ../oxalis-standalone/src/main/bash + bin + + *.sh + + + + + + ../../oxalis-legacy/oxalis-statistics/src/main/resources/sql + sql + + *.sql + + + + + ../oxalis-standalone/target + bin + + oxalis-standalone.jar + + + + + + + + true + + network.oxalis:oxalis-war:* + + + false + false + jee + + oxalis.${artifact.extension} + + + + + true + + network.oxalis:oxalis-outbound:* + + + true + false + api + + + + + + \ No newline at end of file diff --git a/oxalis-dist/oxalis-distribution/src/main/resources/logback-oxalis-app.xml b/oxalis-dist/oxalis-distribution/src/main/resources/logback-oxalis-app.xml new file mode 100644 index 0000000000000000000000000000000000000000..53ad57a1a64d78bfee2114e3973efa89873c7f44 --- /dev/null +++ b/oxalis-dist/oxalis-distribution/src/main/resources/logback-oxalis-app.xml @@ -0,0 +1,44 @@ + + + + + + + oxalis-logs-app/oxalis-app.log + + %d %p [%c] [%X{senderId}] %m %n + + + oxalis-logs-app/oxalis-app.%d{yyyy-MM-dd}.log + + + + + 280 + + + + + + + diff --git a/oxalis-dist/oxalis-distribution/src/main/resources/logback-oxalis-server.xml b/oxalis-dist/oxalis-distribution/src/main/resources/logback-oxalis-server.xml new file mode 100644 index 0000000000000000000000000000000000000000..3e7594bf45be6fde80b23a415b89d813a89112fe --- /dev/null +++ b/oxalis-dist/oxalis-distribution/src/main/resources/logback-oxalis-server.xml @@ -0,0 +1,49 @@ + + + + + + + ../logs/oxalis.log + + %d %p [%c] [%X{senderId}] %m %n + + + ../logs/oxalis.%d{yyyy-MM-dd}.log + + + + + 280 + + + + + + + + + + + + diff --git a/oxalis-dist/oxalis-server/pom.xml b/oxalis-dist/oxalis-server/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..c2dbf49e6a2919b0b7b8247ea23c3cb06be070b8 --- /dev/null +++ b/oxalis-dist/oxalis-server/pom.xml @@ -0,0 +1,125 @@ + + + + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + ../../pom.xml + + 4.0.0 + + oxalis-server + + Oxalis :: Dist :: Server + Oxalis Server with standard Oxalis features only. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + + dk.erst.oxalis + oxalis-inbound + + + dk.erst.oxalis + oxalis-outbound + + + + + dk.erst.oxalis + oxalis-extension-testbed + + + + + org.eclipse.jetty + jetty-server + + + org.eclipse.jetty + jetty-servlet + + + + + + + dist + + + + maven-assembly-plugin + + + src/main/assembly/assembly-full.xml + + + + + create-distribution-package + package + + single + + + + + + maven-resources-plugin + + + copy-resources + package + + copy-resources + + + ../../target + + + ${project.build.directory}/${project.build.finalName}-full + false + + + + + + + + + + + + + diff --git a/oxalis-dist/oxalis-server/src/main/assembly/assembly-full.xml b/oxalis-dist/oxalis-server/src/main/assembly/assembly-full.xml new file mode 100644 index 0000000000000000000000000000000000000000..827b54409ed97cbf26667a8430a8b64456da20d0 --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/assembly/assembly-full.xml @@ -0,0 +1,46 @@ + + + + full + + dir + tar.gz + zip + + false + + + src/main/assembly/full + /oxalis-server + + */**/.gitignore + */**/.gitkeep + + + + + + oxalis-server/lib + + + \ No newline at end of file diff --git a/oxalis-dist/oxalis-server/src/main/assembly/full/bin/run.bat b/oxalis-dist/oxalis-server/src/main/assembly/full/bin/run.bat new file mode 100644 index 0000000000000000000000000000000000000000..65c96099b565a1e10f3fa24614de63417ce28ab4 --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/assembly/full/bin/run.bat @@ -0,0 +1,4 @@ +@echo off +cd %0\..\.. + +java %JAVA_OPTS% -classpath conf/*;lib/*;ext/* network.oxalis.server.Main %* \ No newline at end of file diff --git a/oxalis-dist/oxalis-server/src/main/assembly/full/bin/run.sh b/oxalis-dist/oxalis-server/src/main/assembly/full/bin/run.sh new file mode 100644 index 0000000000000000000000000000000000000000..67e777c06be2475288f82833d1d3bc626895c62a --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/assembly/full/bin/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +cd $(dirname $(readlink -f $0))/.. + +exec java $JAVA_OPTS -classpath conf/*:lib/*:ext/* network.oxalis.server.Main $@ \ No newline at end of file diff --git a/oxalis-dist/oxalis-server/src/main/assembly/full/conf/.gitignore b/oxalis-dist/oxalis-server/src/main/assembly/full/conf/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5aaee21f93eacdb7248433ada9f31fececd1b051 --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/assembly/full/conf/.gitignore @@ -0,0 +1 @@ +oxalis-keystore.jks \ No newline at end of file diff --git a/oxalis-dist/oxalis-server/src/main/assembly/full/conf/.gitkeep b/oxalis-dist/oxalis-server/src/main/assembly/full/conf/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-server/src/main/assembly/full/ext/.gitkeep b/oxalis-dist/oxalis-server/src/main/assembly/full/ext/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-server/src/main/assembly/full/inbound/.gitkeep b/oxalis-dist/oxalis-server/src/main/assembly/full/inbound/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-server/src/main/assembly/full/plugin/.gitkeep b/oxalis-dist/oxalis-server/src/main/assembly/full/plugin/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/Main.java b/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..fe4c21c172208180a2c477f61738bf0543cab36c --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/Main.java @@ -0,0 +1,87 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.server; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Singleton; +import com.google.inject.servlet.GuiceFilter; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.inbound.OxalisGuiceContextListener; +import network.oxalis.server.jetty.JettyConf; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.HandlerList; +import org.eclipse.jetty.server.handler.ShutdownHandler; +import org.eclipse.jetty.server.handler.StatisticsHandler; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; + +import javax.servlet.DispatcherType; +import java.util.EnumSet; + +/** + * @author erlend + */ +@Slf4j +@Singleton +public class Main { + + @Inject + private Injector injector; + + @Inject + private Settings settings; + + public static void main(String... args) throws Exception { + GuiceModuleLoader.initiate().getInstance(Main.class).run(); + } + + public void run() throws Exception { + Server server = new Server(settings.getInt(JettyConf.PORT)); + + HandlerList handlers = new HandlerList(); + + if (settings.getString(JettyConf.SHUTDOWN_TOKEN) != null) + handlers.addHandler(new ShutdownHandler(settings.getString(JettyConf.SHUTDOWN_TOKEN), false, true)); + + ServletContextHandler handler = new ServletContextHandler(server, settings.getString(JettyConf.CONTEXT_PATH)); + handler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class)); + handler.addEventListener(new OxalisGuiceContextListener(injector)); + handler.addServlet(DefaultServlet.class, "/"); + handlers.addHandler(handler); + + StatisticsHandler statisticsHandler = new StatisticsHandler(); + statisticsHandler.setHandler(handler); + handlers.addHandler(statisticsHandler); + + server.setHandler(handlers); + server.setStopTimeout(settings.getInt(JettyConf.STOP_TIMEOUT)); + server.setStopAtShutdown(true); + + log.info("Starting server"); + server.start(); + server.join(); + } +} diff --git a/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/jetty/JettyConf.java b/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/jetty/JettyConf.java new file mode 100644 index 0000000000000000000000000000000000000000..89bc54ea7bbdfaf2924b2675575b576ffc028f3f --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/jetty/JettyConf.java @@ -0,0 +1,30 @@ +package network.oxalis.server.jetty; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Nullable; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + */ +@Title("Jetty") +public enum JettyConf { + + @Path("oxalis.jetty.port") + @DefaultValue("8080") + PORT, + + @Path("oxalis.jetty.context_path") + @DefaultValue("/") + CONTEXT_PATH, + + @Path("oxalis.jetty.shutdown_token") + @Nullable + SHUTDOWN_TOKEN, + + @Path("oxalis.jetty.stop_timeout") + @DefaultValue("10000") + STOP_TIMEOUT, + +} diff --git a/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/jetty/JettyModule.java b/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/jetty/JettyModule.java new file mode 100644 index 0000000000000000000000000000000000000000..dc7937a6fd4a133e48434a285bb688682ed678cf --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/java/network/oxalis/server/jetty/JettyModule.java @@ -0,0 +1,14 @@ +package network.oxalis.server.jetty; + +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + */ +public class JettyModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(JettyConf.class); + } +} diff --git a/oxalis-dist/oxalis-server/src/main/resources/logback.xml b/oxalis-dist/oxalis-server/src/main/resources/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..d26c1f189f52b5a41b5d733b577a03895cf95e07 --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/resources/logback.xml @@ -0,0 +1,41 @@ + + + + + + + + + %d %X{message-id} %p [%c] %m %n + + + + + + + + + + + + diff --git a/oxalis-dist/oxalis-server/src/main/resources/reference.conf b/oxalis-dist/oxalis-server/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..5bc84146a1d55924998fc3f06e895ba6ea39c1f8 --- /dev/null +++ b/oxalis-dist/oxalis-server/src/main/resources/reference.conf @@ -0,0 +1,4 @@ +oxalis.module.server.jetty.class = network.oxalis.server.jetty.JettyModule + +oxalis.path.conf = conf +oxalis.path.plugin = plugin \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/.gitignore b/oxalis-dist/oxalis-standalone/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..82b1791bd281654b39f4b2e21bf0fb7c1e4b981d --- /dev/null +++ b/oxalis-dist/oxalis-standalone/.gitignore @@ -0,0 +1,2 @@ +/*-mdn.txt +/*-rem-evidence.xml \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/example.bat b/oxalis-dist/oxalis-standalone/example.bat new file mode 100644 index 0000000000000000000000000000000000000000..6502ac20f4fe7f6466db45dfbd74e969af10dd13 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/example.bat @@ -0,0 +1,21 @@ +@echo off +REM +REM Sends a sample invoice to Difi's test server. +REM Check the results at +REM https://test-aksesspunkt.difi.no/inbound/9908_810418052/ +REM +@echo on +java -jar target/oxalis-standalone.jar -f src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml^ + -r 9908:810418052 ^ + -s 9909:810418052 +@echo off + +REM Sends a sample invoice to your own local access point +@echo on +java -jar target/oxalis-standalone.jar -f src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml^ + -r 9908:810418052^ + -s 9946:ESPAP^ + -u http://localhost:8080/oxalis/as2^ + -m as2^ + -i APP_1000000135 +@echo off \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/example.sh b/oxalis-dist/oxalis-standalone/example.sh new file mode 100644 index 0000000000000000000000000000000000000000..f3806d898045077e64e577b5c2dfb2cdb9323af3 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/example.sh @@ -0,0 +1,164 @@ +#!/bin/bash +# +# Author: Steinar O. Cook +# +# Sample program illustrating how a single file may be sent using the stand alone client. +# +# The -t option switches the trace facility on +# +# +TRACE="" + +# The default is to send the sample document to our own access point running on our own machine. +URL="https://localhost:8080/oxalis/as2" + +# The URL and the METHOD must correspond +METHOD="as2" + +# The AS2 destination system identifier has to be specified when using AS2 (X.509 common name of receiver) +AS2SID="APP_1000000XXX" + +FILE="./src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml" +DOC_TYPE_OPTION="" + +# Difi PEPPOL Participant Identifier for test purposes. +# Check reception at https://test-aksesspunkt.difi.no/inbound/9908_810418052/ +RECEIVER="9908:810418052" + +SENDER="9908:810017902" +PROFILE="urn:www.cenbii.eu:profile:bii04:ver1.0" + +# Location of the executable program +EXECUTABLE="target/oxalis-standalone.jar" + +function usage() { + cat < + + + + 4.0.0 + + + dk.erst.oxalis + oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + ../../pom.xml + + + oxalis-standalone + jar + + Oxalis :: Dist :: Standalone + Standalone CLI program which may be used for sending a PEPPOL document. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + + + dk.erst.oxalis + oxalis-outbound + + + + dk.erst.oxalis + oxalis-test + test + + + + + ch.qos.logback + logback-classic + + + org.slf4j + jul-to-slf4j + + + + net.sf.jopt-simple + jopt-simple + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.4.1 + + + package + + shade + + + oxalis-standalone + + + reference.conf + + + eu.sendregning.oxalis.Main + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + maven-jar-plugin + + + + true + true + + + + + + maven-resources-plugin + + + rename-jar + package + + copy-resources + + + ../../target + + + ${project.build.directory} + + oxalis-standalone.jar + + + + + + + + + + + + + dist + + + + maven-assembly-plugin + + + src/main/assembly/assembly-full.xml + + + + + create-distribution-package + package + + single + + + + + + maven-resources-plugin + + + copy-resources + package + + copy-resources + + + ../../target + + + ${project.build.directory}/${project.build.finalName}-full + false + + + + + + + + + + + + + diff --git a/oxalis-dist/oxalis-standalone/src/main/assembly/assembly-full.xml b/oxalis-dist/oxalis-standalone/src/main/assembly/assembly-full.xml new file mode 100644 index 0000000000000000000000000000000000000000..1a9cb04bf3dd2b086a2657b9469e0e0c463401dc --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/assembly/assembly-full.xml @@ -0,0 +1,51 @@ + + + + full + + dir + + + false + + + src/main/assembly/full + /oxalis-standalone + + */**/.gitignore + + + + + + oxalis-standalone/lib + + + oxalis-standalone/lib + + network.oxalis:oxalis-extension-currenthome + + + + \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/src/main/assembly/full/bin/run.bat b/oxalis-dist/oxalis-standalone/src/main/assembly/full/bin/run.bat new file mode 100644 index 0000000000000000000000000000000000000000..a2b5a5a5d462ec5dec1909a6e2a077d251b289c2 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/assembly/full/bin/run.bat @@ -0,0 +1,4 @@ +@echo off +cd %0\..\.. + +java %JAVA_OPTS% -classpath conf/*;lib/*;ext/* eu.sendregning.oxalis.Main %* \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/src/main/assembly/full/bin/run.sh b/oxalis-dist/oxalis-standalone/src/main/assembly/full/bin/run.sh new file mode 100644 index 0000000000000000000000000000000000000000..48ec4832f2f1ee0581a3eb7f5f667ecb5db7843f --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/assembly/full/bin/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +cd $(dirname $(readlink -f $0))/.. + +exec java $JAVA_OPTS -classpath conf/*:lib/*:ext/* eu.sendregning.oxalis.Main $@ \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/src/main/assembly/full/conf/.gitkeep b/oxalis-dist/oxalis-standalone/src/main/assembly/full/conf/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-standalone/src/main/assembly/full/ext/.gitkeep b/oxalis-dist/oxalis-standalone/src/main/assembly/full/ext/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-standalone/src/main/assembly/full/inbound/.gitkeep b/oxalis-dist/oxalis-standalone/src/main/assembly/full/inbound/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-standalone/src/main/assembly/full/plugin/.gitkeep b/oxalis-dist/oxalis-standalone/src/main/assembly/full/plugin/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-dist/oxalis-standalone/src/main/bash/send-self.sh b/oxalis-dist/oxalis-standalone/src/main/bash/send-self.sh new file mode 100644 index 0000000000000000000000000000000000000000..c222116178a53690d2b0d51d4d4b58f2bdf08b3f --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/bash/send-self.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# +# Sends sample invoice to ourselves +# + +PRG="$0" + +# Name of directory from which this program is being executed, should normally result in the bin/ directory +# of the distribution. +PRGDIR=`dirname $0` + + +RECEIVER="9908:983995691" + +# PEPPOL Participant id for Difi +DIFI_TEST="9908:810418052" + +# +# Allows overriding from command line +# +for i in "$@" +do + case $i in + -r=*) + RECEIVER="${i#*=}" + shift + ;; + esac +done + +echo "Sender eksempel faktura (bare tull) fra og til oss selv" + +JARFILE=$PRGDIR/oxalis-standalone.jar + +if [ ! -r "$JARFILE" ]; then + echo "$JARFILE not found" + exit 4 +fi + +java -jar $JARFILE -f ./sample-invoice.xml -s 9908:976098897 -r ${RECEIVER} -u http://localhost:8080/oxalis/as2 -m as2 -i APP_1000000270 -e data/evidence + +# --cert /Users/steinar/.oxalis/difi-cert.pem \ +# -u http://localhost:8080/oxalis/as2 -f /var/peppol/samples/hfcEHF_P205044_P3746797_5684_HF_PTI_161107_2115_11897047_216879680363.XML \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/Main.java b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..2cd46ca0eab4a147be1efc2fea9a1172d32b14dd --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/Main.java @@ -0,0 +1,380 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package eu.sendregning.oxalis; + +import com.google.common.io.ByteStreams; +import com.google.inject.Key; +import com.google.inject.name.Names; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.commons.certvalidator.Validator; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.outbound.OxalisOutboundComponent; +import network.oxalis.vefa.peppol.common.model.*; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; + +import java.io.*; +import java.net.URI; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalDouble; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +/** + * @author Steinar O. Cook + * @author Nigel Parker + * @author Thore Johnsen + * @author erlend + * + * @author aaron-kumar + * @since 5.0.0 + */ +@Slf4j +public class Main { + + private static OptionSpec fileSpec; + + private static OptionSpec sender; + + private static OptionSpec recipient; + + private static OptionSpec docType; // The PEPPOL document type (very long string) + + private static OptionSpec profileType; // The PEPPOL document profile + + private static OptionSpec evidencePath; // Path to persistent storage of evidence data + + private static OptionSpec useRequestFactory; + + private static OptionSpec repeatCount; + + private static OptionSpec destinationUrl; + + private static OptionSpec destinationCertificate; + + private static OptionSpec protocol; + + private static OptionSpec maxTransmissions; // Maximum number of transmissions no matter what + + private static OptionSpec probe; + + private static OptionSpec tag; + + private static OptionSpec sleep; + + public static void main(String[] args) throws Exception { + + OptionParser optionParser = getOptionParser(); + + if (args.length == 0) { + System.out.println(); + optionParser.printHelpOn(System.out); + System.out.println(); + System.out.println("Configure logging: java -Dlogback.configurationFile=/path/to/config.xml -jar options"); + return; + } + + OptionSet optionSet; + + try { + optionSet = optionParser.parse(args); + } catch (Exception e) { + printErrorMessage(e.getMessage()); + return; + } + + // bootstraps the Oxalis outbound module + OxalisOutboundComponent oxalisOutboundComponent = new OxalisOutboundComponent(); + TransmissionParameters params = new TransmissionParameters(oxalisOutboundComponent); + + // Verifies the existence of a directory in which transmission evidence is stored. + File evidencePath = Main.evidencePath.value(optionSet); + if (evidencePath == null) { + evidencePath = new File("."); // Default is current directory + } + if (!evidencePath.exists() || !evidencePath.isDirectory()) { + printErrorMessage(evidencePath + " does not exist or is not a directory"); + } + params.setEvidencePath(evidencePath); + + // Tag + params.setTag(tag.value(optionSet)); + + // --- Use Factory + params.setUseFactory(useRequestFactory.value(optionSet)); + + // --- Recipient + String recipientId = recipient.value(optionSet); + if (recipientId != null) { + params.setReceiver(ParticipantIdentifier.of(recipientId)); + } + + // --- Sender + String senderId = sender.value(optionSet); + if (senderId != null) { + params.setSender(ParticipantIdentifier.of(senderId)); + } + + // --- Document type + if (docType != null && docType.value(optionSet) != null) { + String value = docType.value(optionSet); + params.setDocType(DocumentTypeIdentifier.of(value)); + } + + // --- Process type + if (profileType != null && profileType.value(optionSet) != null) { + String value = profileType.value(optionSet); + params.setProcessIdentifier(ProcessIdentifier.of(value)); + } + + if (probe.value(optionSet)) { + CloseableHttpClient httpClient = oxalisOutboundComponent.getInjector() + .getInstance(CloseableHttpClient.class); + try (CloseableHttpResponse response = httpClient.execute(new HttpGet(destinationUrl.value(optionSet)))) { + ByteStreams.copy(response.getEntity().getContent(), System.out); + } + } else { + // --- Destination URL, protocl and system identifier + if (optionSet.has(destinationUrl) && !probe.value(optionSet)) { + String destinationString = destinationUrl.value(optionSet); + + X509Certificate certificate; + try (InputStream inputStream = new FileInputStream(destinationCertificate.value(optionSet))) { + certificate = Validator.getCertificate(inputStream); + } + + params.setEndpoint(Endpoint.of( + TransportProfile.of(protocol.value(optionSet)), + URI.create(destinationString), + certificate)); + } + + // Retrieves the name of the file to be transmitted + String payloadFileSpec = fileSpec.value(optionSet); + + List files = locateFiles(payloadFileSpec); + + + System.out.println(); + System.out.println(); + + int repeats = optionSet.valueOf(repeatCount); + int maximumTransmissions = optionSet.valueOf(maxTransmissions); + + ExecutorService exec = oxalisOutboundComponent.getInjector() + .getInstance(Key.get(ExecutorService.class, Names.named("default"))); + ExecutorCompletionService ecs = new ExecutorCompletionService<>(exec); + + long start = System.nanoTime(); + int submittedTaskCount = 0; + for (File file : files) { + + if (!file.isFile() || !file.canRead()) { + log.error("File " + file + " is not a file or can not be read, skipping..."); + continue; + } + + for (int i = 0; i < repeats; i++) { + TransmissionTask transmissionTask = new TransmissionTask(params, file); + + Future submit = ecs.submit(transmissionTask); + submittedTaskCount++; + if (submittedTaskCount > maximumTransmissions) { + log.info("Stopped submitting tasks at {} " + submittedTaskCount); + break; + } + } + if (submittedTaskCount > maximumTransmissions) { + break; + } + } + + // Wait for the results to be available + List results = new ArrayList<>(); + int failed = 0; + for (int i = 0; i < submittedTaskCount; i++) { + try { + Future future = ecs.take(); + TransmissionResult transmissionResult = future.get(); + results.add(transmissionResult); + } catch (InterruptedException e) { + System.err.println(e.getMessage()); + } catch (ExecutionException e) { + log.error("Execution failed: {}", e.getMessage(), e); + failed++; + } + } + + long elapsed = System.nanoTime() - start; + + exec.shutdownNow(); // Shuts down the executor service + + for (TransmissionResult transmissionResult : results) { + TransmissionIdentifier transmissionIdentifier = transmissionResult.getTransmissionIdentifier(); + System.out.println(String.format("%s transmission took %s ms", + transmissionIdentifier, transmissionResult.getDuration())); + } + + OptionalDouble average = results.stream().mapToLong(TransmissionResult::getDuration).average(); + + if (average.isPresent()) { + System.out.println("Average transmission time was " + average.getAsDouble() + "ms"); + } + long elapsedInSeconds = TimeUnit.SECONDS.convert(elapsed, TimeUnit.NANOSECONDS); + System.out.println("Total time spent: " + elapsedInSeconds + "s"); + System.out.println("Attempted to send " + results.size() + " files"); + System.out.println("Failed transmissions: " + failed); + if (results.size() > 0 && elapsedInSeconds > 0) { + System.out.println("Transmission speed " + results.size() / elapsedInSeconds + " documents per second"); + } + + // Sleep if set to do so. + Integer sleepSecs = sleep.value(optionSet); + if (sleepSecs > 0) { + Thread.sleep(sleepSecs * 1000); + } + + System.exit(failed == 0 ? 0 : 1); + } + } + + /** + * Locates the files to load and transmit. + * + * @param payloadFileSpec specifies the name of the file or the directory holding files to be transmitted. + * @return list of eligible files. + */ + static List locateFiles(String payloadFileSpec) { + + List files = new ArrayList<>(); + if ("-".equals(payloadFileSpec)) { + + // Reads list of files from stdin + try (Reader reader = new InputStreamReader(System.in); + BufferedReader bufferedReader = new BufferedReader(reader)) { + files = bufferedReader.lines() + .map(File::new) + .collect(Collectors.toList()); + } catch (IOException e) { + log.warn(e.getMessage(), e); + } + } else { + File fileSpec = new File(payloadFileSpec); + if (!fileSpec.exists()) { + log.warn(String.format("'%s' does not exists.", fileSpec.getAbsolutePath())); + } else if (fileSpec.isDirectory()) { + try (DirectoryStream stream = Files.newDirectoryStream(Paths.get(payloadFileSpec), "*.{XML,xml}")) { + for (Path path : stream) { + files.add(path.toFile()); + } + + } catch (IOException e) { + throw new IllegalStateException( + String.format("Unable to list files %s; %s", payloadFileSpec, e.getMessage()), e); + } + } else if (fileSpec.isFile()) { + files.add(fileSpec); + } else { + log.warn(String.format("'%s' is neither file nor directory.", fileSpec.getAbsoluteFile())); + } + } + + return files; + } + + + private static void printErrorMessage(String message) { + System.out.println(); + System.out.println("*** " + message); + System.out.println(); + } + + static OptionParser getOptionParser() { + OptionParser optionParser = new OptionParser(); + + fileSpec = optionParser.accepts("f", "File(s) to be transmitted") + .withRequiredArg().ofType(String.class); + + docType = optionParser.accepts("d", "Document type") + .withRequiredArg(); + profileType = optionParser.accepts("p", "Profile type") + .withRequiredArg(); + sender = optionParser.accepts("s", "sender [e.g. 9908:976098897]") + .withRequiredArg(); + recipient = optionParser.accepts("r", "recipient [e.g. 9908:976098897]") + .withRequiredArg(); + + evidencePath = optionParser.accepts("e", "Evidence storage dir") + .withRequiredArg().ofType(File.class); + useRequestFactory = optionParser.accepts("factory", "Use TransmissionRequestFactory (no overrides!)") + .withOptionalArg().ofType(Boolean.class).defaultsTo(false); + repeatCount = optionParser.accepts("repeat", "Number of repeats to use ") + .withRequiredArg().ofType(Integer.class).defaultsTo(1); + + probe = optionParser.accepts("probe", "Perform probing of endpoint.") + .withRequiredArg().ofType(Boolean.class).defaultsTo(false); + + destinationUrl = optionParser.accepts("u", "destination URL") + .requiredIf(probe, protocol).withRequiredArg(); + destinationCertificate = optionParser.accepts("cert", "Receiving AP's certificate (when overriding endpoint)") + .requiredIf(destinationUrl).withRequiredArg().ofType(File.class); + + protocol = optionParser.accepts("protocol", "Protocol to be used") + .withRequiredArg().ofType(String.class).defaultsTo(TransportProfile.AS2_1_0.getIdentifier()); + + maxTransmissions = optionParser.accepts("m", "Max number of transmissions") + .withRequiredArg().ofType(Integer.class).defaultsTo(Integer.MAX_VALUE); + + tag = optionParser.accepts("tag", "User defined tag") + .withRequiredArg(); + + sleep = optionParser.accepts("sleep", "Sleep standalone for x seconds after transmission.") + .withRequiredArg().ofType(Integer.class).defaultsTo(0); + + return optionParser; + } + + @SuppressWarnings("unused") + private static String enterPassword() { + System.out.print("Keystore password: "); + String password = null; + + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) { + password = bufferedReader.readLine(); + } catch (Exception e) { + log.error(e.getMessage(), e); + System.exit(1); + } + return password; + } +} diff --git a/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionParameters.java b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..24c75c733ef279c0f4d8c359825c3af6deaaae5e --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionParameters.java @@ -0,0 +1,132 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package eu.sendregning.oxalis; + +import network.oxalis.api.tag.Tag; +import network.oxalis.outbound.OxalisOutboundComponent; +import network.oxalis.vefa.peppol.common.model.DocumentTypeIdentifier; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import network.oxalis.vefa.peppol.common.model.ProcessIdentifier; + +import java.io.File; +import java.util.Optional; + +/** + * @author steinar + * Date: 08.01.2017 + * Time: 13.06 + * @author erlend + */ +class TransmissionParameters { + + private ParticipantIdentifier receiver; + + private ParticipantIdentifier sender; + + private DocumentTypeIdentifier docType; + + private ProcessIdentifier processIdentifier; + + private Endpoint endpoint; + + private File evidencePath; + + private String tag; + + private boolean useFactory; + + private OxalisOutboundComponent oxalisOutboundComponent; + + public TransmissionParameters(OxalisOutboundComponent oxalisOutboundComponent) { + this.oxalisOutboundComponent = oxalisOutboundComponent; + } + + public Optional getReceiver() { + return Optional.ofNullable(receiver); + } + + public void setReceiver(ParticipantIdentifier receiver) { + this.receiver = receiver; + } + + public Optional getSender() { + return Optional.ofNullable(sender); + } + + public void setSender(ParticipantIdentifier sender) { + this.sender = sender; + } + + public Optional getDocType() { + return Optional.ofNullable(docType); + } + + public void setDocType(DocumentTypeIdentifier documentTypeIdentifier) { + this.docType = documentTypeIdentifier; + } + + public Optional getProcessIdentifier() { + return Optional.ofNullable(processIdentifier); + } + + public void setProcessIdentifier(ProcessIdentifier processIdentifier) { + this.processIdentifier = processIdentifier; + } + + public File getEvidencePath() { + return evidencePath; + } + + public void setEvidencePath(File evidencePath) { + this.evidencePath = evidencePath; + } + + public OxalisOutboundComponent getOxalisOutboundComponent() { + return oxalisOutboundComponent; + } + + public boolean isUseFactory() { + return useFactory; + } + + public void setUseFactory(boolean useFactory) { + this.useFactory = useFactory; + } + + public Optional getEndpoint() { + return Optional.ofNullable(endpoint); + } + + public void setEndpoint(Endpoint endpoint) { + this.endpoint = endpoint; + } + + public Tag getTag() { + return this.tag == null ? Tag.NONE : Tag.of(this.tag); + } + + public void setTag(String tag) { + this.tag = tag; + } +} diff --git a/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionResult.java b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionResult.java new file mode 100644 index 0000000000000000000000000000000000000000..a38a35429ac6a8c546209925e5983e318ef18b1f --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionResult.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package eu.sendregning.oxalis; + +import network.oxalis.api.model.TransmissionIdentifier; + +/** + * @author steinar + * Date: 07.01.2017 + * Time: 22.44 + */ +public class TransmissionResult { + + private final long duration; + + private final TransmissionIdentifier transmissionIdentifier; + + + public TransmissionResult(long duration, TransmissionIdentifier transmissionIdentifier) { + this.duration = duration; + this.transmissionIdentifier = transmissionIdentifier; + } + + public long getDuration() { + return duration; + } + + public TransmissionIdentifier getTransmissionIdentifier() { + return transmissionIdentifier; + } +} diff --git a/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionTask.java b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionTask.java new file mode 100644 index 0000000000000000000000000000000000000000..98dd9963936f0bcf652b77d6d9f2c45eb1644187 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/java/eu/sendregning/oxalis/TransmissionTask.java @@ -0,0 +1,200 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package eu.sendregning.oxalis; + +import io.opentracing.Span; +import io.opentracing.Tracer; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.lang.EvidenceException; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.outbound.Transmitter; +import network.oxalis.commons.filesystem.FileUtils; +import network.oxalis.outbound.transmission.TransmissionRequestBuilder; +import network.oxalis.vefa.peppol.common.model.Endpoint; + +import java.io.*; +import java.nio.file.Files; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; + +/** + * @author steinar + * Date: 07.01.2017 + * Time: 22.43 + */ +@Slf4j +public class TransmissionTask implements Callable { + + private final TransmissionParameters params; + + private final File xmlPayloadFile; + + private final EvidenceFactory evidenceFactory; + + private final Tracer tracer; + + public TransmissionTask(TransmissionParameters params, File xmlPayloadFile) { + this.params = params; + this.xmlPayloadFile = xmlPayloadFile; + + this.evidenceFactory = params.getOxalisOutboundComponent().getEvidenceFactory(); + this.tracer = params.getOxalisOutboundComponent().getInjector().getInstance(Tracer.class); + } + + @Override + public TransmissionResult call() throws Exception { + Span span = tracer.buildSpan("standalone").start(); + try { + TransmissionResponse transmissionResponse; + long duration = 0; + + if (params.isUseFactory()) { + try (InputStream inputStream = Files.newInputStream(xmlPayloadFile.toPath())) { + transmissionResponse = params.getOxalisOutboundComponent() + .getTransmissionService() + .send(inputStream, params.getTag(), span); + } + } else { + + TransmissionRequest transmissionRequest = createTransmissionRequest(span); + + Transmitter transmitter; + Span span1 = tracer.buildSpan("get transmitter").asChildOf(span).start(); + try { + transmitter = params.getOxalisOutboundComponent().getTransmitter(); + } finally { + span1.finish(); + } + + // Performs the transmission + long start = System.nanoTime(); + transmissionResponse = performTransmission( + params.getEvidencePath(), transmitter, transmissionRequest, span); + long elapsed = System.nanoTime() - start; + duration = TimeUnit.MILLISECONDS.convert(elapsed, TimeUnit.NANOSECONDS); + + return new TransmissionResult(duration, transmissionResponse.getTransmissionIdentifier()); + } + return new TransmissionResult(duration, transmissionResponse.getTransmissionIdentifier()); + } finally { + span.finish(); + } + } + + protected TransmissionRequest createTransmissionRequest(Span root) { + Span span = tracer.buildSpan("create transmission request").asChildOf(root).start(); + try { + // creates a transmission request builder and enables trace + TransmissionRequestBuilder requestBuilder = + params.getOxalisOutboundComponent().getTransmissionRequestBuilder(); + + requestBuilder.setTransmissionBuilderOverride(true); + + // add receiver participant + if (params.getReceiver().isPresent()) { + requestBuilder.receiver(params.getReceiver().get()); + } + + // add sender participant + if (params.getSender().isPresent()) { + requestBuilder.sender(params.getSender().get()); + } + + if (params.getDocType().isPresent()) { + requestBuilder.documentType(params.getDocType().get()); + } + + if (params.getProcessIdentifier().isPresent()) { + requestBuilder.processType(params.getProcessIdentifier().get()); + } + + // Supplies the payload + try (InputStream inputStream = new FileInputStream(xmlPayloadFile)) { + requestBuilder.payLoad(inputStream); + } + + // Overrides the destination URL if so requested + if (params.getEndpoint().isPresent()) { + final Endpoint endpoint = params.getEndpoint().get(); + requestBuilder.overrideAs2Endpoint(endpoint); + } + + // Specifying the details completed, creates the transmission request + return requestBuilder.build(span); + } catch (Exception e) { + span.setTag("exception", String.valueOf(e.getMessage())); + System.out.println(); + System.out.println("Message failed : " + e.getMessage()); + //e.printStackTrace(); + System.out.println(); + return null; + } finally { + span.finish(); + } + } + + protected TransmissionResponse performTransmission(File evidencePath, Transmitter transmitter, + TransmissionRequest transmissionRequest, Span root) + throws OxalisTransmissionException, EvidenceException, IOException { + Span span = tracer.buildSpan("transmission").asChildOf(root).start(); + try { + // ... and performs the transmission + long start = System.nanoTime(); + TransmissionResponse transmissionResponse = transmitter.transmit(transmissionRequest, span); + long elapsed = System.nanoTime() - start; + + long durartionInMs = TimeUnit.MILLISECONDS.convert(elapsed, TimeUnit.NANOSECONDS); + // Write the transmission id and where the message was delivered + log.debug(String.format("Message using messageId %s sent to %s using %s was assigned transmissionId %s took %dms\n", + transmissionResponse.getHeader().getIdentifier().getIdentifier(), + transmissionResponse.getEndpoint().getAddress(), + transmissionResponse.getProtocol().getIdentifier(), + transmissionResponse.getTransmissionIdentifier(), + durartionInMs + )); + + saveEvidence(transmissionResponse, evidencePath, span); + + return transmissionResponse; + } finally { + span.finish(); + } + } + + protected void saveEvidence(TransmissionResponse transmissionResponse, File evidencePath, Span root) + throws IOException, EvidenceException { + Span span = tracer.buildSpan("save evidence").asChildOf(root).start(); + + String transIdent = FileUtils.filterString(transmissionResponse.getTransmissionIdentifier().toString()); + File evidenceFile = new File(evidencePath, transIdent + ".receipt.dat"); + + try (OutputStream outputStream = Files.newOutputStream(evidenceFile.toPath())) { + evidenceFactory.write(outputStream, transmissionResponse); + } finally { + span.finish(); + } + } +} diff --git a/oxalis-dist/oxalis-standalone/src/main/resources/logback.xml b/oxalis-dist/oxalis-standalone/src/main/resources/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..55bf20d4bef4d3eec6d456e4075990da80995f80 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/main/resources/logback.xml @@ -0,0 +1,39 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + diff --git a/oxalis-dist/oxalis-standalone/src/test/java/eu/sendregning/oxalis/MainTest.java b/oxalis-dist/oxalis-standalone/src/test/java/eu/sendregning/oxalis/MainTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a8bfb5b1996283bc295ce82dadefcf9c1c470267 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/test/java/eu/sendregning/oxalis/MainTest.java @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package eu.sendregning.oxalis; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import static org.testng.Assert.assertEquals; + +/** + * @author steinar + * Date: 08.01.2017 + * Time: 13.53 + */ +public class MainTest { + + + private Path tempDirectory; + + private Path tempFile; + + private Path tempFile2; + + private Path fileHoldingFileNames; + + @BeforeMethod + public void setUp() throws Exception { + tempDirectory = Files.createTempDirectory("unit"); + + tempFile = Files.createTempFile(tempDirectory, "TEST", ".xml"); + tempFile2 = Files.createTempFile(tempDirectory, "TEST2", ".xml"); + + fileHoldingFileNames = Files.createTempFile("test", ".txt"); + + List fileNames = Arrays.asList(tempFile.toString(), tempFile2.toString()); + Files.write(fileHoldingFileNames, fileNames); + } + + + /** + * Files may be located using any of the following specifications: + * + *
    + *
  • A single hyphen '-' indicates read list of files from stdin, one file per line
  • + *
  • A file referencing a file is, well a single file
  • + *
  • A file referencing a directory, indicates that all .xml files in that directory should be read
  • + *
  • A specification using '*' should be expanded
  • + *
+ * @throws Exception + */ + @Test + public void testLocateFiles() throws Exception { + + List files = Main.locateFiles(tempDirectory.toString()); + + assertEquals(files.size(), 2); + + files = Main.locateFiles(tempFile.toString()); + assertEquals(1, files.size()); + } + + @Test + public void testStdin() throws Exception { + + InputStream saved = System.in; + + System.setIn( new FileInputStream(fileHoldingFileNames.toFile()) ); + + List files = Main.locateFiles("-"); + assertEquals(2, files.size()); + System.setIn(saved); + + } +} + diff --git a/oxalis-dist/oxalis-standalone/src/test/resources/BII04_T10_EHF-v2.0_invoice.xml b/oxalis-dist/oxalis-standalone/src/test/resources/BII04_T10_EHF-v2.0_invoice.xml new file mode 100644 index 0000000000000000000000000000000000000000..32c3224cf12e54c72bf722a203d0229c03172260 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/test/resources/BII04_T10_EHF-v2.0_invoice.xml @@ -0,0 +1,495 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0 + urn:www.cenbii.eu:profile:bii04:ver2.0 + TOSL108 + 2009-12-15 + 380 + Ordered in our booth at the convention. + 2009-11-30 + EUR + Project cost code 123 + + 2009-11-01 + 2009-11-30 + + + 123 + + + Contract321 + Framework agreement + + + Doc1 + Timesheet + + + http://www.suppliersite.eu/sheet001.html + + + + + Doc2 + Drawing + + JVBERi0xLjQNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyhuYi1OTykgL091dHB1dEludGVudHNbPDwvVHlwZS9PdXRwdXRJbnRlbnQvUy9HVFNfUERGQTEvT3V0cHV0Q29uZGl0aW9uSWRlbnRpZmllcihzUkdCKSAvUmVnaXN0cnlOYW1lKGh0dHA6Ly93d3cuY29sb3Iub3JnKSAvSW5mbyhDcmVhdG9yOiBIUCAgICAgTWFudWZhY3R1cmVyOklFQyAgICBNb2RlbDpzUkdCKSAvRGVzdE91dHB1dFByb2ZpbGUgMTEgMCBSPj5dIC9NZXRhZGF0YSAxMiAwIFI+Pg0KZW5kb2JqDQoyIDAgb2JqDQo8PC9UeXBlL1BhZ2VzL0NvdW50IDEvS2lkc1sgMyAwIFJdID4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZS9QYXJlbnQgMiAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4vUHJvY1NldFsvUERGL1RleHQvSW1hZ2VCL0ltYWdlQy9JbWFnZUldID4+L01lZGlhQm94WyAwIDAgNTk1LjMyIDg0MS45Ml0gL0NvbnRlbnRzIDQgMCBSPj4NCmVuZG9iag0KNCAwIG9iag0KPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAxMjA+Pg0Kc3RyZWFtDQp4nHMK4eXSdzNUMDTUMzBRCEnj5TJUMABCQwVzAz0LIxMFczMDPTMLhZBcXi4DhXQQ4c7LFa3hqBCgqWus4aKpa6LhpmlorKGQkg9iJ5eCOLkgZmpeiZ5mrEKIFy+XK9AWpxCE2YYmFnpGRshmR2soIKkFAJQwHV8NCmVuZHN0cmVhbQ0KZW5kb2JqDQo1IDAgb2JqDQo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UcnVlVHlwZS9OYW1lL0YxL0Jhc2VGb250L0FCQ0RFRStDYWxpYnJpL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9Gb250RGVzY3JpcHRvciA2IDAgUi9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE3L1dpZHRocyA4IDAgUj4+DQplbmRvYmoNCjYgMCBvYmoNCjw8L1R5cGUvRm9udERlc2Ny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OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IjMuMS03MDEiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KPC9yZGY6RGVzY3JpcHRpb24+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiICB4bWxuczp4bXBSaWdodHM9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9yaWdodHMvIj4KPHhtcFJpZ2h0czpNYXJrZWQ+VHJ1ZTwveG1wUmlnaHRzOk1hcmtlZD48L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8L3JkZjpSREY+PC94OnhtcG1ldGE+PD94cGFja2V0IGVuZD0idyI/Pg0KZW5kc3RyZWFtDQplbmRvYmoNCjExIDAgb2JqDQo8PC9OIDMvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyNTkzPj4NCnN0cmVhbQ0KeJydlndUVNcWh8+9d3qhzTB0GHqvUgYQ6R2kV1EYZgYYygDDDNgLIioQUUSkKYIEBQwYDUViRRQLAVEBe0CCgBKDUWyoZEbWSnx5ee/l5ffHPd/aZ+9z99l737UuACQvPy4vHZYCII0n4Ad7utAjo6Lp2H4AAzzAAHMAmKysDP8Qj1Agkre7Kz1L5AT+Ra+HASRebxl7BdLp4P+TNCuDLwAAChTxEjYniyXiPBGn5ggyxPZZEVPjU8QMo8TMFyUoYnkxJy6y0WefRXYSMzuNxxaxOOcMdhpbzD0i3pEt5IgY8RNxfjaXkyPi2yLWShWmcUX8VhybxmFmAYAiie0CDitJxGYiJvFDg11FvBQAHCnxC47/ggWc1QLxpVzTM9bwuYlJAroeS59ubmvLoHtxclI5AoFxIJOV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OmFib3V0PSIiICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgo8ZGM6Y3JlYXRvcj48cmRmOlNlcT48cmRmOmxpPnRlcmplaW88L3JkZjpsaT48L3JkZjpTZXE+PC9kYzpjcmVhdG9yPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KPHhtcDpDcmVhdG9yVG9vbD5NaWNyb3NvZnTCriBXb3JkIDIwMTA8L3htcDpDcmVhdG9yVG9vbD48eG1wOkNyZWF0ZURhdGU+MjAxMS0wNC0wNlQxOToyOTo0NCswMjowMDwveG1wOkNyZWF0ZURhdGU+PHhtcDpNb2RpZnlEYXRlPjIwMTEtMDQtMDZUMTk6Mjk6NDQrMDI6MDA8L3htcDpNb2RpZnlEYXRlPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eGFwTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iPgo8eGFwTU06RG9jdW1lbnRJRD40MjY3QUQyNy1GNDY2LTQ2NzMtOTJEMy1BOTM3RDRCODZFNEU8L3hhcE1NOkRvY3VtZW50SUQ+PHhhcE1NOkluc3RhbmNlSUQ+NDI2N0FEMjctRjQ2Ni00NjczLTkyRDMtQTkzN0Q0Qjg2RTRFPC94YXBNTTpJbnN0YW5jZUlEPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6cGRmYWlkPSJodHRwOi8vd3d3LmFpaW0ub3JnL3BkZmEvbnMvaWQvIj4KPHBkZmFpZDpwYXJ0PjE8L3BkZmFpZDpwYXJ0PjxwZGZhaWQ6Y29uZm9ybWFuY2U+QjwvcGRmYWlkOmNvbmZvcm1hbmNlPjwvcmRmOkRlc2NyaXB0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPC9yZGY6UkRGPjwveDp4bXBtZXRhPjw/eHBhY2tldCBlbmQ9InciPz4NCmVuZHN0cmVhbQ0KZW5kb2JqDQp4cmVmDQowIDEzDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDAwMTcgMDAwMDAgbg0KMDAwMDAwMDI5MyAwMDAwMCBuDQowMDAwMDAwMzQ5IDAwMDAwIG4NCjAwMDAwMDA1MTMgMDAwMDAgbg0KMDAwMDAwMDcwNyAwMDAwMCBuDQowMDAwMDAwODc0IDAwMDAwIG4NCjAwMDAwMDExMTIgMDAwMDAgbg0KMDAwMDAwMTMzMiAwMDAwMCBuDQowMDAwMDAxNTU0IDAwMDAwIG4NCjAwMDAwODE3ODMgMDAwMDAgbg0KMDAwMDA4MzMyOSAwMDAwMCBuDQowMDAwMDg2MDAyIDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgMTMvUm9vdCAxIDAgUi9JbmZvIDcgMCBSL0lEWzwyN0FENjc0MjY2RjQ3MzQ2OTJEM0E5MzdENEI4NkU0RT48MjdBRDY3NDI2NkY0NzM0NjkyRDNBOTM3RDRCODZFNEU+XSA+Pg0Kc3RhcnR4cmVmDQo4OTMwMA0KJSVFT0Y= + + + + + 1234567890123 + + Supp123 + + + Salescompany ltd. + + + 1231412341324 + 5467 + Main street + Suite 123 + 1 + Revenue department + Big city + 54321 + RegionA + + NO + + + + NO999999999MVA + + VAT + + + + The Sellercompany Incorporated + 810418052 + + Big city + RegionA + + DK + + + + + O. Hansen + 46211230 + 46211231 + antonio@salescompany.dk + + + Antonio + Salemacher + M + Sales manager + + + + + + 1234567987654 + + 345KS5324 + + + Buyercompany ltd + + + 1238764941386 + 123 + Anystreet + Back door + 8 + Accounting department + Anytown + 101 + RegionB + + BE + + + + BE54321 + + VAT + + + + The buyercompany inc. + 810418052 + + Mainplace + RegionB + + BE + + + + + 3150bdn + 5121230 + 5121231 + john@buyercompany.eu + + + John + Doe + X + Purchasing manager + + + + + + 098740918237 + + + Ebeneser Scrooge Inc. + + + 6411982340 + + + + 2009-12-15 + + 6754238987648 + + Deliverystreet + Side door + 12 + DeliveryCity + 523427 + RegionC + + BE + + + + + + 31 + 2009-12-31 + SW + Payref1 + + NO9386011117947 + + 9710 + + DNBANOKK + + + + + + Penalty percentage 10% from due date + + + true + Packing cost + 100 + + S + 25 + + VAT + + + + + false + Promotion discount + 100 + + S + 25 + + VAT + + + + + 292.20 + + 1460.5 + 292.1 + + S + 25 + + VAT + + + + + 1 + 0.1 + + AA + 10 + + VAT + + + + + -25 + 0 + + E + 0 + AAM + Exempt New Means of Transport + + VAT + + + + + + 1436.5 + 1436.5 + 1729 + 100 + 100 + 1000 + 0.30 + 729 + + + 1 + Scratch on box + 1 + 1273 + BookingCode001 + + 1 + + + false + Damage + 12 + + + true + Testing + 12 + + + 254.6 + + + Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM: 3MB. Screen 1440x900 + Laptop computer + + JB007 + + + 1234567890124 + + + 12344321 + + + 65434568 + + + S + 25 + + VAT + + + + Color + Black + + + + 1273 + 1 + + false + Contract + 0.15 + 225 + 1500 + + + + + 2 + Cover is slightly damaged. + -1 + -3.96 + BookingCode002 + + 5 + + + -0.396 + + + Returned "Advanced computing" book + + JB008 + + + 1234567890125 + + + 32344324 + + + 65434567 + + + AA + 10 + + VAT + + + + + 3.96 + 1 + + + + 3 + 2 + 4.96 + BookingCode003 + + 3 + + + 0.496 + + + "Computing for dummies" book + + JB009 + + + 1234567890126 + + + 32344324 + + + 65434566 + + + AA + 10 + + VAT + + + + + 2.48 + 1 + + false + Contract + 0.1 + 0.275 + 2.75 + + + + + 4 + -1 + -25 + BookingCode004 + + 2 + + + 0 + + + Returned IBM 5150 desktop + + JB010 + + + 1234567890127 + + + 12344322 + + + 65434565 + + + E + 0 + + VAT + + + + + 25 + 1 + + + + 5 + 250 + 187.5 + BookingCode005 + + 4 + + + 37.5 + + + Network cable + + JB011 + + + 1234567890128 + + + 12344325 + + + 65434564 + + + S + 25 + + VAT + + + + Type + Cat5 + + + + 0.75 + 1 + + + \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml b/oxalis-dist/oxalis-standalone/src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d9f46478339ab8ebe75bf33def7d33df00249a1 --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/test/resources/BII04_T10_PEPPOL-v2.0_invoice.xml @@ -0,0 +1,497 @@ + + + + + 2.1 + + urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0 + + urn:www.cenbii.eu:profile:bii04:ver2.0 + TOSL108 + 2009-12-15 + 380 + Ordered in our booth at the convention. + 2009-11-30 + EUR + Project cost code 123 + + 2009-11-01 + 2009-11-30 + + + 123 + + + Contract321 + Framework agreement + + + Doc1 + Timesheet + + + http://www.suppliersite.eu/sheet001.html + + + + + Doc2 + Drawing + + JVBERi0xLjQNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyhuYi1OTykgL091dHB1dEludGVudHNbPDwvVHlwZS9PdXRwdXRJbnRlbnQvUy9HVFNfUERGQTEvT3V0cHV0Q29uZGl0aW9uSWRlbnRpZmllcihzUkdCKSAvUmVnaXN0cnlOYW1lKGh0dHA6Ly93d3cuY29sb3Iub3JnKSAvSW5mbyhDcmVhdG9yOiBIUCAgICAgTWFudWZhY3R1cmVyOklFQyAgICBNb2RlbDpzUkdCKSAvRGVzdE91dHB1dFByb2ZpbGUgMTEgMCBSPj5dIC9NZXRhZGF0YSAxMiAwIFI+Pg0KZW5kb2JqDQoyIDAgb2JqDQo8PC9UeXBlL1BhZ2VzL0NvdW50IDEvS2lkc1sgMyAwIFJdID4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZS9QYXJlbnQgMiAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4vUHJvY1NldFsvUERGL1RleHQvSW1hZ2VCL0ltYWdlQy9JbWFnZUldID4+L01lZGlhQm94WyAwIDAgNTk1LjMyIDg0MS45Ml0gL0NvbnRlbnRzIDQgMCBSPj4NCmVuZG9iag0KNCAwIG9iag0KPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAxMjA+Pg0Kc3RyZWFtDQp4nHMK4eXSdzNUMDTUMzBRCEnj5TJUMABCQwVzAz0LIxMFczMDPTMLhZBcXi4DhXQQ4c7LFa3hqBCgqWus4aKpa6LhpmlorKGQkg9iJ5eCOLkgZmpeiZ5mrEKIFy+XK9AWpxCE2YYmFnpGRshmR2soIKkFAJQwHV8NCmVuZHN0cmVhbQ0KZW5kb2JqDQo1IDAgb2JqDQo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UcnVlVHlwZS9OYW1lL0YxL0Jhc2VGb250L0FCQ0RFRStDYWxpYnJpL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9Gb250RGVzY3JpcHRvciA2IDAgUi9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE3L1dpZHRocyA4IDAgUj4+DQplbmRvYmoNCjYgMCBvYmoNCjw8L1R5cGUvRm9udERlc2Ny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OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IjMuMS03MDEiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KPC9yZGY6RGVzY3JpcHRpb24+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiICB4bWxuczp4bXBSaWdodHM9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9yaWdodHMvIj4KPHhtcFJpZ2h0czpNYXJrZWQ+VHJ1ZTwveG1wUmlnaHRzOk1hcmtlZD48L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8L3JkZjpSREY+PC94OnhtcG1ldGE+PD94cGFja2V0IGVuZD0idyI/Pg0KZW5kc3RyZWFtDQplbmRvYmoNCjExIDAgb2JqDQo8PC9OIDMvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyNTkzPj4NCnN0cmVhbQ0KeJydlndUVNcWh8+9d3qhzTB0GHqvUgYQ6R2kV1EYZgYYygDDDNgLIioQUUSkKYIEBQwYDUViRRQLAVEBe0CCgBKDUWyoZEbWSnx5ee/l5ffHPd/aZ+9z99l737UuACQvPy4vHZYCII0n4Ad7utAjo6Lp2H4AAzzAAHMAmKysDP8Qj1Agkre7Kz1L5AT+Ra+HASRebxl7BdLp4P+TNCuDLwAAChTxEjYniyXiPBGn5ggyxPZZEVPjU8QMo8TMFyUoYnkxJy6y0WefRXYSMzuNxxaxOOcMdhpbzD0i3pEt5IgY8RNxfjaXkyPi2yLWShWmcUX8VhybxmFmAYAiie0CDitJxGYiJvFDg11FvBQAHCnxC47/ggWc1QLxpVzTM9bwuYlJAroeS59ubmvLoHtxclI5AoFxIJOV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OmFib3V0PSIiICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgo8ZGM6Y3JlYXRvcj48cmRmOlNlcT48cmRmOmxpPnRlcmplaW88L3JkZjpsaT48L3JkZjpTZXE+PC9kYzpjcmVhdG9yPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KPHhtcDpDcmVhdG9yVG9vbD5NaWNyb3NvZnTCriBXb3JkIDIwMTA8L3htcDpDcmVhdG9yVG9vbD48eG1wOkNyZWF0ZURhdGU+MjAxMS0wNC0wNlQxOToyOTo0NCswMjowMDwveG1wOkNyZWF0ZURhdGU+PHhtcDpNb2RpZnlEYXRlPjIwMTEtMDQtMDZUMTk6Mjk6NDQrMDI6MDA8L3htcDpNb2RpZnlEYXRlPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eGFwTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iPgo8eGFwTU06RG9jdW1lbnRJRD40MjY3QUQyNy1GNDY2LTQ2NzMtOTJEMy1BOTM3RDRCODZFNEU8L3hhcE1NOkRvY3VtZW50SUQ+PHhhcE1NOkluc3RhbmNlSUQ+NDI2N0FEMjctRjQ2Ni00NjczLTkyRDMtQTkzN0Q0Qjg2RTRFPC94YXBNTTpJbnN0YW5jZUlEPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6cGRmYWlkPSJodHRwOi8vd3d3LmFpaW0ub3JnL3BkZmEvbnMvaWQvIj4KPHBkZmFpZDpwYXJ0PjE8L3BkZmFpZDpwYXJ0PjxwZGZhaWQ6Y29uZm9ybWFuY2U+QjwvcGRmYWlkOmNvbmZvcm1hbmNlPjwvcmRmOkRlc2NyaXB0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPC9yZGY6UkRGPjwveDp4bXBtZXRhPjw/eHBhY2tldCBlbmQ9InciPz4NCmVuZHN0cmVhbQ0KZW5kb2JqDQp4cmVmDQowIDEzDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDAwMTcgMDAwMDAgbg0KMDAwMDAwMDI5MyAwMDAwMCBuDQowMDAwMDAwMzQ5IDAwMDAwIG4NCjAwMDAwMDA1MTMgMDAwMDAgbg0KMDAwMDAwMDcwNyAwMDAwMCBuDQowMDAwMDAwODc0IDAwMDAwIG4NCjAwMDAwMDExMTIgMDAwMDAgbg0KMDAwMDAwMTMzMiAwMDAwMCBuDQowMDAwMDAxNTU0IDAwMDAwIG4NCjAwMDAwODE3ODMgMDAwMDAgbg0KMDAwMDA4MzMyOSAwMDAwMCBuDQowMDAwMDg2MDAyIDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgMTMvUm9vdCAxIDAgUi9JbmZvIDcgMCBSL0lEWzwyN0FENjc0MjY2RjQ3MzQ2OTJEM0E5MzdENEI4NkU0RT48MjdBRDY3NDI2NkY0NzM0NjkyRDNBOTM3RDRCODZFNEU+XSA+Pg0Kc3RhcnR4cmVmDQo4OTMwMA0KJSVFT0Y= + + + + + 1234567890123 + + Supp123 + + + Salescompany ltd. + + + 1231412341324 + 5467 + Main street + Suite 123 + 1 + Revenue department + Big city + 54321 + RegionA + + NO + + + + NO999999999MVA + + VAT + + + + The Sellercompany Incorporated + 810418052 + + Big city + RegionA + + DK + + + + + O. Hansen + 46211230 + 46211231 + antonio@salescompany.dk + + + Antonio + Salemacher + M + Sales manager + + + + + + 1234567987654 + + 345KS5324 + + + Buyercompany ltd + + + 1238764941386 + 123 + Anystreet + Back door + 8 + Accounting department + Anytown + 101 + RegionB + + BE + + + + BE54321 + + VAT + + + + The buyercompany inc. + 810418052 + + Mainplace + RegionB + + BE + + + + + 3150bdn + 5121230 + 5121231 + john@buyercompany.eu + + + John + Doe + X + Purchasing manager + + + + + + 098740918237 + + + Ebeneser Scrooge Inc. + + + 6411982340 + + + + 2009-12-15 + + 6754238987648 + + Deliverystreet + Side door + 12 + DeliveryCity + 523427 + RegionC + + BE + + + + + + 31 + 2009-12-31 + SW + Payref1 + + NO9386011117947 + + 9710 + + DNBANOKK + + + + + + Penalty percentage 10% from due date + + + true + Packing cost + 100 + + S + 25 + + VAT + + + + + false + Promotion discount + 100 + + S + 25 + + VAT + + + + + 292.20 + + 1460.5 + 292.1 + + S + 25 + + VAT + + + + + 1 + 0.1 + + AA + 10 + + VAT + + + + + -25 + 0 + + E + 0 + AAM + Exempt New Means of Transport + + VAT + + + + + + 1436.5 + 1436.5 + 1729 + 100 + 100 + 1000 + 0.30 + 729 + + + 1 + Scratch on box + 1 + 1273 + BookingCode001 + + 1 + + + false + Damage + 12 + + + true + Testing + 12 + + + 254.6 + + + Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM: 3MB. Screen 1440x900 + Laptop computer + + JB007 + + + 1234567890124 + + + 12344321 + + + 65434568 + + + S + 25 + + VAT + + + + Color + Black + + + + 1273 + 1 + + false + Contract + 0.15 + 225 + 1500 + + + + + 2 + Cover is slightly damaged. + -1 + -3.96 + BookingCode002 + + 5 + + + -0.396 + + + Returned "Advanced computing" book + + JB008 + + + 1234567890125 + + + 32344324 + + + 65434567 + + + AA + 10 + + VAT + + + + + 3.96 + 1 + + + + 3 + 2 + 4.96 + BookingCode003 + + 3 + + + 0.496 + + + "Computing for dummies" book + + JB009 + + + 1234567890126 + + + 32344324 + + + 65434566 + + + AA + 10 + + VAT + + + + + 2.48 + 1 + + false + Contract + 0.1 + 0.275 + 2.75 + + + + + 4 + -1 + -25 + BookingCode004 + + 2 + + + 0 + + + Returned IBM 5150 desktop + + JB010 + + + 1234567890127 + + + 12344322 + + + 65434565 + + + E + 0 + + VAT + + + + + 25 + 1 + + + + 5 + 250 + 187.5 + BookingCode005 + + 4 + + + 37.5 + + + Network cable + + JB011 + + + 1234567890128 + + + 12344325 + + + 65434564 + + + S + 25 + + VAT + + + + Type + Cat5 + + + + 0.75 + 1 + + + \ No newline at end of file diff --git a/oxalis-dist/oxalis-standalone/src/test/resources/sbdh-asic.xml b/oxalis-dist/oxalis-standalone/src/test/resources/sbdh-asic.xml new file mode 100644 index 0000000000000000000000000000000000000000..2cc1bef31544daccc97bc7cdc1e857f6ba53a4ca --- /dev/null +++ b/oxalis-dist/oxalis-standalone/src/test/resources/sbdh-asic.xml @@ -0,0 +1,154 @@ + + + + 1.0 + + 9908:810018909 + + + 9908:810418052 + + + urn:oasis:names:specification:ubl:schema:xsd:Tender-2 + 2.1 + FA4A6819-6149-4134-95C3-C53A65338EB6 + Tender + 2015-07-26T20:08:00+01:00 + + + 1 + + application/vnd.etsi.asic-e+zip + #asic + ASiC archive containing the business documents. + + + + + PROCESSID + urn:www.cenbii.eu:profile:bii46:ver3.0 + + + DOCUMENTID + + urn:oasis:names:specification:ubl:schema:xsd:Tender-2::Tender##urn:www.cenbii.eu:transaction:biitrdm090:ver3.0::2.1 + + + + + + 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 + QS1JTkYvbWFuaWZlc3QueG1srZHBasMwDIbveQrj63CS3jaTtLc9wfYAaqyuBls2llKSPf2clMFg + MHqYbhK/vv8XGk5LDOqGhX2iUR/aXiukKTlPH6N+f3s1z1qxADkIiXDUK7I+HZuB+GAjkL8gi6oM + YltHo54L2QTsawsR2cpkU0ZyaZojkti79HvTbobHRtXaiRcf0FRZWdXeziGYDHIddaf3SUTnwcia + axTIOfgJpCbvbuRaFPZttZ4MPn36rLuHwHx217am+pu/CR7jSXGxf+kNz+foxUi9HYthiDngf/rc + iaYguIitLPIbLLhIlwN42phD9/Nnx+YLUEsHCFuZArnqAAAA+wEAAFBLAQIKAAoAAAgAAI1ZMEeK + IflFHwAAAB8AAAAIAAAAKAAAAAAAAAAAAAAAAABtaW1ldHlwZW1pbWV0eXBlPWFwcGxpY2F0aW9u + L3ZuZC5ldHNpLmFzaWMtZSt6aXBQSwECFAAUAAgICACNWTBH1R7KSasEAADfCwAACAAAAAAAAAAA + AAAAAABFAAAAc2JkaC54bWxQSwECFAAUAAgICACNWTBHqhrKndAGAABLEwAAIAAAAAAAAAAAAAAA + AAAmBQAAdHJkbTA5MC1zdWJtaXQtdGVuZGVyLXNhbXBsZS54bWxQSwECFAAUAAgICACNWTBHGHwq + qDcAAAA5AAAAEQAAAAAAAAAAAAAAAABEDAAAc2FtcGxlLXJlYWRtZS50eHRQSwECFAAUAAgICACN + WTBHjEPERu8BAABwBAAAGQAAAAAAAAAAAAAAAAC6DAAATUVUQS1JTkYvYXNpY21hbmlmZXN0Lnht + bFBLAQIUABQACAgIAI1ZMEeS19UY5gUAAGEHAAA7AAAAAAAAAAAAAAAAAPAOAABNRVRBLUlORi9z + aWduYXR1cmUtNGFjMjIwYTUtYzVkMi00YmFlLTliZmItODVhNjdhMDY3ZTZjLnA3c1BLAQIUABQA + CAgIAI1ZMEdbmQK56gAAAPsBAAAVAAAAAAAAAAAAAAAAAD8VAABNRVRBLUlORi9tYW5pZmVzdC54 + bWxQSwUGAAAAAAcABwAUAgAAbBYAACgAbWltZXR5cGU9YXBwbGljYXRpb24vdm5kLmV0c2kuYXNp + Yy1lK3ppcA== + + + diff --git a/oxalis-dist/oxalis-war/README.md b/oxalis-dist/oxalis-war/README.md new file mode 100644 index 0000000000000000000000000000000000000000..91562d3db9afce0db2c194f8c78ad8246bb854e2 --- /dev/null +++ b/oxalis-dist/oxalis-war/README.md @@ -0,0 +1,57 @@ +# Oxalis Web Archive (Oxalis WAR) + +The traditional war distribution for application servers recreated to use Java Servlet 3.0 functionality. +This is the distribution made available as `oxalis.war` in `oxalis-distribution`. + +It is recommended to create your own web archive (war) if you need to change anything inside the one provided by this project. +The following is a Maven configuration file (`pom.xml`) for your own project where you may customize Oxalis to your needs without having to change any existing artifacts. +This allow for the convenient deployment of a single web archive including your own code. + +```xml + + + 4.0.0 + + + com.example.peppol + oxalis + 1.0-SNAPSHOT + + + war + + + + 4.0.x + + + + + network.oxalis + oxalis-war + ${oxalis.version} + classes + + + + + + + oxalis + + + org.apache.maven.plugins + maven-war-plugin + 3.3.2 + + + false + + + + + + +``` diff --git a/oxalis-dist/oxalis-war/pom.xml b/oxalis-dist/oxalis-war/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..ef20f1943b9552165687cf3733f36f1aa1d8dcc9 --- /dev/null +++ b/oxalis-dist/oxalis-war/pom.xml @@ -0,0 +1,66 @@ + + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + ../../pom.xml + + 4.0.0 + + oxalis-war + war + + Oxalis :: Dist :: WAR + Oxalis WAR for deployment on application servers or as library for your own project. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + + dk.erst.oxalis + oxalis-inbound + + + + + javax.servlet + javax.servlet-api + provided + + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.3.2 + + false + + + + org.apache.maven.plugins + maven-jar-plugin + + + package + + jar + + + classes + + + + + + + + \ No newline at end of file diff --git a/oxalis-dist/oxalis-war/src/main/java/network/oxalis/dist/war/WarGuiceFilter.java b/oxalis-dist/oxalis-war/src/main/java/network/oxalis/dist/war/WarGuiceFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..7ae725ca229cf79af27a474c8d527e20ec060dd0 --- /dev/null +++ b/oxalis-dist/oxalis-war/src/main/java/network/oxalis/dist/war/WarGuiceFilter.java @@ -0,0 +1,23 @@ +package network.oxalis.dist.war; + +import com.google.inject.servlet.GuiceFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import java.io.IOException; + +/** + * @author erlend + */ +@WebFilter("/*") +public class WarGuiceFilter extends GuiceFilter { + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + super.doFilter(servletRequest, servletResponse, filterChain); + } +} diff --git a/oxalis-dist/oxalis-war/src/main/java/network/oxalis/dist/war/WarServletContextListener.java b/oxalis-dist/oxalis-war/src/main/java/network/oxalis/dist/war/WarServletContextListener.java new file mode 100644 index 0000000000000000000000000000000000000000..c8a49b4877cca16233b5ce8c400a39ca33fa8b5e --- /dev/null +++ b/oxalis-dist/oxalis-war/src/main/java/network/oxalis/dist/war/WarServletContextListener.java @@ -0,0 +1,13 @@ +package network.oxalis.dist.war; + +import network.oxalis.inbound.OxalisGuiceContextListener; + +import javax.servlet.annotation.WebListener; + +/** + * @author erlend + */ +@WebListener +public class WarServletContextListener extends OxalisGuiceContextListener { + +} diff --git a/oxalis-extension/oxalis-as2/pom.xml b/oxalis-extension/oxalis-as2/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..5da1b108dc62893d6aa28a5e1f6d0ebafb8d1bd2 --- /dev/null +++ b/oxalis-extension/oxalis-as2/pom.xml @@ -0,0 +1,95 @@ + + + + + 4.0.0 + + + dk.erst.oxalis + oxalis-extension + 5.5.0 + + + oxalis-as2 + jar + + Oxalis :: Ext :: AS2 + Library holding classes and stuff pertaining to AS2 + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + + dk.erst.oxalis + oxalis-test + test + + + + javax.servlet + javax.servlet-api + provided + + + + + ch.qos.logback + logback-classic + test + + + + + org.bouncycastle + bcmail-jdk15on + + + + com.sun.mail + jakarta.mail + + + jakarta.activation + jakarta.activation-api + + + + + com.google.inject.extensions + guice-servlet + provided + + + + + io.opentracing.contrib + opentracing-web-servlet-filter + + + + diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/As2Header.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/As2Header.java new file mode 100644 index 0000000000000000000000000000000000000000..512f0532d0bdd777475bbd132caa45239dfe070d --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/As2Header.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +/** + * Defines the AS2-Specific HTTP Headers according to RFC4130 section 6. + * + * @author steinar + * @author erlend + */ +public class As2Header { + + public static final String MESSAGE_ID = "Message-Id"; + + public static final String MIME_VERSION = "MIME-Version"; + + public static final String CONTENT_TYPE = "Content-Type"; + + public static final String AS2_VERSION = "AS2-Version"; + + public static final String AS2_FROM = "AS2-From"; + + public static final String AS2_TO = "AS2-To"; + + public static final String SUBJECT = "Subject"; + + public static final String DATE = "Date"; + + public static final String DISPOSITION_NOTIFICATION_TO = "Disposition-Notification-To"; + + public static final String DISPOSITION_NOTIFICATION_OPTIONS = "Disposition-Notification-Options"; + + public static final String RECEIPT_DELIVERY_OPTION = "Receipt-Delivery-Option"; + + public static final String SERVER = "Server"; + + // PEPPOL Transport Infrastructure AS2 Profile specifies AS2 version 1.0 + public static final String VERSION = "1.0"; + +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/Disposition.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/Disposition.java new file mode 100644 index 0000000000000000000000000000000000000000..2ef4b20098631fd7957fc7bbae87a2923550cc32 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/Disposition.java @@ -0,0 +1,153 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +import com.google.common.collect.ImmutableMap; +import network.oxalis.api.lang.VerifierException; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author erlend + */ +public class Disposition { + + private static final Pattern PATTERN = Pattern.compile("^(.*?); ([a-z]+)/([a-z]+): (.*)|(.*?); ([a-z]+)$"); + + private static final String SENT_AUTOMATICALLY = "automatic-action/MDN-sent-automatically"; + + public static final Disposition PROCESSED = new Disposition( + DispositionType.PROCESSED, null, null); + + public static final Disposition UNSUPPORTED_FORMAT = new Disposition( + DispositionType.FAILED, DispositionModifier.FAILURE, + DispositionModifierExtension.UNEXPECTED_PROCESSING_ERROR); + + public static final Disposition UNSUPPORTED_MIC_ALGORITHMS = new Disposition( + DispositionType.FAILED, DispositionModifier.FAILURE, + DispositionModifierExtension.UNSUPPORTED_MIC_ALGORITHMS); + + public static final Disposition SENDER_EQUALS_RECEIVER = new Disposition( + DispositionType.FAILED, DispositionModifier.FAILURE, + DispositionModifierExtension.SENDER_EQUALS_RECEIVER); + + public static final Disposition DECRYPTION_FAILED = new Disposition( + DispositionType.FAILED, DispositionModifier.ERROR, + DispositionModifierExtension.DECRYPTION_FAILED); + + public static final Disposition AUTHENTICATION_FAILED = new Disposition( + DispositionType.FAILED, DispositionModifier.ERROR, + DispositionModifierExtension.AUTHENTICATION_FAILED); + + public static final Disposition INTEGRITY_CHECK_FAILED = new Disposition( + DispositionType.FAILED, DispositionModifier.ERROR, + DispositionModifierExtension.INTEGRITY_CHECK_FAILED); + + public static final Disposition PARTICIPANT_NOT_ACCEPTED = new Disposition( + DispositionType.FAILED, DispositionModifier.ERROR, + DispositionModifierExtension.PARTICIPANT_NOT_ACCEPTED); + + public static final Disposition DOCUMENT_TYPE_ID_NOT_ACCEPTED = new Disposition( + DispositionType.FAILED, DispositionModifier.ERROR, + DispositionModifierExtension.DOCUMENT_TYPE_ID_NOT_ACCEPTED); + + public static final Disposition PROCESS_ID_NOT_ACCEPTED = new Disposition( + DispositionType.FAILED, DispositionModifier.ERROR, + DispositionModifierExtension.PROCESS_ID_NOT_ACCEPTED); + + public static final Disposition UNEXPECTED_PROCESSING_ERROR = new Disposition( + DispositionType.FAILED, DispositionModifier.ERROR, + DispositionModifierExtension.UNEXPECTED_PROCESSING_ERROR); + + public static final Disposition DUPLICATE_DOCUMENT = new Disposition( + DispositionType.PROCESSED, DispositionModifier.WARNING, + DispositionModifierExtension.DUPLICATE_DOCUMENT); + + private static Map verifierMap = + ImmutableMap.builder() + .put(VerifierException.Reason.DOCUMENT_TYPE, DOCUMENT_TYPE_ID_NOT_ACCEPTED) + .put(VerifierException.Reason.PROCESS, PROCESS_ID_NOT_ACCEPTED) + .put(VerifierException.Reason.PARTICIPANT, PARTICIPANT_NOT_ACCEPTED) + .build(); + + private DispositionType type; + + private DispositionModifier modifier; + + private DispositionModifierExtension extension; + + public static Disposition parse(String str) { + // Matcher matcher = PATTERN.matcher(str); + String cleaned = str.replaceAll("[ \r\n\t]+", " "); + + Matcher matcher = PATTERN.matcher(cleaned); + + if (matcher.matches()) { + if (matcher.group(1) == null) + return new Disposition( + DispositionType.of(matcher.group(6)), + null, null + ); + else + return new Disposition( + DispositionType.of(matcher.group(2)), + DispositionModifier.of(matcher.group(3)), + DispositionModifierExtension.of(matcher.group(4)) + ); + } + + throw new IllegalStateException(String.format("Unable to parseOld disposition '%s'.", str)); + } + + public static Disposition fromVerifierException(VerifierException e) { + return verifierMap.get(e.getReason()); + } + + private Disposition(DispositionType type, DispositionModifier modifier, DispositionModifierExtension extension) { + this.type = type; + this.modifier = modifier; + this.extension = extension; + } + + public DispositionType getType() { + return type; + } + + public DispositionModifier getModifier() { + return modifier; + } + + public DispositionModifierExtension getExtension() { + return extension; + } + + @Override + public String toString() { + if (modifier == null) + return String.format("%s; %s", SENT_AUTOMATICALLY, type); + else + return String.format("%s; %s/%s: %s", SENT_AUTOMATICALLY, type, modifier, extension); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionModifier.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionModifier.java new file mode 100644 index 0000000000000000000000000000000000000000..9e954447a8acf71707a24f3f66e4c5fd34f03832 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionModifier.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +/** + * @author erlend + */ +public enum DispositionModifier { + + FAILURE("failure"), + + ERROR("error"), + + WARNING("warning"); + + private String code; + + public static DispositionModifier of(String str) { + for (DispositionModifier modifier : values()) + if (modifier.code.equals(str)) + return modifier; + + throw new IllegalArgumentException(String.format("Unknown disposition modifier: %s", str)); + } + + DispositionModifier(String code) { + this.code = code; + } + + @Override + public String toString() { + return code; + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionModifierExtension.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionModifierExtension.java new file mode 100644 index 0000000000000000000000000000000000000000..78fb4788405f0b2323bf42ae57f6220236aad98e --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionModifierExtension.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +/** + * @author erlend + */ +public enum DispositionModifierExtension { + + UNSUPPORTED_FORMAT("unsupported format"), + + UNSUPPORTED_MIC_ALGORITHMS("unsupported MIC-algorithms"), + + SENDER_EQUALS_RECEIVER("sender-equals-receiver"), + + DECRYPTION_FAILED("decryption-failed"), + + AUTHENTICATION_FAILED("authentication-failed"), + + INTEGRITY_CHECK_FAILED("integrity-check-failed"), + + PARTICIPANT_NOT_ACCEPTED("participant-not-accepted"), + + DOCUMENT_TYPE_ID_NOT_ACCEPTED("document-modifier-id-not-accepted"), + + PROCESS_ID_NOT_ACCEPTED("process-id-not-accepted"), + + UNEXPECTED_PROCESSING_ERROR("unexpected-processing-error"), + + DUPLICATE_DOCUMENT("duplicate-document"); + + private final String value; + + public static DispositionModifierExtension of(String str) { + for (DispositionModifierExtension extension : values()) + if (extension.value.equals(str)) + return extension; + + throw new IllegalArgumentException(String.format("Unknown disposition modifier extension: %s", str)); + } + + DispositionModifierExtension(String extension) { + this.value = extension; + } + + @Override + public String toString() { + return value; + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionType.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionType.java new file mode 100644 index 0000000000000000000000000000000000000000..16a5e220b5c29b3fea235f3673921c35bc1bb22e --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/DispositionType.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +/** + * @author erlend + */ +public enum DispositionType { + + PROCESSED("processed"), + + FAILED("failed"); + + private String code; + + public static DispositionType of(String str) { + for (DispositionType modifier : values()) + if (modifier.code.equals(str)) + return modifier; + + throw new IllegalArgumentException(String.format("Unknown disposition type: %s", str)); + } + + DispositionType(String code) { + this.code = code; + } + + @Override + public String toString() { + return code; + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/MdnHeader.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/MdnHeader.java new file mode 100644 index 0000000000000000000000000000000000000000..64d1250e3b954fec0b8fc513cb408dad755269a0 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/code/MdnHeader.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +public class MdnHeader { + + public static final String REPORTING_UA = "Reporting-UA"; + + public static final String ORIGINAL_RECIPIENT = "Original-Recipient"; + + public static final String FINAL_RECIPIENT = "Final-Recipient"; + + public static final String ORIGINAL_MESSAGE_ID = "Original-Message-ID"; + + public static final String DISPOSITION = "Disposition"; + + public static final String RECEIVED_CONTENT_MIC = "Received-Content-Mic"; + + public static final String DATE = "Date"; + + public static final String ORIGINAL_CONTENT_HEADER = "X-Oxalis-Original-Content-Header"; + +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/common/As2CommonModule.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/common/As2CommonModule.java new file mode 100644 index 0000000000000000000000000000000000000000..c7331595ae378356661ea7910e4948c261892805 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/common/As2CommonModule.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.common; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.OxalisModule; + +/** + * @author erlend + * @since 4.0.2 + */ +public class As2CommonModule extends OxalisModule { + + @Override + protected void configure() { + bindSettings(As2Conf.class); + } + + @Provides + @Singleton + @Named("as2-notification") + public String getNotification(Settings settings) { + return settings.getString(As2Conf.NOTIFICATION); + } + +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/common/As2Conf.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/common/As2Conf.java new file mode 100644 index 0000000000000000000000000000000000000000..7c21f42843e302699497cd553687960149040553 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/common/As2Conf.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.common; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.2 + */ +@Title("AS2") +public enum As2Conf { + + @Path("oxalis.as2.notification") + @DefaultValue("not.in.use@difi.no") + NOTIFICATION, + +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundHandler.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..321e70ba94d978dcda0a8c44f42997b3b7e14c1b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundHandler.java @@ -0,0 +1,226 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.inbound; + +import com.google.inject.Inject; +import io.opentracing.Span; +import network.oxalis.api.header.HeaderParser; +import network.oxalis.api.identifier.MessageIdGenerator; +import network.oxalis.api.inbound.InboundService; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.lang.OxalisSecurityException; +import network.oxalis.api.lang.VerifierException; +import network.oxalis.api.model.Direction; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.tag.Tag; +import network.oxalis.api.tag.TagGenerator; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.api.timestamp.TimestampProvider; +import network.oxalis.api.transmission.TransmissionVerifier; +import network.oxalis.as2.code.As2Header; +import network.oxalis.as2.code.Disposition; +import network.oxalis.as2.code.MdnHeader; +import network.oxalis.as2.lang.OxalisAs2InboundException; +import network.oxalis.as2.model.Mic; +import network.oxalis.as2.util.*; +import network.oxalis.commons.mode.OxalisCertificateValidator; +import network.oxalis.vefa.peppol.common.code.Service; +import network.oxalis.vefa.peppol.common.model.Digest; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.security.lang.PeppolSecurityException; + +import javax.mail.internet.InternetHeaders; +import javax.mail.internet.MimeMessage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.nio.file.Path; +import java.security.NoSuchAlgorithmException; + +/** + * Main entry point for receiving AS2 messages. + * + * @author steinar + * @author thore + * @author erlend + */ +class As2InboundHandler { + + private final InboundService inboundService; + + private final TimestampProvider timestampProvider; + + private final PersisterHandler persisterHandler; + + private final TransmissionVerifier transmissionVerifier; + + private final OxalisCertificateValidator certificateValidator; + + private final SMimeMessageFactory sMimeMessageFactory; + + private final TagGenerator tagGenerator; + + private final MessageIdGenerator messageIdGenerator; + + private final HeaderParser headerParser; + + @Inject + public As2InboundHandler(InboundService inboundService, TimestampProvider timestampProvider, + OxalisCertificateValidator certificateValidator, PersisterHandler persisterHandler, + TransmissionVerifier transmissionVerifier, SMimeMessageFactory sMimeMessageFactory, + TagGenerator tagGenerator, MessageIdGenerator messageIdGenerator, + HeaderParser headerParser) { + this.inboundService = inboundService; + this.timestampProvider = timestampProvider; + this.certificateValidator = certificateValidator; + + this.persisterHandler = persisterHandler; + this.transmissionVerifier = transmissionVerifier; + + this.sMimeMessageFactory = sMimeMessageFactory; + + this.tagGenerator = tagGenerator; + this.messageIdGenerator = messageIdGenerator; + this.headerParser = headerParser; + } + + /** + * Receives an AS2 Message in the form of a map of headers together with the payload, + * which is made available in an input stream + *

+ * If persisting message to the Message Repository fails, we have to return negative MDN. + * + * @param httpHeaders the http headers received + * @param mimeMessage supplies the MIME message + * @return MDN object to signal if everything is ok or if some error occurred while receiving + */ + public MimeMessage receive(InternetHeaders httpHeaders, MimeMessage mimeMessage, Span root) throws OxalisAs2InboundException { + TransmissionIdentifier transmissionIdentifier = null; + Header header = null; + Path payloadPath = null; + OxalisAs2InboundException exception; + + try { + SignedMessage message = SignedMessage.load(mimeMessage); + + // Validate content + message.validate(Service.AP, certificateValidator, + httpHeaders.getHeader(As2Header.AS2_FROM)[0].replace("\"", "")); + + // Get timestamp using signature as input + Timestamp t2 = timestampProvider.generate(message.getSignature(), Direction.IN); + + Tag tag = tagGenerator.generate(Direction.IN); + + // Initiate MDN + MdnBuilder mdnBuilder = MdnBuilder.newInstance(mimeMessage); + mdnBuilder.addHeader(MdnHeader.DATE, t2.getDate()); + + // Extract Message-ID + transmissionIdentifier = TransmissionIdentifier.fromHeader(httpHeaders.getHeader(As2Header.MESSAGE_ID)[0]); + mdnBuilder.addHeader(MdnHeader.ORIGINAL_MESSAGE_ID, httpHeaders.getHeader(As2Header.MESSAGE_ID)[0]); + + // Extract digest algorithm + SMimeDigestMethod digestMethod = SMimeDigestMethod.findByIdentifier(message.getMicalg()); + + // Extract content headers + byte[] headerBytes = message.getBodyHeader(); + mdnBuilder.addHeader(MdnHeader.ORIGINAL_CONTENT_HEADER, headerBytes); + + byte[] content = message.getContentBytes(); + + // Extract header + header = headerParser.parse(new ByteArrayInputStream(content)); + + // Perform validation of header + transmissionVerifier.verify(header, Direction.IN); + + // Create "fresh" InputStream + try (InputStream payloadInputStream = new ByteArrayInputStream(content)) { + // Persist content + payloadPath = persisterHandler.persist(transmissionIdentifier, header, payloadInputStream); + } + + // Fetch calculated digest + Digest calculatedDigest = Digest.of(digestMethod.getDigestMethod(), message.getDigest()); + mdnBuilder.addHeader(MdnHeader.RECEIVED_CONTENT_MIC, new Mic(calculatedDigest)); + + // Generate Message-Id + String messageId = messageIdGenerator.generate(new As2InboundMetadata(transmissionIdentifier, header, t2, + null, null, message.getSigner(), null, tag)); + + if (!MessageIdUtil.verify(messageId)) + throw new OxalisAs2InboundException( + "Invalid Message-ID '" + messageId + "' generated.", + Disposition.UNEXPECTED_PROCESSING_ERROR); + + // Create receipt (MDN) + mdnBuilder.addHeader(MdnHeader.DISPOSITION, Disposition.PROCESSED); + MimeMessage mdn = sMimeMessageFactory.createSignedMimeMessage(mdnBuilder.build(), digestMethod); + // MimeMessage mdn = sMimeMessageFactory.createSignedMimeMessageNew(mdnBuilder.build(), calculatedDigest, digestMethod); + mdn.setHeader(As2Header.MESSAGE_ID, messageId); + mdn.setHeader(As2Header.AS2_VERSION, As2Header.VERSION); + mdn.setHeader(As2Header.AS2_FROM, httpHeaders.getHeader(As2Header.AS2_TO)[0]); + mdn.setHeader(As2Header.AS2_TO, httpHeaders.getHeader(As2Header.AS2_FROM)[0]); + + // Prepare MDN + ByteArrayOutputStream mdnOutputStream = new ByteArrayOutputStream(); + mdn.writeTo(mdnOutputStream); + + // Persist metadata + As2InboundMetadata inboundMetadata = new As2InboundMetadata(transmissionIdentifier, header, t2, + digestMethod.getTransportProfile(), calculatedDigest, message.getSigner(), mdnOutputStream.toByteArray(), tag); + persisterHandler.persist(inboundMetadata, payloadPath); + + // Persist statistics + inboundService.complete(inboundMetadata); + + return mdn; + } catch (OxalisContentException e) { + exception = new OxalisAs2InboundException(Disposition.UNSUPPORTED_FORMAT, e.getMessage(), e); + persisterHandler.persist(transmissionIdentifier, header, payloadPath, exception); + throw exception; + } catch (NoSuchAlgorithmException e) { + exception = new OxalisAs2InboundException(Disposition.UNSUPPORTED_MIC_ALGORITHMS, e.getMessage(), e); + persisterHandler.persist(transmissionIdentifier, header, payloadPath, exception); + throw exception; + } catch (VerifierException e) { + exception = new OxalisAs2InboundException(Disposition.fromVerifierException(e), e.getMessage(), e); + persisterHandler.persist(transmissionIdentifier, header, payloadPath, exception); + throw exception; + } catch (PeppolSecurityException e) { + exception = new OxalisAs2InboundException(Disposition.AUTHENTICATION_FAILED, e.getMessage(), e); + persisterHandler.persist(transmissionIdentifier, header, payloadPath, exception); + throw exception; + } catch (OxalisSecurityException e) { + exception = new OxalisAs2InboundException(Disposition.INTEGRITY_CHECK_FAILED, e.getMessage(), e); + persisterHandler.persist(transmissionIdentifier, header, payloadPath, exception); + throw exception; + } catch (Exception e) { + exception = new OxalisAs2InboundException(Disposition.UNEXPECTED_PROCESSING_ERROR, e.getMessage(), e); + persisterHandler.persist(transmissionIdentifier, header, payloadPath, exception); + throw exception; + } + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundMetadata.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundMetadata.java new file mode 100644 index 0000000000000000000000000000000000000000..5a376105f62d081787050557003571a9c3a43f92 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundMetadata.java @@ -0,0 +1,146 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.inbound; + +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.tag.Tag; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.vefa.peppol.common.model.*; + +import java.security.cert.X509Certificate; +import java.util.*; + +/** + * @author erlend + */ +class As2InboundMetadata implements InboundMetadata { + + private final TransmissionIdentifier transmissionIdentifier; + + private final Header header; + + private final Date timestamp; + + private final TransportProfile transportProfile; + + private final Digest digest; + + private final Receipt primaryReceipt; + + private final List receipts; + + private final X509Certificate certificate; + + private final Tag tag; + + public As2InboundMetadata(TransmissionIdentifier transmissionIdentifier, Header header, Timestamp timestamp, + TransportProfile transportProfile, Digest digest, X509Certificate certificate, + byte[] primaryReceipt, Tag tag) { + this.transmissionIdentifier = transmissionIdentifier; + this.header = header; + this.timestamp = timestamp.getDate(); + this.transportProfile = transportProfile; + this.digest = digest; + this.certificate = certificate; + this.primaryReceipt = Receipt.of("message/disposition-notification", primaryReceipt); + this.tag = tag; + + List receipts = new ArrayList<>(); + receipts.add(this.primaryReceipt); + if (timestamp.getReceipt().isPresent()) + receipts.add(timestamp.getReceipt().get()); + this.receipts = Collections.unmodifiableList(receipts); + } + + public TransmissionIdentifier getTransmissionIdentifier() { + return transmissionIdentifier; + } + + @Override + public Header getHeader() { + return header; + } + + @Override + public Date getTimestamp() { + return timestamp; + } + + @Override + public TransportProfile getProtocol() { + return transportProfile; + } + + @Override + public TransportProtocol getTransportProtocol() { + return TransportProtocol.AS2; + } + + @Override + public Digest getDigest() { + return digest; + } + + @Override + public List getReceipts() { + return receipts; + } + + @Override + public Receipt primaryReceipt() { + return primaryReceipt; + } + + @Override + public X509Certificate getCertificate() { + return certificate; + } + + @Override + public Tag getTag() { + return tag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + As2InboundMetadata that = (As2InboundMetadata) o; + return Objects.equals(transmissionIdentifier, that.transmissionIdentifier) && + Objects.equals(header, that.header) && + Objects.equals(timestamp, that.timestamp) && + Objects.equals(transportProfile, that.transportProfile) && + Objects.equals(digest, that.digest) && + Objects.equals(primaryReceipt, that.primaryReceipt) && + Objects.equals(receipts, that.receipts) && + Objects.equals(certificate, that.certificate) && + Objects.equals(tag, that.tag); + } + + @Override + public int hashCode() { + return Objects.hash(transmissionIdentifier, header, timestamp, transportProfile, + digest, primaryReceipt, receipts, certificate, tag); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundModule.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundModule.java new file mode 100644 index 0000000000000000000000000000000000000000..3837395d625fc9924f65fcf5bb876fdc1113df15 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2InboundModule.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.inbound; + +import com.google.inject.Key; +import com.google.inject.name.Names; +import com.google.inject.servlet.ServletModule; + +import javax.servlet.http.HttpServlet; + +/** + * Guice module providing AS2 implementation for inbound. + * + * @author erlend + * @since 4.0.0 + */ +public class As2InboundModule extends ServletModule { + + @Override + protected void configureServlets() { + bind(Key.get(HttpServlet.class, Names.named("oxalis-as2"))) + .to(As2Servlet.class) + .asEagerSingleton(); + + serve("/as2*").with(Key.get(HttpServlet.class, Names.named("oxalis-as2"))); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2Servlet.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2Servlet.java new file mode 100644 index 0000000000000000000000000000000000000000..96ff09b8c4f20638e565fade7050b4cd82c1ece5 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/inbound/As2Servlet.java @@ -0,0 +1,235 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.inbound; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import io.opentracing.Span; +import io.opentracing.SpanContext; +import io.opentracing.Tracer; +import io.opentracing.contrib.web.servlet.filter.TracingFilter; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.model.Direction; +import network.oxalis.as2.code.As2Header; +import network.oxalis.as2.code.MdnHeader; +import network.oxalis.as2.lang.OxalisAs2InboundException; +import network.oxalis.as2.util.*; +import network.oxalis.commons.security.CertificateUtils; +import org.slf4j.MDC; + +import javax.mail.Header; +import javax.mail.MessagingException; +import javax.mail.internet.InternetHeaders; +import javax.mail.internet.MimeMessage; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author steinar + * @author thore + * @author erlend + */ +@Slf4j +@Singleton +class As2Servlet extends HttpServlet { + + private final Provider inboundHandlerProvider; + + private final SMimeMessageFactory sMimeMessageFactory; + + private final ErrorTracker errorTracker; + + private final String toIdentifier; + + private final Tracer tracer; + + @Inject + public As2Servlet(Provider inboundHandlerProvider, SMimeMessageFactory sMimeMessageFactory, + ErrorTracker errorTracker, X509Certificate certificate, Tracer tracer) { + this.inboundHandlerProvider = inboundHandlerProvider; + this.sMimeMessageFactory = sMimeMessageFactory; + this.errorTracker = errorTracker; + this.toIdentifier = CertificateUtils.extractCommonName(certificate); + this.tracer = tracer; + } + + /** + * Receives the POST'ed AS2 message. + *

+ * Important to note that the HTTP headers contains the MIME headers for the payload. + * Since the the request can only be read once, using getReader()/getInputStream() + */ + @Override + protected void doPost(final HttpServletRequest request, final HttpServletResponse response) + throws IOException { + + // Fail fast when Message-Id header is not provided. + if (request.getHeader("message-id") == null) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + response.getWriter().println("Header field 'Message-ID' not found."); + return; + } + + // Fail fast when AS2-To is not provided or not addressed to me. + if (request.getHeader("as2-to") == null) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + response.getWriter().println("Header field 'AS2-To' not found."); + return; + } else if (!toIdentifier.equals(request.getHeader("as2-to").replace("\"", "").trim())) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + response.getWriter().println("Invalid value in field 'AS2-To'."); + return; + } + + if (request.getHeader("as2-from") == null) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + response.getWriter().println("Header field 'AS2-From' not found."); + return; + } + + SpanContext spanContext = (SpanContext) request.getAttribute(TracingFilter.SERVER_SPAN_CONTEXT); + + Span root = tracer.buildSpan("as2servlet.post").asChildOf(spanContext).start(); + + // Receives the data, validates the headers, signature etc., invokes the persistence handler + // and finally returns the MdnData to be sent back to the caller + try { + root.setTag("message-id", request.getHeader("message-id")); + MDC.put("message-id", request.getHeader("message-id")); + + // Read all headers + InternetHeaders headers = new InternetHeaders(); + Collections.list(request.getHeaderNames()) + .forEach(name -> headers.addHeader(name, request.getHeader(name))); + + // Read MIME message + MimeMessage mimeMessage = MimeMessageHelper.parse(request.getInputStream(), headers); + + try { + // Performs the actual reception of the message by parsing the HTTP POST request + // persisting the payload etc. + + Span span = tracer.buildSpan("as2message").asChildOf(root).start(); + MimeMessage mdn = inboundHandlerProvider.get().receive(headers, mimeMessage, span); + span.finish(); + + // Returns the MDN + span = tracer.buildSpan("mdn").asChildOf(root).start(); + writeMdn(response, mdn, HttpServletResponse.SC_OK); + span.finish(); + + } catch (OxalisAs2InboundException e) { + String identifier = errorTracker.track(Direction.IN, e, true); + + root.setTag("identifier", identifier); + root.setTag("exception", String.valueOf(e.getMessage())); + + // Begin builder + MdnBuilder mdnBuilder = MdnBuilder.newInstance(mimeMessage); + + // Original Message-Id + mdnBuilder.addHeader(MdnHeader.ORIGINAL_MESSAGE_ID, headers.getHeader(As2Header.MESSAGE_ID)[0]); + + // Disposition from exception + mdnBuilder.addHeader(MdnHeader.DISPOSITION, e.getDisposition()); + mdnBuilder.addText(String.format("Error [%s]", identifier), e.getMessage()); + + // Build and add headers + MimeMessage mdn = sMimeMessageFactory.createSignedMimeMessage(mdnBuilder.build(), + SMimeDigestMethod.findByIdentifier(SignedMessage.extractMicalg(mimeMessage))); + mdn.setHeader(As2Header.AS2_VERSION, As2Header.VERSION); + mdn.setHeader(As2Header.AS2_FROM, toIdentifier); + mdn.setHeader(As2Header.AS2_TO, headers.getHeader(As2Header.AS2_FROM)[0]); + + writeMdn(response, mdn, HttpServletResponse.SC_BAD_REQUEST); + } + } catch (Exception e) { + String identifier = errorTracker.track(Direction.IN, e, false); + + root.setTag("identifier", identifier); + root.setTag("exception", String.valueOf(e.getMessage())); + + // Unexpected internal error, cannot proceed, return HTTP 500 and partly MDN to indicating the problem + writeFailureWithExplanation(request, response, e); + } finally { + MDC.remove("message-id"); + root.finish(); + } + } + + protected void writeMdn(HttpServletResponse response, MimeMessage mdn, int status) + throws MessagingException, IOException { + // Set HTTP status. + response.setStatus(status); + + // Add headers and collect header names. + Map headers = Collections.list((Enumeration) mdn.getAllHeaders()).stream() + .map(Header.class::cast) + .collect(Collectors.toMap(Header::getName, Header::getValue)); + + // Move headers + for (String name : headers.keySet()) { + response.setHeader(name, headers.get(name)); + mdn.removeHeader(name); + } + + // Write MDN content to response. + ByteStreams.copy(mdn.getInputStream(), response.getOutputStream()); + } + + /** + * If the AS2 message processing failed with an exception, we have an internal error and act accordingly + */ + void writeFailureWithExplanation(HttpServletRequest request, HttpServletResponse response, Exception e) + throws IOException { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + + log.error("Request headers:"); + Collections.list(request.getHeaderNames()) + .forEach(name -> log.error("=> {}: {}", name, request.getHeader(name))); + + response.getWriter().write("INTERNAL ERROR!!"); + // Being helpful to those who must read the error logs + log.error("\n---------- REQUEST FAILURE INFORMATION ENDS HERE --------------"); + } + + /** + * Allows for simple http GET requests + */ + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws IOException { + response.setStatus(HttpServletResponse.SC_OK); + response.getOutputStream().println("Hello AS2 world\n"); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/lang/OxalisAs2Exception.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/lang/OxalisAs2Exception.java new file mode 100644 index 0000000000000000000000000000000000000000..9934061dfb77b2dff9d065cb8f721e0fb4f169e3 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/lang/OxalisAs2Exception.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.lang; + +import network.oxalis.api.lang.OxalisException; + +public class OxalisAs2Exception extends OxalisException { + + public OxalisAs2Exception(String message) { + super(message); + } + + public OxalisAs2Exception(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/lang/OxalisAs2InboundException.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/lang/OxalisAs2InboundException.java new file mode 100644 index 0000000000000000000000000000000000000000..549c3b76604f88dfc9a28fe00c3962e6ffc33b19 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/lang/OxalisAs2InboundException.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.lang; + +import network.oxalis.as2.code.Disposition; + +/** + * @author erlend + */ +public class OxalisAs2InboundException extends OxalisAs2Exception { + + private Disposition disposition; + + public OxalisAs2InboundException(String message, Disposition disposition) { + super(message); + this.disposition = disposition; + } + + public OxalisAs2InboundException(Disposition disposition, String message, Throwable cause) { + super(message, cause); + this.disposition = disposition; + } + + public Disposition getDisposition() { + return disposition; + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/As2Disposition.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/As2Disposition.java new file mode 100644 index 0000000000000000000000000000000000000000..a5c9bb95aa70420caf97547e3c09226a420949b3 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/As2Disposition.java @@ -0,0 +1,268 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.model; + +import lombok.Getter; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represents an instance of an AS2 Disposition header to be used in an MDN + *

+ *           automatic-action/MDN-sent-automatically; processed/error: Unknown recipient
+ * 
+ * + * @author steinar + * Date: 09.10.13 + * Time: 21:06 + */ +@Getter +public class As2Disposition { + + public static Pattern pattern = Pattern.compile("(?i)(manual-action|automatic-action)\\s*/\\s*(MDN-sent-automatically|MDN-sent-manually)\\s*;\\s*(processed|failed)\\s*(/\\s*(error|warning|failure)\\s*:?\\s*(.*)){0,1}"); + + ActionMode actionMode; + + SendingMode sendingMode; + + DispositionType dispositionType; // processed | failed + + /** + * Optional. If present, a warning or an error was issued + */ + DispositionModifier dispositionModifier; + + public As2Disposition(ActionMode actionMode, SendingMode sendingMode, DispositionType dispositionType) { + this.actionMode = actionMode; + this.sendingMode = sendingMode; + this.dispositionType = dispositionType; + } + + public As2Disposition(ActionMode actionMode, SendingMode sendingMode, DispositionType dispositionType, DispositionModifier dispositionModifier) { + this.actionMode = actionMode; + this.sendingMode = sendingMode; + this.dispositionType = dispositionType; + + // Only processed/error or processed/warning is allowed + if (dispositionType == DispositionType.PROCESSED && (dispositionModifier.prefix == DispositionModifier.Prefix.FAILURE)) { + throw new IllegalArgumentException("DispositionType 'processed' does not allow a prefix of 'failed'. Only 'error' and 'warning' are allowed"); + } + this.dispositionModifier = dispositionModifier; + } + + public static As2Disposition processed() { + return new As2Disposition(ActionMode.AUTOMATIC, SendingMode.AUTOMATIC, DispositionType.PROCESSED); + } + + public static As2Disposition processedWithWarning(String warningMessage) { + return new As2Disposition(ActionMode.AUTOMATIC, SendingMode.AUTOMATIC, DispositionType.PROCESSED, DispositionModifier.warning(warningMessage)); + } + + public static As2Disposition processedWithError(String errorMessage) { + return new As2Disposition(ActionMode.AUTOMATIC, SendingMode.AUTOMATIC, DispositionType.PROCESSED, DispositionModifier.error(errorMessage)); + } + + public static As2Disposition failed(String message) { + return new As2Disposition(ActionMode.AUTOMATIC, SendingMode.AUTOMATIC, DispositionType.FAILED, DispositionModifier.failed(message)); + } + + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(actionMode.getTextValue() + "/" + sendingMode.getTextValue() + "; " + dispositionType.getTextValue()); + if (dispositionModifier != null) { + sb.append('/'); + sb.append(dispositionModifier.toString()); + } + return sb.toString(); + } + + + public static As2Disposition valueOf(String s) { + String str = s == null ? "" : s.trim(); + + Matcher matcher = pattern.matcher(str); + if (!matcher.matches()) { + throw new IllegalArgumentException("'" + str + "'" + " does not match pattern for As2Disposition"); + } + + String actionModeString = matcher.group(1); + ActionMode actionMode = ActionMode.createFromTextValue(actionModeString); + + String sendingModeString = matcher.group(2); + SendingMode sendingMode = SendingMode.createFromTextValue(sendingModeString); + + String dispositionTypeString = matcher.group(3); + DispositionType dispositionType = DispositionType.valueOf(dispositionTypeString.toUpperCase()); + + As2Disposition result; + if (matcher.group(4) != null) { + DispositionModifier dispositionModifier; + String dispositionModifierPrefixString = matcher.group(5); + String dispositionModifierString = matcher.group(6); + dispositionModifier = new DispositionModifier(DispositionModifier.Prefix.valueOf(dispositionModifierPrefixString.toUpperCase()), dispositionModifierString); + result = new As2Disposition(actionMode, sendingMode, dispositionType, dispositionModifier); + } else { + result = new As2Disposition(actionMode, sendingMode, dispositionType); + } + + return result; + } + + public enum ActionMode { + MANUAL("manual-action"), AUTOMATIC("automatic-action"); + + private final String textValue; + + ActionMode(String textValue) { + + this.textValue = textValue; + } + + String getTextValue() { + return textValue; + } + + public static ActionMode createFromTextValue(String textValue) { + for (ActionMode actionMode : values()) { + if (actionMode.getTextValue().equalsIgnoreCase(textValue)) { + return actionMode; + } + } + throw new IllegalArgumentException(textValue.toLowerCase() + " not recognised as a valid ActionMode"); + } + + } + + public enum SendingMode { + MANUAL("MDN-sent-manually"), AUTOMATIC("MDN-sent-automatically"); + + private final String textValue; + + SendingMode(String textValue) { + this.textValue = textValue; + } + + public String getTextValue() { + return textValue; + } + + public static SendingMode createFromTextValue(String textValue) { + for (SendingMode sendingMode : values()) { + if (sendingMode.getTextValue().equalsIgnoreCase(textValue)) { + return sendingMode; + } + } + throw new IllegalArgumentException(textValue.toLowerCase() + " not recognised as a valid ActionMode"); + } + } + + public enum DispositionType { + PROCESSED("processed"), FAILED("failed"); + + private final String textValue; + + DispositionType(String textValue) { + this.textValue = textValue; + } + + public String getTextValue() { + return textValue; + } + + } + + public static class DispositionModifier { + + public enum Prefix { + ERROR, WARNING, FAILURE + } + + private final Prefix prefix; + + private final String dispositionModifierExtension; + + DispositionModifier(Prefix prefix, String dispositionModifierExtension) { + this.prefix = prefix; + this.dispositionModifierExtension = dispositionModifierExtension; + } + + public Prefix getPrefix() { + return prefix; + } + + public String getDispositionModifierExtension() { + return dispositionModifierExtension; + } + + public static DispositionModifier authenticationFailedError() { + return new DispositionModifier(Prefix.ERROR, "authentication-failed"); + } + + public static DispositionModifier decompressionFailedError() { + return new DispositionModifier(Prefix.ERROR, "decompression-failed"); + } + + public static DispositionModifier decryptionFailedError() { + return new DispositionModifier(Prefix.ERROR, "decryption-failed"); + } + + public static DispositionModifier insufficientMessageSecurityError() { + return new DispositionModifier(Prefix.ERROR, "insufficient-message-security"); + } + + public static DispositionModifier integrityCheckFailedError() { + return new DispositionModifier(Prefix.ERROR, "integrity-check-failed"); + } + + public static DispositionModifier unexpectedProcessingError() { + return new DispositionModifier(Prefix.ERROR, "unexpected-processing-error"); + } + + public static DispositionModifier warning(String description) { + return new DispositionModifier(Prefix.WARNING, description); + } + + public static DispositionModifier unsupportedFormatFailure() { + return new DispositionModifier(Prefix.FAILURE, "unsupported format"); + } + + public static DispositionModifier unsupportedMicAlgorithms() { + return new DispositionModifier(Prefix.FAILURE, "unsupported MIC-algorithms"); + } + + public static DispositionModifier failed(String description) { + return new DispositionModifier(Prefix.FAILURE, description); + } + + public static DispositionModifier error(String description) { + return new DispositionModifier(Prefix.ERROR, description); + } + + @Override + public String toString() { + return prefix + ": " + dispositionModifierExtension; + } + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/As2DispositionNotificationOptions.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/As2DispositionNotificationOptions.java new file mode 100644 index 0000000000000000000000000000000000000000..849eeab5407b726bba4beb1e0a7dde1c7c2e9a0a --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/As2DispositionNotificationOptions.java @@ -0,0 +1,222 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.model; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.as2.util.SMimeDigestMethod; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represents the AS2 Header Disposition-notifications-options + *

+ * The following input string should yield an As2DispositionNotificationOptions with two parameters: + *

+ * Disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature;
+ *  signed-receipt-micalg=required,sha1,md5
+ * 
+ *

+ * The two parameters are: + *

    + *
  1. signed-receipt-protocol
  2. + *
  3. signed-receipt-micalg
  4. + *
+ * + * @author steinar + * Date: 17.10.13 + * Time: 21:08 + */ +@Slf4j +public class As2DispositionNotificationOptions { + + private static final Pattern PATTERN = Pattern.compile( + "(signed-receipt-protocol|signed-receipt-micalg)\\s*=\\s*(required|optional)\\s*,\\s*([^;]*)"); + + private final List parameters; + + public static As2DispositionNotificationOptions getDefault(SMimeDigestMethod digestMethod) { + return valueOf("signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required," + + digestMethod.getIdentifier()); + } + + public static As2DispositionNotificationOptions valueOf(String s) { + if (s == null) { + throw new IllegalArgumentException("Can not parse empty disposition-notification-options."); + } + + List parameterList = new ArrayList<>(); + + log.debug("Inspecting " + s); + Matcher matcher = PATTERN.matcher(s); + while (matcher.find()) { + if (matcher.groupCount() != 3) { + throw new IllegalStateException("Internal error: Invalid group count in RegEx for parameter match in disposition-notification-options."); + } + String attributeName = matcher.group(1); + String importanceName = matcher.group(2); + String value = matcher.group(3); + + Attribute attribute = Attribute.fromString(attributeName); + Importance importance = Importance.valueOf(importanceName.trim().toUpperCase()); + + Parameter parameter = Parameter.of(attribute, importance, value); + parameterList.add(parameter); + } + + if (parameterList.isEmpty()) { + throw new IllegalArgumentException("Unable to create " + As2DispositionNotificationOptions.class.getSimpleName() + " from '" + s + "'"); + } + + return new As2DispositionNotificationOptions(parameterList); + } + + public As2DispositionNotificationOptions(List parameters) { + this.parameters = parameters; + } + + public List getParameters() { + return parameters; + } + + private Parameter getParameterFor(Attribute attribute) { + for (Parameter parameter : parameters) { + if (parameter.attribute == attribute) { + return parameter; + } + } + return null; + } + + /** + * From the official AS2 spec page 22 : + * The "signed-receipt-micalg" parameter is a list of MIC algorithms + * preferred by the requester for use in signing the returned receipt. + * The list of MIC algorithms SHOULD be honored by the recipient from left to right. + */ + public Parameter getSignedReceiptMicalg() { + return getParameterFor(Attribute.SIGNED_RECEIPT_MICALG); + } + + /** + * @return Use the preferred mic algorithm for signed receipt, for PEPPOL AS2 this should be "sha1" + */ + public String getPreferredSignedReceiptMicAlgorithmName() { + String preferredAlgorithm = "" + getSignedReceiptMicalg().getTextValue(); // text value could be "sha1, md5" + return preferredAlgorithm.split(",")[0].trim(); + } + + public Parameter getSignedReceiptProtocol() { + return getParameterFor(Attribute.SIGNED_RECEIPT_PROTOCOL); + } + + @Override + public String toString() { + return String.format("%s; %s", getSignedReceiptProtocol(), getSignedReceiptMicalg()); + } + + static class Parameter { + + Attribute attribute; + + Importance importance; + + String textValue; + + Attribute getAttribute() { + return attribute; + } + + Importance getImportance() { + return importance; + } + + String getTextValue() { + return textValue; + } + + public static Parameter of(Attribute attribute, Importance importance, String textValue) { + return new Parameter(attribute, importance, textValue); + } + + Parameter(Attribute attribute, Importance importance, String textValue) { + this.attribute = attribute; + this.importance = importance; + this.textValue = textValue; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("") + .append(attribute).append("=") + .append(importance) + .append(",").append(textValue); + + return sb.toString(); + } + } + + enum Attribute { + + SIGNED_RECEIPT_PROTOCOL("signed-receipt-protocol"), + SIGNED_RECEIPT_MICALG("signed-receipt-micalg"); + private final String text; + + Attribute(String text) { + this.text = text; + } + + /** + * This is needed as the textual representation of each enum value, contains dashes + */ + static Attribute fromString(String s) { + if (s == null) { + throw new IllegalArgumentException("String value required"); + } + for (Attribute attribute : values()) { + if (attribute.text.equalsIgnoreCase(s)) { + return attribute; + } + } + + throw new IllegalArgumentException(s + " not recognized as an attribute of As2DispositionNotificationOptions"); + } + + @Override + public String toString() { + return text; + } + } + + static enum Importance { + REQUIRED, OPTIONAL; + + + @Override + public String toString() { + return name().toLowerCase(); + } + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/Mic.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/Mic.java new file mode 100644 index 0000000000000000000000000000000000000000..f403fb884f5724c5b44afaf877c07027c279176a --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/model/Mic.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.model; + +import network.oxalis.as2.util.SMimeDigestMethod; +import network.oxalis.vefa.peppol.common.model.Digest; + +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Objects; + +/** + * Value object holding the Message Integrity Control (MIC) of an AS2 message. + * + * @author steinar + */ +public class Mic { + + private final String digestAsString; + + private final SMimeDigestMethod algorithm; + + public Mic(Digest digest) { + this(Base64.getEncoder().encodeToString(digest.getValue()), + SMimeDigestMethod.findByDigestMethod(digest.getMethod())); + } + + public Mic(String digestAsString, SMimeDigestMethod algorithm) { + this.digestAsString = digestAsString; + this.algorithm = algorithm; + } + + public static Mic valueOf(String receivedContentMic) throws NoSuchAlgorithmException { + String s[] = receivedContentMic.split(","); + if (s.length != 2) { + throw new IllegalArgumentException("Invalid mic: '" + receivedContentMic + "'. Required syntax: encoded-message-digest \",\" (sha1|md5)"); + } + return new Mic(s[0].trim(), SMimeDigestMethod.findByIdentifier(s[1].trim())); + } + + @Override + public String toString() { + return String.format("%s, %s", digestAsString, algorithm.getIdentifier()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Mic mic = (Mic) o; + return Objects.equals(digestAsString, mic.digestAsString) && + algorithm == mic.algorithm; + } + + @Override + public int hashCode() { + return Objects.hash(digestAsString, algorithm); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2MessageSender.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2MessageSender.java new file mode 100644 index 0000000000000000000000000000000000000000..56144f76177f562450194349e85e44458b6c0d68 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2MessageSender.java @@ -0,0 +1,358 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.outbound; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.name.Named; +import io.opentracing.Span; +import io.opentracing.Tracer; +import io.opentracing.contrib.apache.http.client.Constants; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.identifier.MessageIdGenerator; +import network.oxalis.api.lang.OxalisSecurityException; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lang.TimestampException; +import network.oxalis.api.model.Direction; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.api.timestamp.TimestampProvider; +import network.oxalis.as2.code.As2Header; +import network.oxalis.as2.code.MdnHeader; +import network.oxalis.as2.model.As2DispositionNotificationOptions; +import network.oxalis.as2.model.Mic; +import network.oxalis.as2.util.*; +import network.oxalis.as2.lang.OxalisAs2Exception; +import network.oxalis.commons.security.CertificateUtils; +import network.oxalis.commons.tracing.Traceable; +import network.oxalis.vefa.peppol.common.model.Digest; +import network.oxalis.vefa.peppol.security.lang.PeppolSecurityException; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.HttpHostConnectException; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.util.EntityUtils; + +import javax.mail.MessagingException; +import javax.mail.internet.InternetHeaders; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.net.ssl.SSLHandshakeException; +import java.io.IOException; +import java.io.InputStream; +import java.net.SocketTimeoutException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Not thread safe implementation of sender, which sends messages using the AS2 protocol. + * Stores the outbound MIC for verification against the mic received from the MDN later. + * + * @author steinar + * @author thore + * @author erlend + */ +@Slf4j +class As2MessageSender extends Traceable { + + /** + * Provider of HTTP clients. + */ + private final Provider httpClientProvider; + + private final SMimeMessageFactory sMimeMessageFactory; + + /** + * Timestamp provider used to create timestamp "t3" (time of reception of transport specific receipt, MDN). + */ + private final TimestampProvider timestampProvider; + + private final String notificationAddress; + + private final MessageIdGenerator messageIdGenerator; + + /** + * Identifier from sender's certificate used during transmission in "AS2-From" header. + */ + private final String fromIdentifier; + + private TransmissionRequest transmissionRequest; + + private TransmissionIdentifier transmissionIdentifier; + + private Span root; + + private Digest outboundMic; + + /** + * Constructor expecting resources needed to perform transmission using AS2. All task required to be done once for + * all requests using this instance is done here. + * + * @param httpClientProvider Provider of HTTP clients. + * @param certificate Certificate of sender. + * @param sMimeMessageFactory Factory prepared to create S/MIME messages using our private key. + * @param timestampProvider Provider used to fetch timestamps. + * @param tracer Tracing tool. + */ + @Inject + public As2MessageSender(Provider httpClientProvider, X509Certificate certificate, + SMimeMessageFactory sMimeMessageFactory, TimestampProvider timestampProvider, + @Named("as2-notification") String notificationAddress, MessageIdGenerator messageIdGenerator, + Tracer tracer) { + super(tracer); + this.httpClientProvider = httpClientProvider; + this.sMimeMessageFactory = sMimeMessageFactory; + this.timestampProvider = timestampProvider; + this.notificationAddress = notificationAddress; + this.messageIdGenerator = messageIdGenerator; + + // Establishes our AS2 System Identifier based upon the contents of the CN= field of the certificate + this.fromIdentifier = CertificateUtils.extractCommonName(certificate); + } + + public TransmissionResponse send(TransmissionRequest transmissionRequest, Span root) + throws OxalisTransmissionException { + this.transmissionRequest = transmissionRequest; + + this.root = tracer.buildSpan("Send AS2 message").asChildOf(root).start(); + try { + return sendHttpRequest(prepareHttpRequest()); + } catch (OxalisTransmissionException e) { + this.root.setTag("exception", e.getMessage()); + throw e; + } finally { + root.finish(); + } + } + + @SuppressWarnings("unchecked") + protected HttpPost prepareHttpRequest() throws OxalisTransmissionException { + Span span = tracer.buildSpan("request").asChildOf(root).start(); + try { + // Create the body part of the MIME message containing our content to be transmitted. + MimeBodyPart mimeBodyPart = MimeMessageHelper + .createMimeBodyPart(transmissionRequest.getPayload(), "application/xml"); + + // Digest method to use. + SMimeDigestMethod digestMethod = SMimeDigestMethod.findByTransportProfile( + transmissionRequest.getEndpoint().getTransportProfile()); + + outboundMic = MimeMessageHelper.calculateMic(mimeBodyPart, digestMethod); + span.setTag("mic", outboundMic.toString()); + span.setTag("endpoint url", transmissionRequest.getEndpoint().getAddress().toString()); + + // Create Message-Id + String messageId = messageIdGenerator.generate(transmissionRequest); + + if (!MessageIdUtil.verify(messageId)) + throw new OxalisTransmissionException("Invalid Message-ID '" + messageId + "' generated."); + + span.setTag("message-id", messageId); + transmissionIdentifier = TransmissionIdentifier.fromHeader(messageId); + + // Create a complete S/MIME message using the body part containing our content as the + // signed part of the S/MIME message. + MimeMessage signedMimeMessage = sMimeMessageFactory + .createSignedMimeMessage(mimeBodyPart, digestMethod); + // .createSignedMimeMessageNew(mimeBodyPart, outboundMic, digestMethod); + + //try (OutputStream outputStream = Files.newOutputStream(Paths.get(UUID.randomUUID().toString()))) { + // signedMimeMessage.writeTo(outputStream); + //} + + // Get all headers in S/MIME message. + Map headers = ((List) Collections.list(signedMimeMessage.getAllHeaders())).stream() + .collect(Collectors.toMap(javax.mail.Header::getName, h -> h.getValue().replace("\r\n\t", ""))); + + // Clear headers in MIME content + for (String name : headers.keySet()) + signedMimeMessage.removeHeader(name); + + // Initiate POST request + HttpPost httpPost = new HttpPost(transmissionRequest.getEndpoint().getAddress()); + + // Inserts the S/MIME message to be posted. + HttpEntity httpEntity = new ByteArrayEntity(ByteStreams.toByteArray(signedMimeMessage.getInputStream())); + httpPost.setEntity(httpEntity); + + // Set all headers. + httpPost.addHeader(As2Header.MESSAGE_ID, messageId); + httpPost.addHeader(As2Header.MIME_VERSION, headers.get(As2Header.MIME_VERSION)); + httpPost.addHeader(As2Header.CONTENT_TYPE, headers.get(As2Header.CONTENT_TYPE)); + httpPost.addHeader(As2Header.AS2_FROM, fromIdentifier); + httpPost.setHeader(As2Header.AS2_TO, CertificateUtils.extractCommonName( + transmissionRequest.getEndpoint().getCertificate())); + httpPost.addHeader(As2Header.DISPOSITION_NOTIFICATION_TO, notificationAddress); + httpPost.addHeader(As2Header.DISPOSITION_NOTIFICATION_OPTIONS, + As2DispositionNotificationOptions.getDefault(digestMethod).toString()); + httpPost.addHeader(As2Header.AS2_VERSION, As2Header.VERSION); + httpPost.addHeader(As2Header.SUBJECT, "AS2 message from Oxalis"); + httpPost.addHeader(As2Header.DATE, As2DateUtil.RFC822.format(new Date())); + + return httpPost; + } catch (MessagingException | IOException e) { + throw new OxalisTransmissionException("Unexpected error during preparation of AS2 message.", e); + } finally { + span.finish(); + } + } + + protected TransmissionResponse sendHttpRequest(HttpPost httpPost) throws OxalisTransmissionException { + Span span = tracer.buildSpan("execute").asChildOf(root).start(); + try (CloseableHttpClient httpClient = httpClientProvider.get()) { + BasicHttpContext basicHttpContext = new BasicHttpContext(); + basicHttpContext.setAttribute(Constants.PARENT_CONTEXT, span.context()); + + CloseableHttpResponse response = httpClient.execute(httpPost, basicHttpContext); + + span.finish(); + + return handleResponse(response); + } catch (SocketTimeoutException e) { + span.setTag("exception", String.valueOf(e.getMessage())); + throw new OxalisTransmissionException("Receiving server has not sent anything back within SOCKET_TIMEOUT", transmissionRequest.getEndpoint().getAddress(), e); + } catch (HttpHostConnectException e) { + span.setTag("exception", e.getMessage()); + throw new OxalisTransmissionException("Receiving server does not seem to be running.", + transmissionRequest.getEndpoint().getAddress(), e); + } catch (SSLHandshakeException e) { + span.setTag("exception", e.getMessage()); + throw new OxalisTransmissionException("Possible invalid SSL Certificate at the other end.", + transmissionRequest.getEndpoint().getAddress(), e); + } catch (IOException e) { + span.setTag("exception", String.valueOf(e.getMessage())); + throw new OxalisTransmissionException(transmissionRequest.getEndpoint().getAddress(), e); + } finally { + span.finish(); + } + } + + protected TransmissionResponse handleResponse(CloseableHttpResponse closeableHttpResponse) + throws OxalisTransmissionException { + Span span = tracer.buildSpan("response").asChildOf(root).start(); + try (CloseableHttpResponse response = closeableHttpResponse) { + span.setTag("code", String.valueOf(response.getStatusLine().getStatusCode())); + + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + log.error("AS2 HTTP POST expected HTTP OK, but got : {} from {}", + response.getStatusLine().getStatusCode(), transmissionRequest.getEndpoint().getAddress()); + + // Throws exception + handleFailedRequest(response); + } + + // handle normal HTTP OK response + log.debug("AS2 transmission to {} returned HTTP OK, verify MDN response", + transmissionRequest.getEndpoint().getAddress()); + + // Verify existence of Content-Type + if (!response.containsHeader("Content-Type")) + throw new OxalisTransmissionException("No Content-Type header in response, probably a server error."); + + // Read MIME message + MimeMessage mimeMessage = MimeMessageHelper.parse( + response.getEntity().getContent(), + Stream.of(response.getAllHeaders()).map(Header::toString) + ); + + SignedMessage message; + + try { + message = SignedMessage.load(mimeMessage); + message.validate(transmissionRequest.getEndpoint().getCertificate()); + } catch (OxalisAs2Exception e) { + throw new OxalisTransmissionException("Unable to parse received MDN.", e); + } catch (OxalisSecurityException | PeppolSecurityException e) { + throw new OxalisTransmissionException( + "Unable to verify content of MDN using certificate provided by SMP.", e); + } + + // Timestamp of reception of MDN + Timestamp t3 = timestampProvider.generate(message.getSignature(), Direction.OUT); + + // Verifies the actual MDN + MdnMimeMessageInspector mdnMimeMessageInspector = new MdnMimeMessageInspector(mimeMessage); + String msg = mdnMimeMessageInspector.getPlainTextPartAsText(); + + if (!mdnMimeMessageInspector.isOkOrWarning(new Mic(outboundMic))) { + log.error("AS2 transmission failed with some error message '{}'.", msg); + throw new OxalisTransmissionException(String.format("AS2 transmission failed : %s", msg)); + } + + // Read structured content + MimeBodyPart mimeBodyPart = (MimeBodyPart) mdnMimeMessageInspector.getMessageDispositionNotificationPart(); + InternetHeaders internetHeaders = new InternetHeaders((InputStream) mimeBodyPart.getContent()); + + // Fetch timestamp if set + Date date = t3.getDate(); + if (internetHeaders.getHeader(MdnHeader.DATE) != null) + date = As2DateUtil.RFC822.parse(internetHeaders.getHeader(MdnHeader.DATE)[0]); + + // Return TransmissionResponse + return new As2TransmissionResponse(transmissionIdentifier, transmissionRequest, + outboundMic, MimeMessageHelper.toBytes(mimeMessage), t3, date); + } catch (TimestampException | IOException e) { + throw new OxalisTransmissionException(e.getMessage(), e); + } catch (NoSuchAlgorithmException | MessagingException e) { + throw new OxalisTransmissionException(String.format("Unable to parseOld received MDN: %s", e.getMessage()), e); + } finally { + span.finish(); + } + } + + protected void handleFailedRequest(HttpResponse response) throws OxalisTransmissionException { + HttpEntity entity = response.getEntity(); // Any results? + try { + if (entity == null) { + // No content returned + throw new OxalisTransmissionException( + String.format("Request failed with rc=%s, no content returned in HTTP response", + response.getStatusLine().getStatusCode())); + } else { + String contents = EntityUtils.toString(entity); + throw new OxalisTransmissionException( + String.format("Request failed with rc=%s, contents received (%s characters): %s", + response.getStatusLine().getStatusCode(), contents.trim().length(), contents)); + } + } catch (IOException e) { + throw new OxalisTransmissionException( + String.format("Request failed with rc=%s, ERROR while retrieving the contents of the response: %s", + response.getStatusLine().getStatusCode(), e.getMessage()), e); + } + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2MessageSenderFacade.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2MessageSenderFacade.java new file mode 100644 index 0000000000000000000000000000000000000000..32b84d8eb2f401c3b349327ff126892b9437839c --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2MessageSenderFacade.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.outbound; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import io.opentracing.Span; +import io.opentracing.Tracer; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.outbound.MessageSender; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.commons.tracing.Traceable; + +class As2MessageSenderFacade extends Traceable implements MessageSender { + + private Provider messageSenderProvider; + + @Inject + public As2MessageSenderFacade(Tracer tracer, Provider messageSenderProvider) { + super(tracer); + this.messageSenderProvider = messageSenderProvider; + } + + @Override + public TransmissionResponse send(TransmissionRequest transmissionRequest) throws OxalisTransmissionException { + Span span = tracer.buildSpan(getClass().getSimpleName()).start(); + try { + return send(transmissionRequest, span); + } finally { + span.finish(); + } + } + + @Override + public TransmissionResponse send(TransmissionRequest transmissionRequest, Span root) + throws OxalisTransmissionException { + return messageSenderProvider.get().send(transmissionRequest, root); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2OutboundModule.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2OutboundModule.java new file mode 100644 index 0000000000000000000000000000000000000000..0a076e4a9a6f76e1211a09a84721a9bee4186887 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2OutboundModule.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.outbound; + +import com.google.inject.Key; +import com.google.inject.name.Names; +import network.oxalis.api.outbound.MessageSender; +import network.oxalis.commons.guice.OxalisModule; + +/** + * Guice module providing AS2 implementation for outbound. + * + * @author erlend + * @since 4.0.0 + */ +public class As2OutboundModule extends OxalisModule { + + @Override + protected void configure() { + bind(Key.get(MessageSender.class, Names.named("oxalis-as2"))) + .to(As2MessageSenderFacade.class); + + bind(As2MessageSender.class); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2TransmissionResponse.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2TransmissionResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..a23b0546515393f3c90afe8cc401813975d15051 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/outbound/As2TransmissionResponse.java @@ -0,0 +1,127 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.outbound; + +import network.oxalis.api.tag.Tag; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.vefa.peppol.common.model.*; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * Implementation of {@link TransmissionResponse} for use in AS2. + * + * @author steinar + * @author thore + * @author erlend + */ +class As2TransmissionResponse implements TransmissionResponse, Serializable { + + private static final long serialVersionUID = 4288900204693153668L; + + private final Tag tag; + + private final Header header; + + private final Endpoint endpoint; + + private final TransmissionIdentifier transmissionIdentifier; + + private final Digest digest; + + private final Receipt receipt; + + private final List receipts; + + private final Date timestamp; + + public As2TransmissionResponse(TransmissionIdentifier transmissionIdentifier, + TransmissionRequest transmissionRequest, Digest digest, + byte[] nativeEvidenceBytes, Timestamp timestamp, Date date) { + this.tag = transmissionRequest.getTag(); + this.header = transmissionRequest.getHeader(); + this.endpoint = transmissionRequest.getEndpoint(); + this.transmissionIdentifier = transmissionIdentifier; + this.digest = digest; + this.receipt = Receipt.of("message/disposition-notification", nativeEvidenceBytes); + this.timestamp = date; + + List receipts = new ArrayList<>(); + receipts.add(receipt); + if (timestamp.getReceipt().isPresent()) + receipts.add(timestamp.getReceipt().get()); + this.receipts = Collections.unmodifiableList(receipts); + } + + @Override + public Tag getTag() { + return tag; + } + + @Override + public Header getHeader() { + return header; + } + + @Override + public TransmissionIdentifier getTransmissionIdentifier() { + return transmissionIdentifier; + } + + @Override + public List getReceipts() { + return receipts; + } + + @Override + public Endpoint getEndpoint() { + return endpoint; + } + + @Override + public Receipt primaryReceipt() { + return receipt; + } + + @Override + public Digest getDigest() { + return digest; + } + + @Override + public TransportProtocol getTransportProtocol() { + return TransportProtocol.AS2; + } + + @Override + public Date getTimestamp() { + return timestamp; + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/As2DateUtil.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/As2DateUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..0984b00479533553b9e83ec2fafcfbebfffb5eaa --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/As2DateUtil.java @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * Ensures that all date time objects are parsed and formatted according to the specifications in RFC4130. + *

+ * RFC-4130 references RFC-2045, which references RFC-1123, which references good old RFC-822. + *

+ * date-time   =  [ day "," ] date time        ; dd mm yy
+ * ;  hh:mm:ss zzz
+ *
+ * day         =  "Mon"  / "Tue" /  "Wed"  / "Thu"
+ * /  "Fri"  / "Sat" /  "Sun"
+ *
+ * date        =  1*2DIGIT month 4DIGIT           ; day month year(4 digits)
+ * ;  e.g. 20 Jun 82
+ *
+ * month       =  "Jan"  /  "Feb" /  "Mar"  /  "Apr"
+ * /  "May"  /  "Jun" /  "Jul"  /  "Aug"
+ * /  "Sep"  /  "Oct" /  "Nov"  /  "Dec"
+ *
+ * time        =  hour zone                       ; ANSI and Military
+ *
+ * hour        =  2DIGIT ":" 2DIGIT [":" 2DIGIT]
+ * ; 00:00:00 - 23:59:59
+ *
+ * zone        =  "UT"  / "GMT"                   ; Universal Time
+ * ; North American : UT
+ * /  "EST" / "EDT"                    ;  Eastern:  - 5/ - 4
+ * /  "CST" / "CDT"                    ;  Central:  - 6/ - 5
+ * /  "MST" / "MDT"                    ;  Mountain: - 7/ - 6
+ * /  "PST" / "PDT"                    ;  Pacific:  - 8/ - 7
+ * /  1ALPHA                           ; Military: Z = UT;
+ * ;  A:-1; (J not used)
+ * ;  M:-12; N:+1; Y:+12
+ * / ( ("+" / "-") 4DIGIT )            ; Local differential
+ * ;  hours+min. (HHMM)
+ * 
+ * + * @author steinar + * @author erlend + * @see "RFC-4130" + * @see "RFC-2045" + * @see "RFC-1123" + * @see "RFC-822" + */ +public enum As2DateUtil { + + RFC822("EEE, dd MMM yyyy HH:mm:ss Z"), + ISO8601("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + private String format; + + As2DateUtil(String format) { + this.format = format; + } + + public Date parse(String s) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.ENGLISH); + + try { + return simpleDateFormat.parse(s); + } catch (ParseException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public String format(Date d) { + return new SimpleDateFormat(format, Locale.ENGLISH).format(d); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/HeaderUtil.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/HeaderUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..28dcad5f8943b5820c227b33d69f4fd5013608a5 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/HeaderUtil.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import javax.mail.internet.InternetHeaders; + +/** + * @author steinar + * Date: 18.11.13 + * Time: 15:56 + */ +public class HeaderUtil { + + public static String getFirstValue(InternetHeaders internetHeaders, String httpHeaderName) { + String[] value = internetHeaders.getHeader(httpHeaderName); + if (value == null) { + return null; + } else + return value[0]; //To change body of created methods use File | Settings | File Templates. + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MdnBuilder.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MdnBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..f596b2189e86249b4d65f6157cfe77434a6e761c --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MdnBuilder.java @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import com.sun.mail.util.LineOutputStream; +import network.oxalis.as2.code.As2Header; +import network.oxalis.as2.code.Disposition; +import network.oxalis.as2.code.MdnHeader; +import network.oxalis.commons.util.OxalisVersion; + +import javax.mail.MessagingException; +import javax.mail.internet.InternetHeaders; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Base64; +import java.util.Collections; +import java.util.Date; +import java.util.Enumeration; + +public class MdnBuilder { + + private static final String ISSUER = String.format("Oxalis %s", OxalisVersion.getVersion()); + + private InternetHeaders headers = new InternetHeaders(); + + private ByteArrayOutputStream textOutputStream = new ByteArrayOutputStream(); + + private LineOutputStream textLineOutputStream = new LineOutputStream(textOutputStream); + + public static MdnBuilder newInstance(MimeMessage mimeMessage) throws MessagingException, IOException { + MdnBuilder mdnBuilder = new MdnBuilder(); + mdnBuilder.addHeader(MdnHeader.REPORTING_UA, ISSUER); + + String recipient = String.format("rfc822; %s", mimeMessage.getHeader(As2Header.AS2_TO)[0]); + mdnBuilder.addHeader(MdnHeader.ORIGINAL_RECIPIENT, recipient); + mdnBuilder.addHeader(MdnHeader.FINAL_RECIPIENT, recipient); + + mdnBuilder.textLineOutputStream.writeln("= Received headers"); + mdnBuilder.textLineOutputStream.writeln(); + for (String header : Collections.list((Enumeration) mimeMessage.getAllHeaderLines())) + mdnBuilder.textLineOutputStream.writeln(header); + mdnBuilder.textLineOutputStream.writeln(); + + return mdnBuilder; + } + + private MdnBuilder() { + // No action. + } + + public void addText(String title, String text) throws IOException { + textLineOutputStream.writeln(String.format("= %s", title)); + textLineOutputStream.writeln(); + textLineOutputStream.writeln(String.valueOf(text)); + textLineOutputStream.writeln(); + } + + public void addHeader(String name, String value) { + headers.addHeader(name, value); + } + + public void addHeader(String name, Date value) { + headers.addHeader(name, As2DateUtil.RFC822.format(value)); + } + + public void addHeader(String name, byte[] value) { + headers.addHeader(name, Base64.getEncoder().encodeToString(value)); + } + + public void addHeader(String name, Object value) { + headers.addHeader(name, value.toString()); + } + + public void addHeader(String name, Disposition disposition) { + headers.addHeader(name, disposition.toString()); + } + + public MimeBodyPart build() throws MessagingException, IOException { + // Initiate multipart + MimeMultipart mimeMultipart = new MimeMultipart(); + mimeMultipart.setSubType("report; Report-Type=disposition-notification"); + + // Insert text part + MimeBodyPart textPart = new MimeBodyPart(); + textLineOutputStream.close(); + textPart.setContent(textOutputStream.toString("UTF-8"), "text/plain"); + // textPart.setHeader("Content-Type", "text/plain"); + mimeMultipart.addBodyPart(textPart); + + // Extract headers + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + LineOutputStream lineOutputStream = new LineOutputStream(outputStream); + for (String header : Collections.list((Enumeration) headers.getAllHeaderLines())) + lineOutputStream.writeln(header); + lineOutputStream.close(); + + // Insert header part + MimeBodyPart headerPart = new MimeBodyPart(); + headerPart.setContent(outputStream.toString(), "message/disposition-notification"); + mimeMultipart.addBodyPart(headerPart); + + MimeBodyPart mimeBodyPart = new MimeBodyPart(); + mimeBodyPart.setContent(mimeMultipart, mimeMultipart.getContentType()); + return mimeBodyPart; + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MdnMimeMessageInspector.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MdnMimeMessageInspector.java new file mode 100644 index 0000000000000000000000000000000000000000..622f07f247eef0bcd030e452d1cf913f713db7c8 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MdnMimeMessageInspector.java @@ -0,0 +1,300 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.as2.model.As2Disposition; +import network.oxalis.as2.model.Mic; +import org.apache.commons.codec.binary.Base64InputStream; + +import javax.mail.BodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.NoSuchAlgorithmException; +import java.util.Locale; +import java.util.Map; +import java.util.TreeMap; + +/** + * Inspects the various properties and parts of an MDN wrapped in a S/MIME message. + *

+ * This class is typically used by the sender of the business message, which will receive + * an MDN from the receiving party. + *

+ * Part 0 : multipart/report; report-type=disposition-notification; + * 0 : Sub part 0 : text/plain + * 0 : Sub part 1 : message/disposition-notification + * 0 : Sub part x : will not be used by Oxalis + * Part 1 : application/pkcs7-signature; name=smime.p7s; smime-type=signed-data + * + * @author steinar + * @author thore + * + * @author aaron-kumar + * @since 5.0.0 + * + */ +@Slf4j +public class MdnMimeMessageInspector { + + private final MimeMessage mdnMimeMessage; + + public MdnMimeMessageInspector(MimeMessage mdnMimeMessage) { + this.mdnMimeMessage = mdnMimeMessage; + } + + public MimeMultipart getSignedMultiPart() { + try { + return (MimeMultipart) mdnMimeMessage.getContent(); + } catch (Exception e) { + throw new IllegalStateException( + "Unable to access the contents of the MDN S/MIME message: " + e.getMessage(), e); + } + } + + /** + * The multipart/report should contain both a text/plain part with textual information and + * a message/disposition-notification part that should be examined for error/failure/warning. + */ + public MimeMultipart getMultipartReport() { + try { + BodyPart bodyPart = getSignedMultiPart().getBodyPart(0); + MimeMultipart multipartReport = new MimeMultipart (bodyPart.getDataHandler().getDataSource()); + if (!containsIgnoreCase(multipartReport.getContentType(), "multipart/report")) { + throw new IllegalStateException( + "The first body part of the first part of the signed message is not a multipart/report"); + } + return multipartReport; + } catch (Exception e) { + throw new IllegalStateException("Unable to retrieve the multipart/report : " + e.getMessage(), e); + } + } + + /** + * We assume that the first text/plain part is the one containing any textual information. + */ + public BodyPart getPlainTextBodyPart() { + return getPartFromMultipartReport("text/plain"); + } + + /** + * We search for the first message/disposition-notification part. + * If we don't find one of that type we assume that part 2 is the right one. + */ + public BodyPart getMessageDispositionNotificationPart() { + BodyPart bp = getPartFromMultipartReport("message/disposition-notification"); + if (bp == null) bp = getBodyPartAt(1); // the second part should be machine readable + return bp; + } + + /** + * Return the fist part which have the given contentType + * + * @param contentType the mime type to look for + */ + private BodyPart getPartFromMultipartReport(String contentType) { + try { + MimeMultipart multipartReport = getMultipartReport(); + for (int t = 0; t < multipartReport.getCount(); t++) { + BodyPart bp = multipartReport.getBodyPart(t); + if (containsIgnoreCase(bp.getContentType(), contentType)) + return bp; + } + } catch (Exception e) { + log.error("Failed to locate part of multipart/report of type '{}'.", contentType, e); + } + return null; + } + + /** + * Get a specific part of the multipart/report + * + * @param position starts at 0 for the first, 1 for the second, etc + */ + private BodyPart getBodyPartAt(int position) { + try { + return getMultipartReport().getBodyPart(position); + } catch (Exception e) { + throw new IllegalStateException( + "Unable to retrieve the body part at position " + position + " : " + e.getMessage(), e); + } + } + + public String getPlainTextPartAsText() { + try { + return getPlainTextBodyPart().getContent().toString(); + } catch (Exception e) { + throw new IllegalStateException("Unable to retrieve the plain text from the MDN: " + e.getMessage(), e); + } + } + + public Map getMdnFields() { + Map ret = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + try { + + BodyPart bp = getMessageDispositionNotificationPart(); + boolean contentIsBase64Encoded = false; + + // + // look for base64 transfer encoded MDN's (when Content-Transfer-Encoding is present) + // + // Content-Type: message/disposition-notification + // Content-Transfer-Encoding: base64 + // + // "Content-Transfer-Encoding not used in HTTP transport Because HTTP, unlike SMTP, + // does not have an early history involving 7-bit restriction. + // There is no need to use the Content Transfer Encodings of MIME." + // + String[] contentTransferEncodings = bp.getHeader("Content-Transfer-Encoding"); + if (contentTransferEncodings != null && contentTransferEncodings.length > 0) { + if (contentTransferEncodings.length > 1) + log.warn("MDN has multiple Content-Transfer-Encoding, we only try the first one"); + String encoding = contentTransferEncodings[0]; + if (encoding == null) encoding = ""; + encoding = encoding.trim(); + log.debug("MDN specifies Content-Transfer-Encoding : '" + encoding + "'"); + if ("base64".equalsIgnoreCase(encoding)) { + contentIsBase64Encoded = true; + } + } + + Object content = bp.getContent(); + if (content instanceof InputStream) { + InputStream contentInputStream = (InputStream) content; + + if (contentIsBase64Encoded) { + log.debug("MDN seems to be base64 encoded, wrapping content stream in Base64 decoding stream"); + contentInputStream = new Base64InputStream(contentInputStream); // wrap in base64 decoding stream + } + + BufferedReader r = new BufferedReader(new InputStreamReader(contentInputStream)); + while (r.ready()) { + String line = r.readLine(); + int firstColon = line.indexOf(":"); // "Disposition: ......" + if (firstColon > 0) { + String key = line.substring(0, firstColon).trim(); // up to : + String value = line.substring(firstColon + 1).trim(); // skip : + ret.put(key, value); + } + } + } else { + throw new Exception("Unsupported MDN content, expected InputStream found @ " + content.toString()); + } + + + } catch (Exception e) { + throw new IllegalStateException("Unable to retrieve the values from the MDN : " + e.getMessage(), e); + } + return ret; + } + + /** + * Decode MDN and make sure the message was processed (allow for warnings) + * + * @param outboundMic the outbound mic to verify against + */ + public boolean isOkOrWarning(Mic outboundMic) throws NoSuchAlgorithmException { + + Map mdnFields = getMdnFields(); + + /* + --------_=_NextPart_001_B096DD27.9007A6CE + Content-Type: message/disposition-notification + + Reporting-UA: AS2 eefacta Server (unimaze.com) + Original-Recipient: rfc822; SMP_2000000005 + Final-Recipient: rfc822; SMP_2000000005 + Original-Message-ID: a60d9982-680c-4f01-9ab4-9b5d5fb05f37 + Received-Content-MIC: ZMY/AoJb2JQS557MOATtc0EZdZQ=, sha1 + Disposition: automatic-action/MDN-sent-automatically; processed + + + --------_=_NextPart_001_B096DD27.9007A6CE-- + */ + + // make sure we have a valid disposition + String disposition = mdnFields.get("Disposition"); + if (disposition == null) { + log.error("Unable to retreieve 'Disposition' from MDN"); + return false; + } + + log.debug("Decoding received disposition ({})", disposition); + As2Disposition as2dis = As2Disposition.valueOf(disposition); + + // make sure we are in processed state + if (!As2Disposition.DispositionType.PROCESSED.equals(as2dis.getDispositionType())) { + // Disposition: automatic-action/MDN-sent-automatically; failed/failure: sender-equals-receiver + log.error("Failed or unknown state: {}", disposition); + return false; + } + + // check if the returned MIC matches our outgoing MIC (sha1 of payload), warn about mic mismatch + String receivedMic = mdnFields.get("Received-Content-MIC"); + if (receivedMic == null) { + log.error("MIC error, no Received-Content-MIC returned in MDN"); + return false; + } + if (!outboundMic.equals(Mic.valueOf(receivedMic))) { + log.warn("MIC mismatch, received MIC was '{}' while sent MIC was '{}'.", + receivedMic, outboundMic.toString()); + return false; + } + + // return when "clean processing state" : Disposition: automatic-action/MDN-sent-automatically; processed + As2Disposition.DispositionModifier modifier = as2dis.getDispositionModifier(); + if (modifier == null) return true; + + // allow partial success (warning) + if (As2Disposition.DispositionModifier.Prefix.WARNING.equals(modifier.getPrefix())) { + // Disposition: automatic-action/MDN-sent-automatically; processed/warning: duplicate-document + log.warn("Returns with warning: {}", disposition); + return true; + } + + // Disposition: automatic-action/MDN-sent-automatically; processed/error: insufficient-message-security + log.warn("MDN failed with disposition raw: {}", disposition); + log.warn("MDN failed with as2 disposition: {}", as2dis.toString()); + + return false; + } + + /** + * Returns true if and only if the first param string contains the specified + * string of second parameter ignoring case. + * + * @param containerString the sequence to search for + * @param s the sequence to search for + * @return true if this string contains {@code s}, false otherwise + */ + private static boolean containsIgnoreCase(String containerString, String s) { + if (containerString == null || s == null) { + return false; + } + return containerString.toLowerCase(Locale.ROOT).contains(s.toLowerCase(Locale.ROOT)); + } + +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MessageIdUtil.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MessageIdUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..ec378d941c8951cf6d24a7054fa1c6580e36aac8 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MessageIdUtil.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import java.util.regex.Pattern; + +/** + * @author erlend + */ +public class MessageIdUtil { + + private static final String ATEXT = "[A-Za-z0-9!#\\$%&'\\*\\+\\-/=\\?\\^_`\\{}\\|~]+"; + + private static final Pattern PATTERN = + Pattern.compile("^<" + ATEXT + "(\\." + ATEXT + ")*@" + ATEXT + "(\\." + ATEXT + ")*>$"); + + public static boolean verify(String identifier) { + return PATTERN.matcher(identifier).matches(); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MimeMessageHelper.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MimeMessageHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..a2c7c76715d37c3fe67aee3ef678a16a8896e11f --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/MimeMessageHelper.java @@ -0,0 +1,153 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import com.google.common.io.ByteStreams; +import network.oxalis.commons.bouncycastle.BCHelper; +import network.oxalis.vefa.peppol.common.model.Digest; + +import javax.activation.DataHandler; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.internet.InternetHeaders; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.util.ByteArrayDataSource; +import java.io.*; +import java.security.DigestOutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Collections; +import java.util.Enumeration; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Collection of useful methods for manipulating MIME messages. + * + * @author Steinar Overbeck Cook + * @author Thore Johnsen + * @author Arun Kumar + */ +public class MimeMessageHelper { + + private static final Session SESSION = Session.getDefaultInstance(System.getProperties(), null); + + /** + * Creates a MIME message from the supplied stream, which must contain headers, + * especially the header "Content-Type:" + */ + public static MimeMessage parse(InputStream inputStream) throws MessagingException { + return new MimeMessage(SESSION, inputStream); + } + + /** + * Creates a MIME message from the supplied InputStream, using values from the HTTP headers to + * do a successful MIME decoding. + */ + public static MimeMessage parse(InputStream inputStream, InternetHeaders headers) + throws MessagingException { + + return parse(inputStream, + Collections.list((Enumeration) headers.getAllHeaderLines()) + .stream() + .map(String.class::cast)); + } + + /** + * Parses a complete MIME message with provided headers. + * + * @param inputStream Content part of MIME message. + * @param headers Headers provided as a stream of Strings. + * @return Parsed MIME message. + * @throws MessagingException Thrown when content is successfully parsed. + * @since 4.0.2 + */ + public static MimeMessage parse(InputStream inputStream, Stream headers) + throws MessagingException { + + // Read headers to a string + String headerString = headers.collect(Collectors.joining("\r\n")) + "\r\n\r\n"; + + // Parse content + return parse(new SequenceInputStream( + new ByteArrayInputStream(headerString.getBytes()), + inputStream + )); + } + + public static MimeBodyPart createMimeBodyPart(InputStream inputStream, String mimeType) { + MimeBodyPart mimeBodyPart = new MimeBodyPart(); + ByteArrayDataSource byteArrayDataSource; + + try { + byteArrayDataSource = new ByteArrayDataSource(inputStream, mimeType); + } catch (IOException e) { + throw new IllegalStateException("Unable to create ByteArrayDataSource from inputStream." + e.getMessage(), e); + } + + try { + DataHandler dh = new DataHandler(byteArrayDataSource); + mimeBodyPart.setDataHandler(dh); + } catch (MessagingException e) { + throw new IllegalStateException("Unable to set data handler on mime body part." + e.getMessage(), e); + } + + try { + mimeBodyPart.setHeader("Content-Type", mimeType); + mimeBodyPart.setHeader("Content-Transfer-Encoding", "binary"); // No content-transfer-encoding needed for http + } catch (MessagingException e) { + throw new IllegalStateException("Unable to set headers." + e.getMessage(), e); + } + + return mimeBodyPart; + } + + /** + * Calculates sha1 mic based on the MIME body part. + */ + public static Digest calculateMic(MimeBodyPart bodyPart, SMimeDigestMethod digestMethod) { + try { + MessageDigest md = BCHelper.getMessageDigest(digestMethod.getIdentifier()); + bodyPart.writeTo(new DigestOutputStream(ByteStreams.nullOutputStream(), md)); + return Digest.of(digestMethod.getDigestMethod(), md.digest()); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(digestMethod.getIdentifier() + " not found", e); + } catch (IOException e) { + throw new IllegalStateException("Unable to read data from digest input. " + e.getMessage(), e); + } catch (MessagingException e) { + throw new IllegalStateException("Unable to handle mime body part. " + e.getMessage(), e); + } + } + + public static byte[] toBytes(MimeMessage mimeMessage) { + ByteArrayOutputStream evidenceBytes = new ByteArrayOutputStream(); + try { + mimeMessage.writeTo(evidenceBytes); + } catch (IOException | MessagingException e) { + throw new IllegalStateException("Unable to convert MDN mime message into bytes()", e); + } + + return evidenceBytes.toByteArray(); + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeBC.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeBC.java new file mode 100644 index 0000000000000000000000000000000000000000..7c4b8004aa3008880744b936d9b9bc571a18d421 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeBC.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import network.oxalis.api.lang.OxalisSecurityException; +import network.oxalis.commons.bouncycastle.BCHelper; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.DERUTCTime; +import org.bouncycastle.asn1.cms.Attribute; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.CMSAttributes; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaCertStore; +import org.bouncycastle.cms.*; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; + +import java.io.IOException; +import java.security.PrivateKey; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Date; + +public class SMimeBC { + + static { + BCHelper.registerProvider(); + } + + public static byte[] createSignature(byte[] digest, SMimeDigestMethod digestMethod, PrivateKey privateKey, + X509Certificate certificate) throws OxalisSecurityException { + try { + ASN1EncodableVector signedAttributes = new ASN1EncodableVector(); + signedAttributes.add(new Attribute(CMSAttributes.contentType, new DERSet(digestMethod.getOid()))); + signedAttributes.add(new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digest)))); + signedAttributes.add(new Attribute(CMSAttributes.signingTime, new DERSet(new DERUTCTime(new Date())))); + + AttributeTable signedAttributesTable = new AttributeTable(signedAttributes); + signedAttributesTable.toASN1EncodableVector(); + DefaultSignedAttributeTableGenerator signedAttributeGenerator = new DefaultSignedAttributeTableGenerator(signedAttributesTable); + + /* Build the SignerInfo generator builder, that will build the generator... that will generate the SignerInformation... */ + SignerInfoGeneratorBuilder signerInfoBuilder = new SignerInfoGeneratorBuilder( + new JcaDigestCalculatorProviderBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build()); + signerInfoBuilder.setSignedAttributeGenerator(signedAttributeGenerator); + CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); + JcaContentSignerBuilder contentSigner = + new JcaContentSignerBuilder(digestMethod.getMethod()).setProvider(BouncyCastleProvider.PROVIDER_NAME); + + generator.addSignerInfoGenerator(signerInfoBuilder.build( + contentSigner.build(privateKey), new X509CertificateHolder(certificate.getEncoded()))); + generator.addCertificates(new JcaCertStore(Collections.singletonList(certificate))); + + return generator.generate(new CMSAbsentContent()).getEncoded(); + } catch (CMSException | IOException | CertificateEncodingException | OperatorCreationException e) { + throw new OxalisSecurityException(e.getMessage(), e); + } + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeDigestMethod.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeDigestMethod.java new file mode 100644 index 0000000000000000000000000000000000000000..82e0a82aba216e4bc20e012db9105bc987a5d38d --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeDigestMethod.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import network.oxalis.vefa.peppol.common.code.DigestMethod; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; + +import java.security.NoSuchAlgorithmException; + +public enum SMimeDigestMethod { + + sha1(new String[]{"sha1", "sha-1", "rsa-sha1"}, "SHA1withRSA", "SHA-1", OIWObjectIdentifiers.idSHA1, + DigestMethod.SHA1, TransportProfile.PEPPOL_AS2_1_0), + + sha256(new String[]{"sha256", "sha-256"}, "SHA256withRSA", "SHA-256", NISTObjectIdentifiers.id_sha256, + DigestMethod.SHA256, TransportProfile.PEPPOL_AS2_2_0), + + sha512(new String[]{"sha512", "sha-512"}, "SHA512withRSA", "SHA-512", NISTObjectIdentifiers.id_sha512, + DigestMethod.SHA512, TransportProfile.of("busdox-transport-as2-ver1p0r1")), + + ; + + private final String[] identifier; + + private final String method; + + private final String algorithm; + + private final ASN1ObjectIdentifier oid; + + private final DigestMethod digestMethod; + + private final TransportProfile transportProfile; + + SMimeDigestMethod(String[] identifier, String method, String algorithm, ASN1ObjectIdentifier oid, + DigestMethod digestMethod, TransportProfile transportProfile) { + this.identifier = identifier; + this.method = method; + this.algorithm = algorithm; + this.oid = oid; + this.digestMethod = digestMethod; + this.transportProfile = transportProfile; + } + + public String getIdentifier() { + return identifier[0]; + } + + public String getMethod() { + return method; + } + + public String getAlgorithm() { + return algorithm; + } + + public ASN1ObjectIdentifier getOid() { + return oid; + } + + public DigestMethod getDigestMethod() { + return digestMethod; + } + + public TransportProfile getTransportProfile() { + return transportProfile; + } + + public static SMimeDigestMethod findByIdentifier(String identifier) throws NoSuchAlgorithmException { + String provided = String.valueOf(identifier).toLowerCase(); + + for (SMimeDigestMethod digestMethod : values()) + for (String ident : digestMethod.identifier) + if (ident.equals(provided)) + return digestMethod; + + throw new NoSuchAlgorithmException(String.format( + "Digest method '%s' not known.", identifier)); + } + + public static SMimeDigestMethod findByTransportProfile(TransportProfile transportProfile) { + for (SMimeDigestMethod digestMethod : values()) + if (digestMethod.transportProfile.equals(transportProfile)) + return digestMethod; + + throw new IllegalArgumentException(String.format( + "Digest method for transport profile '%s' not known.", transportProfile)); + } + + public static SMimeDigestMethod findByDigestMethod(DigestMethod digestMethod) { + for (SMimeDigestMethod method : values()) + if (method.digestMethod.equals(digestMethod)) + return method; + + throw new IllegalArgumentException(String.format( + "Digest method '%s' not known.", digestMethod)); + } +} + diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeMessageFactory.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeMessageFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..518ebc85c624ccbffb2814d64d0d3530f83d9924 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SMimeMessageFactory.java @@ -0,0 +1,205 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import network.oxalis.api.lang.OxalisSecurityException; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.commons.bouncycastle.BCHelper; +import network.oxalis.vefa.peppol.common.model.Digest; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.cert.jcajce.JcaCertStore; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.mail.smime.SMIMEException; +import org.bouncycastle.mail.smime.SMIMESignedGenerator; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.util.Store; + +import javax.activation.DataHandler; +import javax.activation.DataSource; +import javax.activation.MimeType; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.mail.util.ByteArrayDataSource; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.PrivateKey; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Properties; + +/** + * Creates signed Mime messages + */ +@Singleton +public class SMimeMessageFactory { + + private final PrivateKey privateKey; + + private final X509Certificate ourCertificate; + + private final static Session session = Session.getDefaultInstance(System.getProperties(), null); + + static { + BCHelper.registerProvider(); + } + + @Inject + public SMimeMessageFactory(PrivateKey privateKey, X509Certificate ourCertificate) { + this.privateKey = privateKey; + this.ourCertificate = ourCertificate; + } + + /** + * Creates an S/MIME message from the supplied String, having the supplied MimeType as the "content-type". + * + * @param msg holds the payload of the message + * @param mimeType the MIME type to be used as the "Content-Type" + */ + public MimeMessage createSignedMimeMessage(final String msg, MimeType mimeType, SMimeDigestMethod digestMethod) + throws OxalisTransmissionException { + return createSignedMimeMessage(new ByteArrayInputStream(msg.getBytes()), mimeType, digestMethod); + } + + /** + * Creates a new S/MIME message having the supplied MimeType as the "content-type" + */ + public MimeMessage createSignedMimeMessage(final InputStream inputStream, MimeType mimeType, + SMimeDigestMethod digestMethod) throws OxalisTransmissionException { + MimeBodyPart mimeBodyPart = MimeMessageHelper.createMimeBodyPart(inputStream, mimeType.toString()); + return createSignedMimeMessage(mimeBodyPart, digestMethod); + } + + /** + * Creates an S/MIME message using the supplied MimeBodyPart. The signature is generated using the private key + * as supplied in the constructor. Our certificate, which is required to verify the signature is enclosed. + */ + public MimeMessage createSignedMimeMessage(MimeBodyPart mimeBodyPart, SMimeDigestMethod digestMethod) + throws OxalisTransmissionException { + + // + // S/MIME capabilities are required, but we simply supply an empty vector + // + ASN1EncodableVector signedAttrs = new ASN1EncodableVector(); + + // + // create the generator for creating an smime/signed message + // + SMIMESignedGenerator smimeSignedGenerator = new SMIMESignedGenerator("binary"); //also see CMSSignedGenerator ? + + // + // add a signer to the generator - this specifies we are using SHA1 and + // adding the smime attributes above to the signed attributes that + // will be generated as part of the signature. The encryption algorithm + // used is taken from the key - in this RSA with PKCS1Padding + // + try { + smimeSignedGenerator.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder() + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .setSignedAttributeGenerator(new AttributeTable(signedAttrs)) + // .build("SHA1withRSA", privateKey, ourCertificate)); + .build(digestMethod.getMethod(), privateKey, ourCertificate)); + } catch (OperatorCreationException e) { + throw new OxalisTransmissionException("Unable to add Signer information. " + e.getMessage(), e); + } catch (CertificateEncodingException e) { + throw new OxalisTransmissionException(String.format( + "Certificate encoding problems while adding signer information. %s", e.getMessage()), e); + } + + // + // create a CertStore containing the certificates we want carried + // in the signature + // + Store certs; + try { + certs = new JcaCertStore(Collections.singleton(ourCertificate)); + } catch (CertificateEncodingException e) { + throw new OxalisTransmissionException("Unable to create JcaCertStore with our certificate. " + e.getMessage(), e); + } + smimeSignedGenerator.addCertificates(certs); + + // + // Signs the supplied MimeBodyPart + // + MimeMultipart mimeMultipart; + try { + mimeMultipart = smimeSignedGenerator.generate(mimeBodyPart); + } catch (SMIMEException e) { + throw new OxalisTransmissionException("Unable to generate signed mime multipart." + e.getMessage(), e); + } + + // + // Get a Session object and create the mail message + // + Properties props = System.getProperties(); + Session session = Session.getDefaultInstance(props, null); + + MimeMessage mimeMessage = new MimeMessage(session); + + try { + mimeMessage.setContent(mimeMultipart, mimeMultipart.getContentType()); + } catch (MessagingException e) { + throw new OxalisTransmissionException("Unable to set Content type of MimeMessage. " + e.getMessage(), e); + } + try { + mimeMessage.saveChanges(); + } catch (MessagingException e) { + throw new OxalisTransmissionException("Unable to save changes to Mime message. " + e.getMessage(), e); + } + + return mimeMessage; + } + + public MimeMessage createSignedMimeMessageNew(MimeBodyPart mimeBodyPart, Digest digest, SMimeDigestMethod digestMethod) + throws OxalisTransmissionException { + try { + MimeMultipart mimeMultipart = new MimeMultipart(); + mimeMultipart.setSubType("signed"); + mimeMultipart.addBodyPart(mimeBodyPart); + + MimeBodyPart signaturePart = new MimeBodyPart(); + DataSource dataSource = new ByteArrayDataSource(SMimeBC.createSignature(digest.getValue(), digestMethod, privateKey, ourCertificate), "application/pkcs7-signature"); + signaturePart.setDataHandler(new DataHandler(dataSource)); + signaturePart.setHeader("Content-Type", "application/pkcs7-signature; name=smime.p7s; smime-type=signed-data"); + signaturePart.setHeader("Content-Transfer-Encoding", "base64"); + signaturePart.setHeader("Content-Disposition", "attachment; filename=\"smime.p7s\""); + signaturePart.setHeader("Content-Description", "S/MIME Cryptographic Signature"); + mimeMultipart.addBodyPart(signaturePart); + + MimeMessage mimeMessage = new MimeMessage(session); + mimeMessage.setContent(mimeMultipart, mimeMultipart.getContentType()); + mimeMessage.saveChanges(); + + return mimeMessage; + } catch (MessagingException | OxalisSecurityException e) { + throw new OxalisTransmissionException(e.getMessage(), e); + } + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SignedMessage.java b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SignedMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..007dcd9ee0a08fa5ba92e8c410460e5a48afc631 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/java/network/oxalis/as2/util/SignedMessage.java @@ -0,0 +1,221 @@ +package network.oxalis.as2.util; + +import com.google.common.io.ByteStreams; +import com.sun.mail.util.LineOutputStream; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.lang.OxalisSecurityException; +import network.oxalis.as2.lang.OxalisAs2Exception; +import network.oxalis.commons.bouncycastle.BCHelper; +import network.oxalis.commons.security.CertificateUtils; +import network.oxalis.vefa.peppol.common.code.Service; +import network.oxalis.vefa.peppol.security.api.CertificateValidator; +import network.oxalis.vefa.peppol.security.lang.PeppolSecurityException; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.SignerInformation; +import org.bouncycastle.cms.SignerInformationVerifier; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.mail.smime.SMIMESigned; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.util.CollectionStore; + +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.internet.ContentType; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; + +/** + * @author erlend + */ +@Slf4j +public class SignedMessage { + + private static final Session SESSION = Session.getDefaultInstance(System.getProperties()); + + private MimeMultipart mimeMultipart; + + private SMIMESigned smimeSigned; + + // private List

headers; + + private byte[] signature; + + private String micalg; + + private X509Certificate signer; + + private byte[] digest; + + static { + BCHelper.registerProvider(); + } + + public static SignedMessage load(InputStream inputStream) throws IOException, MessagingException, OxalisAs2Exception { + return new SignedMessage(new MimeMessage(SESSION, inputStream)); + } + + public static SignedMessage load(MimeMessage mimeMessage) throws IOException, OxalisAs2Exception { + return new SignedMessage(mimeMessage); + } + + private SignedMessage(MimeMessage message) throws IOException, OxalisAs2Exception { + try { + // Verify content type + if (!message.isMimeType("multipart/signed")) + throw new OxalisAs2Exception("Received content is not 'multipart/signed'."); + + micalg = extractMicalg(message); + + // Extract headers + //noinspection unchecked + // headers = Collections.list((Enumeration
) message.getAllHeaders()); + + // Create MimeMultitype + mimeMultipart = (MimeMultipart) message.getContent(); + + // Extracting signature + signature = ByteStreams.toByteArray(mimeMultipart.getBodyPart(1).getInputStream()); + + // Create signed message + smimeSigned = new SMIMESigned(mimeMultipart); + } catch (CMSException | MessagingException e) { + throw new OxalisAs2Exception("Unable to parse received content.", e); + } + } + + public InputStream getContent() throws IOException, OxalisSecurityException, OxalisAs2Exception { + try { + if (signer == null) + throw new OxalisSecurityException("Content is not validated."); + + return smimeSigned.getContent().getInputStream(); + } catch (MessagingException e) { + throw new OxalisAs2Exception("Unable to fetch content.", e); + } + } + + public byte[] getContentBytes() throws IOException, OxalisSecurityException, OxalisAs2Exception { + return ByteStreams.toByteArray(getContent()); + } + + public String getMicalg() { + return micalg; + } + + public X509Certificate getSigner() { + return signer; + } + + public byte[] getDigest() { + return digest; + } + + public byte[] getSignature() { + return signature; + } + + /** + * Extracts headers of body MIME part. Creates headers as done by Bouncycastle. + * + * @return Headers + */ + public byte[] getBodyHeader() throws IOException, OxalisAs2Exception { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + LineOutputStream los = new LineOutputStream(outputStream); + + Enumeration hdrLines = ((MimeBodyPart) mimeMultipart.getBodyPart(0)).getNonMatchingHeaderLines(new String[]{}); + while (hdrLines.hasMoreElements()) + los.writeln((String) hdrLines.nextElement()); + + // The CRLF separator between header and content + los.writeln(); + los.close(); + + return outputStream.toByteArray(); + } catch (MessagingException e) { + throw new OxalisAs2Exception("Unable to fetch body headers.", e); + } + } + + + public void validate(X509Certificate certificate) throws OxalisSecurityException, PeppolSecurityException { + try { + SignerInformationVerifier verifier = new JcaSimpleSignerInfoVerifierBuilder() + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .build(certificate.getPublicKey()); + + for (SignerInformation signerInformation : smimeSigned.getSignerInfos().getSigners()) { + if (signerInformation.verify(verifier)) { + signer = certificate; + digest = signerInformation.getContentDigest(); + return; + } + } + } catch (CMSException e) { + throw new OxalisSecurityException(e.getMessage(), e); + } catch (OperatorCreationException e) { + throw new OxalisSecurityException("Unable to create SignerInformationVerifier.", e); + } + + throw new PeppolSecurityException("Unable to verify signature."); + } + + public void validate(Service service, CertificateValidator validator) + throws IOException, OxalisSecurityException, PeppolSecurityException { + validate(service, validator, null); + } + + public void validate(Service service, CertificateValidator validator, String commonName) + throws IOException, OxalisSecurityException, PeppolSecurityException { + for (X509CertificateHolder holder : (CollectionStore) smimeSigned.getCertificates()) { + if (CertificateUtils.containsCommonName(holder.getSubject(), commonName)) { + try { + X509Certificate certificate = CertificateUtils.parseCertificate(holder.getEncoded()); + + if (isValid(service, validator, certificate)) { + validate(certificate); + return; + } + } catch (CertificateException e) { + log.debug("Unable to initiate certificate object."); + } + } + } + + throw new OxalisSecurityException(commonName == null ? + "Unable to find valid certificate for validation of content." : + String.format("Unable to find valid certificate with CN '%s' for validation of content.", commonName)); + } + + private boolean isValid(Service service, CertificateValidator validator, X509Certificate certificate) { + try { + validator.validate(service, certificate); + return true; + } catch (PeppolSecurityException e) { + return false; + } + } + + public static String extractMicalg(MimeMessage message) throws OxalisAs2Exception { + try { + ContentType contentType = new ContentType(message.getContentType()); + String micalg = contentType.getParameter("micalg"); + if (micalg == null) + throw new OxalisAs2Exception("Parameter 'micalg' is not provided."); + + return micalg; + } catch (MessagingException e) { + throw new OxalisAs2Exception("Unable to fetch content type.", e); + } + } +} diff --git a/oxalis-extension/oxalis-as2/src/main/resources/reference.conf b/oxalis-extension/oxalis-as2/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..aaf1f1f445b419a5c7ec8545cf542927bef98967 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/main/resources/reference.conf @@ -0,0 +1,29 @@ +oxalis.module.as2.core = { + class = network.oxalis.as2.common.As2CommonModule +} +oxalis.module.as2.inbound = { + class = network.oxalis.as2.inbound.As2InboundModule + dependency = inbound.servlet +} +oxalis.module.as2.outbound = { + class = network.oxalis.as2.outbound.As2OutboundModule + dependency = outbound.lookup +} + +defaults.transport.as2_sha1 = { + profile: busdox-transport-as2-ver1p0 + sender: oxalis-as2 + weight: 1000 +} + +defaults.transport.as2_sha256 = { + profile: busdox-transport-as2-ver2p0 + sender: oxalis-as2 + weight: 1500 +} + +defaults.transport.as2_sha512 = { + profile: busdox-transport-as2-ver1p0r1 + sender: oxalis-as2 + weight: 2000 +} \ No newline at end of file diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/SimpleLoadTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/SimpleLoadTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8d1f6a0f912ec7abe0b22ff60262f3a893ecc730 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/SimpleLoadTest.java @@ -0,0 +1,143 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Names; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.outbound.MessageSender; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.as2.inbound.As2InboundModule; +import network.oxalis.as2.outbound.As2OutboundModule; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.test.jetty.AbstractJettyServerTest; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.InputStream; +import java.net.URI; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +@Slf4j +public class SimpleLoadTest extends AbstractJettyServerTest { + + private static final int MESSAGES = 500; + + @Override + public Injector getInjector() { + return Guice.createInjector( + new GuiceModuleLoader(), + new As2OutboundModule(), + new As2InboundModule() + ); + } + + @Test + public void simpleSha1() throws Exception { + MessageSender messageSender = injector.getInstance(Key.get(MessageSender.class, Names.named("oxalis-as2"))); + + TransmissionRequest transmissionRequest = new TransmissionRequest() { + @Override + public Endpoint getEndpoint() { + return Endpoint.of(TransportProfile.PEPPOL_AS2_1_0, URI.create("http://localhost:8080/as2"), + injector.getInstance(X509Certificate.class)); + } + + @Override + public Header getHeader() { + return Header.newInstance(); + } + + @Override + public InputStream getPayload() { + return getClass().getResourceAsStream("/as2-peppol-bis-invoice-sbdh.xml"); + } + }; + + long ts = System.currentTimeMillis(); + ExecutorService executorService = Executors.newFixedThreadPool(10); + + List> futures = new ArrayList<>(); + for (int i = 0; i < MESSAGES; i++) + futures.add(executorService.submit(() -> messageSender.send(transmissionRequest))); + + for (Future future : futures) + future.get(); + + long result = System.currentTimeMillis() - ts; + log.info("Sent {} messages in {} ms.", MESSAGES, result); + + Assert.assertTrue(result < 5 * 60 * 1000, + String.format("Sending %s messages took more than one minute.", MESSAGES)); + } + + @Test + public void simpleSha256() throws Exception { + MessageSender messageSender = injector.getInstance(Key.get(MessageSender.class, Names.named("oxalis-as2"))); + + TransmissionRequest transmissionRequest = new TransmissionRequest() { + @Override + public Endpoint getEndpoint() { + return Endpoint.of(TransportProfile.PEPPOL_AS2_2_0, URI.create("http://localhost:8080/as2"), + injector.getInstance(X509Certificate.class)); + } + + @Override + public Header getHeader() { + return Header.newInstance(); + } + + @Override + public InputStream getPayload() { + return getClass().getResourceAsStream("/as2-peppol-bis-invoice-sbdh.xml"); + } + }; + + long ts = System.currentTimeMillis(); + ExecutorService executorService = Executors.newFixedThreadPool(10); + + List> futures = new ArrayList<>(); + for (int i = 0; i < MESSAGES; i++) + futures.add(executorService.submit(() -> messageSender.send(transmissionRequest))); + + for (Future future : futures) + future.get(); + + long result = System.currentTimeMillis() - ts; + log.info("Sent {} messages in {} ms.", MESSAGES, result); + + Assert.assertTrue(result < 5 * 60 * 1000, + String.format("Sending %s messages took more than one minute.", MESSAGES)); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/SimpleServerTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/SimpleServerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2c7f3a3df3da44bd61a4d54fa1a268e66bed36dc --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/SimpleServerTest.java @@ -0,0 +1,161 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2; + +import com.google.common.io.ByteStreams; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Names; +import com.google.inject.util.Modules; +import network.oxalis.api.outbound.MessageSender; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.persist.ReceiptPersister; +import network.oxalis.as2.util.SMimeDigestMethod; +import network.oxalis.as2.inbound.As2InboundModule; +import network.oxalis.as2.outbound.As2OutboundModule; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.test.jetty.AbstractJettyServerTest; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import org.testng.Assert; +import org.testng.annotations.Test; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URL; +import java.security.cert.X509Certificate; + +public class SimpleServerTest extends AbstractJettyServerTest { + + @Override + public Injector getInjector() { + return Guice.createInjector( + new As2OutboundModule(), + new As2InboundModule(), + Modules.override(new GuiceModuleLoader()).with(new OxalisModule() { + @Override + protected void configure() { + bind(ReceiptPersister.class).toInstance((m, p) -> { + /* + Assert.assertEquals( + m.getDigest().getValue(), + Base64.getDecoder().decode("WJ/tC+Ijr05qtT60fByQ8LQ4l9k=") + ); + */ + }); + } + })); + } + + @Test + public void simple() throws Exception { + MessageSender messageSender = injector.getInstance(Key.get(MessageSender.class, Names.named("oxalis-as2"))); + + TransmissionResponse transmissionResponse = messageSender.send(new TransmissionRequest() { + @Override + public Endpoint getEndpoint() { + return Endpoint.of(TransportProfile.PEPPOL_AS2_1_0, URI.create("http://localhost:8080/as2"), + injector.getInstance(X509Certificate.class)); + } + + @Override + public Header getHeader() { + return Header.newInstance(); + } + + @Override + public InputStream getPayload() { + return getClass().getResourceAsStream("/as2-peppol-bis-invoice-sbdh.xml"); + } + }); + + Assert.assertNotNull(transmissionResponse); + } + + @Test + public void simpleSha256() throws Exception { + MessageSender messageSender = injector.getInstance(Key.get(MessageSender.class, Names.named("oxalis-as2"))); + + TransmissionResponse transmissionResponse = messageSender.send(new TransmissionRequest() { + @Override + public Endpoint getEndpoint() { + return Endpoint.of(TransportProfile.PEPPOL_AS2_2_0, URI.create("http://localhost:8080/as2"), + injector.getInstance(X509Certificate.class)); + } + + @Override + public Header getHeader() { + return Header.newInstance(); + } + + @Override + public InputStream getPayload() { + return getClass().getResourceAsStream("/as2-peppol-bis-invoice-sbdh.xml"); + } + }); + + Assert.assertNotNull(transmissionResponse); + } + + @Test + public void simpleSha512() throws Exception { + MessageSender messageSender = injector.getInstance(Key.get(MessageSender.class, Names.named("oxalis-as2"))); + + TransmissionResponse transmissionResponse = messageSender.send(new TransmissionRequest() { + @Override + public Endpoint getEndpoint() { + return Endpoint.of( + SMimeDigestMethod.sha512.getTransportProfile(), + URI.create("http://localhost:8080/as2"), + injector.getInstance(X509Certificate.class)); + } + + @Override + public Header getHeader() { + return Header.newInstance(); + } + + @Override + public InputStream getPayload() { + return getClass().getResourceAsStream("/as2-peppol-bis-invoice-sbdh.xml"); + } + }); + + Assert.assertNotNull(transmissionResponse); + } + + @Test + public void simpleGet() throws Exception { + HttpURLConnection urlConnection = (HttpURLConnection) new URL("http://localhost:8080/as2").openConnection(); + + Assert.assertTrue(new String(ByteStreams.toByteArray(urlConnection.getInputStream())) + .contains("Hello AS2 world")); + Assert.assertEquals(urlConnection.getResponseCode(), HttpServletResponse.SC_OK); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/As2HeaderTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/As2HeaderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..44eb25d68ced76f5b64c74632bf97ee8162ebdfd --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/As2HeaderTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +import org.testng.annotations.Test; + +public class As2HeaderTest { + + @Test + public void simpleConstructor() { + new As2Header(); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionModifierExtensionTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionModifierExtensionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..41240e21b5b72e731a25d964f2290ebd028cdb94 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionModifierExtensionTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class DispositionModifierExtensionTest { + + @Test + public void simple() { + Assert.assertEquals(DispositionModifierExtension.of("authentication-failed"), DispositionModifierExtension.AUTHENTICATION_FAILED); + Assert.assertEquals(DispositionModifierExtension.valueOf("AUTHENTICATION_FAILED"), DispositionModifierExtension.AUTHENTICATION_FAILED); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void triggerException() { + DispositionModifierExtension.of("invalid-code"); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionModifierTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionModifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3e062938c89180b8c241273e0674a8e6b8e1052b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionModifierTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class DispositionModifierTest { + + @Test + public void simple() { + Assert.assertEquals(DispositionModifier.of("error"), DispositionModifier.ERROR); + Assert.assertEquals(DispositionModifier.valueOf("ERROR"), DispositionModifier.ERROR); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void triggerException() { + DispositionModifier.of("info"); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1eadf14b759d7148bef4a717653ea039cdf63576 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class DispositionTest { + + /** + * RFC4130 7.5.6 + */ + @Test + public void backeardCompatibility() { + perform("automatic-action/MDN-sent-automatically; processed", DispositionType.PROCESSED, null, null); + + perform("automatic-action/MDN-sent-automatically; processed/error: authentication-failed", + DispositionType.PROCESSED, DispositionModifier.ERROR, + DispositionModifierExtension.AUTHENTICATION_FAILED); + + perform("automatic-action/MDN-sent-automatically;\n" + + " processed/error: authentication-failed", + DispositionType.PROCESSED, DispositionModifier.ERROR, + DispositionModifierExtension.AUTHENTICATION_FAILED); + + perform("automatic-action/MDN-sent-automatically; processed/warning: duplicate-document", + DispositionType.PROCESSED, DispositionModifier.WARNING, + DispositionModifierExtension.DUPLICATE_DOCUMENT); + + perform("automatic-action/MDN-sent-automatically;\n" + + " processed/warning: duplicate-document", + DispositionType.PROCESSED, DispositionModifier.WARNING, + DispositionModifierExtension.DUPLICATE_DOCUMENT); + + perform("automatic-action/MDN-sent-automatically; failed/failure: sender-equals-receiver", + DispositionType.FAILED, DispositionModifier.FAILURE, + DispositionModifierExtension.SENDER_EQUALS_RECEIVER); + + perform("automatic-action/MDN-sent-automatically;\n" + + " failed/failure: sender-equals-receiver", + DispositionType.FAILED, DispositionModifier.FAILURE, + DispositionModifierExtension.SENDER_EQUALS_RECEIVER); + } + + private void perform(String value, DispositionType type, DispositionModifier modifier, + DispositionModifierExtension extension) { + Disposition disposition = Disposition.parse(value); + + Assert.assertEquals(disposition.getType(), type); + Assert.assertEquals(disposition.getModifier(), modifier); + Assert.assertEquals(disposition.getExtension(), extension); + Assert.assertEquals(disposition.toString(), value.replaceAll("[ \r\n\t]+", " ")); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void invalidValue() { + Disposition.parse("Hello World"); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionTypeTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionTypeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..03493cc747bc38006072f119ddd299d5a1d9e4a1 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/DispositionTypeTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +import org.testng.Assert; +import org.testng.annotations.Test; + +import static network.oxalis.as2.code.DispositionType.*; + +/** + * @author erlend + */ +public class DispositionTypeTest { + + @Test + public void simple() { + Assert.assertEquals(of("processed"), PROCESSED); + Assert.assertEquals(valueOf("PROCESSED"), PROCESSED); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void triggerException() { + of("handled"); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/MdnHeaderTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/MdnHeaderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b220d9ee3bceed9b2c3e177c3d11b23479d18b8e --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/code/MdnHeaderTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.code; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class MdnHeaderTest { + + @Test + public void simpleConstructor() { + new MdnHeader(); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/inbound/As2InboundHandlerTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/inbound/As2InboundHandlerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d53e7d87d0731db3a27da117aa802db1262098d6 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/inbound/As2InboundHandlerTest.java @@ -0,0 +1,151 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.inbound; + +import com.google.inject.Inject; +import io.opentracing.Tracer; +import network.oxalis.api.inbound.InboundService; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.model.Direction; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.api.timestamp.TimestampProvider; +import network.oxalis.as2.code.As2Header; +import network.oxalis.as2.util.MimeMessageHelper; +import network.oxalis.as2.util.SMimeDigestMethod; +import network.oxalis.as2.util.SMimeMessageFactory; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.commons.header.SbdhHeaderParser; +import network.oxalis.commons.identifier.DefaultMessageIdGenerator; +import network.oxalis.commons.mode.OxalisCertificateValidator; +import network.oxalis.commons.persist.NoopPersister; +import network.oxalis.commons.security.CertificateUtils; +import network.oxalis.commons.tag.NoopTagGenerator; +import network.oxalis.commons.transmission.DefaultTransmissionVerifier; +import network.oxalis.vefa.peppol.security.api.CertificateValidator; +import org.mockito.Mockito; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.mail.MessagingException; +import javax.mail.internet.InternetHeaders; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.Date; + +import static org.testng.Assert.assertNotNull; + +/** + * Verifies that the As2InboundHandler works as expected. + * + * @author steinar + * Date: 08.12.2015 + * Time: 15.21 + */ +@Guice(modules = GuiceModuleLoader.class) +public class As2InboundHandlerTest { + + private InternetHeaders headers; + + private TimestampProvider mockTimestampProvider; + + @Inject + private X509Certificate certificate; + + @Inject + private PrivateKey privateKey; + + @Inject + private SMimeMessageFactory sMimeMessageFactory; + + @Inject + private Tracer tracer; + + @BeforeClass + public void setUp() throws Exception { + mockTimestampProvider = Mockito.mock(TimestampProvider.class); + Mockito.doReturn(new Timestamp(new Date(), null)).when(mockTimestampProvider) + .generate(Mockito.any(), Mockito.any(Direction.class)); + Mockito.doReturn(new Timestamp(new Date(), null)).when(mockTimestampProvider) + .generate(Mockito.any(), Mockito.any(Direction.class), Mockito.any()); + + String ourCommonName = CertificateUtils.extractCommonName(certificate); + + headers = new InternetHeaders(); + headers.addHeader(As2Header.DISPOSITION_NOTIFICATION_OPTIONS, "Disposition-Notification-Options: signed-receipt-protocol=required, pkcs7-signature; signed-receipt-micalg=required,sha1"); + headers.addHeader(As2Header.AS2_TO, ourCommonName); + headers.addHeader(As2Header.AS2_FROM, ourCommonName); + headers.addHeader(As2Header.MESSAGE_ID, "42"); + headers.addHeader(As2Header.AS2_VERSION, As2Header.VERSION); + headers.addHeader(As2Header.SUBJECT, "An AS2 message"); + headers.addHeader(As2Header.DATE, "Mon Oct 21 22:01:48 CEST 2013"); + + } + + @Test(enabled = false) + public void testReceive() throws Exception { + InputStream inputStream = loadSampleMimeMessage(); + + As2InboundHandler as2InboundHandler = new As2InboundHandler(Mockito.mock(InboundService.class), + mockTimestampProvider, new OxalisCertificateValidator(CertificateValidator.EMPTY, tracer), new NoopPersister(), + new DefaultTransmissionVerifier(), sMimeMessageFactory, new NoopTagGenerator(), + new DefaultMessageIdGenerator("test"), new SbdhHeaderParser()); + + MimeMessage mimeMessage = MimeMessageHelper.parse(inputStream, headers); + as2InboundHandler.receive(headers, mimeMessage, tracer.buildSpan("test").start()); + } + + + /** + * Creates a fake S/MIME message, to mimic the data being posted in an http POST request. + * + * @return + */ + InputStream loadSampleMimeMessage() { + + InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("sbdh-asic.xml"); + assertNotNull(resourceAsStream); + + try { + MimeBodyPart mimeBodyPart = MimeMessageHelper.createMimeBodyPart(resourceAsStream, "application/xml"); + + SMimeMessageFactory sMimeMessageFactory = new SMimeMessageFactory(privateKey, certificate); + MimeMessage signedMimeMessage = sMimeMessageFactory + .createSignedMimeMessage(mimeBodyPart, SMimeDigestMethod.sha1); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + signedMimeMessage.writeTo(os); + + return new ByteArrayInputStream(os.toByteArray()); + } catch (MessagingException | IOException | OxalisTransmissionException e) { + throw new IllegalStateException( + "Unable to write S/MIME message to byte array outputstream " + e.getMessage(), e); + } + } +} + diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/mocking/InboundMockingModule.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/mocking/InboundMockingModule.java new file mode 100644 index 0000000000000000000000000000000000000000..3cb3de054b258a9c09cd56d3c0bb54531883cc8d --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/mocking/InboundMockingModule.java @@ -0,0 +1,16 @@ +package network.oxalis.as2.mocking; + +import network.oxalis.api.inbound.InboundService; +import network.oxalis.commons.guice.OxalisModule; +import org.mockito.Mockito; + +/** + * @author erlend + */ +public class InboundMockingModule extends OxalisModule { + + @Override + protected void configure() { + bind(InboundService.class).toInstance(Mockito.mock(InboundService.class)); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/As2DispositionNotificationOptionsTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/As2DispositionNotificationOptionsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..400b86e8538aea755cab5dd706b63fbae4daf3be --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/As2DispositionNotificationOptionsTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.model; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * @author steinar + * Date: 17.10.13 + * Time: 21:36 + */ +public class As2DispositionNotificationOptionsTest { + + @Test + public void createFromString() { + + As2DispositionNotificationOptions options = As2DispositionNotificationOptions.valueOf("signed-receipt-protocol=required, pkcs7-signature; signed-receipt-micalg=required,sha1"); + assertEquals(options.getParameters().size(), 2); + + As2DispositionNotificationOptions.Parameter parameter = options.getSignedReceiptProtocol(); + assertNotNull(parameter); + + As2DispositionNotificationOptions.Parameter micAlg = options.getSignedReceiptMicalg(); + assertNotNull(micAlg); + + } + + @Test + public void testFromRealMendelsonHeader() { + + As2DispositionNotificationOptions options = As2DispositionNotificationOptions.valueOf("disposition-notification-options: signed-receipt-protocol=optional, pkcs7-signature; signed-receipt-micalg=optional, sha1, md5"); + assertEquals(options.getParameters().size(), 2); + + As2DispositionNotificationOptions.Parameter parameter = options.getSignedReceiptProtocol(); + assertNotNull(parameter); + + As2DispositionNotificationOptions.Parameter micAlg = options.getSignedReceiptMicalg(); + assertNotNull(micAlg); + + assertEquals(micAlg.getTextValue(), "sha1, md5"); + + assertEquals(options.getPreferredSignedReceiptMicAlgorithmName(), "sha1"); + + } + + @Test + public void testSomeExamplesFromCipa() { + + As2DispositionNotificationOptions o1 = As2DispositionNotificationOptions.valueOf("signed-receipt-protocol=optional, pkcs7-signature; signed-receipt-micalg=optional, sha1"); + assertNotNull(o1.getSignedReceiptMicalg()); + assertEquals(o1.getSignedReceiptMicalg().getTextValue(), "sha1"); + + As2DispositionNotificationOptions o2 = As2DispositionNotificationOptions.valueOf("signed-receipt-protocol=required, pkcs7-signature; signed-receipt-micalg=required, sha1"); + assertNotNull(o2.getSignedReceiptMicalg()); + assertEquals(o2.getSignedReceiptMicalg().getTextValue(), "sha1"); + + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void createFromInvalidString() { + As2DispositionNotificationOptions.valueOf("signed-receipt-protocol=reXXuired, pkcs7-signature"); + } + + @Test + public void testToString() { + As2DispositionNotificationOptions options = As2DispositionNotificationOptions.valueOf("signed-receipt-protocol=required, pkcs7-signature; signed-receipt-micalg=required,sha1"); + assertEquals(options.toString(), "signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1"); + + As2DispositionNotificationOptions opt2 = As2DispositionNotificationOptions.valueOf(options.toString()); + assertNotNull(opt2); + assertEquals(opt2.getSignedReceiptMicalg().getImportance(), As2DispositionNotificationOptions.Importance.REQUIRED); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/As2DispositionTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/As2DispositionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..70b4ad763d17f904355401697267a1603e06393b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/As2DispositionTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.model; + +import org.testng.annotations.Test; + +import java.util.regex.Matcher; + +import static org.testng.Assert.*; + +/** + * @author steinar + * Date: 10.10.13 + * Time: 18:50 + */ +public class As2DispositionTest { + + @Test + public void testToString() throws Exception { + + String s = As2Disposition.processed().toString(); + assertEquals(s, "automatic-action/MDN-sent-automatically; processed"); + + s = As2Disposition.failed("uhada").toString(); + assertEquals(s.toLowerCase(), "automatic-action/mdn-sent-automatically; failed/failure: uhada"); + + s = As2Disposition.processedWithError("Ouch!").toString(); + assertEquals(s.toLowerCase(), "automatic-action/mdn-sent-automatically; processed/error: ouch!"); + + } + + @Test + public void parseWithPattern() throws Exception { + String s = "automatic-action/MDN-sent-automatically; processed/error: Unknown recipient"; + + Matcher matcher = As2Disposition.pattern.matcher(s); + assertTrue(matcher.matches()); + assertEquals(matcher.groupCount(), 6); + + String actionMode = matcher.group(1); + String sendingMode = matcher.group(2); + String dispositionType = matcher.group(3); + String dispositionModifierPrefix = matcher.group(5); + String dispositionModifier = matcher.group(6); + + assertEquals(actionMode, "automatic-action"); + assertEquals(sendingMode, "MDN-sent-automatically"); + assertEquals(dispositionType, "processed"); + assertEquals(dispositionModifierPrefix, "error"); + assertEquals(dispositionModifier, "Unknown recipient"); + + s = "automatic-action/MDN-sent-automatically; processed"; + matcher = As2Disposition.pattern.matcher(s); + assertTrue(matcher.matches()); + + assertEquals(matcher.toMatchResult().groupCount(), 6); + + assertEquals(matcher.group(4), null); + } + + @Test + public void parseWithValueOf() throws Exception { + String s = "automatic-action/MdN-sent-automatically; processed/error: Unknown recipient"; + As2Disposition as2Disposition = As2Disposition.valueOf(s); + assertNotNull(as2Disposition); + + assertEquals(as2Disposition.getActionMode(), As2Disposition.ActionMode.AUTOMATIC); + assertEquals(as2Disposition.getSendingMode(), As2Disposition.SendingMode.AUTOMATIC); + assertEquals(as2Disposition.getDispositionType(), As2Disposition.DispositionType.PROCESSED); + assertEquals(as2Disposition.getDispositionModifier().getPrefix(), As2Disposition.DispositionModifier.Prefix.ERROR); + assertEquals(as2Disposition.getDispositionModifier().getDispositionModifierExtension(), "Unknown recipient"); + } + + @Test + public void parseWithValueOfAdvanced() throws Exception { + String s = "automatic-action/MDN-sent-automatically; processed/ERROR: Payload does not contain Standard Business Document Header "; + As2Disposition as2Disposition = As2Disposition.valueOf(s); + assertNotNull(as2Disposition); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void parseLongDispositionFromRealWorldTesting() { + String s = "automatic-action/MDN-sent-automatically; processed\\Error: unexpected-error"; + As2Disposition.valueOf(s); // illegal syntax + } + + @Test + public void parseLongDispositionFromRealWorldTestingFixed() { + String s = " automatic-action/MDN-sent-automatically; processed/Error: unexpected-error "; + As2Disposition unimaze = As2Disposition.valueOf(s); + assertEquals(unimaze.getDispositionModifier().getDispositionModifierExtension(), "unexpected-error"); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void parseShortDispositionFromRealWorldTesting() { + String s = "Disposition: \"disposition-mode\"; processed"; + s = s.split("Disposition:")[1]; + As2Disposition.valueOf(s); // illegal syntax + } + +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/MicTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/MicTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b333906929a6ce34064bee8cfe1f4b6d1e26044b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/model/MicTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.model; + +import network.oxalis.as2.util.SMimeDigestMethod; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertNotNull; + +/** + * @author steinar + * Date: 22.10.13 + * Time: 16:01 + */ +public class MicTest { + @Test + public void testToString() throws Exception { + Mic mic = new Mic("eeWNkOTx7yJYr2EW8CR85I7QJQY=", SMimeDigestMethod.sha1); + assertNotNull(mic); + } + + @Test + public void testValueOf() throws Exception { + + Mic mic = Mic.valueOf("eeWNkOTx7yJYr2EW8CR85I7QJQY=, sha1"); + assertNotNull(mic); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MdnMimeMessageInspectorTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MdnMimeMessageInspectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3bd408035aeda7709cf248f45978da24b3e081af --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MdnMimeMessageInspectorTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import org.testng.annotations.Test; + +import javax.mail.internet.MimeMessage; +import java.io.InputStream; +import java.util.Map; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * @author steinar + * Date: 13.11.13 + * Time: 10:30 + */ +public class MdnMimeMessageInspectorTest { + + public static final String OPENAS2_MDN_TXT = "openas2-mdn.txt"; + + public static final String IBX_MDN_BASE64 = "real-mdn-examples/ibx-mdn-base64.txt"; + + @Test + public void parseOpenAS2MDN() throws Exception { + + InputStream resourceAsStream = MdnMimeMessageInspectorTest.class.getClassLoader().getResourceAsStream(OPENAS2_MDN_TXT); + assertNotNull(resourceAsStream, "Unable to find " + OPENAS2_MDN_TXT + " in class path"); + + MimeMessage mimeMessage = MimeMessageHelper.parse(resourceAsStream); + MdnMimeMessageInspector mdnMimeMessageInspector = new MdnMimeMessageInspector(mimeMessage); + String plainText = mdnMimeMessageInspector.getPlainTextPartAsText(); + assertNotNull(plainText); + + } + + @Test + public void parseOpenAS2MDNFields() throws Exception { + + InputStream resourceAsStream = MdnMimeMessageInspectorTest.class.getClassLoader().getResourceAsStream(OPENAS2_MDN_TXT); + assertNotNull(resourceAsStream, "Unable to find " + OPENAS2_MDN_TXT + " in class path"); + + MimeMessage mimeMessage = MimeMessageHelper.parse(resourceAsStream); + MdnMimeMessageInspector mdnMimeMessageInspector = new MdnMimeMessageInspector(mimeMessage); + Map fields = mdnMimeMessageInspector.getMdnFields(); + assertEquals(fields.get("Original-Recipient"), "rfc822; OpenAS2A"); + assertEquals(fields.get("Final-Recipient"), "rfc822; OpenAS2A"); + assertEquals(fields.get("Original-Message-ID"), "42"); + assertEquals(fields.get("Received-Content-MIC"), "Fp67Ews9SJa5pKGXVl07dBuVW4I=, sha1"); + } + + @Test + public void parseBase64EncodedMDN() throws Exception { + + InputStream resourceAsStream = MdnMimeMessageInspectorTest.class.getClassLoader().getResourceAsStream(IBX_MDN_BASE64); + assertNotNull(resourceAsStream, "Unable to find " + IBX_MDN_BASE64 + " in class path"); + + MimeMessage mimeMessage = MimeMessageHelper.parse(resourceAsStream); + MdnMimeMessageInspector mdnMimeMessageInspector = new MdnMimeMessageInspector(mimeMessage); + Map fields = mdnMimeMessageInspector.getMdnFields(); + assertEquals(fields.size(), 6); + assertEquals(fields.get("Reporting-UA"), "Oxalis"); + assertEquals(fields.get("Disposition"), "automatic-action/MDN-sent-automatically; processed"); + assertEquals(fields.get("Original-Recipient"), "rfc822; APP_1000000030"); + assertEquals(fields.get("Final-Recipient"), "rfc822; APP_1000000030"); + assertEquals(fields.get("Original-Message-ID"), "19a9099c-c553-4ffa-9c60-de2fcfa2922f"); + assertEquals(fields.get("Received-Content-MIC"), "VZOW8aRv9e8uEQEdGRdxwcOYH1g=, sha1"); + + } + +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MessageIdUtilTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MessageIdUtilTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d9d7d3ef45cce8164d3dcaf6fcc544791dd264e9 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MessageIdUtilTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class MessageIdUtilTest { + + @Test + public void simple() { + Assert.assertTrue(MessageIdUtil.verify("<1060501332.515.1528302064500@de77cf5d0088>")); + Assert.assertTrue(MessageIdUtil.verify("")); + + Assert.assertFalse(MessageIdUtil.verify("<1060501332..515.1528302064500@de77cf5d0088>")); + Assert.assertFalse(MessageIdUtil.verify(" <1060501332.515.1528302064500@de77cf5d0088>")); + Assert.assertFalse(MessageIdUtil.verify("<1060501332.515.1528302064500@de77cf5d0088")); + Assert.assertFalse(MessageIdUtil.verify("<1060501332.515.1528302064500_de77cf5d0088>")); + + Assert.assertTrue(MessageIdUtil.verify("")); + } + +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MimeMessageHelperTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MimeMessageHelperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b8b876347224ff1b0442a82db7659b50cfa09f57 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/MimeMessageHelperTest.java @@ -0,0 +1,224 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import network.oxalis.commons.bouncycastle.BCHelper; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cms.SignerInformation; +import org.bouncycastle.cms.SignerInformationStore; +import org.bouncycastle.cms.SignerInformationVerifier; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.mail.smime.SMIMESigned; +import org.bouncycastle.util.Store; +import org.testng.annotations.Test; + +import javax.activation.MimeType; +import javax.mail.BodyPart; +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.Provider; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Iterator; + +import static org.testng.Assert.*; + +/** + * @author steinar + * @author thore + */ +public class MimeMessageHelperTest { + + public static final String OPENAS2_MDN_TXT = "/openas2-mdn.txt"; + + public static final String OPENAS2_MDN_NO_HEADERS_TXT = "/openas2-mdn-no-headers.txt"; + + static { + BCHelper.registerProvider(); + } + + @Test + public void parseLegalMimeMessageWithHeaders() throws Exception { + + InputStream resourceAsStream = getClass().getResourceAsStream(OPENAS2_MDN_TXT); + assertNotNull(resourceAsStream, OPENAS2_MDN_TXT + " not found in classpath"); + + MimeMessage mimeMessage = MimeMessageHelper.parse(resourceAsStream); + Object content = mimeMessage.getContent(); + assertNotNull(content); + String contentType = mimeMessage.getContentType(); + assertEquals(new MimeType(contentType).getBaseType(), new MimeType("multipart/signed").getBaseType()); + + MimeMultipart mimeMultipartSigned = (MimeMultipart) content; + + // Two Bodies in the MimeMultiPart + assertEquals(mimeMultipartSigned.getCount(), 2); + + // First body is a multipart/report + BodyPart firstBody = mimeMultipartSigned.getBodyPart(0); + assertEquals(new MimeType(firstBody.getContentType()).getBaseType(), new MimeType("multipart/report").getBaseType()); + + // Second body contains the signature + BodyPart secondBody = mimeMultipartSigned.getBodyPart(1); + assertEquals(new MimeType(secondBody.getContentType()).getBaseType(), new MimeType("application/pkcs7-signature").getBaseType()); + + // The inner multipart should contain two bodies: the text/plain and the message/disposition-notification + MimeMultipart innerMultiPart = (MimeMultipart) firstBody.getContent(); + assertNotNull(innerMultiPart); + // Must have two parts + assertEquals(innerMultiPart.getCount(), 2); + + // First part is text/plain + assertEquals(new MimeType(innerMultiPart.getBodyPart(0).getContentType()).getBaseType(), new MimeType("text/plain").getBaseType()); + + // Second part of first part in multipart is message/disposition-notification + assertEquals(new MimeType(innerMultiPart.getBodyPart(1).getContentType()).getBaseType(), new MimeType("message/disposition-notification").getBaseType()); + } + + @Test + public void verifyingSignatureOfRealMdn() { + + boolean debug = false; // enable this to add certificate debugging + + // first we validate some real positive MDN's from various systems + String[] mdnsToVerify = {"itsligo-mdn.txt", "unit4-mdn.txt", "unimaze-mdn.txt", "difi-negative-mdn.txt"}; + for (String resourceName : mdnsToVerify) { + boolean verified = verify(resourceName, debug); + //System.out.println("Verification of " + resourceName + " returned status=" + verified); + assertTrue(verified, "Resource " + resourceName + " signature did not validate"); + } + + // then we validate some real negative MDN's from various systems + String[] mdnsNegative = {"unit4-mdn-negative.txt"}; + for (String resourceName : mdnsNegative) { + boolean verified = verify(resourceName, debug); + assertTrue(verified, "Resource " + resourceName + " signature did not validated"); + } + + // then we validate some corrupt MDN's we have manually messed up + String[] mdnsToFail = {"unit4-mdn-error.txt"}; + for (String resourceName : mdnsToFail) { + boolean failed = verify(resourceName, debug); + assertFalse(failed, "Resource " + resourceName + " signature should not have validated"); + } + + if (debug) { + // dump list of all providers registered + for (Provider p : Security.getProviders()) { + System.out.println("Provider : " + p.getName()); + } + } + + } + + /** + * verify the signature (assuming the cert is contained in the message) + */ + private boolean verify(String resourceName, boolean debug) { + + System.out.println("Verifying resource " + resourceName + " (debug=" + debug + ")"); + String resourcePath = "/real-mdn-examples/" + resourceName; + + try { + // shortcuts lots of steps in the above test (parseLegalMimeMessageWithHeaders) + MimeMultipart multipartSigned = (MimeMultipart) MimeMessageHelper.parse( + getClass().getResourceAsStream(resourcePath)).getContent(); + assertNotNull(multipartSigned); + + // verify signature + + + SMIMESigned signedMessage = new SMIMESigned(multipartSigned); + Store certs = signedMessage.getCertificates(); + + SignerInformationStore signers = signedMessage.getSignerInfos(); + + for (Object signerInformation : signers.getSigners()) { + SignerInformation signer = (SignerInformation) signerInformation; + Collection certCollection = certs.getMatches(signer.getSID()); + + Iterator certIterator = certCollection.iterator(); + + X509Certificate cert = new JcaX509CertificateConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getCertificate((X509CertificateHolder) certIterator.next()); + + if (debug) System.out.println("Signing certificate : " + cert); + + SignerInformationVerifier signerInformationVerifier = new JcaSimpleSignerInfoVerifierBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build(cert); + if (signer.verify(signerInformationVerifier)) + return true; + + } + + } catch (Exception ex) { + System.out.println("Verification failed with exception " + ex.getMessage()); + } + + return false; + + } + + /** + * Verifies that if you don't supply the headers, a plain/text message will be created even though it might appear as being a multipart. + * + * @throws Exception + */ + @Test + public void parseMimeMessageStreamWithoutContentTypeEmbedded() throws Exception { + InputStream resourceAsStream = getClass().getResourceAsStream(OPENAS2_MDN_NO_HEADERS_TXT); + assertNotNull(resourceAsStream, OPENAS2_MDN_NO_HEADERS_TXT + " not found in classpath"); + + MimeMessage mimeMessage = MimeMessageHelper.parse(resourceAsStream); + Object content = mimeMessage.getContent(); + assertNotNull(content); + assertTrue(content instanceof String); + assertEquals(mimeMessage.getContentType(), "text/plain"); + } + + + @Test + public void parseMimeMessageExperiment() throws IOException, MessagingException { + + InputStream inputStream = getClass().getClassLoader().getResourceAsStream("mime-message.txt"); + assertNotNull(inputStream, "mime-message.txt not found in class path"); + + + MimeMessage mimeMessage = MimeMessageHelper.parse(inputStream); + + Object content = mimeMessage.getContent(); + assertTrue(content instanceof MimeMultipart); + + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + mimeMessage.writeTo(os); + + String s = new String(os.toByteArray()); + assertFalse(s.contains("--null")); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/SMimeBCTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/SMimeBCTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4ae13727cd466e87243a864124ff017a553fd6e5 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/SMimeBCTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class SMimeBCTest { + + @Test + public void simpleConstructor() { + new SMimeBC(); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/SMimeMessageFactoryTest.java b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/SMimeMessageFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1a6a57b5fee51548e43881741979408797a83c7d --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/java/network/oxalis/as2/util/SMimeMessageFactoryTest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.as2.util; + +import com.google.inject.Inject; +import network.oxalis.commons.guice.GuiceModuleLoader; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.activation.MimeType; +import javax.mail.BodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.InputStream; +import java.io.StringWriter; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +/** + * @author steinar + * Date: 08.10.13 + * Time: 11:34 + */ +@Guice(modules = GuiceModuleLoader.class) +public class SMimeMessageFactoryTest { + + private network.oxalis.as2.util.SMimeMessageFactory SMimeMessageFactory; + + private InputStream resourceAsStream; + + @Inject + private PrivateKey privateKey; + + @Inject + private X509Certificate certificate; + + @BeforeMethod + public void createMimeMessageFactory() { + SMimeMessageFactory = new SMimeMessageFactory(privateKey, certificate); + + // Fetches input stream for data + resourceAsStream = SMimeMessageFactory.class.getClassLoader().getResourceAsStream("example.xml"); + assertNotNull(resourceAsStream); + + } + + @Test + public void inspectSignedMessage() throws Exception { + + + // Creates the signed message + MimeMessage signedMimeMessage = SMimeMessageFactory + .createSignedMimeMessage(resourceAsStream, new MimeType("application", "xml"), SMimeDigestMethod.sha1); + assertNotNull(signedMimeMessage); + + assertTrue(signedMimeMessage.getContent() instanceof MimeMultipart, "Not a MultiPart"); + + // Converts the contents into a Mime Multi Part, which should consist of two body parts + MimeMultipart mimeMultipart = (MimeMultipart) signedMimeMessage.getContent(); + + // First part contains the payload + BodyPart bodyPart = mimeMultipart.getBodyPart(0); + // For which the contents is an input stream giving access to the actual data + Object content = bodyPart.getContent(); + assertTrue(content instanceof InputStream); + + StringWriter sw = new StringWriter(); + int c; + InputStream inputStream = bodyPart.getInputStream(); + while ((c = inputStream.read()) >= 0) { + sw.write(c); + } + + assertTrue(sw.toString().contains(" map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + map.put("NaMe", "value"); + String value = map.get("name"); + assertEquals(value, "value"); + } +} diff --git a/oxalis-extension/oxalis-as2/src/test/resources/as2-message/oxalis-sha1.txt b/oxalis-extension/oxalis-as2/src/test/resources/as2-message/oxalis-sha1.txt new file mode 100644 index 0000000000000000000000000000000000000000..b53c590255aa234b8113be2db224cb41fb108732 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/as2-message/oxalis-sha1.txt @@ -0,0 +1,196 @@ +Message-ID: <2027701910.2.1543119023808.JavaMail.erlend@lappy> +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; + boundary="----=_Part_1_2021835850.1543119023806" + +------=_Part_1_2021835850.1543119023806 +Content-Type: application/xml +Content-Transfer-Encoding: binary + + + + + 1.0 + + 0007:5567125082 + + + 0007:4455454480 + + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + 2.0 + 1070e7f0-3bae-11e3-aa6e-0800200c9a66 + Invoice + 2013-02-19T05:10:10 + + + + DOCUMENTID + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + + PROCESSID + urn:www.cenbii.eu:profile:bii04:ver1.0 + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 1 + 2012-06-08 + 380 + 2012-06-08 + SEK + SOPE + + + + 5567125082 + + + Ecru Consulting + + + Gamla Brogatan + 29 + Stockholm + 11120 + + SE + + + + SE556712508201 + + VAT + + + + 5567125082 + + + Martin + Forsberg + + + + + + + 4455454480 + + + EKONOMISTYRNINGSVERKET (NATIONAL FINANCIAL MANAGEMENT AUTHORITY) + + + 45316 + EFFEKTIV ADMINISTRATION + STOCKHOLM + 104 30 + + SE + + + + 2021005026 + + + 08 - 123456 + 08-123457 + infomail@esv.se + + + SOREN + PEDERSEN + + + + + 31 + 2012-06-23 + + 5955559 + + + BGABSESS + + + + + + 0.25 + + 1 + 0.25 + + S + 25 + + VAT + + + + + + 1 + 1 + 1.25 + 1.25 + + + 1 + 1 + 1 + + 1 + + + TEST AV PEPPOL-FAKTURA + + + 1 + 1 + + + + + +------=_Part_1_2021835850.1543119023806 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIAwggLrMIIB +06ADAgECAgRYiPBmMA0GCSqGSIb3DQEBCwUAMC0xCzAJBgNVBAYTAk5PMR4wHAYDVQQDDBVEdW1t +eSBBQ0NFU1MgUE9JTlQgQ0EwHhcNMTcwMTI1MTgzNzM0WhcNMjIwMTI1MTgzNzM0WjBCMQswCQYD +VQQGEwJOTzEaMBgGA1UECgwRT3hhbGlzIFRlc3RpbmcgMDExFzAVBgNVBAMMDkFQUF8wMDAwMDAw +MDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsaZPCo0IZSKJQ5EiimL60HN5XjCa +DBCge/qfM4wI5xLAag4UJi22pPKBYcq+hPd8b9gn98HFgrMkFfcZUJvjepMDt5vKbvILSUYr/rri +CuOg2GUnckdfsAkiLhEBXjn3u5IcJhJ5FQu0brKWtUz/9sG2PFYaHD17bKE1RONBlkOgROoPDrPc +TV5PeffP15rYmTh6/0vc2EHz6tFo3fj15FbkMi4xH88uMevD1dXjCuwrZQt1W83Qpa5Q9QRL5VrT +CAz3JFWLDAsnf56LYlPAJhTQVPve+2z6sV5NDgCr9fdpUQaxt7FLt3L5yJsVFjD9m9Y8nCsbnVIP +/HCZD3j5aQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCqoMl2ZH8pKBRZfVV46EEYPYPjRFWePRtg +ABC2RA5rP2J5lDvoWd+P04ty+/wRcWFU9tMMv68i9nirTWRE14x5a215sUNwIhRlS7TA+32zSqdR +/vrKopAnDNgdeSnpjSsEav+vAeSkukFPn5W8L2fJE3UN5VnfepVNwz2fYgJtuAmdKcQnC6YAJj/Z +/V9cmxaR0YVi0RyzllBnjg3pUkCyUohlIs6mLbjyV0qNdHeE7JmHRNJeZn9Cgp+oC/WTyCYBbeCn +KGqq85U6tRs2Qwxv7+FDJY2fEtArmhXTtQm3BhPGMWCmt5UkiZGl5fk9GNESidML10lQ2xf3njvY +xIAfAAAxggHnMIIB4wIBATA1MC0xCzAJBgNVBAYTAk5PMR4wHAYDVQQDDBVEdW1teSBBQ0NFU1Mg +UE9JTlQgQ0ECBFiI8GYwCQYFKw4DAhoFAKCBiDAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwG +CSqGSIb3DQEJBTEPFw0xODExMjUwNDEwMjNaMCMGCSqGSIb3DQEJBDEWBBR7FXqoY/ZKfT1oQe+Q +9m6S1vv06zApBgkqhkiG9w0BCTQxHDAaMAkGBSsOAwIaBQChDQYJKoZIhvcNAQEBBQAwDQYJKoZI +hvcNAQEBBQAEggEAJtR/Tj2cRgErExRAur9vY8zgkTTmrvMi1ZoVX8/JgtnGq94JlnXiDNCAlgNg +9Auwya8Q8efB6a5/r/vvyHGbcvKNFrDGYbU8gT27jnwvEWXOnzzI+n3c4B8JviM0oi+jWWYLgtOH +ONYsrbYwXC2++b39KBb9JY64e20QdyOz/SYK6zXhExoo3V4Lfuy+8rk8kVW1eshhjn5Dm4FYuSb0 +Ej/I9uqyjzt6s94zUe4pfnxMCJQopGNY8SbKYwBJMNmftOS1L1y7tZykX33drFPKZCWvFCzpOo4f +ReiU14kegGm/I+5KODWpj5xMUY/dwI76WYK44HfjGAvCpD81dYKLZQAAAAAAAA== +------=_Part_1_2021835850.1543119023806-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/as2-message/oxalis-sha512.txt b/oxalis-extension/oxalis-as2/src/test/resources/as2-message/oxalis-sha512.txt new file mode 100644 index 0000000000000000000000000000000000000000..7a485208d860818aa257b87cf2cac90ca48b7a30 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/as2-message/oxalis-sha512.txt @@ -0,0 +1,197 @@ +Message-ID: <726416425.9.1543118743284.JavaMail.erlend@lappy> +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-512; + boundary="----=_Part_8_670951536.1543118743283" + +------=_Part_8_670951536.1543118743283 +Content-Type: application/xml +Content-Transfer-Encoding: binary + + + + + 1.0 + + 0007:5567125082 + + + 0007:4455454480 + + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + 2.0 + 1070e7f0-3bae-11e3-aa6e-0800200c9a66 + Invoice + 2013-02-19T05:10:10 + + + + DOCUMENTID + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + + PROCESSID + urn:www.cenbii.eu:profile:bii04:ver1.0 + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 1 + 2012-06-08 + 380 + 2012-06-08 + SEK + SOPE + + + + 5567125082 + + + Ecru Consulting + + + Gamla Brogatan + 29 + Stockholm + 11120 + + SE + + + + SE556712508201 + + VAT + + + + 5567125082 + + + Martin + Forsberg + + + + + + + 4455454480 + + + EKONOMISTYRNINGSVERKET (NATIONAL FINANCIAL MANAGEMENT AUTHORITY) + + + 45316 + EFFEKTIV ADMINISTRATION + STOCKHOLM + 104 30 + + SE + + + + 2021005026 + + + 08 - 123456 + 08-123457 + infomail@esv.se + + + SOREN + PEDERSEN + + + + + 31 + 2012-06-23 + + 5955559 + + + BGABSESS + + + + + + 0.25 + + 1 + 0.25 + + S + 25 + + VAT + + + + + + 1 + 1 + 1.25 + 1.25 + + + 1 + 1 + 1 + + 1 + + + TEST AV PEPPOL-FAKTURA + + + 1 + 1 + + + + + +------=_Part_8_670951536.1543118743283 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgMFADCABgkqhkiG9w0BBwEAAKCAMIIC +6zCCAdOgAwIBAgIEWIjwZjANBgkqhkiG9w0BAQsFADAtMQswCQYDVQQGEwJOTzEeMBwGA1UEAwwV +RHVtbXkgQUNDRVNTIFBPSU5UIENBMB4XDTE3MDEyNTE4MzczNFoXDTIyMDEyNTE4MzczNFowQjEL +MAkGA1UEBhMCTk8xGjAYBgNVBAoMEU94YWxpcyBUZXN0aW5nIDAxMRcwFQYDVQQDDA5BUFBfMDAw +MDAwMDAwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGmTwqNCGUiiUORIopi+tBz +eV4wmgwQoHv6nzOMCOcSwGoOFCYttqTygWHKvoT3fG/YJ/fBxYKzJBX3GVCb43qTA7ebym7yC0lG +K/664grjoNhlJ3JHX7AJIi4RAV4597uSHCYSeRULtG6ylrVM//bBtjxWGhw9e2yhNUTjQZZDoETq +Dw6z3E1eT3n3z9ea2Jk4ev9L3NhB8+rRaN349eRW5DIuMR/PLjHrw9XV4wrsK2ULdVvN0KWuUPUE +S+Va0wgM9yRViwwLJ3+ei2JTwCYU0FT73vts+rFeTQ4Aq/X3aVEGsbexS7dy+cibFRYw/ZvWPJwr +G51SD/xwmQ94+WkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAqqDJdmR/KSgUWX1VeOhBGD2D40RV +nj0bYAAQtkQOaz9ieZQ76Fnfj9OLcvv8EXFhVPbTDL+vIvZ4q01kRNeMeWttebFDcCIUZUu0wPt9 +s0qnUf76yqKQJwzYHXkp6Y0rBGr/rwHkpLpBT5+VvC9nyRN1DeVZ33qVTcM9n2ICbbgJnSnEJwum +ACY/2f1fXJsWkdGFYtEcs5ZQZ44N6VJAslKIZSLOpi248ldKjXR3hOyZh0TSXmZ/QoKfqAv1k8gm +AW3gpyhqqvOVOrUbNkMMb+/hQyWNnxLQK5oV07UJtwYTxjFgpreVJImRpeX5PRjREonTC9dJUNsX +95472MSAHwAAMYICGzCCAhcCAQEwNTAtMQswCQYDVQQGEwJOTzEeMBwGA1UEAwwVRHVtbXkgQUND +RVNTIFBPSU5UIENBAgRYiPBmMA0GCWCGSAFlAwQCAwUAoIG4MBgGCSqGSIb3DQEJAzELBgkqhkiG +9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE4MTEyNTA0MDU0M1owLQYJKoZIhvcNAQk0MSAwHjANBglg +hkgBZQMEAgMFAKENBgkqhkiG9w0BAQ0FADBPBgkqhkiG9w0BCQQxQgRA0MJCePem0dJ+vKvFjRIX +mnIK2vFWgP6XBV1PhzF0DnuYF9Bgj2dic/W8A6Vt1Bz2IPhsZvj0No3Bto2WCBEItzANBgkqhkiG +9w0BAQ0FAASCAQBMZIjNNTG1fYLs7NZSUmq6n4VromxcJowdHzgEDax8iw/PboBs5NAzoez33Baa +5HZ/C0cDJTBxdLo1EIbZ9U5vum76WkEp+isnpUZzRb/VFLPUw4b6lQwDpFkP72Ea8KnK3O++Zvrf +FAdaF9k2tsAFm/XH1OHmjdpcYL2MoRnYuepMDWGgHe8S+6Joa1q3dw6NWjdmxC/T5ElcxYkJfIVh +DMaFwDWrbgYM7FSFX+/3UwPS9pDdlQ7j2RFLhidykO2I44ixnj5I8nK6tRNYo4Bcxqf/XyZC9OeU +xVc6X8jjBwRmlvc/f+wjaDa5FtfDCkGf1XsJ3LWXNIpuDUdDnpnoAAAAAAAA +------=_Part_8_670951536.1543118743283-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/as2-message/some.txt b/oxalis-extension/oxalis-as2/src/test/resources/as2-message/some.txt new file mode 100644 index 0000000000000000000000000000000000000000..5bd7397e4950155e49c4ea6dc74eea3e83569d4b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/as2-message/some.txt @@ -0,0 +1,58 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha1"; boundary="----3932653C3BC75F1597D9A147B0D10AC0" + +This is an S/MIME signed message + +------3932653C3BC75F1597D9A147B0D10AC0 +Content-Type: application/EDI-X12 +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename=SI-UBL-INV-1.2-ok-minimal_with_business_header.xml + +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPFN0YW5kYXJkQnVzaW5lc3NEb2N1bWVudCB4bWxucz0iaHR0cDovL3d3dy51bmVjZS5vcmcvY2VmYWN0L25hbWVzcGFjZXMvU3RhbmRhcmRCdXNpbmVzc0RvY3VtZW50SGVhZGVyIj4KICA8U3RhbmRhcmRCdXNpbmVzc0RvY3VtZW50SGVhZGVyPgogICAgICA8SGVhZGVyVmVyc2lvbj4xLjA8L0hlYWRlclZlcnNpb24+CiAgICAgIDxTZW5kZXI+CiAgICAgICAgICA8SWRlbnRpZmllciBBdXRob3JpdHk9ImlzbzY1MjMtYWN0b3JpZC11cGlzIj4wMTA2OnR0dGVzdHBheXQ8L0lkZW50aWZpZXI+CiAgICAgIDwvU2VuZGVyPgogICAgICA8UmVjZWl2ZXI+CiAgICAgICAgICA8SWRlbnRpZmllciBBdXRob3JpdHk9ImlzbzY1MjMtYWN0b3JpZC11cGlzIj4wMTA2OnR0dGVzdHBheXQ8L0lkZW50aWZpZXI+CiAgICAgIDwvUmVjZWl2ZXI+CiAgICAgIDxEb2N1bWVudElkZW50aWZpY2F0aW9uPgogICAgICAgICAgPFN0YW5kYXJkPnVybjpvYXNpczpuYW1lczpzcGVjaWZpY2F0aW9uOnVibDpzY2hlbWE6eHNkOkludm9pY2UtMjwvU3RhbmRhcmQ+CiAgICAgICAgICA8VHlwZVZlcnNpb24+Mi4wPC9UeXBlVmVyc2lvbj4KICAgICAgICAgIDxJbnN0YW5jZUlkZW50aWZpZXI+MTA3MGU3ZjAtM2JhZS0xMWUzLWFhNmUtMDgwMDIwMGM5YTY2PC9JbnN0YW5jZUlkZW50aWZpZXI+CiAgICAgICAgICA8VHlwZT5JbnZvaWNlPC9UeXBlPgogICAgICAgICAgPENyZWF0aW9uRGF0ZUFuZFRpbWU+MjAxMy0wMi0xOVQwNToxMDoxMDwvQ3JlYXRpb25EYXRlQW5kVGltZT4KICAgICAgPC9Eb2N1bWVudElkZW50aWZpY2F0aW9uPgogICAgICA8QnVzaW5lc3NTY29wZT4KICAgICAgICAgIDxTY29wZT4KICAgICAgICAgICAgICA8VHlwZT5ET0NVTUVOVElEPC9UeXBlPgogICAgICAgICAgICAgIDxJbnN0YW5jZUlkZW50aWZpZXI+dXJuOm9hc2lzOm5hbWVzOnNwZWNpZmljYXRpb246dWJsOnNjaGVtYTp4c2Q6SW52b2ljZS0yOjpJbnZvaWNlIyN1cm46d3d3LmNlbmJpaS5ldTp0cmFuc2FjdGlvbjpiaWl0cm5zMDEwOnZlcjIuMDpleHRlbmRlZDp1cm46d3d3LnBlcHBvbC5ldTpiaXM6cGVwcG9sNGE6dmVyMi4wOmV4dGVuZGVkOnVybjp3d3cuc2ltcGxlcmludm9pY2luZy5vcmc6c2k6c2ktdWJsOnZlcjEuMS54OjoyLjE8L0luc3RhbmNlSWRlbnRpZmllcj4KICAgICAgICAgIDwvU2NvcGU+CiAgICAgICAgICA8U2NvcGU+CiAgICAgICAgICAgICAgPFR5cGU+UFJPQ0VTU0lEPC9UeXBlPgogICAgICAgICAgICAgIDxJbnN0YW5jZUlkZW50aWZpZXI+dXJuOnd3dy5jZW5iaWkuZXU6cHJvZmlsZTpiaWkwNDp2ZXIxLjA8L0luc3RhbmNlSWRlbnRpZmllcj4KICAgICAgICAgIDwvU2NvcGU+CiAgICAgIDwvQnVzaW5lc3NTY29wZT4KICA8L1N0YW5kYXJkQnVzaW5lc3NEb2N1bWVudEhlYWRlcj4KICA8SW52b2ljZSB4bWxucz0idXJuOm9hc2lzOm5hbWVzOnNwZWNpZmljYXRpb246dWJsOnNjaGVtYTp4c2Q6SW52b2ljZS0yIiB4bWxuczpjYWM9InVybjpvYXNpczpuYW1lczpzcGVjaWZpY2F0aW9uOnVibDpzY2hlbWE6eHNkOkNvbW1vbkFnZ3JlZ2F0ZUNvbXBvbmVudHMtMiIgeG1sbnM6Y2JjPSJ1cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2NoZW1hOnhzZDpDb21tb25CYXNpY0NvbXBvbmVudHMtMiIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnNjaGVtYUxvY2F0aW9uPSJ1cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2NoZW1hOnhzZDpJbnZvaWNlLTIKICAgIGh0dHA6Ly9kb2NzLm9hc2lzLW9wZW4ub3JnL3VibC9vcy1VQkwtMi4xL3hzZC9tYWluZG9jL1VCTC1JbnZvaWNlLTIuMS54c2QiPgogICAgPGNiYzpVQkxWZXJzaW9uSUQ+Mi4xPC9jYmM6VUJMVmVyc2lvbklEPgogICAgPGNiYzpDdXN0b21pemF0aW9uSUQ+dXJuOnd3dy5jZW5iaWkuZXU6dHJhbnNhY3Rpb246YmlpdHJuczAxMDp2ZXIyLjA6ZXh0ZW5kZWQ6dXJuOnd3dy5wZXBwb2wuZXU6YmlzOnBlcHBvbDRhOnZlcjIuMDpleHRlbmRlZDp1cm46d3d3LnNpbXBsZXJpbnZvaWNpbmcub3JnOnNpOnNpLXVibDp2ZXIxLjI8L2NiYzpDdXN0b21pemF0aW9uSUQ+CiAgICA8Y2JjOlByb2ZpbGVJRD51cm46d3d3LmNlbmJpaS5ldTpwcm9maWxlOmJpaTA0OnZlcjEuMDwvY2JjOlByb2ZpbGVJRD4KICAgIDxjYmM6SUQ+STIwMTMuMDMuNDM2MTwvY2JjOklEPgogICAgPGNiYzpJc3N1ZURhdGU+MjAxMy0wOC0wNjwvY2JjOklzc3VlRGF0ZT4KICAgIDxjYmM6SW52b2ljZVR5cGVDb2RlIGxpc3RJRD0iVU5DTDEwMDEiIGxpc3RBZ2VuY3lJRD0iNiI+MzgwPC9jYmM6SW52b2ljZVR5cGVDb2RlPgogICAgPGNiYzpEb2N1bWVudEN1cnJlbmN5Q29kZSBsaXN0SUQ9IklTTzQyMTciIGxpc3RBZ2VuY3lJRD0iNiI+RVVSPC9jYmM6RG9jdW1lbnRDdXJyZW5jeUNvZGU+CiAgICA8Y2FjOkFjY291bnRpbmdTdXBwbGllclBhcnR5PgogICAgICA8Y2FjOlBhcnR5PgogICAgICAgIDxjYWM6UGFydHlOYW1lPgogICAgICAgICAgPGNiYzpOYW1lPlNlbGxlciBCLlYuPC9jYmM6TmFtZT4KICAgICAgICA8L2NhYzpQYXJ0eU5hbWU+CiAgICAgICAgPGNhYzpQb3N0YWxBZGRyZXNzPgogICAgICAgICAgPGNiYzpTdHJlZXROYW1lPk1haW4gc3RyZWV0PC9jYmM6U3RyZWV0TmFtZT4KICAgICAgICAgIDxjYmM6Q2l0eU5hbWU+QmlnIGNpdHk8L2NiYzpDaXR5TmFtZT4KICAgICAgICAgIDxjYmM6UG9zdGFsWm9uZT41NDMyMTwvY2JjOlBvc3RhbFpvbmU+CiAgICAgICAgICA8Y2FjOkNvdW50cnk+CiAgICAgICAgICAgIDxjYmM6SWRlbnRpZmljYXRpb25Db2RlIGxpc3RBZ2VuY3lJRD0iNiIgbGlzdElEPSJJU08zMTY2LTE6QWxwaGEyIj5OTDwvY2JjOklkZW50aWZpY2F0aW9uQ29kZT4KICAgICAgICAgIDwvY2FjOkNvdW50cnk+CiAgICAgICAgPC9jYWM6UG9zdGFsQWRkcmVzcz4KICAgICAgICA8Y2FjOlBhcnR5TGVnYWxFbnRpdHk+CiAgICAgICAgICA8Y2JjOkNvbXBhbnlJRCBzY2hlbWVJRD0iTkw6VkFUIj4zMzMzMzMzMzMzPC9jYmM6Q29tcGFueUlEPgogICAgICAgIDwvY2FjOlBhcnR5TGVnYWxFbnRpdHk+CiAgICAgIDwvY2FjOlBhcnR5PgogICAgPC9jYWM6QWNjb3VudGluZ1N1cHBsaWVyUGFydHk+CiAgICA8Y2FjOkFjY291bnRpbmdDdXN0b21lclBhcnR5PgogICAgICA8Y2FjOlBhcnR5PgogICAgICAgIDxjYWM6UGFydHlOYW1lPgogICAgICAgICAgPGNiYzpOYW1lPkJ1eWVyY29tcGFueSBWT0Y8L2NiYzpOYW1lPgogICAgICAgIDwvY2FjOlBhcnR5TmFtZT4KICAgICAgICA8Y2FjOlBvc3RhbEFkZHJlc3M+CiAgICAgICAgICA8Y2JjOlN0cmVldE5hbWU+TWFpbiBzdHJlZXQ8L2NiYzpTdHJlZXROYW1lPgogICAgICAgICAgPGNiYzpDaXR5TmFtZT5CaWcgY2l0eTwvY2JjOkNpdHlOYW1lPgogICAgICAgICAgPGNiYzpQb3N0YWxab25lPjU0MzIxPC9jYmM6UG9zdGFsWm9uZT4KICAgICAgICAgIDxjYWM6Q291bnRyeT4KICAgICAgICAgICAgPGNiYzpJZGVudGlmaWNhdGlvbkNvZGUgbGlzdEFnZW5jeUlEPSI2IiBsaXN0SUQ9IklTTzMxNjYtMTpBbHBoYTIiPk5MPC9jYmM6SWRlbnRpZmljYXRpb25Db2RlPgogICAgICAgICAgPC9jYWM6Q291bnRyeT4KICAgICAgICA8L2NhYzpQb3N0YWxBZGRyZXNzPgogICAgICAgIDxjYWM6UGFydHlMZWdhbEVudGl0eT4KICAgICAgICAgIDxjYmM6Q29tcGFueUlEIHNjaGVtZUlEPSJOTDpWQVQiPjMzMzMzMzMzMzM8L2NiYzpDb21wYW55SUQ+CiAgICAgICAgPC9jYWM6UGFydHlMZWdhbEVudGl0eT4KICAgICAgPC9jYWM6UGFydHk+CiAgICA8L2NhYzpBY2NvdW50aW5nQ3VzdG9tZXJQYXJ0eT4KICAgIDxjYWM6TGVnYWxNb25ldGFyeVRvdGFsPgogICAgICA8Y2JjOkxpbmVFeHRlbnNpb25BbW91bnQgY3VycmVuY3lJRD0iRVVSIj4yMDA8L2NiYzpMaW5lRXh0ZW5zaW9uQW1vdW50PgogICAgICA8Y2JjOlRheEV4Y2x1c2l2ZUFtb3VudCBjdXJyZW5jeUlEPSJFVVIiPjIwMDwvY2JjOlRheEV4Y2x1c2l2ZUFtb3VudD4KICAgICAgPGNiYzpUYXhJbmNsdXNpdmVBbW91bnQgY3VycmVuY3lJRD0iRVVSIj4yMDA8L2NiYzpUYXhJbmNsdXNpdmVBbW91bnQ+CiAgICAgIDxjYmM6UGF5YWJsZUFtb3VudCBjdXJyZW5jeUlEPSJFVVIiPjIwMDwvY2JjOlBheWFibGVBbW91bnQ+CiAgICA8L2NhYzpMZWdhbE1vbmV0YXJ5VG90YWw+CiAgICA8Y2FjOkludm9pY2VMaW5lPgogICAgICA8Y2JjOklEPjE8L2NiYzpJRD4KICAgICAgPGNiYzpJbnZvaWNlZFF1YW50aXR5IHVuaXRDb2RlPSI1OSIgdW5pdENvZGVMaXN0SUQ9IlVORUNFUmVjMjAiPjE8L2NiYzpJbnZvaWNlZFF1YW50aXR5PgogICAgICA8Y2JjOkxpbmVFeHRlbnNpb25BbW91bnQgY3VycmVuY3lJRD0iRVVSIj4yMDA8L2NiYzpMaW5lRXh0ZW5zaW9uQW1vdW50PgogICAgICA8Y2FjOkl0ZW0+CiAgICAgICAgPGNiYzpOYW1lPkJpdGNvaW4gTWFzdGVyY2xhc3M8L2NiYzpOYW1lPgogICAgICA8L2NhYzpJdGVtPgogICAgICA8Y2FjOlByaWNlPgogICAgICAgIDxjYmM6UHJpY2VBbW91bnQgY3VycmVuY3lJRD0iRVVSIj4yMDA8L2NiYzpQcmljZUFtb3VudD4KICAgICAgPC9jYWM6UHJpY2U+CiAgICA8L2NhYzpJbnZvaWNlTGluZT4KICA8L0ludm9pY2U+CjwvU3RhbmRhcmRCdXNpbmVzc0RvY3VtZW50Pgo= + +------3932653C3BC75F1597D9A147B0D10AC0 +Content-Type: application/pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIHMgYJKoZIhvcNAQcCoIIHIzCCBx8CAQExCTAHBgUrDgMCGjALBgkqhkiG9w0B +BwGgggRqMIIEZjCCA06gAwIBAgIQQNnrBxVw4uQUu6QaUH9huTANBgkqhkiG9w0B +AQsFADB9MQswCQYDVQQGEwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRF +TEVDT00gQUdFTkNZMR8wHQYDVQQLExZGT1IgVEVTVCBQVVJQT1NFUyBPTkxZMSQw +IgYDVQQDExtQRVBQT0wgQUNDRVNTIFBPSU5UIFRFU1QgQ0EwHhcNMTcwMjE2MDAw +MDAwWhcNMTkwMjE2MjM1OTU5WjA4MQswCQYDVQQGEwJOTDEQMA4GA1UECgwHUGF5 +dCBCVjEXMBUGA1UEAwwOQVBQXzEwMDAwMDAzMDIwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCVbX9y/LE2SZMgSRhXI0m0oyqyOEZLGnzdVz//6gADbx5u +6wJFDq5XLGXXP1wEtghC29u7Q9eHB9xHa4P7G+PlJG8wUT1LscJ3/4pUEyBXelgn +9b0oMIcdE5rVnTfoHJK8AcXbQi6wxtjAAeeempBHRgpG3fObDANdl71/TrGaAnz+ +yOFFMoL3uFAEfbGzw/+AZ22PdiKqb+Xl4eDw6j8rZEyg4n/bbEs0B1Xj0OhrevPK +rRqjKGVc1FCi1IQgc707FZSPi1R81TWlFf4cYHZItmb7JDsp41k1/XnWxS9MctiH ++du2/RT27KI4MQAf/rQ9k5XAtKSUNwCVF5Z2VmJbAgMBAAGjggElMIIBITAJBgNV +HRMEAjAAMAsGA1UdDwQEAwIDuDB2BgNVHR8EbzBtMGugaaBnhmVodHRwOi8vcGls +b3RvbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNl +blBpbG90T3BlblBFUFBPTEFDQ0VTU1BPSU5UQ0EvTGF0ZXN0Q1JMLmNybDAfBgNV +HSMEGDAWgBT3losZTK7iViEAvob9ekesncoFdTAdBgNVHQ4EFgQU5AVdw1gHi9gE +KiPYzxBv5CmbFzAwOgYIKwYBBQUHAQEELjAsMCoGCCsGAQUFBzABhh5odHRwOi8v +cGlsb3Qtb2NzcC52ZXJpc2lnbi5jb20wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJ +KoZIhvcNAQELBQADggEBADKetqlYySQntgjO3jb90CDdQ3TiAxGHiNU8gJ1sQLFY +JIPY61n/JEyZJnlZxw1618HuA/TbgBMMAT6+atmkLSo81aCb4Ycb/6jIBgS5Xkyo +oLfBZBo6m5+l8vHcC0gf1xJBfPMA0I3kN4xiPB9/g38ncjxqkW49NL4CwnhtHc0i +Ais+W5gTERZZtoIRDSToz9dzoktrXxBHplrcPFp5VMgnf0+DCGTVniptPU7L5DqO +s3Fd9qzYyi7ZpqgChJfd0jT9gDOBT3+iGmzxGuOMnxhFCNdnIDDYbX4xLdApGPTx +dwlBBvU/Jb8vHWMGvXudKuWucNAt/sybUKl63TQw+DMxggKSMIICjgIBATCBkTB9 +MQswCQYDVQQGEwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00g +QUdFTkNZMR8wHQYDVQQLExZGT1IgVEVTVCBQVVJQT1NFUyBPTkxZMSQwIgYDVQQD +ExtQRVBQT0wgQUNDRVNTIFBPSU5UIFRFU1QgQ0ECEEDZ6wcVcOLkFLukGlB/Ybkw +BwYFKw4DAhqggdgwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0B +CQUxDxcNMTgxMDMwMTQyNjQyWjAjBgkqhkiG9w0BCQQxFgQUWbnRYDaKGsSScYqR +GPv+OmMRUJoweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJYIZIAWUD +BAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgICAIAwDQYI +KoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZIhvcNAQEB +BQAEggEAD0gncL6ZuoujJYeee6ZzFa8HNvgv8UQWwN7R1dJ1UVh0/Zf80iqqHwN5 +AoJ6dxnOAeu8c9XNq2VbKZjOmia3/He9eoR7V9ifoKAj1TLwBchra1o2mpoPy8xA +TZqqPwnxJYJjWm7IW+a3txZ8mlDigezvanrLXuqIdi8718rE7RQ/1sXj/aG5TJ0P +lBQU8zywMojC6g9SlsXJn2QaB6Q+VKhfMBXFQ0GpDsMZUnKt3DStk2i9aZ4T99rl +KSfohpqpQAGEne86KXZk2DnSAke1jB5KVmm9mUQZLq0WL0ZLaqg51G/h99zeXGhn +ZF1+FMRpzofOmejvw94/kKYXAj9/8w== + +------3932653C3BC75F1597D9A147B0D10AC0-- \ No newline at end of file diff --git a/oxalis-extension/oxalis-as2/src/test/resources/as2-peppol-bis-invoice-sbdh.xml b/oxalis-extension/oxalis-as2/src/test/resources/as2-peppol-bis-invoice-sbdh.xml new file mode 100644 index 0000000000000000000000000000000000000000..96ebf27d9af40ee9d15a908ffe6434b168292f6b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/as2-peppol-bis-invoice-sbdh.xml @@ -0,0 +1,156 @@ + + + + 1.0 + + 0007:5567125082 + + + 0007:4455454480 + + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + 2.0 + 1070e7f0-3bae-11e3-aa6e-0800200c9a66 + Invoice + 2013-02-19T05:10:10 + + + + DOCUMENTID + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + + PROCESSID + urn:www.cenbii.eu:profile:bii04:ver1.0 + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 1 + 2012-06-08 + 380 + 2012-06-08 + SEK + SOPE + + + + 5567125082 + + + Ecru Consulting + + + Gamla Brogatan + 29 + Stockholm + 11120 + + SE + + + + SE556712508201 + + VAT + + + + 5567125082 + + + Martin + Forsberg + + + + + + + 4455454480 + + + EKONOMISTYRNINGSVERKET (NATIONAL FINANCIAL MANAGEMENT AUTHORITY) + + + 45316 + EFFEKTIV ADMINISTRATION + STOCKHOLM + 104 30 + + SE + + + + 2021005026 + + + 08 - 123456 + 08-123457 + infomail@esv.se + + + SOREN + PEDERSEN + + + + + 31 + 2012-06-23 + + 5955559 + + + BGABSESS + + + + + + 0.25 + + 1 + 0.25 + + S + 25 + + VAT + + + + + + 1 + 1 + 1.25 + 1.25 + + + 1 + 1 + 1 + + 1 + + + TEST AV PEPPOL-FAKTURA + + + 1 + 1 + + + + diff --git a/oxalis-extension/oxalis-as2/src/test/resources/example.xml b/oxalis-extension/oxalis-as2/src/test/resources/example.xml new file mode 100644 index 0000000000000000000000000000000000000000..896e8c0997766fe369f260fe7324dbfb75294ac2 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/example.xml @@ -0,0 +1,12 @@ + + + + + org.apache.commons + commons-parent + 12 + + diff --git a/oxalis-extension/oxalis-as2/src/test/resources/logback.xml b/oxalis-extension/oxalis-as2/src/test/resources/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..52855494d9d93f199730dd13569d2e17b5869d9d --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/logback.xml @@ -0,0 +1,41 @@ + + + + + + + + + %d %X{message-id} %p [%c] %m %n + + + + + + + + + + + + diff --git a/oxalis-extension/oxalis-as2/src/test/resources/mime-message.txt b/oxalis-extension/oxalis-as2/src/test/resources/mime-message.txt new file mode 100644 index 0000000000000000000000000000000000000000..0bd3c8234d6944aad9413c8b7381e0bfcf0f755b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/mime-message.txt @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_34_426016548.1445612302735" + +------=_Part_34_426016548.1445612302735 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_32_1720556567.1445612302731" + +------=_Part_32_1720556567.1445612302731 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The following headers were received: +date: fr, 23 okt 2015 16:58:22 +0200 +message-id: 1ae02c7f-825c-4d15-bed6-84d3410b4654 +subject: AS2 message from OXALIS +content-type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; +host: test-aksesspunkt.difi.no +x-real-ip: 109.247.18.12 +x-forwarded-for: 109.247.18.12 +x-forwarded-proto: https +connection: close +as2-from: APP_1000000111 +as2-to: APP_1000000005 +disposition-notification-to: not.in.use@difi.no +disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1 +as2-version: 1.0 +user-agent: Apache-HttpClient/4.3.6 (java 1.5) +accept-encoding: gzip,deflate +content-length: 144689 + +The message sent to AS2 System id APP_1000000111 on Fri, 23 Oct 2015 16:58:22 +0200 with subject AS2 MDN as you requested has been received. +It has been processed successfully. + +------=_Part_32_1720556567.1445612302731 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: Oxalis +Disposition: automatic-action/MDN-sent-automatically; processed +Original-Recipient: rfc822; APP_1000000111 +Final-Recipient: rfc822; APP_1000000111 +Original-Message-ID: 1ae02c7f-825c-4d15-bed6-84d3410b4654 +Received-Content-MIC: qqgUdt1MSJQ5ppbv0YPk6H/VtIA=, sha1 + + +------=_Part_32_1720556567.1445612302731-- + +------=_Part_34_426016548.1445612302735 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIAwggRjMIID +S6ADAgECAhB2xbtJl+hNi2GjbR7XK65dMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAkRLMScw +JQYDVQQKEx5OQVRJT05BTCBJVCBBTkQgVEVMRUNPTSBBR0VOQ1kxHzAdBgNVBAsTFkZPUiBURVNU +IFBVUlBPU0VTIE9OTFkxJDAiBgNVBAMTG1BFUFBPTCBBQ0NFU1MgUE9JTlQgVEVTVCBDQTAeFw0x +NDExMzAwMDAwMDBaFw0xNjExMjkyMzU5NTlaMDUxCzAJBgNVBAYTAk5PMQ0wCwYDVQQKDARESUZJ +MRcwFQYDVQQDDA5BUFBfMTAwMDAwMDAwNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANYqy399Su4zoyw6wV6gfnvCnE/O+b299Ai7iO2aYbGslALHgN2JyLuA9ZuUXBKgmGOnaN57RyT8 +EUYZdr8UUwuHfQB92AVFJKuuLBXunjk/KrMwkzreWDa9vY5hFXi4NlGnt0IGB005ew8t5LIlQYWp +sAQWFzDewM1OsXRaQPKwrBf8qI0NwKs5duGErB5rCvGno3hrK6kJuHN38wA6ptJpJODyPKws9Gzz +QtEV8u3zyiIFwnFEFDNuR51T17dYWzRSfMR2RCfYRrpgrJcq0r8Ztp60GthsfawC1ihGeoQqWzV+ +wU2Jw8meaPB49zxH6E05dZRPAYbEm+4b3W4It1cCAwEAAaOCASUwggEhMAkGA1UdEwQCMAAwCwYD +VR0PBAQDAgO4MHYGA1UdHwRvMG0wa6BpoGeGZWh0dHA6Ly9waWxvdG9uc2l0ZWNybC52ZXJpc2ln +bi5jb20vRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuUGlsb3RPcGVuUEVQUE9MQUNDRVNTUE9JTlRD +QS9MYXRlc3RDUkwuY3JsMB8GA1UdIwQYMBaAFPeWixlMruJWIQC+hv16R6ydygV1MB0GA1UdDgQW +BBRtzlYIF+xBLYqTOeWRTzcS0e9vszA6BggrBgEFBQcBAQQuMCwwKgYIKwYBBQUHMAGGHmh0dHA6 +Ly9waWxvdC1vY3NwLnZlcmlzaWduLmNvbTATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0B +AQsFAAOCAQEAAfPOJJ56O90W5BB9hOwerxyo8HEdceYPvzccUiEQnQ8QFsjwgYayiWlbcN4rOa14 +rdKastg2gpGgaLduSUhGW6NNK3x/C8ysQUBtDijXj84Ve+nc0DqF44qHNTguqHcMYZbP9tVtmeX+ +cNDzKebgx4m/OqSx+zJeVOlZN/rg2A5nae1mr+J9tshKTmRGoqJfbML/RE174LB2P6polC/ATYzC +Zq4YAGiUUf91ROMQJljbcejgJwhrU3O8CnblLbD2ufz8V8ER1ydWfNcCUERTdsIFx8babT4LLpjw +Lk4jSYXzddr+xhLzoh76Nk9FzUv0tgiGEPeBTz/t9ncO8wUU+QAAMYICGDCCAhQCAQEwgZEwfTEL +MAkGA1UEBhMCREsxJzAlBgNVBAoTHk5BVElPTkFMIElUIEFORCBURUxFQ09NIEFHRU5DWTEfMB0G +A1UECxMWRk9SIFRFU1QgUFVSUE9TRVMgT05MWTEkMCIGA1UEAxMbUEVQUE9MIEFDQ0VTUyBQT0lO +VCBURVNUIENBAhB2xbtJl+hNi2GjbR7XK65dMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJ +KoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNTEwMjMxNDU4MjJaMCMGCSqGSIb3DQEJBDEWBBQw +HlmMXCY3GQgnBqhuZtEmobwZZjANBgkqhkiG9w0BAQEFAASCAQCJnHGWwbTNh1xym2W+8fTpv7r3 +f2EaIbzoRwwh3yttmfOFqFxN6HDBr4d+e8h72A6UHnByX/sKdbzFqUXE+HsLIMV1lClFD5027ENp +VGmaV3zhmdT8Lp2kcuv9XZbq7Y26A81ht3CB3jBrXVjbpFMzdFdVcDB4YendDRDpccxERWtv8+im +LMbbyjAE4DzfIuRhpIndrp7Jx8FgpQ601AZDfHTvYMPs+yHuHGkXd7uDXwALvf27o6lmaDOqxDZr ++XlmuPl83fdnycyBSQ4cNahPmA1dStIgTMWXuL5YtN9Y9VMIjWTeL77WfOi7RtMf1o/kFOxb3nS/ +UY0Srm3fNK9jAAAAAAAA +------=_Part_34_426016548.1445612302735-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/openas2-mdn-no-headers.txt b/oxalis-extension/oxalis-as2/src/test/resources/openas2-mdn-no-headers.txt new file mode 100644 index 0000000000000000000000000000000000000000..438e3239f2f660637a3347beb27922d4f246884e --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/openas2-mdn-no-headers.txt @@ -0,0 +1,41 @@ + +------=_Part_2_1193010873.1384331414156 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_0_119619154.1384331414130" + +------=_Part_0_119619154.1384331414130 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The message sent to Recipient OpenAS2A on Wed Nov 13 09:29:03 CET 2013 with Subject PEPPOL message has been received, the EDI Interchange was successfully decrypted and it's integrity was verified. In addition, the sender of the message, Sender OpenAS2B at Location /0:0:0:0:0:0:0:1%0 was authenticated as the originator of the message. There is no guarantee however that the EDI Interchange was syntactically correct, or was received by the EDI application/translator. + +------=_Part_0_119619154.1384331414130 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: ph-OpenAS2 v1.0@/0:0:0:0:0:0:0:1%0:10080 +Original-Recipient: rfc822; OpenAS2A +Final-Recipient: rfc822; OpenAS2A +Original-Message-ID: 42 +Disposition: automatic-action/MDN-sent-automatically; processed +Received-Content-MIC: Fp67Ews9SJa5pKGXVl07dBuVW4I=, sha1 + + +------=_Part_0_119619154.1384331414130-- + +------=_Part_2_1193010873.1384331414156 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAMYIBrjCCAaoC +AQEwKDAgMQswCQYDVQQGEwJBVDERMA8GA1UEAwwIT3BlbkFTMkECBFGKVcEwCQYFKw4DAhoFAKBd +MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTEzMTExMzA4MzAxNFow +IwYJKoZIhvcNAQkEMRYEFAqdoZ4WPXKfehkAQk8I+1iqfJeGMA0GCSqGSIb3DQEBAQUABIIBAHu5 +1PU54BfUG6EPV81JtqoFF9u5bo3RSdFxCTXp4ui6w/Gp+WjelfiCWPD4i/6xHU0si8Xv36Saw0s2 +KZ9arUUtmTphdvP1Wr82sFxZgYLfdAR/1Qm3WMNAQtfZLJPBeLPsUXz4fxg+kPc4Tdha0sgJ9ciL +vv8G/I8gl0NbIDLKaRVtLn3V8nWKl4Cbs2g8uC2gX821yNOvSJ9KwJXi7sC5QPMajKoE/vVyE/fV +XxhOszP2Q7XuISinihXgJQss3kTUkSOstiQ7ESrRqUCr0ckV/P5NhvlJSPc53SzurCe+ms5sB6SP +P1IhOarWg/8V6UHyQt0EXpcMQXEYWTC43EcAAAAAAAA= +------=_Part_2_1193010873.1384331414156-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/openas2-mdn.txt b/oxalis-extension/oxalis-as2/src/test/resources/openas2-mdn.txt new file mode 100644 index 0000000000000000000000000000000000000000..74cb7af33363b796c3bdca53c2a39ca458b3dcdf --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/openas2-mdn.txt @@ -0,0 +1,54 @@ +Date: Wed, 13 Nov 2013 09:30:14 +0100 +From: OpenAS2 A email +Message-ID: +Subject: Your Requested MDN Response +Mime-Version: 1.0 +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; + boundary="----=_Part_2_1193010873.1384331414156" +AS2-To: OpenAS2B +AS2-From: OpenAS2A +AS2-Version: 1.1 +Server ph-OpenAS2 v1.0 is not blacklisted +Server: ph-OpenAS2 v1.0 +Content-Length: 2169 + +------=_Part_2_1193010873.1384331414156 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_0_119619154.1384331414130" + +------=_Part_0_119619154.1384331414130 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The message sent to Recipient OpenAS2A on Wed Nov 13 09:29:03 CET 2013 with Subject PEPPOL message has been received, the EDI Interchange was successfully decrypted and it's integrity was verified. In addition, the sender of the message, Sender OpenAS2B at Location /0:0:0:0:0:0:0:1%0 was authenticated as the originator of the message. There is no guarantee however that the EDI Interchange was syntactically correct, or was received by the EDI application/translator. + +------=_Part_0_119619154.1384331414130 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: ph-OpenAS2 v1.0@/0:0:0:0:0:0:0:1%0:10080 +Original-Recipient: rfc822; OpenAS2A +Final-Recipient: rfc822; OpenAS2A +Original-Message-ID: 42 +Disposition: automatic-action/MDN-sent-automatically; processed +Received-Content-MIC: Fp67Ews9SJa5pKGXVl07dBuVW4I=, sha1 + + +------=_Part_0_119619154.1384331414130-- + +------=_Part_2_1193010873.1384331414156 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAMYIBrjCCAaoC +AQEwKDAgMQswCQYDVQQGEwJBVDERMA8GA1UEAwwIT3BlbkFTMkECBFGKVcEwCQYFKw4DAhoFAKBd +MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTEzMTExMzA4MzAxNFow +IwYJKoZIhvcNAQkEMRYEFAqdoZ4WPXKfehkAQk8I+1iqfJeGMA0GCSqGSIb3DQEBAQUABIIBAHu5 +1PU54BfUG6EPV81JtqoFF9u5bo3RSdFxCTXp4ui6w/Gp+WjelfiCWPD4i/6xHU0si8Xv36Saw0s2 +KZ9arUUtmTphdvP1Wr82sFxZgYLfdAR/1Qm3WMNAQtfZLJPBeLPsUXz4fxg+kPc4Tdha0sgJ9ciL +vv8G/I8gl0NbIDLKaRVtLn3V8nWKl4Cbs2g8uC2gX821yNOvSJ9KwJXi7sC5QPMajKoE/vVyE/fV +XxhOszP2Q7XuISinihXgJQss3kTUkSOstiQ7ESrRqUCr0ckV/P5NhvlJSPc53SzurCe+ms5sB6SP +P1IhOarWg/8V6UHyQt0EXpcMQXEYWTC43EcAAAAAAAA= +------=_Part_2_1193010873.1384331414156-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/oxalis_home/fake-oxalis.conf b/oxalis-extension/oxalis-as2/src/test/resources/oxalis_home/fake-oxalis.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-extension/oxalis-as2/src/test/resources/oxalis_home/logback-test.xml b/oxalis-extension/oxalis-as2/src/test/resources/oxalis_home/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/oxalis_home/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/difi-negative-mdn.txt b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/difi-negative-mdn.txt new file mode 100644 index 0000000000000000000000000000000000000000..bb25134b23e96b409ab636a87a14a6562d6a331b --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/difi-negative-mdn.txt @@ -0,0 +1,82 @@ +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_2_2054159204.1399477056572" + +------=_Part_2_2054159204.1399477056572 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_0_1911916813.1399477056487" + +------=_Part_0_1911916813.1399477056487 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The following headers were received: +date: Wed, 07 May 2014 17:37:33 +0200 +message-id: 6ced0160-bbb7-4294-a68a-fab7481da936 +subject: AS2 message from OXALIS +content-type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; +host: ver-aksesspunkt.difi.no +x-real-ip: 195.1.61.90 +x-forwarded-for: 195.1.61.90 +x-forwarded-proto: https +connection: close +as2-from: APP_1000000006 +as2-to: APP_1000000009 +disposition-notification-to: not.in.use@unit4.com +disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1 +as2-version: 1.2 +user-agent: Apache-HttpClient/4.3.1 (java 1.5) +accept-encoding: gzip,deflate +content-length: 144519 + +The message sent to AS2 System id APP_1000000006 on Wed, 07 May 2014 17:37:36 +0200 with subject AS2 MDN as you requested has been received.It has been processed The warning/error message is: +ERROR: Unable to create directory /var/lib/peppol/oxalis/inbound/0088_5013546205032/9908_810017902 +------=_Part_0_1911916813.1399477056487 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: Oxalis +Disposition: automatic-action/MDN-sent-automatically; processed/ERROR: Unable to create directory /var/lib/peppol/oxalis/inbound/0088_5013546205032/9908_810017902 +Original-Recipient: rfc822; APP_1000000006 +Final-Recipient: rfc822; APP_1000000006 +Original-Message-ID: 6ced0160-bbb7-4294-a68a-fab7481da936 +Received-Content-MIC: , + +------=_Part_0_1911916813.1399477056487-- + +------=_Part_2_2054159204.1399477056572 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIAwggRYMIID +QKADAgECAhBOdXzXUvPVSzefNlAMZvGvMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkRLMScw +JQYDVQQKEx5OQVRJT05BTCBJVCBBTkQgVEVMRUNPTSBBR0VOQ1kxHzAdBgNVBAMTFlBFUFBPTCBB +Q0NFU1MgUE9JTlQgQ0EwHhcNMTMwNzE1MDAwMDAwWhcNMTUwNzE1MjM1OTU5WjBdMQswCQYDVQQG +EwJOTzEXMBUGA1UEAwwOQVBQXzEwMDAwMDAwMDcxNTAzBgNVBAoMLEFnZW5jeSBmb3IgUHVibGlj +IE1hbmFnZW1lbnQgYW5kIGVHb3Zlcm5tZW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAwm80EA6SoFfkeESatW9jSwG5tzcdok4SIP5nvj7TUrLvOWPXSH7QESeWB2vyL/hGyEtKsG7S +TS3mBEnTCyedefrQyccFCq+gw5vxFqEt7FmYi4mZkItuaYagnamx5KjIezmQnVZOrQJObFc0o9Xj +eg8fCu0spPyTI2wFBba2G1jxiO7dacS56Eyzvudy07S2eufMs8CV74hHmkK/ZbnWDfaCRFQ9UftD +o6vENHZ4cuhECBsd0sHeGyVcABtuqHMCdz5TeciIk2Ppa+JkehV6bYqfyrC4vy6YK12rBaZ0dGOJ ++bnwE7o4apevqg+hN3BOd2NC8pvGTjHvg9BjRCYoLQIDAQABo4IBGDCCARQwCQYDVR0TBAIwADAL +BgNVHQ8EBAMCA7gwbAYDVR0fBGUwYzBhoF+gXYZbaHR0cDovL29uc2l0ZWNybC52ZXJpc2lnbi5j +b20vRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuT3BlblBFUFBPTEFDQ0VTU1BPSU5UQ0EvTGF0ZXN0 +Q1JMLmNybDAfBgNVHSMEGDAWgBRN9j4AUCiGbTWg/O9mqvoioSTbjTAdBgNVHQ4EFgQU1WkX8tTt +mDjwQIVVAf6nfZ2LfmowNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vcGtpLW9j +c3Auc3ltYXV0aC5jb20wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAH0k +dItdmxsoq1i5SsJ0oaUjJwh6yNmm4/Zc/vIKhLX2v6i3ISQGvAK608CO6wLRuLv3c8T6+NLOMT5l +qv6gcvTU8L50eF7uOyRGuVfl6o4/+nrM8bQCdbQq6zQgtGn+88yzLo+4m9VzH/WO8OZ6mT63CcyI +H+8UjCDhhoXMM8bY8EVaJkbvX3kL1WDW2fGbzeXUF7RR+0fAJnIHrJkPeKuxDqMUjXd19gpte4Rj +Ihkhmj669Ya/mDnRQfO0pvt4DltM7w/OLXrwBngvVM1RNjzHrfi7OYqBdA5tgNWQJN5dFP85rSo2 +8EunYw5b1uVj61GlrZ5L30eJdnbwsdHvKKgAADGCAfEwggHtAgEBMGswVzELMAkGA1UEBhMCREsx +JzAlBgNVBAoTHk5BVElPTkFMIElUIEFORCBURUxFQ09NIEFHRU5DWTEfMB0GA1UEAxMWUEVQUE9M +IEFDQ0VTUyBQT0lOVCBDQQIQTnV811Lz1Us3nzZQDGbxrzAJBgUrDgMCGgUAoF0wGAYJKoZIhvcN +AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTQwNTA3MTUzNzM2WjAjBgkqhkiG9w0B +CQQxFgQUuOQPHHsfo4ZpGmUlBg8488gpnI4wDQYJKoZIhvcNAQEBBQAEggEAZJrJ6zi0url93ao8 +4/7mt63US3e5K5npLTZA6FZjhMTGKNqyPI1rRCq7UDZPrisJBrJhyKgYjgdmzj88r4ANEu0D40A4 +oYnNx7HBuBvXKpjwotsIGkPMmgnkteN7vK3F4MzSzY3w1atm1NwtnCRvpqqTggrTUbNhWQYXVs4l +O7LVY+/xWaTjjsWfNKAqAroAWw66Iwix0FFIQVZ5Vo2Dy9+spLP/RoeehBTzMLMzOUbZfrE6uVDx +mbqPX3yc28yS6EYHF23I3mo129b0fTs4bBof/RfTVrXgzM5/weoRWQ1YdjgeDE1WVlChwTOMatQY +kIrbecVQ3twAQu3BEV3DxQAAAAAAAA== +------=_Part_2_2054159204.1399477056572-- + \ No newline at end of file diff --git a/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/ibx-mdn-base64.txt b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/ibx-mdn-base64.txt new file mode 100644 index 0000000000000000000000000000000000000000..a49acca23f25bb30b1c28139f0c6c61514018124 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/ibx-mdn-base64.txt @@ -0,0 +1,77 @@ +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_9916_110858470.1409652908446" + +------=_Part_9916_110858470.1409652908446 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_9915_55548288.1409652908446" + +------=_Part_9915_55548288.1409652908446 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The following headers were received: +Date: ti, 02 sep 2014 12:15:00 +0200 +Message-Id: 19a9099c-c553-4ffa-9c60-de2fcfa2922f +Subject: AS2 message from OXALIS +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_1_25794584.1409652900611" +Content-Length: 343334 +as2-from: APP_1000000030 +as2-to: APP_1000000014 +disposition-notification-to: not.in.use@unit4.com +disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1 +as2-version: 1.0 +host: peppolap.ibxplatform.net +connection: Keep-Alive +user-agent: Apache-HttpClient/4.3.1 (java 1.5) +accept-encoding: gzip,deflate +x-forwarded-proto: SSL +x-forwarded-for: 134.47.109.184 +The message sent to AS2 System id APP_1000000030 on Tue, 02 Sep 2014 10:15:08 +0000 with subject AS2 MDN as you requested has been received. +It has been processed successfully. +------=_Part_9915_55548288.1409652908446 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: base64 + +UmVwb3J0aW5nLVVBOiBPeGFsaXMNCkRpc3Bvc2l0aW9uOiBhdXRvbWF0aWMtYWN0aW9uL01ETi1z +ZW50LWF1dG9tYXRpY2FsbHk7IHByb2Nlc3NlZA0KT3JpZ2luYWwtUmVjaXBpZW50OiByZmM4MjI7 +IEFQUF8xMDAwMDAwMDMwDQpGaW5hbC1SZWNpcGllbnQ6IHJmYzgyMjsgQVBQXzEwMDAwMDAwMzAN +Ck9yaWdpbmFsLU1lc3NhZ2UtSUQ6IDE5YTkwOTljLWM1NTMtNGZmYS05YzYwLWRlMmZjZmEyOTIy +Zg0KUmVjZWl2ZWQtQ29udGVudC1NSUM6IFZaT1c4YVJ2OWU4dUVRRWRHUmR4d2NPWUgxZz0sIHNo +YTENCg0K +------=_Part_9915_55548288.1409652908446-- + +------=_Part_9916_110858470.1409652908446 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIAwggQ4MIID +IKADAgECAhBbpYt7gzvMwfrN1q5VDc6oMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkRLMScw +JQYDVQQKEx5OQVRJT05BTCBJVCBBTkQgVEVMRUNPTSBBR0VOQ1kxHzAdBgNVBAMTFlBFUFBPTCBB +Q0NFU1MgUE9JTlQgQ0EwHhcNMTMxMDAzMDAwMDAwWhcNMTUxMDAzMjM1OTU5WjA9MQswCQYDVQQG +EwJTRTEXMBUGA1UEAwwOQVBQXzEwMDAwMDAwMTQxFTATBgNVBAoMDElCWCBHcm91cCBBQjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALL27Jv39N3GW+twGQqqMS1uNNfBAHwQNehYSwUa +gm21s0zplyZPa+UmgtBmPC2fjpd9bMDdm1Rh/Up1mlBAnjIpLRIPwMGN/lyzfdSla+kF7vSXtbwY +CH6Zf6u4rZqQ1Ncq/zli1/tK4B1Je9cbYmQ55I6C2WKpNzz1g4dYpn6klXNBUk/fyrKx9nB4+MUl +TTC2XJTV7ZVfmbULdNKckGFmHN9XWhEV2BI0p19xEe5CABzsoOw7C7SE18lfquALHKNk8QtldssZ +pQ1Xv5eKKt7659TF1Q7niydbo+MHC+AUSwKRXj5NtWuG+JJ5ubJpDcipLGhQ66PAasbfFws1P2sC +AwEAAaOCARgwggEUMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgO4MGwGA1UdHwRlMGMwYaBfoF2GW2h0 +dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNlbk9wZW5Q +RVBQT0xBQ0NFU1NQT0lOVENBL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgwFoAUTfY+AFAohm01oPzv +Zqr6IqEk240wHQYDVR0OBBYEFP2A11RTpVimXRhiOvDyjUi3Bx9kMDcGCCsGAQUFBwEBBCswKTAn +BggrBgEFBQcwAYYbaHR0cDovL3BraS1vY3NwLnN5bWF1dGguY29tMBMGA1UdJQQMMAoGCCsGAQUF +BwMCMA0GCSqGSIb3DQEBCwUAA4IBAQB207P1LBkSjBmXenbelNf3UryPxNB5BRVFf7/HvUR/jXWo +TbupzB4b9kusNt4YgSoYInZhHFMp6uTnNXYJtJxSCy0hqxHbSEDoldV/p22i7YOrEphTx5u3dZiV +5qjSPxPNNlsodprxtxzOTSTv+VJYir517eVird62pto8TlSYhOKH+wP0CN2ckr9jcgK4/bhQY14s +//WJ/ImYMQNLRCqyCfdWykEd+DWPSTPSE2/mzvuWUHBU1dlxGMQSP+zav/mXK6/eKTdeG2x75mfB +PwgYx4YiRkyKRU70DjyvvBDyUlb2kXeWJgyEsZlxASsV5aS79s+gQjR4EzNswdGQXjpNAAAxggHx +MIIB7QIBATBrMFcxCzAJBgNVBAYTAkRLMScwJQYDVQQKEx5OQVRJT05BTCBJVCBBTkQgVEVMRUNP +TSBBR0VOQ1kxHzAdBgNVBAMTFlBFUFBPTCBBQ0NFU1MgUE9JTlQgQ0ECEFuli3uDO8zB+s3WrlUN +zqgwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8X +DTE0MDkwMjEwMTUwOFowIwYJKoZIhvcNAQkEMRYEFIhD8Abnj4UYUXsGN+jhnpuflTigMA0GCSqG +SIb3DQEBAQUABIIBACnyrP7ZuOlAjzuCEenOMYFg/ZS0ZQUTNEtDG/jiBQgqRYP1mwF5HQfOPzaU +R597hzNUQs6bZNa0+0dEbf+BuxZm2GJTeWiTQYulAXJHj5/9TqgCND5pJGDK+PAW5a5iusya7Vx7 +k+V2DXajPLgDrfr0MfGEr3XLq4MnpIataMFb+7qORPvMRfhyYrxWQNdKmeKqnswc3wYJZQNvuKKB +L9nJnezdhm72H76yw0uc5SmPANrO5+Jf7Qm6NFqY2BS4fV6lrObELDHSISYLanNhkRikByIuvFEx +BV7DF7Lena3r3bdmSK0tTwWvATSE7wu7gqePVuIjuuTFQj64X0f678oAAAAAAAA= +------=_Part_9916_110858470.1409652908446-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/itsligo-mdn.txt b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/itsligo-mdn.txt new file mode 100644 index 0000000000000000000000000000000000000000..dd97533d2c77bd2ea167625e2affc3f75cdcf1e3 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/itsligo-mdn.txt @@ -0,0 +1,42 @@ +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha1; boundary="boundarykmWBAw==" + +--boundarykmWBAw== +Content-Type: multipart/report; Report-Type=disposition-notification; boundary="----=MDN_boundary_ffb81710-0c1e-4b95-a097-57252ea0aea0" + +------=MDN_boundary_ffb81710-0c1e-4b95-a097-57252ea0aea0 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +MDN for - +Message-ID: ebbfc406-6388-4f44-86bc-9d66844ad92c@CourierWeb +Subject: MDN +Date: Tue, 06 May 2014 13:01:20 GMT +From: peppol-APP_1000000009 +To: APP_1000000006 +Received On: Tue, 06 May 2014 13:01:20 GMT +Status: Disposition: automatic-action/MDN-sent-automatically; processed +Comment: This is not a guarantee that the message has been completely processed or understood by the receiving translator + + +------=MDN_boundary_ffb81710-0c1e-4b95-a097-57252ea0aea0 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: Omni ; Courier +Original-Recipient: rfc822;peppol-APP_1000000009 +Final-Recipient: rfc822;peppol-APP_1000000009 +Original-Message-ID: 6229515e-28af-4d90-9587-f4f6f952ccf5 +Received-Content-MIC: rcg7GeeTSRscbqD9i0bNnzLlkvw=, sha1 +Disposition: automatic-action/MDN-sent-automatically; processed + +------=MDN_boundary_ffb81710-0c1e-4b95-a097-57252ea0aea0-- + +--boundarykmWBAw== +Content-Type: application/pkcs7-signature; name="smime.p7s" +Content-Disposition: attachment; filename="smime.p7s" +Content-Transfer-Encoding: base64 + +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 + +--boundarykmWBAw==-- + diff --git a/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unimaze-mdn.txt b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unimaze-mdn.txt new file mode 100644 index 0000000000000000000000000000000000000000..d385f944f00abb640b2e65a84797838a7c501958 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unimaze-mdn.txt @@ -0,0 +1,79 @@ +Content-Type: multipart/signed; boundary="------_=_NextPart_001_071EE00D.7087D242"; micalg="sha-1"; protocol="application/pkcs7-signature" + +--------_=_NextPart_001_071EE00D.7087D242 +Content-Type: multipart/report; + boundary="------_=_NextPart_001_E57B66E8.6B77E4C3" + +--------_=_NextPart_001_E57B66E8.6B77E4C3 +Content-Type: text/plain; + charset="us-ascii" + +MDN for - + Message-Id: 477b2b62-675d-4122-8e59-b24626d4c375 + AS2-From: APP_1000000006 + AS2-To: SMP_2000000005 + Date: Tue, 06 May 2014 18:55:37 +0200 + Subject: AS2 message from OXALIS + +The message has been received. It has been processed successfully. + +--------_=_NextPart_001_E57B66E8.6B77E4C3 +Content-Type: message/disposition-notification + +Reporting-UA: AS2 eefacta Server (unimaze.com) +Original-Recipient: rfc822; SMP_2000000005 +Final-Recipient: rfc822; SMP_2000000005 +Original-Message-ID: 477b2b62-675d-4122-8e59-b24626d4c375 +Received-Content-MIC: 10g8Xg9swwOlTqAqjXpwpEhW1LQ=, sha1 +Disposition: automatic-action/MDN-sent-automatically; processed + + +--------_=_NextPart_001_E57B66E8.6B77E4C3 +Content-Type: text/plain + + +--------_=_NextPart_001_E57B66E8.6B77E4C3-- + +--------_=_NextPart_001_071EE00D.7087D242 +Content-Type: application/pkcs7-signature; + name="smime.7ps"; + smime-type="signed-data" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="smime.7ps" + +MIAGCSqGSIb3DQEHAqCAMIACAQExgDAJBgUrDgMCGgUAAAAwgAYJKoZIhvcNAQcBAACggDCCBDww +ggMkoAMCAQICEDo9Q6Uo26Ro7phICY6e0K0wDQYJKoZIhvcNAQELBQAwVzELMAkGA1UEBhMCREsx +JzAlBgNVBAoTHk5BVElPTkFMIElUIEFORCBURUxFQ09NIEFHRU5DWTEfMB0GA1UEAxMWUEVQUE9M +IEFDQ0VTUyBQT0lOVCBDQTAeFw0xMzExMDQwMDAwMDBaFw0xNTExMDQyMzU5NTlaMEExCzAJBgNV +BAYTAklTMRcwFQYDVQQDDA5BUFBfMTAwMDAwMDA1MzEZMBcGA1UECgwQVW5pbWF6ZSBTb2Z0d2Fy +ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANU/u4z2ykLWduxqdpNCIs3/9huTlYoM +GJonlAdVaQkvyX4g0BIJ7Puj/mRbe+X4PuphkKu5xgZiTCeHbsH0koCcNy/OwEFhe48v3cne3j5R +OF+np5y4Z5CsKb3g4yposDFVBg9+tKvZVvZ3EQfcd1XgUj+Mcgk9zIwpdAqRvu03RZnL1D0knTNh +y7ifNSdGjsVtaTHU1Ck7MMPxgkmXXxWvz5hQbwgjeI4n51lGC1vcVc5lfyG09eXUBJ/4cjGnp2xC +dCLQN33UlDB37mbFQEF+POlI/oixpI9mGH883b3BJ9GTyHT9exmBJTOg7u1xoN70J7+DnejPiQOD +yOifHe0CAwEAAaOCARgwggEUMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgO4MGwGA1UdHwRlMGMwYaBf +oF2GW2h0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL0RpZ2l0YWxpc2VyaW5nc3N0eXJlbHNl +bk9wZW5QRVBQT0xBQ0NFU1NQT0lOVENBL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgwFoAUTfY+AFAo +hm01oPzvZqr6IqEk240wHQYDVR0OBBYEFFJv1siJv5dBzRURgvU4/3zB4ATyMDcGCCsGAQUFBwEB +BCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3BraS1vY3NwLnN5bWF1dGguY29tMBMGA1UdJQQMMAoG +CCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQAvQx+oB/Lr6r+TXaWL7a8rRkZugdB6JVvcl41U +MHTnXgU/KukHjiC3HF0DwQ9NRD9tsvhivZYii6FIZJOUYRnXH4UrrvYsV9TApOUi74NCCFAaAnnp +QUQijUzFIWMYNit+qUMLNMC2ZbO5GyqWTsiIJzBZKOCsdIgBsFmIACXsMgKvB8d01DqQE2OsZHBj +n2BOIjWOavinrZpgNJgZh7QEvhb6r1N2JcRwPfrAjcCW4rYkHp/ZJOnJwGkuNVBXpNiAGLcmrBdJ +u/TZFOj/uWhlOms0EtTgFb7oaT24/wSoR3axfl5RpMpF/9G/duji6P+kKFRJTB6hzpb2hike8KAE +AAAxgDCCAlcCAQEwazBXMQswCQYDVQQGEwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRF +TEVDT00gQUdFTkNZMR8wHQYDVQQDExZQRVBQT0wgQUNDRVNTIFBPSU5UIENBAhA6PUOlKNukaO6Y +SAmOntCtMAkGBSsOAwIaBQCggcYwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0B +CQUxDxcNMTQwNTA2MTY1NjAyWjAjBgkqhkiG9w0BCQQxFgQUjVvVQgrWMaqgOks0B78fzPbMv+ow +ZwYJKoZIhvcNAQkPMVowWDAHBgUrDgMCBzAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgICAIAwDQYI +KoZIhvcNAwICAUAwDQYIKoZIhvcNAwICASgwBwYFKw4DAhowCgYIKoZIhvcNAgUwDQYJKoZIhvcN +AQEBBQAEggEAsPjNqJIcA4GtjpboIUwIHBLmh/45tgAMC7Y+8cu758iOyBdi8PC9lA8qJbzf5bKJ +kr6CP0U5M3b2AulNVXzQInDcZGY89qNv8NBwyarNNJjhleGm3qAmRHv7CNODtWD3HV8IUX1yFCHW +9fO7TjVUVRIKTUHZE4W5KFIFxQDG5U4Ad4CI48CPdXX+J1dq/ehpwiFdwhIQzVwXOhpNhppBJ5My +5Kqi2YKU+VVpc+KjabyKG6ks7lK5QCXV8lj3xF76csOa3aYQPgmIeT6nPp++SGazIwuuw3T6WmcF +BarqNZ/KsoNG19KBmGfm910Bdlr6eSedyaMFoBRvSshWYCasTQAAAAAAAAAA + +--------_=_NextPart_001_071EE00D.7087D242-- + + diff --git a/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn-error.txt b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn-error.txt new file mode 100644 index 0000000000000000000000000000000000000000..e9a1a6532f066d6abdc51b9bcace9030bc8067ca --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn-error.txt @@ -0,0 +1,78 @@ +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_8_1114200408.1399392201942" + +------=_Part_8_1114200408.1399392201942 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_6_205642152.1399392201937" + +------=_Part_6_205642152.1399392201937 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The following headers were received: +date: Tue, 06 May 2014 18:03:30 +0200 +message-id: 437a76b5-0a91-470d-87eb-1b4f1e125d86 +subject: AS2 message from OXALIS +content-type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; +host: ap-test.unit4.com +x-forwarded-for: 195.1.61.4 +connection: close +as2-from: APP_1000000006 +as2-to: APP_1000000009 +disposition-notification-to: not.in.use@unit4.com +disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1 +as2-version: 1.2 +user-agent: Apache-HttpClient/4.3.1 (java 1.5) +accept-encoding: gzip,deflate +content-length: 144523 + +The message sent to AS2 System id APP_1000000006 on Tue, 06 May 2014 18:03:21 +0200 with subject AS2 MDN as you requested has been received.It has been processed successfully. +------=_Part_6_205642152.1399392201937 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: Oxalis +Disposition: automatic-action/MDN-sent-automatically; processed +Original-Recipient: rfc822; APP_1000000006 +Final-Recipient: rfc822; APP_1000000006 +Original-Message-ID: 437a76b5-0a91-470d-87eb-1b4f1e125d86 +Received-Content-MIC: GrW0abLVrbKXxkMdDmAfDZoW3w0=, sha1 +Added-Header: This header was manually added after signing so that the signature should break + +------=_Part_6_205642152.1399392201937-- + +------=_Part_8_1114200408.1399392201942 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +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 +------=_Part_8_1114200408.1399392201942-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn-negative.txt b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn-negative.txt new file mode 100644 index 0000000000000000000000000000000000000000..95cd32c829188ad6c1a4fdd0263433add293fbac --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn-negative.txt @@ -0,0 +1,79 @@ +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_34_1575144894.1399904449035" + +------=_Part_34_1575144894.1399904449035 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_32_573291651.1399904449032" + +------=_Part_32_573291651.1399904449032 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The following headers were received: +date: ma, 12 mai 2014 16:20:55 +0200 +message-id: 67c6fb66-5d91-411a-be50-0126d1510a9d +subject: AS2 message from OXALIS +content-type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; +host: ap-test.unit4.com +x-forwarded-for: 195.1.61.4 +connection: close +as2-from: APP_1000000006 +as2-to: APP_1000000006 +disposition-notification-to: not.in.use@unit4.com +disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1 +as2-version: 1.2 +user-agent: Apache-HttpClient/4.3.1 (java 1.5) +accept-encoding: gzip,deflate +content-length: 3199 + +The message sent to AS2 System id APP_1000000006 on Mon, 12 May 2014 16:20:49 +0200 with subject AS2 MDN as you requested has been received.It has been processed The warning/error message is: +ERROR: Index: 0, Size: 0 +------=_Part_32_573291651.1399904449032 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: Oxalis +Disposition: automatic-action/MDN-sent-automatically; processed/ERROR: Index: 0, Size: 0 +Original-Recipient: rfc822; APP_1000000006 +Final-Recipient: rfc822; APP_1000000006 +Original-Message-ID: 67c6fb66-5d91-411a-be50-0126d1510a9d +Received-Content-MIC: QgWi3uJbd2DI9yuUUWTxvtugm9w=, sha1 + +------=_Part_32_573291651.1399904449032-- + +------=_Part_34_1575144894.1399904449035 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +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 +------=_Part_34_1575144894.1399904449035-- + diff --git a/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn.txt b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn.txt new file mode 100644 index 0000000000000000000000000000000000000000..164b810e6b239c630dc08992224300f9abca5cff --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/real-mdn-examples/unit4-mdn.txt @@ -0,0 +1,77 @@ +Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_8_1114200408.1399392201942" + +------=_Part_8_1114200408.1399392201942 +Content-Type: multipart/report; report-type=disposition-notification; + boundary="----=_Part_6_205642152.1399392201937" + +------=_Part_6_205642152.1399392201937 +Content-Type: text/plain +Content-Transfer-Encoding: 7bit + +The following headers were received: +date: Tue, 06 May 2014 18:03:30 +0200 +message-id: 437a76b5-0a91-470d-87eb-1b4f1e125d86 +subject: AS2 message from OXALIS +content-type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; +host: ap-test.unit4.com +x-forwarded-for: 195.1.61.4 +connection: close +as2-from: APP_1000000006 +as2-to: APP_1000000009 +disposition-notification-to: not.in.use@unit4.com +disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1 +as2-version: 1.2 +user-agent: Apache-HttpClient/4.3.1 (java 1.5) +accept-encoding: gzip,deflate +content-length: 144523 + +The message sent to AS2 System id APP_1000000006 on Tue, 06 May 2014 18:03:21 +0200 with subject AS2 MDN as you requested has been received.It has been processed successfully. +------=_Part_6_205642152.1399392201937 +Content-Type: message/disposition-notification +Content-Transfer-Encoding: 7bit + +Reporting-UA: Oxalis +Disposition: automatic-action/MDN-sent-automatically; processed +Original-Recipient: rfc822; APP_1000000006 +Final-Recipient: rfc822; APP_1000000006 +Original-Message-ID: 437a76b5-0a91-470d-87eb-1b4f1e125d86 +Received-Content-MIC: GrW0abLVrbKXxkMdDmAfDZoW3w0=, sha1 + +------=_Part_6_205642152.1399392201937-- + +------=_Part_8_1114200408.1399392201942 +Content-Type: application/pkcs7-signature; name=smime.p7s; smime-type=signed-data +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" +Content-Description: S/MIME Cryptographic Signature + +MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIAwggQ3MIID +H6ADAgECAhAqfF77g8DrtmCJ3BVCV5ZPMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkRLMScw +JQYDVQQKEx5OQVRJT05BTCBJVCBBTkQgVEVMRUNPTSBBR0VOQ1kxHzAdBgNVBAMTFlBFUFBPTCBB +Q0NFU1MgUE9JTlQgQ0EwHhcNMTMwNTA2MDAwMDAwWhcNMTUwNTA2MjM1OTU5WjA8MQswCQYDVQQG +EwJOTzEXMBUGA1UEAwwOQVBQXzEwMDAwMDAwMDYxFDASBgNVBAoMC1NlbmRSZWduaW5nMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3nP2ylJO9opc3czwBhGrpxhDYtR7JBHV1aG9CWhE +hYGt4y7++ABfADt0pc4XFRlMpXSw8pvU6kbiz57k3rae/zO2mEHhjJHZOKTdIReHtm8wdAcPZBg+ +f9r4tfjwAVBYE7hIqq8Zo6q2PNwSQNcE7hyzjDVxEoJ9locbOQd+JO/voHOI0MenBMRAS1pjqKRB +S2bwfFKbMP8VCEQt56ry6xcCvdLqFWrTyaaAgJvz9n5+Sn/xeeKztTpwvGoJaypvZ2Gv0ODqocS1 +azpUPzPpcSrp223HIHlLmQlVkYbpMzmlzFJqQFveozyn/ItGtw8a94DrrSjcuFgHthLTJRB/OQID +AQABo4IBGDCCARQwCQYDVR0TBAIwADALBgNVHQ8EBAMCA7gwbAYDVR0fBGUwYzBhoF+gXYZbaHR0 +cDovL29uc2l0ZWNybC52ZXJpc2lnbi5jb20vRGlnaXRhbGlzZXJpbmdzc3R5cmVsc2VuT3BlblBF +UFBPTEFDQ0VTU1BPSU5UQ0EvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBRN9j4AUCiGbTWg/O9m +qvoioSTbjTAdBgNVHQ4EFgQUTmbSAHsnDuRz6W2WJIbRzik6erswNwYIKwYBBQUHAQEEKzApMCcG +CCsGAQUFBzABhhtodHRwOi8vcGtpLW9jc3Auc3ltYXV0aC5jb20wEwYDVR0lBAwwCgYIKwYBBQUH +AwIwDQYJKoZIhvcNAQELBQADggEBAHQAdNKgoRqycHuVxhLNww675sfkctICEJb1WrT8dwJ70S63 +AgraMgfMNL8anJ+XQxRGicDX85Y52HIKUaaA+JAFkqQTQivXkLoxGGsseZQydT1tEixPy4SjGJcf +puJRXDZKsBLr1O3pe/fJ02EOIUZ3GwP5h+RrVyIfpPE5+WKyq1G457BKRXSS95DkuYxfn3kGvcIi +aaKY2cGNfKqhFtm01CY6APzn/OZbsFfwkDIIv1v7ZouZRMVDIiIZaI06T6l04u2l2GT1IoSj6F9d +BUxZZE8zVL8z6Q0ljOOVwL/Mva/bHomhygGRBKyOETBwSQgX1RaaKoYrAveoAqw42eIAADGCAfEw +ggHtAgEBMGswVzELMAkGA1UEBhMCREsxJzAlBgNVBAoTHk5BVElPTkFMIElUIEFORCBURUxFQ09N +IEFHRU5DWTEfMB0GA1UEAxMWUEVQUE9MIEFDQ0VTUyBQT0lOVCBDQQIQKnxe+4PA67ZgidwVQleW +TzAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTQwNTA2MTYwMzIxWjAjBgkqhkiG9w0BCQQxFgQUVykA8oqGpvaVwvFtzutPo4Hwh8UwDQYJKoZI +hvcNAQEBBQAEggEAGG5lkWwWFIyd/TMPvCLfA1ZyQ0hbdcyJwriCvbSqJfcEQ86WIStzkQKI6Kj7 +omFqK9btpojtrhXbCybuZQqWLQKaUczyQLPpmimAhJOMZNDXiLie6SClT+Raho6QVJpdHdq6ndDN +AfXgcgovyJkz24uiXErkAVL6LVPMM2m9IKgcqUBB26uKZ5m0Wm6p4adlyTM7C6P4o1fGuhliISTi +3i9Kg2AegonccXCotgADGE3bgCNS+j+tRdN/ZccYsbRMCugn9nuDlvUsfzaEfSG1sc+4jvkBGzdy +mnvlClk2VEJ7e+WFof8tDPVwZoBTy6Kh86IHKq7vikgm73YT32s/aQAAAAAAAA== +------=_Part_8_1114200408.1399392201942-- diff --git a/oxalis-extension/oxalis-as2/src/test/resources/reference.conf b/oxalis-extension/oxalis-as2/src/test/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..47a59b1d377e45187dc7619334aaee4802964b1e --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/reference.conf @@ -0,0 +1,10 @@ +oxalis.module.inbound.mocking.class = network.oxalis.as2.mocking.InboundMockingModule + +brave.reporter = noop +oxalis.statistics.service = noop +oxalis.persister.payload = noop +oxalis.persister.receipt = noop + +oxalis.http.pool.max_route = 10 +oxalis.http.pool.validate_after_inactivity = 1000 +oxalis.http.pool.time_to_live = 30 diff --git a/oxalis-extension/oxalis-as2/src/test/resources/sample-as2-post-headers.txt b/oxalis-extension/oxalis-as2/src/test/resources/sample-as2-post-headers.txt new file mode 100644 index 0000000000000000000000000000000000000000..2ea76926e443a088e120907bd8ae654619df041c --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/sample-as2-post-headers.txt @@ -0,0 +1,14 @@ +as2-from: APP_1000000135 +as2-to: peppol-APP_1000000006 +disposition-notification-to: not.in.use@difi.no +disposition-notification-options: signed-receipt-protocol=required,pkcs7-signature; signed-receipt-micalg=required,sha1 +as2-version: 1.0 +subject: AS2 message from OXALIS +message-id: 8c096de8-ec58-4dc6-a9c4-6c465b2c83c5 +date: ti, 22 des 2015 21:50:17 +0100 +content-length: 11448 +content-type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; boundary="----=_Part_1_1095273238.1450817416972" +host: localhost:8443 +connection: Keep-Alive +user-agent: Apache-HttpClient/4.3.6 (java 1.5) +accept-encoding: gzip,deflate \ No newline at end of file diff --git a/oxalis-extension/oxalis-as2/src/test/resources/sample.asice b/oxalis-extension/oxalis-as2/src/test/resources/sample.asice new file mode 100644 index 0000000000000000000000000000000000000000..186ea597143ba820e8b92775ab49d5fe614e401e Binary files /dev/null and b/oxalis-extension/oxalis-as2/src/test/resources/sample.asice differ diff --git a/oxalis-extension/oxalis-as2/src/test/resources/sbdh-asic.xml b/oxalis-extension/oxalis-as2/src/test/resources/sbdh-asic.xml new file mode 100644 index 0000000000000000000000000000000000000000..66eb24b521ec2732038e72a4fc7c7030d95f7a58 --- /dev/null +++ b/oxalis-extension/oxalis-as2/src/test/resources/sbdh-asic.xml @@ -0,0 +1,154 @@ + + + + 1.0 + + 9908:810018909 + + + 9908:810418052 + + + urn:oasis:names:specification:ubl:schema:xsd:Tender-2 + 2.1 + FA4A6819-6149-4134-95C3-C53A65338EB6 + Tender + 2015-07-26T20:08:00+01:00 + + + 1 + + application/vnd.etsi.asic-e+zip + #asic + Base64 encoded ASiC archive containing business documents. + + + + + PROCESSID + urn:www.cenbii.eu:profile:bii46:ver3.0 + + + DOCUMENTID + + urn:oasis:names:specification:ubl:schema:xsd:Tender-2::Tender##urn:www.cenbii.eu:transaction:biitrdm090:ver3.0::2.1 + + + + + + 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 + QS1JTkYvbWFuaWZlc3QueG1srZHBasMwDIbveQrj63CS3jaTtLc9wfYAaqyuBls2llKSPf2clMFg + MHqYbhK/vv8XGk5LDOqGhX2iUR/aXiukKTlPH6N+f3s1z1qxADkIiXDUK7I+HZuB+GAjkL8gi6oM + YltHo54L2QTsawsR2cpkU0ZyaZojkti79HvTbobHRtXaiRcf0FRZWdXeziGYDHIddaf3SUTnwcia + axTIOfgJpCbvbuRaFPZttZ4MPn36rLuHwHx217am+pu/CR7jSXGxf+kNz+foxUi9HYthiDngf/rc + iaYguIitLPIbLLhIlwN42phD9/Nnx+YLUEsHCFuZArnqAAAA+wEAAFBLAQIKAAoAAAgAAI1ZMEeK + IflFHwAAAB8AAAAIAAAAKAAAAAAAAAAAAAAAAABtaW1ldHlwZW1pbWV0eXBlPWFwcGxpY2F0aW9u + L3ZuZC5ldHNpLmFzaWMtZSt6aXBQSwECFAAUAAgICACNWTBH1R7KSasEAADfCwAACAAAAAAAAAAA + AAAAAABFAAAAc2JkaC54bWxQSwECFAAUAAgICACNWTBHqhrKndAGAABLEwAAIAAAAAAAAAAAAAAA + AAAmBQAAdHJkbTA5MC1zdWJtaXQtdGVuZGVyLXNhbXBsZS54bWxQSwECFAAUAAgICACNWTBHGHwq + qDcAAAA5AAAAEQAAAAAAAAAAAAAAAABEDAAAc2FtcGxlLXJlYWRtZS50eHRQSwECFAAUAAgICACN + WTBHjEPERu8BAABwBAAAGQAAAAAAAAAAAAAAAAC6DAAATUVUQS1JTkYvYXNpY21hbmlmZXN0Lnht + bFBLAQIUABQACAgIAI1ZMEeS19UY5gUAAGEHAAA7AAAAAAAAAAAAAAAAAPAOAABNRVRBLUlORi9z + aWduYXR1cmUtNGFjMjIwYTUtYzVkMi00YmFlLTliZmItODVhNjdhMDY3ZTZjLnA3c1BLAQIUABQA + CAgIAI1ZMEdbmQK56gAAAPsBAAAVAAAAAAAAAAAAAAAAAD8VAABNRVRBLUlORi9tYW5pZmVzdC54 + bWxQSwUGAAAAAAcABwAUAgAAbBYAACgAbWltZXR5cGU9YXBwbGljYXRpb24vdm5kLmV0c2kuYXNp + Yy1lK3ppcA== + + + diff --git a/oxalis-extension/oxalis-extension-example/README.md b/oxalis-extension/oxalis-extension-example/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4962976e3fcc9fef9792acae325b49540e8be21d --- /dev/null +++ b/oxalis-extension/oxalis-extension-example/README.md @@ -0,0 +1,23 @@ +# Example extension + +This is an example extension providing a simple implementation of TransmissionVerifier to log each message (metadata only) to be verified. + +This implementation consists of the following files: + +* [LoggingTransmissionVerifier](src/main/java/network/oxalis/ext/example/LoggingTransmissionVerifier.java) - The implementation. +* [ExampleModule](src/main/java/network/oxalis/ext/example/ExampleModule.java) - Guice module to make the implementation known to Oxalis. +* [reference.conf](src/main/resources/reference.conf) - Configuration to register the Guice module during Oxalis startup. +* [pom.xml](pom.xml) - Maven configuration to build an extension using Maven. + +Extensions are included in classpath as of Oxalis 4.0.0. +The best ways of deploying your Oxalis instance: + +* WAR file - Build your own WAR file containing the Oxalis libraries and your extensions for deployment on your servers. +* Oxalis Server - Include extensions and additional libaries in the `ext` folder. +* Docker - Include extensions and additional libraries in `/oxalis/ext/`. + +To enable the verifier implementation included in this extension must the following be included in the oxalis configuration file: + +```properties +oxalis.transmission.verifier = logging +``` \ No newline at end of file diff --git a/oxalis-extension/oxalis-extension-example/pom.xml b/oxalis-extension/oxalis-extension-example/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..428e431348a8273b93f69ed31a1080627579d8d2 --- /dev/null +++ b/oxalis-extension/oxalis-extension-example/pom.xml @@ -0,0 +1,47 @@ + + + + + + oxalis-extension + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + 4.0.0 + + oxalis-extension-example + + Oxalis :: Ext :: Example + + + + \ No newline at end of file diff --git a/oxalis-extension/oxalis-extension-example/src/main/java/network/oxalis/ext/example/ExampleModule.java b/oxalis-extension/oxalis-extension-example/src/main/java/network/oxalis/ext/example/ExampleModule.java new file mode 100644 index 0000000000000000000000000000000000000000..e7990d25d2150493b3a0b4110a69ab764fc467fd --- /dev/null +++ b/oxalis-extension/oxalis-extension-example/src/main/java/network/oxalis/ext/example/ExampleModule.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.ext.example; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.transmission.TransmissionVerifier; +import network.oxalis.commons.guice.OxalisModule; + +/** + * Guice module where we bind our implementations. + * + * @author erlend + * @since 4.0.1 + */ +@Slf4j +public class ExampleModule extends OxalisModule { + + public ExampleModule() { + log.info("Loaded."); + } + + @Override + protected void configure() { + bindTyped(TransmissionVerifier.class, LoggingTransmissionVerifier.class); + } +} diff --git a/oxalis-extension/oxalis-extension-example/src/main/java/network/oxalis/ext/example/LoggingTransmissionVerifier.java b/oxalis-extension/oxalis-extension-example/src/main/java/network/oxalis/ext/example/LoggingTransmissionVerifier.java new file mode 100644 index 0000000000000000000000000000000000000000..71abea22f345db159220b1d491c70bdd0f162186 --- /dev/null +++ b/oxalis-extension/oxalis-extension-example/src/main/java/network/oxalis/ext/example/LoggingTransmissionVerifier.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.ext.example; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.model.Direction; +import network.oxalis.api.transmission.TransmissionVerifier; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Singleton; + +/** + * This is a simple implementation of {@link TransmissionVerifier} where each message is logged. + * + * @author erlend + * @since 4.0.1 + */ +@Slf4j +@Singleton +@Type("logging") // Name given to the implementation for use in configuration. +public class LoggingTransmissionVerifier implements TransmissionVerifier { + + @Override + public void verify(Header header, Direction direction) { + log.info("Direction: {} | Sender/Receiver: {}/{} | Instance identifier: {}", + direction, + header.getSender().getIdentifier(), + header.getReceiver().getIdentifier(), + header.getIdentifier()); + } +} diff --git a/oxalis-extension/oxalis-extension-example/src/main/resources/reference.conf b/oxalis-extension/oxalis-extension-example/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..c258b75a70f200ea9147d5a3b127afda59ee8538 --- /dev/null +++ b/oxalis-extension/oxalis-extension-example/src/main/resources/reference.conf @@ -0,0 +1,2 @@ +// Making our (Guice) module available to Oxalis. +oxalis.module.ext-example.main.class = network.oxalis.ext.example.ExampleModule diff --git a/oxalis-extension/oxalis-extension-testbed/.gitignore b/oxalis-extension/oxalis-extension-testbed/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..bc910ca20370c4db4bbf0c05f58112b25531eb64 --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/.gitignore @@ -0,0 +1 @@ +*.http \ No newline at end of file diff --git a/oxalis-extension/oxalis-extension-testbed/pom.xml b/oxalis-extension/oxalis-extension-testbed/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..192d34c3a03d8b8166b8f0527eaad9f383e825e0 --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/pom.xml @@ -0,0 +1,77 @@ + + + + oxalis-extension + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + 4.0.0 + + oxalis-extension-testbed + + Oxalis :: Ext :: Testbed connector + + + + + dk.erst.oxalis + oxalis-inbound + + + dk.erst.oxalis + oxalis-outbound + + + + + javax.servlet + javax.servlet-api + provided + + + + + + + org.codehaus.mojo + jaxb2-maven-plugin + 1.6 + + + xjc + + xjc + + + + + UTF-8 + 2.1 + + + + org.codehaus.mojo + properties-maven-plugin + 1.1.0 + + + set-additional-system-properties + + set-system-properties + + + + + + + javax.xml.accessExternalSchema + all + + + ${project.build.outputDirectory}/project.properties + + + + + + \ No newline at end of file diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedConf.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedConf.java new file mode 100644 index 0000000000000000000000000000000000000000..6bf26a3a569497b89120adb24fa1c19d158a0890 --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedConf.java @@ -0,0 +1,22 @@ +package network.oxalis.ext.testbed.v1; + +import network.oxalis.api.settings.DefaultValue; +import network.oxalis.api.settings.Path; +import network.oxalis.api.settings.Title; + +/** + * @author erlend + * @since 4.0.3 + */ +@Title("Testbed") +public enum TestbedConf { + + @Path("oxalis.testbed.v1.password") + @DefaultValue("testbed") + PASSWORD, + + @Path("oxalis.testbed.v1.controller") + @DefaultValue("https://localhost/controller") + CONTROLLER, + +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedErrorTracker.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedErrorTracker.java new file mode 100644 index 0000000000000000000000000000000000000000..00887022d8b3190a0a865db85f3ca436d46e8e1a --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedErrorTracker.java @@ -0,0 +1,26 @@ +package network.oxalis.ext.testbed.v1; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.model.Direction; +import network.oxalis.ext.testbed.v1.jaxb.ErrorType; + +/** + * @author erlend + */ +@Singleton +public class TestbedErrorTracker implements ErrorTracker { + + @Inject + private TestbedSender sender; + + @Override + public String track(Direction direction, Exception e, boolean handled) { + ErrorType error = new ErrorType(); + error.setMessage(e.getMessage()); + sender.send(error); + + return null; + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedFilter.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..8f83f3d4f266f499a1c1cdae12a2839286ae1968 --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedFilter.java @@ -0,0 +1,56 @@ +package network.oxalis.ext.testbed.v1; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author erlend + */ +@Singleton +@Slf4j +public class TestbedFilter extends HttpFilter { + + @Inject + private TestbedSecurity security; + + @Override + protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) + throws IOException, ServletException { + if (req.getHeader("Authorization") == null) { + noAccess(res); + return; + } + + List parts = Stream.of(req.getHeader("Authorization").trim().split("\\s+", 2)) + .map(String::trim) + .collect(Collectors.toList()); + + if (parts.size() != 2 || !parts.get(0).equals("Digest")) { + noAccess(res); + return; + } + + if (!parts.get(1).equals(security.getExpectedAuthorization())) { + noAccess(res); + return; + } + + chain.doFilter(req, res); + } + + private void noAccess(HttpServletResponse res) throws IOException { + res.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + res.getWriter().write("No access."); + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedJaxb.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedJaxb.java new file mode 100644 index 0000000000000000000000000000000000000000..b6dad133220f3d8cc62ef138b6fa90324076406e --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedJaxb.java @@ -0,0 +1,36 @@ +package network.oxalis.ext.testbed.v1; + +import network.oxalis.ext.testbed.v1.jaxb.*; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +/** + * @author erlend + */ +public class TestbedJaxb { + + public static final JAXBContext JAXB_CONTEXT; + + public static final ObjectFactory OBJECT_FACTORY = new ObjectFactory(); + + static { + try { + JAXB_CONTEXT = JAXBContext.newInstance(InformationType.class, OutboundType.class, + OutboundResponseType.class, InboundType.class, ErrorType.class); + } catch (JAXBException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static Marshaller marshaller() throws JAXBException { + return JAXB_CONTEXT.createMarshaller(); + } + + public static Unmarshaller unmarshaller() throws JAXBException { + return JAXB_CONTEXT.createUnmarshaller(); + } + +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedModule.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedModule.java new file mode 100644 index 0000000000000000000000000000000000000000..ff934240daa1cf601719ff251ee84cae1a856d5a --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedModule.java @@ -0,0 +1,29 @@ +package network.oxalis.ext.testbed.v1; + +import com.google.inject.Key; +import com.google.inject.name.Names; +import com.google.inject.servlet.ServletModule; +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.commons.settings.SettingsBuilder; + +/** + * @author erlend + * @since 4.0.3 + */ +public class TestbedModule extends ServletModule { + + @Override + protected void configureServlets() { + SettingsBuilder.with(binder(), TestbedConf.class); + + bind(Key.get(PersisterHandler.class, Names.named("testbed-v1"))) + .to(TestbedPersisterHandler.class); + + bind(Key.get(ErrorTracker.class, Names.named("testbed-v1"))) + .to(TestbedErrorTracker.class); + + serve("/testbed/v1").with(TestbedServlet.class); + filter("/testbed/v1").through(TestbedFilter.class); + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedPersisterHandler.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedPersisterHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..84377fc92e446aa811395e9f203bea70da29ee75 --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedPersisterHandler.java @@ -0,0 +1,63 @@ +package network.oxalis.ext.testbed.v1; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.lang.EvidenceException; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.util.Type; +import network.oxalis.ext.testbed.v1.jaxb.InboundType; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Named; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +/** + * @author erlend + */ +@Singleton +@Type("testbed-v1") +@Slf4j +public class TestbedPersisterHandler implements PersisterHandler { + + @Inject + @Named("rem") + private EvidenceFactory evidenceFactory; + + @Inject + private TestbedSender sender; + + @Override + public Path persist(TransmissionIdentifier transmissionIdentifier, Header header, InputStream inputStream) + throws IOException { + Path path = File.createTempFile("oxalis-testbed-inbound", header.getIdentifier().getIdentifier()).toPath(); + try (OutputStream outputStream = Files.newOutputStream(path)) { + ByteStreams.copy(inputStream, outputStream); + } + return path; + } + + @Override + public void persist(InboundMetadata inboundMetadata, Path payloadPath) throws IOException { + try (InputStream inputStream = Files.newInputStream(payloadPath)) { + InboundType inbound = new InboundType(); + inbound.setTransportProfile(inboundMetadata.getProtocol().getIdentifier()); + inbound.setPayload(ByteStreams.toByteArray(inputStream)); + inbound.setReceipt(ByteStreams.toByteArray(evidenceFactory.write(inboundMetadata))); + sender.send(inbound); + } catch (EvidenceException e) { + log.error(e.getMessage(), e); + } + + Files.delete(payloadPath); + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedSecurity.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedSecurity.java new file mode 100644 index 0000000000000000000000000000000000000000..a41192dd61fe5da168be4330c669d830e3b17f5c --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedSecurity.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2017 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.ext.testbed.v1; + +import com.google.common.hash.Hashing; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import network.oxalis.api.settings.Settings; + +import java.nio.charset.StandardCharsets; + +/** + * @author erlend + */ +@Singleton +public class TestbedSecurity { + + private String expectedAuthorization; + + @Inject + public void init(Settings settings) { + expectedAuthorization = Hashing.sha256() + .hashString(settings.getString(TestbedConf.PASSWORD), StandardCharsets.UTF_8) + .toString(); + + System.out.println(expectedAuthorization); + } + + public String getExpectedAuthorization() { + return expectedAuthorization; + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedSender.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedSender.java new file mode 100644 index 0000000000000000000000000000000000000000..ce1d06fcf7798be17b077ff913c979f188b4cc14 --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedSender.java @@ -0,0 +1,74 @@ +package network.oxalis.ext.testbed.v1; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.settings.Settings; +import network.oxalis.ext.testbed.v1.jaxb.ErrorType; +import network.oxalis.ext.testbed.v1.jaxb.InboundType; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.CloseableHttpClient; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * @author erlend + */ +@Singleton +@Slf4j +public class TestbedSender { + + @Inject + private TestbedSecurity security; + + @Inject + private Settings settings; + + @Inject + private CloseableHttpClient httpClient; + + public void send(InboundType inbound) throws IOException { + try { + HttpPost httpPost = new HttpPost(settings.getString(TestbedConf.CONTROLLER)); + httpPost.setEntity(new ByteArrayEntity(prepareContent(TestbedJaxb.OBJECT_FACTORY.createInbound(inbound)), ContentType.APPLICATION_XML)); + + try (CloseableHttpResponse response = send(httpPost)) { + // No action at the moment. + } + } catch (JAXBException e) { + throw new IOException("Unable to create document to send to testbed controller.", e); + } + } + + public void send(ErrorType error) { + try { + HttpPut httpPut = new HttpPut(settings.getString(TestbedConf.CONTROLLER)); + httpPut.setEntity(new ByteArrayEntity(prepareContent(TestbedJaxb.OBJECT_FACTORY.createError(error)), ContentType.APPLICATION_XML)); + + try (CloseableHttpResponse response = send(httpPut)) { + // No action at the moment. + } + } catch (JAXBException | IOException e) { + log.warn("Unable to send error to testbed controller.", e); + } + } + + private byte[] prepareContent(JAXBElement element) throws JAXBException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + TestbedJaxb.marshaller().marshal(element, baos); + return baos.toByteArray(); + } + + private CloseableHttpResponse send(HttpUriRequest request) throws IOException { + request.addHeader("Authorization", String.format("Digest %s", security.getExpectedAuthorization())); + return httpClient.execute(request); + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedServlet.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..59e75bf30f13517b00533769212d19423d49dd4e --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedServlet.java @@ -0,0 +1,121 @@ +package network.oxalis.ext.testbed.v1; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.outbound.TransmissionMessage; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.outbound.Transmitter; +import network.oxalis.commons.util.OxalisVersion; +import network.oxalis.ext.testbed.v1.jaxb.InformationType; +import network.oxalis.ext.testbed.v1.jaxb.OutboundResponseType; +import network.oxalis.ext.testbed.v1.jaxb.OutboundType; +import network.oxalis.outbound.transmission.TransmissionRequestFactory; +import network.oxalis.vefa.peppol.common.model.TransportProfile; + +import javax.inject.Named; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.JAXBException; +import javax.xml.transform.stream.StreamSource; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author erlend + */ +@Singleton +public class TestbedServlet extends HttpServlet { + + @Inject + private Provider transmissionRequestFactory; + + @Inject + private Provider transmitter; + + @Inject + @Named("rem") + private EvidenceFactory evidenceFactory; + + @Inject + @Named("prioritized") + private List transportProfiles; + + @Inject + private X509Certificate certificate; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + InformationType informationType = new InformationType(); + informationType.setName("Oxalis"); + informationType.setVersion(OxalisVersion.getVersion()); + informationType.setApiVersion("1.0"); + informationType.getTransportProfile().addAll(transportProfiles.stream() + .map(TransportProfile::getIdentifier) + .collect(Collectors.toList())); + informationType.setCertificate(certificate.getEncoded()); + + resp.addHeader("Content-Type", "application/xml;charset=UTF-8"); + TestbedJaxb.marshaller().marshal( + TestbedJaxb.OBJECT_FACTORY.createInformation(informationType), + resp.getWriter()); + } catch (JAXBException | CertificateEncodingException e) { + throw new ServletException(e.getMessage(), e); + } + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + OutboundType outbound = TestbedJaxb.unmarshaller() + .unmarshal(new StreamSource(req.getInputStream()), OutboundType.class) + .getValue(); + + TransmissionMessage transmissionMessage = transmissionRequestFactory.get() + .newInstance(new ByteArrayInputStream(outbound.getPayload())); + + TransmissionResponse transmissionResponse; + if (outbound.getDestination() == null) { + transmissionResponse = transmitter.get() + .transmit(transmissionMessage); + } else { + transmissionResponse = transmitter.get() + .transmit(new TestbedTransmissionRequest(transmissionMessage, outbound.getDestination())); + } + + InputStream evidenceInputStream = evidenceFactory.write(transmissionResponse); + + OutboundResponseType response = new OutboundResponseType(); + response.setReceipt(ByteStreams.toByteArray(evidenceInputStream)); + + resp.addHeader("Content-Type", "application/xml;charset=UTF-8"); + TestbedJaxb.marshaller().marshal( + TestbedJaxb.OBJECT_FACTORY.createOutboundResponse(response), + resp.getWriter()); + } catch (JAXBException e) { + throw new ServletException(e.getMessage(), e); + } catch (Exception e) { + try { + OutboundResponseType response = new OutboundResponseType(); + response.setError(e.getMessage()); + + resp.addHeader("Content-Type", "application/xml;charset=UTF-8"); + TestbedJaxb.marshaller().marshal( + TestbedJaxb.OBJECT_FACTORY.createOutboundResponse(response), + resp.getWriter()); + } catch (JAXBException ex) { + throw new ServletException(ex.getMessage(), ex); + } + } + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedTransmissionRequest.java b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedTransmissionRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..179a6ab8b4470fd89a8d1c65d176baa8b348b85b --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/java/network/oxalis/ext/testbed/v1/TestbedTransmissionRequest.java @@ -0,0 +1,58 @@ +package network.oxalis.ext.testbed.v1; + +import network.oxalis.api.outbound.TransmissionMessage; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.tag.Tag; +import network.oxalis.commons.security.CertificateUtils; +import network.oxalis.ext.testbed.v1.jaxb.DestinationType; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.common.model.TransportProfile; + +import java.io.InputStream; +import java.net.URI; +import java.security.cert.CertificateException; + +/** + * @author erlend + */ +public class TestbedTransmissionRequest implements TransmissionRequest { + + private TransmissionMessage transmissionMessage; + + private Endpoint endpoint; + + public TestbedTransmissionRequest(TransmissionMessage transmissionMessage, DestinationType destination) + throws CertificateException { + this(transmissionMessage, Endpoint.of( + TransportProfile.of(destination.getTransportProfile()), + URI.create(destination.getURI()), + CertificateUtils.parseCertificate(destination.getCertificate()) + )); + } + + public TestbedTransmissionRequest(TransmissionMessage transmissionMessage, Endpoint endpoint) { + this.transmissionMessage = transmissionMessage; + this.endpoint = endpoint; + } + + @Override + public Endpoint getEndpoint() { + return endpoint; + } + + @Override + public Header getHeader() { + return transmissionMessage.getHeader(); + } + + @Override + public InputStream getPayload() { + return transmissionMessage.getPayload(); + } + + @Override + public Tag getTag() { + return transmissionMessage.getTag(); + } +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/resources/reference.conf b/oxalis-extension/oxalis-extension-testbed/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..49cd6622e45d3f5f2f7eb7dfdbc14fa435c5d08c --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/resources/reference.conf @@ -0,0 +1,4 @@ +oxalis.module.ext-testbed.v1 = { + class = network.oxalis.ext.testbed.v1.TestbedModule + enabled = false +} diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/xjb/bindings.xjb b/oxalis-extension/oxalis-extension-testbed/src/main/xjb/bindings.xjb new file mode 100644 index 0000000000000000000000000000000000000000..65b3ca0e304c73c7b91f731dedcf6067bd286970 --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/xjb/bindings.xjb @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/oxalis-extension/oxalis-extension-testbed/src/main/xsd/testbed-v1.xsd b/oxalis-extension/oxalis-extension-testbed/src/main/xsd/testbed-v1.xsd new file mode 100644 index 0000000000000000000000000000000000000000..85ee953754ca8617caaa849ab24f7073b7160c4c --- /dev/null +++ b/oxalis-extension/oxalis-extension-testbed/src/main/xsd/testbed-v1.xsd @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oxalis-extension/pom.xml b/oxalis-extension/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..ca331918a8e4cd920e8458a3fe07046365405efb --- /dev/null +++ b/oxalis-extension/pom.xml @@ -0,0 +1,52 @@ + + + + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + 4.0.0 + + oxalis-extension + pom + + Oxalis :: Ext + + + + + oxalis-extension-example + oxalis-extension-testbed + + + + + dk.erst.oxalis + oxalis-commons + provided + + + + diff --git a/oxalis-inbound/pom.xml b/oxalis-inbound/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..d909dd079c347a4dd54e6e8cd7d662b71bd68d7a --- /dev/null +++ b/oxalis-inbound/pom.xml @@ -0,0 +1,123 @@ + + + + + 4.0.0 + + + dk.erst.oxalis + oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + + oxalis-inbound + + Oxalis :: Core :: Inbound + Component for handling receiving. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + + com.google.guava + guava + + + + joda-time + joda-time + + + + + javax.servlet + javax.servlet-api + provided + + + + + dk.erst.oxalis + oxalis-commons + + + dk.erst.oxalis + oxalis-test + test + + + + + + + com.google.inject.extensions + guice-servlet + + + + + org.bouncycastle + bcmail-jdk15on + + + + + io.opentracing.contrib + opentracing-web-servlet-filter + + + + + + + src/main/resources + true + + + + + org.jacoco + jacoco-maven-plugin + + + + + diff --git a/oxalis-inbound/src/main/java/network/oxalis/inbound/DefaultInboundService.java b/oxalis-inbound/src/main/java/network/oxalis/inbound/DefaultInboundService.java new file mode 100644 index 0000000000000000000000000000000000000000..92ef0912bb123af23b4068c6fff0f04c1383f33a --- /dev/null +++ b/oxalis-inbound/src/main/java/network/oxalis/inbound/DefaultInboundService.java @@ -0,0 +1,27 @@ +package network.oxalis.inbound; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.inbound.InboundService; +import network.oxalis.api.statistics.StatisticsService; + +/** + * @author erlend + * @since 4.0.2 + */ +@Singleton +public class DefaultInboundService implements InboundService { + + private StatisticsService statisticsService; + + @Inject + public DefaultInboundService(StatisticsService statisticsService) { + this.statisticsService = statisticsService; + } + + @Override + public void complete(InboundMetadata inboundMetadata) { + statisticsService.persist(inboundMetadata); + } +} diff --git a/oxalis-inbound/src/main/java/network/oxalis/inbound/InboundModule.java b/oxalis-inbound/src/main/java/network/oxalis/inbound/InboundModule.java new file mode 100644 index 0000000000000000000000000000000000000000..de29d5e578f27d6062af4205abfb692b01988dcc --- /dev/null +++ b/oxalis-inbound/src/main/java/network/oxalis/inbound/InboundModule.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.inbound; + +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.servlet.ServletModule; +import io.opentracing.Tracer; +import io.opentracing.contrib.web.servlet.filter.TracingFilter; +import network.oxalis.api.inbound.InboundService; +import network.oxalis.inbound.servlet.HomeServlet; +import network.oxalis.inbound.servlet.StatusServlet; + +/** + * @author erlend + */ +public class InboundModule extends ServletModule { + + @Override + protected void configureServlets() { + filter("/*").through(TracingFilter.class); + + serve("/").with(HomeServlet.class); + serve("/status").with(StatusServlet.class); + + bind(InboundService.class).to(DefaultInboundService.class); + } + + @Provides + @Singleton + protected TracingFilter getTracingFilter(Tracer tracer) { + return new TracingFilter(tracer); + } +} diff --git a/oxalis-inbound/src/main/java/network/oxalis/inbound/OxalisGuiceContextListener.java b/oxalis-inbound/src/main/java/network/oxalis/inbound/OxalisGuiceContextListener.java new file mode 100644 index 0000000000000000000000000000000000000000..76b0ad2af21b5d18ab906e413112dc49e26c4a68 --- /dev/null +++ b/oxalis-inbound/src/main/java/network/oxalis/inbound/OxalisGuiceContextListener.java @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.inbound; + +import com.google.inject.Injector; +import com.google.inject.servlet.GuiceServletContextListener; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.commons.guice.GuiceModuleLoader; + +/** + * Wires our object graph together using Google Guice. + * + * @author steinar + * Date: 29.11.13 + * Time: 10:26 + * @author erlend + */ +@Slf4j +public class OxalisGuiceContextListener extends GuiceServletContextListener { + + private Injector injector; + + public OxalisGuiceContextListener() { + try { + this.injector = GuiceModuleLoader.initiate(); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new IllegalStateException(e.getMessage(), e); + } + } + + public OxalisGuiceContextListener(Injector injector) { + this.injector = injector; + } + + @Override + public Injector getInjector() { + return injector; + } +} diff --git a/oxalis-inbound/src/main/java/network/oxalis/inbound/servlet/HomeServlet.java b/oxalis-inbound/src/main/java/network/oxalis/inbound/servlet/HomeServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..fbcb16bd8dea5b57255b3869db25aec4a7653488 --- /dev/null +++ b/oxalis-inbound/src/main/java/network/oxalis/inbound/servlet/HomeServlet.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.inbound.servlet; + +import com.google.inject.Singleton; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Singleton +public class HomeServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.setContentType("text/html;charset=UTF-8"); + resp.getWriter().println("\n" + + "\n" + + " \n" + + " \n" + + " Oxalis PEPPOL server\n" + + " \n" + + " \n" + + "

Welcome to the Oxalis PEPPOL server

\n" + + "

The protocols for this Access Point are :

\n" + + "
    \n" + + "
  • The AS4 endpoint can be found here.
  • \n" + + "
\n" + + "

Some status information can be found at status.

\n" + + " \n" + + "\n"); + } +} diff --git a/oxalis-inbound/src/main/java/network/oxalis/inbound/servlet/StatusServlet.java b/oxalis-inbound/src/main/java/network/oxalis/inbound/servlet/StatusServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..4a292829c313e659da526b66e4b69220cbb82851 --- /dev/null +++ b/oxalis-inbound/src/main/java/network/oxalis/inbound/servlet/StatusServlet.java @@ -0,0 +1,98 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.inbound.servlet; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.typesafe.config.Config; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.commons.util.OxalisVersion; +import network.oxalis.vefa.peppol.mode.Mode; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Properties; + +/** + * Servlet returning diagnostic information to ease operation, support and debugging. + * Since this servlet is public accessible, it should NOT contain any sensitive + * information about it's runtime environment. + * + * @author erlend + * @author thore + */ +@Singleton +public class StatusServlet extends HttpServlet { + + private final X509Certificate certificate; + + private final Config config; + + private final Mode mode; + + @Inject + public StatusServlet(X509Certificate certificate, Config config, Mode mode) { + this.certificate = certificate; + this.mode = mode; + this.config = config; + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.setContentType("text/plain"); + + PrintWriter writer = resp.getWriter(); + writer.println("version.oxalis: " + OxalisVersion.getVersion()); + writer.println("version.java: " + System.getProperty("java.version")); + writer.println("mode: " + mode.getIdentifier()); + + if (config.hasPath("lookup.locator.hostname")) { + writer.print("lookup.locator.hostname: "); + writer.println(config.getString("lookup.locator.hostname")); + } + + writer.println("certificate.subject: " + certificate.getSubjectX500Principal().getName()); + writer.println("certificate.issuer: " + certificate.getIssuerX500Principal().getName()); + writer.println("certificate.expired: " + certificate.getNotAfter().before(new Date())); + writer.println("build.id: " + OxalisVersion.getBuildId()); + writer.println("build.tstamp: " + OxalisVersion.getBuildTimeStamp()); + String as4id = "undefined"; + String as4tstamp = "undefined"; + try (InputStream inputStream = OxalisVersion.class.getResourceAsStream("/oxalis-as4-version.properties")) { + Properties properties = new Properties(); + properties.load(inputStream); + as4id = properties.getProperty("as4.build.id"); + as4tstamp = properties.getProperty("as4.build.tstamp"); + } catch (Exception e) { + // probably not an as4 build... + } + writer.println("as4.build.id: " + as4id); + writer.println("as4.build.tstamp: " + as4tstamp); + } +} diff --git a/oxalis-inbound/src/main/resources/logback.xml b/oxalis-inbound/src/main/resources/logback.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5a2f971f2ad609b1b82ea7561aebba61b0b9e9e --- /dev/null +++ b/oxalis-inbound/src/main/resources/logback.xml @@ -0,0 +1,49 @@ + + + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + diff --git a/oxalis-inbound/src/main/resources/reference.conf b/oxalis-inbound/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..89ebd547b6b133662bf820ba15f9e260d50ada00 --- /dev/null +++ b/oxalis-inbound/src/main/resources/reference.conf @@ -0,0 +1,4 @@ +oxalis.module.inbound.servlet.class = network.oxalis.inbound.InboundModule + +# This defaults is necessary as the code in ConfigModule looks for a defaults conf, but since we removed defaults from AS2, we need to add one here, so startup does not fail. From UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported --> +defaults.as2NotSupported=networkAS2NoLongerSupportedInOxalis diff --git a/oxalis-inbound/src/test/java/network/oxalis/inbound/RunJettyServer.java b/oxalis-inbound/src/test/java/network/oxalis/inbound/RunJettyServer.java new file mode 100644 index 0000000000000000000000000000000000000000..1ea45714b3e2d444e930363118c9d5ab2323eed7 --- /dev/null +++ b/oxalis-inbound/src/test/java/network/oxalis/inbound/RunJettyServer.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.inbound; + +import com.google.inject.Injector; +import network.oxalis.test.jetty.AbstractJettyServerTest; +import org.testng.annotations.Test; + +public class RunJettyServer extends AbstractJettyServerTest { + + @Override + public Injector getInjector() { + return new OxalisGuiceContextListener().getInjector(); + } + + @Test(groups = "manual", enabled = false) + public void runServer() throws Exception { + server.join(); + } +} diff --git a/oxalis-inbound/src/test/java/network/oxalis/inbound/servlet/HomeServletTest.java b/oxalis-inbound/src/test/java/network/oxalis/inbound/servlet/HomeServletTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6a9620a0d25c46b83953574a531ab26c51862ea0 --- /dev/null +++ b/oxalis-inbound/src/test/java/network/oxalis/inbound/servlet/HomeServletTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.inbound.servlet; + +import com.google.inject.Injector; +import network.oxalis.inbound.OxalisGuiceContextListener; +import network.oxalis.test.jetty.AbstractJettyServerTest; +import org.testng.Assert; +import org.testng.annotations.Test; + +import javax.servlet.http.HttpServletResponse; +import java.net.HttpURLConnection; +import java.net.URL; + +@Test +public class HomeServletTest extends AbstractJettyServerTest { + + @Override + public Injector getInjector() { + return new OxalisGuiceContextListener().getInjector(); + } + + @Test + public void get() throws Exception { + HttpURLConnection httpURLConnection = + (HttpURLConnection) new URL("http://localhost:8080/").openConnection(); + + Assert.assertEquals(httpURLConnection.getResponseCode(), HttpServletResponse.SC_OK); + } + + @Test + public void post() throws Exception { + HttpURLConnection httpURLConnection = + (HttpURLConnection) new URL("http://localhost:8080/").openConnection(); + httpURLConnection.setRequestMethod("POST"); + + Assert.assertEquals(httpURLConnection.getResponseCode(), HttpServletResponse.SC_METHOD_NOT_ALLOWED); + } +} diff --git a/oxalis-inbound/src/test/java/network/oxalis/inbound/servlet/StatusServletTest.java b/oxalis-inbound/src/test/java/network/oxalis/inbound/servlet/StatusServletTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6533dd654121e3039ff7f429fd2efcc2fdc34830 --- /dev/null +++ b/oxalis-inbound/src/test/java/network/oxalis/inbound/servlet/StatusServletTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.inbound.servlet; + +import com.google.inject.Injector; +import network.oxalis.inbound.OxalisGuiceContextListener; +import network.oxalis.test.jetty.AbstractJettyServerTest; +import org.testng.Assert; +import org.testng.annotations.Test; + +import javax.servlet.http.HttpServletResponse; +import java.net.HttpURLConnection; +import java.net.URL; + +@Test +public class StatusServletTest extends AbstractJettyServerTest { + + @Override + public Injector getInjector() { + return new OxalisGuiceContextListener().getInjector(); + } + + @Test + public void get() throws Exception { + HttpURLConnection httpURLConnection = + (HttpURLConnection) new URL("http://localhost:8080/status").openConnection(); + + Assert.assertEquals(httpURLConnection.getResponseCode(), HttpServletResponse.SC_OK); + } + + @Test + public void post() throws Exception { + HttpURLConnection httpURLConnection = + (HttpURLConnection) new URL("http://localhost:8080/status").openConnection(); + httpURLConnection.setRequestMethod("POST"); + + Assert.assertEquals(httpURLConnection.getResponseCode(), HttpServletResponse.SC_METHOD_NOT_ALLOWED); + } +} diff --git a/oxalis-inbound/src/test/resources/logback-error.xml b/oxalis-inbound/src/test/resources/logback-error.xml new file mode 100644 index 0000000000000000000000000000000000000000..83e8b6081b7383c5eb59fd83bb386dd17b6b5dd0 --- /dev/null +++ b/oxalis-inbound/src/test/resources/logback-error.xml @@ -0,0 +1,41 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + diff --git a/oxalis-inbound/src/test/resources/logback-test.xml b/oxalis-inbound/src/test/resources/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..b383ba8b78ef9d01248d404b96d6ee25ce28e244 --- /dev/null +++ b/oxalis-inbound/src/test/resources/logback-test.xml @@ -0,0 +1,44 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + + + diff --git a/oxalis-inbound/src/test/resources/logback-test2.xml b/oxalis-inbound/src/test/resources/logback-test2.xml new file mode 100644 index 0000000000000000000000000000000000000000..83e8b6081b7383c5eb59fd83bb386dd17b6b5dd0 --- /dev/null +++ b/oxalis-inbound/src/test/resources/logback-test2.xml @@ -0,0 +1,41 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + diff --git a/oxalis-inbound/src/test/resources/oxalis_home/fake-oxalis.conf b/oxalis-inbound/src/test/resources/oxalis_home/fake-oxalis.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-inbound/src/test/resources/oxalis_home/logback-test.xml b/oxalis-inbound/src/test/resources/oxalis_home/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-inbound/src/test/resources/oxalis_home/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-legacy/README.md b/oxalis-legacy/README.md new file mode 100644 index 0000000000000000000000000000000000000000..95256b9f904bad4300f4638df57b4cf637fb4121 --- /dev/null +++ b/oxalis-legacy/README.md @@ -0,0 +1,3 @@ +# Oxalis Legacy + +This folder contains modules provided for convenience even though they are not actively maintained. \ No newline at end of file diff --git a/oxalis-legacy/oxalis-document-sniffer/README.md b/oxalis-legacy/oxalis-document-sniffer/README.md new file mode 100644 index 0000000000000000000000000000000000000000..06f1c2d457c2ae4f40bca5876537a82d03a88541 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/README.md @@ -0,0 +1,6 @@ +# Oxalis Document Sniffer (Legacy) + +This extension contains functionality provided to help users during introduction of SBDH in OpenPEPPOL. + +As the introduction of SBDH is completed, and quite some time has passed, this extension will not receive further updates. +Users may expect this extension and its functionality to be removed from Oxalis as of version 4.2 or 5.0. \ No newline at end of file diff --git a/oxalis-legacy/oxalis-document-sniffer/doc/SchemeAndOrgId.puml b/oxalis-legacy/oxalis-document-sniffer/doc/SchemeAndOrgId.puml new file mode 100644 index 0000000000000000000000000000000000000000..b65be405cf238e81f194e15a45763510dc679e8d --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/doc/SchemeAndOrgId.puml @@ -0,0 +1,64 @@ +@startuml + +package vefa { + enum SchemeId { + schemeId : String + icd : String[4] + + // To be overridden + String formatOrganisationId(String s) + -- + {static}SchemeId: parse() + {static}SchemeId fromISO6523(String code) + } + + class PeppolParticipantId { + String: Icd + String: OrgId + SchemeId: schmeId + .. Constructor ... + PeppolParticipantId(SchemeId s, OrgId o) + -- identical -- + String: getOrganisationId() + String: stringValue() + -- + {static}PeppolParticipantId: valueFor(String orgId) // xxxx:yyyy or Norwegian + {static}boolean: isValidNorwegianOrgNum(String orgNo) + -int: generateOrgNumModulus11(String s) + } + + SchemeId --> PeppolParticipantId +} + +package Oxalis { + enum Oxalis.SchemeId { + schemeId : String + icd : String[4] + + // new + String formatOrganisationId(String s) + -- + {static}SchemeId: parse() + {static}SchemeId fromISO6523(String code) + } + + class ParticipantId { + String: value + .. Constructor .. + ParticipantId(String participantId) + -- Identical -- + String: stringValue() + String: toString() + -- + // Checks for : + {static} boolean isValidParticipantIdentifierSyntax() + + // Verifies syntax and does mod-11 check for Norwegian organisation numbers + {static} boolean isValidParticipantIdentifier(String value) + + {static} boolean isValidNorwegianOrganisationNumber(String org) + } + + ParticipantId --> Oxalis.SchemeId +} +@enduml \ No newline at end of file diff --git a/oxalis-legacy/oxalis-document-sniffer/doc/sbdhparsing.puml b/oxalis-legacy/oxalis-document-sniffer/doc/sbdhparsing.puml new file mode 100644 index 0000000000000000000000000000000000000000..bc2c143042c2fffa6d12fad73d29e681d88a4458 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/doc/sbdhparsing.puml @@ -0,0 +1,35 @@ +@startuml +start +:sbdhFastParser.parse __parsedSbdh__ ; + +partition makeEffectiveSbdh { + :input parsedSBDH? and suppliedHeaderFields?; + if (isOverrideAllowed) then (Yes) + if (supplied sbdh is complete) then (Yes) + :use supplied sbdh; + else (No) + :parsePayloadAndDeduceSbdh + from business data; + :create effective header; + endif + else (No) + :parsePayloadAndDeduceSbdh: + convert parsedSBDH? to PeppolSBDH or parse payload; + :createEffectiveHeader; + endif +} + +partition determineEndPoint { + if (endpoint supplied && override allowed) then (Yes) + :warning; + else + :perform SMP lookup; + :throw exception if override attempted; + endif +} + +:wrap payload with SBDH using +effective Sbdh; + +end +@enduml \ No newline at end of file diff --git a/oxalis-legacy/oxalis-document-sniffer/pom.xml b/oxalis-legacy/oxalis-document-sniffer/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..2bb6631400db653170d49ecbbdcf2254fed9df51 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/pom.xml @@ -0,0 +1,61 @@ + + + + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + ../../pom.xml + + 4.0.0 + + oxalis-document-sniffer + + Oxalis :: Leg :: Document Sniffer (Legacy) + Document sniffer used to generate SBDH for document types. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + dk.erst.oxalis + oxalis-commons + provided + + + dk.erst.oxalis + oxalis-test + test + + + network.oxalis.vefa + peppol-icd + + + + \ No newline at end of file diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/PeppolStandardBusinessHeader.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/PeppolStandardBusinessHeader.java new file mode 100644 index 0000000000000000000000000000000000000000..c4e4f3ba5e40ab9e4b0720dcffe9e6a7db24e4bd --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/PeppolStandardBusinessHeader.java @@ -0,0 +1,215 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer; + +import network.oxalis.sniffer.identifier.InstanceId; +import network.oxalis.sniffer.identifier.PeppolDocumentTypeId; +import network.oxalis.vefa.peppol.common.model.*; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Our representation of the SBDH (Standard Business Document Header), which makes us + * independent of the StandardBusinessDocumentHeader generated by JAXB. Furthermore + * the UN/CEFACT SBDH is kind of awkward to use as some of the elements of interest to us, + * are split into several fields. + * + * @author steinar + * @author thore + */ +public class PeppolStandardBusinessHeader { + + /** + * Peppol Participant Identification for the recipient + */ + private ParticipantIdentifier recipientId; + + /** + * Peppol Participant Identification for the sender + */ + private ParticipantIdentifier senderId; + + /** + * The type of document to send + */ + private DocumentTypeIdentifier peppolDocumentTypeId; + + /** + * The business process this document is a part of + */ + private ProcessIdentifier profileTypeIdentifier; + + /** + * Represents the unique identity of the message envelope. It is not the same as the ID of the + * business message (such as the Invoice number). Nor is it the same as the transmission Message ID + * generated by the application sending the message (as defined in AS2). + *

+ * This messageId is not the same as the "AS2 Message-ID" or the "START message id", which really are + * unique "transmission id's" that should be unique for each transmission. + *

+ * //StandardBusinessDocumentHeader/DocumentIdentification/InstanceIdentifier + */ + private InstanceId instanceId; + + private Date creationDateAndTime; + + /** + * Set the time to current and makes a random TransmissionIdentifier as default + */ + public static PeppolStandardBusinessHeader createPeppolStandardBusinessHeaderWithNewDate() { + PeppolStandardBusinessHeader p = new PeppolStandardBusinessHeader(); + p.setCreationDateAndTime(new Date()); + return p; + } + + /** + * Empty constructor, no defaults - all must be supplied by user + */ + public PeppolStandardBusinessHeader() { + /* intentionally nothing */ + } + + public PeppolStandardBusinessHeader(Header header) { + senderId = header.getSender(); + recipientId = header.getReceiver(); + creationDateAndTime = header.getCreationTimestamp(); + peppolDocumentTypeId = header.getDocumentType(); + profileTypeIdentifier = header.getProcess(); + instanceId = new InstanceId(header.getIdentifier().getIdentifier()); + } + + /** + * Copy constructor + */ + public PeppolStandardBusinessHeader(PeppolStandardBusinessHeader peppolStandardBusinessHeader) { + recipientId = peppolStandardBusinessHeader.getRecipientId(); + senderId = peppolStandardBusinessHeader.getSenderId(); + peppolDocumentTypeId = peppolStandardBusinessHeader.getDocumentTypeIdentifier(); + profileTypeIdentifier = peppolStandardBusinessHeader.getProfileTypeIdentifier(); + instanceId = peppolStandardBusinessHeader.getInstanceId(); + creationDateAndTime = peppolStandardBusinessHeader.getCreationDateAndTime(); + } + + /** + * Do we have enough transport details to send the message? + * + * @return true if transport details are complete. + */ + public boolean isComplete() { + return ((recipientId != null) && + (senderId != null) && + (peppolDocumentTypeId != null) && + (profileTypeIdentifier != null) && + (instanceId != null) && + (creationDateAndTime != null)); + } + + /** + * Returns a list of property names that are still missing. + * + * @return empty list if headers are complete + */ + public List listMissingProperties() { + List mhf = new ArrayList<>(); + if (recipientId == null) mhf.add("recipientId"); + if (senderId == null) mhf.add("senderId"); + if (peppolDocumentTypeId == null) mhf.add("peppolDocumentTypeId"); + if (profileTypeIdentifier == null) mhf.add("profileTypeIdentifier"); + if (instanceId == null) mhf.add("messageId"); + if (creationDateAndTime == null) mhf.add("creationDateAndTime"); + return mhf; + } + + public void setRecipientId(ParticipantIdentifier recipientId) { + this.recipientId = recipientId; + } + + public ParticipantIdentifier getRecipientId() { + return recipientId; + } + + public void setSenderId(ParticipantIdentifier senderId) { + this.senderId = senderId; + } + + public ParticipantIdentifier getSenderId() { + return senderId; + } + + public void setInstanceId(InstanceId instanceId) { + this.instanceId = instanceId; + } + + public InstanceId getInstanceId() { + return instanceId; + } + + public void setCreationDateAndTime(Date creationDateAndTime) { + this.creationDateAndTime = creationDateAndTime; + } + + public Date getCreationDateAndTime() { + return creationDateAndTime; + } + + @Deprecated + public void setDocumentTypeIdentifier(PeppolDocumentTypeId documentTypeIdentifier) { + setDocumentTypeIdentifier(documentTypeIdentifier.toVefa()); + } + + public void setDocumentTypeIdentifier(DocumentTypeIdentifier documentTypeIdentifier) { + this.peppolDocumentTypeId = documentTypeIdentifier; + } + + public DocumentTypeIdentifier getDocumentTypeIdentifier() { + return peppolDocumentTypeId; + } + + public void setProfileTypeIdentifier(ProcessIdentifier processIdentifier) { + this.profileTypeIdentifier = processIdentifier; + } + + public ProcessIdentifier getProfileTypeIdentifier() { + return profileTypeIdentifier; + } + + public Header toVefa() { + PeppolDocumentTypeId documentTypeId = PeppolDocumentTypeId.valueOf(peppolDocumentTypeId.getIdentifier()); + + return Header.of( + senderId, + recipientId, + profileTypeIdentifier, + peppolDocumentTypeId, + instanceId == null ? InstanceIdentifier.generateUUID() : instanceId.toVefa(), + InstanceType.of( + documentTypeId.getRootNameSpace(), + documentTypeId.getLocalName(), + documentTypeId.getVersion() + ), + creationDateAndTime + ); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/SnifferModule.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/SnifferModule.java new file mode 100644 index 0000000000000000000000000000000000000000..e207cd5529871c06adf9207052bb2776e77ded27 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/SnifferModule.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer; + +import network.oxalis.api.transformer.ContentDetector; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.sniffer.document.NoSbdhParser; + +/** + * @author erlend + * @since 4.0.1 + */ +public class SnifferModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(ContentDetector.class, NoSbdhParser.class); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/HardCodedNamespaceResolver.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/HardCodedNamespaceResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..f0bb791e31216e0ffc41390bb86d15371fd58366 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/HardCodedNamespaceResolver.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document; + +import com.google.common.collect.ImmutableMap; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import java.util.Iterator; +import java.util.Map; + +/** + * Namespace resolver hard coded for UBL based documents only. + * + * @author steinar + * @author thore + * @author erlend + */ +public class HardCodedNamespaceResolver implements NamespaceContext { + + private static final Map NAMESPACE_MAP = ImmutableMap.builder() + .put("xsi", "http://www.w3.org/2001/XMLSchema-instance") + .put("cac", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2") + .put("cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2") + .put("ext", "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2") + .build(); + + @Override + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("No prefix provided!"); + } + String uri = NAMESPACE_MAP.get(prefix); + if (uri == null) { + return XMLConstants.NULL_NS_URI; + } else { + return uri; + } + } + + @Override + public String getPrefix(String namespaceURI) { + // Not needed in this context. + return null; + } + + @Override + public Iterator getPrefixes(String namespaceURI) { + // Not needed in this context. + return null; + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/NoSbdhParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/NoSbdhParser.java new file mode 100644 index 0000000000000000000000000000000000000000..61c4937b88f2107ecad3134d9f2d66ab24f26120 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/NoSbdhParser.java @@ -0,0 +1,144 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document; + +import com.google.inject.Singleton; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.transformer.ContentDetector; +import network.oxalis.api.util.Type; +import network.oxalis.sniffer.PeppolStandardBusinessHeader; +import network.oxalis.sniffer.document.parsers.PEPPOLDocumentParser; +import network.oxalis.vefa.peppol.common.model.Header; +import org.w3c.dom.Document; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; +import java.io.InputStream; + +/** + * Parses UBL based documents, which are not wrapped within an SBDH, extracting data and + * creating a PeppolStandardBusinessHeader. + * + * @author steinar + * @author thore + */ +@Slf4j +@Singleton +@Type("legacy") +public class NoSbdhParser implements ContentDetector { + + private static final DocumentBuilderFactory documentBuilderFactory; + + static { + documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + + try { + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to configure DOM parser for secure processing.", e); + } + } + + public NoSbdhParser() { + log.warn("You have enabled support for automatic detection of content. " + + "This functionality will be turned of by default in version 4.1 and removed in version 4.2/5.0. " + + "Use configuration \"oxalis.transformer.detector = noop\" to disable it today."); + } + + /** + * Parses and extracts the data needed to create a PeppolStandardBusinessHeader object. The inputstream supplied + * should not be wrapped in an SBDH. + * + * @param inputStream UBL XML data without an SBDH. + * @return an instance of Header populated with data from the UBL XML document. + */ + @Override + public Header parse(InputStream inputStream) throws OxalisContentException { + return originalParse(inputStream).toVefa(); + } + + /** + * Parses and extracts the data needed to create a PeppolStandardBusinessHeader object. The inputstream supplied + * should not be wrapped in an SBDH. + * + * @param inputStream UBL XML data without an SBDH. + * @return an instance of PeppolStandardBusinessHeader populated with data from the UBL XML document. + */ + public PeppolStandardBusinessHeader originalParse(InputStream inputStream) throws OxalisContentException { + try { + + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document document = documentBuilder.parse(inputStream); + + XPath xPath = XPathFactory.newInstance().newXPath(); + xPath.setNamespaceContext(new HardCodedNamespaceResolver()); + + PeppolStandardBusinessHeader sbdh = PeppolStandardBusinessHeader + .createPeppolStandardBusinessHeaderWithNewDate(); + + // use the plain UBL header parser to decode format and create correct document parser + PlainUBLHeaderParser headerParser = new PlainUBLHeaderParser(document, xPath); + + // make sure we actually have a UBL type document + if (headerParser.canParse()) { + + sbdh.setDocumentTypeIdentifier(headerParser.fetchDocumentTypeId().toVefa()); + sbdh.setProfileTypeIdentifier(headerParser.fetchProcessTypeId()); + + // try to use a specialized document parser to fetch more document details + PEPPOLDocumentParser documentParser = null; + try { + documentParser = headerParser.createDocumentParser(); + } catch (Exception ex) { + /* + allow this to happen so that "unknown" PEPPOL documents still + can be used by explicitly setting sender and receiver thru API + */ + } + /* However, if we found an eligible parser, we should be able to determine the sender and receiver */ + if (documentParser != null) { + try { + sbdh.setSenderId(documentParser.getSender()); + } catch (Exception e) { + // Continue with recipient + } + try { + sbdh.setRecipientId(documentParser.getReceiver()); + } catch (Exception e) { + // Just continue + } + } + } + + return sbdh; + } catch (Exception e) { + throw new OxalisContentException("Unable to parseOld document " + e.getMessage(), e); + } + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/PlainUBLHeaderParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/PlainUBLHeaderParser.java new file mode 100644 index 0000000000000000000000000000000000000000..f8c51a98cf2cebd81f2f02e5225d54d0f5b22219 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/PlainUBLHeaderParser.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document; + +import lombok.extern.slf4j.Slf4j; +import network.oxalis.sniffer.document.parsers.*; +import network.oxalis.sniffer.identifier.CustomizationIdentifier; +import network.oxalis.sniffer.identifier.PeppolDocumentTypeId; +import network.oxalis.vefa.peppol.common.model.ProcessIdentifier; +import org.w3c.dom.Document; + +import javax.xml.xpath.XPath; + +/** + * Parses the common PEPPOL header information, enough to decide document type and profile + * + * @author steinar + * @author thore + * @author arun + */ +@Slf4j +public class PlainUBLHeaderParser extends PlainUBLParser { + + public PlainUBLHeaderParser(Document document, XPath xPath) { + super(document, xPath); + } + + public CustomizationIdentifier fetchCustomizationId() { + String value = retriveValueForXpath("//cbc:CustomizationID"); + return CustomizationIdentifier.valueOf(value); + } + + public ProcessIdentifier fetchProcessTypeId() { + String value = retriveValueForXpath("//cbc:ProfileID"); + return ProcessIdentifier.of(value); + } + + public PeppolDocumentTypeId fetchDocumentTypeId() { + CustomizationIdentifier customizationIdentifier = fetchCustomizationId(); + return new PeppolDocumentTypeId(rootNameSpace(), localName(), customizationIdentifier, ublVersion()); + } + + public PEPPOLDocumentParser createDocumentParser() { + String type = localName(); + log.debug("Creating DocumentParser for type : " + localName()); + // despatch advice scenario + if ("DespatchAdvice".equalsIgnoreCase(type)) return new DespatchAdviceDocumentParser(this); + // catalogue scenario + if ("Catalogue".equalsIgnoreCase(type)) return new CatalogueDocumentParser(this); + // invoice scenario + if ("CreditNote".equalsIgnoreCase(type)) return new InvoiceDocumentParser(this); + if ("Invoice".equalsIgnoreCase(type)) return new InvoiceDocumentParser(this); + if ("Reminder".equalsIgnoreCase(type)) return new InvoiceDocumentParser(this); + // order scenario + if ("Order".equalsIgnoreCase(type)) return new OrderDocumentParser(this); + if ("OrderResponse".equalsIgnoreCase(type)) return new OrderDocumentParser(this); + if ("OrderResponseSimple".equalsIgnoreCase(type)) return new OrderDocumentParser(this); + // application response used by CatalogueResponse, MessageLevelResponse + if ("ApplicationResponse".equalsIgnoreCase(type)) return new ApplicationResponseDocumentParser(this); + // unknown scenario - for now we do not have a backup plan + throw new IllegalStateException("Cannot decide which PEPPOLDocumentParser to use for type " + type); + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/PlainUBLParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/PlainUBLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..85224d18428ebb6343ebdc4647f92e891a3f28d3 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/PlainUBLParser.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; + +/** + * Simple parser that is UBL aware and handles xpath with namespaces. + * + * @author thore + */ +public class PlainUBLParser { + + private final Document document; + + private final XPath xPath; + + public PlainUBLParser(Document document, XPath xPath) { + this.document = document; + this.xPath = xPath; + } + + public String localName() { + return document.getDocumentElement().getLocalName(); + } + + public String rootNameSpace() { + return document.getDocumentElement().getNamespaceURI(); + } + + public String ublVersion() { + return retriveValueForXpath("//cbc:UBLVersionID"); + } + + public boolean canParse() { + return ("" + rootNameSpace()).startsWith("urn:oasis:names:specification:ubl:schema:xsd:"); + } + + public Element retrieveElementForXpath(String s) { + try { + Element element = (Element) xPath.evaluate(s, document, XPathConstants.NODE); + if (element == null) { + throw new IllegalStateException("No element in XPath: " + s); + } + return element; + } catch (XPathExpressionException e) { + throw new IllegalStateException("Unable to evaluate " + s + "; " + e.getMessage(), e); + } + } + + public String retriveValueForXpath(String s) { + try { + String value = xPath.evaluate(s, document); + if (value == null) { + throw new IllegalStateException("Unable to find value for Xpath expr " + s); + } + return value.trim(); + } catch (XPathExpressionException e) { + throw new IllegalStateException("Unable to evaluate " + s + "; " + e.getMessage(), e); + } + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/AbstractDocumentParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/AbstractDocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..9a7587b07e9f3dc56fdbe3c59d5b601142ff8403 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/AbstractDocumentParser.java @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document.parsers; + +import network.oxalis.sniffer.document.PlainUBLParser; +import network.oxalis.sniffer.identifier.ParticipantId; +import network.oxalis.sniffer.identifier.SchemeId; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import org.w3c.dom.Element; + +/** + * Abstract implementation based on the PlainUBLParser to retrieve information from PEPPOL documents. + * Contains common functionality to be used as a base for decoding types. + * + * @author thore + */ +public abstract class AbstractDocumentParser implements PEPPOLDocumentParser { + + protected PlainUBLParser parser; + + public AbstractDocumentParser(PlainUBLParser parser) { + this.parser = parser; + } + + /** + * Retrieves the ParticipantId which is retrieved using the supplied XPath. + */ + protected ParticipantIdentifier participantId(String xPathExpr) { + ParticipantId ret; + + // first we retrieve the correct participant element + Element element; + try { + element = parser.retrieveElementForXpath(xPathExpr); + } catch (Exception ex) { + // DOM parser throws "java.lang.IllegalStateException: No element in XPath: ..." if no Element is found + throw new IllegalStateException(String.format("No ParticipantId found at '%s'.", xPathExpr)); + } + + // get value and any schemeId given + String companyId = element.getFirstChild().getNodeValue().trim(); + String schemeIdTextValue = element.getAttribute("schemeID").trim(); + + // check if we already have a valid participant 9908:987654321 + if (ParticipantId.isValidParticipantIdentifierPattern(companyId)) { + if (schemeIdTextValue.length() == 0) { + // we accept participants with icd prefix if schemeId is missing ... + ret = new ParticipantId(companyId); + } else { + // ... or when given schemeId matches the icd code stat eg NO:VAT matches 9908 from 9908:987654321 + if (companyId.startsWith(SchemeId.parse(schemeIdTextValue).getCode() + ":")) { + ret = new ParticipantId(companyId); + } else { + throw new IllegalStateException(String.format( + "ParticipantId at '%s' is illegal, schemeId '%s' and icd code prefix of '%s' does not match", + xPathExpr, schemeIdTextValue, companyId)); + } + } + } else { + // try to add the given icd prefix to the participant id + companyId = String.format("%s:%s", SchemeId.parse(schemeIdTextValue).getCode(), companyId); + if (!ParticipantId.isValidParticipantIdentifierPattern(companyId)) { + throw new IllegalStateException(String.format( + "ParticipantId syntax at '%s' evaluates to '%s' and is invalid", xPathExpr, companyId)); + } + ret = new ParticipantId(companyId); + } + return ret.toVefa(); + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/ApplicationResponseDocumentParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/ApplicationResponseDocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..b06436e7cd4f09eb2b9e8efb9ed856c7cbdc2531 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/ApplicationResponseDocumentParser.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document.parsers; + +import network.oxalis.sniffer.document.PlainUBLParser; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * Parser to retrieves information from PEPPOL Application Response documents. + * Should be able to decode Catalogue Response, Message Level Response and others based on ApplicationResponse + * + * @author thore + */ +public class ApplicationResponseDocumentParser extends AbstractDocumentParser { + + public ApplicationResponseDocumentParser(PlainUBLParser parser) { + super(parser); + } + + @Override + public ParticipantIdentifier getSender() { + String applicationResponse = "//cac:SenderParty/cbc:EndpointID"; + return participantId(applicationResponse); + } + + @Override + public ParticipantIdentifier getReceiver() { + String applicationResponse = "//cac:ReceiverParty/cbc:EndpointID"; + return participantId(applicationResponse); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/CatalogueDocumentParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/CatalogueDocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..7b77d39b35d76dde437bec8e28d51b7407baa0ec --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/CatalogueDocumentParser.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document.parsers; + +import network.oxalis.sniffer.document.PlainUBLParser; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * Parser to retrieves information from PEPPOL Catalogue scenarios. + * Should be able to decode Catalogue (for catalogue response see ApplicationResponse) + * + * @author thore + */ +public class CatalogueDocumentParser extends AbstractDocumentParser { + + public CatalogueDocumentParser(PlainUBLParser parser) { + super(parser); + } + + @Override + public ParticipantIdentifier getSender() { + String catalogue = "//cac:ProviderParty/cbc:EndpointID"; + return participantId(catalogue); + } + + @Override + public ParticipantIdentifier getReceiver() { + String catalogue = "//cac:ReceiverParty/cbc:EndpointID"; + return participantId(catalogue); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/DespatchAdviceDocumentParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/DespatchAdviceDocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..1b0400f0879e88f35c104050f1d639941fb3433d --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/DespatchAdviceDocumentParser.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document.parsers; + +import network.oxalis.sniffer.document.PlainUBLParser; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * Parser to retrieves information from PEPPOL Despatch Advice scenarios. + * Should be able to decode Despatch Advice document + * + * @author thore + */ +public class DespatchAdviceDocumentParser extends AbstractDocumentParser { + + public DespatchAdviceDocumentParser(PlainUBLParser parser) { + super(parser); + } + + @Override + public ParticipantIdentifier getSender() { + String despatchAdvice = "//cac:DespatchSupplierParty/cac:Party/cbc:EndpointID"; + return participantId(despatchAdvice); + } + + @Override + public ParticipantIdentifier getReceiver() { + String despatchAdvice = "//cac:DeliveryCustomerParty/cac:Party/cbc:EndpointID"; + return participantId(despatchAdvice); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/InvoiceDocumentParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/InvoiceDocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..3786a6433b796a623c85d21eef4df84dcb3e06b7 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/InvoiceDocumentParser.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document.parsers; + +import network.oxalis.sniffer.document.PlainUBLParser; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * Parser to retrieves information from PEPPOL Invoice scenarios. + * Should be able to decode Invoices in plain UBL and Norwegian EHF variants. + * + * @author thore + */ +public class InvoiceDocumentParser extends AbstractDocumentParser { + + public InvoiceDocumentParser(PlainUBLParser parser) { + super(parser); + } + + @Override + public ParticipantIdentifier getSender() { + String endpointFirst = "//cac:AccountingSupplierParty/cac:Party/cbc:EndpointID"; + String companySecond = "//cac:AccountingSupplierParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID"; + ParticipantIdentifier s; + try { + s = participantId(endpointFirst); + } catch (IllegalStateException e) { + s = participantId(companySecond); + } + return s; + } + + @Override + public ParticipantIdentifier getReceiver() { + String endpointFirst = "//cac:AccountingCustomerParty/cac:Party/cbc:EndpointID"; + String companySecond = "//cac:AccountingCustomerParty/cac:Party/cac:PartyLegalEntity/cbc:CompanyID"; + ParticipantIdentifier s; + try { + s = participantId(endpointFirst); + } catch (IllegalStateException e) { + s = participantId(companySecond); + } + return s; + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/OrderDocumentParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/OrderDocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..0df71271c919e300b0d89b852a49e7a9a33cb752 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/OrderDocumentParser.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document.parsers; + +import network.oxalis.sniffer.document.PlainUBLParser; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * Parser to retrieves information from PEPPOL Order scenarios. + * Should be able to decode Order and OrderResponse documents. + * + * @author thore + */ +public class OrderDocumentParser extends AbstractDocumentParser { + + public OrderDocumentParser(PlainUBLParser parser) { + super(parser); + } + + @Override + public ParticipantIdentifier getSender() { + String xpath = "//cac:BuyerCustomerParty/cac:Party/cbc:EndpointID"; + if (parser.localName().startsWith("OrderResponse")) { + // Matches both OrderResponse and OrderResponseSimple + xpath = "//cac:SellerSupplierParty/cac:Party/cbc:EndpointID"; + } + return participantId(xpath); + } + + @Override + public ParticipantIdentifier getReceiver() { + String xpath = "//cac:SellerSupplierParty/cac:Party/cbc:EndpointID"; + if (parser.localName().startsWith("OrderResponse")) { + // Matches both OrderResponse and OrderResponseSimple + xpath = "//cac:BuyerCustomerParty/cac:Party/cbc:EndpointID"; + } + return participantId(xpath); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/PEPPOLDocumentParser.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/PEPPOLDocumentParser.java new file mode 100644 index 0000000000000000000000000000000000000000..69be72617203ee727a9163a70643b60574a9d778 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/document/parsers/PEPPOLDocumentParser.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document.parsers; + +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * A small set of common information we should be able to retrieve from any PEPPOL UBL/EHF document. + * + * @author thore + */ +public interface PEPPOLDocumentParser { + + /** + * Identify and return the PEPPOL participant sending the document. + */ + ParticipantIdentifier getSender(); + + /** + * Identify and return the PEPPOL participant receiving the document. + */ + ParticipantIdentifier getReceiver(); + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/CustomizationIdentifier.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/CustomizationIdentifier.java new file mode 100644 index 0000000000000000000000000000000000000000..3d1d21c3562f615467aee729f7da131c9308b28e --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/CustomizationIdentifier.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import java.io.Serializable; + +/** + * Represents a PEPPOL Customization Identifier contained within a PEPPOL Document Identifier. + * + * @author Steinar Overbeck Cook steinar@sendregning.no + * @author Thore Johnsen thore@sendregning.no + * + * @see "PEPPOL Policy for use of identifiers v3.0 of 2014-02-03" + */ +public class CustomizationIdentifier implements Serializable { + + private String value; + + public CustomizationIdentifier(String customizationIdentifier) { + if (customizationIdentifier != null) customizationIdentifier = customizationIdentifier.trim(); + this.value = customizationIdentifier; + } + + public static CustomizationIdentifier valueOf(String s) { + return new CustomizationIdentifier(s); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CustomizationIdentifier that = (CustomizationIdentifier) o; + return value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public String toString() { + return value; + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/InstanceId.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/InstanceId.java new file mode 100644 index 0000000000000000000000000000000000000000..3110e5c7c59b5c14a586ac5ac60cb24beb9e5e63 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/InstanceId.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import network.oxalis.vefa.peppol.common.model.InstanceIdentifier; + +import java.util.UUID; + +/** + * Represents the Instance Identifier used in the SBDH. + * + * @author steinar + * Date: 21.11.2016 + * Time: 09.22 + */ +public class InstanceId implements java.io.Serializable { + + + private final String value; + + /** Creates new InstanceId with random UUID */ + public InstanceId() { + value = UUID.randomUUID().toString(); + } + + /** Creates new InstanceId with supplied value */ + public InstanceId(String value) { + this.value = value; + } + + + @Override + public String toString() { + return value; + } + + public InstanceId valueOf(String value) { + return new InstanceId(value); + } + + public InstanceIdentifier toVefa() { + return InstanceIdentifier.of(value); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/ParticipantId.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/ParticipantId.java new file mode 100644 index 0000000000000000000000000000000000000000..19de83748746d824f35beeb4f8fe341a673d9986 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/ParticipantId.java @@ -0,0 +1,175 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import network.oxalis.sniffer.lang.InvalidPeppolParticipantException; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import network.oxalis.vefa.peppol.icd.api.Icd; + +import java.io.Serializable; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Steinar Overbeck Cook + * @author Thore Johnsen + * @see SchemeId + */ +public class ParticipantId implements Serializable { + + private static final Pattern ISO6523_PATTERN = Pattern.compile("^(\\d{4}):([^\\s]+)$"); + + //max length for international organisation number + private static final int INTERNATION_ORG_ID_MAX_LENGTH = 50; + + // Holds the textual representation of this PEPPOL participant id + private final String value; + + /** + * Constructs a new instance based upon a match of the following patterns : + *

    + *
  1. {@code xxxx:yyyyyy} - i.e. a 4 digit ICD followed by a ':' followed by the organisationID
  2. + *
  3. AB999999999 - i.e. a prefix of at least two characters followed by something
  4. + *
+ * + * @param participantId participant Id represented as a string + * @throws InvalidPeppolParticipantException if we are unable to recognize the input as a PEPPOL participant ID + */ + public ParticipantId(String participantId) { + value = parse(participantId); + } + + /** + * Uses combination of SchemeId and Organisation identifier to create new instance. + * The Organisation identifier is validated in accordance with the rules of the scheme. + * + * @param schemeId + * @param organisationId + */ + public ParticipantId(final Icd schemeId, final String organisationId) { + + if (schemeId == null) { + throw new IllegalArgumentException("SchemeId must be specified with a a valid ISO6523 code."); + } + + if (organisationId == null) { + throw new IllegalArgumentException("The organisation id must be specified."); + } + + if (organisationId.length() > INTERNATION_ORG_ID_MAX_LENGTH) { + throw new IllegalArgumentException(String.format( + "Invalid organisation id. '%s' is longer than %d characters" + , organisationId, INTERNATION_ORG_ID_MAX_LENGTH)); + } + + // Formats the organisation identifier in accordance with what PEPPOL expects. + value = String.format("%s:%s", schemeId.getCode(), organisationId); + } + + /** + * Parses the input string assuming it represents an organisation number or PEPPOL participant identifier in one + * of these forms: + *
    + *
  1. icd +':' + organisation identifier
  2. + *
  3. National organisation number with at least two character prefix.
  4. + *
+ *

+ * After parsing, the organisation identifier is validated in accordance with the rules of the scheme a + * validator is found. + *

+ * + * @param participantId the string representing the participant identifier or organisation identifier + * @return a string on the form [ISO6523 ICD]:[participantId]; + */ + static String parse(final String participantId) throws InvalidPeppolParticipantException { + String organisationId = participantId.trim().replaceAll("\\s", ""); // Squeezes out any white spaces + Icd schemeId = null; + + Matcher matcher = ISO6523_PATTERN.matcher(organisationId); + + if (!matcher.matches()) + throw new InvalidPeppolParticipantException(String.format("ICD not found in '%s'.", participantId)); + + // If the representation is in the form xxxx:yyyyyyyyy, we are good + String icd = matcher.group(1); + organisationId = matcher.group(2); + + try { + schemeId = SchemeId.fromISO6523(icd); // Locates the associated scheme + } catch (IllegalArgumentException e) { + // No action. + } + + if (schemeId == null) + throw new InvalidPeppolParticipantException("ICD " + icd + " is unknown"); + + // Constructs the textual representation of the PEPPOL participant identifier + return String.format("%s:%s", schemeId.getCode(), organisationId); + } + + + /** + * Parses the provided participant identifier into a validated instance + * of {@link ParticipantId} + * + * @param participantId The organisation number as xxxx:yyyy or just an organisation number + * @return validated instance of Participant Id + */ + public static ParticipantId valueOf(String participantId) { + return new ParticipantId(parse(participantId.trim())); + + } + + /** + * Simple syntax verifier, verifies icd prefix + code + */ + public static boolean isValidParticipantIdentifierPattern(String value) { + if (value == null) return false; + + Matcher matcher = ISO6523_PATTERN.matcher(value); + return matcher.find(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ParticipantId that = (ParticipantId) o; + return Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + + @Override + public String toString() { + return value; + } + + public ParticipantIdentifier toVefa() { + return ParticipantIdentifier.of(value, ParticipantIdentifier.DEFAULT_SCHEME); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/PeppolDocumentTypeId.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/PeppolDocumentTypeId.java new file mode 100644 index 0000000000000000000000000000000000000000..4cd0c6f3e651206bebc96c4e75a93311c356603c --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/PeppolDocumentTypeId.java @@ -0,0 +1,141 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import network.oxalis.vefa.peppol.common.model.DocumentTypeIdentifier; + +import java.io.Serializable; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represents a type safe PEPPOL Document Identifier, textually represented thus: + *

+ *

+ *     {@literal ::##::}
+ * 
+ * + * @author Steinar Overbeck Cook + * @author Thore Johnsen + * @see "PEPPOL Policy for use of identifiers v3.0 of 2014-02-03" + */ +public class PeppolDocumentTypeId implements Serializable { + + private final String rootNameSpace; + + private final String localName; + + private final CustomizationIdentifier customizationIdentifier; + + private final String version; + + /** + *
+     *     <root NS>::<document element local name>##<customization id>::<version>
+     * 
+ */ + static Pattern documentIdPattern = Pattern.compile("(.*)::(.*)##(.*)::(.*)"); + + public PeppolDocumentTypeId(String rootNameSpace, String localName, + CustomizationIdentifier customizationIdentifier, String version) { + this.rootNameSpace = rootNameSpace; + this.localName = localName; + this.customizationIdentifier = customizationIdentifier; + this.version = version; + } + + /** + * Parses the supplied text string into the separate components of a PEPPOL Document Identifier. + * + * @param documentIdAsText textual representation of a document identifier. + * @return type safe instance of DocumentTypeIdentifier + */ + public static PeppolDocumentTypeId valueOf(String documentIdAsText) { + if (documentIdAsText == null) + throw new NullPointerException("Value 'null' is not a valid document type identifier."); + + Matcher matcher = documentIdPattern.matcher(documentIdAsText.trim()); + if (matcher.matches()) { + String rootNameSpace = matcher.group(1); + String localName = matcher.group(2); + String customizationIdAsText = matcher.group(3); + String version = matcher.group(4); + CustomizationIdentifier customizationIdentifier = CustomizationIdentifier.valueOf(customizationIdAsText); + return new PeppolDocumentTypeId(rootNameSpace, localName, customizationIdentifier, version); + } else + throw new IllegalArgumentException( + String.format("Unable to parseOld '%s' into PEPPOL Document Type Identifier", documentIdAsText)); + } + + /** + * Provides a textual representation of this document type identifier + * + * @return textual value. + */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append(rootNameSpace); + sb.append("::").append(localName); + sb.append("##").append(customizationIdentifier); + sb.append("::").append(version); + return sb.toString(); + } + + public String getRootNameSpace() { + return rootNameSpace; + } + + public String getLocalName() { + return localName; + } + + public CustomizationIdentifier getCustomizationIdentifier() { + return customizationIdentifier; + } + + public String getVersion() { + return version; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PeppolDocumentTypeId that = (PeppolDocumentTypeId) o; + return Objects.equals(rootNameSpace, that.rootNameSpace) && + Objects.equals(localName, that.localName) && + Objects.equals(customizationIdentifier, that.customizationIdentifier) && + Objects.equals(version, that.version); + } + + @Override + public int hashCode() { + return Objects.hash(rootNameSpace, localName, customizationIdentifier, version); + } + + public DocumentTypeIdentifier toVefa() { + return DocumentTypeIdentifier.of(toString()); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/SchemeId.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/SchemeId.java new file mode 100644 index 0000000000000000000000000000000000000000..8ca5efecb36ec9ff89423a00addf23facf59bb88 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/identifier/SchemeId.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import network.oxalis.vefa.peppol.icd.Icds; +import network.oxalis.vefa.peppol.icd.api.Icd; +import network.oxalis.vefa.peppol.icd.code.PeppolIcd; + +/** + * Provides a binding between the attributes schemeAgencyId and the corresponding ISO6523 prefix (ICD). + * The ENUM is taken from Policy for use of Identifiers version 3.0 dated 2014-02-03. + * The ICD's should be 4 digits, a list can be found : http://www.oid-info.com/doc/ICD-list.pdf + *

+ * Possible improvements are: + *

    + *
  • Add an attribute with the literal prefix of the organisation identifiers for each scheme. + * This would make it easier to identify which scheme an organisation identifier belongs to. This could be + * combined with a regexp
  • + *
+ * + * @author andy + * @author steinar + * @author thore + */ +public class SchemeId { + + private static final Icds ICDS = Icds.of(PeppolIcd.values()); + + /** + * Tries to find the Party id with the given schemeId + * e.g. "ES:VAT" --> ES_VAT + * + * @param schemeId textual representation of scheme, i.e. NO:ORGNR + * @return instance of SchemeId if found + * @throws IllegalStateException if not found, i.e. unknown scheme + */ + public static Icd parse(String schemeId) { + return ICDS.findByIdentifier(schemeId); + } + + /** + * Tries to find the Party id from the ISO652 code + * e.g. "9919" --> AT_KUR + * + * @param code + * @return the scheme id if found null otherwise. + */ + public static Icd fromISO6523(String code) { + return ICDS.findByCode(code); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/lang/InvalidPeppolParticipantException.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/lang/InvalidPeppolParticipantException.java new file mode 100644 index 0000000000000000000000000000000000000000..6d158ab115f12e355c7f0f2fb7c7e3027b42442f --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/lang/InvalidPeppolParticipantException.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.lang; + +import network.oxalis.api.lang.OxalisRuntimeException; + +/** + * @author steinar + * Date: 09.11.2016 + * Time: 20.09 + */ +public class InvalidPeppolParticipantException extends OxalisRuntimeException { + + public InvalidPeppolParticipantException(String s) { + super(s); + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/sbdh/SbdhWrapper.java b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/sbdh/SbdhWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..b9d40fd3d3cf8a8d3a7f1f95e5a8ac4730c9615b --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/java/network/oxalis/sniffer/sbdh/SbdhWrapper.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.sbdh; + +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.sbdh.SbdWriter; +import network.oxalis.vefa.peppol.sbdh.util.XMLStreamUtils; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +/** + * Takes a document and wraps it together with headers into a StandardBusinessDocument. + *

+ * The SBDH part of the document is constructed from the headers. + * The document will be the payload (xs:any) following the SBDH. + * + * @author thore + * @author steinar + * @author erlend + */ +public class SbdhWrapper { + + /** + * Wraps payload + headers into a StandardBusinessDocument + * + * @param inputStream the input stream to be wrapped + * @param headers the headers to use for sbdh + * @return byte buffer with the resulting output in utf-8 + */ + public byte[] wrap(InputStream inputStream, Header headers) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + try (SbdWriter sbdWriter = SbdWriter.newInstance(baos, headers)) { + XMLStreamUtils.copy(inputStream, sbdWriter.xmlWriter()); + } catch (Exception ex) { + throw new IllegalStateException("Unable to wrap document inside SBD (SBDH). " + ex.getMessage(), ex); + } + + return baos.toByteArray(); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/main/resources/reference.conf b/oxalis-legacy/oxalis-document-sniffer/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..2cf612f1ab957fabd9ede9ba4f73ffac06712909 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/main/resources/reference.conf @@ -0,0 +1 @@ +oxalis.module.document-sniffer.sniffer.class = network.oxalis.sniffer.SnifferModule diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/document/NoSbdh2PeppolHeaderParserTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/document/NoSbdh2PeppolHeaderParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..064d6854fc321492d0f4e46f87f6da950ce1e75b --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/document/NoSbdh2PeppolHeaderParserTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document; + +import network.oxalis.sniffer.PeppolStandardBusinessHeader; +import network.oxalis.test.identifier.PeppolDocumentTypeIdAcronym; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import org.testng.annotations.Test; + +import java.io.InputStream; + +import static org.testng.Assert.*; + +/** + * @author steinar + * Date: 05.11.13 + * Time: 15:14 + */ +public class NoSbdh2PeppolHeaderParserTest { + + @Test + public void sniffDocumentWithoutSBDH() throws Exception { + InputStream resourceAsStream = getClass().getResourceAsStream("/ehf-invoice-no-sbdh.xml"); + assertNotNull(resourceAsStream); + + NoSbdhParser sniffer = new NoSbdhParser(); + PeppolStandardBusinessHeader sbdh = sniffer.originalParse(resourceAsStream); + + assertNotNull(sbdh.getDocumentTypeIdentifier()); + assertNotNull(sbdh.getCreationDateAndTime()); + assertNull(sbdh.getInstanceId(), "InstanceId should not be parsed from EHF invoice with no SBDH"); + assertNotNull(sbdh.getProfileTypeIdentifier()); + assertNotNull(sbdh.getRecipientId()); + assertNotNull(sbdh.getSenderId()); + + assertEquals(sbdh.getSenderId(), ParticipantIdentifier.of("9908:991974466")); + assertEquals(sbdh.getRecipientId(), ParticipantIdentifier.of("9908:889640782")); + + assertEquals( + sbdh.getDocumentTypeIdentifier(), + PeppolDocumentTypeIdAcronym.EHF_INVOICE.toVefa() + ); + + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/document/NoSbdhParserTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/document/NoSbdhParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6366291505a1da2cfe8e199f5c03b89f73998f0f --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/document/NoSbdhParserTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.document; + +import network.oxalis.sniffer.PeppolStandardBusinessHeader; +import org.testng.annotations.Test; + +import java.io.InputStream; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * @author soc + */ +public class NoSbdhParserTest { + + @Test + public void verifyCorrectParsingOfReceiver() throws Exception { + + InputStream resourceAsStream = getClass().getResourceAsStream("/issue250/Issue250-sample-invoice.xml"); + assertNotNull(resourceAsStream, "Test resource not found"); + + NoSbdhParser p = new NoSbdhParser(); + PeppolStandardBusinessHeader peppolStandardBusinessHeader = p.originalParse(resourceAsStream); + String receiver = peppolStandardBusinessHeader.getRecipientId().getIdentifier(); + + assertEquals("9954:111111111", receiver); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/CustomizationIdentifierTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/CustomizationIdentifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c246eb0ca4a3279633c45afbf8e917530d520be2 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/CustomizationIdentifierTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +/* Created by steinar on 20.05.12 at 12:14 */ + +package network.oxalis.sniffer.identifier; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Steinar Overbeck Cook steinar@sendregning.no + */ +public class CustomizationIdentifierTest { + + @Test + public void parseEhfKreditNota() { + CustomizationIdentifier.valueOf("urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixx:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1"); + } + + @Test + public void parseApplicationResponse() { + final String s = "urn:www.cenbii.eu:transaction:biicoretrdm057:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0"; + CustomizationIdentifier customizationIdentifier = CustomizationIdentifier.valueOf(s); + assertEquals(customizationIdentifier.toString(), s); + } + + @Test + public void equalsTest() { + final String s = "urn:www.cenbii.eu:transaction:biicoretrdm057:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0"; + CustomizationIdentifier c1 = CustomizationIdentifier.valueOf(s); + CustomizationIdentifier c2 = CustomizationIdentifier.valueOf(s); + + assertEquals(c1, c2); + } + + @Test + public void valueOfEqualsAndEquals() throws Exception { + String value = "aamund var her"; + CustomizationIdentifier customizationIdentifier = CustomizationIdentifier.valueOf(value); + assertEquals(customizationIdentifier.toString(), value); + + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/DocumentTypeIdentifierTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/DocumentTypeIdentifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2cf33f9ff788224c48ceb64a1c1fb2da1d91d121 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/DocumentTypeIdentifierTest.java @@ -0,0 +1,196 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; + +/** + * @author Steinar Overbeck Cook steinar@sendregning.no + */ +public class DocumentTypeIdentifierTest { + + @Test + public void testValueOf() { + String documentIdAsText = + "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse" + + "##urn:www.cenbii.eu:transaction:biicoretrdm057:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0" + + "::2.0"; + PeppolDocumentTypeId documentTypeIdentifier = PeppolDocumentTypeId.valueOf(documentIdAsText); + assertEquals(documentTypeIdentifier.toString(), documentIdAsText); + + assertEquals(documentTypeIdentifier.getRootNameSpace(), + "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2"); + assertEquals(documentTypeIdentifier.getLocalName(), "ApplicationResponse"); + assertEquals(documentTypeIdentifier.getCustomizationIdentifier(), CustomizationIdentifier.valueOf( + "urn:www.cenbii.eu:transaction:biicoretrdm057:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0")); + assertEquals(documentTypeIdentifier.getVersion(), "2.0"); + } + + @Test + public void equals() { + String s = "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixx:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1" + + "::2.0"; + String s2 = "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixx:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1" + + "::3.0"; + + PeppolDocumentTypeId d1 = PeppolDocumentTypeId.valueOf(s); + PeppolDocumentTypeId d2 = PeppolDocumentTypeId.valueOf(s); + + PeppolDocumentTypeId d3 = PeppolDocumentTypeId.valueOf(s2); + assertEquals(d1, d2); + + assertNotEquals(d1, d3); + } + + /** + * Verifies the Tender document + */ + @Test + public void tender() { + PeppolDocumentTypeId tender = new PeppolDocumentTypeId( + "urn:oasis:names:specification:ubl:schema:xsd:Tender-2", + "Tender", + new CustomizationIdentifier("urn:www.cenbii.eu:transaction:biitrdm090:ver3.0") + , "2.1"); + assertEquals("urn:oasis:names:specification:ubl:schema:xsd:Tender-2::Tender" + + "##urn:www.cenbii.eu:transaction:biitrdm090:ver3.0" + + "::2.1", tender.toString()); + } + + @Test + public void testLotsOfExpectedPeppolDocumentTypeIds() { + + // These are known to be in use and should be parsable without errors + String[] documentIdentifiers = { + // BIS and EHF + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol4a:ver1.0" + + "#urn:www.difi.no:ehf:faktura:ver1" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Reminder-2::Reminder" + + "##urn:www.cenbii.eu:transaction:biicoretrdm017:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixy:ver1.0" + + "#urn:www.difi.no:ehf:purring:ver1" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order" + + "##urn:www.cenbii.eu:transaction:biicoretrdm001:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol3a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol4a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm015:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixy:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:OrderResponseSimple-2::OrderResponseSimple" + + "##urn:www.cenbii.eu:transaction:biicoretrdm003:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2::Catalogue" + + "##urn:www.cenbii.eu:transaction:biicoretrdm019:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:OrderResponseSimple-2::OrderResponseSimple" + + "##urn:www.cenbii.eu:transaction:biicoretrdm002:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm015:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixy:ver1.0" + + "#urn:www.difi.no:ehf:faktura:ver1" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixx:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse" + + "##urn:www.cenbii.eu:transaction:biicoretrdm057:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order" + + "##urn:www.cenbii.eu:transaction:biicoretrdm001:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2::ApplicationResponse" + + "##urn:www.cenbii.eu:transaction:biicoretrdm058:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "::2.0", + // NESUBL + "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##NESUBL-2.0" + + "::2.0", + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##NESUBL-2.0" + + "::2.0", + // OIOUBL + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##OIOUBL-2.02" + + "::2.0" + }; + + for (String s : documentIdentifiers) { + PeppolDocumentTypeId d = PeppolDocumentTypeId.valueOf(s); + assertEquals(d.toString(), s); + } + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/LocaleTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/LocaleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..56db5ba6435a40234ab7939876e7a011e7755548 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/LocaleTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import lombok.extern.slf4j.Slf4j; +import org.testng.annotations.Test; + +import java.util.Locale; + +/** + * @author steinar + * Date: 09.11.2016 + * Time: 18.09 + */ +@Slf4j +public class LocaleTest { + + @Test + public void whatIsDefaultLocale() { + Locale aDefault = Locale.getDefault(); + log.info("Default locale, country: " + aDefault.getCountry()); + } + + @Test + public void test() { + String[] strings = {"NO:ORGNR", "DUNS"}; + for (String s : strings) { + String[] split = s.split(":"); + log.info(split[0]); + } + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/ParticipantIdTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/ParticipantIdTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d97bf29cda39b5e4f399fffb19301d7ed69098c2 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/ParticipantIdTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import network.oxalis.sniffer.lang.InvalidPeppolParticipantException; +import org.testng.annotations.Test; + +/** + * User: andy + * Date: 4/11/12 + * Time: 11:19 AM + */ +public class ParticipantIdTest { + + @Test + public void testSample() { + ParticipantId.valueOf("9908:810018909"); + + } + + @Test(expectedExceptions = {InvalidPeppolParticipantException.class}) + public void testInvalidScheme() { + ParticipantId.valueOf("0001:976098897"); + } + + @Test(expectedExceptions = InvalidPeppolParticipantException.class) + public void testOrgIdWithNoDigits() { + ParticipantId.valueOf("sender"); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/PeppolParticipantIdTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/PeppolParticipantIdTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bf4fed4b6fe8860d3d30f83ac5998912d813dc55 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/PeppolParticipantIdTest.java @@ -0,0 +1,169 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import network.oxalis.sniffer.lang.InvalidPeppolParticipantException; +import network.oxalis.vefa.peppol.icd.code.PeppolIcd; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import static org.testng.Assert.*; + +/** + * @author andy + * @author thore + */ +public class PeppolParticipantIdTest { + + // ZZZ is not allowed in PEPPOL Network. + @Test(enabled = false) + public void testFoedselsnummerWhichCouldBeUsedByDigitalMultiKanal() { + + // multikanal uses fødselsnummer + ParticipantId p1 = ParticipantId.valueOf("9999:42342342343"); + assertNotNull(p1); + + // multikanal uses orgnumbers + assertNotNull(ParticipantId.valueOf("9999:968218743")); + + } + + @Test + public void testParsePeppolParticpantId() throws Exception { + + ParticipantId no976098897 = ParticipantId.valueOf("9908:976098897"); + assertEquals(no976098897, new ParticipantId(PeppolIcd.NO_ORGNR, "976098897")); + + no976098897 = ParticipantId.valueOf("9908:976098897"); + assertEquals(no976098897, new ParticipantId(PeppolIcd.NO_ORGNR, "976098897")); + + no976098897 = ParticipantId.valueOf("9901:976098897"); + assertEquals(no976098897, new ParticipantId(PeppolIcd.DK_CPR, "976098897")); + + //invalid iso code will not be parsed. + try { + ParticipantId.valueOf("0001:976098897"); + fail("Invalid scheme should not result in a participant instance"); + } catch (Exception e) { + + } + + } + + /** + * Tests that when using value of we get null with invalid norwegian organisation numbers + */ + @Test() + public void testIsValidValueOf() { + + + assertNotNull(ParticipantId.valueOf("9908:968218743")); + + assertNotNull(ParticipantId.valueOf("9908:NO976098897MVA")); + + assertNotNull(ParticipantId.valueOf("9908:NO 976098897 MVA")); + + assertNotNull(ParticipantId.valueOf("9908:976098897 MVA")); + + assertNotNull(ParticipantId.valueOf("9908:976098897MVA")); + + + } + + @Test(expectedExceptions = {InvalidPeppolParticipantException.class}) + public void invalidOrganisationNumbers() { + // Not a valid orgNo + assertNotNull(ParticipantId.valueOf("968218743")); + + // not valid + assertNull(ParticipantId.valueOf("123456789")); + assertNull(ParticipantId.valueOf("986532933")); + assertNull(ParticipantId.valueOf("986532952")); + assertNull(ParticipantId.valueOf("986532954")); + assertNull(ParticipantId.valueOf("986532955")); + assertNotNull(ParticipantId.valueOf("988890081")); + + assertNotNull(ParticipantId.valueOf("968 218 743")); + + // null + assertNull(ParticipantId.valueOf((String) null)); + + // empty String + assertNull(ParticipantId.valueOf("")); + } + + @Test + public void testOrganistaionId() throws Exception { + ParticipantId.valueOf("9908:968218743"); + } + + @Test + public void testOrgNumWithSpaces() throws Exception { + ParticipantId.valueOf("9908:968 218 743"); + + ParticipantId.valueOf("99 08:9682 18743"); + + ParticipantId.valueOf("00 07:9682 18743"); + } + + + @Test + public void testSerialize() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(out); + ObjectInputStream ois = null; + try { + final ParticipantId expectedParticipantId = ParticipantId.valueOf("9908:976098897"); + + oos.writeObject(expectedParticipantId); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ois = new ObjectInputStream(in); + + final ParticipantId peppolParticipantId = (ParticipantId) ois.readObject(); + assertEquals(peppolParticipantId, expectedParticipantId); + } finally { + oos.close(); + if (ois != null) { + ois.close(); + } + } + + + assertTrue(out.toByteArray().length > 0); + } + + + @Test(enabled = false) + public void testSRO3079() throws Exception { + + ParticipantId peppolParticipantId = ParticipantId.valueOf("9147:91723"); + assertNotNull(peppolParticipantId); + + peppolParticipantId = ParticipantId.valueOf("9957:61394"); + assertNotNull(peppolParticipantId); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/SchemeIdTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/SchemeIdTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a05c530c629c5a096b56bfcf78ccc37a85e7bdea --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/identifier/SchemeIdTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.identifier; + +import network.oxalis.vefa.peppol.icd.api.Icd; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author steinar + * Date: 10.11.2016 + * Time: 11.54 + */ +public class SchemeIdTest { + + @Test + public void testBelgianCrossroadBankOfEnterprises() throws Exception { + Icd sid = SchemeId.parse("BE:CBE"); + assertEquals(sid.getIdentifier(), "BE:CBE"); + assertEquals(sid.getCode(), "9956"); + assertEquals(SchemeId.fromISO6523("9956"), sid); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/sbdh/ParseSbdhTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/sbdh/ParseSbdhTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4ddfba0993686610c505bea7f306768de125d7b5 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/sbdh/ParseSbdhTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.sbdh; + +import network.oxalis.peppol.sbdh.jaxb.DocumentIdentification; +import network.oxalis.peppol.sbdh.jaxb.StandardBusinessDocument; +import org.testng.annotations.Test; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Unmarshaller; +import java.io.File; +import java.io.FileInputStream; +import java.net.URL; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +/** + * @author steinar + * Date: 23.10.13 + * Time: 14:51 + * + * @author aaron-kumar + * @since 5.0.0 + */ +public class ParseSbdhTest { + + @Test(enabled = false) + public void testParseSbdh() throws Exception { + JAXBContext jaxbContext = JAXBContext.newInstance("org.unece.cefact.namespaces.standardbusinessdocumentheader"); + + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + + URL resource = ParseSbdhTest.class.getClassLoader().getResource("peppol-bis-invoice-sbdh.xml"); + assertNotNull(resource); + + File file = new File(resource.toURI()); + assertTrue(file.isFile() && file.canRead()); + + FileInputStream fileInputStream = new FileInputStream(file); + + // Parses the entire XML document + //noinspection unchecked + JAXBElement sbdh = (JAXBElement) unmarshaller.unmarshal(fileInputStream); + assertNotNull(sbdh); + + StandardBusinessDocument standardBusinessDocument = sbdh.getValue(); + DocumentIdentification documentIdentification = standardBusinessDocument + .getStandardBusinessDocumentHeader().getDocumentIdentification(); + assertNotNull(documentIdentification); + + String type = standardBusinessDocument.getStandardBusinessDocumentHeader() + .getBusinessScope().getScope().get(0).getType(); + String instanceIdentifier = standardBusinessDocument.getStandardBusinessDocumentHeader() + .getBusinessScope().getScope().get(0).getInstanceIdentifier(); + + System.out.println(type); + System.out.println(instanceIdentifier); + } +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/sbdh/SbdhWrapperTest.java b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/sbdh/SbdhWrapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bfd49aec63e269d8b3707a286bd4af02c3e79744 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/java/network/oxalis/sniffer/sbdh/SbdhWrapperTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.sniffer.sbdh; + +import network.oxalis.api.header.HeaderParser; +import network.oxalis.commons.header.SbdhHeaderParser; +import network.oxalis.vefa.peppol.common.model.Header; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; + +import static org.testng.Assert.*; + +/** + * @author steinar + * @author thore + */ +public class SbdhWrapperTest { + + private static final HeaderParser PARSER = new SbdhHeaderParser(); + + @Test + public void testWrapWithHeaders() throws Exception { + + // parseOld header from an existing file + URL resource = ParseSbdhTest.class.getClassLoader().getResource("peppol-bis-invoice-sbdh.xml"); + assertNotNull(resource); + File file = new File(resource.toURI()); + assertTrue(file.isFile() && file.canRead()); + Header header = PARSER.parse(new FileInputStream(file)); + + // wrap a new document in sbdh using the same header + InputStream resourceAsStream = SbdhWrapperTest.class.getClassLoader().getResourceAsStream("ehf-invoice-no-sbdh.xml"); + assertNotNull(resourceAsStream); + SbdhWrapper sbdhWrapper = new SbdhWrapper(); + byte[] wrap = sbdhWrapper.wrap(resourceAsStream, header); + + // just print the wrapped document for visual debugging + // String s = new String(wrap, "UTF-8"); + // System.out.println(s); + + // validate that header from result document matches the original + Header resultHeaders = PARSER.parse(new ByteArrayInputStream(wrap)); + assertEquals(resultHeaders.getSender(), header.getSender()); + assertEquals(resultHeaders.getReceiver(), header.getReceiver()); + assertEquals(resultHeaders.getDocumentType(), header.getDocumentType()); + assertEquals(resultHeaders.getProcess(), header.getProcess()); + // assertEquals(resultHeaders.getInstanceId(), header.getInstanceId()); + // assertEquals(resultHeaders.getCreationDateAndTime(), header.getCreationDateAndTime()); + + } + +} diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/resources/ehf-invoice-no-sbdh.xml b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/ehf-invoice-no-sbdh.xml new file mode 100644 index 0000000000000000000000000000000000000000..cafbc9aff063b36ccab7881fd40227d1ca02227f --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/ehf-invoice-no-sbdh.xml @@ -0,0 +1,289 @@ + + + + + + + 2.0 + + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1 + + urn:www.cenbii.eu:profile:bii04:ver1.0 + 3456 + 2013-11-05 + Levering: NAV HMS Nord-Trøndelag - Kikrkegata 2 C - 7600 Levanger + NOK + + 1671018 + + + + 9908:991974466 + + Comfort Audio AS + + + Postboks 304 + SANDEFJORD + 3201 + + NO + + + + 991974466MVA + + + VAT + + + + Comfort Audio AS + 991974466 + + + 3462 + 95987910 + alexander.delgado@comfortaudio.com + + + + + + 9908:889640782 + + 10019 + + + NAV Økonomitjeneste + + + Sognefjordveien 56 + LEIKANGER + 6863 + + NO + + + + NAV Økonomitjeneste + 889640782 + + + SRA4711 + + + + + 2013-11-05 + + + Sognefjordveien 56 + LEIKANGER + 6863 + + NO + + + + + + 31 + 2013-12-05 + + 60210741723 + + + + + 4105.00 + + 16420.00 + 4105.00 + + S + 25.00 + + VAT + + + + + + 16420.00 + 16420.00 + 20525.00 + 0.00 + 20525.00 + + + + 1 + 1.00 + 5890.00 + + Comfort Digisystem DM10 (HMS nr. 160723) + + F00209 + + + S + 25.00 + + VAT + + + + + 5890.00 + + + + + 2 + 1.00 + 425.00 + + Veske Digisystem (HMS nr. 161381) + + F00493 + + + S + 25.00 + + VAT + + + + + 425.00 + + + + + 3 + 1.00 + 190.00 + + Nettadapter A11 1-2 enheter (HMS nr. 161752) + + F00359 + + + S + 25.00 + + VAT + + + + + 190.00 + + + + + 4 + 1.00 + 1795.00 + + Hodebøylemikrofon (HMS nr. 161759) + + F00243 + + + S + 25.00 + + VAT + + + + + 1795.00 + + + + + 5 + 2.00 + 950.00 + + Ladestativ DM/DH (HMS nr. 161760) + + F00254 + + + S + 25.00 + + VAT + + + + + 475.00 + + + + + 6 + 1.00 + 7170.00 + + Comfort Digisystem DM90 m/BT (HMS nr. 193853) + + F00684 + + + S + 25.00 + + VAT + + + + + 7170.00 + + + diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/resources/issue250/Issue250-sample-invoice-with-sbdh.xml b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/issue250/Issue250-sample-invoice-with-sbdh.xml new file mode 100644 index 0000000000000000000000000000000000000000..d79fe22f124a0b42ecd32937b829d113f2b35ae9 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/issue250/Issue250-sample-invoice-with-sbdh.xml @@ -0,0 +1,185 @@ + + + + 1.0 + + 9908:XXXXXX + + + 9908:222222222 + + + XXXXXX + 2.0 + XXXXXX + Invoice + XXXXXX-05-03T11:25:25.026+05:30 + + + + DOCUMENTID + XXXXXX + + + PROCESSID + XXXXXX + + + + + 2.0 + XXXXXX + XXXXXX + XXXXXX + XXXXXX-04-24 + 380 + NOK + + XXXXXX + XXXXXX + + + + + XXXXXX + + + XXXXXX + + + XXXXXX + + XXXXXX + XXXXXX + + XXXXXX + + + + XXXXXX + + XXXXXX + + + + XXXXXX + XXXXXX + + + XXXXXX + XXXXXX + XXXXXX + + + + + + 9954:XXXXXX + + XXXXXX + + + XXXXXX + + + XXXXXX + + XXXXXX + XXXXXX + + XXXXXX + + + + XXXXXX + + XXXXXX + + + + XXXXXX + XXXXXX + + + XXXXXX + XXXXXX + + + + + XXXXXX-04-25 + + XXXXXX + + XXXXXX + XXXXXX + XXXXXX + + XXXXXX + + + + + + XXXXXX + XXXXXX-05-24 + XXXXXX- + + XXXXXX + + + + XXXXXX + + + XXXXXX + + XXXXXX + XXXXXX + + S + XXXXXX + + XXXXXX + + + + + + XXXXXX + XXXXXX + XXXXXX + XXXXXX + + + 10 + 1.000 + XXXXXX + + XXXXXX + XXXXXX + XXXXXX + + + XXXXXX + + + XXXXXX + + XXXXXX + + + S + XXXXXX + + XXXXXX + + + + + XXXXXX + + + + \ No newline at end of file diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/resources/issue250/Issue250-sample-invoice.xml b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/issue250/Issue250-sample-invoice.xml new file mode 100644 index 0000000000000000000000000000000000000000..b1648ed7d8a11aadd3f8e65433afcfa0731efe88 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/issue250/Issue250-sample-invoice.xml @@ -0,0 +1,158 @@ + + + + 2.0 + XXXXXXX + XXXXXXX + XXXXXXX + XXXXXXX-04-24 + 380 + NOK + + XXXXXXXXXXXXXX + XXXXXXX + + + + + XXXXX + + + sdasdasda + + + sdfsdfasdad + + asadad + asda + + XX + + + + dfreddewdd + + XXX + + + + Olafsen Engros AS + 981588347 + + + XXXXXXX + XXXXXXX + XXXXXXX + + + + + + 9954:111111111 + + XXXXXXX + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + + XXXXXXX + + XXXXXXX + XXXXXXX + + XXXXXXX + + + + XXXXXXX + + XXXXXXX + + + + XXXXXXX + 222222222 + + + XXXXXXX + XXXXXXXXXXXXXX + + + + + XXXXXXX-04-25 + + XXXXXXXXXXXXXX + + XXXXXXXXXXXXXX + XXXXXXX + XXXXXXX + + XXXXXXX + + + + + + XXXXXXX + XXXXXXX-05-24 + XXXXXXX- + + XXXXXXX + + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXX + + + XXXXXXX.55 + + XXXXXXX.18 + XXXXXXX.55 + + S + XXXXXXX.0 + + XXXXXXX + + + + + + XXXXXXX.XX + XXXXXXX.XX + XXXXXXX.XX + XXXXXXX.XX + + + XX + XX.000 + XXXXXXX.XX + + XXXXXXX + XXXXXXX + XXXXXXX + + + XXXXXXX + + + XXXXXXX + + XXXXXXX + + + S + XXXXXXX.0 + + XXXXXXX + + + + + XXXXXXX + + + \ No newline at end of file diff --git a/oxalis-legacy/oxalis-document-sniffer/src/test/resources/peppol-bis-invoice-sbdh.xml b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/peppol-bis-invoice-sbdh.xml new file mode 100644 index 0000000000000000000000000000000000000000..5939bb626fd49f84fb0abf0d130dfb15c3b1f063 --- /dev/null +++ b/oxalis-legacy/oxalis-document-sniffer/src/test/resources/peppol-bis-invoice-sbdh.xml @@ -0,0 +1,150 @@ + + + + 1.0 + + 0007:5567125082 + + + 0007:4455454480 + + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + 2.0 + 1070e7f0-3bae-11e3-aa6e-0800200c9a66 + Invoice + 2013-02-19T05:10:10 + + + + DOCUMENTID + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0 + + + PROCESSID + urn:www.cenbii.eu:profile:bii04:ver1.0 + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 1 + 2012-06-08 + 380 + 2012-06-08 + SEK + SOPE + + + + 5567125082 + + + Ecru Consulting + + + Gamla Brogatan + 29 + Stockholm + 11120 + + SE + + + + SE556712508201 + + VAT + + + + 810418052 + + + Martin + Forsberg + + + + + + + 4455454480 + + + EKONOMISTYRNINGSVERKET (NATIONAL FINANCIAL MANAGEMENT AUTHORITY) + + + 45316 + EFFEKTIV ADMINISTRATION + STOCKHOLM + 104 30 + + SE + + + + 976098897 + + + 08 - 123456 + 08-123457 + infomail@esv.se + + + SOREN + PEDERSEN + + + + + 31 + 2012-06-23 + + 5955559 + + + BGABSESS + + + + + + 0.25 + + 1 + 0.25 + + S + 25 + + VAT + + + + + + 1 + 1 + 1.25 + 1.25 + + + 1 + 1 + 1 + + 1 + + + TEST AV PEPPOL-FAKTURA + + + 1 + 1 + + + + diff --git a/oxalis-legacy/oxalis-persistence/.gitignore b/oxalis-legacy/oxalis-persistence/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..249cda967c11bb62c8affe06d18f26bc5b5f3af0 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/.gitignore @@ -0,0 +1 @@ +/data \ No newline at end of file diff --git a/oxalis-legacy/oxalis-persistence/doc/persistence-component.puml b/oxalis-legacy/oxalis-persistence/doc/persistence-component.puml new file mode 100644 index 0000000000000000000000000000000000000000..caf6cce2230798ff175a1ec98140766d0458b6d2 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/doc/persistence-component.puml @@ -0,0 +1,18 @@ +@startuml + +package "RepositoryModule" { + interface DataSource + interface Repository + interface JdbcTxManager + Repository -> JdbcTxManager + JdbcTxManager -> DataSource + +} + +interface OxalisDataSourceFactory +interface GlobalConfiguration + +RepositoryModule -> GlobalConfiguration +RepositoryModule -> OxalisDataSourceFactory + +@enduml \ No newline at end of file diff --git a/oxalis-legacy/oxalis-persistence/pom.xml b/oxalis-legacy/oxalis-persistence/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e1ea96e8862ed346cfa69ebdf978d1f99900df5 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/pom.xml @@ -0,0 +1,115 @@ + + + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + ../../pom.xml + + 4.0.0 + + oxalis-persistence + jar + + Oxalis :: Leg :: Persistence + Persistence layer of the Oxalis application. Holds code related to DataSource + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + org.apache.commons + commons-dbcp2 + + + commons-logging + commons-logging + + + + + + + org.slf4j + slf4j-api + + + org.slf4j + jcl-over-slf4j + + + ch.qos.logback + logback-classic + provided + + + + + dk.erst.oxalis + oxalis-commons + + + dk.erst.oxalis + oxalis-test + test + + + + com.google.inject + guice + + + + com.h2database + h2 + + + org.hsqldb + hsqldb + test + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + + diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/annotation/Repository.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/annotation/Repository.java new file mode 100644 index 0000000000000000000000000000000000000000..5b117a018c4f04048c3a84b44a84515ec11d6e34 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/annotation/Repository.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.annotation; + +import network.oxalis.persistence.aop.RepositoryConnectionMethodInterceptor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates to Google Guice where that the java class is a Repository. + * This enables us to automatically fetch the connection before a method is invoked. + * + * Only works for methods that are public, package-private or protected (https://github.com/google/guice/wiki/AOP) + * + * @see RepositoryConnectionMethodInterceptor + * + * User: andy + * Date: 1/19/12 + * Time: 12:03 PM + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface Repository { + +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/annotation/Transactional.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/annotation/Transactional.java new file mode 100644 index 0000000000000000000000000000000000000000..b0fef157d2bc3842fa7bd944d65c1d836eb41ef4 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/annotation/Transactional.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.annotation; + +import network.oxalis.persistence.aop.TransactionalMethodInterceptor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates to Google Guice that the method specified should be handled within a transaction + * + * Only works for methods that are public, package-private or protected (https://github.com/google/guice/wiki/AOP) + * + * @see TransactionalMethodInterceptor + * + * User: andy + * Date: 1/19/12 + * Time: 12:03 PM + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface Transactional { + +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/JdbcTxManagerImpl.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/JdbcTxManagerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..1a02fb598dd94d758f3089c47ef028c8718411d9 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/JdbcTxManagerImpl.java @@ -0,0 +1,268 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.aop; + + +import com.google.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.persistence.api.JdbcTxManager; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * Implementation of a transaction manager, which is responsible + * for handling a Connection object which is placed into ThreadLocal. + *

+ * It is responsible for fetching Connection objects from a DataSource, and setting + * them up so that they can be transactional (autoCommit --> false). + *

+ * It also can be used to rollback programatically an existing transaction. + */ +@Slf4j +public class JdbcTxManagerImpl implements JdbcTxManager { + + private static int instances = 0; + + /** + * Used to track problems with multiple instances being created. + */ + private int id; + + /** + * Stores a thread local copy of the current connection + */ + private final ThreadLocal threadLocalJdbcTransaction = new ThreadLocal<>(); + + private final DataSource dataSource; + + @Inject + public JdbcTxManagerImpl(DataSource dataSource) { + if (dataSource == null) { + throw new IllegalArgumentException("DataSource not supplied in constructor"); + } + this.id = instances; + instances++; + trace("new instance"); + this.dataSource = dataSource; + } + + @Override + public boolean isTransaction() { + + try { + final Connection connection = getThreadLocalConnection(); + return connection != null && !connection.getAutoCommit(); + } catch (SQLException e) { + throw new IllegalStateException("Unable to check if a transaction has been started", e); + } + } + + @Override + public boolean isConnection() { + final Connection connection = getThreadLocalConnection(); + return connection != null; + } + + @Override + public void newConnection(boolean autoCommit) { + + try { + //only allowed to create a new transaction if the old one is commited. + if (isTransaction()) { + final String message = "Unable to start a new transaction existing connection is not commited"; + trace(message); + throw new IllegalStateException(message); + } + + //fetches the connection from the datasource. + final Connection connection = dataSource.getConnection(); + + //sets whether or not the connection should autocommit. + connection.setAutoCommit(autoCommit); + + //adds the connection to the current thread + final JdbcTransaction jdbcTransaction = new JdbcTransaction(connection); + threadLocalJdbcTransaction.set(jdbcTransaction); + + } catch (SQLException e) { + final String message = "Unable to get a connection from the provided datasource"; + trace(message); + throw new IllegalStateException(message, e); + } + } + + @Override + public void commit() { + + try { + if (!isTransaction()) { + final String message = "Unable to commit transaction connection, no transaction exists"; + trace(message); + throw new IllegalStateException(message); + } + + final JdbcTransaction jdbcTransaction = threadLocalJdbcTransaction.get(); + //if the transaction has been marked for rollback, rollback the transaction. + if (jdbcTransaction.isRollback()) { + trace("Not commiting - Transaction marked for rollback"); + rollback(); + } else { + //Commits the transaction... connection cannot be null as the isTransaction method tests for that + trace("Commiting transaction"); + jdbcTransaction.getConnection().commit(); + } + + } catch (SQLException e) { + final String message = "Unable to commit the transaction"; + trace(message); + throw new IllegalStateException(message, e); + } + } + + @Override + public void rollback() { + try { + if (!isTransaction()) { + final String message = "Unable to rollback transaction, no transaction exists"; + trace(message); + throw new IllegalStateException(message); + } + getThreadLocalConnection().rollback(); + } catch (SQLException e) { + final String message = "Unable to rollback the transaction"; + trace(message); + throw new IllegalStateException(message, e); + } + } + + @Override + public void cleanUp() { + try { + //closes the connection + final Connection connection = getThreadLocalConnection(); + if (connection != null) { + trace("closing connection"); + connection.close(); + } + } catch (SQLException e) { + final String message = "Unable to close the connection"; + trace(message); + throw new IllegalStateException(message, e); + } finally { + //Essential that we remove the reference to thread local to avoid memory leaks + trace("Removing transaction manager"); + threadLocalJdbcTransaction.set(null); + threadLocalJdbcTransaction.remove(); // Ensures we don't get memory leaks + } + } + + /** + * Gets the connection + * + * @return + */ + @Override + public Connection getConnection() { + final Connection connection = getThreadLocalConnection(); + if (connection == null) { + final String message = "Unable to get the connection. Did you forget to annotate the method with @Transactional or the repository with @Repository?"; + trace(message); + throw new IllegalStateException(message); + } + try { + if (connection.isClosed()) { + throw new IllegalStateException("Connection is closed!"); + } + } catch (SQLException e) { + throw new IllegalStateException("Unable to inspect connection: " + e.getMessage(), e); + } + return connection; + } + + /** + * marks the transaction to be rollbacked + */ + @Override + public void setRollbackOnly() { + final JdbcTransaction jdbcTransaction = threadLocalJdbcTransaction.get(); + if (jdbcTransaction == null) { + final String message = "Unable to mark the transaction as rollbackOnly. Did you forget to annotate the method with @Transactional or the repository with @Repository?"; + trace(message); + throw new IllegalStateException(message); + } + trace("Transaction marked for rollback"); + jdbcTransaction.setRollback(true); + } + + /** + * Helper method for null safe fetching of the JDBC Connection. + * + * @return + */ + private Connection getThreadLocalConnection() { + final JdbcTransaction jdbcTransaction = threadLocalJdbcTransaction.get(); + return jdbcTransaction == null ? null : jdbcTransaction.getConnection(); + } + + /** + * logs a debug message with the current transaction object + * + * @param message + */ + @Override + public void trace(String message) { + if (log.isDebugEnabled()) { + JdbcTransaction jdbcTransaction = threadLocalJdbcTransaction.get(); + final String transaction = jdbcTransaction == null ? "" : ("" + jdbcTransaction.hashCode()); + log.debug(String.format("Trace %s:%s\t>>\t%s", id, transaction, message)); + } + } + + /** + * Helper class that holds a Connection object and whether or not the transaction should be rolled back. + */ + private class JdbcTransaction { + + private final Connection connection; + + private boolean rollback = false; + + private JdbcTransaction(Connection connection) { + this.connection = connection; + } + + public Connection getConnection() { + return connection; + } + + public void setRollback(boolean rollback) { + this.rollback = rollback; + } + + public boolean isRollback() { + return rollback; + } + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/RepositoryConnectionMethodInterceptor.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/RepositoryConnectionMethodInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..4d7ac76a0f0e984ae10021ab6408cb89c8b26b99 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/RepositoryConnectionMethodInterceptor.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.aop; + +import com.google.inject.Inject; +import network.oxalis.persistence.annotation.Transactional; +import network.oxalis.persistence.api.JdbcTxManager; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +/** + * Looks for all @Repository annotations and makes a database connection available to the + * methods within the repository. + *

+ * User: andy + * Date: 8/13/12 + * Time: 2:19 PM + */ +public class RepositoryConnectionMethodInterceptor implements MethodInterceptor { + + @Inject + private JdbcTxManager jdbcTxManager; + + /** + * Starts a jdbc transaction if a transaction doesnt already exist. + * Joins the transaction if one exists + * + * @param invocation the method invocation joinpoint + * @return the result of the call to {@link + * org.aopalliance.intercept.Joinpoint#proceed()}, might be intercepted by the + * interceptor. + * @throws Throwable if the interceptors or the + * target-object throws an exception. + */ + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + + //Ignore the call if the current method is annotated with Transactional + if (invocation.getMethod().isAnnotationPresent(Transactional.class)) { + jdbcTxManager.trace(String.format( + "Ignoring method %s because it is annotated with Transactional", + invocation.getMethod().toGenericString())); + return invocation.proceed(); + } + + //if there is already a connection do nothing as the connection will be cleaned up elsewhere + if (jdbcTxManager.isConnection()) { + // just continue + jdbcTxManager.trace("Using existing connection for method " + invocation.getMethod().getName()); + return invocation.proceed(); + } + + + // Commits/rollbacks the transaction + try { + jdbcTxManager.newConnection(true); + jdbcTxManager.trace("Fetched connection from datasource"); + + return invocation.proceed(); + } finally { + //Essential that we clean up + jdbcTxManager.cleanUp(); + } + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/TransactionalMethodInterceptor.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/TransactionalMethodInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..d75e746b1e878f3139a26a67cba474852cf35207 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/aop/TransactionalMethodInterceptor.java @@ -0,0 +1,103 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.aop; + +import com.google.inject.Inject; +import network.oxalis.persistence.api.JdbcTxManager; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +/** + * Looks for all @Transactional annotations and injects code for starting and stopping transactions. + *

+ * User: andy + * Date: 8/13/12 + * Time: 2:19 PM + */ +public class TransactionalMethodInterceptor implements MethodInterceptor { + + @Inject + private JdbcTxManager jdbcTxManager; + + /** + * Starts a jdbc transaction if a transaction doesnt already exist. + * Joins the transaction if one exists. + * + * @param invocation the method invocation joinpoint + * @return the result of the call to {@link + * org.aopalliance.intercept.Joinpoint#proceed()}, might be intercepted by the + * interceptor. + * @throws Throwable if the interceptors or the + * target-object throws an exception. + * IllegalStateException if there already exists a connection which is not transactional + */ + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + + //we need to find out whether or not there is an existing transaction or an existing Connection + final boolean transaction = jdbcTxManager.isTransaction(); + final boolean connection = jdbcTxManager.isConnection(); + + //If there is a transaction running do nothing as the transaction will be cleaned up by the + //code which created the transaction + if (transaction) { + //tx already exists so continues operation. + jdbcTxManager.trace(String.format("Transaction already exists so not starting a new one when calling method: %s", invocation.getMethod().getName())); + return invocation.proceed(); + } + + //If there is a connection we have decided that this is an error because it means that + //a non transactional method in a repository is calling a transactional method elsewhere. + //which we believe is BAD DESIGN. (It would be possible to implement using a separate variable + //for the transactional connection if we ever change our minds ;)) + if (connection) { + throw new IllegalStateException("Unable to start a transaction, there already exists a connection which is not transactional" + invocation.getMethod().getName()); + } + + try { + // Starts the transaction by setting the autocommit value to be false on the connection. + jdbcTxManager.newConnection(false); + jdbcTxManager.trace("Started new transaction due to annotation on method: " + invocation.getMethod().getName()); + //makes the call to the method that is being wrapped. + Object returnValue = invocation.proceed(); + + // Tries to commit the transaction. + // it is still possible that the TxManager will rollback the transaction, + // but as far as we are concerned our code worked as expected + jdbcTxManager.commit(); + + //returns the result of the wrapped method call + return returnValue; + } catch (Throwable thr) { + //if an exception is thrown we need to rollback the transaction. + jdbcTxManager.trace("Rolling back transaction due to exception: " + thr.getMessage()); + jdbcTxManager.rollback(); + jdbcTxManager.trace("Rolling back transaction ok"); + //rethrows the exception so that it can be handled by the calling code + throw thr; + } finally { + //Essential that we clean up as we are placing connections on thread local + jdbcTxManager.cleanUp(); + } + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/DataSourceProvider.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/DataSourceProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..182f71dadd43ecb6ed654e610bb51c48ca66154a --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/DataSourceProvider.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.api; + +import javax.sql.DataSource; + +/** + * @author steinar + * Date: 18.04.13 + * Time: 13:43 + */ +public interface DataSourceProvider { + + DataSource getDataSource(); + +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/JdbcTxManager.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/JdbcTxManager.java new file mode 100644 index 0000000000000000000000000000000000000000..80defbad390626743ab65f6f55817319a81378f3 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/JdbcTxManager.java @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.api; + +import java.sql.Connection; + +/** + * Manages JDBC transactions. + * + * Provides access to the connection object which is automagically fetched + * as long as the the method is in a class annotated with @Repository or + * the method is annotated with @Transactional + * The connection is stored in ThreadLocal + * + * User: andy + * Date: 8/9/12 + * Time: 1:23 PM + */ +public interface JdbcTxManager { + + /** + * Checks whether the current connection is not null and autocomit is set to false. + * @return + */ + boolean isTransaction(); + + /** + * Checks if the current connection is null. + * @return + */ + boolean isConnection(); + + /** + * N.B. DO NOT USE THIS METHOD DIRECTLY. It is only to be used by the TransactionalMethodInterceptor + * and the RepositoryConnectionMethodInterceptor + * + * Makes a Connection object available from the getConnection() method with either autocomit set to true or false. + * + * @param autoCommit automatically commits after each execute. Set to false to use transactions. + */ + void newConnection(boolean autoCommit); + + /** + * Commits the current connection + * Requires that the existing connection was created with autocommit set to false. + */ + void commit(); + + /** + * Rollbacks the current connection + */ + void rollback(); + + /** + * Closes the connection and removes the connection from the thread local + */ + void cleanUp(); + + /** + * Gets the connection that is currently being used. + * @return + */ + Connection getConnection(); + + /** + * Marks the transaction for rollback when completing. + * The connection will always be rolled back even when an exception does not occur. + */ + void setRollbackOnly(); + + + void trace(String message); +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/Platform.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/Platform.java new file mode 100644 index 0000000000000000000000000000000000000000..681d9c8a521c6b4efbc9f28cfbe44c41a8caa211 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/api/Platform.java @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.api; + +import network.oxalis.api.inject.NamedImpl; + +import javax.inject.Named; + +/** + * @author erlend + */ +public interface Platform { + + boolean detect(String identifier); + + String getIdentifier(); + + default Named getNamed() { + return new NamedImpl(getIdentifier()); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/datasource/DbcpDataSourceProvider.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/datasource/DbcpDataSourceProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..283fbecdeee4a5387d17d2feb63605259abb71c4 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/datasource/DbcpDataSourceProvider.java @@ -0,0 +1,142 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.datasource; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.name.Named; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.filesystem.ClassLoaderUtils; +import network.oxalis.persistence.util.PersistenceConf; +import org.apache.commons.dbcp2.*; +import org.apache.commons.pool2.impl.GenericObjectPool; + +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.sql.DataSource; +import java.nio.file.Path; +import java.sql.Driver; +import java.util.Properties; + +/** + * Given a set configuration parameters represented by {@link Settings}, this class will + * provide a DataSource wrapped in a DataSource pool. + *

+ * Relies upon Guice to make sure provided DataSource is threated as a singleton. + * + * @author steinar + * Date: 18.04.13 + * Time: 13:28 + * @author erlend + */ +@Slf4j +public class DbcpDataSourceProvider implements Provider { + + private final Settings settings; + + private final Path homeFolder; + + @Inject + public DbcpDataSourceProvider(Settings settings, @Named("home") Path homeFolder) { + this.settings = settings; + this.homeFolder = homeFolder; + + log.info("DataSource: {} ", settings.getString(PersistenceConf.JDBC_CONNECTION_URI)); + } + + /** + * Creates a DataSource with connection pooling as provided by Apache DBCP + * + * @return a DataSource + */ + public DataSource get() { + + log.debug("Configuring DataSource wrapped in a Database Connection Pool, using custom loader"); + + Path jdbcDriverClassPath = settings.getPath(PersistenceConf.DRIVER_PATH, homeFolder); + + log.debug("Loading JDBC Driver with custom class path: " + jdbcDriverClassPath); + // Creates a new class loader, which will be used for loading our JDBC driver + ClassLoader classLoader = ClassLoaderUtils.initiate(jdbcDriverClassPath); + + String className = settings.getString(PersistenceConf.DRIVER_CLASS); + String connectURI = settings.getString(PersistenceConf.JDBC_CONNECTION_URI); + + // Loads the JDBC Driver in a separate class loader + Driver driver = getJdbcDriver(classLoader, className); + + Properties properties = new Properties(); + properties.put("user", settings.getString(PersistenceConf.JDBC_USERNAME)); + properties.put("password", settings.getString(PersistenceConf.JDBC_PASSWORD)); + + // DBCP factory which will produce JDBC Driver instances + ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driver, connectURI, properties); + + // DBCP Factory holding the pooled connection, which are created by the driver connection + // factory and held in the supplied pool + ObjectName dataSourceJmxName; + try { + dataSourceJmxName = new ObjectName("network.oxalis", "connectionPool", "OxalisDB"); + } catch (MalformedObjectNameException e) { + throw new IllegalStateException(e.getMessage(), e); + } + PoolableConnectionFactory poolableConnectionFactory = + new PoolableConnectionFactory(driverConnectionFactory, dataSourceJmxName); + + String validationQuery = settings.getString(PersistenceConf.DBCP_VALIDATION_QUERY); + if (validationQuery != null) { + poolableConnectionFactory.setValidationQuery(validationQuery); + } + // DBCP object pool holding our driver connections + GenericObjectPool genericObjectPool = new GenericObjectPool<>(poolableConnectionFactory); + poolableConnectionFactory.setPool(genericObjectPool); + genericObjectPool.setMaxTotal(settings.getInt(PersistenceConf.DBCP_MAX_TOTAL)); + genericObjectPool.setMaxIdle(settings.getInt(PersistenceConf.DBCP_MAX_IDLE)); + genericObjectPool.setMaxWaitMillis(10000); + + // Test the connection returned from the pool + genericObjectPool.setTestOnBorrow(true); + + // Test idle instances visited by the pool maintenance thread and destroy any that fail validation + genericObjectPool.setTestWhileIdle(true); + + // Test every hour + genericObjectPool.setTimeBetweenEvictionRunsMillis(60 * 60 * 1000); + + // Creates the actual DataSource instance + return new PoolingDataSource(genericObjectPool); + } + + private static Driver getJdbcDriver(ClassLoader classLoader, String className) { + try { + return (Driver) Class.forName(className, true, classLoader).newInstance(); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Unable to locate class " + className + ".", e); + } catch (InstantiationException e) { + throw new IllegalStateException("Unable to instantiate driver from class " + className, e); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Unable to access driver class " + className + "; " + e, e); + } + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/datasource/JndiDataSourceProvider.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/datasource/JndiDataSourceProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..d6d5ea613f48ae91f0ad341127f146cdc7dbac58 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/datasource/JndiDataSourceProvider.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.datasource; + +import com.google.inject.Provider; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.settings.Settings; +import network.oxalis.persistence.util.PersistenceConf; + +import javax.inject.Inject; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; + +/** + * Provides an instance of {@link javax.sql.DataSource} using the configuration parameters found + * in {@link Settings}, which is located in OXALIS_HOME. + * + * @author steinar + * Date: 18.04.13 + * Time: 13:28 + * @author erlend + */ +@Slf4j +public class JndiDataSourceProvider implements Provider { + + private final Settings settings; + + @Inject + public JndiDataSourceProvider(Settings settings) { + this.settings = settings; + } + + @Override + public DataSource get() { + String dataSourceJndiName = settings.getString(PersistenceConf.JDBC_CONNECTION_URI); + + log.debug("Obtaining data source from JNDI: {}", dataSourceJndiName); + try { + Context initCtx = new InitialContext(); + + return (DataSource) initCtx.lookup(dataSourceJndiName); + } catch (NamingException e) { + throw new IllegalStateException( + String.format("Unable to obtain JNDI datasource from '%s'.", dataSourceJndiName), e); + } + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/guice/AopJdbcTxManagerModule.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/guice/AopJdbcTxManagerModule.java new file mode 100644 index 0000000000000000000000000000000000000000..1cafaa8ae61c72c9d94fd2b79059ea02a674d150 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/guice/AopJdbcTxManagerModule.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.guice; + +import com.google.inject.Singleton; +import com.google.inject.matcher.Matchers; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.persistence.annotation.Repository; +import network.oxalis.persistence.annotation.Transactional; +import network.oxalis.persistence.aop.JdbcTxManagerImpl; +import network.oxalis.persistence.aop.RepositoryConnectionMethodInterceptor; +import network.oxalis.persistence.aop.TransactionalMethodInterceptor; +import network.oxalis.persistence.api.JdbcTxManager; + +/** + * @author andy + * @author thore + */ +public class AopJdbcTxManagerModule extends OxalisModule { + + @Override + protected void configure() { + + // The tx Manager needs to be a singleton so that the same reference to the threadlocal containing the + // connection is shared amongst repositories etc. + bind(JdbcTxManager.class) + .to(JdbcTxManagerImpl.class) + .in(Singleton.class); + + //creates the transactional method interceptor which handles methods annotated with @Transactional + final TransactionalMethodInterceptor transactionalMethodInterceptor = new TransactionalMethodInterceptor(); + + // Creates the method interceptor which handles methods annotated with @Repository + final RepositoryConnectionMethodInterceptor repositoryConnectionMethodInterceptor = + new RepositoryConnectionMethodInterceptor(); + + //injects the JdbcTxManager into the method interceptor for methods annotated with @Transactional. + requestInjection(transactionalMethodInterceptor); + + //injects the JdbcTxManager into the method interceptor for methods annotated with @Repository + requestInjection(repositoryConnectionMethodInterceptor); + + //makes individual methods in a class transactional. + bindInterceptor(Matchers.any(), Matchers.annotatedWith(Transactional.class), transactionalMethodInterceptor); + + //makes all methods in the class transactional + bindInterceptor(Matchers.annotatedWith(Transactional.class), Matchers.any(), + transactionalMethodInterceptor); + bindInterceptor(Matchers.annotatedWith(Repository.class), Matchers.any(), + repositoryConnectionMethodInterceptor); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/guice/DataSourceModule.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/guice/DataSourceModule.java new file mode 100644 index 0000000000000000000000000000000000000000..04a11a03afabf51a81290ac25586e110448a8e93 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/guice/DataSourceModule.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.guice; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Names; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.commons.settings.SettingsBuilder; +import network.oxalis.persistence.datasource.DbcpDataSourceProvider; +import network.oxalis.persistence.datasource.JndiDataSourceProvider; +import network.oxalis.persistence.util.PersistenceConf; + +import javax.sql.DataSource; + +/** + * Guice module providing a {@link DataSource} configured and bound to an SQL DBMS + * based upon the contents of a configuration file. + * + * @author steinar + * @author erlend + */ +public class DataSourceModule extends OxalisModule { + + @Override + protected void configure() { + SettingsBuilder.with(binder(), PersistenceConf.class); + + bind(Key.get(DataSource.class, Names.named("dbcp"))) + .toProvider(DbcpDataSourceProvider.class) + .in(Singleton.class); + + bind(Key.get(DataSource.class, Names.named("jndi"))) + .toProvider(JndiDataSourceProvider.class) + .in(Singleton.class); + } + + @Provides + @Singleton + protected DataSource dataSourceProvider(Injector injector, Settings settings) { + return injector.getInstance( + Key.get(DataSource.class, settings.getNamed(PersistenceConf.DATASOURCE))); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/H2Platform.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/H2Platform.java new file mode 100644 index 0000000000000000000000000000000000000000..b3fc719059d948078869b9f25979b7e2d65f5470 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/H2Platform.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import network.oxalis.persistence.api.Platform; + +/** + * @author erlend + */ +public class H2Platform implements Platform { + + public static final String IDENTIFIER = "H2"; + + @Override + public boolean detect(String identifier) { + return identifier.toLowerCase().contains("h2"); + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/HSQLDBPlatform.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/HSQLDBPlatform.java new file mode 100644 index 0000000000000000000000000000000000000000..443ec0421f984eb311194312eab16eaf2df35fae --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/HSQLDBPlatform.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import network.oxalis.persistence.api.Platform; + +/** + * @author erlend + */ +public class HSQLDBPlatform implements Platform { + + public static final String IDENTIFIER = "HSqlDB"; + + @Override + public boolean detect(String identifier) { + return identifier.toLowerCase().contains("hsql"); + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/MsSQLPlatform.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/MsSQLPlatform.java new file mode 100644 index 0000000000000000000000000000000000000000..160beaf657e1757701d609b1f99eefcf2112ebfd --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/MsSQLPlatform.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import network.oxalis.persistence.api.Platform; + +/** + * @author erlend + */ +public class MsSQLPlatform implements Platform { + + public static final String IDENTIFIER = "MsSql"; + + @Override + public boolean detect(String identifier) { + return identifier.toLowerCase().contains("microsoft"); + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/MySQLPlatform.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/MySQLPlatform.java new file mode 100644 index 0000000000000000000000000000000000000000..7f383cc3269f5bbe1f5eb7f9438fa5ae660f16aa --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/MySQLPlatform.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import network.oxalis.persistence.api.Platform; + +/** + * @author erlend + */ +public class MySQLPlatform implements Platform { + + public static final String IDENTIFIER = "MySQL"; + + @Override + public boolean detect(String identifier) { + return identifier.toLowerCase().contains("mysql"); + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/OraclePlatform.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/OraclePlatform.java new file mode 100644 index 0000000000000000000000000000000000000000..c07469d7e54062831b9b0e4b599f8246b6bf7b2c --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/OraclePlatform.java @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import network.oxalis.persistence.api.Platform; + +/** + * @author erlend + */ +public class OraclePlatform implements Platform { + + public static final String IDENTIFIER = "Oracle"; + + @Override + public boolean detect(String identifier) { + return identifier.toLowerCase().contains("oracle"); + } + + @Override + public String getIdentifier() { + return IDENTIFIER; + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/PlatformModule.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/PlatformModule.java new file mode 100644 index 0000000000000000000000000000000000000000..507fada08c375bb83b17c4aa5714b8fe975b2808 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/PlatformModule.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import com.google.inject.Singleton; +import com.google.inject.multibindings.Multibinder; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.persistence.api.Platform; + +/** + * @author erlend + */ +public class PlatformModule extends OxalisModule { + + @Override + protected void configure() { + Multibinder multibinder = Multibinder.newSetBinder(binder(), Platform.class); + multibinder.addBinding().to(H2Platform.class); + multibinder.addBinding().to(HSQLDBPlatform.class); + multibinder.addBinding().to(MySQLPlatform.class); + multibinder.addBinding().to(MsSQLPlatform.class); + multibinder.addBinding().to(OraclePlatform.class); + + bind(Platform.class) + .toProvider(PlatformProvider.class) + .in(Singleton.class); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/PlatformProvider.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/PlatformProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..ef579cd6c1345649e234e5e311ca4c6d958bb792 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/platform/PlatformProvider.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.persistence.annotation.Repository; +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.persistence.api.Platform; + +import java.sql.SQLException; +import java.util.Set; + +/** + * @author erlend + */ +@Repository +class PlatformProvider implements Provider { + + private JdbcTxManager jdbcTxManager; + + private Set platforms; + + @Inject + public PlatformProvider(JdbcTxManager jdbcTxManager, Set platforms) { + this.jdbcTxManager = jdbcTxManager; + this.platforms = platforms; + } + + @Override + public Platform get() { + try { + String productName = jdbcTxManager.getConnection().getMetaData().getDatabaseProductName(); + + for (Platform platform : platforms) + if (platform.detect(productName)) + return platform; + + throw new OxalisLoadingException(String.format("Unable to load platform for '%s'.", productName)); + } catch (SQLException e) { + throw new OxalisLoadingException("Unable to detect database platform.", e); + } + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/util/PersistenceConf.java b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/util/PersistenceConf.java new file mode 100644 index 0000000000000000000000000000000000000000..df8e5837f34ee538cca479d22c14b90b8f13e887 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/java/network/oxalis/persistence/util/PersistenceConf.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.util; + +import network.oxalis.api.settings.*; + +/** + * @author erlend + * @since 4.0.0 + */ +@Title("Persistence") +public enum PersistenceConf { + + @Path("oxalis.database.datasource") + @DefaultValue("dbcp") + DATASOURCE, + + @Path("oxalis.database.driver.class") + @DefaultValue("org.h2.Driver") + DRIVER_CLASS, + + @Path("oxalis.database.driver.path") + @Nullable + DRIVER_PATH, + + @Path("oxalis.database.jdbc.connection") + @DefaultValue("jdbc:h2:file:./data/oxalis") + JDBC_CONNECTION_URI, + + @Path("oxalis.database.jdbc.username") + @DefaultValue("sa") + JDBC_USERNAME, + + @Path("oxalis.database.jdbc.password") + @DefaultValue("") + @Secret + JDBC_PASSWORD, + + @Path("oxalis.database.jndi.resource") + @DefaultValue("jdbc/oxalis") + JNDI_RESOURCE, + + @Path("oxalis.database.dbcp.max.idle") + @DefaultValue("30") + DBCP_MAX_IDLE, + + @Path("oxalis.database.dbcp.max.total") + @DefaultValue("100") + DBCP_MAX_TOTAL, + + @Path("oxalis.database.dbcp.validation") + @DefaultValue("select 1") + DBCP_VALIDATION_QUERY, + +} diff --git a/oxalis-legacy/oxalis-persistence/src/main/resources/reference.conf b/oxalis-legacy/oxalis-persistence/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..2da84a5bca2868a2472c9b45380b3d28d3370f11 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/main/resources/reference.conf @@ -0,0 +1,3 @@ +oxalis.module.persistence.aop.class = network.oxalis.persistence.guice.AopJdbcTxManagerModule +oxalis.module.persistence.datasource.class = network.oxalis.persistence.guice.DataSourceModule +oxalis.module.persistence.platform.class = network.oxalis.persistence.platform.PlatformModule diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/DbcpDataSourceProviderTest.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/DbcpDataSourceProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4c98ec3fb3456821f66ccf86bb410d4ab0e4be40 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/DbcpDataSourceProviderTest.java @@ -0,0 +1,253 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.datasource; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.name.Named; +import network.oxalis.api.settings.Settings; +import network.oxalis.commons.filesystem.ClassLoaderUtils; +import network.oxalis.persistence.testng.PersistenceModuleFactory; +import network.oxalis.persistence.util.PersistenceConf; +import org.apache.commons.dbcp2.*; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.sql.DataSource; +import java.net.MalformedURLException; +import java.net.URI; +import java.nio.file.Path; +import java.sql.*; +import java.util.Properties; + +import static org.testng.Assert.*; + +/** + * TODO Enable testing. + * + * @author steinar + * Date: 18.04.13 + * Time: 14:08 + */ +@Guice(moduleFactory = PersistenceModuleFactory.class) +public class DbcpDataSourceProviderTest { + + @Inject + private Provider dataSourceProvider; + + @Inject + private Provider dataSourceProvider2; + + @Inject + private Settings settings; + + @Inject + @Named("home") + private Path homeFolder; + + @BeforeClass + public void setUp() { + assertNotNull(settings); + } + + @Test + public void oxalisDataSourceFactoryIsSingleton() throws Exception { + + // Attempts to load the first instance of DataSourceProvider + assertNotNull(dataSourceProvider); + + // Second invocation should return same instance + assertEquals(dataSourceProvider, dataSourceProvider2, + "Seems the Singleton pattern in DataSourceProviderFactory is not working"); + + // The datasource should also be the same instance + DataSource dataSource1 = dataSourceProvider.get(); + assertNotNull(dataSource1); + DataSource dataSource2 = dataSourceProvider.get(); + + assertEquals(dataSource1, dataSource2, + dataSourceProvider.getClass().getSimpleName() + " is not returning a singleton instance of DataSource"); + + } + + /** + * Verifies that we can create a pooled jdbc data source using the + * JDBC .jar-file supplied in the global configuration file. + */ + @Test + public void testLoadJdbcDriverUsingCustomClassLoader() throws Exception { + ConnectionFactory driverConnectionFactory = createConnectionFactory(false); + + ObjectName poolName = new ObjectName("network.oxalis", "connectionPool", "TestPool"); + PoolableConnectionFactory factory = new PoolableConnectionFactory(driverConnectionFactory, poolName); + + GenericObjectPool pool = new GenericObjectPool<>(factory); + factory.setPool(pool); + + pool.setMaxTotal(10); + pool.setMaxWaitMillis(100); + + + assertEquals(pool.getFactory(), factory); + + PoolableConnectionFactory pcf = (PoolableConnectionFactory) ((GenericObjectPool) pool).getFactory(); + //ObjectPool pool1 = + pcf.getPool(); + + PoolingDataSource poolingDataSource = new PoolingDataSource<>(pool); + + Connection connection = poolingDataSource.getConnection(); + assertNotNull(connection); + + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("select current_date()"); + + assertTrue(resultSet.next()); + } + + + @Test + public void testFailWithStaleConnection() throws Exception { + ConnectionFactory driverConnectionFactory = createConnectionFactory(false); + + + PoolingDataSource poolingDataSource = createPoolingDataSource(driverConnectionFactory); + try { + runTwoSqlStatementsWithTwoConnections(poolingDataSource); + } catch (Exception e) { + assertTrue(e.getClass().getName().contains("CommunicationsException")); + } + } + + @Test(enabled = false) + public void testHandleStaleConnections() throws Exception { + ConnectionFactory driverConnectionFactory = createConnectionFactory(true); + + PoolingDataSource poolingDataSource = createPoolingDataSource(driverConnectionFactory); + + runTwoSqlStatementsWithTwoConnections(poolingDataSource); + } + + @Test + public void testBasicDataSource() throws Exception { + + Path jdbcDriverClassPath = settings.getPath(PersistenceConf.DRIVER_PATH, homeFolder); + ClassLoader classLoader = ClassLoaderUtils.initiate(jdbcDriverClassPath); + + BasicDataSource basicDataSource = new BasicDataSource(); + basicDataSource.setDriverClassName(settings.getString(PersistenceConf.DRIVER_CLASS)); + basicDataSource.setUrl(settings.getString(PersistenceConf.JDBC_CONNECTION_URI)); + basicDataSource.setUsername(settings.getString(PersistenceConf.JDBC_USERNAME)); + basicDataSource.setPassword(settings.getString(PersistenceConf.JDBC_PASSWORD)); + + // Does not work in 1.4, fixed in 1.4.1 + basicDataSource.setDriverClassLoader(classLoader); + + try { + Connection connection = basicDataSource.getConnection(); + assertNotNull(connection); + } catch (SQLException e) { + // As expected when using DBCP 1.4 + } + } + + private void runTwoSqlStatementsWithTwoConnections(PoolingDataSource poolingDataSource) + throws SQLException, InterruptedException { + + Connection connection = poolingDataSource.getConnection(); + if (connection.getMetaData().getDatabaseProductName().toLowerCase().contains("mysql")) { + assertNotNull(connection); + + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("select current_date()"); + + statement = connection.createStatement(); + statement.execute("set session wait_timeout=1"); + assertTrue(resultSet.next()); + + connection.close(); // return to pool + + // Wait for 2 seconds + System.err.print("Sleeping for 2 seconds...."); + Thread.sleep(2 * 1000L); + System.err.println("Running again now"); + connection = poolingDataSource.getConnection(); + statement = connection.createStatement(); + statement.executeQuery("select current_time()"); + } + } + + + private ConnectionFactory createConnectionFactory(boolean profileSql) throws MalformedURLException, + ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException { + Path jdbcDriverClassPath = settings.getPath(PersistenceConf.DRIVER_PATH, homeFolder); + + ClassLoader classLoader = ClassLoaderUtils.initiate(jdbcDriverClassPath); + + String jdbcDriverClassName = settings.getString(PersistenceConf.DRIVER_CLASS); + URI connectURI = URI.create(settings.getString(PersistenceConf.JDBC_CONNECTION_URI)); // + "?initialTimeout=2"; + String userName = settings.getString(PersistenceConf.JDBC_USERNAME); + String password = settings.getString(PersistenceConf.JDBC_PASSWORD); + + Class aClass; + try { + aClass = Class.forName(jdbcDriverClassName, true, classLoader); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(String.format( + "Unable to locate class '%s' in class path '%s'", jdbcDriverClassName, jdbcDriverClassPath)); + } + Driver driver = (Driver) aClass.newInstance(); + assertTrue(driver.acceptsURL(connectURI.toString())); + + Properties properties = new Properties(); + properties.put("user", userName); + properties.put("password", password); + if (profileSql) { + properties.put("profileSQL", "true"); // MySQL debug option + } + return new DriverConnectionFactory(driver, connectURI.toString(), properties); + } + + + @SuppressWarnings("unchecked") + private PoolingDataSource createPoolingDataSource(ConnectionFactory driverConnectionFactory) { + + PoolableConnectionFactory poolableConnectionFactory; + try { + + poolableConnectionFactory = new PoolableConnectionFactory(driverConnectionFactory, + new ObjectName("network.oxalis", "connectionPool", "TestPool")); + + GenericObjectPool pool = new GenericObjectPool<>(poolableConnectionFactory); + poolableConnectionFactory.setPool(pool); + poolableConnectionFactory.setValidationQuery("select 1"); + return new PoolingDataSource(pool); + } catch (MalformedObjectNameException e) { + throw new IllegalStateException("Unable to create poolable conneciton factory: " + e.getMessage(), e); + } + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/JndiDataSourceProviderTest.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/JndiDataSourceProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a613406c13f07a512508e93a4e96a3a1ba9d9495 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/JndiDataSourceProviderTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.datasource; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.name.Named; +import network.oxalis.persistence.testng.PersistenceModuleFactory; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.sql.DataSource; + +/** + * @author erlend + */ +@Guice(moduleFactory = PersistenceModuleFactory.class) +public class JndiDataSourceProviderTest { + + @Inject + @Named("jndi") + private Provider dataSourceProvider; + + @Test + public void simple() { + Assert.assertNotNull(dataSourceProvider); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/SimpleDataSourceTest.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/SimpleDataSourceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2cf22c80fdb440b952699a8d2afee80fbc6554b7 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/datasource/SimpleDataSourceTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.datasource; + +import com.google.inject.Inject; +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.persistence.testng.PersistenceModuleFactory; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.sql.DataSource; + +/** + * @author erlend + */ +@Guice(moduleFactory = PersistenceModuleFactory.class) +public class SimpleDataSourceTest { + + @Inject + private DataSource dataSource; + + @Inject + private JdbcTxManager jdbcTxManager; + + @Test + public void simple() { + Assert.assertNotNull(dataSource); + Assert.assertNotNull(jdbcTxManager); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformModuleTest.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformModuleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3cfcc8ce60acf9a73d660c647dc796bd0ff53c5e --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformModuleTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import com.google.inject.Inject; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.persistence.api.Platform; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +@Guice(modules = GuiceModuleLoader.class) +public class PlatformModuleTest { + + @Inject + private Platform platform; + + @Test + public void simple() { + Assert.assertTrue(platform instanceof H2Platform); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformProviderTest.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3f91ec8798f2a29451038330ffbf86393eaded8c --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformProviderTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import network.oxalis.api.lang.OxalisLoadingException; +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.persistence.api.Platform; +import org.mockito.Mockito; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Collections; + +/** + * @author erlend + */ +public class PlatformProviderTest { + + private JdbcTxManager jdbcTxManager; + + private Connection connection; + + private DatabaseMetaData databaseMetaData; + + @BeforeClass + public void beforeMethod() { + jdbcTxManager = Mockito.mock(JdbcTxManager.class); + connection = Mockito.mock(Connection.class); + databaseMetaData = Mockito.mock(DatabaseMetaData.class); + } + + @Test + public void simple() throws Exception { + Mockito.doReturn(connection).when(jdbcTxManager).getConnection(); + Mockito.doReturn(databaseMetaData).when(connection).getMetaData(); + Mockito.doReturn("H2").when(databaseMetaData).getDatabaseProductName(); + + Platform platform = new H2Platform(); + + PlatformProvider platformProvider = new PlatformProvider(jdbcTxManager, Collections.singleton(platform)); + + Assert.assertEquals(platformProvider.get(), platform); + } + + @Test(expectedExceptions = OxalisLoadingException.class) + public void notFound() throws Exception { + Mockito.doReturn(connection).when(jdbcTxManager).getConnection(); + Mockito.doReturn(databaseMetaData).when(connection).getMetaData(); + Mockito.doReturn("MySQL").when(databaseMetaData).getDatabaseProductName(); + + Platform platform = new H2Platform(); + + PlatformProvider platformProvider = new PlatformProvider(jdbcTxManager, Collections.singleton(platform)); + + platformProvider.get(); + } + + @Test(expectedExceptions = OxalisLoadingException.class) + public void exception() throws Exception { + Mockito.doReturn(connection).when(jdbcTxManager).getConnection(); + Mockito.doThrow(new SQLException()).when(connection).getMetaData(); + + Platform platform = new H2Platform(); + + PlatformProvider platformProvider = new PlatformProvider(jdbcTxManager, Collections.singleton(platform)); + + platformProvider.get(); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformsTest.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d6234c5199ef15538862c4192beffd60f9b8ae42 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/platform/PlatformsTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.platform; + +import network.oxalis.persistence.api.Platform; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class PlatformsTest { + + @Test + public void h2() { + Platform platform = new H2Platform(); + + Assert.assertTrue(platform.detect("H2")); + Assert.assertFalse(platform.detect("MySQL")); + + Assert.assertEquals(platform.getIdentifier(), H2Platform.IDENTIFIER); + Assert.assertEquals(platform.getNamed().value(), H2Platform.IDENTIFIER); + } + + @Test + public void hsqldb() { + Platform platform = new HSQLDBPlatform(); + + Assert.assertTrue(platform.detect("HSqlDB")); + Assert.assertFalse(platform.detect("MySQL")); + + Assert.assertEquals(platform.getIdentifier(), HSQLDBPlatform.IDENTIFIER); + } + + @Test + public void mssql() { + Platform platform = new MsSQLPlatform(); + + Assert.assertFalse(platform.detect("H2")); + Assert.assertTrue(platform.detect("Microsoft")); + + Assert.assertEquals(platform.getIdentifier(), MsSQLPlatform.IDENTIFIER); + } + + @Test + public void mysql() { + Platform platform = new MySQLPlatform(); + + Assert.assertFalse(platform.detect("H2")); + Assert.assertTrue(platform.detect("MySQL")); + + Assert.assertEquals(platform.getIdentifier(), MySQLPlatform.IDENTIFIER); + } + + @Test + public void oracle() { + Platform platform = new OraclePlatform(); + + Assert.assertFalse(platform.detect("H2")); + Assert.assertTrue(platform.detect("Oracle")); + + Assert.assertEquals(platform.getIdentifier(), OraclePlatform.IDENTIFIER); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/testng/PersistenceModuleFactory.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/testng/PersistenceModuleFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..f24c8041400774a1597317ca4a0d2ca1d75fb9c8 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/testng/PersistenceModuleFactory.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.testng; + +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.name.Names; +import com.google.inject.util.Modules; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import network.oxalis.commons.filesystem.FileSystemModule; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.persistence.guice.AopJdbcTxManagerModule; +import network.oxalis.persistence.guice.DataSourceModule; +import network.oxalis.test.config.TestConfigModule; +import network.oxalis.test.filesystem.TestFileSystemModule; +import org.testng.IModuleFactory; +import org.testng.ITestContext; + +/** + * TestNG implementation of factory, which provides the Google Guice modules required + * for running the tests. + * + * @author steinar + * Date: 16.10.2016 + * Time: 19.44 + */ +public class PersistenceModuleFactory implements IModuleFactory { + + public static final String CREATE_OXALIS_DBMS_H2_SQL = "/sql/raw_stats-h2.sql"; + + @Override + public Module createModule(ITestContext iTestContext, Class aClass) { + return new OxalisModule() { + @Override + protected void configure() { + install(new DataSourceModule()); + install(new AopJdbcTxManagerModule()); + install(new TestConfigModule()); + install(Modules.override(new FileSystemModule()).with(new TestFileSystemModule())); + install(new OxalisModule() { + @Override + protected void configure() { + bind(Key.get(Config.class, Names.named("reference"))) + .toInstance(ConfigFactory.defaultOverrides()); + } + }); + } + }; + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/util/PersistenceConfTest.java b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/util/PersistenceConfTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a6c26320212dab73eea5c23c1eaf9e9a483a6fe4 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/java/network/oxalis/persistence/util/PersistenceConfTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.persistence.util; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author erlend + */ +public class PersistenceConfTest { + + @Test + public void simple() { + Assert.assertEquals(PersistenceConf.valueOf("DATASOURCE"), PersistenceConf.DATASOURCE); + } +} diff --git a/oxalis-legacy/oxalis-persistence/src/test/resources/logback-test.xml b/oxalis-legacy/oxalis-persistence/src/test/resources/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..dda59efbd42a8c8df626806ae5f1909ad3795878 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/resources/logback-test.xml @@ -0,0 +1,38 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + \ No newline at end of file diff --git a/oxalis-legacy/oxalis-persistence/src/test/resources/oxalis_home/fake-oxalis.conf b/oxalis-legacy/oxalis-persistence/src/test/resources/oxalis_home/fake-oxalis.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-legacy/oxalis-persistence/src/test/resources/oxalis_home/logback-test.xml b/oxalis-legacy/oxalis-persistence/src/test/resources/oxalis_home/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/resources/oxalis_home/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-legacy/oxalis-persistence/src/test/resources/reference.conf b/oxalis-legacy/oxalis-persistence/src/test/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..a8dfccb68a1e970252d40ef48487b970d6ca150a --- /dev/null +++ b/oxalis-legacy/oxalis-persistence/src/test/resources/reference.conf @@ -0,0 +1 @@ +defaults = {} \ No newline at end of file diff --git a/oxalis-legacy/oxalis-statistics/.gitignore b/oxalis-legacy/oxalis-statistics/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..249cda967c11bb62c8affe06d18f26bc5b5f3af0 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/.gitignore @@ -0,0 +1 @@ +/data \ No newline at end of file diff --git a/oxalis-legacy/oxalis-statistics/pom.xml b/oxalis-legacy/oxalis-statistics/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..ee8962ecbf0ebf474a5935991835977d6d7264b5 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/pom.xml @@ -0,0 +1,93 @@ + + + + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + ../../pom.xml + + 4.0.0 + + oxalis-statistics + + Oxalis :: Leg :: Statistics + Features to support gathering of statistics. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + dk.erst.oxalis + oxalis-persistence + + + dk.erst.oxalis + oxalis-test + test + + + dk.erst.oxalis + oxalis-persistence + test-jar + test + + + dk.erst.oxalis + oxalis-inbound + test + + + + + com.google.inject.extensions + guice-servlet + provided + + + + + joda-time + joda-time + + + + + javax.servlet + javax.servlet-api + provided + + + + + commons-codec + commons-codec + + + + \ No newline at end of file diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/ChannelId.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/ChannelId.java new file mode 100644 index 0000000000000000000000000000000000000000..262c4d14a8e775b94efb57bb884845e14e091ae4 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/ChannelId.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.api; + +import java.io.Serializable; + +/** + * @author Steinar Overbeck Cook + */ +public class ChannelId implements Serializable { + + String value; + + public ChannelId(String channelId) { + if (channelId == null) { + value = ""; + } else + this.value = channelId; + } + + public String stringValue() { + return toString(); + } + + @Override + public String toString() { + return value; + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/RawStatistics.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/RawStatistics.java new file mode 100644 index 0000000000000000000000000000000000000000..8fc0e7d40f68c9c200052c7394810d3da4861d2d --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/RawStatistics.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.api; + +import network.oxalis.api.model.AccessPointIdentifier; +import network.oxalis.api.model.Direction; +import network.oxalis.vefa.peppol.common.model.DocumentTypeIdentifier; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import network.oxalis.vefa.peppol.common.model.ProcessIdentifier; + +import java.util.Date; + +/** + * @author erlend + */ +public interface RawStatistics { + + ParticipantIdentifier getSender(); + + ParticipantIdentifier getReceiver(); + + Direction getDirection(); + + Date getDate(); + + AccessPointIdentifier getAccessPointIdentifier(); + + DocumentTypeIdentifier getDocumentTypeIdentifier(); + + ChannelId getChannelId(); + + ProcessIdentifier getProcessIdentifier(); + +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/RawStatisticsRepository.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/RawStatisticsRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..2e04fe4ccc274f46bcc6568147fd02a8af2c757c --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/RawStatisticsRepository.java @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.api; + +import java.util.Date; + +/** + * Objects implementing this interface are capable of storing and retrieving raw data + * pertaining to the sending and receiving of PEPPOL messages in order to provide statistics. + *

+ * User: steinar + * Date: 30.01.13 + * Time: 19:28 + */ +public interface RawStatisticsRepository { + + /** + * Persists another raw statistics entry into table {@code raw_stats} + */ + Integer persist(RawStatistics rawStatistics); + + /** + * Retrieves data from table raw_stats and transforms it into an appropriate XML document + */ + void fetchAndTransformRawStatistics(StatisticsTransformer transformer, Date start, Date end, + StatisticsGranularity granularity); + +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/StatisticsGranularity.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/StatisticsGranularity.java new file mode 100644 index 0000000000000000000000000000000000000000..236d1761ce9ae71ad35da1c309dbd81a81add3c3 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/StatisticsGranularity.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.api; + +/** + * Represents granularity of statistics data. + * + * @author steinar + * Date: 26.03.13 + * Time: 09:17 + */ +public enum StatisticsGranularity { + + YEAR("Y"),MONTH("M"), DAY("D"), HOUR("H"); + + private final String abbreviation; + + StatisticsGranularity(String abbreviation) { + this.abbreviation = abbreviation; + } + + public String getAbbreviation() { + return abbreviation; + } + + public static StatisticsGranularity valueForAbbreviation(String abbreviation) { + if (abbreviation == null) { + throw new IllegalArgumentException("null string is an invalid abbreviation for statistics granularity"); + } + + for (StatisticsGranularity granularity : values()) { + if (granularity.abbreviation.equalsIgnoreCase(abbreviation)) { + return granularity; + } + } + + throw new IllegalArgumentException("Invalid abbreviation for statistics granularity: " + abbreviation); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/StatisticsTransformer.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/StatisticsTransformer.java new file mode 100644 index 0000000000000000000000000000000000000000..ca47ae9259353e5d1e9d298f3e30a95cbe9807b0 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/api/StatisticsTransformer.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.api; + +import java.util.Date; + +/** + * Transforms aggregated statistics into another format. This interface has been designed to maximize performance + * when transforming the results from the statistics repository into whatever format the implementor of this + * interface has choosen. I.e. transformation from SQL ResultSet to XML, which will not require any new objects to + * be created. + * + *

To use it: + *

    + *
  1. Invoke {@link #startEntry()} first
  2. + *
  3. Invoke the writeXxxx methods for each field
  4. + *
  5. Complete the entry by calling {@link #endEntry()}
  6. + *
+ * + * User: steinar + * Date: 24.02.13 + * Time: 10:27 + */ +public interface StatisticsTransformer { + + String STATISTICS_DOCUMENT_START_ELEMENT_NAME = "peppol-ap-statistics"; + String ENTRY_START_ELEMENT_NAME = "entry"; + String ACCESS_POINT_ID_ELEMENT_NAME = "access-point-id"; + String PARTICIPANT_ID_ELEMENT_NAME = "participant-id"; + String DOCUMENT_TYPE_ELEMENT_NAME = "document-type"; + String PROFILE_ID_ELEMENT_NAME = "profile-id"; + String CHANNEL_ELEMENT_NAME = "channel"; + String COUNT_ELEMENT_NAME = "count"; + String PERIOD_ELEMENT_NAME = "period"; + String DIRECTION_ELEMENT_NAME = "direction"; + + void startStatistics(Date start, Date end); + + /** Invoked by the transformer upon the start of a new entry (row, line, etc.) of statistical data */ + void startEntry(); + + void writeAccessPointIdentifier(String accessPointIdentifier); + + void writePeriod(String period); + + void writeDirection(String direction); + + void writeParticipantIdentifier(String participantId); + + void writeDocumentType(String documentType); + + void writeProfileId(String profileId); + + void writeChannel(String channel); + + void writeCount(int count); + + /** Completes the current statistics entry */ + void endEntry(); + + void endStatistics(); +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/guice/RawStatisticsRepositoryModule.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/guice/RawStatisticsRepositoryModule.java new file mode 100644 index 0000000000000000000000000000000000000000..eb8d3671926efa4aae527b04d0def2ed6d7bb370 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/guice/RawStatisticsRepositoryModule.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.guice; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Names; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.persistence.api.Platform; +import network.oxalis.persistence.guice.AopJdbcTxManagerModule; +import network.oxalis.persistence.platform.*; +import network.oxalis.statistics.jdbc.RawStatisticsRepositoryHSqlImpl; +import network.oxalis.statistics.jdbc.RawStatisticsRepositoryMySqlImpl; +import network.oxalis.statistics.api.RawStatisticsRepository; +import network.oxalis.statistics.jdbc.RawStatisticsRepositoryMsSqlImpl; +import network.oxalis.statistics.jdbc.RawStatisticsRepositoryOracleImpl; + +/** + * Wires up the persistence component. + *

+ * NOTE! When creating an injector, remember to supply an instance of {@link javax.sql.DataSource} + * + * @author steinar + * Date: 25.10.2016 + * Time: 21.43 + */ +public class RawStatisticsRepositoryModule extends OxalisModule { + + @Override + protected void configure() { + // Includes the Aop based Tx manager, which needs a DataSource + binder().install(new AopJdbcTxManagerModule()); + + bind(Key.get(RawStatisticsRepository.class, Names.named(H2Platform.IDENTIFIER))) + .to(RawStatisticsRepositoryMsSqlImpl.class); + + bind(Key.get(RawStatisticsRepository.class, Names.named(MySQLPlatform.IDENTIFIER))) + .to(RawStatisticsRepositoryMySqlImpl.class); + + bind(Key.get(RawStatisticsRepository.class, Names.named(MsSQLPlatform.IDENTIFIER))) + .to(RawStatisticsRepositoryMsSqlImpl.class); + + bind(Key.get(RawStatisticsRepository.class, Names.named(OraclePlatform.IDENTIFIER))) + .to(RawStatisticsRepositoryOracleImpl.class); + + bind(Key.get(RawStatisticsRepository.class, Names.named(HSQLDBPlatform.IDENTIFIER))) + .to(RawStatisticsRepositoryHSqlImpl.class); + } + + @Provides + @Singleton + public RawStatisticsRepository get(Injector injector, Platform platform) { + return injector.getInstance(Key.get(RawStatisticsRepository.class, platform.getNamed())); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsInboundModule.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsInboundModule.java new file mode 100644 index 0000000000000000000000000000000000000000..7e48d575a8d5b0b6f741e5c055adeaf71239862a --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsInboundModule.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.inbound; + +import com.google.inject.servlet.ServletModule; + +/** + * @author erlend + */ +public class StatisticsInboundModule extends ServletModule { + + @Override + protected void configureServlets() { + serve("/statistics/*").with(StatisticsServlet.class); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsProducer.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsProducer.java new file mode 100644 index 0000000000000000000000000000000000000000..4d521a73508f1b02556bbd37b13e4cd4dd19936f --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsProducer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.inbound; + +import com.google.inject.Inject; +import network.oxalis.statistics.api.RawStatisticsRepository; +import network.oxalis.statistics.api.StatisticsGranularity; +import network.oxalis.statistics.util.StatisticsToXmlTransformer; + +import java.io.OutputStream; +import java.util.Date; + +/** + * User: steinar + * Date: 23.02.13 + * Time: 21:49 + */ +public class StatisticsProducer { + + private final RawStatisticsRepository rawStatisticsRepository; + + @Inject + public StatisticsProducer(RawStatisticsRepository rawStatisticsRepository) { + this.rawStatisticsRepository = rawStatisticsRepository; + } + + public void emitData(OutputStream outputStream, Date start, Date end, StatisticsGranularity granularity) { + StatisticsToXmlTransformer statisticsToXmlTransformer = new StatisticsToXmlTransformer(outputStream); + + rawStatisticsRepository.fetchAndTransformRawStatistics(statisticsToXmlTransformer, start, end, granularity); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsServlet.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..5f22049858f347c896cdf4a47680806e77cdc4d8 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/inbound/StatisticsServlet.java @@ -0,0 +1,158 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.inbound; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import network.oxalis.statistics.api.StatisticsGranularity; +import network.oxalis.statistics.security.OxalisCipher; +import network.oxalis.statistics.security.OxalisCipherConverter; +import network.oxalis.statistics.security.StatisticsKeyTool; +import org.joda.time.DateTime; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.security.PublicKey; +import java.util.Date; +import java.util.Map; + +/** + * There are only 3 parameters, start, end and granularity - like this : + * {@literal https://your.accesspoint.com/oxalis/statistics?start=2013-01-01T00&end=2014-02-01T00&granularity=H} + *

+ * The start/end are dates are ISO formatted like : yyyy-mm-ddThh + * The granularity can be H (hour), D (day), M (month) and Y (year), for reference {@link StatisticsGranularity} + * + * @author steinar + * @author thore + */ +@Singleton +public class StatisticsServlet extends HttpServlet { + + @Inject + private StatisticsProducer statisticsProducer; + + private PublicKey publicKey; + + @Inject + private StatisticsKeyTool statisticsKeyTool; + + @Override + public void init(ServletConfig servletConfig) { + // Loads our asymmetric public key + publicKey = statisticsKeyTool.loadPublicKeyFromClassPath(); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.getOutputStream().write("Hello!\nOxalis statistics does not support http POST".getBytes()); + } + + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + Map parameterMap = request.getParameterMap(); + + Params params = parseParams(parameterMap); + + // Need the output stream for emission of XML + ServletOutputStream servletOutputStream = response.getOutputStream(); + + // Encryption of the output stream + OxalisCipher oxalisCipher = new OxalisCipher(); + + // Returns the symmetric key used in the Cipher, wrapped with the public key + String wrappedSymmetricKeyAsString = new OxalisCipherConverter() + .getWrappedSymmetricKeyAsString(publicKey, oxalisCipher); + response.setHeader(OxalisCipher.WRAPPED_SYMMETRIC_KEY_HEADER_NAME, wrappedSymmetricKeyAsString); + + // wraps the servlet output stream with encryption + OutputStream encryptedOutputStream = oxalisCipher.encryptStream(servletOutputStream); + + // Retrieves the data from the DBMS and emits the XML thru the encryped stream + statisticsProducer.emitData(encryptedOutputStream, params.start, params.end, params.granularity); + + encryptedOutputStream.close(); + } + + Params parseParams(Map parameterMap) { + Params result = new Params(); + parseGranularity(parameterMap, result); + parseDates(parameterMap, result); + return result; + } + + private void parseDates(Map parameterMap, Params result) { + result.start = parseDate(getParamFromMultiValues(parameterMap, "start")); + result.end = parseDate(getParamFromMultiValues(parameterMap, "end")); + } + + private void parseGranularity(Map parameterMap, Params result) { + String granularity = getParamFromMultiValues(parameterMap, "g"); + if (granularity == null) { + granularity = getParamFromMultiValues(parameterMap, "granularity"); + } + if (granularity == null) { + throw new IllegalArgumentException("Missing request parameter: 'granularity' (Y,M,D or H)"); + } else { + result.granularity = StatisticsGranularity.valueForAbbreviation(granularity); + } + } + + String getParamFromMultiValues(Map parameterMap, String key) { + String[] values = parameterMap.get(key); + if (values != null && values.length > 0) { + return values[0]; + } else { + return null; + } + } + + private Date parseDate(String dateAsString) { + if (dateAsString != null) { + try { + // JODA time is really the king of date and time parsing :-) + DateTime date = DateTime.parse(dateAsString); + return date.toDate(); + } catch (Exception e) { + throw new IllegalStateException(String.format( + "Unable to parseMultipart '%s'into a date and time using ISO8601 pattern YYYY-MM-DD HH", + dateAsString)); + } + } + return null; + } + + static class Params { + Date start; + + Date end; + + StatisticsGranularity granularity; + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryHSqlImpl.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryHSqlImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..433977017f89979f8498ebb17c6c6680282cd256 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryHSqlImpl.java @@ -0,0 +1,165 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.persistence.annotation.Repository; +import network.oxalis.statistics.util.DataSourceHelper; +import network.oxalis.statistics.util.JdbcHelper; +import network.oxalis.statistics.api.StatisticsGranularity; +import network.oxalis.statistics.api.StatisticsTransformer; + +import javax.inject.Inject; +import java.sql.*; +import java.util.Date; + +/** + * This is RawStatisticsRepository implementation for running the statistics database on MySql backend, through JDBC. + * + * @author steinar + * @author zeko78 + */ +@Repository +public class RawStatisticsRepositoryHSqlImpl extends RawStatisticsRepositoryJdbcImpl { + + @Inject + public RawStatisticsRepositoryHSqlImpl(JdbcTxManager jdbcTxManager) { + super(jdbcTxManager); + } + + /** + * Composes the SQL query to persist raw statistics into the DBMS. + */ + @Override + public String getPersistSqlQueryText() { + return String.format("INSERT INTO %s (ap, tstamp, direction, sender, receiver, doc_type, profile, channel) values(?,?,?,?,?,?,?,?)", RawStatisticsRepositoryJdbcImpl.RAW_STATS_TABLE_NAME); + } + + /** + * Composes the SQL query for retrieval of statistical data between a start and end data, with + * a granularity as supplied. + * + * @param granularity the granularity of the statics period reported. + */ + @Override + public String getRawStatisticsSqlQueryText(StatisticsGranularity granularity) { + String hSqlDateFormat = hSqlDateFormat(granularity); + return "SELECT\n" + + " ap,\n" + + " 'OUT' AS direction,\n" + + " TO_CHAR(tstamp,'" + hSqlDateFormat + "') AS period,\n" + + " sender AS ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(id) AS c\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'OUT'\n" + + " and tstamp between ? and ?\n" + + "GROUP BY ap,direction,period,ppid,doc_type,profile,channel\n" + + "union\n" + + "SELECT\n" + + " ap,\n" + + " 'IN' AS direction,\n" + + " TO_CHAR(tstamp,'" + hSqlDateFormat + "') AS period,\n" + + " receiver AS ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(id) AS c\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'IN'\n" + + " and tstamp between ? and ?\n" + + "\n" + + "GROUP BY ap,direction,period,ppid,doc_type,profile,channel\n" + + "order by period, ap\n" + + ";"; + } + + /** + * Retrieves statistics and transforms it using the supplied transformer. + */ + @Override + public void fetchAndTransformRawStatistics(StatisticsTransformer transformer, Date start, Date end, StatisticsGranularity granularity) { + + String sql = this.getRawStatisticsSqlQueryText(granularity); + + start = JdbcHelper.setStartDateIfNull(start); + end = JdbcHelper.setEndDateIfNull(end); + + Connection con = null; + PreparedStatement ps; + try { + con = jdbcTxManager.getConnection(); + ps = con.prepareStatement(sql); + + // Sets the start and end parameters for both parts of the SELECT UNION + ps.setTimestamp(1, new Timestamp(start.getTime())); + ps.setTimestamp(2, new Timestamp(end.getTime())); + ps.setTimestamp(3, new Timestamp(start.getTime())); + ps.setTimestamp(4, new Timestamp(end.getTime())); + ResultSet rs = ps.executeQuery(); + + transformer.startStatistics(start, end); + while (rs.next()) { + transformer.startEntry(); + transformer.writeAccessPointIdentifier(rs.getString("ap")); + transformer.writeDirection(rs.getString("direction")); + transformer.writePeriod(rs.getString("period")); + transformer.writeParticipantIdentifier(rs.getString("ppid")); + transformer.writeDocumentType(rs.getString("doc_type")); + transformer.writeProfileId(rs.getString("profile")); + transformer.writeChannel(rs.getString("channel")); + transformer.writeCount(rs.getInt("c")); + transformer.endEntry(); + } + transformer.endStatistics(); + } catch (SQLException e) { + throw new IllegalStateException("SQL error:" + e, e); + } finally { + DataSourceHelper.close(con); + } + } + + /** + * Return the correct date_format parameter for the chosen granularity + */ + static String hSqlDateFormat(StatisticsGranularity granularity) { + switch (granularity) { + case YEAR: + return "YY"; + case MONTH: + return "YY-MM"; + case DAY: + return "YY-MM-DD"; + case HOUR: + return "YY-MM-DD\"T\"HH24"; + default: + throw new IllegalArgumentException("Unable to convert " + granularity + " into a MySQL date_format() string"); + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryJdbcImpl.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryJdbcImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..0c688b35f19c316492bc167fc15d6e14e7f5b62b --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryJdbcImpl.java @@ -0,0 +1,149 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.statistics.util.DataSourceHelper; +import network.oxalis.statistics.util.JdbcHelper; +import network.oxalis.statistics.api.RawStatistics; +import network.oxalis.statistics.api.RawStatisticsRepository; +import network.oxalis.statistics.api.StatisticsGranularity; +import network.oxalis.statistics.api.StatisticsTransformer; + +import java.sql.*; +import java.util.Date; + +/** + * Basic JDBC implementation of StatisticsRepository component supplied with Oxalis. + * In theory, you may use any implementation of StatisticsRepository you like, + * however; in real life, most people will probably stick with the SQL database. + * + * @author steinar + */ +public abstract class RawStatisticsRepositoryJdbcImpl implements RawStatisticsRepository { + + public static final String RAW_STATS_TABLE_NAME = "raw_stats"; + + protected final JdbcTxManager jdbcTxManager; + + public RawStatisticsRepositoryJdbcImpl(JdbcTxManager jdbcTxManager) { + this.jdbcTxManager = jdbcTxManager; + } + + /** + * Persists raw statistics into the DBMS via JDBC, no caching is utilized. + */ + @Override + public Integer persist(RawStatistics rawStatistics) { + Connection con = null; + PreparedStatement ps; + Integer result = 0; + try { + + String sqlStatement = this.getPersistSqlQueryText(); + con = jdbcTxManager.getConnection(); + ps = con.prepareStatement(sqlStatement, Statement.RETURN_GENERATED_KEYS); + + ps.setString(1, rawStatistics.getAccessPointIdentifier().toString()); + ps.setTimestamp(2, new Timestamp(rawStatistics.getDate().getTime())); + ps.setString(3, rawStatistics.getDirection().toString()); + ps.setString(4, rawStatistics.getSender().getIdentifier()); + ps.setString(5, rawStatistics.getReceiver().getIdentifier()); + ps.setString(6, rawStatistics.getDocumentTypeIdentifier().toString()); + ps.setString(7, rawStatistics.getProcessIdentifier().toString()); + ps.setString(8, rawStatistics.getChannelId() == null ? null : rawStatistics.getChannelId().stringValue()); + + ps.executeUpdate(); + ResultSet rs = ps.getGeneratedKeys(); + if (rs.next()) { + result = rs.getInt(1); + rs.close(); + } + + } catch (SQLException e) { + throw new IllegalStateException("Unable to execute statement " + e, e); + } finally { + DataSourceHelper.close(con); + } + return result; + } + + /** + * Retrieves statistics and transforms it using the supplied transformer. + */ + @Override + public void fetchAndTransformRawStatistics(StatisticsTransformer transformer, Date start, Date end, StatisticsGranularity granularity) { + + String sql = this.getRawStatisticsSqlQueryText(granularity); + + start = JdbcHelper.setStartDateIfNull(start); + end = JdbcHelper.setEndDateIfNull(end); + + Connection con = null; + PreparedStatement ps; + try { + con = jdbcTxManager.getConnection(); + ps = con.prepareStatement(sql); + + // Sets the start and end parameters for both parts of the SELECT UNION + ps.setTimestamp(1, new Timestamp(start.getTime())); + ps.setTimestamp(2, new Timestamp(end.getTime())); + ps.setTimestamp(3, new Timestamp(start.getTime())); + ps.setTimestamp(4, new Timestamp(end.getTime())); + ResultSet rs = ps.executeQuery(); + + transformer.startStatistics(start, end); + while (rs.next()) { + transformer.startEntry(); + transformer.writeAccessPointIdentifier(rs.getString("ap")); + transformer.writeDirection(rs.getString("direction")); + transformer.writePeriod(rs.getString("period")); + transformer.writeParticipantIdentifier(rs.getString("ppid")); + transformer.writeDocumentType(rs.getString("doc_type")); + transformer.writeProfileId(rs.getString("profile")); + transformer.writeChannel(rs.getString("channel")); + transformer.writeCount(rs.getInt("count")); + transformer.endEntry(); + } + transformer.endStatistics(); + } catch (SQLException e) { + throw new IllegalStateException("SQL error:" + e, e); + } finally { + DataSourceHelper.close(con); + } + } + + /** + * Composes the SQL query to persist raw statistics into the DBMS. + */ + abstract String getPersistSqlQueryText(); + + /** + * Composes the SQL query for retrieval of statistical data between a start and end data, + * with a granularity as supplied. + * + * @param granularity the granularity of the statics period reported. + */ + abstract String getRawStatisticsSqlQueryText(StatisticsGranularity granularity); + +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMsSqlImpl.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMsSqlImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..333bc745f40bca33f9928973510f0009ea22ee89 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMsSqlImpl.java @@ -0,0 +1,116 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import network.oxalis.persistence.annotation.Repository; +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.statistics.api.StatisticsGranularity; + +import javax.inject.Inject; + +/** + * This is RawStatisticsRepository implementation for running the statistics database on MsSql backend, through Jdbc. + * + * @author zeko78 + */ +@Repository +public class RawStatisticsRepositoryMsSqlImpl extends RawStatisticsRepositoryJdbcImpl { + + @Inject + public RawStatisticsRepositoryMsSqlImpl(JdbcTxManager jdbcTxManager) { + super(jdbcTxManager); + } + + /** + * Composes the SQL query to persist raw statistics into the DBMS. + */ + String getPersistSqlQueryText() { + return String.format("INSERT INTO %s (ap, tstamp, direction, sender, receiver, doc_type, profile, channel) " + + "values(?,?,?,?,?,?,?,?)", RawStatisticsRepositoryJdbcImpl.RAW_STATS_TABLE_NAME); + } + + /** + * Composes the SQL query for retrieval of statistical data between a start and end data, with + * a granularity as supplied. + * + * @param granularity the granularity of the statics period reported. + */ + String getRawStatisticsSqlQueryText(StatisticsGranularity granularity) { + String granularityQuery = granularityQuery(granularity); + String sql = "SELECT\n" + + " ap,\n" + + " 'OUT' direction,\n" + + " " + granularityQuery + " period,\n" + + " sender ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(*) count\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'OUT'\n" + + " and tstamp between ? and ?\n" + + "GROUP BY ap,direction," + granularityQuery + ",sender,doc_type,profile,channel\n" + + "union\n" + + "SELECT\n" + + " ap,\n" + + " 'IN' direction,\n" + + " " + granularityQuery + " period,\n" + + " receiver ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(*) count\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'IN'\n" + + " and tstamp between ? and ?\n" + + "\n" + + "GROUP BY ap,direction," + granularityQuery + ",receiver,doc_type,profile,channel\n" + + "order by period, ap\n" + + ";"; + + return sql; + } + + /** + * Return the currect date_format parameter for the chosen granularity + */ + static String granularityQuery(StatisticsGranularity granularity) { + switch (granularity) { + case YEAR: + return "LEFT(CONVERT(VARCHAR, CONVERT(datetime, tstamp, 121), 121), 4)"; + case MONTH: + return "LEFT(CONVERT(VARCHAR, CONVERT(datetime, tstamp, 121), 121), 7)"; + case DAY: + return "LEFT(CONVERT(VARCHAR, CONVERT(datetime, tstamp, 121), 121), 10)"; + case HOUR: + return "REPLACE(LEFT(CONVERT(VARCHAR, CONVERT(datetime, tstamp, 121), 121), 13), ' ', 'T')"; + default: + throw new IllegalArgumentException(String.format( + "Unable to convert '%s' into a MsSQL function string", granularity)); + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMySqlImpl.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMySqlImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..68d08e19006d8bcc1e649fa9e9c47de09c49ed40 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMySqlImpl.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.persistence.annotation.Repository; +import network.oxalis.statistics.api.StatisticsGranularity; + +import javax.inject.Inject; + +/** + * This is RawStatisticsRepository implementation for running the statistics database on MySql backend, through JDBC. + * + * @author steinar + * @author zeko78 + */ +@Repository +public class RawStatisticsRepositoryMySqlImpl extends RawStatisticsRepositoryJdbcImpl { + + @Inject + public RawStatisticsRepositoryMySqlImpl(JdbcTxManager jdbcTxManager) { + super(jdbcTxManager); + } + + /** + * Composes the SQL query to persist raw statistics into the DBMS. + */ + @Override + String getPersistSqlQueryText() { + return String.format("INSERT INTO %s (ap, tstamp, direction, sender, receiver, doc_type, profile, channel) " + + "values(?,?,?,?,?,?,?,?)", RawStatisticsRepositoryJdbcImpl.RAW_STATS_TABLE_NAME); + } + + /** + * Composes the SQL query for retrieval of statistical data between a start and end data, with + * a granularity as supplied. + * + * @param granularity the granularity of the statics period reported. + */ + @Override + String getRawStatisticsSqlQueryText(StatisticsGranularity granularity) { + String mySqlDateFormat = mySqlDateFormat(granularity); + return "SELECT\n" + + " ap,\n" + + " 'OUT' direction,\n" + + " date_format(tstamp,'" + mySqlDateFormat + "') period,\n" + + " sender ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(*) count\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'OUT'\n" + + " and tstamp between ? and ?\n" + + "GROUP BY 1,2,3,4,5,6,7\n" + + "union\n" + + "SELECT\n" + + " ap,\n" + + " 'IN' direction,\n" + + " date_format(tstamp,'" + mySqlDateFormat + "') period,\n" + + " receiver ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(*) count\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'IN'\n" + + " and tstamp between ? and ?\n" + + "\n" + + "GROUP BY 1,2,3,4,5,6,7\n" + + "order by period, ap\n" + + ";"; + } + + /** + * Return the correct date_format parameter for the chosen granularity + */ + static String mySqlDateFormat(StatisticsGranularity granularity) { + switch (granularity) { + case YEAR: + return "%Y"; + case MONTH: + return "%Y-%m"; + case DAY: + return "%Y-%m-%d"; + case HOUR: + return "%Y-%m-%dT%h"; + default: + throw new IllegalArgumentException(String.format( + "Unable to convert '%s' into a MySQL date_format() string.", granularity)); + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryOracleImpl.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryOracleImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..400d5b6c8c3e861885ae755951cc1ebb26f743dd --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryOracleImpl.java @@ -0,0 +1,142 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import network.oxalis.persistence.annotation.Repository; +import network.oxalis.persistence.api.JdbcTxManager; +import network.oxalis.statistics.api.RawStatistics; +import network.oxalis.statistics.api.StatisticsGranularity; +import network.oxalis.statistics.util.DataSourceHelper; + +import javax.inject.Inject; +import java.sql.*; + +/** + * This is RawStatisticsRepository implementation for running the statistics database on Oracle backend, through JDBC. + * + * @author thore + */ +@Repository +public class RawStatisticsRepositoryOracleImpl extends RawStatisticsRepositoryJdbcImpl { + + @Inject + public RawStatisticsRepositoryOracleImpl(JdbcTxManager jdbcTxManager) { + super(jdbcTxManager); + } + + @Override + public Integer persist(RawStatistics rawStatistics) { + Connection con = null; + PreparedStatement ps; + Integer result = 0; + try { + con = jdbcTxManager.getConnection(); + String sqlStatement = this.getPersistSqlQueryText(); + + // Oracle does not support Statement.RETURN_GENERATED_KEYS, so return the trigger generated "id" column + ps = con.prepareStatement(sqlStatement, new String[]{"id"}); + ps.setString(1, rawStatistics.getAccessPointIdentifier().toString()); + ps.setTimestamp(2, new Timestamp(rawStatistics.getDate().getTime())); + ps.setString(3, rawStatistics.getDirection().toString()); + ps.setString(4, rawStatistics.getSender().getIdentifier()); + ps.setString(5, rawStatistics.getReceiver().getIdentifier()); + ps.setString(6, rawStatistics.getDocumentTypeIdentifier().toString()); + ps.setString(7, rawStatistics.getProcessIdentifier().toString()); + ps.setString(8, rawStatistics.getChannelId() == null ? null : rawStatistics.getChannelId().stringValue()); + + ps.executeUpdate(); + ResultSet rs = ps.getGeneratedKeys(); + if (rs.next()) { + result = rs.getInt(1); + rs.close(); + } + } catch (SQLException e) { + throw new IllegalStateException("Unable to execute statement " + e, e); + } finally { + DataSourceHelper.close(con); + } + return result; + } + + @Override + String getPersistSqlQueryText() { + return String.format("INSERT INTO %s (ap, tstamp, direction, sender, receiver, doc_type, profile, channel) values (?,?,?,?,?,?,?,?)", RawStatisticsRepositoryJdbcImpl.RAW_STATS_TABLE_NAME); + } + + @Override + String getRawStatisticsSqlQueryText(StatisticsGranularity granularity) { + String dateFormatWithSelectedGranularity = oracleDateFormat(granularity); + return "SELECT\n" + + " ap,\n" + + " 'OUT' direction,\n" + + " TO_CHAR(tstamp,'" + dateFormatWithSelectedGranularity + "') period,\n" + + " sender ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(*) count\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'OUT'\n" + + " and tstamp between ? and ?\n" + + "GROUP BY 1,2,3,4,5,6,7\n" + + "union\n" + + "SELECT\n" + + " ap,\n" + + " 'IN' direction,\n" + + " TO_CHAR(tstamp,'" + dateFormatWithSelectedGranularity + "') period,\n" + + " receiver ppid,\n" + + " doc_type,\n" + + " profile,\n" + + " channel,\n" + + " COUNT(*) count\n" + + "FROM\n" + + " raw_stats\n" + + "WHERE\n" + + " direction = 'IN'\n" + + " and tstamp between ? and ?\n" + + "\n" + + "GROUP BY 1,2,3,4,5,6,7\n" + + "order by period, ap\n"; + } + + /** + * Return the currect date_format parameter for the chosen granularity + */ + private String oracleDateFormat(StatisticsGranularity granularity) { + switch (granularity) { + case YEAR: + return "YYYY"; + case MONTH: + return "YYYY-MM"; + case DAY: + return "YYYY-MM-DD"; + case HOUR: + return "YYYY-MM-DDT%HH24"; + default: + throw new IllegalArgumentException(String.format( + "Unable to convert '%s' into a Oracle date format string.", granularity)); + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/model/AbstractStatistics.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/model/AbstractStatistics.java new file mode 100644 index 0000000000000000000000000000000000000000..4b7f224d4ee058d336e40437fdcedeb4c670356b --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/model/AbstractStatistics.java @@ -0,0 +1,169 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.model; + +import network.oxalis.api.model.AccessPointIdentifier; +import network.oxalis.api.model.Direction; +import network.oxalis.statistics.api.ChannelId; +import network.oxalis.statistics.api.RawStatistics; +import network.oxalis.vefa.peppol.common.model.DocumentTypeIdentifier; +import network.oxalis.vefa.peppol.common.model.ProcessIdentifier; + +import java.util.Date; + +/** + * Basic collection of statistics held for a given transmission + * + * @author steinar + * Date: 25.03.13 + * Time: 14:09 + */ +abstract class AbstractStatistics implements RawStatistics { + + AccessPointIdentifier accessPointIdentifier; + + Date date; + + Direction direction; + + DocumentTypeIdentifier peppolDocumentTypeId; + + ChannelId channelId; + + ProcessIdentifier processIdentifier; + + AbstractStatistics(AbstractBuilder abstractBuilder) { + this.processIdentifier = abstractBuilder.peppolProcessTypeId; + this.peppolDocumentTypeId = abstractBuilder.peppolDocumentTypeId; + this.accessPointIdentifier = abstractBuilder.accessPointIdentifier; + this.date = abstractBuilder.date; + this.direction = abstractBuilder.direction; + this.channelId = abstractBuilder.channelId; + } + + public Direction getDirection() { + return direction; + } + + public Date getDate() { + return date; + } + + public AccessPointIdentifier getAccessPointIdentifier() { + return accessPointIdentifier; + } + + public DocumentTypeIdentifier getDocumentTypeIdentifier() { + return peppolDocumentTypeId; + } + + public ChannelId getChannelId() { + return channelId; + } + + public ProcessIdentifier getProcessIdentifier() { + return processIdentifier; + } + + protected static abstract class AbstractBuilder { + + AccessPointIdentifier accessPointIdentifier; + + Date date = new Date(); + + Direction direction; + + DocumentTypeIdentifier peppolDocumentTypeId; + + ProcessIdentifier peppolProcessTypeId; + + ChannelId channelId; + + public T date(Date dt) { + this.date = dt; + return getThis(); + } + + public T accessPointIdentifier(AccessPointIdentifier accessPointIdentifier) { + this.accessPointIdentifier = accessPointIdentifier; + return getThis(); + } + + + public T direction(Direction direction) { + this.direction = direction; + return getThis(); + } + + public T outbound() { + this.direction = Direction.OUT; + return getThis(); + } + + public T inbound() { + this.direction = Direction.IN; + return getThis(); + } + + public T documentType(DocumentTypeIdentifier peppolDocumentTypeId) { + this.peppolDocumentTypeId = peppolDocumentTypeId; + return getThis(); + } + + public T profile(ProcessIdentifier processIdentifier) { + this.peppolProcessTypeId = processIdentifier; + return getThis(); + } + + public T channel(ChannelId channelId) { + this.channelId = channelId; + return getThis(); + } + + protected void checkRequiredFields() { + + if (direction == null) { + throw new IllegalStateException("Must specify the direction of the message"); + } + + if (accessPointIdentifier == null) { + throw new IllegalStateException("Identity of access point required"); + } + + if (peppolDocumentTypeId == null) { + throw new IllegalStateException("Document type required"); + } + if (peppolProcessTypeId == null) { + throw new IllegalStateException("Process id/profile id required"); + } + + if (date == null) { + throw new IllegalStateException("Date (period) required"); + } + } + + public abstract B build(); + + protected abstract T getThis(); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/model/DefaultRawStatistics.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/model/DefaultRawStatistics.java new file mode 100644 index 0000000000000000000000000000000000000000..ee2757d17ac364370131d57ea66173374c1098c2 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/model/DefaultRawStatistics.java @@ -0,0 +1,94 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.model; + +import network.oxalis.statistics.api.RawStatistics; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * Holds a raw statistics entry, which represents a single receipt or transmit operation. + *

+ * User: steinar + * Date: 30.01.13 + * Time: 20:35 + */ +public class DefaultRawStatistics extends AbstractStatistics implements RawStatistics { + + protected ParticipantIdentifier sender; + + protected ParticipantIdentifier receiver; + + private DefaultRawStatistics(RawStatisticsBuilder builder) { + super(builder); + this.sender = builder.sender; + this.receiver = builder.receiver; + + } + + @Override + public ParticipantIdentifier getSender() { + return sender; + } + + @Override + public ParticipantIdentifier getReceiver() { + return receiver; + } + + public static class RawStatisticsBuilder + extends AbstractStatistics.AbstractBuilder { + + ParticipantIdentifier sender; + + ParticipantIdentifier receiver; + + public RawStatisticsBuilder sender(ParticipantIdentifier sender) { + this.sender = sender; + return getThis(); + } + + public RawStatisticsBuilder receiver(ParticipantIdentifier receiver) { + this.receiver = receiver; + return getThis(); + } + + public DefaultRawStatistics build() { + + checkRequiredFields(); + + if (sender == null) { + throw new IllegalStateException("Must specify identity of sender"); + } + if (receiver == null) { + throw new IllegalStateException("Identity of receiver required"); + } + + return new DefaultRawStatistics(this); + } + + @Override + protected RawStatisticsBuilder getThis() { + return this; + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/OxalisCipher.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/OxalisCipher.java new file mode 100644 index 0000000000000000000000000000000000000000..9c35b0a5f3697d0b14f858d41983f6cf73efa949 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/OxalisCipher.java @@ -0,0 +1,126 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import javax.crypto.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + * Oxalis' cipher implementation. Encapsulates information required for encryption and decryption of data using + * a symmetric key. + * + * @author steinar + * Date: 06.05.13 + * Time: 21:22 + */ +public class OxalisCipher { + + // Advanced Encryption Standard (AES) with Electronic Cookbook Mode (ECB) block mode and PKCS5 Padding + // FIXME: Determine why specifying AES/ECB/PKCS5Padding fails when compiling with maven + public static final String SYMMETRIC_KEY_ALGORITHM = "AES"; + + /** + * Name of our encrypted (wrapped) symmetric key. Typically used in HTTP headers, name and value pairs, etc. + */ + public static final String WRAPPED_SYMMETRIC_KEY_HEADER_NAME = "PEPPOL-wrapped-key"; + + private SecretKey secretKey; + + public OxalisCipher() { + try { + KeyGenerator keyGenerator = KeyGenerator.getInstance(SYMMETRIC_KEY_ALGORITHM); + secretKey = keyGenerator.generateKey(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("Unable to create symmetric key for " + SYMMETRIC_KEY_ALGORITHM + e, e); + } + } + + public OxalisCipher(SecretKey secretKey) { + this.secretKey = secretKey; + } + + + /** + * Wraps the supplied OutputStream in a encrypted cipher stream, i.e. every plain text byte written + * into the new OutputStream is encrypted using our SecretKey. + * + * @param outputStream the plaint text output stream to encrypted + * @return a new OutputStream which will encrypt every byte written to it. + * @see #decryptStream(java.io.InputStream) + */ + public OutputStream encryptStream(OutputStream outputStream) { + Cipher cipher = createCipher(Cipher.ENCRYPT_MODE); + return new CipherOutputStream(outputStream, cipher); + } + + /** + * Wraps the supplied InputStream in a decrypted cipher stream, i.e. every encrypted byte read from + * the new InputStream reads is decrypted using our SecretKey. + * + * @param inputStream the encrypted input stream + * @return new InputStream which will decrypt every byte read from it. + */ + public InputStream decryptStream(InputStream inputStream) { + + Cipher cipher = createCipher(Cipher.DECRYPT_MODE); + return new CipherInputStream(inputStream, cipher); + } + + + Cipher createCipher(int encryptMode) { + if (secretKey == null) { + throw new IllegalStateException("No symmetric secret key available"); + } + + Cipher cipher = null; + try { + cipher = Cipher.getInstance(SYMMETRIC_KEY_ALGORITHM); + cipher.init(encryptMode, secretKey); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("Unable to create cipher for algorithm " + SYMMETRIC_KEY_ALGORITHM, e); + } catch (NoSuchPaddingException e) { + throw new IllegalStateException("Default padding does not work with algorithm " + SYMMETRIC_KEY_ALGORITHM, e); + } catch (InvalidKeyException e) { + throw new IllegalStateException("Invalid " + SYMMETRIC_KEY_ALGORITHM + " key"); + } + return cipher; + } + + + public SecretKey getSecretKey() { + return secretKey; + } + + byte[] encrypt(byte[] bytes) throws BadPaddingException, IllegalBlockSizeException { + Cipher cipher = createCipher(Cipher.ENCRYPT_MODE); + return cipher.doFinal(bytes); + } + + byte[] decrypt(byte[] encryptedBytes) throws BadPaddingException, IllegalBlockSizeException { + Cipher cipher = createCipher(Cipher.DECRYPT_MODE); + return cipher.doFinal(encryptedBytes); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/OxalisCipherConverter.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/OxalisCipherConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..93942532051c387745dc05c3a7a732984c00137e --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/OxalisCipherConverter.java @@ -0,0 +1,119 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; + +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; + +/** + * @author steinar + * Date: 14.05.13 + * Time: 09:57 + */ +public class OxalisCipherConverter { + + /** + * Creates an instance of OxalisCipher: + *

    + *
  1. Decodes the supplied hex string representation of a wrapped key into an array of bytes representation
  2. + *
  3. Creates a cipher, which is initialized with a private key
  4. + *
  5. Unwraps (decrypts) the secret key represented by an array of bytes into a SecretKey
  6. + *
  7. Creates an OxalisCipher using the unwrapped SecretKey
  8. + *
+ */ + public OxalisCipher createCipherFromWrappedHexKey(String wrappedSymmetricKeyAsHexString, PrivateKey privateKey) { + + // 1) Decodes the hex string representation of a wrapped key + byte[] encodedBytes = encodedBytesFromHexString(wrappedSymmetricKeyAsHexString); + + try { + // 2) Creates the Cipher using supplied private key + Cipher cipher = Cipher.getInstance(StatisticsKeyTool.ASYMMETRIC_KEY_ALGORITHM); + cipher.init(Cipher.UNWRAP_MODE, privateKey); + + // 3) Unwraps (decrypts) the secret key using our private key + SecretKey secretKey = (SecretKey) cipher.unwrap(encodedBytes, OxalisCipher.SYMMETRIC_KEY_ALGORITHM, Cipher.SECRET_KEY); + + // 4) creates the Oxalis cipher + OxalisCipher oxalisCipher = new OxalisCipher(secretKey); + return oxalisCipher; + + } catch (NoSuchAlgorithmException e) { + throw new UnwrapSymmetricKeyException(wrappedSymmetricKeyAsHexString, e); + } catch (NoSuchPaddingException e) { + throw new UnwrapSymmetricKeyException(wrappedSymmetricKeyAsHexString, e); + } catch (InvalidKeyException e) { + throw new UnwrapSymmetricKeyException(wrappedSymmetricKeyAsHexString, e); + } + } + + /** + * Encrypts the secret key (symmetric key) held inside the OxalisCipher instance using the supplied PublicKey, after + * which the resulting wrapped secret key is transformed into a hex string suitable for transmission, persistence etc. + * + * @param publicKey the public asymmetric key to use for encrypting the secret symmetric key + * @param oxalisCipher the instance of OxalisCipher in which the secret symmetric key is held. + * @return + */ + public String getWrappedSymmetricKeyAsString(PublicKey publicKey, OxalisCipher oxalisCipher) { + + try { + Cipher cipher = Cipher.getInstance(StatisticsKeyTool.ASYMMETRIC_KEY_ALGORITHM); + cipher.init(Cipher.WRAP_MODE, publicKey); + SecretKey secretKey = oxalisCipher.getSecretKey(); + byte[] encodedBytes = cipher.wrap(secretKey); + + return new String(Hex.encodeHex(encodedBytes)); + + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("Unable to create cipher with algorithm: " + StatisticsKeyTool.ASYMMETRIC_KEY_ALGORITHM, e); + } catch (NoSuchPaddingException e) { + throw new IllegalStateException("Unable to create cipher with default padding for algorithm " + StatisticsKeyTool.ASYMMETRIC_KEY_ALGORITHM, e); + } catch (InvalidKeyException e) { + throw new IllegalStateException("The public key is invalid " + e.getMessage(), e); + } catch (IllegalBlockSizeException e) { + throw new IllegalStateException("Error during encryption of symmetric key: " + e.getMessage(), e); + } + } + + + private byte[] encodedBytesFromHexString(String wrappedSymmetricKeyAsHexString) { + byte[] encodedBytes; + + try { + encodedBytes = Hex.decodeHex(wrappedSymmetricKeyAsHexString.toCharArray()); + } catch (DecoderException e) { + throw new IllegalArgumentException("Unable to decode hex string " + wrappedSymmetricKeyAsHexString + "; " + e.getMessage(), e); + } + return encodedBytes; + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/StatisticsKeyTool.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/StatisticsKeyTool.java new file mode 100644 index 0000000000000000000000000000000000000000..63919ff9ed607d0670dde259f251bfde755c202c --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/StatisticsKeyTool.java @@ -0,0 +1,167 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import lombok.extern.slf4j.Slf4j; + +import java.io.*; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; + +/** + * Provides various methods for generation, loading and saving private and public keys. + * + * @author steinar + * Date: 01.05.13 + * Time: 21:17 + */ +@Slf4j +public class StatisticsKeyTool { + + public static final String ASYMMETRIC_KEY_ALGORITHM = "RSA"; + + public static final String OXALIS_STATISTICS_PUBLIC_KEY = "oxalis-statistics-public.key"; + + public static final int MAX_LENGTH_OF_ENCODED_KEY = 4096; + + /** + * The Oxalis statistics public key is supplied as part of the distribution (of course). + * + * @return the statistics public key + */ + public PublicKey loadPublicKeyFromClassPath() { + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(OXALIS_STATISTICS_PUBLIC_KEY); + if (inputStream == null) { + throw new IllegalStateException("Unable to locate file " + OXALIS_STATISTICS_PUBLIC_KEY); + } + try { + byte[] bytes = loadBytesFrom(inputStream); + log.info("Loaded public key with " + bytes.length + " bytes"); + return publicKeyFromBytes(bytes); + + } catch (InvalidKeySpecException e) { + throw new IllegalStateException("Invalid public key encoded in " + OXALIS_STATISTICS_PUBLIC_KEY, e); + } finally { + try { + inputStream.close(); + } catch (IOException e) { + throw new IllegalStateException("Unable to close input stream for " + OXALIS_STATISTICS_PUBLIC_KEY, e); + } + } + } + + /** + * Loads the public key used for encrypting statistical data. + * + * @param file + * @return + */ + public PublicKey loadPublicKey(File file) { + try { + byte[] encodedPublicKey = loadBytesFromFile(file); + + return publicKeyFromBytes(encodedPublicKey); + + } catch (InvalidKeySpecException e) { + throw new IllegalStateException("Unable to create key from encoded specification in " + file.getAbsolutePath() + "; " + e.getMessage(), e); + } + + } + + + File getPublicKeyFile() { + return new File(getResourceDirectory(), OXALIS_STATISTICS_PUBLIC_KEY); + } + + + /** + * Provides the name of the temporary directory into which generated keys will be stored. + * + * @return + */ + File getResourceDirectory() { + String tempDirName = System.getProperty("java.io.tmpdir"); + return new File(tempDirName); + } + + + private PublicKey publicKeyFromBytes(byte[] encodedPublicKey) throws InvalidKeySpecException { + X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(encodedPublicKey); + + KeyFactory keyFactory = createKeyFactory(); + return keyFactory.generatePublic(x509EncodedKeySpec); + } + + + private byte[] loadBytesFromFile(File file) { + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(file); + + return loadBytesFrom(fileInputStream); + } catch (FileNotFoundException e) { + throw new IllegalStateException("Unable to open file " + file.getAbsolutePath()); + } finally { + if (fileInputStream != null) { + try { + fileInputStream.close(); + } catch (IOException e) { + throw new IllegalStateException("Unable to close file " + file.getAbsolutePath(), e); + } + } + } + } + + private byte[] loadBytesFrom(InputStream inputStream) { + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + int nRead; + byte[] data = new byte[MAX_LENGTH_OF_ENCODED_KEY]; + + try { + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + buffer.flush(); + } catch (IOException e) { + log.warn(e.getMessage(), e); + } + return buffer.toByteArray(); + + } + + private KeyFactory createKeyFactory() { + try { + KeyFactory keyFactory = KeyFactory.getInstance(ASYMMETRIC_KEY_ALGORITHM); + return keyFactory; + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException("Unable to create key factory with algorithm " + ASYMMETRIC_KEY_ALGORITHM + "; " + e.getMessage(), e); + } + } + +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/UnwrapSymmetricKeyException.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/UnwrapSymmetricKeyException.java new file mode 100644 index 0000000000000000000000000000000000000000..94504052b15d98fb9c2db3bbd375c4521ad4748c --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/security/UnwrapSymmetricKeyException.java @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import java.security.GeneralSecurityException; + +/** + * @author steinar + * Date: 13.05.13 + * Time: 12:56 + */ +public class UnwrapSymmetricKeyException extends RuntimeException { + + public UnwrapSymmetricKeyException(String encodedSymmetricKey, GeneralSecurityException cause) { + super("Unable to unwrap and decrypt wrapped symmetric key; " + cause.getMessage(), cause); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/service/DefaultStatisticsService.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/service/DefaultStatisticsService.java new file mode 100644 index 0000000000000000000000000000000000000000..b7e5e9566c16baa0813d43ff281db6f54a678242 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/service/DefaultStatisticsService.java @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.service; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import io.opentracing.Span; +import io.opentracing.Tracer; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.model.AccessPointIdentifier; +import network.oxalis.api.model.Direction; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.statistics.StatisticsService; +import network.oxalis.api.util.Type; +import network.oxalis.commons.security.CertificateUtils; +import network.oxalis.commons.tracing.Traceable; +import network.oxalis.statistics.api.ChannelId; +import network.oxalis.statistics.api.RawStatisticsRepository; +import network.oxalis.statistics.model.DefaultRawStatistics; + +@Slf4j +@Singleton +@Type("default") +class DefaultStatisticsService extends Traceable implements StatisticsService { + + private final RawStatisticsRepository rawStatisticsRepository; + + @Inject + public DefaultStatisticsService(RawStatisticsRepository rawStatisticsRepository, Tracer tracer) { + super(tracer); + this.rawStatisticsRepository = rawStatisticsRepository; + } + + @Override + public void persist(TransmissionRequest transmissionRequest, TransmissionResponse transmissionResponse, Span root) { + Span span = tracer.buildSpan("persist statistics").asChildOf(root).start(); + try { + String protocolName = transmissionRequest.getEndpoint().getTransportProfile().getIdentifier(); + String receivingAccessPointCommonName = transmissionRequest.getEndpoint().getCertificate() != null ? CertificateUtils + .extractCommonName(transmissionRequest.getEndpoint().getCertificate()) : ""; + + DefaultRawStatistics rawStatistics = new DefaultRawStatistics.RawStatisticsBuilder() + .accessPointIdentifier(new AccessPointIdentifier(receivingAccessPointCommonName)) + .direction(Direction.OUT) + .documentType(transmissionResponse.getHeader().getDocumentType()) + .sender(transmissionResponse.getHeader().getSender()) + .receiver(transmissionResponse.getHeader().getReceiver()) + .profile(transmissionResponse.getHeader().getProcess()) + .channel(new ChannelId(protocolName)) + .date(transmissionResponse.getTimestamp()) // Time stamp of reception of the receipt + .build(); + + rawStatisticsRepository.persist(rawStatistics); + } catch (Exception ex) { + span.setTag("exception", String.valueOf(ex.getMessage())); + log.error("Persisting DefaultRawStatistics about outbound transmission failed : {}", ex.getMessage(), ex); + } finally { + span.finish(); + } + } + + @Override + public void persist(InboundMetadata inboundMetadata) { + // Persists raw statistics when message was received (ignore if stats couldn't be persisted, just warn) + try { + String protocolName = inboundMetadata.getProtocol().getIdentifier(); + String sendingAccessPointCommonName = CertificateUtils.extractCommonName(inboundMetadata.getCertificate()); + + DefaultRawStatistics rawStatistics = new DefaultRawStatistics.RawStatisticsBuilder() + .accessPointIdentifier(new AccessPointIdentifier(sendingAccessPointCommonName)) + .direction(Direction.IN) + .documentType(inboundMetadata.getHeader().getDocumentType()) + .sender(inboundMetadata.getHeader().getSender()) + .receiver(inboundMetadata.getHeader().getReceiver()) + .profile(inboundMetadata.getHeader().getProcess()) + .channel(new ChannelId(protocolName)) + .build(); + + rawStatisticsRepository.persist(rawStatistics); + } catch (Exception e) { + log.error("Unable to persist statistics for " + inboundMetadata.toString() + ";\n " + e.getMessage(), e); + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/service/StatisticsModule.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/service/StatisticsModule.java new file mode 100644 index 0000000000000000000000000000000000000000..70d5c7961814551791cc0be3986223844ff7ab0d --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/service/StatisticsModule.java @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.service; + +import network.oxalis.api.statistics.StatisticsService; +import network.oxalis.commons.guice.OxalisModule; + +public class StatisticsModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(StatisticsService.class, DefaultStatisticsService.class); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/DataSourceHelper.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/DataSourceHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..51745135d27beb4caef9278fd8a2848f9fbc3f40 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/DataSourceHelper.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.util; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author steinar + * Date: 15.08.13 + * Time: 15:50 + */ +public class DataSourceHelper { + + public static void close(Connection con) { + if (con != null) { + try { + con.close(); + } catch (SQLException e) { + throw new IllegalStateException("Unable to close JDBC connection " + con); + } + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/JdbcHelper.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/JdbcHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..fcf9bb06642c688d91421aa6e47521dbdca8b680 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/JdbcHelper.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.util; + +import java.util.Calendar; +import java.util.Date; + +/** + * @author steinar + * Date: 15.08.13 + * Time: 16:13 + */ +public class JdbcHelper { + + public static Date setEndDateIfNull(Date end) { + if (end == null) { + end = new Date(); + } + return end; + } + + public static Date setStartDateIfNull(Date start) { + Date result = start; + if (start == null) { + Calendar calendar = Calendar.getInstance(); + calendar.set(2013, Calendar.FEBRUARY, 1); + result = calendar.getTime(); + } + + return result; + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/StatisticsToXmlTransformer.java b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/StatisticsToXmlTransformer.java new file mode 100644 index 0000000000000000000000000000000000000000..0ba96c920624a05cf51da9e3bd53794fa50ff49b --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/java/network/oxalis/statistics/util/StatisticsToXmlTransformer.java @@ -0,0 +1,156 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.util; + + +import network.oxalis.statistics.api.StatisticsTransformer; + +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import java.io.OutputStream; +import java.util.Date; + +/** + * User: steinar + * Date: 24.02.13 + * Time: 10:36 + */ +public class StatisticsToXmlTransformer implements StatisticsTransformer { + + private final OutputStream outputStream; + + private XMLStreamWriter xmlStreamWriter; + + public StatisticsToXmlTransformer(OutputStream outputStream) { + + if (outputStream == null) { + throw new IllegalArgumentException("Required argument outputStream is null"); + } + this.outputStream = outputStream; + } + + @Override + public void startStatistics(Date start, Date end) { + XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); + + try { + xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(outputStream, "UTF-8"); + xmlStreamWriter.writeStartDocument("UTF-8", "1.0"); + // TODO: consider the use of a name space? + xmlStreamWriter.writeStartElement(STATISTICS_DOCUMENT_START_ELEMENT_NAME); + + String startString = String.format("%tF %tR", start, start); + xmlStreamWriter.writeAttribute("start", startString); + + String endString = String.format("%tF %tR", end, end); + xmlStreamWriter.writeAttribute("end", endString); + + } catch (XMLStreamException e) { + throw new IllegalStateException("Unable to create XML stream writer; " + e.getMessage(), e); + } + } + + @Override + public void startEntry() { + + try { + xmlStreamWriter.writeStartElement(ENTRY_START_ELEMENT_NAME); + } catch (XMLStreamException e) { + throw new IllegalStateException("Unable to write element " + STATISTICS_DOCUMENT_START_ELEMENT_NAME + "; " + e, e); + } + } + + @Override + public void writeAccessPointIdentifier(String accessPointIdentifier) { + writeElementAndContents(ACCESS_POINT_ID_ELEMENT_NAME, accessPointIdentifier); + } + + @Override + public void writePeriod(String period) { + writeElementAndContents(PERIOD_ELEMENT_NAME, period); + } + + @Override + public void writeDirection(String direction) { + writeElementAndContents(DIRECTION_ELEMENT_NAME, direction); + } + + private void writeElementAndContents(String elementName, String contents) { + try { + xmlStreamWriter.writeStartElement(elementName); + if (contents != null) { + xmlStreamWriter.writeCharacters(contents); + } + xmlStreamWriter.writeEndElement(); + } catch (XMLStreamException e) { + throw new IllegalStateException("Unable to write " + elementName + " element with value of " + contents + "; " + e, e); + } + } + + @Override + public void writeParticipantIdentifier(String participantId) { + writeElementAndContents(PARTICIPANT_ID_ELEMENT_NAME, participantId); + } + + @Override + public void writeDocumentType(String documentType) { + writeElementAndContents(DOCUMENT_TYPE_ELEMENT_NAME, documentType); + } + + @Override + public void writeProfileId(String profileId) { + writeElementAndContents(PROFILE_ID_ELEMENT_NAME, profileId); + } + + @Override + public void writeChannel(String channel) { + writeElementAndContents(CHANNEL_ELEMENT_NAME, channel); + } + + @Override + public void writeCount(int count) { + writeElementAndContents(COUNT_ELEMENT_NAME, "" + count); + } + + @Override + public void endEntry() { + try { + xmlStreamWriter.writeEndElement(); + } catch (XMLStreamException e) { + throw new IllegalStateException("Unable to write statistics end element " + e, e); + } + + } + + @Override + public void endStatistics() { + + try { + xmlStreamWriter.writeEndDocument(); + xmlStreamWriter.flush(); + } catch (XMLStreamException e) { + throw new IllegalStateException("Unable to write end of statistics document; " + e.getMessage(), e); + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/main/resources/oxalis-statistics-public.key b/oxalis-legacy/oxalis-statistics/src/main/resources/oxalis-statistics-public.key new file mode 100644 index 0000000000000000000000000000000000000000..0aa7b87be1329e4896feef72b480d53f98917e5a Binary files /dev/null and b/oxalis-legacy/oxalis-statistics/src/main/resources/oxalis-statistics-public.key differ diff --git a/oxalis-legacy/oxalis-statistics/src/main/resources/reference.conf b/oxalis-legacy/oxalis-statistics/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..9da0b39be064b7331cffa29f271e653011b0aa88 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/resources/reference.conf @@ -0,0 +1,8 @@ +oxalis.module.statistics.repository.class = network.oxalis.statistics.guice.RawStatisticsRepositoryModule + +oxalis.module.statistics.inbound = { + class = network.oxalis.statistics.inbound.StatisticsInboundModule + dependency = inbound.servlet +} + +oxalis.module.statistics.default.class = network.oxalis.statistics.service.StatisticsModule \ No newline at end of file diff --git a/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-h2.sql b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-h2.sql new file mode 100644 index 0000000000000000000000000000000000000000..ca0e1d3a5d42108ecb86f0ba7392bfdc92eb1277 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-h2.sql @@ -0,0 +1,21 @@ + +drop table if exists raw_stats; + + +/** + * Creates the table to hold the raw statistics, which everybody needs. + */ +create table if not exists raw_stats( + id integer auto_increment primary key, + ap varchar(35) not null, + tstamp timestamp not null default current_timestamp, + direction varchar(8), + sender varchar(35) not null, + receiver varchar(35) not null, + doc_type varchar(255) not null, + profile varchar(255) , + channel varchar(255), + CONSTRAINT unique_direction_stats check(direction in ('IN','OUT')) + +); + diff --git a/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-hsqldb.sql b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-hsqldb.sql new file mode 100644 index 0000000000000000000000000000000000000000..ca78d373a1797a359190994f3ed02dd884b12278 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-hsqldb.sql @@ -0,0 +1,13 @@ +create table if not exists raw_stats( + id integer generated by default as identity (start with 1) primary key, + ap varchar(35) not null, + tstamp timestamp with time zone default current_timestamp, + direction varchar(8) not null, + sender varchar(35) not null, + receiver varchar(35) not null, + doc_type varchar(255) not null, + profile varchar(255) , + channel varchar(255) +); + +grant all on raw_stats to skrue; \ No newline at end of file diff --git a/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-mssql.sql b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-mssql.sql new file mode 100644 index 0000000000000000000000000000000000000000..fb9fe7acfd6a180839f5d076da0dc259a5e3bab7 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-mssql.sql @@ -0,0 +1,16 @@ +/** + * MICROSOFT SQL SERVER ADAPTED SQL (raw_stats-mssql.sql) + */ +create table raw_stats( + id integer identity(1,1) primary key, + ap varchar(35) not null, + tstamp datetime not null default current_timestamp, + direction varchar(8), + sender varchar(35) not null, + receiver varchar(35) not null, + doc_type varchar(255) not null, + profile varchar(255) , + channel varchar(255), + CONSTRAINT unique_direction_stats check(direction in ('IN','OUT')), + +); diff --git a/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-mysql.sql b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-mysql.sql new file mode 100644 index 0000000000000000000000000000000000000000..81cc136b383d87d3222e767b5d1ff346e4a71000 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-mysql.sql @@ -0,0 +1,14 @@ +/** + * Creates the table to hold the raw statistics, which everybody needs. + */ +create table if not exists raw_stats( + id integer auto_increment primary key, + ap varchar(35) not null, + tstamp timestamp default current_timestamp, + direction enum('IN','OUT'), + sender varchar(35) not null, + receiver varchar(35) not null, + doc_type varchar(255) not null, + profile varchar(255) , + channel varchar(255) +); diff --git a/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-oracle.sql b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-oracle.sql new file mode 100644 index 0000000000000000000000000000000000000000..9dfbba5625daefccd1e38a11516518653ac1de64 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/main/resources/sql/raw_stats-oracle.sql @@ -0,0 +1,44 @@ +-- ========================================== +-- ORACLE ADAPTED SQL (raw_stats-oracle.sql) +-- ========================================== + +-- drop trigger raw_stats_trg; +-- drop table /* if exists */ raw_stats; +-- drop sequence raw_stats_seq; + +create sequence raw_stats_seq start with 1 increment by 1 nocache; + +create table raw_stats ( + id integer /* auto_increment */ primary key, + ap varchar(35) not null, + tstamp timestamp default current_timestamp, + direction /* enum */ VARCHAR2(8) CHECK( direction IN ('IN','OUT') ), + sender varchar(35) not null, + receiver varchar(35) not null, + doc_type varchar(255) not null, + profile varchar(255), + channel varchar(255) +); + +CREATE OR REPLACE TRIGGER raw_stats_trg + BEFORE INSERT ON raw_stats FOR EACH ROW +BEGIN + IF :NEW.id IS NULL THEN + SELECT raw_stats_seq.NEXTVAL INTO :NEW.id FROM DUAL; + END IF; +END; + +-- desc raw_stats; +-- insert into raw_stats (ap, direction, sender, receiver, doc_type) values ('ap', 'OUT', 'sender', 'receiver', 'invoice'); + + + + + + + + + + + + diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/inbound/StatisticsServletTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/inbound/StatisticsServletTest.java new file mode 100644 index 0000000000000000000000000000000000000000..66145c88da8a85065adf637228c6dc7c50c5e84f --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/inbound/StatisticsServletTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.inbound; + +import com.google.inject.Injector; +import network.oxalis.inbound.OxalisGuiceContextListener; +import network.oxalis.test.jetty.AbstractJettyServerTest; +import org.testng.Assert; +import org.testng.annotations.Test; + +import javax.servlet.http.HttpServletResponse; +import java.net.HttpURLConnection; +import java.net.URL; + +@Test +public class StatisticsServletTest extends AbstractJettyServerTest { + + @Override + public Injector getInjector() { + return new OxalisGuiceContextListener().getInjector(); + } + + @Test + public void emptyGet() throws Exception { + HttpURLConnection httpURLConnection = + (HttpURLConnection) new URL("http://localhost:8080/statistics/").openConnection(); + + Assert.assertEquals(httpURLConnection.getResponseCode(), HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + @Test + public void post() throws Exception { + HttpURLConnection httpURLConnection = + (HttpURLConnection) new URL("http://localhost:8080/statistics/").openConnection(); + httpURLConnection.setRequestMethod("POST"); + + Assert.assertEquals(httpURLConnection.getResponseCode(), HttpServletResponse.SC_OK); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryModuleTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryModuleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6dd8a58085a311682a5eb24d7f9e7cc8279627fb --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryModuleTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import com.google.inject.CreationException; +import com.google.inject.Guice; +import network.oxalis.statistics.guice.RawStatisticsRepositoryModule; +import org.testng.annotations.Test; + +import static org.testng.Assert.fail; + +/** + * @author steinar + * Date: 28.10.2016 + * Time: 08.38 + */ +public class RawStatisticsRepositoryModuleTest { + + @Test + public void testConfigure() throws Exception { + + try { + Guice.createInjector(new RawStatisticsRepositoryModule()); + fail("Should not be able to create injector with supplying a module providing \n" + + "an instance of DataSource and Settings"); + } catch (CreationException e) { + // As expected + } + } + +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMySqlMockTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMySqlMockTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4f2afd29cdb947ba391f4f3002c610e1edb77fed --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryMySqlMockTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.statistics.api.ChannelId; +import network.oxalis.statistics.api.RawStatisticsRepository; +import network.oxalis.statistics.api.StatisticsGranularity; +import network.oxalis.statistics.guice.RawStatisticsRepositoryModule; +import network.oxalis.statistics.model.DefaultRawStatistics; +import network.oxalis.test.identifier.PeppolDocumentTypeIdAcronym; +import network.oxalis.test.identifier.PeppolProcessTypeIdAcronym; +import network.oxalis.api.model.AccessPointIdentifier; +import network.oxalis.persistence.annotation.Transactional; +import network.oxalis.persistence.platform.MySQLPlatform; +import network.oxalis.persistence.platform.PlatformModule; +import network.oxalis.persistence.testng.PersistenceModuleFactory; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import org.h2.tools.RunScript; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.sql.DataSource; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +/** + * Tests the MySQL implementation + * + * @author steinar + * Date: 26.03.13 + * Time: 10:38 + * @author erlend + */ +@Guice(moduleFactory = PersistenceModuleFactory.class, + modules = {RawStatisticsRepositoryModule.class, PlatformModule.class}) +public class RawStatisticsRepositoryMySqlMockTest { + + @Inject + @Named(MySQLPlatform.IDENTIFIER) + private RawStatisticsRepository repository; + + @Inject + private DataSource dataSource; + + @BeforeClass + @Transactional + public void beforeClass() throws Exception { + RunScript.execute(dataSource.getConnection(), new InputStreamReader( + getClass().getResourceAsStream(PersistenceModuleFactory.CREATE_OXALIS_DBMS_H2_SQL), + StandardCharsets.UTF_8)); + } + + @Test + public void testPersist() throws Exception { + + assertTrue(repository instanceof RawStatisticsRepositoryMySqlImpl); + + DefaultRawStatistics rawStatistics = new DefaultRawStatistics.RawStatisticsBuilder() + .accessPointIdentifier(new AccessPointIdentifier("AP_SendRegning")) + .outbound() + .sender(ParticipantIdentifier.of("9908:810017902")) + .receiver(ParticipantIdentifier.of("9908:810017902")) + .channel(new ChannelId("CH01")) + .documentType(PeppolDocumentTypeIdAcronym.INVOICE.toVefa()) + .profile(PeppolProcessTypeIdAcronym.INVOICE_ONLY.toVefa()) + .build(); + repository.persist(rawStatistics); + } + + @Test + public void testMySqlDateFormatYear() throws Exception { + String s = RawStatisticsRepositoryMySqlImpl.mySqlDateFormat(StatisticsGranularity.YEAR); + assertEquals(s, "%Y"); + } + + @Test + public void testMySqlDateFormatMonth() throws Exception { + String s = RawStatisticsRepositoryMySqlImpl.mySqlDateFormat(StatisticsGranularity.MONTH); + assertEquals(s, "%Y-%m"); + } + + @Test + public void testMySqlDateFormatDay() throws Exception { + String s = RawStatisticsRepositoryMySqlImpl.mySqlDateFormat(StatisticsGranularity.DAY); + assertEquals(s, "%Y-%m-%d"); + } + + @Test + public void testMySqlDateFormatHour() throws Exception { + String s = RawStatisticsRepositoryMySqlImpl.mySqlDateFormat(StatisticsGranularity.HOUR); + assertEquals(s, "%Y-%m-%dT%h"); + } + +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a8de2657afad79aecfeeaf60992f4d4410dc26e0 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/jdbc/RawStatisticsRepositoryTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.jdbc; + +import network.oxalis.persistence.platform.PlatformModule; +import network.oxalis.persistence.testng.PersistenceModuleFactory; +import network.oxalis.statistics.api.RawStatisticsRepository; +import network.oxalis.statistics.guice.RawStatisticsRepositoryModule; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.inject.Inject; + +import static org.testng.Assert.assertNotNull; + +/** + * @author steinar + * Date: 28.10.2016 + * Time: 17.23 + */ +@Guice(moduleFactory = PersistenceModuleFactory.class, + modules = {RawStatisticsRepositoryModule.class, PlatformModule.class}) +public class RawStatisticsRepositoryTest { + + @Inject + private RawStatisticsRepository rawStatisticsRepository; + + @Test + public void testInjection() { + assertNotNull(rawStatisticsRepository); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/EncryptionTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/EncryptionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..34a965fb914c244011470b4eede3b93345e61f7d --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/EncryptionTest.java @@ -0,0 +1,252 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import javax.crypto.*; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.*; +import java.nio.charset.Charset; +import java.security.*; + +import static org.testng.Assert.assertEquals; + +/** + * @author steinar + * Date: 29.04.13 + * Time: 09:51 + */ +public class EncryptionTest { + + private KeyPair keyPair; + + private SecretKey secretKey; + + @BeforeClass + public void createKeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + keyPairGenerator.initialize(1024); // Medium security is fine + keyPair = keyPairGenerator.generateKeyPair(); + + KeyGenerator keyGenerator = KeyGenerator.getInstance("DES"); + keyGenerator.init(new SecureRandom()); + secretKey = keyGenerator.generateKey(); + } + + + @Test() + public void encryptData() throws Exception { + + String plainText = "Hello world"; + byte[] encryptedBytes = encrypt(keyPair, plainText); + + String decryptedPlainText = decrypt(keyPair, encryptedBytes); + + assertEquals(decryptedPlainText, plainText); + + } + + + @Test + public void encryptAndDecryptFile() throws Exception { + + File file = File.createTempFile("oxalis", ".data"); + + // Writes encrypted data into file + Cipher encryptionCipher = Cipher.getInstance("DES/CFB8/NoPadding"); + encryptionCipher.init(Cipher.ENCRYPT_MODE, secretKey); + + + CipherOutputStream cipherOutputStream = new CipherOutputStream(new FileOutputStream(file), encryptionCipher); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(cipherOutputStream, Charset.forName("UTF-8")); + + String plainText = "Hello world"; + outputStreamWriter.write(plainText); + outputStreamWriter.close(); + + + // Reads and decrypts data from a file + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + Cipher cipher = Cipher.getInstance("DES/CFB8/NoPadding"); + AlgorithmParameters parameters = encryptionCipher.getParameters(); + System.err.println(parameters.toString()); + cipher.init(Cipher.DECRYPT_MODE, secretKey, parameters); + + Cipher symmetricCipher = cipher; + CipherInputStream cipherInputStream = new CipherInputStream(new FileInputStream(file), symmetricCipher); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(cipherInputStream, Charset.forName("UTF-8"))); + + String decryptedText = bufferedReader.readLine(); + assertEquals(decryptedText, plainText); + + file.delete(); + } + + + /** + * Experimental test method. Does not test any part of the system + * + * @throws Exception + */ + @Test + public void encryptDataWithWrappedKey() throws Exception { + + // Creates the shared key to be used for encrypting the data + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + Key sharedKey = keyGenerator.generateKey(); + + // Wraps the shared key within an asymmetric key + String password = "The quick brown fox jumped over the lazy dog"; + + byte[] salt = {0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x06, 0x08}; + + PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, 20); + PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray()); + + SecretKeyFactory kf = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); + SecretKey passwordKey = kf.generateSecret(pbeKeySpec); + + Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES"); + cipher.init(Cipher.WRAP_MODE, passwordKey, pbeParameterSpec); + byte[] wrappedSharedKey = cipher.wrap(sharedKey); + + + // Encrypt some data with shared key + cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, sharedKey); + + String plainText = "Hello world"; + byte[] input = plainText.getBytes(); + byte[] encrypted = cipher.doFinal(input); + + // Read the wrapped key and the encrypted data + + // First; unwrap the key + cipher = Cipher.getInstance("PBEWithMD5AndDES"); + // TODO: pass the parameters of the wrappedSharedKey + cipher.init(Cipher.UNWRAP_MODE, passwordKey, pbeParameterSpec); + + Key unwrappedKey = cipher.unwrap(wrappedSharedKey, "AES", Cipher.SECRET_KEY); + + // Decrypt the data + cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, unwrappedKey); + + String newData = new String(cipher.doFinal(encrypted)); + + assertEquals(newData, plainText); + } + + + @Test + public void createAsymmetricKeyPair() throws Exception { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + KeyPair pair = keyPairGenerator.generateKeyPair(); + PublicKey publicKey = pair.getPublic(); + System.err.println("Algorithm:" + publicKey.getAlgorithm()); + System.err.println("Format" + publicKey.getFormat()); + + byte[] encoded = publicKey.getEncoded(); + for (int i = 0; i < encoded.length; i++) { + byte b = encoded[i]; + } + } + + /** + * Encrypts something with AES, transforms the key into a key specification, recreates the key and decrypts + * the encrypted contents. + * + * @throws NoSuchAlgorithmException + * @throws NoSuchPaddingException + * @throws InvalidKeyException + * @throws UnsupportedEncodingException + * @throws BadPaddingException + * @throws IllegalBlockSizeException + */ + @Test + public void encryptAndDecryptWithSymmetricKey() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException { + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + SecretKey key = keyGenerator.generateKey(); + System.err.println("Algorithm:" + key.getAlgorithm()); + System.err.println("Format:" + key.getFormat()); + + // Transforms the secret key (symmetric) into a secret key specification + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getEncoded(), "AES"); + + Cipher encryptionCipher = Cipher.getInstance("AES"); + encryptionCipher.init(Cipher.ENCRYPT_MODE, key); + + String plainText = "Hello world"; + + byte[] encryptedBytes = encryptionCipher.doFinal(plainText.getBytes("UTF-8")); + + Cipher decryptionCipher = Cipher.getInstance("AES"); + decryptionCipher.init(Cipher.DECRYPT_MODE, secretKeySpec); + + byte[] decryptedBytes = decryptionCipher.doFinal(encryptedBytes); + + String decryptedText = new String(decryptedBytes, Charset.forName("UTF-8")); + + assertEquals(decryptedText, plainText); + } + + + @Test + public void holdEncryptedBytes() throws Exception { + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + SecretKey key = keyGenerator.generateKey(); + } + + private Cipher getSymmetricCipher(int mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { + Cipher cipher = Cipher.getInstance("DES/CFB8/NoPadding"); + cipher.init(mode, secretKey); + + return cipher; + } + + private String decrypt(KeyPair keyPair, byte[] encryptedBytes) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { + Cipher cipher = getCipher(); + cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); + + byte[] bytes = cipher.doFinal(encryptedBytes); + + return new String(bytes, Charset.forName("UTF-8")); + } + + private Cipher getCipher() throws NoSuchAlgorithmException, NoSuchPaddingException { + return Cipher.getInstance("RSA"); + } + + private byte[] encrypt(KeyPair keyPair, String plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + Cipher cipher = getCipher(); + cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); + byte[] bytes = cipher.doFinal(plainText.getBytes()); + + return bytes; + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/OxalisCipherTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/OxalisCipherTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3dbb05040ca26f76465c6a803daa2b69c3587fd3 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/OxalisCipherTest.java @@ -0,0 +1,213 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.SecretKey; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PublicKey; +import java.util.Arrays; + +import static org.testng.Assert.*; + +/** + * @author steinar + * Date: 06.05.13 + * Time: 22:34 + */ +public class OxalisCipherTest { + + private StatisticsKeyTool statisticsKeyTool; + + private OxalisCipher oxalisCipher; + + private OxalisCipherConverter oxalisCipherConverter; + + @BeforeMethod + public void setUp() throws IOException { + oxalisCipher = new OxalisCipher(); + oxalisCipherConverter = new OxalisCipherConverter(); + + Path tempDirectory = Files.createTempDirectory("unit-test"); + + statisticsKeyTool = new StatisticsKeyTool(); + assertNotNull(statisticsKeyTool); + } + + + /** + * Verifies understanding of converting a string between bytes and a string + */ + @Test + public void convertBetweenCharAndBytes() throws Exception { + + String s = "Hello World!" + "\u00e6" + "\u00f8" + "\u00e5" + "\u00c6" + "\u00d8" + "\u00c5"; + + byte[] bytes = s.getBytes("UTF-8"); + + String s1 = new String(bytes, "UTF-8"); + assertEquals(s, s1); + } + + + @Test + public void encryptAndDecryptAString() throws Exception { + String s = "Hello World! " + "\u00e6" + "\u00f8" + "\u00e5" + "\u00c6" + "\u00d8" + "\u00c5"; + + // Encrypt, decrypt and compare using the simple methods + byte[] encryptedBytes = oxalisCipher.encrypt(s.getBytes("UTF-8")); + byte[] decryptedBytes = oxalisCipher.decrypt(encryptedBytes); + + // array of bytes should be equal + assertTrue(Arrays.equals(s.getBytes("UTF-8"), decryptedBytes)); + + // Converting back to a string should still equal our initial string + String s2 = new String(decryptedBytes, "UTF-8"); + assertEquals(s, s2, "Oops decrypted string does not compare to encrypted string. Perhaps an encoding problem?"); + } + + @Test + public void encryptAndDecryptSomeXml() throws Exception { + String s = "\n" + + ""; + + // Encrypt, decrypt and compare using the simple methods + byte[] encryptedBytes = oxalisCipher.encrypt(s.getBytes("UTF-8")); + byte[] decryptedBytes = oxalisCipher.decrypt(encryptedBytes); + + // array of bytes should be equal + assertTrue(Arrays.equals(s.getBytes("UTF-8"), decryptedBytes)); + + // Converting back to a string should still equal our initial string + String s2 = new String(decryptedBytes, "UTF-8"); + assertEquals(s, s2); + } + + + /** + * Mimics how a servlet will respond with an encrypted entity for which the key is encrypted and placed + * in a header. + */ + @Test + public void testEncryptAndDecrypt() throws IOException, BadPaddingException, IllegalBlockSizeException { + + String plainText = "Hello World! " + "\u00e6" + "\u00f8" + "\u00e5"; + + byte[] encryptedBytes = encryptString(plainText, Charset.forName("ISO-8859-1")); + + String s = decryptToString(oxalisCipher, encryptedBytes, Charset.forName("ISO-8859-1")); + + assertEquals(s, plainText); + } + + /** + * Decrypts bytes using the symmetric key held in the OxalisCipher instance. + * Uses Cipher streams. + * + * @param cipher + * @param encryptedBytes + * @param charset the character set encoding to use + * @return + * @throws IOException + */ + private String decryptToString(OxalisCipher cipher, byte[] encryptedBytes, Charset charset) + throws IOException, BadPaddingException, IllegalBlockSizeException { + + byte[] decryptedBytes = oxalisCipher.decrypt(encryptedBytes); + + return new String(decryptedBytes, charset); + } + + /** + * Encrypts bytes using the symmetric key held in the OxalisCipher instance. + */ + private byte[] encryptString(String plainText, Charset charset) + throws IOException, BadPaddingException, IllegalBlockSizeException { + return oxalisCipher.encrypt(plainText.getBytes(charset)); + } + + + /** + * Encrypts data using our symmetric secret key obtained from the instance of OxalisCipher, after which + * the secret key is encrypted (wrapped) using the public asymmetric RSA keys loaded from disk. + * Finally the secret key is decrypted (unwrapped) and the encrypted data is decrypted. + *

+ * NOTE! If this goes belly up, you should verify that the public and private key loaded by + * StatisticsKeyTool is actually a pair. + * + * @param publicKey + * @throws Exception + */ + @Test(dataProvider = "publicKey") + public void encryptDataEncryptKeyAndReverse(PublicKey publicKey) throws Exception { + + String plainText = "Sample data for testing purposes æøå"; + byte[] encryptedBytes = encryptString(plainText, Charset.forName("UTF-8")); + + String encodedSymmetricKey = oxalisCipherConverter.getWrappedSymmetricKeyAsString(publicKey, oxalisCipher); + assertNotNull(encodedSymmetricKey); + } + + /** + * Proves that a symmetric AES key, which we obtain from the OxalisCipher instance, + * can be wrapped and unwrapped using an asymmetric RSA key. + * + * @throws Exception + */ + @Test + public void testWrapKey() throws Exception { + // Generates our asymmetric key pair + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + + // Wraps the symmetric secret key + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.WRAP_MODE, keyPair.getPublic()); + byte[] wrappedSecretKey = cipher.wrap(oxalisCipher.getSecretKey()); + + + // Unwraps the symmetric secret key + Cipher cipher1 = Cipher.getInstance("RSA"); + cipher1.init(Cipher.UNWRAP_MODE, keyPair.getPrivate()); + SecretKey aes = (SecretKey) cipher1.unwrap(wrappedSecretKey, "AES", Cipher.SECRET_KEY); + + } + + @DataProvider(name = "publicKey") + public Object[][] createKeyPair() { + return new Object[][]{ + {statisticsKeyTool.loadPublicKeyFromClassPath()} + }; + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/SignatureTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/SignatureTest.java new file mode 100644 index 0000000000000000000000000000000000000000..08e254517304dfb89a32417d5d90ffbff639d620 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/SignatureTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import org.testng.annotations.Test; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.IOException; +import java.security.*; +import java.security.cert.CertificateException; + +import static org.testng.Assert.assertTrue; + +/** + * User: steinar + * Date: 13.12.12 + * Time: 15:43 + */ +public class SignatureTest { + + + private final String plainText = "The quick brown fox jumped over the lazy dog"; + + @Test + public void testSigning() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException { + + + KeyPair keyPair = generateKeyPair(); + + Signature signature = Signature.getInstance("SHA1withDSA"); + + PrivateKey privateKey = keyPair.getPrivate(); + + signature.initSign(privateKey); + + signature.update(plainText.getBytes()); + + byte[] signatureBytes = signature.sign(); + + + Signature signature2 = Signature.getInstance("SHA1withDSA"); + signature2.initVerify(keyPair.getPublic()); + signature2.update(plainText.getBytes()); + + boolean verifies = signature2.verify(signatureBytes); + assertTrue(verifies); + } + + + @Test void testSaveAndReadPublicKey() throws NoSuchProviderException, NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException { + KeyPair keyPair = generateKeyPair(); + + KeyStore keyStore = KeyStore.getInstance("JCEKS"); + keyStore.load(null); + keyStore.setKeyEntry("dumbo", keyPair.getPrivate().getEncoded(), (java.security.cert.Certificate[]) null); + } + + + + private String decrypt(byte[] encryptedBytes, PrivateKey aPrivate) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + Cipher cipher = Cipher.getInstance("AES"); + + cipher.init(Cipher.DECRYPT_MODE, aPrivate); + byte[] bytes = cipher.doFinal(encryptedBytes); + + return new String(bytes); + } + + private byte[] encrypt(KeyPair keyPair) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); + return cipher.doFinal(plainText.getBytes()); + } + + + private KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA"); + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN"); + keyPairGenerator.initialize(1024, secureRandom); + + return keyPairGenerator.generateKeyPair(); + } + + + + +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/StatisticsKeyToolTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/StatisticsKeyToolTest.java new file mode 100644 index 0000000000000000000000000000000000000000..870768a4ee8e4190f246c86174544fcf8c0e84f5 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/StatisticsKeyToolTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import org.testng.annotations.Test; + +import java.security.PublicKey; + +import static org.testng.Assert.assertNotNull; + +/** + * Verifies the handling of the statistics public and private keys. + * + * @author steinar + * Date: 01.05.13 + * Time: 21:36 + */ +public class StatisticsKeyToolTest { + + @Test + public void loadPublicKeyFromClassPath() { + StatisticsKeyTool statisticsKeyTool = new StatisticsKeyTool(); + + PublicKey publicKey = statisticsKeyTool.loadPublicKeyFromClassPath(); + assertNotNull(publicKey); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/SymmetricCipherTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/SymmetricCipherTest.java new file mode 100644 index 0000000000000000000000000000000000000000..aae3679409daa4aebbd39b272657cd120dedbc96 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/security/SymmetricCipherTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.security; + +import org.testng.annotations.Test; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +/** + * @author steinar + * Date: 17.09.13 + * Time: 14:54 + */ +public class SymmetricCipherTest { + + private static byte[] iv = {0x0a, 0x01, 0x02, 0x03, 0x04, 0x0b, 0x0c, 0x0d}; + + private static byte[] encrypt(byte[] inpBytes, + SecretKey key, String xform) throws Exception { + Cipher cipher = Cipher.getInstance(xform); + cipher.init(Cipher.ENCRYPT_MODE, key); + return cipher.doFinal(inpBytes); + } + + private static byte[] decrypt(byte[] inpBytes, + SecretKey key, String xform) throws Exception { + Cipher cipher = Cipher.getInstance(xform); + cipher.init(Cipher.DECRYPT_MODE, key); + return cipher.doFinal(inpBytes); + } + + @Test + public void testCipher() throws Exception { + //String xform = "DES/ECB/PKCS5Padding"; + String xform = "AES/ECB/PKCS5Padding"; + + // Generate a secret key + KeyGenerator kg = KeyGenerator.getInstance("AES"); +// kg.init(56); // 56 is the keysize. Fixed for DES + SecretKey key = kg.generateKey(); + + byte[] dataBytes = + new String("J2EE Security for Servlets, EJBs and Web Services " + "\u00e6" + "\u00f8" + "\u00e5" + "\u00c6" + "\u00d8" + "\u00c5").getBytes(); + + byte[] encBytes = encrypt(dataBytes, key, xform); + byte[] decBytes = decrypt(encBytes, key, xform); + + boolean expected = java.util.Arrays.equals(dataBytes, decBytes); + System.out.println("Test " + (expected ? "SUCCEEDED!" : "FAILED!")); + } + +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/DateParserTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/DateParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4affc7421220f19d2e20ee93f6df667be79d708f --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/DateParserTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.util; + +import lombok.extern.slf4j.Slf4j; +import org.joda.time.DateTime; +import org.joda.time.MutableDateTime; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author steinar + * Date: 25.03.13 + * Time: 16:08 + */ +@Slf4j +public class DateParserTest { + + private String[][] testData = { + {"2013", "2013-01-01T00"}, + {"2013-02", "2013-02-01T00"}, + {"2013-03-25", "2013-03-25T00"}, + {"2013-03-25T14", "2013-03-25T14"}, + {"2013-06-12T23:59", "2013-06-12T23"} + }; + + @Test + public void testDateWithZeroParts() throws Exception { + + DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateOptionalTimeParser(); + DateTimeFormatter dateHourFormat = ISODateTimeFormat.dateHour(); + + for (String[] entry : testData) { + + String input = entry[0]; + String expected = entry[1]; + + DateTime dateTime = dateTimeFormatter.parseDateTime(input); + MutableDateTime mutableDateTime = dateTime.toMutableDateTimeISO(); + + mutableDateTime.setTime(dateTime.getHourOfDay(), 0, 0, 0); + + log.info("{} {} {}", dateTime, dateHourFormat.print(dateTime), mutableDateTime.toDate()); + Assert.assertEquals(dateHourFormat.print(dateTime), expected); + + } + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/StatisticsGranularityTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/StatisticsGranularityTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bd5bc7f90ac9f66cdc56ba92efbd85dd1b4b904b --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/StatisticsGranularityTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.util; + +import network.oxalis.statistics.api.StatisticsGranularity; +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author steinar + * Date: 26.03.13 + * Time: 09:22 + */ +public class StatisticsGranularityTest { + @Test + public void testValueForAbbreviation() throws Exception { + StatisticsGranularity g = StatisticsGranularity.valueForAbbreviation("m"); + Assert.assertEquals(g, StatisticsGranularity.MONTH); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testNullAbbreviation() { + StatisticsGranularity g = StatisticsGranularity.valueForAbbreviation(null); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testInvalidAbbreviation() { + StatisticsGranularity g = StatisticsGranularity.valueForAbbreviation("x"); + } +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/StatisticsToXmlTransformerTest.java b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/StatisticsToXmlTransformerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d8ad9ba4e108e77b85931dc98b9accdef7cdc776 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/java/network/oxalis/statistics/util/StatisticsToXmlTransformerTest.java @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.statistics.util; + +import network.oxalis.statistics.api.StatisticsTransformer; +import network.oxalis.test.identifier.PeppolDocumentTypeIdAcronym; +import network.oxalis.test.identifier.PeppolProcessTypeIdAcronym; +import network.oxalis.api.model.Direction; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.util.Date; + +import static org.testng.Assert.assertTrue; + +/** + * User: steinar + * Date: 24.02.13 + * Time: 10:46 + */ +public class StatisticsToXmlTransformerTest { + + private ByteArrayOutputStream byteArrayOutputStream; + + private StatisticsToXmlTransformer transformer; + + @BeforeMethod + public void setUp() { + byteArrayOutputStream = new ByteArrayOutputStream(); + transformer = new StatisticsToXmlTransformer(byteArrayOutputStream); + } + + @Test + public void testWriteSampleStatisticsToXml() throws UnsupportedEncodingException { + Date now = new Date(); + Date start = new Date(now.getTime() - 86400000L); + Date end = new Date(); + + transformer.startStatistics(start, end); + transformer.startEntry(); + transformer.writeAccessPointIdentifier("AP-0001"); + transformer.writeParticipantIdentifier("9908:810017902"); + transformer.writeDirection(Direction.OUT.name()); + transformer.writePeriod("2013-01-T13"); + transformer.writeDocumentType(PeppolDocumentTypeIdAcronym.INVOICE.toString()); + transformer.writeProfileId(PeppolProcessTypeIdAcronym.INVOICE_ONLY.toString()); + transformer.writeChannel("SR-TEST"); + transformer.writeCount(10); + transformer.endEntry(); + transformer.endStatistics(); + + String s = byteArrayOutputStream.toString("UTF-8"); + + assertTrue(s.contains(StatisticsTransformer.STATISTICS_DOCUMENT_START_ELEMENT_NAME)); + assertTrue(s.contains(StatisticsTransformer.ENTRY_START_ELEMENT_NAME)); + assertTrue(s.contains(StatisticsTransformer.ACCESS_POINT_ID_ELEMENT_NAME), "Missing " + StatisticsTransformer.PARTICIPANT_ID_ELEMENT_NAME + " element in result"); + assertTrue(s.contains(StatisticsTransformer.PARTICIPANT_ID_ELEMENT_NAME), "Missing " + StatisticsTransformer.PARTICIPANT_ID_ELEMENT_NAME); + assertTrue(s.contains(StatisticsTransformer.CHANNEL_ELEMENT_NAME), "Missing " + StatisticsTransformer.CHANNEL_ELEMENT_NAME); + assertTrue(s.contains(StatisticsTransformer.DOCUMENT_TYPE_ELEMENT_NAME)); + assertTrue(s.contains(StatisticsTransformer.PROFILE_ID_ELEMENT_NAME)); + assertTrue(s.contains(StatisticsTransformer.COUNT_ELEMENT_NAME)); + + System.err.println(s); + } + +} diff --git a/oxalis-legacy/oxalis-statistics/src/test/resources/logback-test.xml b/oxalis-legacy/oxalis-statistics/src/test/resources/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa6fe6d582664e4679e8b5741c2995efb870283f --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/resources/logback-test.xml @@ -0,0 +1,44 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + + + diff --git a/oxalis-legacy/oxalis-statistics/src/test/resources/oxalis_home/fake-oxalis.conf b/oxalis-legacy/oxalis-statistics/src/test/resources/oxalis_home/fake-oxalis.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-legacy/oxalis-statistics/src/test/resources/oxalis_home/logback-test.xml b/oxalis-legacy/oxalis-statistics/src/test/resources/oxalis_home/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-legacy/oxalis-statistics/src/test/resources/oxalis_home/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-outbound/.gitignore b/oxalis-outbound/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..249cda967c11bb62c8affe06d18f26bc5b5f3af0 --- /dev/null +++ b/oxalis-outbound/.gitignore @@ -0,0 +1 @@ +/data \ No newline at end of file diff --git a/oxalis-outbound/pom.xml b/oxalis-outbound/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e99cd5e91bfa9a271c51b6ee13cff387fd6cbd4 --- /dev/null +++ b/oxalis-outbound/pom.xml @@ -0,0 +1,119 @@ + + + + + 4.0.0 + + + dk.erst.oxalis + oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + + oxalis-outbound + jar + + Oxalis :: Core :: Outbound + Component for handling sending. + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + + + dk.erst.oxalis + oxalis-commons + + + dk.erst.oxalis + oxalis-document-sniffer + + + dk.erst.oxalis + oxalis-test + test + + + + + + org.apache.commons + commons-dbcp2 + + + commons-logging + commons-logging + + + + + + + ch.qos.logback + logback-classic + test + + + org.slf4j + jcl-over-slf4j + + + + + network.oxalis.vefa + peppol-lookup + + + network.oxalis.vefa + peppol-sbdh + + + network.oxalis.vefa + peppol-security + + + + + + + src/main/resources + true + + + + + org.jacoco + jacoco-maven-plugin + + + + + diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/OxalisOutboundComponent.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/OxalisOutboundComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..31949b058a7f33c411152add807bcda0ff5258fd --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/OxalisOutboundComponent.java @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound; + +import com.google.inject.Injector; +import network.oxalis.api.evidence.EvidenceFactory; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.api.outbound.TransmissionService; +import network.oxalis.api.outbound.Transmitter; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.outbound.transmission.TransmissionRequestBuilder; +import network.oxalis.outbound.transmission.TransmissionRequestFactory; + +/** + * Entry point and Object factory for the Oxalis outbound module. + * + * Should be treated as a singleton when used to make sure Oxalis is not loaded more times than needed. + * + * @author steinar + * @author thore + * @author erlend + */ +public class OxalisOutboundComponent { + + private Injector injector = GuiceModuleLoader.initiate(); + + /** + * Retrieves instances of TransmissionRequestBuilder, while not exposing Google Guice to the outside + * + * @return instance of TransmissionRequestBuilder + */ + public TransmissionRequestBuilder getTransmissionRequestBuilder() { + return injector.getInstance(TransmissionRequestBuilder.class); + } + + public TransmissionRequestFactory getTransmissionRequestFactory() { + return injector.getInstance(TransmissionRequestFactory.class); + } + + /** + * Retrieves instance of LookupService, without revealing intern object dependency injection. + */ + public LookupService getLookupService() { + return injector.getInstance(LookupService.class); + } + + /** + * Retrieves instance of DefaultTransmitter, without revealing intern object dependency injection. + * + * @return instance of Transmitter + */ + public Transmitter getTransmitter() { + return injector.getInstance(Transmitter.class); + } + + public EvidenceFactory getEvidenceFactory() { + return injector.getInstance(EvidenceFactory.class); + } + + /** + * Provides access to the Google Guice injector in order to reuse the component with other components that also uses + * Google Guice. + * + * @return + */ + public Injector getInjector() { + return injector; + } + + public TransmissionService getTransmissionService() { + return injector.getInstance(TransmissionService.class); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/CachedLookupService.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/CachedLookupService.java new file mode 100644 index 0000000000000000000000000000000000000000..652ad6447d5f7ead009dd983f224f6245adc72f6 --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/CachedLookupService.java @@ -0,0 +1,124 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.lookup; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.*; +import network.oxalis.vefa.peppol.lookup.LookupClient; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +/** + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("cached") +class CachedLookupService extends CacheLoader implements LookupService { + + private final LookupClient lookupClient; + + private final TransportProfile[] transportProfiles; + + private final LoadingCache cache; + + @Inject + public CachedLookupService(LookupClient lookupClient, + @Named("prioritized") List transportProfiles) { + this.lookupClient = lookupClient; + this.transportProfiles = transportProfiles.toArray(new TransportProfile[transportProfiles.size()]); + + this.cache = CacheBuilder.newBuilder() + .maximumSize(1000) + .expireAfterWrite(5, TimeUnit.MINUTES) + .build(this); + } + + @Override + public Endpoint lookup(Header header) throws OxalisTransmissionException { + try { + return cache.get(new HeaderStub(header)); + } catch (ExecutionException e) { + throw new OxalisTransmissionException(e.getCause().getMessage(), e.getCause()); + } + } + + @Override + public Endpoint load(HeaderStub header) throws Exception { + return lookupClient.getEndpoint(header.getReceiver(), header.getDocumentType(), + header.getProcess(), transportProfiles); + } + + static class HeaderStub { + + private ParticipantIdentifier receiver; + + private DocumentTypeIdentifier documentType; + + private ProcessIdentifier process; + + public HeaderStub(Header header) { + this.receiver = header.getReceiver(); + this.documentType = header.getDocumentType(); + this.process = header.getProcess(); + } + + public ParticipantIdentifier getReceiver() { + return receiver; + } + + public DocumentTypeIdentifier getDocumentType() { + return documentType; + } + + public ProcessIdentifier getProcess() { + return process; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + HeaderStub that = (HeaderStub) o; + return Objects.equals(receiver, that.receiver) && + Objects.equals(documentType, that.documentType) && + Objects.equals(process, that.process); + } + + @Override + public int hashCode() { + return Objects.hash(receiver, documentType, process); + } + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/DefaultLookupService.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/DefaultLookupService.java new file mode 100644 index 0000000000000000000000000000000000000000..1b5bc5276385115e3773357e2c879fb15f944dae --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/DefaultLookupService.java @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.lookup; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.lang.EndpointNotFoundException; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import network.oxalis.vefa.peppol.lookup.LookupClient; +import network.oxalis.vefa.peppol.lookup.api.LookupException; +import network.oxalis.vefa.peppol.security.lang.PeppolSecurityException; + +import java.util.List; + +/** + * Default implementation of {@link LookupService}. This implementation performs no caching except caching part of + * underlying implementations. + * + * @author erlend + * @since 4.0.0 + */ +@Singleton +@Type("default") +class DefaultLookupService implements LookupService { + + /** + * LookupClient provided by VEFA PEPPOL project. + */ + private final LookupClient lookupClient; + + /** + * Prioritized list of supported transport profiles detected. + */ + private final TransportProfile[] transportProfiles; + + @Inject + public DefaultLookupService(LookupClient lookupClient, + @Named("prioritized") List transportProfiles) { + this.lookupClient = lookupClient; + this.transportProfiles = transportProfiles.toArray(new TransportProfile[transportProfiles.size()]); + } + + /** + * {@inheritDoc} + */ + @Override + public Endpoint lookup(Header header) throws OxalisTransmissionException { + try { + return lookupClient.getEndpoint(header, transportProfiles); + } catch (LookupException | PeppolSecurityException | EndpointNotFoundException e) { + throw new OxalisTransmissionException(e.getMessage(), e); + } + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/LookupModule.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/LookupModule.java new file mode 100644 index 0000000000000000000000000000000000000000..6501b42076a338ec202ac58d95fa457416e14cc1 --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/LookupModule.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.lookup; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Names; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.commons.mode.OxalisCertificateValidator; +import network.oxalis.vefa.peppol.common.lang.PeppolLoadingException; +import network.oxalis.vefa.peppol.lookup.LookupClient; +import network.oxalis.vefa.peppol.lookup.LookupClientBuilder; +import network.oxalis.vefa.peppol.lookup.api.MetadataFetcher; +import network.oxalis.vefa.peppol.mode.Mode; + +/** + * @author erlend + * @since 4.0.0 + */ +public class LookupModule extends OxalisModule { + + @Override + protected void configure() { + bindTyped(LookupService.class, CachedLookupService.class); + bindTyped(LookupService.class, DefaultLookupService.class); + + bind(MetadataFetcher.class) + .to(OxalisApacheFetcher.class); + } + + @Provides + @Singleton + protected LookupService getLookupService(Mode mode, Injector injector) { + return injector.getInstance(Key.get(LookupService.class, Names.named(mode.getString("oxalis.lookup.service")))); + } + + @Provides + @Singleton + protected LookupClient providesLookupClient(Mode mode, OxalisCertificateValidator certificateValidator, + MetadataFetcher fetcher) + throws PeppolLoadingException { + return LookupClientBuilder.forMode(mode) + .fetcher(fetcher) + .certificateValidator(certificateValidator) + .build(); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/OxalisApacheFetcher.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/OxalisApacheFetcher.java new file mode 100644 index 0000000000000000000000000000000000000000..69aa3e341db72d06729206a30dff4db22744593e --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/lookup/OxalisApacheFetcher.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.lookup; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import network.oxalis.vefa.peppol.lookup.fetcher.BasicApacheFetcher; +import network.oxalis.vefa.peppol.mode.Mode; +import org.apache.http.impl.client.CloseableHttpClient; + +/** + * @author erlend + * @since 4.0.0 + */ +@Singleton +class OxalisApacheFetcher extends BasicApacheFetcher { + + private Provider httpClientProvider; + + @Inject + public OxalisApacheFetcher(Provider httpClientProvider, Mode mode) { + super(mode); + this.httpClientProvider = httpClientProvider; + } + + @Override + protected CloseableHttpClient createClient() { + return httpClientProvider.get(); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transformer/XmlContentWrapper.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transformer/XmlContentWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..454bd718e51e91904da7c994b10bb0b7c22549f6 --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transformer/XmlContentWrapper.java @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transformer; + +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.transformer.ContentWrapper; +import network.oxalis.api.util.Type; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.sbdh.SbdWriter; +import network.oxalis.vefa.peppol.sbdh.lang.SbdhException; +import network.oxalis.vefa.peppol.sbdh.util.XMLStreamUtils; + +import javax.inject.Singleton; +import javax.xml.stream.XMLStreamException; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.1 + */ +@Singleton +@Type("xml") +public class XmlContentWrapper implements ContentWrapper { + + @Override + public InputStream wrap(InputStream inputStream, Header header) throws IOException, OxalisContentException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (SbdWriter sbdWriter = SbdWriter.newInstance(outputStream, header)) { + XMLStreamUtils.copy(inputStream, sbdWriter.xmlWriter()); + } catch (SbdhException | XMLStreamException e) { + throw new OxalisContentException("Unable to wrap content into SBDH.", e); + } + + return new ByteArrayInputStream(outputStream.toByteArray()); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionMessage.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..01d45628ffdd0f966ea07d05ef7897e3864f7feb --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionMessage.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import network.oxalis.api.tag.Tag; +import network.oxalis.api.outbound.TransmissionMessage; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.InputStream; +import java.io.Serializable; + +/** + * @author erlend + * @since 4.0.0 + */ +class DefaultTransmissionMessage implements TransmissionMessage, Serializable { + + private static final long serialVersionUID = -2292244133544793106L; + + private final Tag tag; + + private final Header header; + + private final InputStream payload; + + public DefaultTransmissionMessage(Header header, InputStream payload, Tag tag) { + this.tag = tag; + this.header = header; + this.payload = payload; + } + + @Override + public Tag getTag() { + return tag; + } + + @Override + public Header getHeader() { + return header; + } + + @Override + public InputStream getPayload() { + return payload; + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionRequest.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..70999a6c4e8415e7a7442fbd86db651f6c22f11d --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionRequest.java @@ -0,0 +1,107 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import network.oxalis.api.tag.Tag; +import network.oxalis.api.outbound.TransmissionMessage; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; + +import java.io.InputStream; +import java.io.Serializable; +import java.util.Objects; + +/** + * Describes a request to transmit a payload (PEPPOL Document) to a designated end-point. + * Instances of this class are to be deemed as value objects, as they are immutable. + * + * @author steinar + * @author thore + * @author erlend + */ +class DefaultTransmissionRequest implements TransmissionRequest, Serializable { + + private static final long serialVersionUID = -4542158917465140099L; + + private final Tag tag; + + private final Endpoint endpoint; + + private final Header header; + + private final InputStream payload; + + /** + * Module private constructor grabbing the constructor data from the supplied builder. + */ + public DefaultTransmissionRequest(Header header, InputStream inputStream, Endpoint endpoint, Tag tag) { + this.tag = tag; + this.endpoint = endpoint; + this.header = header; + this.payload = inputStream; + } + + public DefaultTransmissionRequest(TransmissionMessage transmissionMessage, Endpoint endpoint) { + this.endpoint = endpoint; + this.tag = transmissionMessage.getTag(); + this.header = transmissionMessage.getHeader(); + this.payload = transmissionMessage.getPayload(); + } + + @Override + public Endpoint getEndpoint() { + return endpoint; + } + + @Override + public Tag getTag() { + return tag; + } + + @Override + public Header getHeader() { + return header; + } + + @Override + public InputStream getPayload() { + return payload; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DefaultTransmissionRequest that = (DefaultTransmissionRequest) o; + return Objects.equals(tag, that.tag) && + Objects.equals(endpoint, that.endpoint) && + Objects.equals(header, that.header) && + Objects.equals(payload, that.payload); + } + + @Override + public int hashCode() { + return Objects.hash(tag, endpoint, header, payload); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionService.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionService.java new file mode 100644 index 0000000000000000000000000000000000000000..11d993b627e0d74433a903c6318153fc0fe5bfb2 --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmissionService.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import io.opentracing.Span; +import io.opentracing.Tracer; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.tag.Tag; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.outbound.TransmissionService; +import network.oxalis.api.outbound.Transmitter; +import network.oxalis.commons.tracing.Traceable; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Default implementation of {@link TransmissionService}. + * + * @author erlend + */ +@Singleton +class DefaultTransmissionService extends Traceable implements TransmissionService { + + private final TransmissionRequestFactory transmissionRequestFactory; + + private final Transmitter transmitter; + + /** + * {@inheritDoc} + */ + @Inject + public DefaultTransmissionService(TransmissionRequestFactory transmissionRequestFactory, + Transmitter transmitter, Tracer tracer) { + super(tracer); + this.transmissionRequestFactory = transmissionRequestFactory; + this.transmitter = transmitter; + } + + /** + * {@inheritDoc} + */ + @Override + public TransmissionResponse send(InputStream inputStream, Tag tag) + throws IOException, OxalisTransmissionException, OxalisContentException { + Span root = tracer.buildSpan("TransmissionService").start(); + try { + return send(inputStream, tag, root); + } finally { + root.finish(); + } + } + + @Override + public TransmissionResponse send(InputStream inputStream, Tag tag, Span root) + throws IOException, OxalisTransmissionException, OxalisContentException { + return transmitter.transmit(transmissionRequestFactory.newInstance(inputStream, tag, root), root); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmitter.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmitter.java new file mode 100644 index 0000000000000000000000000000000000000000..52994285de0a11e3f79b4c804e59f521f61e985e --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/DefaultTransmitter.java @@ -0,0 +1,171 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Inject; +import io.opentracing.Span; +import io.opentracing.Tracer; +import network.oxalis.api.error.ErrorTracker; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.api.model.Direction; +import network.oxalis.api.outbound.*; +import network.oxalis.api.statistics.StatisticsService; +import network.oxalis.api.transmission.TransmissionVerifier; +import network.oxalis.commons.mode.OxalisCertificateValidator; +import network.oxalis.commons.tracing.Traceable; +import network.oxalis.vefa.peppol.common.code.Service; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import network.oxalis.vefa.peppol.security.lang.PeppolSecurityException; + +/** + * Executes transmission requests by sending the payload to the requested destination. + * Updates statistics for the transmission using the configured RawStatisticsRepository. + *

+ * Will log an error if the recording of statistics fails for some reason. + * + * @author steinar + * @author thore + * @author erlend + */ +class DefaultTransmitter extends Traceable implements Transmitter { + + /** + * Factory used to fetch implementation of required transport profile implementation. + */ + private final MessageSenderFactory messageSenderFactory; + + /** + * Service to report statistics when transmission is successfully transmitted. + */ + private final StatisticsService statisticsService; + + private final TransmissionVerifier transmissionVerifier; + + private final LookupService lookupService; + + private final OxalisCertificateValidator certificateValidator; + + private final ErrorTracker errorTracker; + + @Inject + public DefaultTransmitter(MessageSenderFactory messageSenderFactory, StatisticsService statisticsService, + TransmissionVerifier transmissionVerifier, LookupService lookupService, Tracer tracer, + OxalisCertificateValidator certificateValidator, ErrorTracker errorTracker) { + super(tracer); + this.messageSenderFactory = messageSenderFactory; + this.statisticsService = statisticsService; + this.transmissionVerifier = transmissionVerifier; + this.lookupService = lookupService; + this.certificateValidator = certificateValidator; + this.errorTracker = errorTracker; + } + + /** + * {@inheritDoc} + */ + @Override + public TransmissionResponse transmit(TransmissionMessage transmissionMessage, Span root) + throws OxalisTransmissionException { + Span span = tracer.buildSpan("transmit").asChildOf(root).start(); + try { + return perform(transmissionMessage, span); + } finally { + span.finish(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public TransmissionResponse transmit(TransmissionMessage transmissionMessage) throws OxalisTransmissionException { + Span root = tracer.buildSpan("transmit").start(); + try { + return perform(transmissionMessage, root); + } finally { + root.finish(); + } + } + + private TransmissionResponse perform(TransmissionMessage transmissionMessage, Span root) + throws OxalisTransmissionException { + try { + if (transmissionMessage == null) + throw new OxalisTransmissionException("No transmission is provided."); + + transmissionVerifier.verify(transmissionMessage.getHeader(), Direction.OUT); + + TransmissionRequest transmissionRequest; + if (transmissionMessage instanceof TransmissionRequest) { + transmissionRequest = (TransmissionRequest) transmissionMessage; + + // Validate provided certificate + if (transmissionRequest.getEndpoint().getCertificate() == null) + throw new OxalisTransmissionException("Certificate of receiving access point is not provided."); + certificateValidator.validate(Service.AP, transmissionRequest.getEndpoint().getCertificate(), root); + } else { + // Perform lookup using header. + Span span = tracer.buildSpan("Fetch endpoint information").asChildOf(root).start(); + Endpoint endpoint; + try { + endpoint = lookupService.lookup(transmissionMessage.getHeader(), span); + span.setTag("transport profile", endpoint.getTransportProfile().getIdentifier()); + transmissionRequest = new DefaultTransmissionRequest(transmissionMessage, endpoint); + } catch (OxalisTransmissionException e) { + span.setTag("exception", e.getMessage()); + throw e; + } finally { + span.finish(); + } + } + + Span span = tracer.buildSpan("send message").asChildOf(root).start(); + TransmissionResponse transmissionResponse; + try { + TransportProfile transportProfile = transmissionRequest.getEndpoint().getTransportProfile(); + MessageSender messageSender = messageSenderFactory.getMessageSender(transportProfile); + transmissionResponse = messageSender.send(transmissionRequest, span); + } catch (OxalisTransmissionException e) { + span.setTag("exception", e.getMessage()); + throw e; + } finally { + span.finish(); + } + + statisticsService.persist(transmissionRequest, transmissionResponse, root); + + return transmissionResponse; + } catch (PeppolSecurityException e) { + errorTracker.track(Direction.OUT, e, true); + throw new OxalisTransmissionException("Unable to verify certificate of receiving access point.", e); + } catch (OxalisTransmissionException e) { + errorTracker.track(Direction.OUT, e, true); + throw e; + } catch (RuntimeException e) { + errorTracker.track(Direction.OUT, e, false); + throw e; + } + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/MessageSenderFactory.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/MessageSenderFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..fb80d165f03c1c0c1bfe43f10aa9cc5941717041 --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/MessageSenderFactory.java @@ -0,0 +1,125 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Names; +import com.typesafe.config.Config; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.outbound.MessageSender; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import network.oxalis.vefa.peppol.mode.Mode; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Factory orchestrating available implementations of transport profiles. + * + * @author erlend + */ +@Slf4j +class MessageSenderFactory { + + /** + * Guice injector used to load MessageSender implementation when needed, allows use of non-singleton + * implementations. It is not considered best practice to inject injector like this, however in this case is this + * suitable based on our requirements. + */ + private final Injector injector; + + /** + * Map of configurations for supported transport profiles. + */ + private final Map configMap; + + /** + * Prioritized list of supported transport profiles. + */ + private final List prioritizedTransportProfiles; + + @Inject + public MessageSenderFactory(Injector injector, Config config, Mode mode) { + this.injector = injector; + + // Construct map of configuration for detected transport profiles. + configMap = config.getObject("transport").keySet().stream() + .map(key -> config.getConfig(String.format("transport.%s", key))) + .collect(Collectors.toMap(c -> TransportProfile.of(c.getString("profile")), Function.identity())); + + // Create prioritized list of transport profiles. + prioritizedTransportProfiles = Collections.unmodifiableList(configMap.values().stream() + .filter(o -> !o.hasPath("enabled") || o.getBoolean("enabled")) + .filter(o -> !o.hasPath("modes") || o.getStringList("modes").contains(mode.getIdentifier())) + .sorted((o1, o2) -> Integer.compare(o2.getInt("weight"), o1.getInt("weight"))) + .map(o -> o.getString("profile")) + .map(TransportProfile::of) + .collect(Collectors.toList())); + + // Logging list of prioritized transport profiles supported. + log.info("Prioritized list of transport profiles:"); + prioritizedTransportProfiles + .forEach(tp -> log.info("=> {}", tp.getIdentifier())); + } + + /** + * Fetch list of supported transport profiles ordered by priority. + * + * @return List of supported transport profiles. + */ + public List getPrioritizedTransportProfiles() { + return prioritizedTransportProfiles; + } + + /** + * Fetch identifier used in named annotation for the implementation of requested transport profile. + * + * @param transportProfile Identifier of transport profile requested. + * @return String used in the named annotation. + * @throws OxalisTransmissionException Thrown when transport profile is not supported. + */ + public String getSender(TransportProfile transportProfile) throws OxalisTransmissionException { + if (!configMap.containsKey(transportProfile)) + throw new OxalisTransmissionException( + String.format("Transport protocol '%s' not supported.", transportProfile.getIdentifier())); + + return configMap.get(transportProfile).getString("sender"); + } + + /** + * Fetch MessageSender implementing from provided transport profile. + * + * @param transportProfile Identifier of transport profile used to fetch MessageSender. + * @return MessageSender implementing the transport profile requested. + * @throws OxalisTransmissionException Thrown when loading of implementation fails or implementation is not found. + */ + public MessageSender getMessageSender(TransportProfile transportProfile) throws OxalisTransmissionException { + return injector.getInstance(Key.get(MessageSender.class, Names.named(getSender(transportProfile)))); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionModule.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionModule.java new file mode 100644 index 0000000000000000000000000000000000000000..051e0507d5211490200788f3c6215d2f2cdb8019 --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionModule.java @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Provides; +import com.google.inject.name.Named; +import network.oxalis.api.outbound.TransmissionService; +import network.oxalis.api.outbound.Transmitter; +import network.oxalis.api.transformer.ContentWrapper; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.outbound.transformer.XmlContentWrapper; +import network.oxalis.vefa.peppol.common.model.TransportProfile; + +import javax.inject.Singleton; +import java.util.List; + +/** + * Guice module orchestrating transmission related classes in transmission package. + * + * @author steinar + * Date: 18.11.2016 + * Time: 16.10 + * @author erlend + */ +public class TransmissionModule extends OxalisModule { + + @Override + protected void configure() { + bind(Transmitter.class) + .to(DefaultTransmitter.class) + .asEagerSingleton(); + + bind(TransmissionRequestFactory.class) + .asEagerSingleton(); + + bind(TransmissionService.class) + .to(DefaultTransmissionService.class); + + bind(MessageSenderFactory.class) + .asEagerSingleton(); + + bindTyped(ContentWrapper.class, XmlContentWrapper.class); + } + + /** + * Makes the prioritized list of supported transport profiles available to classes needing such a list (lookup...). + * + * @param messageSenderFactory Factory containing configuration for supported transport profiles. + * @return Prioritized list of supported transport profiles. + */ + @Provides + @Singleton + @Named("prioritized") + protected List getTransportProfiles(MessageSenderFactory messageSenderFactory) { + return messageSenderFactory.getPrioritizedTransportProfiles(); + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionRequestBuilder.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionRequestBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..42aee3483cefc4a506849ed186c6925a95040669 --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionRequestBuilder.java @@ -0,0 +1,379 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import io.opentracing.Span; +import io.opentracing.Tracer; +import lombok.extern.slf4j.Slf4j; +import network.oxalis.api.header.HeaderParser; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.api.model.Direction; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.tag.Tag; +import network.oxalis.api.tag.TagGenerator; +import network.oxalis.api.transformer.ContentDetector; +import network.oxalis.sniffer.PeppolStandardBusinessHeader; +import network.oxalis.sniffer.identifier.InstanceId; +import network.oxalis.sniffer.sbdh.SbdhWrapper; +import network.oxalis.vefa.peppol.common.model.DocumentTypeIdentifier; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import network.oxalis.vefa.peppol.common.model.ProcessIdentifier; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +/** + * @author steinar + * @author thore + * Date: 04.11.13 + * Time: 10:04 + * @author erlend + */ +@Slf4j +public class TransmissionRequestBuilder { + + private final ContentDetector contentDetector; + + private final LookupService lookupService; + + private final TagGenerator tagGenerator; + + private final HeaderParser headerParser; + + private final Tracer tracer; + + private boolean allowOverride; + + /** + * Will contain the payload PEPPOL document + */ + private byte[] payload; + + /** + * The address of the endpoint either supplied by the caller or looked up in the SMP + */ + private Endpoint endpoint; + + private Tag tag = Tag.NONE; + + /** + * The header fields supplied by the caller as opposed to the header fields parsed from the payload + */ + private PeppolStandardBusinessHeader suppliedHeaderFields = new PeppolStandardBusinessHeader(); + + /** + * The header fields in effect, i.e. merge the parsed header fields with the supplied ones, + * giving precedence to the supplied ones. + */ + private PeppolStandardBusinessHeader effectiveStandardBusinessHeader; + + @Inject + public TransmissionRequestBuilder(ContentDetector contentDetector, LookupService lookupService, + TagGenerator tagGenerator, HeaderParser headerParser, Tracer tracer) { + this.contentDetector = contentDetector; + this.lookupService = lookupService; + this.tagGenerator = tagGenerator; + this.headerParser = headerParser; + this.tracer = tracer; + } + + public void reset() { + suppliedHeaderFields = new PeppolStandardBusinessHeader(); + effectiveStandardBusinessHeader = null; + } + + /** + * Supplies the builder with the contents of the message to be sent. + */ + public TransmissionRequestBuilder payLoad(InputStream inputStream) { + savePayLoad(inputStream); + return this; + } + + /** + * Overrides the endpoint URL and the AS2 System identifier for the AS2 protocol. + * You had better know what you are doing :-) + */ + public TransmissionRequestBuilder overrideAs2Endpoint(Endpoint endpoint) { + this.endpoint = endpoint; + return this; + } + + public TransmissionRequestBuilder receiver(ParticipantIdentifier receiverId) { + suppliedHeaderFields.setRecipientId(receiverId); + return this; + } + + public TransmissionRequestBuilder sender(ParticipantIdentifier senderId) { + suppliedHeaderFields.setSenderId(senderId); + return this; + } + + public TransmissionRequestBuilder documentType(DocumentTypeIdentifier documentTypeIdentifier) { + suppliedHeaderFields.setDocumentTypeIdentifier(documentTypeIdentifier); + return this; + } + + public TransmissionRequestBuilder processType(ProcessIdentifier processTypeId) { + suppliedHeaderFields.setProfileTypeIdentifier(processTypeId); + return this; + } + + public TransmissionRequestBuilder instanceId(InstanceId instanceId) { + suppliedHeaderFields.setInstanceId(instanceId); + return this; + } + + public TransmissionRequestBuilder tag(Tag tag) { + this.tag = tag; + return this; + } + + public TransmissionRequest build(Span root) throws OxalisTransmissionException, OxalisContentException { + Span span = tracer.buildSpan("build").asChildOf(root).start(); + try { + return build(); + } finally { + span.finish(); + } + } + + /** + * Builds the actual {@link TransmissionRequest}. + *

+ * The {@link PeppolStandardBusinessHeader} is built as following: + * + *

    + *
  1. If the payload contains an SBHD, allow override if global "overrideAllowed" flag is set, + * otherwise use the one parsed
  2. + *
  3. If the payload does not contain an SBDH, parseOld payload to determine some of the SBDH attributes + * and allow override if global "overrideAllowed" flag is set.
  4. + *
+ * + * @return Prepared transmission request. + */ + public TransmissionRequest build() throws OxalisTransmissionException, OxalisContentException { + if (payload.length < 2) + throw new OxalisTransmissionException("You have forgotten to provide payload"); + + PeppolStandardBusinessHeader optionalParsedSbdh = null; + try { + optionalParsedSbdh = + new PeppolStandardBusinessHeader(headerParser.parse(new ByteArrayInputStream(payload))); + } catch (OxalisContentException e) { + // No action. + } + + // Calculates the effectiveStandardBusinessHeader to be used + effectiveStandardBusinessHeader = makeEffectiveSbdh( + Optional.ofNullable(optionalParsedSbdh), suppliedHeaderFields); + + // If the endpoint has not been overridden by the caller, look up the endpoint address in + // the SMP using the data supplied in the payload + if (isEndpointSuppliedByCaller() && isOverrideAllowed()) { + log.warn("Endpoint was set by caller not retrieved from SMP, make sure this is intended behaviour."); + } else { + Endpoint endpoint = lookupService.lookup(effectiveStandardBusinessHeader.toVefa(), null); + + if (isEndpointSuppliedByCaller() && !this.endpoint.equals(endpoint)) { + throw new IllegalStateException("You are not allowed to override the EndpointAddress from SMP."); + } + + this.endpoint = endpoint; + } + + // make sure payload is encapsulated in SBDH + if (optionalParsedSbdh == null) { + // Wraps the payload with an SBDH, as this is required for AS2 + payload = wrapPayLoadWithSBDH(new ByteArrayInputStream(payload), effectiveStandardBusinessHeader); + } + + // Transfers all the properties of this object into the newly created TransmissionRequest + return new DefaultTransmissionRequest( + getEffectiveStandardBusinessHeader().toVefa(), getPayload(), + getEndpoint(), tagGenerator.generate(Direction.OUT, tag)); + } + + /** + * Merges the SBDH parsed from the payload with the SBDH data supplied by the caller, i.e. the caller wishes to + * override the contents of the SBDH parsed. That is, if the payload contains an SBDH + * + * @param optionalParsedSbdh the SBDH as parsed (extracted) from the payload. + * @param peppolSbdhSuppliedByCaller the SBDH data supplied by the caller in order to override data from the payload + * @return the merged, effective SBDH created by combining the two data sets + */ + PeppolStandardBusinessHeader makeEffectiveSbdh(Optional optionalParsedSbdh, + PeppolStandardBusinessHeader peppolSbdhSuppliedByCaller) + throws OxalisContentException { + PeppolStandardBusinessHeader effectiveSbdh; + + if (isOverrideAllowed()) { + if (peppolSbdhSuppliedByCaller.isComplete()) { + // we have sufficient meta data (set explicitly by the caller using API functions) + effectiveSbdh = peppolSbdhSuppliedByCaller; + } else { + // missing meta data, parseOld payload, which does not contain SBHD, in order to deduce missing fields + PeppolStandardBusinessHeader parsedPeppolStandardBusinessHeader = parsePayLoadAndDeduceSbdh(optionalParsedSbdh); + effectiveSbdh = createEffectiveHeader(parsedPeppolStandardBusinessHeader, peppolSbdhSuppliedByCaller); + } + } else { + // override is not allowed, make sure we do not override any restricted headers + PeppolStandardBusinessHeader parsedPeppolStandardBusinessHeader = parsePayLoadAndDeduceSbdh(optionalParsedSbdh); + List overriddenHeaders = findRestricedHeadersThatWillBeOverridden(parsedPeppolStandardBusinessHeader, peppolSbdhSuppliedByCaller); + if (overriddenHeaders.isEmpty()) { + effectiveSbdh = createEffectiveHeader(parsedPeppolStandardBusinessHeader, peppolSbdhSuppliedByCaller); + } else { + throw new IllegalStateException("Your are not allowed to override " + Arrays.toString(overriddenHeaders.toArray()) + " in production mode, makes sure headers match the ones in the document."); + } + } + if (!effectiveSbdh.isComplete()) { + throw new IllegalStateException("TransmissionRequest can not be built, missing " + Arrays.toString(effectiveSbdh.listMissingProperties().toArray()) + " metadata."); + } + + return effectiveSbdh; + } + + + private PeppolStandardBusinessHeader parsePayLoadAndDeduceSbdh( + Optional optionallyParsedSbdh) throws OxalisContentException { + if (optionallyParsedSbdh.isPresent()) + return optionallyParsedSbdh.get(); + + return new PeppolStandardBusinessHeader(contentDetector.parse(new ByteArrayInputStream(payload))); + } + + /** + * Merges the supplied header fields with the SBDH parsed or derived from the payload thus allowing the caller + * to explicitly override whatever has been supplied in the payload. + * + * @param parsed the PeppolStandardBusinessHeader parsed from the payload + * @param supplied the header fields supplied by the caller + * @return the merged and effective headers + */ + protected PeppolStandardBusinessHeader createEffectiveHeader(final PeppolStandardBusinessHeader parsed, + final PeppolStandardBusinessHeader supplied) { + + // Creates a copy of the original business headers + PeppolStandardBusinessHeader mergedHeaders = new PeppolStandardBusinessHeader(parsed); + + if (supplied.getSenderId() != null) { + mergedHeaders.setSenderId(supplied.getSenderId()); + } + if (supplied.getRecipientId() != null) { + mergedHeaders.setRecipientId(supplied.getRecipientId()); + } + if (supplied.getDocumentTypeIdentifier() != null) { + mergedHeaders.setDocumentTypeIdentifier(supplied.getDocumentTypeIdentifier()); + } + if (supplied.getProfileTypeIdentifier() != null) { + mergedHeaders.setProfileTypeIdentifier(supplied.getProfileTypeIdentifier()); + } + + // If instanceId was supplied by caller, use it otherwise, create new + if (supplied.getInstanceId() != null) { + mergedHeaders.setInstanceId(supplied.getInstanceId()); + } else { + mergedHeaders.setInstanceId(new InstanceId()); + } + + if (supplied.getCreationDateAndTime() != null) { + mergedHeaders.setCreationDateAndTime(supplied.getCreationDateAndTime()); + } + + return mergedHeaders; + + } + + /** + * Returns a list of "restricted" header names that will be overridden when calling #createEffectiveHeader + * The restricted header names are SenderId, RecipientId, DocumentTypeIdentifier and ProfileTypeIdentifier + * Compares values that exist both as parsed and supplied headers. + * Ignores values that only exists in one of them (that allows for sending new and unknown document types) + */ + protected List findRestricedHeadersThatWillBeOverridden(final PeppolStandardBusinessHeader parsed, + final PeppolStandardBusinessHeader supplied) { + List headers = new ArrayList<>(); + if ((parsed.getSenderId() != null) && (supplied.getSenderId() != null) + && (!supplied.getSenderId().equals(parsed.getSenderId()))) headers.add("SenderId"); + if ((parsed.getRecipientId() != null) && (supplied.getRecipientId() != null) + && (!supplied.getRecipientId().equals(parsed.getRecipientId()))) headers.add("RecipientId"); + if ((parsed.getDocumentTypeIdentifier() != null) && (supplied.getDocumentTypeIdentifier() != null) + && (!supplied.getDocumentTypeIdentifier().equals(parsed.getDocumentTypeIdentifier()))) + headers.add("DocumentTypeIdentifier"); + if ((parsed.getProfileTypeIdentifier() != null) && (supplied.getProfileTypeIdentifier() != null) + && (!supplied.getProfileTypeIdentifier().equals(parsed.getProfileTypeIdentifier()))) + headers.add("ProfileTypeIdentifier"); + return headers; + } + + protected PeppolStandardBusinessHeader getEffectiveStandardBusinessHeader() { + return effectiveStandardBusinessHeader; + } + + protected void savePayLoad(InputStream inputStream) { + try { + payload = ByteStreams.toByteArray(inputStream); + } catch (IOException e) { + throw new IllegalStateException("Unable to save the payload: " + e.getMessage(), e); + } + } + + protected InputStream getPayload() { + return new ByteArrayInputStream(payload); + } + + public Endpoint getEndpoint() { + return endpoint; + } + + public boolean isOverrideAllowed() { + return allowOverride; + } + + private boolean isEndpointSuppliedByCaller() { + return endpoint != null; + } + + private byte[] wrapPayLoadWithSBDH(ByteArrayInputStream byteArrayInputStream, + PeppolStandardBusinessHeader effectiveStandardBusinessHeader) { + SbdhWrapper sbdhWrapper = new SbdhWrapper(); + return sbdhWrapper.wrap(byteArrayInputStream, effectiveStandardBusinessHeader.toVefa()); + } + + /** + * For testing purposes only + */ + public void setTransmissionBuilderOverride(boolean transmissionBuilderOverride) { + this.allowOverride = transmissionBuilderOverride; + } +} diff --git a/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionRequestFactory.java b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionRequestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..d2aebf258ac96b482a016706d2e081e8d80c87dd --- /dev/null +++ b/oxalis-outbound/src/main/java/network/oxalis/outbound/transmission/TransmissionRequestFactory.java @@ -0,0 +1,151 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import io.opentracing.Span; +import io.opentracing.Tracer; +import network.oxalis.api.header.HeaderParser; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.model.Direction; +import network.oxalis.api.outbound.TransmissionMessage; +import network.oxalis.api.tag.Tag; +import network.oxalis.api.tag.TagGenerator; +import network.oxalis.api.transformer.ContentDetector; +import network.oxalis.api.transformer.ContentWrapper; +import network.oxalis.commons.io.PeekingInputStream; +import network.oxalis.commons.tracing.Traceable; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.inject.Inject; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author erlend + * @since 4.0.0 + */ +public class TransmissionRequestFactory extends Traceable { + + private final ContentDetector contentDetector; + + private final ContentWrapper contentWrapper; + + private final TagGenerator tagGenerator; + + private final HeaderParser headerParser; + + @Inject + public TransmissionRequestFactory(ContentDetector contentDetector, ContentWrapper contentWrapper, + TagGenerator tagGenerator, HeaderParser headerParser, Tracer tracer) { + super(tracer); + this.contentDetector = contentDetector; + this.contentWrapper = contentWrapper; + this.tagGenerator = tagGenerator; + this.headerParser = headerParser; + } + + public TransmissionMessage newInstance(InputStream inputStream) + throws IOException, OxalisContentException { + return newInstance(inputStream, Tag.NONE); + } + + public TransmissionMessage newInstance(InputStream inputStream, Tag tag) + throws IOException, OxalisContentException { + Span root = tracer.buildSpan(getClass().getSimpleName()).start(); + try { + return perform(inputStream, tag, root); + } finally { + root.finish(); + } + } + + public TransmissionMessage newInstance(InputStream inputStream, Span root) + throws IOException, OxalisContentException { + return newInstance(inputStream, Tag.NONE, root); + } + + public TransmissionMessage newInstance(InputStream inputStream, Tag tag, Span root) + throws IOException, OxalisContentException { + Span span = tracer.buildSpan(getClass().getSimpleName()).asChildOf(root).start(); + try { + return perform(inputStream, tag, span); + } finally { + span.finish(); + } + } + + private TransmissionMessage perform(InputStream inputStream, Tag tag, Span root) + throws IOException, OxalisContentException { + PeekingInputStream peekingInputStream = new PeekingInputStream(inputStream); + + // Read header from content to send. + Header header; + try { + // Read header from SBDH. + Span span = tracer.buildSpan("Reading SBDH").asChildOf(root).start(); + try { + header = headerParser.parse(peekingInputStream); + span.setTag("identifier", header.getIdentifier().getIdentifier()); + } catch (OxalisContentException e) { + span.setTag("exception", e.getMessage()); + throw e; + } finally { + span.finish(); + } + + // Create transmission request. + return new DefaultTransmissionMessage(header, peekingInputStream.newInputStream(), + tagGenerator.generate(Direction.OUT, tag)); + } catch (OxalisContentException e) { + byte[] payload = peekingInputStream.getContent(); + + // Detect header from content. + Span span = tracer.buildSpan("Detect SBDH from content").asChildOf(root).start(); + try { + header = contentDetector.parse(new ByteArrayInputStream(payload)); + span.setTag("identifier", header.getIdentifier().getIdentifier()); + } catch (OxalisContentException ex) { + span.setTag("exception", ex.getMessage()); + throw new OxalisContentException(ex.getMessage(), ex); + } finally { + span.finish(); + } + + // Wrap content in SBDH. + span = tracer.buildSpan("Wrap content in SBDH").asChildOf(root).start(); + InputStream wrappedContent; + try { + wrappedContent = contentWrapper.wrap(new ByteArrayInputStream(payload), header); + } catch (OxalisContentException ex) { + span.setTag("exception", ex.getMessage()); + throw ex; + } finally { + span.finish(); + } + + // Create transmission request. + return new DefaultTransmissionMessage(header, wrappedContent, tagGenerator.generate(Direction.OUT, tag)); + } + } +} diff --git a/oxalis-outbound/src/main/resources/reference.conf b/oxalis-outbound/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..3893f18a5a0165b1994c51f1bf3d8098ec3a21a1 --- /dev/null +++ b/oxalis-outbound/src/main/resources/reference.conf @@ -0,0 +1,4 @@ +oxalis.module.outbound.lookup.class = network.oxalis.outbound.lookup.LookupModule +oxalis.module.outbound.transmission.class = network.oxalis.outbound.transmission.TransmissionModule + +mode.default.oxalis.lookup.service = cached \ No newline at end of file diff --git a/oxalis-outbound/src/test/java/javax/XmlEncodingTest.java b/oxalis-outbound/src/test/java/javax/XmlEncodingTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f91509ac2c323b01363fbedccc581414a0091bb2 --- /dev/null +++ b/oxalis-outbound/src/test/java/javax/XmlEncodingTest.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package javax; + +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.*; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * @author Steinar Overbeck Cook + * Date: 26.12.11 + * Time: 14:08 + */ +public class XmlEncodingTest { + + protected static final String EHF_TEST_SEND_REGNING_HELSE_VEST2_XML = "ehf-test-SendRegning-HelseVest2.xml"; + + /** + * Parses an XML file and verifies that the address contained in + * /Invoice/AccountingSupplierParty/Party/PostalAddress/StreetName/text() + * the + */ + @Test + public void testXmlEncoding() throws ParserConfigurationException, IOException, SAXException, + XPathExpressionException, URISyntaxException { + + URL url = XmlEncodingTest.class.getClassLoader().getResource(EHF_TEST_SEND_REGNING_HELSE_VEST2_XML); + assertNotNull(url, EHF_TEST_SEND_REGNING_HELSE_VEST2_XML + " not found in classpath"); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(false); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + + File file = new File(url.toURI()); + Document document = documentBuilder.parse(file); + + XPathFactory xPathFactory = XPathFactory.newInstance(); + XPath xPath = xPathFactory.newXPath(); + XPathExpression expr = xPath.compile("/Invoice/AccountingSupplierParty/Party/PostalAddress/StreetName/text()"); + String s = (String) expr.evaluate(document, XPathConstants.STRING); + + assertEquals(s, "\u00D8stre Aker vei 243H"); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/OxalisOutboundComponentTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/OxalisOutboundComponentTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f207afb791c7ab30500dd8f28adb542b1f1d0c84 --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/OxalisOutboundComponentTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author steinar + * Date: 18.11.2016 + * Time: 16.32 + */ +public class OxalisOutboundComponentTest { + + @Test + public void testGetters() throws Exception { + OxalisOutboundComponent oxalisOutboundComponent = new OxalisOutboundComponent(); + + Assert.assertNotNull(oxalisOutboundComponent.getTransmissionRequestBuilder()); + Assert.assertNotNull(oxalisOutboundComponent.getTransmissionRequestFactory()); + Assert.assertNotNull(oxalisOutboundComponent.getLookupService()); + Assert.assertNotNull(oxalisOutboundComponent.getTransmitter()); + Assert.assertNotNull(oxalisOutboundComponent.getEvidenceFactory()); + Assert.assertNotNull(oxalisOutboundComponent.getInjector()); + Assert.assertNotNull(oxalisOutboundComponent.getTransmissionService()); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/guice/TestResourceModule.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/guice/TestResourceModule.java new file mode 100644 index 0000000000000000000000000000000000000000..1b5cf5e8b209b6e3b626d03902cd20b5336ca1ab --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/guice/TestResourceModule.java @@ -0,0 +1,308 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.guice; + +import com.google.inject.Provides; +import com.google.inject.name.Named; +import network.oxalis.commons.guice.OxalisModule; +import network.oxalis.sniffer.PeppolStandardBusinessHeader; +import network.oxalis.sniffer.identifier.CustomizationIdentifier; +import network.oxalis.sniffer.identifier.PeppolDocumentTypeId; +import network.oxalis.test.identifier.WellKnownParticipant; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import network.oxalis.vefa.peppol.common.model.ProcessIdentifier; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import static org.testng.Assert.assertNotNull; + +/** + * Guice module providing different testfiles used by unit tests + * + * @author steinar + * @author thore + */ +public class TestResourceModule extends OxalisModule { + + public static final String PEPPOL_BIS_INVOICE_SBD_XML = "/peppol-bis-invoice-sbdh.xml"; + + public static final String EHF_T10_ALLE_ELEMENTER_XML = "/ehf-bii05-t10-valid-invoice.xml"; + + public static final String EHF_T10_MANGLER_ELEMENTER_XML = "/ehf-t10-mangler-elementer.xml"; + + @Override + protected void configure() { /* nothing */ } + + /** + * All InputStream annotated with + * @Inject @Named("sampleXml"), will have an instance of this InputStream injected. + * + * @return InputStream connected to PEPPOL_BIS_INVOICE_SBD_XML + */ + @Provides + @Named("sample-xml-with-sbdh") + public InputStream getSampleXmlInputStream() { + InputStream resourceAsStream = getClass().getResourceAsStream(PEPPOL_BIS_INVOICE_SBD_XML); + assertNotNull(resourceAsStream, "Unable to load " + PEPPOL_BIS_INVOICE_SBD_XML + " from class path"); + return resourceAsStream; + } + + @Provides + @Named("sample-xml-no-sbdh") + public InputStream getSampleXmlInputStreamWithoutSbdh() { + InputStream inputStream = getClass().getResourceAsStream(EHF_T10_ALLE_ELEMENTER_XML); + assertNotNull(inputStream, "Unable to load " + EHF_T10_ALLE_ELEMENTER_XML + " from class path"); + return inputStream; + } + + @Provides + @Named("sample-xml-missing-metadata") + public InputStream getSampleXmlInputStreamWithMissingMetadata() { + InputStream inputStream = getClass().getResourceAsStream(EHF_T10_MANGLER_ELEMENTER_XML); + assertNotNull(inputStream, "Unable to load " + EHF_T10_MANGLER_ELEMENTER_XML + " from class path"); + return inputStream; + } + + /** + * Provides a Map of resource names and their PeppolStandardBusinessHeader "facit". + * Extend the number of testfiles and update this list to automatically test decoding of new formats. + */ + @Provides + @Named("test-files-with-identification") + public Map getTestData() { + Map map = new HashMap<>(); + + // + // example Despatch Advice scenario files + // + + map.put("DespatchAdvice/1.0/Eksempel1.xml", createPeppolStandardBusinessHeader( + "DespatchAdvice", "urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns016:ver1.0" + + ":extended:urn:www.peppol.eu:bis:peppol30a:ver1.0" + + ":extended:urn:www.difi.no:ehf:pakkseddel:ver1.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii30:ver2.0")); + + map.put("DespatchAdvice/1.0/Eksempel2.xml", createPeppolStandardBusinessHeader( + "DespatchAdvice", "urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns016:ver1.0" + + ":extended:urn:www.peppol.eu:bis:peppol30a:ver1.0" + + ":extended:urn:www.difi.no:ehf:pakkseddel:ver1.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii30:ver2.0")); + + map.put("DespatchAdvice/1.0/Eksempel3.xml", createPeppolStandardBusinessHeader( + "DespatchAdvice", "urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns016:ver1.0" + + ":extended:urn:www.peppol.eu:bis:peppol30a:ver1.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii30:ver2.0")); + + map.put("DespatchAdvice/1.0/Eksempel4.xml", createPeppolStandardBusinessHeader( + "DespatchAdvice", "urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns016:ver1.0" + + ":extended:urn:www.peppol.eu:bis:peppol30a:ver1.0" + + ":extended:urn:www.difi.no:ehf:pakkseddel:ver1.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii30:ver2.0")); + + map.put("DespatchAdvice/1.0/Eksempel5.xml", createPeppolStandardBusinessHeader( + "DespatchAdvice", "urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns016:ver1.0" + + ":extended:urn:www.peppol.eu:bis:peppol30a:ver1.0" + + ":extended:urn:www.difi.no:ehf:pakkseddel:ver1.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii30:ver2.0")); + + // + // example Catalogue scenario files + // + + map.put("EHFCatalogue/1.0/Example file EHF Catalogue Response.xml", createPeppolStandardBusinessHeader( + "ApplicationResponse", "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns058:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol1a:ver2.0" + + ":extended:urn:www.difi.no:ehf:katalogbekreftelse:ver1.0", + "9908:976098897", "9908:810018909", "urn:www.cenbii.eu:profile:biiI02:ver2.0")); + + map.put("EHFCatalogue/1.0/Example file EHF Catalogue.xml", createPeppolStandardBusinessHeader( + "Catalogue", "urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns019:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol1a:ver2.0" + + ":extended:urn:www.difi.no:ehf:katalog:ver1.0", + "9908:976098897", "9908:810018909", "urn:www.cenbii.eu:profile:bii01:ver2.0")); + + // + // example Invoice scenario files + // + + map.put("EHFInvoice/1.6/T14-norsk-profil05.xml", createPeppolStandardBusinessHeader( + "CreditNote", "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2", "2.0", + "urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1", + "9908:977187761", "9908:810305282", "urn:www.cenbii.eu:profile:bii05:ver1.0")); + + map.put("EHFInvoice/1.6/T14-norsk-profil05-without-endpointid.xml", createPeppolStandardBusinessHeader( + "CreditNote", "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2", "2.0", + "urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1", + "9908:977187761", "9908:810305282", "urn:www.cenbii.eu:profile:bii05:ver1.0")); + + map.put("EHFInvoice/1.6/T14-norsk-profilxx.xml", createPeppolStandardBusinessHeader( + "CreditNote", "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2", "2.0", + "urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1", + "9908:977187761", "9908:810305282", "urn:www.cenbii.eu:profile:biixx:ver1.0")); + + map.put("EHFInvoice/1.6/T14-norsk-profilxy.xml", createPeppolStandardBusinessHeader( + "CreditNote", "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2", "2.0", + "urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixy:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1", + "9908:977187761", "9908:810305282", "urn:www.cenbii.eu:profile:biixy:ver1.0")); + + map.put("EHFInvoice/1.6/T14-utland-profil05.xml", createPeppolStandardBusinessHeader( + "CreditNote", "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2", "2.0", + "urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0", + "9908:977187761", "9908:810305282", "urn:www.cenbii.eu:profile:bii05:ver1.0")); + + map.put("EHFInvoice/2.0/T10-B2C.xml", createPeppolStandardBusinessHeader( + "Invoice", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns010:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol5a:ver2.0" + + ":extended:urn:www.difi.no:ehf:faktura:ver2.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii05:ver2.0")); + + map.put("EHFInvoice/2.0/T10-Valuta-EUR.xml", createPeppolStandardBusinessHeader( + "Invoice", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns010:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol5a:ver2.0" + + ":extended:urn:www.difi.no:ehf:faktura:ver2.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii05:ver2.0")); + + map.put("EHFInvoice/2.0/T14-Valuta-EUR.xml", createPeppolStandardBusinessHeader( + "CreditNote", "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns014:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol5a:ver2.0" + + ":extended:urn:www.difi.no:ehf:kreditnota:ver2.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii05:ver2.0")); + + // + // example Order scenario files + // + + map.put("EHFOrder/1.0/Eksempelfil EHF Ordre.xml", createPeppolStandardBusinessHeader( + "Order", "urn:oasis:names:specification:ubl:schema:xsd:Order-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns001:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol28a:ver1.0" + + ":extended:urn:www.difi.no:ehf:ordre:ver1.0", + "9908:976098897", + WellKnownParticipant.DIFI_TEST.getIdentifier(), "urn:www.cenbii.eu:profile:bii28:ver2.0")); + + map.put("EHFOrder/1.0/Eksempelfil EHF Ordrebekreftelse.xml", createPeppolStandardBusinessHeader( + "OrderResponse", "urn:oasis:names:specification:ubl:schema:xsd:OrderResponse-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns076:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol28a:ver1.0" + + ":extended:urn:www.difi.no:ehf:ordrebekreftelse:ver1.0", + "9908:810018909", "9908:976098897", "urn:www.cenbii.eu:profile:bii28:ver2.0")); + + map.put("EHFOrder/SimpleOrderResponse.xml", createPeppolStandardBusinessHeader( + "OrderResponseSimple", "urn:oasis:names:specification:ubl:schema:xsd:OrderResponseSimple-2", "2.0", + "urn:www.cenbii.eu:transaction:biicoretrdm003:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0", + "9908:999999999", "9908:000000000", "urn:www.cenbii.eu:profile:bii06:ver1.0")); + + // + // example Reminder scenario files + // + + map.put("EHFReminder/1.6/T17-norsk-profilxy.xml", createPeppolStandardBusinessHeader( + "Reminder", "urn:oasis:names:specification:ubl:schema:xsd:Reminder-2", "2.0", + "urn:www.cenbii.eu:transaction:biicoretrdm017:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixy:ver1.0" + + "#urn:www.difi.no:ehf:purring:ver1", + "9908:810018909", + WellKnownParticipant.DIFI_TEST.getIdentifier(), "urn:www.cenbii.eu:profile:biixy:ver1.0")); + + // + // example Message Level Response scenario files + // + + map.put("MessageLevelResponse/1.0/Use Case1.xml", createPeppolStandardBusinessHeader( + "ApplicationResponse", "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns071:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol36a:ver1.0", + "9908:981915550", "9908:976098897", "urn:www.cenbii.eu:profile:bii36:ver2.0")); + + map.put("MessageLevelResponse/1.0/Use Case2.xml", createPeppolStandardBusinessHeader( + "ApplicationResponse", "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns071:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol36a:ver1.0", + "9908:981915550", "9908:976098897", "urn:www.cenbii.eu:profile:bii36:ver2.0")); + + map.put("MessageLevelResponse/1.0/Use Case3.xml", createPeppolStandardBusinessHeader( + "ApplicationResponse", "urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2", "2.1", + "urn:www.cenbii.eu:transaction:biitrns071:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol36a:ver1.0", + "9908:981915550", "9908:976098897", "urn:www.cenbii.eu:profile:bii36:ver2.0")); + + return map; + } + + /** + * Provides a Map of non-UBL type resource names and PeppolStandardBusinessHeader data. + * Oxalis should allow new or unknown formats to be transported using PEPPOL. + */ + @Provides + @Named("test-non-ubl-documents") + public Map getNonUBLTestData() { + Map map = new HashMap<>(); + + // + // example non-UBL document scenario (contributed by Jacob Lund Mogensen), should be allowed + // + + map.put("OIOXML/OIOXML_PCM_99018008_ValidKnown-Original.xml", createPeppolStandardBusinessHeader( + "Invoice", "http://rep.oio.dk/ubl/xml/schemas/0p71/pcm/", "1.0", + "urn:customization", + "9908:810018909", "9902:99018008", "urn:profile")); + + return map; + } + + private PeppolStandardBusinessHeader createPeppolStandardBusinessHeader( + String localname, String namespace, String version, + String customization, + String sender, String receiver, String profileId) { + PeppolStandardBusinessHeader p = PeppolStandardBusinessHeader.createPeppolStandardBusinessHeaderWithNewDate(); + p.setDocumentTypeIdentifier(new PeppolDocumentTypeId(namespace, localname, + new CustomizationIdentifier(customization), version).toVefa()); + p.setSenderId(ParticipantIdentifier.of(sender)); + p.setRecipientId(ParticipantIdentifier.of(receiver)); + p.setProfileTypeIdentifier(ProcessIdentifier.of(profileId)); + return p; + } + +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/CachedLookupServiceTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/CachedLookupServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fe6c2db964bede8e9567c18546afca5794d80147 --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/CachedLookupServiceTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.lookup; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.vefa.peppol.common.model.*; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Ignore; +import org.testng.annotations.Test; + +@Guice(modules = GuiceModuleLoader.class) +public class CachedLookupServiceTest { + + private static ParticipantIdentifier participant = ParticipantIdentifier.of("0208:0871221633"); + + private static DocumentTypeIdentifier documenttype = DocumentTypeIdentifier.of( + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##" + + "urn:cen.eu:en16931:2017#compliant#" + + "urn:fdc:peppol.eu:2017:poacc:billing:3.0" + + "::2.1", DocumentTypeIdentifier.BUSDOX_DOCID_QNS_SCHEME); + + private static ProcessIdentifier process = ProcessIdentifier.of("urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"); + + @Inject + @Named("cached") + private LookupService lookupService; + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test + public void simple() throws Exception { + Endpoint endpoint = lookupService.lookup(Header.newInstance() + .receiver(participant) + .documentType(documenttype) + .process(process)); + + Assert.assertNotNull(endpoint); + } + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test + public void simpleCached() throws Exception { + Endpoint endpoint1 = lookupService.lookup(Header.newInstance() + .receiver(participant) + .documentType(documenttype) + .process(process)); + + Endpoint endpoint2 = lookupService.lookup(Header.newInstance() + .receiver(participant) + .documentType(documenttype) + .process(process)); + + Assert.assertSame(endpoint1, endpoint2); + } + + @Test(expectedExceptions = OxalisTransmissionException.class) + public void triggerException() throws Exception { + lookupService.lookup(Header.newInstance() + .receiver(ParticipantIdentifier.of("9908:---")) + .documentType(documenttype) + .process(process)); + } + + @Test + public void simpleHeaderStub() { + CachedLookupService.HeaderStub headerStub = new CachedLookupService.HeaderStub(Header.newInstance() + .receiver(participant) + .documentType(documenttype) + .process(process)); + + Assert.assertTrue(headerStub.equals(new CachedLookupService.HeaderStub(Header.newInstance() + .receiver(participant) + .documentType(documenttype) + .process(process)))); + Assert.assertFalse(headerStub.equals(new CachedLookupService.HeaderStub(Header.newInstance() + .receiver(ParticipantIdentifier.of("9908:---")) + .documentType(documenttype) + .process(process)))); + Assert.assertFalse(headerStub.equals(new CachedLookupService.HeaderStub(Header.newInstance() + .receiver(participant) + .documentType(DocumentTypeIdentifier.of("---")) + .process(process)))); + Assert.assertFalse(headerStub.equals(new CachedLookupService.HeaderStub(Header.newInstance() + .receiver(participant) + .documentType(documenttype) + .process(ProcessIdentifier.of("---"))))); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/DefaultLookupServiceTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/DefaultLookupServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..103063540bbe379dd4d93107c5f7b7b20c2566be --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/DefaultLookupServiceTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.lookup; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.vefa.peppol.common.model.*; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Ignore; +import org.testng.annotations.Test; + +@Guice(modules = GuiceModuleLoader.class) +public class DefaultLookupServiceTest { + + @Inject + @Named("default") + private LookupService lookupService; + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test + public void simple() throws Exception { + Endpoint endpoint = lookupService.lookup(Header.newInstance() + .receiver(ParticipantIdentifier.of("0208:0871221633")) + .documentType(DocumentTypeIdentifier.of("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1")) + .process(ProcessIdentifier.of("urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"))); + + Assert.assertNotNull(endpoint); + } + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test + public void simpleBusdoxDocIdQnsScheme() throws Exception { + Endpoint endpoint = lookupService.lookup(Header.newInstance() + .receiver(ParticipantIdentifier.of("0208:0871221633")) + .documentType(DocumentTypeIdentifier.of("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1", DocumentTypeIdentifier.BUSDOX_DOCID_QNS_SCHEME)) + .process(ProcessIdentifier.of("urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"))); + + Assert.assertNotNull(endpoint); + } + + @Test(expectedExceptions = OxalisTransmissionException.class) + public void triggerException() throws Exception { + lookupService.lookup(Header.newInstance() + .receiver(ParticipantIdentifier.of("9908:---")) + .documentType(DocumentTypeIdentifier.of("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol4a:ver2.0::2.1")) + .process(ProcessIdentifier.of("urn:www.cenbii.eu:profile:bii04:ver2.0"))); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/LookupServiceTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/LookupServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..f09ecd25de06b033709942946f9bca32810d5860 --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/lookup/LookupServiceTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.lookup; + +import com.google.inject.Inject; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.vefa.peppol.common.model.*; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Ignore; +import org.testng.annotations.Test; + +@Guice(modules = GuiceModuleLoader.class) +public class LookupServiceTest { + + @Inject + private LookupService lookupService; + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test + public void simple() throws Exception { + Endpoint endpoint = lookupService.lookup(Header.newInstance() + .receiver(ParticipantIdentifier.of("0208:0871221633")) + .documentType(DocumentTypeIdentifier.of( + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##" + + "urn:cen.eu:en16931:2017#compliant#" + + "urn:fdc:peppol.eu:2017:poacc:billing:3.0" + + "::2.1")) + .process(ProcessIdentifier.of("urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"))); + + Assert.assertNotNull(endpoint); + } + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test + public void simpleBusdoxDocIdQnsScheme() throws Exception { + Endpoint endpoint = lookupService.lookup(Header.newInstance() + .receiver(ParticipantIdentifier.of("0208:0871221633")) + .documentType(DocumentTypeIdentifier.of( + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##" + + "urn:cen.eu:en16931:2017#compliant#" + + "urn:fdc:peppol.eu:2017:poacc:billing:3.0" + + "::2.1", DocumentTypeIdentifier.BUSDOX_DOCID_QNS_SCHEME)) + .process(ProcessIdentifier.of("urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"))); + + Assert.assertNotNull(endpoint); + } + +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/DefaultTransmissionServiceTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/DefaultTransmissionServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8a4a390c07ad22abd7a6e3c6cf0d57857b951858 --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/DefaultTransmissionServiceTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.util.Modules; +import io.opentracing.Span; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.api.outbound.TransmissionService; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.test.asd.AsdTransmissionResponse; +import network.oxalis.test.lookup.MockLookupModule; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import org.mockito.Mockito; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import java.net.SocketTimeoutException; + +public class DefaultTransmissionServiceTest { + + private Injector injector = Guice.createInjector( + Modules.override(new GuiceModuleLoader()).with(new MockLookupModule())); + + private LookupService lookupService; + + private TransmissionService transmissionService; + + @BeforeClass + public void beforeClass() { + lookupService = injector.getInstance(LookupService.class); + transmissionService = injector.getInstance(TransmissionService.class); + } + + @Test + public void simple() throws Exception { + MockLookupModule.resetService(); + + TransmissionResponse transmissionResponse = transmissionService.send(getClass().getResourceAsStream("/peppol-bis-invoice-sbdh.xml")); + + Assert.assertTrue(transmissionResponse instanceof AsdTransmissionResponse); + Assert.assertEquals(transmissionResponse.getProtocol(), TransportProfile.of("bdx-transport-asd")); + + Assert.assertNotNull(transmissionResponse.getHeader()); + Assert.assertNotNull(transmissionResponse.getProtocol()); + } + + @Test(expectedExceptions = OxalisTransmissionException.class, enabled = false) + public void simpleTriggerException() throws Exception { + Mockito.reset(lookupService); + Mockito.when(lookupService.lookup(Mockito.any(Header.class), Mockito.any(Span.class))) + .thenThrow(new OxalisTransmissionException("From unit test.")); + + transmissionService.send(getClass().getResourceAsStream("/ehf-bii05-t10-valid-invoice.xml")); + } + + @Test(expectedExceptions = SocketTimeoutException.class, enabled = false) + public void socketTimeoutException() throws Exception { + MockLookupModule.resetService(); + + TransmissionResponse transmissionResponse = transmissionService.send(getClass().getResourceAsStream("/ehf-bii05-t10-valid-invoice.xml")); + + Assert.assertTrue(transmissionResponse instanceof AsdTransmissionResponse); + Assert.assertEquals(transmissionResponse.getProtocol(), TransportProfile.of("bdx-transport-asd")); + + Assert.assertNotNull(transmissionResponse.getHeader()); + Assert.assertNotNull(transmissionResponse.getProtocol()); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/DefaultTransmitterTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/DefaultTransmitterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..eca715d6223b66adff62cfb12e7604c4d651854f --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/DefaultTransmitterTest.java @@ -0,0 +1,94 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import io.opentracing.Tracer; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.Transmitter; +import network.oxalis.api.statistics.StatisticsService; +import network.oxalis.commons.error.SilentErrorTracker; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.commons.mode.OxalisCertificateValidator; +import network.oxalis.commons.transmission.DefaultTransmissionVerifier; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import network.oxalis.vefa.peppol.security.api.CertificateValidator; +import org.mockito.Mockito; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.io.ByteArrayInputStream; +import java.net.URI; + +@Guice(modules = GuiceModuleLoader.class) +public class DefaultTransmitterTest { + + @Inject + private MessageSenderFactory messageSenderFactory; + + @Inject + @Named("noop") + private StatisticsService statisticsService; + + @Inject + private Tracer tracer; + + @Inject + private LookupService lookupService; + + @Test(expectedExceptions = OxalisTransmissionException.class) + public void simple() throws Exception { + TransmissionRequest transmissionRequest = Mockito.mock(TransmissionRequest.class); + Mockito.when(transmissionRequest.getEndpoint()).thenReturn(Endpoint.of( + TransportProfile.of("busdox-transport-dummy"), URI.create("http://localhost/"), null)); + Mockito.when(transmissionRequest.getPayload()) + .thenReturn(new ByteArrayInputStream("".getBytes())); + + Transmitter transmitter = new DefaultTransmitter(messageSenderFactory, statisticsService, + new DefaultTransmissionVerifier(), lookupService, tracer, + new OxalisCertificateValidator(CertificateValidator.EMPTY, tracer), + new SilentErrorTracker()); + transmitter.transmit(transmissionRequest); + } + + @Test(expectedExceptions = OxalisTransmissionException.class) + public void throwException() throws Exception { + MessageSenderFactory messageSenderFactory = Mockito.mock(MessageSenderFactory.class); + Mockito.when(messageSenderFactory.getMessageSender(Mockito.any(TransportProfile.class))) + .thenThrow(new OxalisTransmissionException("From unit test")); + + TransmissionRequest transmissionRequest = Mockito.mock(TransmissionRequest.class); + Mockito.when(transmissionRequest.getEndpoint()) + .thenReturn(Endpoint.of(TransportProfile.AS2_1_0, URI.create("http://localhost/"), null)); + + Transmitter transmitter = new DefaultTransmitter(messageSenderFactory, statisticsService, + new DefaultTransmissionVerifier(), lookupService, tracer, + new OxalisCertificateValidator(CertificateValidator.EMPTY, tracer), + new SilentErrorTracker()); + transmitter.transmit(transmissionRequest); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/MessageSenderFactoryTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/MessageSenderFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..35b24ec6f1d61a61548a55dffe3d82cfb833ebc8 --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/MessageSenderFactoryTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Inject; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.test.asd.AsdConstants; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.List; + +@Guice(modules = GuiceModuleLoader.class) +public class MessageSenderFactoryTest { + + @Inject + private MessageSenderFactory messageSenderFactory; + + @Test + public void simple() throws OxalisTransmissionException { + Assert.assertTrue(messageSenderFactory.getPrioritizedTransportProfiles().size() > 0); + Assert.assertEquals(messageSenderFactory.getSender(TransportProfile.of("bdx-transport-asd")), "oxalis-asd"); + } + + @Test + public void validTransportProfile() throws OxalisTransmissionException { + Assert.assertNotNull(messageSenderFactory.getMessageSender(AsdConstants.TRANSPORT_PROFILE)); + } + + @Test(expectedExceptions = OxalisTransmissionException.class) + public void invalidTransportProfile() throws OxalisTransmissionException { + messageSenderFactory.getMessageSender(TransportProfile.START); + } + + @Test + public void canDisableTransportProfileByMode() { + List transportProfileList = messageSenderFactory.getPrioritizedTransportProfiles(); + Assert.assertNotNull(transportProfileList); + Assert.assertFalse(transportProfileList.stream().anyMatch(t -> t.getIdentifier().equals("foo-mode-transport")), "should not contain transport which is only enabled in other modes"); + } + + @Test + public void canEnableTransportProfileByMode() { + List transportProfileList = messageSenderFactory.getPrioritizedTransportProfiles(); + Assert.assertNotNull(transportProfileList); + Assert.assertTrue(transportProfileList.stream().anyMatch(t -> t.getIdentifier().equals("dummy-mode-transport")), "should contain transport which is only enabled in DUMMY mode"); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestBuilderTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestBuilderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8b20fb9b301e9432ecd2f23e4a35c3baa5afd2c6 --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestBuilderTest.java @@ -0,0 +1,261 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.test.identifier.PeppolDocumentTypeIdAcronym; +import network.oxalis.test.identifier.PeppolProcessTypeIdAcronym; +import network.oxalis.test.identifier.WellKnownParticipant; +import network.oxalis.api.lang.OxalisException; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.sniffer.PeppolStandardBusinessHeader; +import network.oxalis.sniffer.identifier.ParticipantId; +import network.oxalis.test.lookup.MockLookupModule; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import org.testng.annotations.*; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.security.cert.X509Certificate; +import java.util.Map; + +import static org.testng.Assert.*; + +/** + * These tests needs TransmissionRequestBuilder to run in TEST-mode to be able to override values + * + * @author steinar + * @author thore + */ +@Guice(modules = GuiceModuleLoader.class) +public class TransmissionRequestBuilderTest { + + @Inject + @Named("test-files-with-identification") + public Map testFilesForIdentification; + + @Inject + @Named("test-non-ubl-documents") + public Map testNonUBLFiles; + + @Inject + @Named("sample-xml-with-sbdh") + InputStream inputStreamWithSBDH; + + @Inject + @Named("sample-xml-no-sbdh") + InputStream noSbdhInputStream; + + @Inject + @Named("sample-xml-missing-metadata") + InputStream missingMetadataInputStream; + + @Inject + TransmissionRequestBuilder transmissionRequestBuilder; + + @Inject + private X509Certificate certificate; + + @BeforeMethod + public void setUp() { + MockLookupModule.resetService(); + + // Request overriding + transmissionRequestBuilder.setTransmissionBuilderOverride(true); + + inputStreamWithSBDH.mark(Integer.MAX_VALUE); + noSbdhInputStream.mark(Integer.MAX_VALUE); + } + + @AfterMethod + public void tearDown() throws IOException { + inputStreamWithSBDH.reset(); + noSbdhInputStream.reset(); + } + + @Test + public void makeSureWeAllowOverrides() { + assertNotNull(transmissionRequestBuilder); + assertTrue(transmissionRequestBuilder.isOverrideAllowed(), + "Overriding transmission request parameters is not permitted!"); + } + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test + public void createTransmissionRequestBuilderWithOnlyTheMessageDocument() throws Exception { + + assertNotNull(transmissionRequestBuilder); + assertNotNull(inputStreamWithSBDH); + + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + + // Builds the actual transmission request + TransmissionRequest transmissionRequest = transmissionRequestBuilder.build(); + + PeppolStandardBusinessHeader sbdh = transmissionRequestBuilder.getEffectiveStandardBusinessHeader(); + assertNotNull(sbdh); + assertEquals(sbdh.getRecipientId(), WellKnownParticipant.RANDOM_TEST); + + assertNotNull(transmissionRequest.getEndpoint()); + + assertNotNull(transmissionRequest.getHeader()); + + assertEquals(transmissionRequest.getHeader().getReceiver(), WellKnownParticipant.RANDOM_TEST); + + assertEquals(transmissionRequest.getEndpoint().getTransportProfile(), + TransportProfile.of("busdox-transport-as2-ver1p0")); + + assertNotNull(transmissionRequest.getHeader().getIdentifier()); + } + + @Test + @Ignore + public void xmlWithNoSBDH() throws Exception { + + TransmissionRequestBuilder builder = transmissionRequestBuilder.payLoad(noSbdhInputStream) + .receiver(WellKnownParticipant.DIFI_TEST); + TransmissionRequest request = builder.build(); + + assertNotNull(builder); + assertNotNull(builder.getEffectiveStandardBusinessHeader(), "Effective SBDH is null"); + + assertEquals(builder.getEffectiveStandardBusinessHeader().getRecipientId(), + WellKnownParticipant.DIFI_TEST, "Receiver has not been overridden"); + assertEquals(request.getHeader().getReceiver(), WellKnownParticipant.DIFI_TEST); + + } + + + @Test + @Ignore + public void overrideFields() throws Exception { + + TransmissionRequestBuilder builder = transmissionRequestBuilder.payLoad(noSbdhInputStream) + .sender(WellKnownParticipant.DIFI_TEST) + .receiver(WellKnownParticipant.U4_TEST) + .documentType(PeppolDocumentTypeIdAcronym.ORDER.toVefa()); + + TransmissionRequest request = builder.build(); + + assertEquals(request.getEndpoint().getTransportProfile(), TransportProfile.of("busdox-transport-as2-ver1p0")); + assertEquals(request.getHeader().getReceiver(), WellKnownParticipant.U4_TEST); + assertEquals(request.getHeader().getSender(), WellKnownParticipant.DIFI_TEST); + assertEquals(request.getHeader().getDocumentType(), + PeppolDocumentTypeIdAcronym.ORDER.toVefa()); + } + + @Test + public void testOverrideEndPoint() throws Exception { + assertNotNull(inputStreamWithSBDH); + URI url = URI.create("http://localhost:8080/oxalis/as2"); + TransmissionRequest request = transmissionRequestBuilder + .payLoad(inputStreamWithSBDH) + .overrideAs2Endpoint(Endpoint.of(TransportProfile.AS2_1_0, url, certificate)) + .build(); + assertEquals(request.getEndpoint().getTransportProfile(), TransportProfile.AS2_1_0); + assertEquals(request.getEndpoint().getAddress(), url); + } + + @Test + public void testOverrideOfAllValues() throws Exception { + TransmissionIdentifier transmissionIdentifier = TransmissionIdentifier.of("messageid"); + TransmissionRequest request = transmissionRequestBuilder + .payLoad(inputStreamWithSBDH) + .sender(WellKnownParticipant.DIFI_TEST) + .receiver(WellKnownParticipant.U4_TEST) + .documentType(PeppolDocumentTypeIdAcronym.ORDER.toVefa()) + .processType(PeppolProcessTypeIdAcronym.ORDER_ONLY.toVefa()) + .build(); + + Header header = request.getHeader(); + assertEquals(header.getSender(), WellKnownParticipant.DIFI_TEST); + assertEquals(header.getReceiver(), WellKnownParticipant.U4_TEST); + assertEquals(header.getDocumentType(), PeppolDocumentTypeIdAcronym.ORDER.toVefa()); + assertEquals(header.getProcess(), PeppolProcessTypeIdAcronym.ORDER_ONLY.toVefa()); + assertNotEquals(header.getIdentifier().getIdentifier(), transmissionIdentifier.getIdentifier(), + "The SBDH instanceId should not be equal to the AS2 transmission identifier"); + } + + /** + * If a messageId is not provided a default one is created before sending. + */ + @Test + @Ignore + public void testMessageIdSuppliedByBuilder() throws OxalisException { + TransmissionRequest request = transmissionRequestBuilder + .payLoad(inputStreamWithSBDH) + .sender(WellKnownParticipant.DIFI_TEST) + .receiver(WellKnownParticipant.U4_TEST) + .documentType(PeppolDocumentTypeIdAcronym.ORDER.toVefa()) + .processType(PeppolProcessTypeIdAcronym.ORDER_ONLY.toVefa()) + .build(); + + assertNotNull(request.getHeader().getIdentifier()); + + transmissionRequestBuilder.reset(); + TransmissionRequest request2 = transmissionRequestBuilder.payLoad(noSbdhInputStream) + .sender(WellKnownParticipant.DIFI_TEST) + .receiver(WellKnownParticipant.U4_TEST) + .documentType(PeppolDocumentTypeIdAcronym.ORDER.toVefa()) + .processType(PeppolProcessTypeIdAcronym.ORDER_ONLY.toVefa()) + .build(); + + assertNotNull(request2.getHeader().getIdentifier()); + } + + @Test + @Ignore + public void makeSureWeDetectMissingProperties() { + try { + transmissionRequestBuilder + .payLoad(missingMetadataInputStream) + .build(); + fail("The build() should have failed indicating missing properties"); + } catch (Exception ex) { + assertEquals(ex.getMessage(), + "TransmissionRequest can not be built, missing [recipientId, senderId] metadata."); + } + } + + @Test + @Ignore + public void testIssue250() throws Exception { + InputStream resourceAsStream = getClass().getResourceAsStream("/Issue250-sample-invoice.xml"); + assertNotNull(resourceAsStream); + + transmissionRequestBuilder.reset(); + TransmissionRequest transmissionRequest = transmissionRequestBuilder.payLoad(resourceAsStream).build(); + + ParticipantIdentifier recipientId = transmissionRequest.getHeader().getReceiver(); + assertEquals(recipientId, new ParticipantId("9954:111111111").toVefa()); + assertNotNull(transmissionRequest.getHeader().getIdentifier()); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestBuilderWithoutOverridesTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestBuilderWithoutOverridesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1719e5cc38698882711d9596d9d42f456373343b --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestBuilderWithoutOverridesTest.java @@ -0,0 +1,188 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisException; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.sniffer.identifier.ParticipantId; +import network.oxalis.test.lookup.MockLookupModule; +import network.oxalis.vefa.peppol.common.model.*; +import org.testng.annotations.*; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.security.cert.X509Certificate; + +import static org.testng.Assert.*; + +/** + * These tests needs TransmissionRequestBuilder to run in PRODUCTION-mode + * and verifies that we are unable to override key values + * + * @author thore + */ +@Guice(modules = GuiceModuleLoader.class) +public class TransmissionRequestBuilderWithoutOverridesTest { + + @Inject + @Named("sample-xml-with-sbdh") + private InputStream inputStreamWithSBDH; + + @Inject + @Named("sample-xml-no-sbdh") + private InputStream noSbdhInputStream; + + @Inject + private TransmissionRequestBuilder transmissionRequestBuilder; + + @Inject + private X509Certificate certificate; + + + @BeforeMethod + public void setUp() { + // Defaults to prevention of overriding + transmissionRequestBuilder.setTransmissionBuilderOverride(false); + + // Ensures that the state of the transmissionrequest builder is reset for each test method + transmissionRequestBuilder.reset(); + inputStreamWithSBDH.mark(Integer.MAX_VALUE); + noSbdhInputStream.mark(Integer.MAX_VALUE); + } + + @AfterMethod + public void tearDown() throws IOException { + inputStreamWithSBDH.reset(); + noSbdhInputStream.reset(); + } + + @Test + public void makeSureWeDoNotAllowOverrides() { + assertNotNull(transmissionRequestBuilder); + assertFalse(transmissionRequestBuilder.isOverrideAllowed()); + } + + @Test + public void makeSureTestDataAreAvailable() { + assertNotNull(inputStreamWithSBDH); + assertNotNull(noSbdhInputStream); + } + + @Test(expectedExceptions = IllegalStateException.class, + expectedExceptionsMessageRegExp = ".*not allowed to override \\[SenderId\\] in production mode.*") + public void makeSureWeAreUnableToOverrideSender() throws OxalisException { + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + transmissionRequestBuilder.sender(ParticipantIdentifier.of("0088:0000000000")); + transmissionRequestBuilder.build(); + fail("We expected this test to fail"); + } + + @Test(expectedExceptions = IllegalStateException.class, + expectedExceptionsMessageRegExp = ".*not allowed to override \\[RecipientId\\] in production mode.*") + public void makeSureWeAreUnableToOverrideReceiver() throws OxalisException { + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + transmissionRequestBuilder.receiver(ParticipantIdentifier.of("0088:0000000000")); + transmissionRequestBuilder.build(); + fail("We expected this test to fail"); + } + + @Test(expectedExceptions = RuntimeException.class, + expectedExceptionsMessageRegExp = ".*not allowed to override \\[DocumentTypeIdentifier\\] in production mode.*") + public void makeSureWeAreUnableToOverrideDocumentType() throws OxalisException { + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + transmissionRequestBuilder.documentType(DocumentTypeIdentifier.of("this::is##not::found")); + transmissionRequestBuilder.build(); + fail("We expected this test to fail"); + } + + @Test(expectedExceptions = IllegalStateException.class, + expectedExceptionsMessageRegExp = ".*not allowed to override \\[ProfileTypeIdentifier\\] in production mode.*") + public void makeSureWeAreUnableToOverrideProcessType() throws OxalisException { + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + transmissionRequestBuilder.processType(ProcessIdentifier.of("urn:some-undefined-process")); + transmissionRequestBuilder.build(); + } + + @Test(expectedExceptions = IllegalStateException.class, + expectedExceptionsMessageRegExp = ".*not allowed to override \\[SenderId, RecipientId, DocumentTypeIdentifier, ProfileTypeIdentifier\\] in production mode.*") + public void makeSureWeDetectAllIllegalOverrides() throws OxalisException { + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + transmissionRequestBuilder.sender(ParticipantIdentifier.of("0088:0000000000")); + transmissionRequestBuilder.receiver(ParticipantIdentifier.of("0088:0000000000")); + transmissionRequestBuilder.documentType(DocumentTypeIdentifier.of("this::is##not::found")); + transmissionRequestBuilder.processType(ProcessIdentifier.of("urn:some-undefined-process")); + transmissionRequestBuilder.build(); + } + + // This test is ignored due to UAN-318 - Fjern AS2 protokollen fra Oxalis AP. AS2 no longer supported. Hence the endpoint no longer exists + @Ignore + @Test(expectedExceptions = IllegalStateException.class, + expectedExceptionsMessageRegExp = "You are not allowed to override the EndpointAddress from SMP.") + public void makeSureWeDetectEndpointOverrides() throws Exception { + MockLookupModule.resetService(); + + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + transmissionRequestBuilder.overrideAs2Endpoint(Endpoint.of( + TransportProfile.AS2_1_0, URI.create("http://localhost:8443/oxalis/as2"), null)); + transmissionRequestBuilder.build(); + } + + @Test + public void makeSureWeCanSupplySameValuesAsThoseFromTheDocument() throws Exception { + + transmissionRequestBuilder.payLoad(inputStreamWithSBDH); + transmissionRequestBuilder.sender(ParticipantIdentifier.of("9908:976098897")); + transmissionRequestBuilder.receiver(ParticipantIdentifier.of("9908:810017902")); + transmissionRequestBuilder.documentType(DocumentTypeIdentifier.of( + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol4a:ver1.0" + + "::2.0", DocumentTypeIdentifier.BUSDOX_DOCID_QNS_SCHEME)); + transmissionRequestBuilder.processType(ProcessIdentifier.of("urn:www.cenbii.eu:profile:bii04:ver1.0")); + transmissionRequestBuilder.overrideAs2Endpoint(Endpoint.of( + TransportProfile.AS2_1_0, URI.create("https://localhost:8080/oxalis/as2"), certificate)); + + transmissionRequestBuilder.setTransmissionBuilderOverride(true); + + // Builds the request + TransmissionRequest request = transmissionRequestBuilder.build(); + + Header header = request.getHeader(); + assertNotEquals(header.getIdentifier().getIdentifier(), "1070e7f0-3bae-11e3-aa6e-0800200c9a66"); + assertEquals(header.getSender(), new ParticipantId("9908:976098897").toVefa()); + assertEquals(header.getReceiver(), new ParticipantId("9908:810017902").toVefa()); + assertEquals(header.getDocumentType(), DocumentTypeIdentifier.of( + "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol4a:ver1.0" + + "::2.0", DocumentTypeIdentifier.BUSDOX_DOCID_QNS_SCHEME)); + assertEquals(header.getProcess(), ProcessIdentifier.of("urn:www.cenbii.eu:profile:bii04:ver1.0")); + assertEquals(request.getEndpoint(), Endpoint.of( + TransportProfile.AS2_1_0, URI.create("https://localhost:8080/oxalis/as2"), certificate)); + } + +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestFactoryMockTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestFactoryMockTest.java new file mode 100644 index 0000000000000000000000000000000000000000..12ab57d234a95c0900262fcbe511124a2a7b2b9f --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestFactoryMockTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import com.google.inject.Injector; +import com.google.inject.util.Modules; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.outbound.TransmissionMessage; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.test.lookup.MockLookupModule; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import javax.inject.Inject; +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +public class TransmissionRequestFactoryMockTest { + + private Injector injector = com.google.inject.Guice.createInjector( + Modules.override(new GuiceModuleLoader()).with(new MockLookupModule())); + + @Inject + private TransmissionRequestFactory transmissionRequestFactory; + + @BeforeClass + public void beforeClass() { + transmissionRequestFactory = injector.getInstance(TransmissionRequestFactory.class); + } + + @Test + public void simple() throws Exception { + MockLookupModule.resetService(); + + TransmissionMessage transmissionMessage; + try (InputStream inputStream = getClass().getResourceAsStream("/peppol-bis-invoice-sbdh.xml")) { + transmissionMessage = transmissionRequestFactory.newInstance(inputStream); + } + + Assert.assertNotNull(transmissionMessage.getHeader()); + } + + @Test(expectedExceptions = OxalisContentException.class) + public void unrecognizedContent() throws Exception { + transmissionRequestFactory.newInstance(new ByteArrayInputStream("Hello World!".getBytes())); + } +} diff --git a/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestFactoryTest.java b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestFactoryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..15eb519c4e3b51127c2ee470f7a1a321055200bd --- /dev/null +++ b/oxalis-outbound/src/test/java/network/oxalis/outbound/transmission/TransmissionRequestFactoryTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.outbound.transmission; + +import network.oxalis.api.outbound.TransmissionMessage; +import network.oxalis.commons.guice.GuiceModuleLoader; +import network.oxalis.test.lookup.MockLookupModule; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.inject.Inject; +import java.io.InputStream; + +@Guice(modules = GuiceModuleLoader.class) +public class TransmissionRequestFactoryTest { + + @Inject + private TransmissionRequestFactory transmissionRequestFactory; + + @Test + public void simple() throws Exception { + MockLookupModule.resetService(); + + TransmissionMessage transmissionMessage; + try (InputStream inputStream = getClass().getResourceAsStream("/simple-sbd.xml")) { + transmissionMessage = transmissionRequestFactory.newInstance(inputStream); + } + + Assert.assertNotNull(transmissionMessage.getHeader()); + } +} diff --git a/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel1.xml b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel1.xml new file mode 100644 index 0000000000000000000000000000000000000000..462a682173f2825449763e8e91eefd7e99db041f --- /dev/null +++ b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel1.xml @@ -0,0 +1,126 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns016:ver1.0:extended:urn:www.peppol.eu:bis:peppol30a:ver1.0:extended:urn:www.difi.no:ehf:pakkseddel:ver1.0 + urn:www.cenbii.eu:profile:bii30:ver2.0 + 1234 + 2013-03-15 + 08:00:00 + Free text note relating to the Despatch Advice + + 4321 + + + + 123456789 + + Sender Company + + + John + 123456789 + 8273741728 + John@SenderCompany.no + + + + + + 987654321 + + Receiver Company + + + 25 + Receiver Street 1 + Receiver Building + Receiver City + 9000 + Region A + + NO + + + + + Tim + 987654321 + 4546474849 + Tim@ReceiverCompany.no + + + + NA + The shipment is Despatched on schedule + 10.00 + 25.00 + + 12345 + + + CarrierPart + + + + + + 2013-03-15 + 08:00:00 + 2013-03-16 + 12:00:00 + + + 2013-03-13 + 08:00:00 + + + + + 1 + 10 + + 1 + + + Item123 + + 010120401 + + + + + 2 + 10 + + 2 + + + Item456 + + 010140403 + + + + diff --git a/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel2.xml b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel2.xml new file mode 100644 index 0000000000000000000000000000000000000000..0c43c4c7c23a0b562a28506a4e24aab0b0ca7539 --- /dev/null +++ b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel2.xml @@ -0,0 +1,231 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns016:ver1.0:extended:urn:www.peppol.eu:bis:peppol30a:ver1.0:extended:urn:www.difi.no:ehf:pakkseddel:ver1.0 + urn:www.cenbii.eu:profile:bii30:ver2.0 + 1234 + 2013-03-15 + 08:00:00 + Free text note relating to the Despatch Advice + + 4321 + + + + 123456789 + + 5790000435968 + + + Sender Company + + + John + 123456789 + 8273741728 + John@SenderCompany.no + + + + + + 987654321 + + 5790000435944 + + + Receiver Company + + + 25 + Receiver Street 1 + Receiver Building + Receiver City + 9000 + Region A + + NO + + + + + Tim + 987654321 + 4546474849 + Tim@ReceiverCompany.no + + + + + + 5790000435951 + + + Buyer Company + + + + + + + 5790000436057 + + + Seller Company + + + Allan + 43444546 + 12345678 + Allan@SellerCompany.no + + + + + NA + Free text information relating to the Shipment + 23 + 27 + + 12345 + + + CarrierParty + + + + + + 2013-03-15 + 08:00:00 + 2013-03-16 + 12:00:00 + + + 2013-03-13 + 08:00:00 + + + + + + 1 + Free text information relating to the despatch line + 10 + + 1 + + + Item123 + + 010120401 + 123 + + + 7611104117056 + 123 + + + + + + 2 + Free text information relating to the despatch line + 6 + 4 + AV + + 2 + + + Item456 + + 010120409 + + + 7611104117054 + + + + + + 3 + Free text information relating to the despatch line + 6 + 0 + AV + + 3 + + + Item789 + + 010120405 + + + 7611104117052 + + + + + + 4 + Free text information relating to the despatch line + 6 + 3 + AV + + 4 + + + Item321 + + 010120407 + + + 7611104117055 + + + + + + 5 + This line contains an oversupply + 12 + WQ + + 5 + + + Item654 + + 010120408 + + + 7611104117051 + + + + diff --git a/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel3.xml b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel3.xml new file mode 100644 index 0000000000000000000000000000000000000000..160093553dbe9878dbc228e65b50115bcd4fbb9d --- /dev/null +++ b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel3.xml @@ -0,0 +1,239 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns016:ver1.0:extended:urn:www.peppol.eu:bis:peppol30a:ver1.0 + urn:www.cenbii.eu:profile:bii30:ver2.0 + 1234 + 2013-03-15 + 08:00:00 + Goods are not to be left unattended + + 4321 + + + + 123456789 + + 5790000435968 + + + John Smith + 123456789 + 8273741728 + John.Smith@SenderCompany.no + + + + + + 987654321 + + 5790000435944 + + + + 5790000435951> + + + + Hr Berg + 987654321 + 4546474849 + berg@ReceiverCompany.no + + + + + + 5790000436057 + + + Miracle products Ltd + + + + + + + 5790000436064 + + + Widget makers inc + + + Allan Green + 43444546 + 12345678 + Allan.Green@SellerCompany.dk + + + + + 57098761234567890 + Free text information relating to the Shipment + 23.00 + 27.00 + + 570987698767654567898767876765 + + + Swift and Sure Freight Co Ltd + + + + + + 2013-03-15 + 08:00:00 + 2013-03-16 + 12:00:00 + + + 2013-03-13 + 08:00:00 + + + + + 1 + Free text information relating to the despatch line + 10 + + 1 + + + Wondercure medicare kit + + 05702938473625 + + + 1234567 + + 898A123 + 2015-07-01 + + + + + NA + + 340123450000000014 + OE + + AAB + 10.00 + + + + + + 2 + Free text information relating to the despatch line + 23 + + 2 + + + Brake-a-leg Supersplint set + + 7611104117051 + + + + 898A124 + 2015-07-01 + + + + + NA + + 340123450000000014 + OE + + AAB + 7.00 + + + + + + 3 + Free text information relating to the despatch line + 500 + + 3 + + + Cough sirup + + 08886765117054 + 123 + + + + 898A128 + 2015-07-01 + + + + + NA + + 354123450000000106 + OE + + AAB + 7.00 + + + + + + 4 + Free text information relating to the despatch line + 12 + + 4 + + + Tray, plastic + + 057098987656543 + + + + NA + + 354123450000000106 + OE + + AAB + 7.00 + + + + + diff --git a/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel4.xml b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel4.xml new file mode 100644 index 0000000000000000000000000000000000000000..b8f2d4f535927e249dfab223bc02c0f5406399e4 --- /dev/null +++ b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel4.xml @@ -0,0 +1,204 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns016:ver1.0:extended:urn:www.peppol.eu:bis:peppol30a:ver1.0:extended:urn:www.difi.no:ehf:pakkseddel:ver1.0 + urn:www.cenbii.eu:profile:bii30:ver2.0 + 1234 + 2013-03-15 + 08:00:00 + Use Case 4 Despatch with weight and/or volume based articles (ie vegetables, meat) + + 4321 + + + + 123456789 + + 5790000435968 + + + Sender Company + + + John + 123456789 + 8273741728 + Monica@SenderCompany.no + + + + + + 987654321 + + 5790000435944 + + + Receiver Company + + + 25 + Reciever Street 1 + Receiver Building + Reciever City + 9000 + Region A + + NO + + + + + Tim + 987654321 + 4546474849 + Tim@ReceiverCompany.no + + + + NA + 15 + + + 2013-03-15 + 08:00:00 + + + + + 1 + 4.25 + + 1 + + + Cheese app 1 kg + + 07311104114566 + + + 2013-05-01 + + + + NA + + 173111000000000013 + SW + + AAB + 4.50 + + + + + + 2 + 5.97 + + 2 + + + Bananas + + 07311100000030 + + + + NA + + 173111000000000020 + UTE + + AAB + 6.07 + + + + + + 3 + 8 + + 3 + + + Nasal Drops + + 87774744 + + + + 898A123 + 2015-07-01 + + + + + NA + + 173111000000000037 + PA + + AAB + 1.00 + + + + + + 4 + 3 + + 5 + + + Medical device 010120789 + + 010120789 + + + OR250RHZ444 + + + OR250RHZ4445 + + + OR250RHZ4446 + + + + NA + + 173111000000000044 + BX + + AAB + 2.50 + + + + + diff --git a/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel5.xml b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel5.xml new file mode 100644 index 0000000000000000000000000000000000000000..3f9431b38f92f7f7549ba849e5e1332f9d1fc741 --- /dev/null +++ b/oxalis-outbound/src/test/resources/DespatchAdvice/1.0/Eksempel5.xml @@ -0,0 +1,320 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns016:ver1.0:extended:urn:www.peppol.eu:bis:peppol30a:ver1.0:extended:urn:www.difi.no:ehf:pakkseddel:ver1.0 + urn:www.cenbii.eu:profile:bii30:ver2.0 + 1234 + 2013-03-15 + 08:00:00 + Use Case 5 Demonstrates the use of most of the existing terms available in the Despatch advice message + + 4321 + + + + 123456789 + + 5790000435968 + + + Sender Company + + + John + 123456789 + 8273741728 + John@SenderCompany.no + + + + + + 987654321 + + 5790000435944 + + + Receiver Company + + + Receiver Street 1 + Receiver Building + Receiver City + 9000 + Region A + + NO + + + + + Tim + 987654321 + 4546474849 + Tim@RecieverCompany.no + + + + + + 5790000435951 + + + Buyer Company + + + + + + + 5541277711 + + + Seller Company + + + Allan + 43444546 + 12345678 + Allan@SellerCompany.se + + + + + + + 5790000436064 + + + Original orderer + + + + + 57098761234567890 + Free text information relating to the Shipment + 19.7 + 0.5 + 4 + + 570987698767654567898767876765 + Truck 3356 + + + Posten Norge + + + + 75445 + Employee no in Posten Norge + + + + + + 37900933321178298510 + + 2013-03-15 + 08:00:00 + 2013-03-15 + 12:00:00 + + + 2013-03-15 + 09:34:00 + + Pickup Street 1 + Pickup Building + Pickup City + 9000 + Region A + + NO + + + + + + + 1 + Free text information relating to the despatch line + 1 + + 1 + + + Item123 + + 07311100000047 + 123 + + + OR250RHZ444 + + 898A123 + 2015-07-01 + + + + + NA + + 173111000000000013 + BX + + AAB + 7.00 + + + + + + 2 + Free text information relating to the despatch line + 6 + + 2 + + + Item456 + + 010120402 + 123 + + + 2013-05-01 + + + + NA + + 173111000000000013 + PA + + AAB + 5.00 + + + + + + 3A + Free text information relating to the despatch line + 3.0 + + 3 + + + Item789 + + 010120403 + + + 2015-04-15 + + + + NA + + 173111000000000020 + UTE + + AAB + 3.1 + + + + + + 3B + Free text information relating to the despatch line + 0.975 + + 3 + + + Item789 + + 010120403 + + + 2015-04-25 + + + + NA + + 173111000000000037 + UTE + + AAB + 1.0 + + + + + + 4 + Free text information relating to the despatch line + 3 + + 5 + + + Item987 + + 7611104117059 + + + ADR + 2.3 + + + OR250RHZ4464 + + 898A129 + + + + OR250RHZ445 + + + OR250RHZ446 + + + + NA + + 173111000000000044 + PA + true + + AAB + 3.60 + + + + + diff --git a/oxalis-outbound/src/test/resources/EHFCatalogue/1.0/Example file EHF Catalogue Response.xml b/oxalis-outbound/src/test/resources/EHFCatalogue/1.0/Example file EHF Catalogue Response.xml new file mode 100644 index 0000000000000000000000000000000000000000..6ec1c3baba3ac8057602d0c26c08e707e060c9a9 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFCatalogue/1.0/Example file EHF Catalogue Response.xml @@ -0,0 +1,44 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns058:ver2.0:extended:urn:www.peppol.eu:bis:peppol1a:ver2.0:extended:urn:www.difi.no:ehf:katalogbekreftelse:ver1.0 + urn:www.cenbii.eu:profile:biiI02:ver2.0 + 1 + 2012-05-29 + + 1234567890 + + + 123456789 + + + + RE + + + 1 + + + diff --git a/oxalis-outbound/src/test/resources/EHFCatalogue/1.0/Example file EHF Catalogue.xml b/oxalis-outbound/src/test/resources/EHFCatalogue/1.0/Example file EHF Catalogue.xml new file mode 100644 index 0000000000000000000000000000000000000000..ed3b69eb42b7a4943189297cc0baee119bc4770e --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFCatalogue/1.0/Example file EHF Catalogue.xml @@ -0,0 +1,214 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns019:ver2.0:extended:urn:www.peppol.eu:bis:peppol1a:ver2.0:extended:urn:www.difi.no:ehf:katalog:ver1.0 + urn:www.cenbii.eu:profile:bii01:ver2.0 + 1234 + Add + 2013-09-23 + v1.0 + + 2013-09-25 + 2013-12-31 + + + 123123 + StandardContract + + + 1234567890 + + Provider AS + + + Produsentnavn + + + + 123456789 + + HBE 1018275 + + + Helse Vest + + + + + 987654321 + + 984297793 + + + Supplier + + + Per Krohgs vei 1,Karihaugen + OSLO + Norway + + NO + + + + Ole Olsen + +46123123123 + test@ibxeurope.com + + + + + + 113 + Add + true + PK + 1 + + 111 + 25 + + + + 31.16 + + + + Limsparkel 10cm (25) + + 8085250 + + + 1 + HMS Safety sheet + + + http://www.unece.org/trans/danger/publi/unrec/rev13/13files_e.html + + + + + 44121631 + + + 3265 + + + M + + VAT + + + + + + 114 + Add + true + EA + + + 2406.76 + + + + Skriver Brother HL4150CDN fargelaser + + 772583 + + + 43212105 + + + BAL + SVANEN + SVANEN + + + SVANEN + + + + http://www.anskaffelser.no/artikler/2010/03/der-blaue-engel-blaa-engel + + + + + + 200 + Add + true + EA + 1 + 1 + 1 + 1 + CU + + 2013-10-01 + 2013-12-31 + + + 13 + + 504.5 + + + + + 1 + LÅSKASSE LK1362/28 R STOLPE25 + + 2451015 + + + 2451015 + + + 05704368876486 + + + 46171500 + + + S + + VAT + + + + + Manufacturer + + + + AAE + 0.574 + + + + diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profil05-without-endpointid.xml b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profil05-without-endpointid.xml new file mode 100644 index 0000000000000000000000000000000000000000..2c5f901b12cb5454795ae21b0c2800954bc14de9 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profil05-without-endpointid.xml @@ -0,0 +1,245 @@ + + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0:#urn:www.peppol.eu:bis:peppol5a:ver1.0#urn:www.difi.no:ehf:kreditnota:ver1 + urn:www.cenbii.eu:profile:bii05:ver1.0 + 32 + 2012-07-24 + NOK + + DTJ1234 + + + Kontrakt + + + + + + 7080003093035 + + + IntegrasjonsPartner testkunde + + + 7080003093035 + Sarpsborg + Sarpsborg + 1710 + + NO + + + + 977187761MVA + + VAT + + + + IntegrasjonsPartner testkunde + 977187761 + + Sarpsborg + + NO + + + + + David + + + + + + + + 7080003093035 + + + TestKunde + + + Storgata 3 + SARPSBORG + 1701 + + NO + + + + 810305282MVA + + VAT + + + + TestKunde + 810305282 + + SARPSBORG + + NO + + + + + DTJ1234 + + + + + true + Frakt + 100.00 + + S + 25.00 + + VAT + + + + + true + Fakturagebyr + 75.00 + + S + 25.00 + + VAT + + + + + false + 2% Totalrabatt + 69.00 + + S + 25.00 + + VAT + + + + + 889.00 + + 3556.00 + 889.00 + + S + 25.00 + + VAT + + + + + + 3450.00 + 3556.00 + 4445.00 + 69.00 + 175.00 + 0.00 + 4445.00 + + +1 + 10.00 + 900.00 + 123 + + Vare A + + AAA + + + S + 25.00 + + VAT + + + + + 90.00 + + false + 10%Rabatt + + 0.100 + 10.00 + 100.00 + + + + + 2 + 15.00 + 2550.00 + 123 + + Vare B + + BBB + + + S + 25.00 + + VAT + + + + + 170.00 + + false + 20% Kampanjerabatt, deretter 15% Rabatt + + 80.00 + 250.00 + + + + diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profil05.xml b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profil05.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d9e2d358a87cb708042e4f8434cbd2a7c4c1c91 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profil05.xml @@ -0,0 +1,245 @@ + + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0:#urn:www.peppol.eu:bis:peppol5a:ver1.0#urn:www.difi.no:ehf:kreditnota:ver1 + urn:www.cenbii.eu:profile:bii05:ver1.0 + 32 + 2012-07-24 + NOK + + DTJ1234 + + + Kontrakt + + + + 9908:977187761 + + 7080003093035 + + + IntegrasjonsPartner testkunde + + + 7080003093035 + Sarpsborg + Sarpsborg + 1710 + + NO + + + + 977187761MVA + + VAT + + + + IntegrasjonsPartner testkunde + 977187761 + + Sarpsborg + + NO + + + + + David + + + + + + 9908:810305282 + + 7080003093035 + + + TestKunde + + + Storgata 3 + SARPSBORG + 1701 + + NO + + + + 810305282MVA + + VAT + + + + TestKunde + 810305282 + + SARPSBORG + + NO + + + + + DTJ1234 + + + + + true + Frakt + 100.00 + + S + 25.00 + + VAT + + + + + true + Fakturagebyr + 75.00 + + S + 25.00 + + VAT + + + + + false + 2% Totalrabatt + 69.00 + + S + 25.00 + + VAT + + + + + 889.00 + + 3556.00 + 889.00 + + S + 25.00 + + VAT + + + + + + 3450.00 + 3556.00 + 4445.00 + 69.00 + 175.00 + 0.00 + 4445.00 + + +1 + 10.00 + 900.00 + 123 + + Vare A + + AAA + + + S + 25.00 + + VAT + + + + + 90.00 + + false + 10%Rabatt + + 0.100 + 10.00 + 100.00 + + + + + 2 + 15.00 + 2550.00 + 123 + + Vare B + + BBB + + + S + 25.00 + + VAT + + + + + 170.00 + + false + 20% Kampanjerabatt, deretter 15% Rabatt + + 80.00 + 250.00 + + + + diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profilxx.xml b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profilxx.xml new file mode 100644 index 0000000000000000000000000000000000000000..48d1befbcad829222e26a41c675b010d9b77dd51 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profilxx.xml @@ -0,0 +1,246 @@ + + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0:#urn:www.peppol.eu:bis:peppol5a:ver1.0#urn:www.difi.no:ehf:kreditnota:ver1 + urn:www.cenbii.eu:profile:biixx:ver1.0 + 32 + 2012-07-24 + NOK + + DTJ1234 + + + Kontrakt + + + + 9908:977187761 + + 7080003093035 + + + IntegrasjonsPartner testkunde + + + 7080003093035 + Sarpsborg + Sarpsborg + 1710 + + NO + + + + 977187761MVA + + VAT + + + + IntegrasjonsPartner testkunde + 977187761 + + Sarpsborg + + NO + + + + + David + + + + + + 9908:810305282 + + 7080003093035 + + + TestKunde + + + Storgata 3 + SARPSBORG + 1701 + + NO + + + + 810305282MVA + + VAT + + + + TestKunde + 810305282 + + SARPSBORG + + NO + + + + + DTJ1234 + + + + + true + Frakt + 100.00 + + S + 25.00 + + VAT + + + + + true + Fakturagebyr + 75.00 + + S + 25.00 + + VAT + + + + + false + 2% Totalrabatt + 69.00 + + S + 25.00 + + VAT + + + + + 889.00 + + 3556.00 + 889.00 + + S + 25.00 + + VAT + + + + + + 3450.00 + 3556.00 + 4445.00 + 69.00 + 175.00 + 0.00 + 4445.00 + + +1 + 10.00 + 900.00 + 123 + + Vare A + + AAA + + + S + 25.00 + + VAT + + + + + 90.00 + + false + 10%Rabatt + + 0.100 + 10.00 + 100.00 + + + + + 2 + 15.00 + 2550.00 + 123 + + Vare B + + BBB + + + S + 25.00 + + VAT + + + + + 170.00 + + false + 20% Kampanjerabatt, deretter 15% Rabatt + + 80.00 + 250.00 + + + + diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profilxy.xml b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profilxy.xml new file mode 100644 index 0000000000000000000000000000000000000000..5903041489f62d0498ce22b5cf5e8e02f0f6a5aa --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-norsk-profilxy.xml @@ -0,0 +1,245 @@ + + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0:#urn:www.cenbii.eu:profile:biixy:ver1.0#urn:www.difi.no:ehf:kreditnota:ver1 + urn:www.cenbii.eu:profile:biixy:ver1.0 + 32 + 2012-07-24 + NOK + + DTJ1234 + + + Kontrakt + + + + 9908:977187761 + + 7080003093035 + + + IntegrasjonsPartner testkunde + + + 7080003093035 + Sarpsborg + Sarpsborg + 1710 + + NO + + + + 977187761MVA + + VAT + + + + IntegrasjonsPartner testkunde + 977187761 + + Sarpsborg + + NO + + + + + David + + + + + + 9908:810305282 + + 7080003093035 + + + TestKunde + + + Storgata 3 + SARPSBORG + 1701 + + NO + + + + 810305282MVA + + VAT + + + + TestKunde + 810305282 + + SARPSBORG + + NO + + + + + DTJ1234 + + + + + true + Frakt + 100.00 + + S + 25.00 + + VAT + + + + + true + Fakturagebyr + 75.00 + + S + 25.00 + + VAT + + + + + false + 2% Totalrabatt + 69.00 + + S + 25.00 + + VAT + + + + + 889.00 + + 3556.00 + 889.00 + + S + 25.00 + + VAT + + + + + + 3450.00 + 3556.00 + 4445.00 + 69.00 + 175.00 + 0.00 + 4445.00 + + +1 + 10.00 + 900.00 + 123 + + Vare A + + AAA + + + S + 25.00 + + VAT + + + + + 90.00 + + false + 10%Rabatt + + 0.100 + 10.00 + 100.00 + + + + + 2 + 15.00 + 2550.00 + 123 + + Vare B + + BBB + + + S + 25.00 + + VAT + + + + + 170.00 + + false + 20% Kampanjerabatt, deretter 15% Rabatt + + 80.00 + 250.00 + + + + diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-utland-profil05.xml b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-utland-profil05.xml new file mode 100644 index 0000000000000000000000000000000000000000..7a2599874719023b117512af6b86d99d284f9bd5 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/1.6/T14-utland-profil05.xml @@ -0,0 +1,245 @@ + + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0:#urn:www.peppol.eu:bis:peppol5a:ver1.0 + urn:www.cenbii.eu:profile:bii05:ver1.0 + 32 + 2012-07-24 + NOK + + DTJ1234 + + + Kontrakt + + + + 9908:977187761 + + 7080003093035 + + + IntegrasjonsPartner testkunde + + + 7080003093035 + Sarpsborg + Sarpsborg + 1710 + + NO + + + + 977187761MVA + + VAT + + + + IntegrasjonsPartner testkunde + 977187761 + + Sarpsborg + + NO + + + + + David + + + + + + 9908:810305282 + + 7080003093035 + + + TestKunde + + + Storgata 3 + SARPSBORG + 1701 + + NO + + + + 810305282MVA + + VAT + + + + TestKunde + 810305282 + + SARPSBORG + + NO + + + + + DTJ1234 + + + + + true + Frakt + 100.00 + + S + 25.00 + + VAT + + + + + true + Fakturagebyr + 75.00 + + S + 25.00 + + VAT + + + + + false + 2% Totalrabatt + 69.00 + + S + 25.00 + + VAT + + + + + 889.00 + + 3556.00 + 889.00 + + S + 25.00 + + VAT + + + + + + 3450.00 + 3556.00 + 4445.00 + 69.00 + 175.00 + 0.00 + 4445.00 + + +1 + 10.00 + 900.00 + 123 + + Vare A + + AAA + + + S + 25.00 + + VAT + + + + + 90.00 + + false + 10%Rabatt + + 0.100 + 10.00 + 100.00 + + + + + 2 + 15.00 + 2550.00 + 123 + + Vare B + + BBB + + + S + 25.00 + + VAT + + + + + 170.00 + + false + 20% Kampanjerabatt, deretter 15% Rabatt + + 80.00 + 250.00 + + + + diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T10-B2C.xml b/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T10-B2C.xml new file mode 100644 index 0000000000000000000000000000000000000000..bc072989ea04f9c1a51dfbe2762a60b9bf345875 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T10-B2C.xml @@ -0,0 +1,213 @@ + + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0 + urn:www.cenbii.eu:profile:bii05:ver2.0 + 1001776522 + 2013-05-08 + 380 + Målernummer: 008999762 + 2013-05-08 + NOK + + 2013-01-04 + 2013-01-05 + + + 1 + + + 3345534454213433 + efakturareferanse + + + + 123456789 + + Kraftleverandøren ASA + + + Postboks 123 + Oslo + 0203 + + NO + + + + 123456789MVA + + VAT + + + + Kraftleverandøren ASA + 123456789 + + Oslo + + NO + + + + + Vår ref. + Hans Hansen + 81509990 + + + + + + 987489712 + + 26987762 + + + Ola Nordmann + + + Strandgt. 14 + Bergen + 5000 + + NO + + + + Ola Nordmann + + + + + 2013-05-01 + + 707057500022939815 + + Strandgt. 14 + Bergen + 5000 + + NO + + + + + + 31 + 2013-05-25 + 0003434323213231 + + 51400567890 + + + + Ved for sen betaling blit 8,5 % rente lagt til + + + 223.28 + + 893.10 + 223.28 + + S + 25 + + VAT + + + + + + 893.10 + 893.10 + 1116.38 + 1116.38 + + + 1 + 2307 + 810.91 + 123 + + 1 + + + Energiledd nett + + ELNE + + + S + 25 + + VAT + + + + + 0.3515 + + + + 2 + 30 + 82.19 + 123 + + 2 + + + Fastledd nett + + FLNE + + + S + 25 + + VAT + + + + + 1000 + 365 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T10-Valuta-EUR.xml b/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T10-Valuta-EUR.xml new file mode 100644 index 0000000000000000000000000000000000000000..d33c28a4d7eb42bf71c75ec2a545cde172bb8261 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T10-Valuta-EUR.xml @@ -0,0 +1,211 @@ + + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0 + urn:www.cenbii.eu:profile:bii05:ver2.0 + 1001776522 + 2013-05-08 + 380 + 2013-05-08 + EUR + + 2013-01-04 + 2013-01-05 + + + 1 + + + + 123456789 + + Leverendøren ASA + + + Postboks 123 + Oslo + 0203 + + NO + + + + 123456789MVA + + VAT + + + + Leverendøren ASA + 123456789 + + Oslo + + NO + + + + + Vår ref. + Hans Hansen + 81509990 + + + + + + + 26987762 + + + Kunden AS + + + Strandgt. 14 + Bergen + 5000 + + NO + + + + 987654321MVA + + VAT + + + + Kunden AS + 987654321 + + Mainplace + + NO + + + + + 3150Kun + Ola Nordmann + 81509990 + support@kunden.no + + + + + 2013-05-01 + + + Strandgt. 14 + Bergen + 5000 + + NO + + + + + + 31 + 2013-05-25 + 0003434323213231 + + 51400567890 + + + + Ved for sen betaling blit 8,5 % rente lagt til + + + 250.00 + + 1000.00 + 250.00 + + S + 25 + + VAT + + + + + + 2000.00 + + 8000.00 + 2000.00 + + S + 25 + + VAT + + + + + + 1000.00 + 1000.00 + 1250.00 + 1250.00 + + + 1 + 1 + 1000.00 + 123 + + 1 + + + Test product + + TP + + + S + 25 + + VAT + + + + + 1000.00 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T14-Valuta-EUR.xml b/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T14-Valuta-EUR.xml new file mode 100644 index 0000000000000000000000000000000000000000..159f730bcbd1e46e5ae46666b83bc1a12e578ad7 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFInvoice/2.0/T14-Valuta-EUR.xml @@ -0,0 +1,183 @@ + + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns014:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.difi.no:ehf:kreditnota:ver2.0 + urn:www.cenbii.eu:profile:bii05:ver2.0 + 1001776522 + 2013-05-08 + EUR + + 2013-01-04 + 2013-01-05 + + + + 12345 + + + + + 123456789 + + Leverandøren ASA + + + Postboks 123 + Oslo + 0203 + + NO + + + + 123456789MVA + + VAT + + + + Leverandøren ASA + 123456789 + + Oslo + + NO + + + + + Vår ref. + 81509990 + + + + + + + 26987762 + + + Kunden AS + + + Strandgt. 14 + Bergen + 5000 + + NO + + + + 987654321MVA + + VAT + + + + Kunden AS + 987654321 + + Mainplace + + NO + + + + + 3150Kun + Ola Nordmann + 81509990 + support@kunden.no + + + + + 250.00 + + 1000.00 + 250.00 + + S + 25 + + VAT + + + + + + 2000.00 + + 8000.00 + 2000.00 + + S + 25 + + VAT + + + + + + 1000.00 + 1000.00 + 1250.00 + 1250.00 + + + 1 + 1 + 1000.00 + + Test product + + TP + + + S + 25 + + VAT + + + + + 1000.00 + + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/EHFOrder/1.0/Eksempelfil EHF Ordre.xml b/oxalis-outbound/src/test/resources/EHFOrder/1.0/Eksempelfil EHF Ordre.xml new file mode 100644 index 0000000000000000000000000000000000000000..fa277852add6384053f7d54597dcc0c3cdb23ea2 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFOrder/1.0/Eksempelfil EHF Ordre.xml @@ -0,0 +1,291 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns001:ver2.0:extended:urn:www.peppol.eu:bis:peppol28a:ver1.0:extended:urn:www.difi.no:ehf:ordre:ver1.0 + urn:www.cenbii.eu:profile:bii28:ver2.0 + 34 + 2012-10-01 + 12:30:00 + Information text for the whole order + NOK + Project123 + + 2013-01-31 + + + QuoteID123 + + + RjectedOrderID123 + + + MAFO + + + Doc1 + Timesheet + + + http://www.suppliersite.eu/sheet001.html + + + + + Doc2 + Drawing + + UjBsR09EbGhjZ0dTQUxNQUFBUUNBRU1tQ1p0dU1GUXhEUzhi + + + + 34322 + FrameworkAgreementID123 + + + + 931186755 + + 7080000985134 + + + Helseforetak + + + Sinsenveien 40 + Oppgang B + Oslo + 0501 + + NO + + + + 9311867455MVA + + VAT + + + + Helseforetak AS + 931186755 + + Oslo + + NO + + + + + 3150bdn + Ole Olsen + 23055000 + post@helseforetak.no + + + + + + 938752655 + + 7080000374200 + + + Medical + + + Storgt. 12 + 4. etasje + Oslo + 0585 + + NO + + + + Nils Nilsen + 22150510 + post@medical.no + + + + + + + 12345 + + + Helseavdeling + + + Per Persen + 67915000 + post@helse.no + + + + + + + Solheimsveien 10 + Lørenskog + 1473 + + NO + + + + + 2012-10-10 + 2012-10-20 + + + + 1369 + + + Helseavdeling + + + Ole + 987098709 + ole@helseforetak.no + + + + + FOT + CAD + + STO + + + + true + Transport documents + 100 + + + false + Total order value discount + 100 + + + 1556.25 + + + 6225 + 6225 + 7781.25 + 100 + 100 + 7781.25 + + + Freetext note on line 1 + + 1 + 120 + 6000 + 1500 + false + + + 2010-02-10 + 2010-02-25 + + + + + EmployeeXXX + + + Josef K. + + + + 50 + 1 + + + Needle 4mm + Needle 4mm + + 121212 + + + 12345 + + + Length + 30 mm + + + + + + Freetext note on line 2 + + 2 + 15 + 225 + 56.25 + false + ProjectID123 + + + 2012-10-15 + 2012-10-31 + + + + + EmployeeXXX + + + Josef K. + + + + 15 + 1 + + + Wet tissues for children + Wet tissues + + SItemNo011 + + + 56789 + + + Weight + 100 g + + + + + + diff --git a/oxalis-outbound/src/test/resources/EHFOrder/1.0/Eksempelfil EHF Ordrebekreftelse.xml b/oxalis-outbound/src/test/resources/EHFOrder/1.0/Eksempelfil EHF Ordrebekreftelse.xml new file mode 100644 index 0000000000000000000000000000000000000000..8454fb7a319b7ce82826598ee3b4ea74a64db1dc --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFOrder/1.0/Eksempelfil EHF Ordrebekreftelse.xml @@ -0,0 +1,111 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns076:ver2.0:extended:urn:www.peppol.eu:bis:peppol28a:ver1.0:extended:urn:www.difi.no:ehf:ordrebekreftelse:ver1.0 + urn:www.cenbii.eu:profile:bii28:ver2.0 + 34 + 2012-10-01 + 12:30:00 + 30 + Changes in 2 orderlines + + 1 + + + + 123456789 + + 7080000123456 + + + Medical + + + Nils Nilsen + 22150510 + nils.nilsen@medical.no + + + + + + 931186755 + + 7080000985134 + + + Helseforetak + + + + + + 1 + Change in Quantity + 30 + 20 + + Needle 4mm + + 121212 + + + + + 1 + + + + + 2 + Substitution of article + 30 + + Wet tissues for children + + SItemNo011 + + + + + 2 + + Wet tissues for adults + + SItemNo012 + + + 05704368124358 + + + 675634 + + + + + 2 + + + diff --git a/oxalis-outbound/src/test/resources/EHFOrder/SimpleOrderResponse.xml b/oxalis-outbound/src/test/resources/EHFOrder/SimpleOrderResponse.xml new file mode 100644 index 0000000000000000000000000000000000000000..ec3c9bbc0aca65b424c59401dd44d8c4f095bf7a --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFOrder/SimpleOrderResponse.xml @@ -0,0 +1,116 @@ + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm003:ver1.0:#urn:www.peppol.eu:bis:peppol6a:ver1.0 + urn:www.cenbii.eu:profile:bii06:ver1.0 + TESTING + 2012-10-01 + 12:30:00 + 30 + Changes in 2 orderlines + NOK + + 1 + + + + 999999999 + + 7080000857906 + + + Medical + + + TESTING Nilsen + 22150510 + TESTING@TESTING.no + + + + + + 000000000 + + 7080000874675 + + + TESTING + + + + + + 1 + Change in Quantity + 30 + 20 + + Needle 4mm + + 121212 + + + + + 1 + + + + + 2 + Substitution of article + 30 + + Wet tissues for children + + SItemNo011 + + + + + 2 + + WTESTING + + SItemNo012 + + + 05704368124358 + + + 675634 + + + + + 2 + + + diff --git a/oxalis-outbound/src/test/resources/EHFReminder/1.6/T17-norsk-profilxy.xml b/oxalis-outbound/src/test/resources/EHFReminder/1.6/T17-norsk-profilxy.xml new file mode 100644 index 0000000000000000000000000000000000000000..57c13327207499b9935dfa4311e94b331c23b322 --- /dev/null +++ b/oxalis-outbound/src/test/resources/EHFReminder/1.6/T17-norsk-profilxy.xml @@ -0,0 +1,172 @@ + + + + +> + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm017:ver1.0:#urn:www.cenbii.eu:profile:biixy:ver1.0#urn:www.difi.no:ehf:purring:ver1 + urn:www.cenbii.eu:profile:biixy:ver1.0 + 123456 + 2010-12-03 + 999 + 3 + Henvendelse angående purring rettes til Utstyr salg AS, tlf 22 05 11 34, faks + 22 05 11 35, eller epost post@utstyrsalg.no + + + 9908:123456789 + + Supp123 + + + Utstyr salg AS + + + Vika 123 + Oslogate + 1 + Oslo + 0612 + Vika området + + NO + + + + Utstyr salg AS + 999999999 + + Sørum + Akershus + + NO + + + + + + + + 9908:123456798 + + Cus123 + + + Barnehage AS + + + Lindeberg 501 + Stasjonsveien + 5 + Frogner + 2016 + Akershus + + NO + + + + Barnehage AS + 888888888 + + Frogner + Akershus + + NO + + + + + 3159bbx + 900 00 000 + 222 22 222 + bbx@bbx.com + + + + + + 098740918237 + + + Faktoring AS + + + + 25 + + 100 + 25 + + S + + VAT + + + + + + 160 + 160 + + + 1 + Ny betalingsfrist 23.12.2010 til Konto 70560512345 med KID 75300005 + 100 + 0 + + + 123456 + + + + + + + + 2 + Purregebyr + 60 + 0 + + + 123456 + + + + + + + diff --git a/oxalis-outbound/src/test/resources/Issue250-sample-invoice.xml b/oxalis-outbound/src/test/resources/Issue250-sample-invoice.xml new file mode 100644 index 0000000000000000000000000000000000000000..cc6da04efc67358144ea4135fae4c39bd3ca5697 --- /dev/null +++ b/oxalis-outbound/src/test/resources/Issue250-sample-invoice.xml @@ -0,0 +1,180 @@ + + + + + + 2.0 + XXXXXXX + XXXXXXX + XXXXXXX + XXXXXXX-04-24 + 380 + NOK + + XXXXXXXXXXXXXX + XXXXXXX + + + + + XXXXX + + + sdasdasda + + + sdfsdfasdad + + asadad + asda + + XX + + + + dfreddewdd + + XXX + + + + Olafsen Engros AS + 981588347 + + + XXXXXXX + XXXXXXX + XXXXXXX + + + + + + 9954:111111111 + + XXXXXXX + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + + + XXXXXXX + + XXXXXXX + XXXXXXX + + XXXXXXX + + + + XXXXXXX + + XXXXXXX + + + + XXXXXXX + 222222222 + + + XXXXXXX + XXXXXXXXXXXXXX + + + + + XXXXXXX-04-25 + + XXXXXXXXXXXXXX + + XXXXXXXXXXXXXX + XXXXXXX + XXXXXXX + + XXXXXXX + + + + + + XXXXXXX + XXXXXXX-05-24 + XXXXXXX- + + XXXXXXX + + + + XXXXXXXXXXXXXXXXXXXXXXXXXXXX + + + XXXXXXX.55 + + XXXXXXX.18 + XXXXXXX.55 + + S + XXXXXXX.0 + + XXXXXXX + + + + + + XXXXXXX.XX + XXXXXXX.XX + XXXXXXX.XX + XXXXXXX.XX + + + XX + XX.000 + XXXXXXX.XX + + XXXXXXX + XXXXXXX + XXXXXXX + + + XXXXXXX + + + XXXXXXX + + XXXXXXX + + + S + XXXXXXX.0 + + XXXXXXX + + + + + XXXXXXX + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case1.xml b/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case1.xml new file mode 100644 index 0000000000000000000000000000000000000000..34e81c5f241fc28bd3ad09ed55084aedacfb89c3 --- /dev/null +++ b/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case1.xml @@ -0,0 +1,63 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns071:ver2.0:extended:urn:www.peppol.eu:bis:peppol36a:ver1.0 + urn:www.cenbii.eu:profile:bii36:ver2.0 + 1001589778 + 2013-05-01 + 10:10:10 + This is the first test of Message Level Response + + 981915550 + + 3213213213243 + + + Sender company + + + + 987654321 + + 6793178965432 + + + Receiver company + + + + + AP + Accepted + + + 1001589778 + 380 + + + + diff --git a/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case2.xml b/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case2.xml new file mode 100644 index 0000000000000000000000000000000000000000..a1a0fd6aaf61e36ed0df8202f996353dfb05094a --- /dev/null +++ b/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case2.xml @@ -0,0 +1,76 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns071:ver2.0:extended:urn:www.peppol.eu:bis:peppol36a:ver1.0 + urn:www.cenbii.eu:profile:bii36:ver2.0 + 1001589779 + 2013-05-02 + 12:15:35 + This is the second test of Message Level Response + + 981915550 + + 3213213213243 + + + Sender company + + + + 987654321 + + 6793178965432 + + + Receiver company + + + + + RE + Rejected + + + 1001589779 + 380 + + + + Invoice/cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount + + + RE + Error: [BIIRULE-T10-R012]-Invoice tax exclusive amount MUST equal the sum of lines plus allowances and charges on header level + + BV + + + + + + + diff --git a/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case3.xml b/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case3.xml new file mode 100644 index 0000000000000000000000000000000000000000..35e714bbf0bb8a2ade2c6f34e1e6b482cb2c4b44 --- /dev/null +++ b/oxalis-outbound/src/test/resources/MessageLevelResponse/1.0/Use Case3.xml @@ -0,0 +1,115 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns071:ver2.0:extended:urn:www.peppol.eu:bis:peppol36a:ver1.0 + urn:www.cenbii.eu:profile:bii36:ver2.0 + 1001589780 + 2013-05-03 + 14:35:48 + This is the third test of Message Level Response + + 981915550 + + 3213213213243 + + + Sender company + + + + 987654321 + + 6793178965432 + + + Receiver company + + + + + RE + Rejected + + + 1001589780 + 380 + + + + NA + + + RE + Error: Cvc-complex-type.2.4a:Invalid content was found starting with element 'cac:InvoicePeriod’. + + SV + + + + + + Invoice/cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount + + + RE + Error: [BIIRULE-T10-R012]-Invoice tax exclusive amount MUST equal the sum of lines plus allowances and charges on header level + + BV + + + + + + Invoice/cac:LegalMonetaryTotal/cbc:LineExtensionAmount + + + RE + Error: [BIIRULE-T10-R011]-Invoice total line extension amount MUST equal the sum of the line totals + + BV + + + + + + Invoice/cac:InvoiceLine/cbc:AccountingCost + + + AP + Warning: [NOGOV-T10-R003]-The buyer's accounting code applied to the Invoice Line SHOULD be provided according to EHF. + + BW + + + + + + + + + + diff --git a/oxalis-outbound/src/test/resources/NESUBL/CreditNote.xml b/oxalis-outbound/src/test/resources/NESUBL/CreditNote.xml new file mode 100644 index 0000000000000000000000000000000000000000..36b3e4aea67c5255ae691db682c8ae32154629c8 --- /dev/null +++ b/oxalis-outbound/src/test/resources/NESUBL/CreditNote.xml @@ -0,0 +1,137 @@ + + + + + 2.0 + NESUBL-2.0 + urn:www.nesubl.eu:profiles:profile5:ver2.0 + 112 + 2014-10-21 + 381 + ISK + + + + Supplier + + + 0000000000 + StructuredLax + Street + City + 111 + + IS + + + + 00000 + + VAT + + + + 0000000000 + + + + + + + Customer + + + 1111111111 + StructuredLax + Street + City + 112 + + + 111111 + + VAT + + + + 1111111111 + + + + + 255.000 + + 1000.000 + 255.000 + + S + 25.500 + + VAT + + + + + + 1000.000 + 1000.000 + 1255.000 + 1255.000 + + + 1 + 10.000 + 1000.000 + + 255.000 + + 1000.000 + 255.000 + + S + 25.500 + + VAT + + + + + + Name + + 000000-0000 + + + S + + VAT + + + + + 100.000 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/NESUBL/Invoice.xml b/oxalis-outbound/src/test/resources/NESUBL/Invoice.xml new file mode 100644 index 0000000000000000000000000000000000000000..22bbf40b20ea1d1d580cafc130b7e8f75b478292 --- /dev/null +++ b/oxalis-outbound/src/test/resources/NESUBL/Invoice.xml @@ -0,0 +1,151 @@ + + + + + 2.0 + NESUBL-2.0 + urn:www.nesubl.eu:profiles:profile4:ver2.0 + 111 + 2014-10-21 + 380 + ISK + + + + Supplier + + + 0000000000 + StructuredLax + Street + City + 111 + + IS + + + + 00000 + + VAT + + + + 0000000000 + + + + + + + Customer + + + 1111111111 + StructuredLax + Street + City + 112 + + + 111111 + + VAT + + + + 1111111111 + + + + + 1 + 2014-10-30 + + 11111 + IS:00 + + 0000 + + + + + 14 days + 1255.000 + + + 255.000 + + 1000.000 + 255.000 + + S + 25.500 + + VAT + + + + + + 1000.000 + 1000.000 + 1255.000 + 1255.000 + + + 1 + 10.000 + 1000.000 + + 255.000 + + 1000.000 + 255.000 + + S + 25.500 + + VAT + + + + + + Name + + 000000-0000 + + + S + + VAT + + + + + 100.000 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/OIOXML/OIOXML_PCM_99018008_ValidKnown-Original.xml b/oxalis-outbound/src/test/resources/OIOXML/OIOXML_PCM_99018008_ValidKnown-Original.xml new file mode 100644 index 0000000000000000000000000000000000000000..c8b4cba1c0a839a579d7865fe382979aa1c4eb63 --- /dev/null +++ b/oxalis-outbound/src/test/resources/OIOXML/OIOXML_PCM_99018008_ValidKnown-Original.xml @@ -0,0 +1,161 @@ + + + + + + PCM-04-001 + 2009-01-15 + PCM + DKK + 99018008 + + 014881 + 00007113 + 2009-01-10 + + + 5798009811691 + + + Region X + + + Fakturering + Regisonvejen + 1 + Aalborg + 9000 + + DK + + + + 9000000123 + Peter Petersen + 22334455 + + indkoeb@regionx.dk + Rekvirent + + + + 32433030 + + + Papirhuset + + + Vareafsendelse + Papirstræde + 1 + + Aalborg + 9000 + + DK + + + + 32433030 + + + + 71 + 2009-02-28 + INDBETALINGSKORT + 709056716118001 + 85567595 + + + VAT + + 425.00 + 106.25 + + + VAT + 25 + + 425.00 + 106.25 + + + + + 425.00 + 531.25 + + + 1 + 10.00 + 250.00 + + A4-001 + A4 Print og kopipapir, hvid, 80g + + VAT + VAT + 25 + + + + 25.00 + + + + 2 + 5.00 + 175.00 + + A3-001 + A3 Print og kopipapir, hvid, 80g + + VAT + VAT + 25 + + + + 35.00 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/ehf-bii05-t10-valid-invoice.xml b/oxalis-outbound/src/test/resources/ehf-bii05-t10-valid-invoice.xml new file mode 100644 index 0000000000000000000000000000000000000000..39bc781dc74477b19aa0741d3d4f0eaf456dd984 --- /dev/null +++ b/oxalis-outbound/src/test/resources/ehf-bii05-t10-valid-invoice.xml @@ -0,0 +1,527 @@ + + + + + 2.1 + urn:www.cenbii.eu:transaction:biitrns010:ver2.0:extended:urn:www.peppol.eu:bis:peppol5a:ver2.0:extended:urn:www.difi.no:ehf:faktura:ver2.0 + urn:www.cenbii.eu:profile:bii05:ver2.0 + TOSL108 + 2013-06-30 + 380 + Ordered in our booth at the convention. + 2013-06-30 + NOK + Project cost code 123 + + 2013-06-01 + 2013-06-30 + + + 123 + + + Contract321 + 2 + Framework agreement + + + Doc1 + Timesheet + + + http://www.suppliersite.eu/sheet001.html + + + + + Doc2 + EHF specification + + + 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b2RpbmcvRm9udERlc2NyaXB0b3IgOSAwIFIvRmlyc3RDaGFyIDMyL0xhc3RDaGFyIDIyOS9XaWR0aHMgNzU5NyAwIFI+Pg0KZW5kb2JqDQo5IDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL0FyaWFsL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvQXNjZW50IDkwNS9EZXNjZW50IC0yMTAvQ2FwSGVpZ2h0IDcyOC9BdmdXaWR0aCA0NDEvTWF4V2lkdGggMjY2NS9Gb250V2VpZ2h0IDQwMC9YSGVpZ2h0IDI1MC9MZWFkaW5nIDMzL1N0ZW1WIDQ0L0ZvbnRCQm94WyAtNjY1IC0yMTAgMjAwMCA3MjhdID4+DQplbmRvYmoNCjEwIDAgb2JqDQo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UcnVlVHlwZS9OYW1lL0YzL0Jhc2VGb250L1RpbWVzIzIwTmV3IzIwUm9tYW4sQm9sZC9FbmNvZGluZy9XaW5BbnNpRW5jb2RpbmcvRm9udERlc2NyaXB0b3IgMTEgMCBSL0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxMjIvV2lkdGhzIDc1OTggMCBSPj4NCmVuZG9iag0KMTEgMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvVGltZXMjMjBOZXcjMjBSb21hbixCb2xkL0ZsYWdzIDMyL0l0YWxpY0FuZ2xlIDAvQXNjZW50IDg5MS9EZXNjZW50IC0yMTYvQ2FwSGVpZ2h0IDY3Ny9BdmdXaWR0aCA0MjcvTWF4V2lkdGggMjU1OC9Gb250V2VpZ2h0IDcwMC9YSGVpZ2h0IDI1MC9MZWFkaW5nIDQyL1N0ZW1WIDQyL0ZvbnRCQm94WyAtNTU4IC0yMTYgMjAwMCA2NzddID4+DQplbmRvYmoNCjEyIDAgb2JqDQo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UcnVlVHlwZS9OYW1lL0Y0L0Jhc2VGb250L1RpbWVzIzIwTmV3IzIwUm9tYW4vRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZvbnREZXNjcmlwdG9yIDEzIDAgUi9GaXJzdENoYXIgMzIvTGFzdENoYXIgMjQ4L1dpZHRocyA3NjAyIDAgUj4+DQpl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MFJvbWFuL0VuY29kaW5nL0lkZW50aXR5LUgvRGVzY2VuZGFudEZvbnRzIDE5IDAgUi9Ub1VuaWNvZGUgNzU5OSAwIFI+Pg0KZW5kb2JqDQoxOSAwIG9iag0KWyAyMCAwIFJdIA0KZW5kb2JqDQoyMCAwIG9iag0KPDwvQmFzZUZvbnQvVGltZXMjMjBOZXcjMjBSb21hbi9TdWJ0eXBlL0NJREZvbnRUeXBlMi9UeXBlL0ZvbnQvQ0lEVG9HSURNYXAvSWRlbnRpdHkvRFcgMTAwMC9DSURTeXN0ZW1JbmZvIDIxIDAgUi9Gb250RGVzY3JpcHRvciAyMiAwIFIvVyA3NjAxIDAgUj4+DQplbmRvYmoNCjIxIDAgb2JqDQo8PC9PcmRlcmluZyhJZGVudGl0eSkgL1JlZ2lzdHJ5KEFkb2JlKSAvU3VwcGxlbWVudCAwPj4NCmVuZG9iag0KMjIgMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvVGltZXMjMjBOZXcjMjBSb21hbi9GbGFncyAzMi9JdGFsaWNBbmdsZSAwL0FzY2VudCA4OTEvRGVzY2VudCAtMjE2L0NhcEhlaWdodCA2OTMvQXZnV2lkdGggNDAxL01heFdpZHRoIDI1NjgvRm9udFdlaWdodCA0MDAvWEhlaWdodCAyNTAvTGVhZGluZyA0Mi9TdGVtViA0MC9Gb250QkJveFsgLTU2OCAtMjE2IDIwMDAgNjkzXSAvRm9udEZpbGUyIDc2MDAgMCBSPj4NCmVuZG9iag0KMjMgMCBvYmoNCjw8L1R5cGUvUGFnZS9QYXJlbnQgMiAwIFIvUmVzb3VyY2VzPDwvRXh0R1N0YXRlPDwvR1M1IDUgMCBSPj4vRm9udDw8L0YxIDYgMCBSL0YyIDggMCBSL0Y0IDEyIDAgUi9GMyAxMCAwIFI+Pi9Qcm9jU2V0Wy9QREYvVGV4dC9JbWFnZUIvSW1hZ2VDL0ltYWdlSV0gPj4vTWVkaWFCb3hbIDAgMCA3OTIgNjEyXSAvQ29udGVudHMgMjQgMCBSL0dyb3VwPDwvVHlwZS9Hcm91cC9TL1RyYW5zcGFyZW5jeS9DUy9EZXZpY2VSR0I+Pi9UYWJzL1MvU3RydWN0UGFyZW50cyAzPj4NCmVuZG9iag0KMjQgMCBv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b7S+phsAJyQd0e3abTy3cOvi9ulHrwy/eNqvrDPf8HrK4veV4tk6empFr/NClufVm084ovvBqa70aPFoDXu1aDOeon/S1u2R6hU67ltvy17Pr+pTx0+WA02jziY7NZ0G4N8AXWNilQ0KZW5kc3RyZWFtDQplbmRvYmoNCjc2MDEgMCBvYmoNClsgMFsgNzc4XSAgM1sgMjUwXSAgNVsgNDA4IDUwMF0gIDhbIDgzM10gIDExWyAzMzMgMzMzIDUwMCA1NjQgMjUwIDMzMyAyNTAgMjc4IDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCAyNzhdICAzMlsgNTY0XSAgMzVbIDkyMSA3MjIgNjY3IDY2NyA3MjIgNjExIDU1NiA3MjIgNzIyIDMzMyAzODkgNzIyIDYxMSA4ODkgNzIyIDcyMiA1NTYgNzIyIDY2NyA1NTYgNjExIDcyMiA3MjJdICA2MVsgNjExXSAgNjhbIDQ0NCA1MDAgNDQ0IDUwMCA0NDQgMzMzIDUwMCA1MDAgMjc4IDI3OCA1MDAgMjc4IDc3OCA1MDAgNTAwIDUwMCA1MDAgMzMzIDM4OSAyNzggNTAwIDUwMCA3MjIgNTAwIDUwMCA0NDRdICA5OVsgNzIyXSAgMTEwWyA0NDRdICAxNDVbIDcyMl0gIDE2MFsgNjY3IDUwMF0gIDE2OVsgNTAwIDUwMF0gIDE3OVsgNDQ0IDQ0NF0gXSANCmVuZG9iag0KNzYwMiAwIG9iag0KWyAyNTAgMCA0MDggNTAwIDAgODMzIDAgMCAzMzMgMzMzIDUwMCA1NjQgMjUwIDMzMyAyNTAgMjc4IDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCAyNzggMCAwIDU2NCAwIDAgOTIxIDcyMiA2NjcgNjY3IDcyMiA2MTEgNTU2IDcyMiA3MjIgMzMzIDM4OSA3MjIgNjExIDg4OSA3MjIgNzIyIDU1NiA3MjIgNjY3IDU1NiA2MTEgNzIyIDcyMiAwIDAgMCA2MTEgMCAwIDAgMCAwIDAgNDQ0IDUwMCA0NDQgNTAwIDQ0NCAzMzMgNTAwIDUwMCAyNzggMjc4IDUwMCAyNzggNzc4IDUwMCA1MDAgNTAwIDUwMCAzMzMgMzg5IDI3OCA1MDAg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ODMwOSAwMDAwMCBuDQowMDAwMDQ4NTk0IDAwMDAwIG4NCjAwMDAwNjU3MzkgMDAwMDAgbg0KMDAwMDA2NjAzNCAwMDAwMCBuDQowMDAwMDgyMjY1IDAwMDAwIG4NCjAwMDAwODI1NjAgMDAwMDAgbg0KMDAwMDEwMDg0NSAwMDAwMCBuDQowMDAwMTAxMTQwIDAwMDAwIG4NCjAwMDAxMjAxNDEgMDAwMDAgbg0KMDAwMDEyMDQwMiAwMDAwMCBuDQowMDAwMTM4MDY3IDAwMDAwIG4NCjAwMDAxMzgzNjQgMDAwMDAgbg0KMDAwMDE1MzI1NiAwMDAwMCBuDQowMDAwMTUzMzEwIDAwMDAwIG4NCjAwMDAxNTM1OTUgMDAwMDAgbg0KMDAwMDE2ODE2NSAwMDAwMCBuDQowMDAwMTY4NDUxIDAwMDAwIG4NCjAwMDAxODMxNzMgMDAwMDAgbg0KMDAwMDE4MzQzNSAwMDAwMCBuDQowMDAwMjAxOTMxIDAwMDAwIG4NCjAwMDAyMDIxOTMgMDAwMDAgbg0KMDAwMDIxOTQ5OCAwMDAwMCBuDQowMDAwMjE5NzcwIDAwMDAwIG4NCjAwMDAyMzAxNjEgMDAwMDAgbg0KMDAwMDIzMDMzMiAwMDAwMCBuDQowMDAwMjMwNTc0IDAwMDAwIG4NCjAwMDAwMDAwNTAgNjU1MzUgZg0KMDAwMDAwMDA1MSA2NTUzNSBmDQowMDAwMDAwMDUyIDY1NTM1IGYNCjAwMDAwMDAwNTMgNjU1MzUgZg0KMDAwMDAwMDA1NCA2NTUzNSBmDQowMDAwMDAwMDU1IDY1NTM1IGYNCjAwMDAwMDAwNTYgNjU1MzUgZg0KMDAwMDAwMDA1NyA2NTUzNSBmDQowMDAwMDAwMDU4IDY1NTM1IGYNCjAwMDAwMDAwNTkgNjU1MzUgZg0KMDAwMDAwMDA2MCA2NTUzNSBmDQowMDAwMDAwMDYxIDY1NTM1IGYNCjAwMDAwMDAwNjIgNjU1MzUgZg0KMDAwMDAwMDA2MyA2NTUzNSBmDQowMDAwMDAwMDY0IDY1NTM1IGYNCjAwMDAwMDAwNjUgNjU1MzUgZg0KMDAwMDAwMDA2NiA2NTUzNSBmDQowMDAwMDAwMDY3IDY1NTM1IGYNCjAwMDAwMDAwNjggNjU1MzUgZg0KMDAwMDAwMDA2OSA2NTUzNSBmDQowMDAwMDAwMDcwIDY1NTM1IGYNCjAwMDAwMDAwNzEgNjU1MzUgZg0KMDAwMDAwMDA3MiA2NTUzNSBmDQowMDAwMDAwMDczIDY1NTM1IGYNCjAwMDAwMDAwNzQgNjU1MzUgZg0KMDAwMDAwMDA3NSA2NTUzNSBmDQowMDAwMDAwMDc2IDY1NTM1IGYNCjAwMDAwMDAwNzcgNjU1MzUgZg0KMDAwMDAwMDA3OCA2NTUzNSBmDQowMDAwMDAwMDc5IDY1NTM1IGYNCjAwMDAwMDAwODAgNjU1MzUgZg0KMDAwMDAwMDA4MSA2NTUzNSBmDQowMDAwMDAwMDgyIDY1NTM1IGYNCjAwMDAwMDAwODMgNjU1MzUgZg0KMDAwMDAwMDA4NCA2NTUzNSBmDQowMDAwMDAwMDg1IDY1NTM1IGYNCjAwMDAwMDAwODYgNjU1MzUgZg0KMDAwMDAwMDA4NyA2NTUzNSBmDQowMDAwMDAwMDg4IDY1NTM1IGYNCjAwMDAwMDAwODkgNjU1MzUgZg0KMDAwMDAwMDA5MCA2NTUzNSBmDQowMDAwMDAwMDkxIDY1NTM1IGYNCjAwMDAwMDAwOTIgNjU1MzUgZg0KMDAwMDAwMDA5MyA2NTUzNSBmDQowMDAwMDAwMDk0IDY1NTM1IGYNCjAwMDAwMDAwOTUgNjU1MzUgZg0KMDAwMDAwMDA5NiA2NTUzNSBmDQowMDAwMDAwMDk3IDY1NTM1IGYNCjAwMDAwMDAwOTggNjU1MzUgZg0KMDAwMDAwMDA5OSA2NTUzNSBmDQowMDAwMDAwMTAwIDY1NTM1IGYNCjAwMDAwMDAxMDEgNjU1MzUgZg0KMDAwMDAwMDEwMiA2NTUzNSBmDQowMDAwMDAwMTAzIDY1NTM1IGYNCjAwMDAwMDAxMDQgNjU1MzUgZg0KMDAwMDAwMDEwNSA2NTUzNSBmDQowMDAwMDAwMTA2IDY1NTM1IGYNCjAwMDAwMDAxMDcgNjU1MzUgZg0KMDAwMDAwMDEwOCA2NTUzNSBmDQowMDAwMDAwMTA5IDY1NTM1IGYNCjAwMDAwMDAxMTAgNjU1MzUgZg0KMDAwMDAwMDExMSA2NTUzNSBmDQowMDAwMDAwMTEyIDY1NTM1IGYNCjAwMDAwMDAxMTMgNjU1MzUgZg0KMDAwMDAwMDExNCA2NTUzNSBmDQowMDAwMDAwMTE1IDY1NTM1IGYNCjAwMDAwMDAxMTYgNjU1MzUgZg0KMDAwMDAwMDExNyA2NTUzNSBmDQowMDAwMDAwMTE4IDY1NTM1IGYNCjAwMDAwMDAxMTkgNjU1MzUgZg0KMDAwMDAwMDEyMCA2NTUzNSBmDQowMDAwMDAwMTIxIDY1NTM1IGYNCjAwMDAwMDAxMjIgNjU1MzUgZg0KMDAwMDAwMDEyMyA2NTUzNSBmDQowMDAwMDAwMTI0IDY1NTM1IGYNCjAwMDAwMDAxMjUgNjU1MzUgZg0KMDAwMDAwMDEyNiA2NTUzNSBmDQowMDAwMDAwMTI3IDY1NTM1IGYNCjAwMDAwMDAxMjggNjU1MzUgZg0KMDAwMDAwMDEyOSA2NTUzNSBmDQowMDAwMDAwMTMwIDY1NTM1IGYNCjAwMDAwMDAxMzEgNjU1MzUgZg0KMDAwMDAwMDEzMiA2NTUzNSBmDQowMDAwMDAwMTMzIDY1NTM1IGYNCjAwMDAwMDAxMzQgNjU1MzUgZg0KMDAwMDAwMDEzNSA2NTUzNSBmDQowMDAwMDAwMTM2IDY1NTM1IGYNCjAwMDAwMDAxMzcgNjU1MzUgZg0KMDAwMDAwMDEzOCA2NTUzNSBmDQowMDAwMDAwMTM5IDY1NTM1IGYNCjAwMDAwMDAxNDAgNjU1MzUgZg0KMDAwMDAwMDE0MSA2NTUzNSBmDQowMDAwMDAwMTQyIDY1NTM1IGYNCjAwMDAwMDAxNDMgNjU1MzUgZg0KMDAwMDAwMDE0NCA2NTUzNSBmDQowMDAwMDAwMTQ1IDY1NTM1IGYNCjAwMDAwMDAxNDYgNjU1MzUgZg0KMDAwMDAwMDE0NyA2NTUzNSBmDQowMDAwMDAwMTQ4IDY1NTM1IGYNCjAwMDAwMDAxNDkgNjU1MzUgZg0KMDAwMDAwMDE1MCA2NTUzNSBmDQowMDAwMDAwMTUxIDY1NTM1IGYNCjAwMDAwMDAxNTIgNjU1MzUgZg0KMDAwMDAwMDE1MyA2NTUzNSBmDQowMDAwMDAwMTU0IDY1NTM1IGYNCjAwMDAwMDAxNTUgNjU1MzUgZg0KMDAwMDAwMDE1NiA2NTUzNSBmDQowMDAwMDAwMTU3IDY1NTM1IGYNCjAwMDAwMDAxNTggNjU1MzUgZg0KMDAwMDAwMDE1OSA2NTUzNSBmDQowMDAwMDAwMTYwIDY1NTM1IGYNCjAwMDAwMDAxNjEgNjU1MzUgZg0KMDAwMDAwMDE2MiA2NTUzNSBmDQowMDAwMDAwMTYzIDY1NTM1IGYNCjAwMDAwMDAxNjQgNjU1MzUgZg0KMDAwMDAwMDE2NSA2NTUzNSBmDQowMDAwMDAwMTY2IDY1NTM1IGYNCjAwMDAwMDAxNjcgNjU1MzUgZg0KMDAwMDAwMDE2OCA2NTUzNSBmDQowMDAwMDAwMTY5IDY1NTM1IGYNCjAwMDAwMDAxNzAgNjU1MzUgZg0KMDAwMDAwMDE3MSA2NTUzNSBmDQowMDAwMDAwMTcyIDY1NTM1IGYNCjAwMDAwMDAxNzMgNjU1MzUgZg0KMDAwMDAwMDE3NCA2NTUzNSBmDQowMDAwMDAwMTc1IDY1NTM1IGYNCjAwMDAwMDAxNzYgNjU1MzUgZg0KMDAwMDAwMDE3NyA2NTUzNSBmDQowMDAwMDAwMTc4IDY1NTM1IGYNCjAwMDAwMDAxNzkgNjU1MzUgZg0KMDAwMDAwMDE4MCA2NTUzNSBmDQowMDAwMDAwMTgxIDY1NTM1IGYNCjAwMDAwMDAxODIgNjU1MzUgZg0KMDAwMDAwMDE4MyA2NTUzNSBmDQowMDAwMDAwMTg0IDY1NTM1IGYNCjAwMDAwMDAxODUgNjU1MzUgZg0KMDAwMDAwMDE4NiA2NTUzNSBmDQowMDAwMDAwMTg3IDY1NTM1IGYNCjAwMDAwMDAxODggNjU1MzUgZg0KMDAwMDAwMDE4OSA2NTUzNSBmDQowMDAwMDAwMTkwIDY1NTM1IGYNCjAwMDAwMDAxOTEgNjU1MzUgZg0KMDAwMDAwMDE5MiA2NTUzNSBmDQowMDAwMDAwMTkzIDY1NTM1IGYNCjAwMDAwMDAxOTQgNjU1MzUgZg0KMDAwMDAwMDE5NSA2NTUzNSBmDQowMDAwMDAwMTk2IDY1NTM1IGYNCjAwMDAwMDAxOTcgNjU1MzUgZg0KMDAwMDAwMDE5OCA2NTUzNSBmDQowMDAwMDAwMTk5IDY1NTM1IGYNCjAwMDAwMDAyMDAgNjU1MzUgZg0KMDAwMDAwMDIwMSA2NTUzNSBmDQowMDAwMDAwMjAyIDY1NTM1IGYNCjAwMDAwMDAyMDMgNjU1MzUgZg0KMDAwMDAwMDIwNCA2NTUzNSBmDQowMDAwMDAwMjA1IDY1NTM1IGYNCjAwMDAwMDAyMDYgNjU1MzUgZg0KMDAwMDAwMDIwNyA2NTUzNSBmDQowMDAwMDAwMjA4IDY1NTM1IGYNCjAwMDAwMDAyMDkgNjU1MzUgZg0KMDAwMDAwMDIxMCA2NTUzNSBmDQowMDAwMDAwMjExIDY1NTM1IGYNCjAwMDAwMDAyMTIgNjU1MzUgZg0KMDAwMDAwMDIxMyA2NTUzNSBmDQowMDAwMDAwMjE0IDY1NTM1IGYNCjAwMDAwMDAyMTUgNjU1MzUgZg0KMDAwMDAwMDIxNiA2NTUzNSBmDQowMDAwMDAwMjE3IDY1NTM1IGYNCjAwMDAwMDAyMTggNjU1MzUgZg0KMDAwMDAwMDIxOSA2NTUzNSBmDQowMDAwMDAwMjIwIDY1NTM1IGYNCjAwMDAwMDAyMjEgNjU1MzUgZg0KMDAwMDAwMDIyMiA2NTUzNSBmDQowMDAwMDAwMjIzIDY1NTM1IGYNCjAwMDAwMDAyMjQgNjU1MzUgZg0KMDAwMDAwMDIyNSA2NTUzNSBmDQowMDAwMDAwMjI2IDY1NTM1IGYNCjAwMDAwMDAyMjcgNjU1MzUgZg0KMDAwMDAwMDIyOCA2NTUzNSBmDQowMDAwMDAwMjI5IDY1NTM1IGYNCjAwMDAwMDAyMzAgNjU1MzUgZg0KMDAwMDAwMDIzMSA2NTUzNSBmDQowMDAwMDAwMjMyIDY1NTM1IGYNCjAwMDAwMDAyMzMgNjU1MzUgZg0KMDAwMDAwMDIzNCA2NTUzNSBmDQowMDAwMDAwMjM1IDY1NTM1IGYNCjAwMDAwMDAyMzYgNjU1MzUgZg0KMDAwMDAwMDIzNyA2NTUzNSBmDQowMDAwMDAwMjM4IDY1NTM1IGYNCjAwMDAwMDAyMzkgNjU1MzUgZg0KMDAwMDAwMDI0MCA2NTUzNSBmDQowMDAwMDAwMjQxIDY1NTM1IGYNCjAwMDAwMDAyNDIgNjU1MzUgZg0KMDAwMDAwMDI0MyA2NTUzNSBmDQowMDAwMDAwMjQ0IDY1NTM1IGYNCjAwMDAwMDAyNDUgNjU1MzUgZg0KMDAwMDAwMDI0NiA2NTUzNSBmDQowMDAwMDAwMjQ3IDY1NTM1IGYNCjAwMDAwMDAyNDggNjU1MzUgZg0KMDAwMDAwMDI0OSA2NTUzNSBmDQowMDAwMDAwMjUwIDY1NTM1IGYNCjAwMDAwMDAyNTEgNjU1MzUgZg0KMDAwMDAwMDI1MiA2NTUzNSBmDQowMDAwMDAwMjUzIDY1NTM1IGYNCjAwMDAwMDAyNTQgNjU1MzUgZg0KMDAwMDAwMDI1NSA2NTUzNSBmDQowMDAwMDAwMjU2IDY1NTM1IGYNCjAwMDAwMDAyNTcgNjU1MzUgZg0KMDAwMDAwMDI1OCA2NTUzNSBmDQowMDAwMDAwMjU5IDY1NTM1IGYNCjAwMDAwMDAyNjAgNjU1MzUgZg0KMDAwMDAwMDI2MSA2NTUzNSBmDQowMDAwMDAwMjYyIDY1NTM1IGYNCjAwMDAwMDAyNjMgNjU1MzUgZg0KMDAwMDAwMDI2NCA2NTUzNSBmDQowMDAwMDAwMjY1IDY1NTM1IGYNCjAwMDAwMDAyNjYgNjU1MzUgZg0KMDAwMDAwMDI2NyA2NTUzNSBmDQowMDAwMDAwMjY4IDY1NTM1IGYNCjAwMDAwMDAyNjkgNjU1MzUgZg0KMDAwMDAwMDI3MCA2NTUzNSBmDQowMDAwMDAwMjcxIDY1NTM1IGYNCjAwMDAwMDAyNzIgNjU1MzUgZg0KMDAwMDAwMDI3MyA2NTUzNSBmDQowMDAwMDAwMjc0IDY1NTM1IGYNCjAwMDAwMDAyNzUgNjU1MzUgZg0KMDAwMDAwMDI3NiA2NTUzNSBmDQowMDAwMDAwMjc3IDY1NTM1IGYNCjAwMDAwMDAyNzggNjU1MzUgZg0KMDAwMDAwMDI3OSA2NTUzNSBmDQowMDAwMDAwMjgwIDY1NTM1IGYNCjAwMDAwMDAyODEgNjU1MzUgZg0KMDAwMDAwMDI4MiA2NTUzNSBmDQowMDAwMDAwMjgzIDY1NTM1IGYNCjAwMDAwMDAyODQgNjU1MzUgZg0KMDAwMDAwMDI4NSA2NTUzNSBmDQowMDAwMDAwMjg2IDY1NTM1IGYNCjAwMDAwMDAyODcgNjU1MzUgZg0KMDAwMDAwMDI4OCA2NTUzNSBmDQowMDAwMDAwMjg5IDY1NTM1IGYNCjAwMDAwMDAyOTAgNjU1MzUgZg0KMDAwMDAwMDI5MSA2NTUzNSBmDQowMDAwMDAwMjkyIDY1NTM1IGYNCjAwMDAwMDAyOTMgNjU1MzUgZg0KMDAwMDAwMDI5NCA2NTUzNSBmDQowMDAwMDAwMjk1IDY1NTM1IGYNCjAwMDAwMDAyOTYgNjU1MzUgZg0KMDAwMDAwMDI5NyA2NTUzNSBmDQowMDAwMDAwMjk4IDY1NTM1IGYNCjAwMDAwMDAyOTkgNjU1MzUgZg0KMDAwMDAwMDMwMCA2NTUzNSBmDQowMDAwMDAwMzAxIDY1NTM1IGYNCjAwMDAwMDAzMDIgNjU1MzUgZg0KMDAwMDAwMDMwMyA2NTUzNSBmDQowMDAwMDAwMzA0IDY1NTM1IGYNCjAwMDAwMDAzMDUgNjU1MzUgZg0KMDAwMDAwMDMwNiA2NTUzNSBmDQowMDAwMDAwMzA3IDY1NTM1IGYNCjAwMDAwMDAzMDggNjU1MzUgZg0KMDAwMDAwMDMwOSA2NTUzNSBmDQowMDAwMDAwMzEwIDY1NTM1IGYNCjAwMDAwMDAzMTEgNjU1MzUgZg0KMDAwMDAwMDMxMiA2NTUzNSBmDQowMDAwMDAwMzEzIDY1NTM1IGYNCjAwMDAwMDAzMTQgNjU1MzUgZg0KMDAwMDAwMDMxNSA2NTUzNSBmDQowMDAwMDAwMzE2IDY1NTM1IGYNCjAwMDAwMDAzMTcgNjU1MzUgZg0KMDAwMDAwMDMxOCA2NTUzNSBmDQowMDAwMDAwMzE5IDY1NTM1IGYNCjAwMDAwMDAzMjAgNjU1MzUgZg0KMDAwMDAwMDMyMSA2NTUzNSBmDQowMDAwMDAwMzIyIDY1NTM1IGYNCjAwMDAwMDAzMjMgNjU1MzUgZg0KMDAwMDAwMDMyNCA2NTUzNSBmDQowMDAwMDAwMzI1IDY1NTM1IGYNCjAwMDAwMDAzMjYgNjU1MzUgZg0KMDAwMDAwMDMyNyA2NTUzNSBmDQowMDAwMDAwMzI4IDY1NTM1IGYNCjAwMDAwMDAzMjkgNjU1MzUgZg0KMDAwMDAwMDMzMCA2NTUzNSBmDQowMDAwMDAwMzMxIDY1NTM1IGYNCjAwMDAwMDAzMzIgNjU1MzUgZg0KMDAwMDAwMDMzMyA2NTUzNSBmDQowMDAwMDAwMzM0IDY1NTM1IGYNCjAwMDAwMDAzMzUgNjU1MzUgZg0KMDAwMDAwMDMzNiA2NTUzNSBmDQowMDAwMDAwMzM3IDY1NTM1IGYNCjAwMDAwMDAzMzggNjU1MzUgZg0KMDAwMDAwMDMzOSA2NTUzNSBmDQowMDAwMDAwMzQwIDY1NTM1IGYNCjAwMDAwMDAzNDEgNjU1MzUgZg0KMDAwMDAwMDM0MiA2NTUzNSBmDQowMDAwMDAwMzQzIDY1NTM1IGYNCjAwMDAwMDAzNDQgNjU1MzUgZg0KMDAwMDAwMDM0NSA2NTUzNSBmDQowMDAwMDAwMzQ2IDY1NTM1IGYNCjAwMDAwMDAzNDcgNjU1MzUgZg0KMDAwMDAwMDM0OCA2NTUzNSBmDQowMDAwMDAwMzQ5IDY1NTM1IGYNCjAwMDAwMDAzNTAgNjU1MzUgZg0KMDAwMDAwMDM1MSA2NTUzNSBmDQowMDAwMDAwMzUyIDY1NTM1IGYNCjAwMDAwMDAzNTMgNjU1MzUgZg0KMDAwMDAwMDM1NCA2NTUzNSBmDQowMDAwMDAwMzU1IDY1NTM1IGYNCjAwMDAwMDAzNTYgNjU1MzUgZg0KMDAwMDAwMDM1NyA2NTUzNSBmDQowMDAwMDAwMzU4IDY1NTM1IGYNCjAwMDAwMDAzNTkgNjU1MzUgZg0KMDAwMDAwMDM2MCA2NTUzNSBmDQowMDAwMDAwMzYxIDY1NTM1IGYNCjAwMDAwMDAzNjIgNjU1MzUgZg0KMDAwMDAwMDM2MyA2NTUzNSBmDQowMDAwMDAwMzY0IDY1NTM1IGYNCjAwMDAwMDAzNjUgNjU1MzUgZg0KMDAwMDAwMDM2NiA2NTUzNSBmDQowMDAwMDAwMzY3IDY1NTM1IGYNCjAwMDAwMDAzNjggNjU1MzUgZg0KMDAwMDAwMDM2OSA2NTUzNSBmDQowMDAwMDAwMzcwIDY1NTM1IGYNCjAwMDAwMDAzNzEgNjU1MzUgZg0KMDAwMDAwMDM3MiA2NTUzNSBmDQowMDAwMDAwMzczIDY1NTM1IGYNCjAwMDAwMDAzNzQgNjU1MzUgZg0KMDAwMDAwMDM3NSA2NTUzNSBmDQowMDAwMDAwMzc2IDY1NTM1IGYNCjAwMDAwMDAzNzcgNjU1MzUgZg0KMDAwMDAwMDM3OCA2NTUzNSBmDQowMDAwMDAwMzc5IDY1NTM1IGYNCjAwMDAwMDAzODAgNjU1MzUgZg0KMDAwMDAwMDM4MSA2NTUzNSBmDQowMDAwMDAwMzgyIDY1NTM1IGYNCjAwMDAwMDAzODMgNjU1MzUgZg0KMDAwMDAwMDM4NCA2NTUzNSBmDQowMDAwMDAwMzg1IDY1NTM1IGYNCjAwMDAwMDAzODYgNjU1MzUgZg0KMDAwMDAwMDM4NyA2NTUzNSBmDQowMDAwMDAwMzg4IDY1NTM1IGYNCjAwMDAwMDAzODkgNjU1MzUgZg0KMDAwMDAwMDM5MCA2NTUzNSBmDQowMDAwMDAwMzkxIDY1NTM1IGYNCjAwMDAwMDAzOTIgNjU1MzUgZg0KMDAwMDAwMDM5MyA2NTUzNSBmDQowMDAwMDAwMzk0IDY1NTM1IGYNCjAwMDAwMDAzOTUgNjU1MzUgZg0KMDAwMDAwMDM5NiA2NTUzNSBmDQowMDAwMDAwMzk3IDY1NTM1IGYNCjAwMDAwMDAzOTggNjU1MzUgZg0KMDAwMDAwMDM5OSA2NTUzNSBmDQowMDAwMDAwNDAwIDY1NTM1IGYNCjAwMDAwMDA0MDEgNjU1MzUgZg0KMDAwMDAwMDQwMiA2NTUzNSBmDQowMDAwMDAwNDAzIDY1NTM1IGYNCjAwMDAwMDA0MDQgNjU1MzUgZg0KMDAwMDAwMDQwNSA2NTUzNSBmDQowMDAwMDAwNDA2IDY1NTM1IGYNCjAwMDAwMDA0MDcgNjU1MzUgZg0KMDAwMDAwMDQwOCA2NTUzNSBmDQowMDAwMDAwNDA5IDY1NTM1IGYNCjAwMDAwMDA0MTAgNjU1MzUgZg0KMDAwMDAwMDQxMSA2NTUzNSBmDQowMDAwMDAwNDEyIDY1NTM1IGYNCjAwMDAwMDA0MTMgNjU1MzUgZg0KMDAwMDAwMDQxNCA2NTUzNSBmDQowMDAwMDAwNDE1IDY1NTM1IGYNCjAwMDAwMDA0MTYgNjU1MzUgZg0KMDAwMDAwMDQxNyA2NTUzNSBmDQowMDAwMDAwNDE4IDY1NTM1IGYNCjAwMDAwMDA0MTkgNjU1MzUgZg0KMDAwMDAwMDQyMCA2NTUzNSBmDQowMDAwMDAwNDIxIDY1NTM1IGYNCjAwMDAwMDA0MjIgNjU1MzUgZg0KMDAwMDAwMDQyMyA2NTUzNSBmDQowMDAwMDAwNDI0IDY1NTM1IGYNCjAwMDAwMDA0MjUgNjU1MzUgZg0KMDAwMDAwMDQyNiA2NTUzNSBmDQowMDAwMDAwNDI3IDY1NTM1IGYNCjAwMDAwMDA0MjggNjU1MzUgZg0KMDAwMDAwMDQyOSA2NTUzNSBmDQowMDAwMDAwNDMwIDY1NTM1IGYNCjAwMDAwMDA0MzEgNjU1MzUgZg0KMDAwMDAwMDQzMiA2NTUzNSBmDQowMDAwMDAwNDMzIDY1NTM1IGYNCjAwMDAwMDA0MzQgNjU1MzUgZg0KMDAwMDAwMDQzNSA2NTUzNSBmDQowMDAwMDAwNDM2IDY1NTM1IGYNCjAwMDAwMDA0MzcgNjU1MzUgZg0KMDAwMDAwMDQzOCA2NTUzNSBmDQowMDAwMDAwNDM5IDY1NTM1IGYNCjAwMDAwMDA0NDAgNjU1MzUgZg0KMDAwMDAwMDQ0MSA2NTUzNSBmDQowMDAwMDAwNDQyIDY1NTM1IGYNCjAwMDAwMDA0NDMgNjU1MzUgZg0KMDAwMDAwMDQ0NCA2NTUzNSBmDQowMDAwMDAwNDQ1IDY1NTM1IGYNCjAwMDAwMDA0NDYgNjU1MzUgZg0KMDAwMDAwMDQ0NyA2NTUzNSBmDQowMDAwMDAwNDQ4IDY1NTM1IGYNCjAwMDAwMDA0NDkgNjU1MzUgZg0KMDAwMDAwMDQ1MCA2NTUzNSBmDQowMDAwMDAwNDUxIDY1NTM1IGYNCjAwMDAwMDA0NTIgNjU1MzUgZg0KMDAwMDAwMDQ1MyA2NTUzNSBmDQowMDAwMDAwNDU0IDY1NTM1IGYNCjAwMDAwMDA0NTUgNjU1MzUgZg0KMDAwMDAwMDQ1NiA2NTUzNSBmDQowMDAwMDAwNDU3IDY1NTM1IGYNCjAwMDAwMDA0NTggNjU1MzUgZg0KMDAwMDAwMDQ1OSA2NTUzNSBmDQowMDAwMDAwNDYwIDY1NTM1IGYNCjAwMDAwMDA0NjEgNjU1MzUgZg0KMDAwMDAwMDQ2MiA2NTUzNSBmDQowMDAwMDAwNDYzIDY1NTM1IGYNCjAwMDAwMDA0NjQgNjU1MzUgZg0KMDAwMDAwMDQ2NSA2NTUzNSBmDQowMDAwMDAwNDY2IDY1NTM1IGYNCjAwMDAwMDA0NjcgNjU1MzUgZg0KMDAwMDAwMDQ2OCA2NTUzNSBmDQowMDAwMDAwNDY5IDY1NTM1IGYNCjAwMDAwMDA0NzAgNjU1MzUgZg0KMDAwMDAwMDQ3MSA2NTUzNSBmDQowMDAwMDAwNDcyIDY1NTM1IGYNCjAwMDAwMDA0NzMgNjU1MzUgZg0KMDAwMDAwMDQ3NCA2NTUzNSBmDQowMDAwMDAwNDc1IDY1NTM1IGYNCjAwMDAwMDA0NzYgNjU1MzUgZg0KMDAwMDAwMDQ3NyA2NTUzNSBmDQowMDAwMDAwNDc4IDY1NTM1IGYNCjAwMDAwMDA0NzkgNjU1MzUgZg0KMDAwMDAwMDQ4MCA2NTUzNSBmDQowMDAwMDAwNDgxIDY1NTM1IGYNCjAwMDAwMDA0ODIgNjU1MzUgZg0KMDAwMDAwMDQ4MyA2NTUzNSBmDQowMDAwMDAwNDg0IDY1NTM1IGYNCjAwMDAwMDA0ODUgNjU1MzUgZg0KMDAwMDAwMDQ4NiA2NTUzNSBmDQowMDAwMDAwNDg3IDY1NTM1IGYNCjAwMDAwMDA0ODggNjU1MzUgZg0KMDAwMDAwMDQ4OSA2NTUzNSBmDQowMDAwMDAwNDkwIDY1NTM1IGYNCjAwMDAwMDA0OTEgNjU1MzUgZg0KMDAwMDAwMDQ5MiA2NTUzNSBmDQowMDAwMDAwNDkzIDY1NTM1IGYNCjAwMDAwMDA0OTQgNjU1MzUgZg0KMDAwMDAwMDQ5NSA2NTUzNSBmDQowMDAwMDAwNDk2IDY1NTM1IGYNCjAwMDAwMDA0OTcgNjU1MzUgZg0KMDAwMDAwMDQ5OCA2NTUzNSBmDQowMDAwMDAwNDk5IDY1NTM1IGYNCjAwMDAwMDA1MDAgNjU1MzUgZg0KMDAwMDAwMDUwMSA2NTUzNSBmDQowMDAwMDAwNTAyIDY1NTM1IGYNCjAwMDAwMDA1MDMgNjU1MzUgZg0KMDAwMDAwMDUwNCA2NTUzNSBmDQowMDAwMDAwNTA1IDY1NTM1IGYNCjAwMDAwMDA1MDYgNjU1MzUgZg0KMDAwMDAwMDUwNyA2NTUzNSBmDQowMDAwMDAwNTA4IDY1NTM1IGYNCjAwMDAwMDA1MDkgNjU1MzUgZg0KMDAwMDAwMDUxMCA2NTUzNSBmDQowMDAwMDAwNTExIDY1NTM1IGYNCjAwMDAwMDA1MTIgNjU1MzUgZg0KMDAwMDAwMDUxMyA2NTUzNSBmDQowMDAwMDAwNTE0IDY1NTM1IGYNCjAwMDAwMDA1MTUgNjU1MzUgZg0KMDAwMDAwMDUxNiA2NTUzNSBmDQowMDAwMDAwNTE3IDY1NTM1IGYNCjAwMDAwMDA1MTggNjU1MzUgZg0KMDAwMDAwMDUxOSA2NTUzNSBmDQowMDAwMDAwNTIwIDY1NTM1IGYNCjAwMDAwMDA1MjEgNjU1MzUgZg0KMDAwMDAwMDUyMiA2NTUzNSBmDQowMDAwMDAwNTIzIDY1NTM1IGYNCjAwMDAwMDA1MjQgNjU1MzUgZg0KMDAwMDAwMDUyNSA2NTUzNSBmDQowMDAwMDAwNTI2IDY1NTM1IGYNCjAwMDAwMDA1MjcgNjU1MzUgZg0KMDAwMDAwMDUyOCA2NTUzNSBmDQowMDAwMDAwNTI5IDY1NTM1IGYNCjAwMDAwMDA1MzAgNjU1MzUgZg0KMDAwMDAwMDUzMSA2NTUzNSBmDQowMDAwMDAwNTMyIDY1NTM1IGYNCjAwMDAwMDA1MzMgNjU1MzUgZg0KMDAwMDAwMDUzNCA2NTUzNSBmDQowMDAwMDAwNTM1IDY1NTM1IGYNCjAwMDAwMDA1MzYgNjU1MzUgZg0KMDAwMDAwMDUzNyA2NTUzNSBmDQowMDAwMDAwNTM4IDY1NTM1IGYNCjAwMDAwMDA1MzkgNjU1MzUgZg0KMDAwMDAwMDU0MCA2NTUzNSBmDQowMDAwMDAwNTQxIDY1NTM1IGYNCjAwMDAwMDA1NDIgNjU1MzUgZg0KMDAwMDAwMDU0MyA2NTUzNSBmDQowMDAwMDAwNTQ0IDY1NTM1IGYNCjAwMDAwMDA1NDUgNjU1MzUgZg0KMDAwMDAwMDU0NiA2NTUzNSBmDQowMDAwMDAwNTQ3IDY1NTM1IGYNCjAwMDAwMDA1NDggNjU1MzUgZg0KMDAwMDAwMDU0OSA2NTUzNSBmDQowMDAwMDAwNTUwIDY1NTM1IGYNCjAwMDAwMDA1NTEgNjU1MzUgZg0KMDAwMDAwMDU1MiA2NTUzNSBmDQowMDAwMDAwNTUzIDY1NTM1IGYNCjAwMDAwMDA1NTQgNjU1MzUgZg0KMDAwMDAwMDU1NSA2NTUzNSBmDQowMDAwMDAwNTU2IDY1NTM1IGYNCjAwMDAwMDA1NTcgNjU1MzUgZg0KMDAwMDAwMDU1OCA2NTUzNSBmDQowMDAwMDAwNTU5IDY1NTM1IGYNCjAwMDAwMDA1NjAgNjU1MzUgZg0KMDAwMDAwMDU2MSA2NTUzNSBmDQowMDAwMDAwNTYyIDY1NTM1IGYNCjAwMDAwMDA1NjMgNjU1MzUgZg0KMDAwMDAwMDU2NCA2NTUzNSBmDQowMDAwMDAwNTY1IDY1NTM1IGYNCjAwMDAwMDA1NjYgNjU1MzUgZg0KMDAwMDAwMDU2NyA2NTUzNSBmDQowMDAwMDAwNTY4IDY1NTM1IGYNCjAwMDAwMDA1NjkgNjU1MzUgZg0KMDAwMDAwMDU3MCA2NTUzNSBmDQowMDAwMDAwNTcxIDY1NTM1IGYNCjAwMDAwMDA1NzIgNjU1MzUgZg0KMDAwMDAwMDU3MyA2NTUzNSBmDQowMDAwMDAwNTc0IDY1NTM1IGYNCjAwMDAwMDA1NzUgNjU1MzUgZg0KMDAwMDAwMDU3NiA2NTUzNSBmDQowMDAwMDAwNTc3IDY1NTM1IGYNCjAwMDAwMDA1NzggNjU1MzUgZg0KMDAwMDAwMDU3OSA2NTUzNSBmDQowMDAwMDAwNTgwIDY1NTM1IGYNCjAwMDAwMDA1ODEgNjU1MzUgZg0KMDAwMDAwMDU4MiA2NTUzNSBmDQowMDAwMDAwNTgzIDY1NTM1IGYNCjAwMDAwMDA1ODQgNjU1MzUgZg0KMDAwMDAwMDU4NSA2NTUzNSBmDQowMDAwMDAwNTg2IDY1NTM1IGYNCjAwMDAwMDA1ODcgNjU1MzUgZg0KMDAwMDAwMDU4OCA2NTUzNSBmDQowMDAwMDAwNTg5IDY1NTM1IGYNCjAwMDAwMDA1OTAgNjU1MzUgZg0KMDAwMDAwMDU5MSA2NTUzNSBmDQowMDAwMDAwNTkyIDY1NTM1IGYNCjAwMDAwMDA1OTMgNjU1MzUgZg0KMDAwMDAwMDU5NCA2NTUzNSBmDQowMDAwMDAwNTk1IDY1NTM1IGYNCjAwMDAwMDA1OTYgNjU1MzUgZg0KMDAwMDAwMDU5NyA2NTUzNSBmDQowMDAwMDAwNTk4IDY1NTM1IGYNCjAwMDAwMDA1OTkgNjU1MzUgZg0KMDAwMDAwMDYwMCA2NTUzNSBmDQowMDAwMDAwNjAxIDY1NTM1IGYNCjAwMDAwMDA2MDIgNjU1MzUgZg0KMDAwMDAwMDYwMyA2NTUzNSBmDQowMDAwMDAwNjA0IDY1NTM1IGYNCjAwMDAwMDA2MDUgNjU1MzUgZg0KMDAwMDAwMDYwNiA2NTUzNSBmDQowMDAwMDAwNjA3IDY1NTM1IGYNCjAwMDAwMDA2MDggNjU1MzUgZg0KMDAwMDAwMDYwOSA2NTUzNSBmDQowMDAwMDAwNjEwIDY1NTM1IGYNCjAwMDAwMDA2MTEgNjU1MzUgZg0KMDAwMDAwMDYxMiA2NTUzNSBmDQowMDAwMDAwNjEzIDY1NTM1IGYNCjAwMDAwMDA2MTQgNjU1MzUgZg0KMDAwMDAwMDYxNSA2NTUzNSBmDQowMDAwMDAwNjE2IDY1NTM1IGYNCjAwMDAwMDA2MTcgNjU1MzUgZg0KMDAwMDAwMDYxOCA2NTUzNSBmDQowMDAwMDAwNjE5IDY1NTM1IGYNCjAwMDAwMDA2MjAgNjU1MzUgZg0KMDAwMDAwMDYyMSA2NTUzNSBmDQowMDAwMDAwNjIyIDY1NTM1IGYNCjAwMDAwMDA2MjMgNjU1MzUgZg0KMDAwMDAwMDYyNCA2NTUzNSBmDQowMDAwMDAwNjI1IDY1NTM1IGYNCjAwMDAwMDA2MjYgNjU1MzUgZg0KMDAwMDAwMDYyNyA2NTUzNSBmDQowMDAwMDAwNjI4IDY1NTM1IGYNCjAwMDAwMDA2MjkgNjU1MzUgZg0KMDAwMDAwMDYzMCA2NTUzNSBmDQowMDAwMDAwNjMxIDY1NTM1IGYNCjAwMDAwMDA2MzIgNjU1MzUgZg0KMDAwMDAwMDYzMyA2NTUzNSBmDQowMDAwMDAwNjM0IDY1NTM1IGYNCjAwMDAwMDA2MzUgNjU1MzUgZg0KMDAwMDAwMDYzNiA2NTUzNSBmDQowMDAwMDAwNjM3IDY1NTM1IGYNCjAwMDAwMDA2MzggNjU1MzUgZg0KMDAwMDAwMDYzOSA2NTUzNSBmDQowMDAwMDAwNjQwIDY1NTM1IGYNCjAwMDAwMDA2NDEgNjU1MzUgZg0KMDAwMDAwMDY0MiA2NTUzNSBmDQowMDAwMDAwNjQzIDY1NTM1IGYNCjAwMDAwMDA2NDQgNjU1MzUgZg0KMDAwMDAwMDY0NSA2NTUzNSBmDQowMDAwMDAwNjQ2IDY1NTM1IGYNCjAwMDAwMDA2NDcgNjU1MzUgZg0KMDAwMDAwMDY0OCA2NTUzNSBmDQowMDAwMDAwNjQ5IDY1NTM1IGYNCjAwMDAwMDA2NTAgNjU1MzUgZg0KMDAwMDAwMDY1MSA2NTUzNSBmDQowMDAwMDAwNjUyIDY1NTM1IGYNCjAwMDAwMDA2NTMgNjU1MzUgZg0KMDAwMDAwMDY1NCA2NTUzNSBmDQowMDAwMDAwNjU1IDY1NTM1IGYNCjAwMDAwMDA2NTYgNjU1MzUgZg0KMDAwMDAwMDY1NyA2NTUzNSBmDQowMDAwMDAwNjU4IDY1NTM1IGYNCjAwMDAwMDA2NTkgNjU1MzUgZg0KMDAwMDAwMDY2MCA2NTUzNSBmDQowMDAwMDAwNjYxIDY1NTM1IGYNCjAwMDAwMDA2NjIgNjU1MzUgZg0KMDAwMDAwMDY2MyA2NTUzNSBmDQowMDAwMDAwNjY0IDY1NTM1IGYNCjAwMDAwMDA2NjUgNjU1MzUgZg0KMDAwMDAwMDY2NiA2NTUzNSBmDQowMDAwMDAwNjY3IDY1NTM1IGYNCjAwMDAwMDA2NjggNjU1MzUgZg0KMDAwMDAwMDY2OSA2NTUzNSBmDQowMDAwMDAwNjcwIDY1NTM1IGYNCjAwMDAwMDA2NzEgNjU1MzUgZg0KMDAwMDAwMDY3MiA2NTUzNSBmDQowMDAwMDAwNjczIDY1NTM1IGYNCjAwMDAwMDA2NzQgNjU1MzUgZg0KMDAwMDAwMDY3NSA2NTUzNSBmDQowMDAwMDAwNjc2IDY1NTM1IGYNCjAwMDAwMDA2NzcgNjU1MzUgZg0KMDAwMDAwMDY3OCA2NTUzNSBmDQowMDAwMDAwNjc5IDY1NTM1IGYNCjAwMDAwMDA2ODAgNjU1MzUgZg0KMDAwMDAwMDY4MSA2NTUzNSBmDQowMDAwMDAwNjgyIDY1NTM1IGYNCjAwMDAwMDA2ODMgNjU1MzUgZg0KMDAwMDAwMDY4NCA2NTUzNSBmDQowMDAwMDAwNjg1IDY1NTM1IGYNCjAwMDAwMDA2ODYgNjU1MzUgZg0KMDAwMDAwMDY4NyA2NTUzNSBmDQowMDAwMDAwNjg4IDY1NTM1IGYNCjAwMDAwMDA2ODkgNjU1MzUgZg0KMDAwMDAwMDY5MCA2NTUzNSBmDQowMDAwMDAwNjkxIDY1NTM1IGYNCjAwMDAwMDA2OTIgNjU1MzUgZg0KMDAwMDAwMDY5MyA2NTUzNSBmDQowMDAwMDAwNjk0IDY1NTM1IGYNCjAwMDAwMDA2OTUgNjU1MzUgZg0KMDAwMDAwMDY5NiA2NTUzNSBmDQowMDAwMDAwNjk3IDY1NTM1IGYNCjAwMDAwMDA2OTggNjU1MzUgZg0KMDAwMDAwMDY5OSA2NTUzNSBmDQowMDAwMDAwNzAwIDY1NTM1IGYNCjAwMDAwMDA3MDEgNjU1MzUgZg0KMDAwMDAwMDcwMiA2NTUzNSBmDQowMDAwMDAwNzAzIDY1NTM1IGYNCjAwMDAwMDA3MDQgNjU1MzUgZg0KMDAwMDAwMDcwNSA2NTUzNSBmDQowMDAwMDAwNzA2IDY1NTM1IGYNCjAwMDAwMDA3MDcgNjU1MzUgZg0KMDAwMDAwMDcwOCA2NTUzNSBmDQowMDAwMDAwNzA5IDY1NTM1IGYNCjAwMDAwMDA3MTAgNjU1MzUgZg0KMDAwMDAwMDcxMSA2NTUzNSBmDQowMDAwMDAwNzEyIDY1NTM1IGYNCjAwMDAwMDA3MTMgNjU1MzUgZg0KMDAwMDAwMDcxNCA2NTUzNSBmDQowMDAwMDAwNzE1IDY1NTM1IGYNCjAwMDAwMDA3MTYgNjU1MzUgZg0KMDAwMDAwMDcxNyA2NTUzNSBmDQowMDAwMDAwNzE4IDY1NTM1IGYNCjAwMDAwMDA3MTkgNjU1MzUgZg0KMDAwMDAwMDcyMCA2NTUzNSBmDQowMDAwMDAwNzIxIDY1NTM1IGYNCjAwMDAwMDA3MjIgNjU1MzUgZg0KMDAwMDAwMDcyMyA2NTUzNSBmDQowMDAwMDAwNzI0IDY1NTM1IGYNCjAwMDAwMDA3MjUgNjU1MzUgZg0KMDAwMDAwMDcyNiA2NTUzNSBmDQowMDAwMDAwNzI3IDY1NTM1IGYNCjAwMDAwMDA3MjggNjU1MzUgZg0KMDAwMDAwMDcyOSA2NTUzNSBmDQowMDAwMDAwNzMwIDY1NTM1IGYNCjAwMDAwMDA3MzEgNjU1MzUgZg0KMDAwMDAwMDczMiA2NTUzNSBmDQowMDAwMDAwNzMzIDY1NTM1IGYNCjAwMDAwMDA3MzQgNjU1MzUgZg0KMDAwMDAwMDczNSA2NTUzNSBmDQowMDAwMDAwNzM2IDY1NTM1IGYNCjAwMDAwMDA3MzcgNjU1MzUgZg0KMDAwMDAwMDczOCA2NTUzNSBmDQowMDAwMDAwNzM5IDY1NTM1IGYNCjAwMDAwMDA3NDAgNjU1MzUgZg0KMDAwMDAwMDc0MSA2NTUzNSBmDQowMDAwMDAwNzQyIDY1NTM1IGYNCjAwMDAwMDA3NDMgNjU1MzUgZg0KMDAwMDAwMDc0NCA2NTUzNSBmDQowMDAwMDAwNzQ1IDY1NTM1IGYNCjAwMDAwMDA3NDYgNjU1MzUgZg0KMDAwMDAwMDc0NyA2NTUzNSBmDQowMDAwMDAwNzQ4IDY1NTM1IGYNCjAwMDAwMDA3NDkgNjU1MzUgZg0KMDAwMDAwMDc1MCA2NTUzNSBmDQowMDAwMDAwNzUxIDY1NTM1IGYNCjAwMDAwMDA3NTIgNjU1MzUgZg0KMDAwMDAwMDc1MyA2NTUzNSBmDQowMDAwMDAwNzU0IDY1NTM1IGYNCjAwMDAwMDA3NTUgNjU1MzUgZg0KMDAwMDAwMDc1NiA2NTUzNSBmDQowMDAwMDAwNzU3IDY1NTM1IGYNCjAwMDAwMDA3NTggNjU1MzUgZg0KMDAwMDAwMDc1OSA2NTUzNSBmDQowMDAwMDAwNzYwIDY1NTM1IGYNCjAwMDAwMDA3NjEgNjU1MzUgZg0KMDAwMDAwMDc2MiA2NTUzNSBmDQowMDAwMDAwNzYzIDY1NTM1IGYNCjAwMDAwMDA3NjQgNjU1MzUgZg0KMDAwMDAwMDc2NSA2NTUzNSBmDQowMDAwMDAwNzY2IDY1NTM1IGYNCjAwMDAwMDA3NjcgNjU1MzUgZg0KMDAwMDAwMDc2OCA2NTUzNSBmDQowMDAwMDAwNzY5IDY1NTM1IGYNCjAwMDAwMDA3NzAgNjU1MzUgZg0KMDAwMDAwMDc3MSA2NTUzNSBmDQowMDAwMDAwNzcyIDY1NTM1IGYNCjAwMDAwMDA3NzMgNjU1MzUgZg0KMDAwMDAwMDc3NCA2NTUzNSBmDQowMDAwMDAwNzc1IDY1NTM1IGYNCjAwMDAwMDA3NzYgNjU1MzUgZg0KMDAwMDAwMDc3NyA2NTUzNSBmDQowMDAwMDAwNzc4IDY1NTM1IGYNCjAwMDAwMDA3NzkgNjU1MzUgZg0KMDAwMDAwMDc4MCA2NTUzNSBmDQowMDAwMDAwNzgxIDY1NTM1IGYNCjAwMDAwMDA3ODIgNjU1MzUgZg0KMDAwMDAwMDc4MyA2NTUzNSBmDQowMDAwMDAwNzg0IDY1NTM1IGYNCjAwMDAwMDA3ODUgNjU1MzUgZg0KMDAwMDAwMDc4NiA2NTUzNSBmDQowMDAwMDAwNzg3IDY1NTM1IGYNCjAwMDAwMDA3ODggNjU1MzUgZg0KMDAwMDAwMDc4OSA2NTUzNSBmDQowMDAwMDAwNzkwIDY1NTM1IGYNCjAwMDAwMDA3OTEgNjU1MzUgZg0KMDAwMDAwMDc5MiA2NTUzNSBmDQowMDAwMDAwNzkzIDY1NTM1IGYNCjAwMDAwMDA3OTQgNjU1MzUgZg0KMDAwMDAwMDc5NSA2NTUzNSBmDQowMDAwMDAwNzk2IDY1NTM1IGYNCjAwMDAwMDA3OTcgNjU1MzUgZg0KMDAwMDAwMDc5OCA2NTUzNSBmDQowMDAwMDAwNzk5IDY1NTM1IGYNCjAwMDAwMDA4MDAgNjU1MzUgZg0KMDAwMDAwMDgwMSA2NTUzNSBmDQowMDAwMDAwODAyIDY1NTM1IGYNCjAwMDAwMDA4MDMgNjU1MzUgZg0KMDAwMDAwMDgwNCA2NTUzNSBmDQowMDAwMDAwODA1IDY1NTM1IGYNCjAwMDAwMDA4MDYgNjU1MzUgZg0KMDAwMDAwMDgwNyA2NTUzNSBmDQowMDAwMDAwODA4IDY1NTM1IGYNCjAwMDAwMDA4MDkgNjU1MzUgZg0KMDAwMDAwMDgxMCA2NTUzNSBmDQowMDAwMDAwODExIDY1NTM1IGYNCjAwMDAwMDA4MTIgNjU1MzUgZg0KMDAwMDAwMDgxMyA2NTUzNSBmDQowMDAwMDAwODE0IDY1NTM1IGYNCjAwMDAwMDA4MTUgNjU1MzUgZg0KMDAwMDAwMDgxNiA2NTUzNSBmDQowMDAwMDAwODE3IDY1NTM1IGYNCjAwMDAwMDA4MTggNjU1MzUgZg0KMDAwMDAwMDgxOSA2NTUzNSBmDQowMDAwMDAwODIwIDY1NTM1IGYNCjAwMDAwMDA4MjEgNjU1MzUgZg0KMDAwMDAwMDgyMiA2NTUzNSBmDQowMDAwMDAwODIzIDY1NTM1IGYNCjAwMDAwMDA4MjQgNjU1MzUgZg0KMDAwMDAwMDgyNSA2NTUzNSBmDQowMDAwMDAwODI2IDY1NTM1IGYNCjAwMDAwMDA4MjcgNjU1MzUgZg0KMDAwMDAwMDgyOCA2NTUzNSBmDQowMDAwMDAwODI5IDY1NTM1IGYNCjAwMDAwMDA4MzAgNjU1MzUgZg0KMDAwMDAwMDgzMSA2NTUzNSBmDQowMDAwMDAwODMyIDY1NTM1IGYNCjAwMDAwMDA4MzMgNjU1MzUgZg0KMDAwMDAwMDgzNCA2NTUzNSBmDQowMDAwMDAwODM1IDY1NTM1IGYNCjAwMDAwMDA4MzYgNjU1MzUgZg0KMDAwMDAwMDgzNyA2NTUzNSBmDQowMDAwMDAwODM4IDY1NTM1IGYNCjAwMDAwMDA4MzkgNjU1MzUgZg0KMDAwMDAwMDg0MCA2NTUzNSBmDQowMDAwMDAwODQxIDY1NTM1IGYNCjAwMDAwMDA4NDIgNjU1MzUgZg0KMDAwMDAwMDg0MyA2NTUzNSBmDQowMDAwMDAwODQ0IDY1NTM1IGYNCjAwMDAwMDA4NDUgNjU1MzUgZg0KMDAwMDAwMDg0NiA2NTUzNSBmDQowMDAwMDAwODQ3IDY1NTM1IGYNCjAwMDAwMDA4NDggNjU1MzUgZg0KMDAwMDAwMDg0OSA2NTUzNSBmDQowMDAwMDAwODUwIDY1NTM1IGYNCjAwMDAwMDA4NTEgNjU1MzUgZg0KMDAwMDAwMDg1MiA2NTUzNSBmDQowMDAwMDAwODUzIDY1NTM1IGYNCjAwMDAwMDA4NTQgNjU1MzUgZg0KMDAwMDAwMDg1NSA2NTUzNSBmDQowMDAwMDAwODU2IDY1NTM1IGYNCjAwMDAwMDA4NTcgNjU1MzUgZg0KMDAwMDAwMDg1OCA2NTUzNSBmDQowMDAwMDAwODU5IDY1NTM1IGYNCjAwMDAwMDA4NjAgNjU1MzUgZg0KMDAwMDAwMDg2MSA2NTUzNSBmDQowMDAwMDAwODYyIDY1NTM1IGYNCjAwMDAwMDA4NjMgNjU1MzUgZg0KMDAwMDAwMDg2NCA2NTUzNSBmDQowMDAwMDAwODY1IDY1NTM1IGYNCjAwMDAwMDA4NjYgNjU1MzUgZg0KMDAwMDAwMDg2NyA2NTUzNSBmDQowMDAwMDAwODY4IDY1NTM1IGYNCjAwMDAwMDA4NjkgNjU1MzUgZg0KMDAwMDAwMDg3MCA2NTUzNSBmDQowMDAwMDAwODcxIDY1NTM1IGYNCjAwMDAwMDA4NzIgNjU1MzUgZg0KMDAwMDAwMDg3MyA2NTUzNSBmDQowMDAwMDAwODc0IDY1NTM1IGYNCjAwMDAwMDA4NzUgNjU1MzUgZg0KMDAwMDAwMDg3NiA2NTUzNSBmDQowMDAwMDAwODc3IDY1NTM1IGYNCjAwMDAwMDA4NzggNjU1MzUgZg0KMDAwMDAwMDg3OSA2NTUzNSBmDQowMDAwMDAwODgwIDY1NTM1IGYNCjAwMDAwMDA4ODEgNjU1MzUgZg0KMDAwMDAwMDg4MiA2NTUzNSBmDQowMDAwMDAwODgzIDY1NTM1IGYNCjAwMDAwMDA4ODQgNjU1MzUgZg0KMDAwMDAwMDg4NSA2NTUzNSBmDQowMDAwMDAwODg2IDY1NTM1IGYNCjAwMDAwMDA4ODcgNjU1MzUgZg0KMDAwMDAwMDg4OCA2NTUzNSBmDQowMDAwMDAwODg5IDY1NTM1IGYNCjAwMDAwMDA4OTAgNjU1MzUgZg0KMDAwMDAwMDg5MSA2NTUzNSBmDQowMDAwMDAwODkyIDY1NTM1IGYNCjAwMDAwMDA4OTMgNjU1MzUgZg0KMDAwMDAwMDg5NCA2NTUzNSBmDQowMDAwMDAwODk1IDY1NTM1IGYNCjAwMDAwMDA4OTYgNjU1MzUgZg0KMDAwMDAwMDg5NyA2NTUzNSBmDQowMDAwMDAwODk4IDY1NTM1IGYNCjAwMDAwMDA4OTkgNjU1MzUgZg0KMDAwMDAwMDkwMCA2NTUzNSBmDQowMDAwMDAwOTAxIDY1NTM1IGYNCjAwMDAwMDA5MDIgNjU1MzUgZg0KMDAwMDAwMDkwMyA2NTUzNSBmDQowMDAwMDAwOTA0IDY1NTM1IGYNCjAwMDAwMDA5MDUgNjU1MzUgZg0KMDAwMDAwMDkwNiA2NTUzNSBmDQowMDAwMDAwOTA3IDY1NTM1IGYNCjAwMDAwMDA5MDggNjU1MzUgZg0KMDAwMDAwMDkwOSA2NTUzNSBmDQowMDAwMDAwOTEwIDY1NTM1IGYNCjAwMDAwMDA5MTEgNjU1MzUgZg0KMDAwMDAwMDkxMiA2NTUzNSBmDQowMDAwMDAwOTEzIDY1NTM1IGYNCjAwMDAwMDA5MTQgNjU1MzUgZg0KMDAwMDAwMDkxNSA2NTUzNSBmDQowMDAwMDAwOTE2IDY1NTM1IGYNCjAwMDAwMDA5MTcgNjU1MzUgZg0KMDAwMDAwMDkxOCA2NTUzNSBmDQowMDAwMDAwOTE5IDY1NTM1IGYNCjAwMDAwMDA5MjAgNjU1MzUgZg0KMDAwMDAwMDkyMSA2NTUzNSBmDQowMDAwMDAwOTIyIDY1NTM1IGYNCjAwMDAwMDA5MjMgNjU1MzUgZg0KMDAwMDAwMDkyNCA2NTUzNSBmDQowMDAwMDAwOTI1IDY1NTM1IGYNCjAwMDAwMDA5MjYgNjU1MzUgZg0KMDAwMDAwMDkyNyA2NTUzNSBmDQowMDAwMDAwOTI4IDY1NTM1IGYNCjAwMDAwMDA5MjkgNjU1MzUgZg0KMDAwMDAwMDkzMCA2NTUzNSBmDQowMDAwMDAwOTMxIDY1NTM1IGYNCjAwMDAwMDA5MzIgNjU1MzUgZg0KMDAwMDAwMDkzMyA2NTUzNSBmDQowMDAwMDAwOTM0IDY1NTM1IGYNCjAwMDAwMDA5MzUgNjU1MzUgZg0KMDAwMDAwMDkzNiA2NTUzNSBmDQowMDAwMDAwOTM3IDY1NTM1IGYNCjAwMDAwMDA5MzggNjU1MzUgZg0KMDAwMDAwMDkzOSA2NTUzNSBmDQowMDAwMDAwOTQwIDY1NTM1IGYNCjAwMDAwMDA5NDEgNjU1MzUgZg0KMDAwMDAwMDk0MiA2NTUzNSBmDQowMDAwMDAwOTQzIDY1NTM1IGYNCjAwMDAwMDA5NDQgNjU1MzUgZg0KMDAwMDAwMDk0NSA2NTUzNSBmDQowMDAwMDAwOTQ2IDY1NTM1IGYNCjAwMDAwMDA5NDcgNjU1MzUgZg0KMDAwMDAwMDk0OCA2NTUzNSBmDQowMDAwMDAwOTQ5IDY1NTM1IGYNCjAwMDAwMDA5NTAgNjU1MzUgZg0KMDAwMDAwMDk1MSA2NTUzNSBmDQowMDAwMDAwOTUyIDY1NTM1IGYNCjAwMDAwMDA5NTMgNjU1MzUgZg0KMDAwMDAwMDk1NCA2NTUzNSBmDQowMDAwMDAwOTU1IDY1NTM1IGYNCjAwMDAwMDA5NTYgNjU1MzUgZg0KMDAwMDAwMDk1NyA2NTUzNSBmDQowMDAwMDAwOTU4IDY1NTM1IGYNCjAwMDAwMDA5NTkgNjU1MzUgZg0KMDAwMDAwMDk2MCA2NTUzNSBmDQowMDAwMDAwOTYxIDY1NTM1IGYNCjAwMDAwMDA5NjIgNjU1MzUgZg0KMDAwMDAwMDk2MyA2NTUzNSBmDQowMDAwMDAwOTY0IDY1NTM1IGYNCjAwMDAwMDA5NjUgNjU1MzUgZg0KMDAwMDAwMDk2NiA2NTUzNSBmDQowMDAwMDAwOTY3IDY1NTM1IGYNCjAwMDAwMDA5NjggNjU1MzUgZg0KMDAwMDAwMDk2OSA2NTUzNSBmDQowMDAwMDAwOTcwIDY1NTM1IGYNCjAwMDAwMDA5NzEgNjU1MzUgZg0KMDAwMDAwMDk3MiA2NTUzNSBmDQowMDAwMDAwOTczIDY1NTM1IGYNCjAwMDAwMDA5NzQgNjU1MzUgZg0KMDAwMDAwMDk3NSA2NTUzNSBmDQowMDAwMDAwOTc2IDY1NTM1IGYNCjAwMDAwMDA5NzcgNjU1MzUgZg0KMDAwMDAwMDk3OCA2NTUzNSBmDQowMDAwMDAwOTc5IDY1NTM1IGYNCjAwMDAwMDA5ODAgNjU1MzUgZg0KMDAwMDAwMDk4MSA2NTUzNSBmDQowMDAwMDAwOTgyIDY1NTM1IGYNCjAwMDAwMDA5ODMgNjU1MzUgZg0KMDAwMDAwMDk4NCA2NTUzNSBmDQowMDAwMDAwOTg1IDY1NTM1IGYNCjAwMDAwMDA5ODYgNjU1MzUgZg0KMDAwMDAwMDk4NyA2NTUzNSBmDQowMDAwMDAwOTg4IDY1NTM1IGYNCjAwMDAwMDA5ODkgNjU1MzUgZg0KMDAwMDAwMDk5MCA2NTUzNSBmDQowMDAwMDAwOTkxIDY1NTM1IGYNCjAwMDAwMDA5OTIgNjU1MzUgZg0KMDAwMDAwMDk5MyA2NTUzNSBmDQowMDAwMDAwOTk0IDY1NTM1IGYNCjAwMDAwMDA5OTUgNjU1MzUgZg0KMDAwMDAwMDk5NiA2NTUzNSBmDQowMDAwMDAwOTk3IDY1NTM1IGYNCjAwMDAwMDA5OTggNjU1MzUgZg0KMDAwMDAwMDk5OSA2NTUzNSBmDQowMDAwMDAxMDAwIDY1NTM1IGYNCjAwMDAwMDEwMDEgNjU1MzUgZg0KMDAwMDAwMTAwMiA2NTUzNSBmDQowMDAwMDAxMDAzIDY1NTM1IGYNCjAwMDAwMDEwMDQgNjU1MzUgZg0KMDAwMDAwMTAwNSA2NTUzNSBmDQowMDAwMDAxMDA2IDY1NTM1IGYNCjAwMDAwMDEwMDcgNjU1MzUgZg0KMDAwMDAwMTAwOCA2NTUzNSBmDQowMDAwMDAxMDA5IDY1NTM1IGYNCjAwMDAwMDEwMTAgNjU1MzUgZg0KMDAwMDAwMTAxMSA2NTUzNSBmDQowMDAwMDAxMDEyIDY1NTM1IGYNCjAwMDAwMDEwMTMgNjU1MzUgZg0KMDAwMDAwMTAxNCA2NTUzNSBmDQowMDAwMDAxMDE1IDY1NTM1IGYNCjAwMDAwMDEwMTYgNjU1MzUgZg0KMDAwMDAwMTAxNyA2NTUzNSBmDQowMDAwMDAxMDE4IDY1NTM1IGYNCjAwMDAwMDEwMTkgNjU1MzUgZg0KMDAwMDAwMTAyMCA2NTUzNSBmDQowMDAwMDAxMDIxIDY1NTM1IGYNCjAwMDAwMDEwMjIgNjU1MzUgZg0KMDAwMDAwMTAyMyA2NTUzNSBmDQowMDAwMDAxMDI0IDY1NTM1IGYNCjAwMDAwMDEwMjUgNjU1MzUgZg0KMDAwMDAwMTAyNiA2NTUzNSBmDQowMDAwMDAxMDI3IDY1NTM1IGYNCjAwMDAwMDEwMjggNjU1MzUgZg0KMDAwMDAwMTAyOSA2NTUzNSBmDQowMDAwMDAxMDMwIDY1NTM1IGYNCjAwMDAwMDEwMzEgNjU1MzUgZg0KMDAwMDAwMTAzMiA2NTUzNSBmDQowMDAwMDAxMDMzIDY1NTM1IGYNCjAwMDAwMDEwMzQgNjU1MzUgZg0KMDAwMDAwMTAzNSA2NTUzNSBmDQowMDAwMDAxMDM2IDY1NTM1IGYNCjAwMDAwMDEwMzcgNjU1MzUgZg0KMDAwMDAwMTAzOCA2NTUzNSBmDQowMDAwMDAxMDM5IDY1NTM1IGYNCjAwMDAwMDEwNDAgNjU1MzUgZg0KMDAwMDAwMTA0MSA2NTUzNSBmDQowMDAwMDAxMDQyIDY1NTM1IGYNCjAwMDAwMDEwNDMgNjU1MzUgZg0KMDAwMDAwMTA0NCA2NTUzNSBmDQowMDAwMDAxMDQ1IDY1NTM1IGYNCjAwMDAwMDEwNDYgNjU1MzUgZg0KMDAwMDAwMTA0NyA2NTUzNSBmDQowMDAwMDAxMDQ4IDY1NTM1IGYNCjAwMDAwMDEwNDkgNjU1MzUgZg0KMDAwMDAwMTA1MCA2NTUzNSBmDQowMDAwMDAxMDUxIDY1NTM1IGYNCjAwMDAwMDEwNTIgNjU1MzUgZg0KMDAwMDAwMTA1MyA2NTUzNSBmDQowMDAwMDAxMDU0IDY1NTM1IGYNCjAwMDAwMDEwNTUgNjU1MzUgZg0KMDAwMDAwMTA1NiA2NTUzNSBmDQowMDAwMDAxMDU3IDY1NTM1IGYNCjAwMDAwMDEwNTggNjU1MzUgZg0KMDAwMDAwMTA1OSA2NTUzNSBmDQowMDAwMDAxMDYwIDY1NTM1IGYNCjAwMDAwMDEwNjEgNjU1MzUgZg0KMDAwMDAwMTA2MiA2NTUzNSBmDQowMDAwMDAxMDYzIDY1NTM1IGYNCjAwMDAwMDEwNjQgNjU1MzUgZg0KMDAwMDAwMTA2NSA2NTUzNSBmDQowMDAwMDAxMDY2IDY1NTM1IGYNCjAwMDAwMDEwNjcgNjU1MzUgZg0KMDAwMDAwMTA2OCA2NTUzNSBmDQowMDAwMDAxMDY5IDY1NTM1IGYNCjAwMDAwMDEwNzAgNjU1MzUgZg0KMDAwMDAwMTA3MSA2NTUzNSBmDQowMDAwMDAxMDcyIDY1NTM1IGYNCjAwMDAwMDEwNzMgNjU1MzUgZg0KMDAwMDAwMTA3NCA2NTUzNSBmDQowMDAwMDAxMDc1IDY1NTM1IGYNCjAwMDAwMDEwNzYgNjU1MzUgZg0KMDAwMDAwMTA3NyA2NTUzNSBmDQowMDAwMDAxMDc4IDY1NTM1IGYNCjAwMDAwMDEwNzkgNjU1MzUgZg0KMDAwMDAwMTA4MCA2NTUzNSBmDQowMDAwMDAxMDgxIDY1NTM1IGYNCjAwMDAwMDEwODIgNjU1MzUgZg0KMDAwMDAwMTA4MyA2NTUzNSBmDQowMDAwMDAxMDg0IDY1NTM1IGYNCjAwMDAwMDEwODUgNjU1MzUgZg0KMDAwMDAwMTA4NiA2NTUzNSBmDQowMDAwMDAxMDg3IDY1NTM1IGYNCjAwMDAwMDEwODggNjU1MzUgZg0KMDAwMDAwMTA4OSA2NTUzNSBmDQowMDAwMDAxMDkwIDY1NTM1IGYNCjAwMDAwMDEwOTEgNjU1MzUgZg0KMDAwMDAwMTA5MiA2NTUzNSBmDQowMDAwMDAxMDkzIDY1NTM1IGYNCjAwMDAwMDEwOTQgNjU1MzUgZg0KMDAwMDAwMTA5NSA2NTUzNSBmDQowMDAwMDAxMDk2IDY1NTM1IGYNCjAwMDAwMDEwOTcgNjU1MzUgZg0KMDAwMDAwMTA5OCA2NTUzNSBmDQowMDAwMDAxMDk5IDY1NTM1IGYNCjAwMDAwMDExMDAgNjU1MzUgZg0KMDAwMDAwMTEwMSA2NTUzNSBmDQowMDAwMDAxMTAyIDY1NTM1IGYNCjAwMDAwMDExMDMgNjU1MzUgZg0KMDAwMDAwMTEwNCA2NTUzNSBmDQowMDAwMDAxMTA1IDY1NTM1IGYNCjAwMDAwMDExMDYgNjU1MzUgZg0KMDAwMDAwMTEwNyA2NTUzNSBmDQowMDAwMDAxMTA4IDY1NTM1IGYNCjAwMDAwMDExMDkgNjU1MzUgZg0KMDAwMDAwMTExMCA2NTUzNSBmDQowMDAwMDAxMTExIDY1NTM1IGYNCjAwMDAwMDExMTIgNjU1MzUgZg0KMDAwMDAwMTExMyA2NTUzNSBmDQowMDAwMDAxMTE0IDY1NTM1IGYNCjAwMDAwMDExMTUgNjU1MzUgZg0KMDAwMDAwMTExNiA2NTUzNSBmDQowMDAwMDAxMTE3IDY1NTM1IGYNCjAwMDAwMDExMTggNjU1MzUgZg0KMDAwMDAwMTExOSA2NTUzNSBmDQowMDAwMDAxMTIwIDY1NTM1IGYNCjAwMDAwMDExMjEgNjU1MzUgZg0KMDAwMDAwMTEyMiA2NTUzNSBmDQowMDAwMDAxMTIzIDY1NTM1IGYNCjAwMDAwMDExMjQgNjU1MzUgZg0KMDAwMDAwMTEyNSA2NTUzNSBmDQowMDAwMDAxMTI2IDY1NTM1IGYNCjAwMDAwMDExMjcgNjU1MzUgZg0KMDAwMDAwMTEyOCA2NTUzNSBmDQowMDAwMDAxMTI5IDY1NTM1IGYNCjAwMDAwMDExMzAgNjU1MzUgZg0KMDAwMDAwMTEzMSA2NTUzNSBmDQowMDAwMDAxMTMyIDY1NTM1IGYNCjAwMDAwMDExMzMgNjU1MzUgZg0KMDAwMDAwMTEzNCA2NTUzNSBmDQowMDAwMDAxMTM1IDY1NTM1IGYNCjAwMDAwMDExMzYgNjU1MzUgZg0KMDAwMDAwMTEzNyA2NTUzNSBmDQowMDAwMDAxMTM4IDY1NTM1IGYNCjAwMDAwMDExMzkgNjU1MzUgZg0KMDAwMDAwMTE0MCA2NTUzNSBmDQowMDAwMDAxMTQxIDY1NTM1IGYNCjAwMDAwMDExNDIgNjU1MzUgZg0KMDAwMDAwMTE0MyA2NTUzNSBmDQowMDAwMDAxMTQ0IDY1NTM1IGYNCjAwMDAwMDExNDUgNjU1MzUgZg0KMDAwMDAwMTE0NiA2NTUzNSBmDQowMDAwMDAxMTQ3IDY1NTM1IGYNCjAwMDAwMDExNDggNjU1MzUgZg0KMDAwMDAwMTE0OSA2NTUzNSBmDQowMDAwMDAxMTUwIDY1NTM1IGYNCjAwMDAwMDExNTEgNjU1MzUgZg0KMDAwMDAwMTE1MiA2NTUzNSBmDQowMDAwMDAxMTUzIDY1NTM1IGYNCjAwMDAwMDExNTQgNjU1MzUgZg0KMDAwMDAwMTE1NSA2NTUzNSBmDQowMDAwMDAxMTU2IDY1NTM1IGYNCjAwMDAwMDExNTcgNjU1MzUgZg0KMDAwMDAwMTE1OCA2NTUzNSBmDQowMDAwMDAxMTU5IDY1NTM1IGYNCjAwMDAwMDExNjAgNjU1MzUgZg0KMDAwMDAwMTE2MSA2NTUzNSBmDQowMDAwMDAxMTYyIDY1NTM1IGYNCjAwMDAwMDExNjMgNjU1MzUgZg0KMDAwMDAwMTE2NCA2NTUzNSBmDQowMDAwMDAxMTY1IDY1NTM1IGYNCjAwMDAwMDExNjYgNjU1MzUgZg0KMDAwMDAwMTE2NyA2NTUzNSBmDQowMDAwMDAxMTY4IDY1NTM1IGYNCjAwMDAwMDExNjkgNjU1MzUgZg0KMDAwMDAwMTE3MCA2NTUzNSBmDQowMDAwMDAxMTcxIDY1NTM1IGYNCjAwMDAwMDExNzIgNjU1MzUgZg0KMDAwMDAwMTE3MyA2NTUzNSBmDQowMDAwMDAxMTc0IDY1NTM1IGYNCjAwMDAwMDExNzUgNjU1MzUgZg0KMDAwMDAwMTE3NiA2NTUzNSBmDQowMDAwMDAxMTc3IDY1NTM1IGYNCjAwMDAwMDExNzggNjU1MzUgZg0KMDAwMDAwMTE3OSA2NTUzNSBmDQowMDAwMDAxMTgwIDY1NTM1IGYNCjAwMDAwMDExODEgNjU1MzUgZg0KMDAwMDAwMTE4MiA2NTUzNSBmDQowMDAwMDAxMTgzIDY1NTM1IGYNCjAwMDAwMDExODQgNjU1MzUgZg0KMDAwMDAwMTE4NSA2NTUzNSBmDQowMDAwMDAxMTg2IDY1NTM1IGYNCjAwMDAwMDExODcgNjU1MzUgZg0KMDAwMDAwMTE4OCA2NTUzNSBmDQowMDAwMDAxMTg5IDY1NTM1IGYNCjAwMDAwMDExOTAgNjU1MzUgZg0KMDAwMDAwMTE5MSA2NTUzNSBmDQowMDAwMDAxMTkyIDY1NTM1IGYNCjAwMDAwMDExOTMgNjU1MzUgZg0KMDAwMDAwMTE5NCA2NTUzNSBmDQowMDAwMDAxMTk1IDY1NTM1IGYNCjAwMDAwMDExOTYgNjU1MzUgZg0KMDAwMDAwMTE5NyA2NTUzNSBmDQowMDAwMDAxMTk4IDY1NTM1IGYNCjAwMDAwMDExOTkgNjU1MzUgZg0KMDAwMDAwMTIwMCA2NTUzNSBmDQowMDAwMDAxMjAxIDY1NTM1IGYNCjAwMDAwMDEyMDIgNjU1MzUgZg0KMDAwMDAwMTIwMyA2NTUzNSBmDQowMDAwMDAxMjA0IDY1NTM1IGYNCjAwMDAwMDEyMDUgNjU1MzUgZg0KMDAwMDAwMTIwNiA2NTUzNSBmDQowMDAwMDAxMjA3IDY1NTM1IGYNCjAwMDAwMDEyMDggNjU1MzUgZg0KMDAwMDAwMTIwOSA2NTUzNSBmDQowMDAwMDAxMjEwIDY1NTM1IGYNCjAwMDAwMDEyMTEgNjU1MzUgZg0KMDAwMDAwMTIxMiA2NTUzNSBmDQowMDAwMDAxMjEzIDY1NTM1IGYNCjAwMDAwMDEyMTQgNjU1MzUgZg0KMDAwMDAwMTIxNSA2NTUzNSBmDQowMDAwMDAxMjE2IDY1NTM1IGYNCjAwMDAwMDEyMTcgNjU1MzUgZg0KMDAwMDAwMTIxOCA2NTUzNSBmDQowMDAwMDAxMjE5IDY1NTM1IGYNCjAwMDAwMDEyMjAgNjU1MzUgZg0KMDAwMDAwMTIyMSA2NTUzNSBmDQowMDAwMDAxMjIyIDY1NTM1IGYNCjAwMDAwMDEyMjMgNjU1MzUgZg0KMDAwMDAwMTIyNCA2NTUzNSBmDQowMDAwMDAxMjI1IDY1NTM1IGYNCjAwMDAwMDEyMjYgNjU1MzUgZg0KMDAwMDAwMTIyNyA2NTUzNSBmDQowMDAwMDAxMjI4IDY1NTM1IGYNCjAwMDAwMDEyMjkgNjU1MzUgZg0KMDAwMDAwMTIzMCA2NTUzNSBmDQowMDAwMDAxMjMxIDY1NTM1IGYNCjAwMDAwMDEyMzIgNjU1MzUgZg0KMDAwMDAwMTIzMyA2NTUzNSBmDQowMDAwMDAxMjM0IDY1NTM1IGYNCjAwMDAwMDEyMzUgNjU1MzUgZg0KMDAwMDAwMTIzNiA2NTUzNSBmDQowMDAwMDAxMjM3IDY1NTM1IGYNCjAwMDAwMDEyMzggNjU1MzUgZg0KMDAwMDAwMTIzOSA2NTUzNSBmDQowMDAwMDAxMjQwIDY1NTM1IGYNCjAwMDAwMDEyNDEgNjU1MzUgZg0KMDAwMDAwMTI0MiA2NTUzNSBmDQowMDAwMDAxMjQzIDY1NTM1IGYNCjAwMDAwMDEyNDQgNjU1MzUgZg0KMDAwMDAwMTI0NSA2NTUzNSBmDQowMDAwMDAxMjQ2IDY1NTM1IGYNCjAwMDAwMDEyNDcgNjU1MzUgZg0KMDAwMDAwMTI0OCA2NTUzNSBmDQowMDAwMDAxMjQ5IDY1NTM1IGYNCjAwMDAwMDEyNTAgNjU1MzUgZg0KMDAwMDAwMTI1MSA2NTUzNSBmDQowMDAwMDAxMjUyIDY1NTM1IGYNCjAwMDAwMDEyNTMgNjU1MzUgZg0KMDAwMDAwMTI1NCA2NTUzNSBmDQowMDAwMDAxMjU1IDY1NTM1IGYNCjAwMDAwMDEyNTYgNjU1MzUgZg0KMDAwMDAwMTI1NyA2NTUzNSBmDQowMDAwMDAxMjU4IDY1NTM1IGYNCjAwMDAwMDEyNTkgNjU1MzUgZg0KMDAwMDAwMTI2MCA2NTUzNSBmDQowMDAwMDAxMjYxIDY1NTM1IGYNCjAwMDAwMDEyNjIgNjU1MzUgZg0KMDAwMDAwMTI2MyA2NTUzNSBmDQowMDAwMDAxMjY0IDY1NTM1IGYNCjAwMDAwMDEyNjUgNjU1MzUgZg0KMDAwMDAwMTI2NiA2NTUzNSBmDQowMDAwMDAxMjY3IDY1NTM1IGYNCjAwMDAwMDEyNjggNjU1MzUgZg0KMDAwMDAwMTI2OSA2NTUzNSBmDQowMDAwMDAxMjcwIDY1NTM1IGYNCjAwMDAwMDEyNzEgNjU1MzUgZg0KMDAwMDAwMTI3MiA2NTUzNSBmDQowMDAwMDAxMjczIDY1NTM1IGYNCjAwMDAwMDEyNzQgNjU1MzUgZg0KMDAwMDAwMTI3NSA2NTUzNSBmDQowMDAwMDAxMjc2IDY1NTM1IGYNCjAwMDAwMDEyNzcgNjU1MzUgZg0KMDAwMDAwMTI3OCA2NTUzNSBmDQowMDAwMDAxMjc5IDY1NTM1IGYNCjAwMDAwMDEyODAgNjU1MzUgZg0KMDAwMDAwMTI4MSA2NTUzNSBmDQowMDAwMDAxMjgyIDY1NTM1IGYNCjAwMDAwMDEyODMgNjU1MzUgZg0KMDAwMDAwMTI4NCA2NTUzNSBmDQowMDAwMDAxMjg1IDY1NTM1IGYNCjAwMDAwMDEyODYgNjU1MzUgZg0KMDAwMDAwMTI4NyA2NTUzNSBmDQowMDAwMDAxMjg4IDY1NTM1IGYNCjAwMDAwMDEyODkgNjU1MzUgZg0KMDAwMDAwMTI5MCA2NTUzNSBmDQowMDAwMDAxMjkxIDY1NTM1IGYNCjAwMDAwMDEyOTIgNjU1MzUgZg0KMDAwMDAwMTI5MyA2NTUzNSBmDQowMDAwMDAxMjk0IDY1NTM1IGYNCjAwMDAwMDEyOTUgNjU1MzUgZg0KMDAwMDAwMTI5NiA2NTUzNSBmDQowMDAwMDAxMjk3IDY1NTM1IGYNCjAwMDAwMDEyOTggNjU1MzUgZg0KMDAwMDAwMTI5OSA2NTUzNSBmDQowMDAwMDAxMzAwIDY1NTM1IGYNCjAwMDAwMDEzMDEgNjU1MzUgZg0KMDAwMDAwMTMwMiA2NTUzNSBmDQowMDAwMDAxMzAzIDY1NTM1IGYNCjAwMDAwMDEzMDQgNjU1MzUgZg0KMDAwMDAwMTMwNSA2NTUzNSBmDQowMDAwMDAxMzA2IDY1NTM1IGYNCjAwMDAwMDEzMDcgNjU1MzUgZg0KMDAwMDAwMTMwOCA2NTUzNSBmDQowMDAwMDAxMzA5IDY1NTM1IGYNCjAwMDAwMDEzMTAgNjU1MzUgZg0KMDAwMDAwMTMxMSA2NTUzNSBmDQowMDAwMDAxMzEyIDY1NTM1IGYNCjAwMDAwMDEzMTMgNjU1MzUgZg0KMDAwMDAwMTMxNCA2NTUzNSBmDQowMDAwMDAxMzE1IDY1NTM1IGYNCjAwMDAwMDEzMTYgNjU1MzUgZg0KMDAwMDAwMTMxNyA2NTUzNSBmDQowMDAwMDAxMzE4IDY1NTM1IGYNCjAwMDAwMDEzMTkgNjU1MzUgZg0KMDAwMDAwMTMyMCA2NTUzNSBmDQowMDAwMDAxMzIxIDY1NTM1IGYNCjAwMDAwMDEzMjIgNjU1MzUgZg0KMDAwMDAwMTMyMyA2NTUzNSBmDQowMDAwMDAxMzI0IDY1NTM1IGYNCjAwMDAwMDEzMjUgNjU1MzUgZg0KMDAwMDAwMTMyNiA2NTUzNSBmDQowMDAwMDAxMzI3IDY1NTM1IGYNCjAwMDAwMDEzMjggNjU1MzUgZg0KMDAwMDAwMTMyOSA2NTUzNSBmDQowMDAwMDAxMzMwIDY1NTM1IGYNCjAwMDAwMDEzMzEgNjU1MzUgZg0KMDAwMDAwMTMzMiA2NTUzNSBmDQowMDAwMDAxMzMzIDY1NTM1IGYNCjAwMDAwMDEzMzQgNjU1MzUgZg0KMDAwMDAwMTMzNSA2NTUzNSBmDQowMDAwMDAxMzM2IDY1NTM1IGYNCjAwMDAwMDEzMzcgNjU1MzUgZg0KMDAwMDAwMTMzOCA2NTUzNSBmDQowMDAwMDAxMzM5IDY1NTM1IGYNCjAwMDAwMDEzNDAgNjU1MzUgZg0KMDAwMDAwMTM0MSA2NTUzNSBmDQowMDAwMDAxMzQyIDY1NTM1IGYNCjAwMDAwMDEzNDMgNjU1MzUgZg0KMDAwMDAwMTM0NCA2NTUzNSBmDQowMDAwMDAxMzQ1IDY1NTM1IGYNCjAwMDAwMDEzNDYgNjU1MzUgZg0KMDAwMDAwMTM0NyA2NTUzNSBmDQowMDAwMDAxMzQ4IDY1NTM1IGYNCjAwMDAwMDEzNDkgNjU1MzUgZg0KMDAwMDAwMTM1MCA2NTUzNSBmDQowMDAwMDAxMzUxIDY1NTM1IGYNCjAwMDAwMDEzNTIgNjU1MzUgZg0KMDAwMDAwMTM1MyA2NTUzNSBmDQowMDAwMDAxMzU0IDY1NTM1IGYNCjAwMDAwMDEzNTUgNjU1MzUgZg0KMDAwMDAwMTM1NiA2NTUzNSBmDQowMDAwMDAxMzU3IDY1NTM1IGYNCjAwMDAwMDEzNTggNjU1MzUgZg0KMDAwMDAwMTM1OSA2NTUzNSBmDQowMDAwMDAxMzYwIDY1NTM1IGYNCjAwMDAwMDEzNjEgNjU1MzUgZg0KMDAwMDAwMTM2MiA2NTUzNSBmDQowMDAwMDAxMzYzIDY1NTM1IGYNCjAwMDAwMDEzNjQgNjU1MzUgZg0KMDAwMDAwMTM2NSA2NTUzNSBmDQowMDAwMDAxMzY2IDY1NTM1IGYNCjAwMDAwMDEzNjcgNjU1MzUgZg0KMDAwMDAwMTM2OCA2NTUzNSBmDQowMDAwMDAxMzY5IDY1NTM1IGYNCjAwMDAwMDEzNzAgNjU1MzUgZg0KMDAwMDAwMTM3MSA2NTUzNSBmDQowMDAwMDAxMzcyIDY1NTM1IGYNCjAwMDAwMDEzNzMgNjU1MzUgZg0KMDAwMDAwMTM3NCA2NTUzNSBmDQowMDAwMDAxMzc1IDY1NTM1IGYNCjAwMDAwMDEzNzYgNjU1MzUgZg0KMDAwMDAwMTM3NyA2NTUzNSBmDQowMDAwMDAxMzc4IDY1NTM1IGYNCjAwMDAwMDEzNzkgNjU1MzUgZg0KMDAwMDAwMTM4MCA2NTUzNSBmDQowMDAwMDAxMzgxIDY1NTM1IGYNCjAwMDAwMDEzODIgNjU1MzUgZg0KMDAwMDAwMTM4MyA2NTUzNSBmDQowMDAwMDAxMzg0IDY1NTM1IGYNCjAwMDAwMDEzODUgNjU1MzUgZg0KMDAwMDAwMTM4NiA2NTUzNSBmDQowMDAwMDAxMzg3IDY1NTM1IGYNCjAwMDAwMDEzODggNjU1MzUgZg0KMDAwMDAwMTM4OSA2NTUzNSBmDQowMDAwMDAxMzkwIDY1NTM1IGYNCjAwMDAwMDEzOTEgNjU1MzUgZg0KMDAwMDAwMTM5MiA2NTUzNSBmDQowMDAwMDAxMzkzIDY1NTM1IGYNCjAwMDAwMDEzOTQgNjU1MzUgZg0KMDAwMDAwMTM5NSA2NTUzNSBmDQowMDAwMDAxMzk2IDY1NTM1IGYNCjAwMDAwMDEzOTcgNjU1MzUgZg0KMDAwMDAwMTM5OCA2NTUzNSBmDQowMDAwMDAxMzk5IDY1NTM1IGYNCjAwMDAwMDE0MDAgNjU1MzUgZg0KMDAwMDAwMTQwMSA2NTUzNSBmDQowMDAwMDAxNDAyIDY1NTM1IGYNCjAwMDAwMDE0MDMgNjU1MzUgZg0KMDAwMDAwMTQwNCA2NTUzNSBmDQowMDAwMDAxNDA1IDY1NTM1IGYNCjAwMDAwMDE0MDYgNjU1MzUgZg0KMDAwMDAwMTQwNyA2NTUzNSBmDQowMDAwMDAxNDA4IDY1NTM1IGYNCjAwMDAwMDE0MDkgNjU1MzUgZg0KMDAwMDAwMTQxMCA2NTUzNSBmDQowMDAwMDAxNDExIDY1NTM1IGYNCjAwMDAwMDE0MTIgNjU1MzUgZg0KMDAwMDAwMTQxMyA2NTUzNSBmDQowMDAwMDAxNDE0IDY1NTM1IGYNCjAwMDAwMDE0MTUgNjU1MzUgZg0KMDAwMDAwMTQxNiA2NTUzNSBmDQowMDAwMDAxNDE3IDY1NTM1IGYNCjAwMDAwMDE0MTggNjU1MzUgZg0KMDAwMDAwMTQxOSA2NTUzNSBmDQowMDAwMDAxNDIwIDY1NTM1IGYNCjAwMDAwMDE0MjEgNjU1MzUgZg0KMDAwMDAwMTQyMiA2NTUzNSBmDQowMDAwMDAxNDIzIDY1NTM1IGYNCjAwMDAwMDE0MjQgNjU1MzUgZg0KMDAwMDAwMTQyNSA2NTUzNSBmDQowMDAwMDAxNDI2IDY1NTM1IGYNCjAwMDAwMDE0MjcgNjU1MzUgZg0KMDAwMDAwMTQyOCA2NTUzNSBmDQowMDAwMDAxNDI5IDY1NTM1IGYNCjAwMDAwMDE0MzAgNjU1MzUgZg0KMDAwMDAwMTQzMSA2NTUzNSBmDQowMDAwMDAxNDMyIDY1NTM1IGYNCjAwMDAwMDE0MzMgNjU1MzUgZg0KMDAwMDAwMTQzNCA2NTUzNSBmDQowMDAwMDAxNDM1IDY1NTM1IGYNCjAwMDAwMDE0MzYgNjU1MzUgZg0KMDAwMDAwMTQzNyA2NTUzNSBmDQowMDAwMDAxNDM4IDY1NTM1IGYNCjAwMDAwMDE0MzkgNjU1MzUgZg0KMDAwMDAwMTQ0MCA2NTUzNSBmDQowMDAwMDAxNDQxIDY1NTM1IGYNCjAwMDAwMDE0NDIgNjU1MzUgZg0KMDAwMDAwMTQ0MyA2NTUzNSBmDQowMDAwMDAxNDQ0IDY1NTM1IGYNCjAwMDAwMDE0NDUgNjU1MzUgZg0KMDAwMDAwMTQ0NiA2NTUzNSBmDQowMDAwMDAxNDQ3IDY1NTM1IGYNCjAwMDAwMDE0NDggNjU1MzUgZg0KMDAwMDAwMTQ0OSA2NTUzNSBmDQowMDAwMDAxNDUwIDY1NTM1IGYNCjAwMDAwMDE0NTEgNjU1MzUgZg0KMDAwMDAwMTQ1MiA2NTUzNSBmDQowMDAwMDAxNDUzIDY1NTM1IGYNCjAwMDAwMDE0NTQgNjU1MzUgZg0KMDAwMDAwMTQ1NSA2NTUzNSBmDQowMDAwMDAxNDU2IDY1NTM1IGYNCjAwMDAwMDE0NTcgNjU1MzUgZg0KMDAwMDAwMTQ1OCA2NTUzNSBmDQowMDAwMDAxNDU5IDY1NTM1IGYNCjAwMDAwMDE0NjAgNjU1MzUgZg0KMDAwMDAwMTQ2MSA2NTUzNSBmDQowMDAwMDAxNDYyIDY1NTM1IGYNCjAwMDAwMDE0NjMgNjU1MzUgZg0KMDAwMDAwMTQ2NCA2NTUzNSBmDQowMDAwMDAxNDY1IDY1NTM1IGYNCjAwMDAwMDE0NjYgNjU1MzUgZg0KMDAwMDAwMTQ2NyA2NTUzNSBmDQowMDAwMDAxNDY4IDY1NTM1IGYNCjAwMDAwMDE0NjkgNjU1MzUgZg0KMDAwMDAwMTQ3MCA2NTUzNSBmDQowMDAwMDAxNDcxIDY1NTM1IGYNCjAwMDAwMDE0NzIgNjU1MzUgZg0KMDAwMDAwMTQ3MyA2NTUzNSBmDQowMDAwMDAxNDc0IDY1NTM1IGYNCjAwMDAwMDE0NzUgNjU1MzUgZg0KMDAwMDAwMTQ3NiA2NTUzNSBmDQowMDAwMDAxNDc3IDY1NTM1IGYNCjAwMDAwMDE0NzggNjU1MzUgZg0KMDAwMDAwMTQ3OSA2NTUzNSBmDQowMDAwMDAxNDgwIDY1NTM1IGYNCjAwMDAwMDE0ODEgNjU1MzUgZg0KMDAwMDAwMTQ4MiA2NTUzNSBmDQowMDAwMDAxNDgzIDY1NTM1IGYNCjAwMDAwMDE0ODQgNjU1MzUgZg0KMDAwMDAwMTQ4NSA2NTUzNSBmDQowMDAwMDAxNDg2IDY1NTM1IGYNCjAwMDAwMDE0ODcgNjU1MzUgZg0KMDAwMDAwMTQ4OCA2NTUzNSBmDQowMDAwMDAxNDg5IDY1NTM1IGYNCjAwMDAwMDE0OTAgNjU1MzUgZg0KMDAwMDAwMTQ5MSA2NTUzNSBmDQowMDAwMDAxNDkyIDY1NTM1IGYNCjAwMDAwMDE0OTMgNjU1MzUgZg0KMDAwMDAwMTQ5NCA2NTUzNSBmDQowMDAwMDAxNDk1IDY1NTM1IGYNCjAwMDAwMDE0OTYgNjU1MzUgZg0KMDAwMDAwMTQ5NyA2NTUzNSBmDQowMDAwMDAxNDk4IDY1NTM1IGYNCjAwMDAwMDE0OTkgNjU1MzUgZg0KMDAwMDAwMTUwMCA2NTUzNSBmDQowMDAwMDAxNTAxIDY1NTM1IGYNCjAwMDAwMDE1MDIgNjU1MzUgZg0KMDAwMDAwMTUwMyA2NTUzNSBmDQowMDAwMDAxNTA0IDY1NTM1IGYNCjAwMDAwMDE1MDUgNjU1MzUgZg0KMDAwMDAwMTUwNiA2NTUzNSBmDQowMDAwMDAxNTA3IDY1NTM1IGYNCjAwMDAwMDE1MDggNjU1MzUgZg0KMDAwMDAwMTUwOSA2NTUzNSBmDQowMDAwMDAxNTEwIDY1NTM1IGYNCjAwMDAwMDE1MTEgNjU1MzUgZg0KMDAwMDAwMTUxMiA2NTUzNSBmDQowMDAwMDAxNTEzIDY1NTM1IGYNCjAwMDAwMDE1MTQgNjU1MzUgZg0KMDAwMDAwMTUxNSA2NTUzNSBmDQowMDAwMDAxNTE2IDY1NTM1IGYNCjAwMDAwMDE1MTcgNjU1MzUgZg0KMDAwMDAwMTUxOCA2NTUzNSBmDQowMDAwMDAxNTE5IDY1NTM1IGYNCjAwMDAwMDE1MjAgNjU1MzUgZg0KMDAwMDAwMTUyMSA2NTUzNSBmDQowMDAwMDAxNTIyIDY1NTM1IGYNCjAwMDAwMDE1MjMgNjU1MzUgZg0KMDAwMDAwMTUyNCA2NTUzNSBmDQowMDAwMDAxNTI1IDY1NTM1IGYNCjAwMDAwMDE1MjYgNjU1MzUgZg0KMDAwMDAwMTUyNyA2NTUzNSBmDQowMDAwMDAxNTI4IDY1NTM1IGYNCjAwMDAwMDE1MjkgNjU1MzUgZg0KMDAwMDAwMTUzMCA2NTUzNSBmDQowMDAwMDAxNTMxIDY1NTM1IGYNCjAwMDAwMDE1MzIgNjU1MzUgZg0KMDAwMDAwMTUzMyA2NTUzNSBmDQowMDAwMDAxNTM0IDY1NTM1IGYNCjAwMDAwMDE1MzUgNjU1MzUgZg0KMDAwMDAwMTUzNiA2NTUzNSBmDQowMDAwMDAxNTM3IDY1NTM1IGYNCjAwMDAwMDE1MzggNjU1MzUgZg0KMDAwMDAwMTUzOSA2NTUzNSBmDQowMDAwMDAxNTQwIDY1NTM1IGYNCjAwMDAwMDE1NDEgNjU1MzUgZg0KMDAwMDAwMTU0MiA2NTUzNSBmDQowMDAwMDAxNTQzIDY1NTM1IGYNCjAwMDAwMDE1NDQgNjU1MzUgZg0KMDAwMDAwMTU0NSA2NTUzNSBmDQowMDAwMDAxNTQ2IDY1NTM1IGYNCjAwMDAwMDE1NDcgNjU1MzUgZg0KMDAwMDAwMTU0OCA2NTUzNSBmDQowMDAwMDAxNTQ5IDY1NTM1IGYNCjAwMDAwMDE1NTAgNjU1MzUgZg0KMDAwMDAwMTU1MSA2NTUzNSBmDQowMDAwMDAxNTUyIDY1NTM1IGYNCjAwMDAwMDE1NTMgNjU1MzUgZg0KMDAwMDAwMTU1NCA2NTUzNSBmDQowMDAwMDAxNTU1IDY1NTM1IGYNCjAwMDAwMDE1NTYgNjU1MzUgZg0KMDAwMDAwMTU1NyA2NTUzNSBmDQowMDAwMDAxNTU4IDY1NTM1IGYNCjAwMDAwMDE1NTkgNjU1MzUgZg0KMDAwMDAwMTU2MCA2NTUzNSBmDQowMDAwMDAxNTYxIDY1NTM1IGYNCjAwMDAwMDE1NjIgNjU1MzUgZg0KMDAwMDAwMTU2MyA2NTUzNSBmDQowMDAwMDAxNTY0IDY1NTM1IGYNCjAwMDAwMDE1NjUgNjU1MzUgZg0KMDAwMDAwMTU2NiA2NTUzNSBmDQowMDAwMDAxNTY3IDY1NTM1IGYNCjAwMDAwMDE1NjggNjU1MzUgZg0KMDAwMDAwMTU2OSA2NTUzNSBmDQowMDAwMDAxNTcwIDY1NTM1IGYNCjAwMDAwMDE1NzEgNjU1MzUgZg0KMDAwMDAwMTU3MiA2NTUzNSBmDQowMDAwMDAxNTczIDY1NTM1IGYNCjAwMDAwMDE1NzQgNjU1MzUgZg0KMDAwMDAwMTU3NSA2NTUzNSBmDQowMDAwMDAxNTc2IDY1NTM1IGYNCjAwMDAwMDE1NzcgNjU1MzUgZg0KMDAwMDAwMTU3OCA2NTUzNSBmDQowMDAwMDAxNTc5IDY1NTM1IGYNCjAwMDAwMDE1ODAgNjU1MzUgZg0KMDAwMDAwMTU4MSA2NTUzNSBmDQowMDAwMDAxNTgyIDY1NTM1IGYNCjAwMDAwMDE1ODMgNjU1MzUgZg0KMDAwMDAwMTU4NCA2NTUzNSBmDQowMDAwMDAxNTg1IDY1NTM1IGYNCjAwMDAwMDE1ODYgNjU1MzUgZg0KMDAwMDAwMTU4NyA2NTUzNSBmDQowMDAwMDAxNTg4IDY1NTM1IGYNCjAwMDAwMDE1ODkgNjU1MzUgZg0KMDAwMDAwMTU5MCA2NTUzNSBmDQowMDAwMDAxNTkxIDY1NTM1IGYNCjAwMDAwMDE1OTIgNjU1MzUgZg0KMDAwMDAwMTU5MyA2NTUzNSBmDQowMDAwMDAxNTk0IDY1NTM1IGYNCjAwMDAwMDE1OTUgNjU1MzUgZg0KMDAwMDAwMTU5NiA2NTUzNSBmDQowMDAwMDAxNTk3IDY1NTM1IGYNCjAwMDAwMDE1OTggNjU1MzUgZg0KMDAwMDAwMTU5OSA2NTUzNSBmDQowMDAwMDAxNjAwIDY1NTM1IGYNCjAwMDAwMDE2MDEgNjU1MzUgZg0KMDAwMDAwMTYwMiA2NTUzNSBmDQowMDAwMDAxNjAzIDY1NTM1IGYNCjAwMDAwMDE2MDQgNjU1MzUgZg0KMDAwMDAwMTYwNSA2NTUzNSBmDQowMDAwMDAxNjA2IDY1NTM1IGYNCjAwMDAwMDE2MDcgNjU1MzUgZg0KMDAwMDAwMTYwOCA2NTUzNSBmDQowMDAwMDAxNjA5IDY1NTM1IGYNCjAwMDAwMDE2MTAgNjU1MzUgZg0KMDAwMDAwMTYxMSA2NTUzNSBmDQowMDAwMDAxNjEyIDY1NTM1IGYNCjAwMDAwMDE2MTMgNjU1MzUgZg0KMDAwMDAwMTYxNCA2NTUzNSBmDQowMDAwMDAxNjE1IDY1NTM1IGYNCjAwMDAwMDE2MTYgNjU1MzUgZg0KMDAwMDAwMTYxNyA2NTUzNSBmDQowMDAwMDAxNjE4IDY1NTM1IGYNCjAwMDAwMDE2MTkgNjU1MzUgZg0KMDAwMDAwMTYyMCA2NTUzNSBmDQowMDAwMDAxNjIxIDY1NTM1IGYNCjAwMDAwMDE2MjIgNjU1MzUgZg0KMDAwMDAwMTYyMyA2NTUzNSBmDQowMDAwMDAxNjI0IDY1NTM1IGYNCjAwMDAwMDE2MjUgNjU1MzUgZg0KMDAwMDAwMTYyNiA2NTUzNSBmDQowMDAwMDAxNjI3IDY1NTM1IGYNCjAwMDAwMDE2MjggNjU1MzUgZg0KMDAwMDAwMTYyOSA2NTUzNSBmDQowMDAwMDAxNjMwIDY1NTM1IGYNCjAwMDAwMDE2MzEgNjU1MzUgZg0KMDAwMDAwMTYzMiA2NTUzNSBmDQowMDAwMDAxNjMzIDY1NTM1IGYNCjAwMDAwMDE2MzQgNjU1MzUgZg0KMDAwMDAwMTYzNSA2NTUzNSBmDQowMDAwMDAxNjM2IDY1NTM1IGYNCjAwMDAwMDE2MzcgNjU1MzUgZg0KMDAwMDAwMTYzOCA2NTUzNSBmDQowMDAwMDAxNjM5IDY1NTM1IGYNCjAwMDAwMDE2NDAgNjU1MzUgZg0KMDAwMDAwMTY0MSA2NTUzNSBmDQowMDAwMDAxNjQyIDY1NTM1IGYNCjAwMDAwMDE2NDMgNjU1MzUgZg0KMDAwMDAwMTY0NCA2NTUzNSBmDQowMDAwMDAxNjQ1IDY1NTM1IGYNCjAwMDAwMDE2NDYgNjU1MzUgZg0KMDAwMDAwMTY0NyA2NTUzNSBmDQowMDAwMDAxNjQ4IDY1NTM1IGYNCjAwMDAwMDE2NDkgNjU1MzUgZg0KMDAwMDAwMTY1MCA2NTUzNSBmDQowMDAwMDAxNjUxIDY1NTM1IGYNCjAwMDAwMDE2NTIgNjU1MzUgZg0KMDAwMDAwMTY1MyA2NTUzNSBmDQowMDAwMDAxNjU0IDY1NTM1IGYNCjAwMDAwMDE2NTUgNjU1MzUgZg0KMDAwMDAwMTY1NiA2NTUzNSBmDQowMDAwMDAxNjU3IDY1NTM1IGYNCjAwMDAwMDE2NTggNjU1MzUgZg0KMDAwMDAwMTY1OSA2NTUzNSBmDQowMDAwMDAxNjYwIDY1NTM1IGYNCjAwMDAwMDE2NjEgNjU1MzUgZg0KMDAwMDAwMTY2MiA2NTUzNSBmDQowMDAwMDAxNjYzIDY1NTM1IGYNCjAwMDAwMDE2NjQgNjU1MzUgZg0KMDAwMDAwMTY2NSA2NTUzNSBmDQowMDAwMDAxNjY2IDY1NTM1IGYNCjAwMDAwMDE2NjcgNjU1MzUgZg0KMDAwMDAwMTY2OCA2NTUzNSBmDQowMDAwMDAxNjY5IDY1NTM1IGYNCjAwMDAwMDE2NzAgNjU1MzUgZg0KMDAwMDAwMTY3MSA2NTUzNSBmDQowMDAwMDAxNjcyIDY1NTM1IGYNCjAwMDAwMDE2NzMgNjU1MzUgZg0KMDAwMDAwMTY3NCA2NTUzNSBmDQowMDAwMDAxNjc1IDY1NTM1IGYNCjAwMDAwMDE2NzYgNjU1MzUgZg0KMDAwMDAwMTY3NyA2NTUzNSBmDQowMDAwMDAxNjc4IDY1NTM1IGYNCjAwMDAwMDE2NzkgNjU1MzUgZg0KMDAwMDAwMTY4MCA2NTUzNSBmDQowMDAwMDAxNjgxIDY1NTM1IGYNCjAwMDAwMDE2ODIgNjU1MzUgZg0KMDAwMDAwMTY4MyA2NTUzNSBmDQowMDAwMDAxNjg0IDY1NTM1IGYNCjAwMDAwMDE2ODUgNjU1MzUgZg0KMDAwMDAwMTY4NiA2NTUzNSBmDQowMDAwMDAxNjg3IDY1NTM1IGYNCjAwMDAwMDE2ODggNjU1MzUgZg0KMDAwMDAwMTY4OSA2NTUzNSBmDQowMDAwMDAxNjkwIDY1NTM1IGYNCjAwMDAwMDE2OTEgNjU1MzUgZg0KMDAwMDAwMTY5MiA2NTUzNSBmDQowMDAwMDAxNjkzIDY1NTM1IGYNCjAwMDAwMDE2OTQgNjU1MzUgZg0KMDAwMDAwMTY5NSA2NTUzNSBmDQowMDAwMDAxNjk2IDY1NTM1IGYNCjAwMDAwMDE2OTcgNjU1MzUgZg0KMDAwMDAwMTY5OCA2NTUzNSBmDQowMDAwMDAxNjk5IDY1NTM1IGYNCjAwMDAwMDE3MDAgNjU1MzUgZg0KMDAwMDAwMTcwMSA2NTUzNSBmDQowMDAwMDAxNzAyIDY1NTM1IGYNCjAwMDAwMDE3MDMgNjU1MzUgZg0KMDAwMDAwMTcwNCA2NTUzNSBmDQowMDAwMDAxNzA1IDY1NTM1IGYNCjAwMDAwMDE3MDYgNjU1MzUgZg0KMDAwMDAwMTcwNyA2NTUzNSBmDQowMDAwMDAxNzA4IDY1NTM1IGYNCjAwMDAwMDE3MDkgNjU1MzUgZg0KMDAwMDAwMTcxMCA2NTUzNSBmDQowMDAwMDAxNzExIDY1NTM1IGYNCjAwMDAwMDE3MTIgNjU1MzUgZg0KMDAwMDAwMTcxMyA2NTUzNSBmDQowMDAwMDAxNzE0IDY1NTM1IGYNCjAwMDAwMDE3MTUgNjU1MzUgZg0KMDAwMDAwMTcxNiA2NTUzNSBmDQowMDAwMDAxNzE3IDY1NTM1IGYNCjAwMDAwMDE3MTggNjU1MzUgZg0KMDAwMDAwMTcxOSA2NTUzNSBmDQowMDAwMDAxNzIwIDY1NTM1IGYNCjAwMDAwMDE3MjEgNjU1MzUgZg0KMDAwMDAwMTcyMiA2NTUzNSBmDQowMDAwMDAxNzIzIDY1NTM1IGYNCjAwMDAwMDE3MjQgNjU1MzUgZg0KMDAwMDAwMTcyNSA2NTUzNSBmDQowMDAwMDAxNzI2IDY1NTM1IGYNCjAwMDAwMDE3MjcgNjU1MzUgZg0KMDAwMDAwMTcyOCA2NTUzNSBmDQowMDAwMDAxNzI5IDY1NTM1IGYNCjAwMDAwMDE3MzAgNjU1MzUgZg0KMDAwMDAwMTczMSA2NTUzNSBmDQowMDAwMDAxNzMyIDY1NTM1IGYNCjAwMDAwMDE3MzMgNjU1MzUgZg0KMDAwMDAwMTczNCA2NTUzNSBmDQowMDAwMDAxNzM1IDY1NTM1IGYNCjAwMDAwMDE3MzYgNjU1MzUgZg0KMDAwMDAwMTczNyA2NTUzNSBmDQowMDAwMDAxNzM4IDY1NTM1IGYNCjAwMDAwMDE3MzkgNjU1MzUgZg0KMDAwMDAwMTc0MCA2NTUzNSBmDQowMDAwMDAxNzQxIDY1NTM1IGYNCjAwMDAwMDE3NDIgNjU1MzUgZg0KMDAwMDAwMTc0MyA2NTUzNSBmDQowMDAwMDAxNzQ0IDY1NTM1IGYNCjAwMDAwMDE3NDUgNjU1MzUgZg0KMDAwMDAwMTc0NiA2NTUzNSBmDQowMDAwMDAxNzQ3IDY1NTM1IGYNCjAwMDAwMDE3NDggNjU1MzUgZg0KMDAwMDAwMTc0OSA2NTUzNSBmDQowMDAwMDAxNzUwIDY1NTM1IGYNCjAwMDAwMDE3NTEgNjU1MzUgZg0KMDAwMDAwMTc1MiA2NTUzNSBmDQowMDAwMDAxNzUzIDY1NTM1IGYNCjAwMDAwMDE3NTQgNjU1MzUgZg0KMDAwMDAwMTc1NSA2NTUzNSBmDQowMDAwMDAxNzU2IDY1NTM1IGYNCjAwMDAwMDE3NTcgNjU1MzUgZg0KMDAwMDAwMTc1OCA2NTUzNSBmDQowMDAwMDAxNzU5IDY1NTM1IGYNCjAwMDAwMDE3NjAgNjU1MzUgZg0KMDAwMDAwMTc2MSA2NTUzNSBmDQowMDAwMDAxNzYyIDY1NTM1IGYNCjAwMDAwMDE3NjMgNjU1MzUgZg0KMDAwMDAwMTc2NCA2NTUzNSBmDQowMDAwMDAxNzY1IDY1NTM1IGYNCjAwMDAwMDE3NjYgNjU1MzUgZg0KMDAwMDAwMTc2NyA2NTUzNSBmDQowMDAwMDAxNzY4IDY1NTM1IGYNCjAwMDAwMDE3NjkgNjU1MzUgZg0KMDAwMDAwMTc3MCA2NTUzNSBmDQowMDAwMDAxNzcxIDY1NTM1IGYNCjAwMDAwMDE3NzIgNjU1MzUgZg0KMDAwMDAwMTc3MyA2NTUzNSBmDQowMDAwMDAxNzc0IDY1NTM1IGYNCjAwMDAwMDE3NzUgNjU1MzUgZg0KMDAwMDAwMTc3NiA2NTUzNSBmDQowMDAwMDAxNzc3IDY1NTM1IGYNCjAwMDAwMDE3NzggNjU1MzUgZg0KMDAwMDAwMTc3OSA2NTUzNSBmDQowMDAwMDAxNzgwIDY1NTM1IGYNCjAwMDAwMDE3ODEgNjU1MzUgZg0KMDAwMDAwMTc4MiA2NTUzNSBmDQowMDAwMDAxNzgzIDY1NTM1IGYNCjAwMDAwMDE3ODQgNjU1MzUgZg0KMDAwMDAwMTc4NSA2NTUzNSBmDQowMDAwMDAxNzg2IDY1NTM1IGYNCjAwMDAwMDE3ODcgNjU1MzUgZg0KMDAwMDAwMTc4OCA2NTUzNSBmDQowMDAwMDAxNzg5IDY1NTM1IGYNCjAwMDAwMDE3OTAgNjU1MzUgZg0KMDAwMDAwMTc5MSA2NTUzNSBmDQowMDAwMDAxNzkyIDY1NTM1IGYNCjAwMDAwMDE3OTMgNjU1MzUgZg0KMDAwMDAwMTc5NCA2NTUzNSBmDQowMDAwMDAxNzk1IDY1NTM1IGYNCjAwMDAwMDE3OTYgNjU1MzUgZg0KMDAwMDAwMTc5NyA2NTUzNSBmDQowMDAwMDAxNzk4IDY1NTM1IGYNCjAwMDAwMDE3OTkgNjU1MzUgZg0KMDAwMDAwMTgwMCA2NTUzNSBmDQowMDAwMDAxODAxIDY1NTM1IGYNCjAwMDAwMDE4MDIgNjU1MzUgZg0KMDAwMDAwMTgwMyA2NTUzNSBmDQowMDAwMDAxODA0IDY1NTM1IGYNCjAwMDAwMDE4MDUgNjU1MzUgZg0KMDAwMDAwMTgwNiA2NTUzNSBmDQowMDAwMDAxODA3IDY1NTM1IGYNCjAwMDAwMDE4MDggNjU1MzUgZg0KMDAwMDAwMTgwOSA2NTUzNSBmDQowMDAwMDAxODEwIDY1NTM1IGYNCjAwMDAwMDE4MTEgNjU1MzUgZg0KMDAwMDAwMTgxMiA2NTUzNSBmDQowMDAwMDAxODEzIDY1NTM1IGYNCjAwMDAwMDE4MTQgNjU1MzUgZg0KMDAwMDAwMTgxNSA2NTUzNSBmDQowMDAwMDAxODE2IDY1NTM1IGYNCjAwMDAwMDE4MTcgNjU1MzUgZg0KMDAwMDAwMTgxOCA2NTUzNSBmDQowMDAwMDAxODE5IDY1NTM1IGYNCjAwMDAwMDE4MjAgNjU1MzUgZg0KMDAwMDAwMTgyMSA2NTUzNSBmDQowMDAwMDAxODIyIDY1NTM1IGYNCjAwMDAwMDE4MjMgNjU1MzUgZg0KMDAwMDAwMTgyNCA2NTUzNSBmDQowMDAwMDAxODI1IDY1NTM1IGYNCjAwMDAwMDE4MjYgNjU1MzUgZg0KMDAwMDAwMTgyNyA2NTUzNSBmDQowMDAwMDAxODI4IDY1NTM1IGYNCjAwMDAwMDE4MjkgNjU1MzUgZg0KMDAwMDAwMTgzMCA2NTUzNSBmDQowMDAwMDAxODMxIDY1NTM1IGYNCjAwMDAwMDE4MzIgNjU1MzUgZg0KMDAwMDAwMTgzMyA2NTUzNSBmDQowMDAwMDAxODM0IDY1NTM1IGYNCjAwMDAwMDE4MzUgNjU1MzUgZg0KMDAwMDAwMTgzNiA2NTUzNSBmDQowMDAwMDAxODM3IDY1NTM1IGYNCjAwMDAwMDE4MzggNjU1MzUgZg0KMDAwMDAwMTgzOSA2NTUzNSBmDQowMDAwMDAxODQwIDY1NTM1IGYNCjAwMDAwMDE4NDEgNjU1MzUgZg0KMDAwMDAwMTg0MiA2NTUzNSBmDQowMDAwMDAxODQzIDY1NTM1IGYNCjAwMDAwMDE4NDQgNjU1MzUgZg0KMDAwMDAwMTg0NSA2NTUzNSBmDQowMDAwMDAxODQ2IDY1NTM1IGYNCjAwMDAwMDE4NDcgNjU1MzUgZg0KMDAwMDAwMTg0OCA2NTUzNSBmDQowMDAwMDAxODQ5IDY1NTM1IGYNCjAwMDAwMDE4NTAgNjU1MzUgZg0KMDAwMDAwMTg1MSA2NTUzNSBmDQowMDAwMDAxODUyIDY1NTM1IGYNCjAwMDAwMDE4NTMgNjU1MzUgZg0KMDAwMDAwMTg1NCA2NTUzNSBmDQowMDAwMDAxODU1IDY1NTM1IGYNCjAwMDAwMDE4NTYgNjU1MzUgZg0KMDAwMDAwMTg1NyA2NTUzNSBmDQowMDAwMDAxODU4IDY1NTM1IGYNCjAwMDAwMDE4NTkgNjU1MzUgZg0KMDAwMDAwMTg2MCA2NTUzNSBmDQowMDAwMDAxODYxIDY1NTM1IGYNCjAwMDAwMDE4NjIgNjU1MzUgZg0KMDAwMDAwMTg2MyA2NTUzNSBmDQowMDAwMDAxODY0IDY1NTM1IGYNCjAwMDAwMDE4NjUgNjU1MzUgZg0KMDAwMDAwMTg2NiA2NTUzNSBmDQowMDAwMDAxODY3IDY1NTM1IGYNCjAwMDAwMDE4NjggNjU1MzUgZg0KMDAwMDAwMTg2OSA2NTUzNSBmDQowMDAwMDAxODcwIDY1NTM1IGYNCjAwMDAwMDE4NzEgNjU1MzUgZg0KMDAwMDAwMTg3MiA2NTUzNSBmDQowMDAwMDAxODczIDY1NTM1IGYNCjAwMDAwMDE4NzQgNjU1MzUgZg0KMDAwMDAwMTg3NSA2NTUzNSBmDQowMDAwMDAxODc2IDY1NTM1IGYNCjAwMDAwMDE4NzcgNjU1MzUgZg0KMDAwMDAwMTg3OCA2NTUzNSBmDQowMDAwMDAxODc5IDY1NTM1IGYNCjAwMDAwMDE4ODAgNjU1MzUgZg0KMDAwMDAwMTg4MSA2NTUzNSBmDQowMDAwMDAxODgyIDY1NTM1IGYNCjAwMDAwMDE4ODMgNjU1MzUgZg0KMDAwMDAwMTg4NCA2NTUzNSBmDQowMDAwMDAxODg1IDY1NTM1IGYNCjAwMDAwMDE4ODYgNjU1MzUgZg0KMDAwMDAwMTg4NyA2NTUzNSBmDQowMDAwMDAxODg4IDY1NTM1IGYNCjAwMDAwMDE4ODkgNjU1MzUgZg0KMDAwMDAwMTg5MCA2NTUzNSBmDQowMDAwMDAxODkxIDY1NTM1IGYNCjAwMDAwMDE4OTIgNjU1MzUgZg0KMDAwMDAwMTg5MyA2NTUzNSBmDQowMDAwMDAxODk0IDY1NTM1IGYNCjAwMDAwMDE4OTUgNjU1MzUgZg0KMDAwMDAwMTg5NiA2NTUzNSBmDQowMDAwMDAxODk3IDY1NTM1IGYNCjAwMDAwMDE4OTggNjU1MzUgZg0KMDAwMDAwMTg5OSA2NTUzNSBmDQowMDAwMDAxOTAwIDY1NTM1IGYNCjAwMDAwMDE5MDEgNjU1MzUgZg0KMDAwMDAwMTkwMiA2NTUzNSBmDQowMDAwMDAxOTAzIDY1NTM1IGYNCjAwMDAwMDE5MDQgNjU1MzUgZg0KMDAwMDAwMTkwNSA2NTUzNSBmDQowMDAwMDAxOTA2IDY1NTM1IGYNCjAwMDAwMDE5MDcgNjU1MzUgZg0KMDAwMDAwMTkwOCA2NTUzNSBmDQowMDAwMDAxOTA5IDY1NTM1IGYNCjAwMDAwMDE5MTAgNjU1MzUgZg0KMDAwMDAwMTkxMSA2NTUzNSBmDQowMDAwMDAxOTEyIDY1NTM1IGYNCjAwMDAwMDE5MTMgNjU1MzUgZg0KMDAwMDAwMTkxNCA2NTUzNSBmDQowMDAwMDAxOTE1IDY1NTM1IGYNCjAwMDAwMDE5MTYgNjU1MzUgZg0KMDAwMDAwMTkxNyA2NTUzNSBmDQowMDAwMDAxOTE4IDY1NTM1IGYNCjAwMDAwMDE5MTkgNjU1MzUgZg0KMDAwMDAwMTkyMCA2NTUzNSBmDQowMDAwMDAxOTIxIDY1NTM1IGYNCjAwMDAwMDE5MjIgNjU1MzUgZg0KMDAwMDAwMTkyMyA2NTUzNSBmDQowMDAwMDAxOTI0IDY1NTM1IGYNCjAwMDAwMDE5MjUgNjU1MzUgZg0KMDAwMDAwMTkyNiA2NTUzNSBmDQowMDAwMDAxOTI3IDY1NTM1IGYNCjAwMDAwMDE5MjggNjU1MzUgZg0KMDAwMDAwMTkyOSA2NTUzNSBmDQowMDAwMDAxOTMwIDY1NTM1IGYNCjAwMDAwMDE5MzEgNjU1MzUgZg0KMDAwMDAwMTkzMiA2NTUzNSBmDQowMDAwMDAxOTMzIDY1NTM1IGYNCjAwMDAwMDE5MzQgNjU1MzUgZg0KMDAwMDAwMTkzNSA2NTUzNSBmDQowMDAwMDAxOTM2IDY1NTM1IGYNCjAwMDAwMDE5MzcgNjU1MzUgZg0KMDAwMDAwMTkzOCA2NTUzNSBmDQowMDAwMDAxOTM5IDY1NTM1IGYNCjAwMDAwMDE5NDAgNjU1MzUgZg0KMDAwMDAwMTk0MSA2NTUzNSBmDQowMDAwMDAxOTQyIDY1NTM1IGYNCjAwMDAwMDE5NDMgNjU1MzUgZg0KMDAwMDAwMTk0NCA2NTUzNSBmDQowMDAwMDAxOTQ1IDY1NTM1IGYNCjAwMDAwMDE5NDYgNjU1MzUgZg0KMDAwMDAwMTk0NyA2NTUzNSBmDQowMDAwMDAxOTQ4IDY1NTM1IGYNCjAwMDAwMDE5NDkgNjU1MzUgZg0KMDAwMDAwMTk1MCA2NTUzNSBmDQowMDAwMDAxOTUxIDY1NTM1IGYNCjAwMDAwMDE5NTIgNjU1MzUgZg0KMDAwMDAwMTk1MyA2NTUzNSBmDQowMDAwMDAxOTU0IDY1NTM1IGYNCjAwMDAwMDE5NTUgNjU1MzUgZg0KMDAwMDAwMTk1NiA2NTUzNSBmDQowMDAwMDAxOTU3IDY1NTM1IGYNCjAwMDAwMDE5NTggNjU1MzUgZg0KMDAwMDAwMTk1OSA2NTUzNSBmDQowMDAwMDAxOTYwIDY1NTM1IGYNCjAwMDAwMDE5NjEgNjU1MzUgZg0KMDAwMDAwMTk2MiA2NTUzNSBmDQowMDAwMDAxOTYzIDY1NTM1IGYNCjAwMDAwMDE5NjQgNjU1MzUgZg0KMDAwMDAwMTk2NSA2NTUzNSBmDQowMDAwMDAxOTY2IDY1NTM1IGYNCjAwMDAwMDE5NjcgNjU1MzUgZg0KMDAwMDAwMTk2OCA2NTUzNSBmDQowMDAwMDAxOTY5IDY1NTM1IGYNCjAwMDAwMDE5NzAgNjU1MzUgZg0KMDAwMDAwMTk3MSA2NTUzNSBmDQowMDAwMDAxOTcyIDY1NTM1IGYNCjAwMDAwMDE5NzMgNjU1MzUgZg0KMDAwMDAwMTk3NCA2NTUzNSBmDQowMDAwMDAxOTc1IDY1NTM1IGYNCjAwMDAwMDE5NzYgNjU1MzUgZg0KMDAwMDAwMTk3NyA2NTUzNSBmDQowMDAwMDAxOTc4IDY1NTM1IGYNCjAwMDAwMDE5NzkgNjU1MzUgZg0KMDAwMDAwMTk4MCA2NTUzNSBmDQowMDAwMDAxOTgxIDY1NTM1IGYNCjAwMDAwMDE5ODIgNjU1MzUgZg0KMDAwMDAwMTk4MyA2NTUzNSBmDQowMDAwMDAxOTg0IDY1NTM1IGYNCjAwMDAwMDE5ODUgNjU1MzUgZg0KMDAwMDAwMTk4NiA2NTUzNSBmDQowMDAwMDAxOTg3IDY1NTM1IGYNCjAwMDAwMDE5ODggNjU1MzUgZg0KMDAwMDAwMTk4OSA2NTUzNSBmDQowMDAwMDAxOTkwIDY1NTM1IGYNCjAwMDAwMDE5OTEgNjU1MzUgZg0KMDAwMDAwMTk5MiA2NTUzNSBmDQowMDAwMDAxOTkzIDY1NTM1IGYNCjAwMDAwMDE5OTQgNjU1MzUgZg0KMDAwMDAwMTk5NSA2NTUzNSBmDQowMDAwMDAxOTk2IDY1NTM1IGYNCjAwMDAwMDE5OTcgNjU1MzUgZg0KMDAwMDAwMTk5OCA2NTUzNSBmDQowMDAwMDAxOTk5IDY1NTM1IGYNCjAwMDAwMDIwMDAgNjU1MzUgZg0KMDAwMDAwMjAwMSA2NTUzNSBmDQowMDAwMDAyMDAyIDY1NTM1IGYNCjAwMDAwMDIwMDMgNjU1MzUgZg0KMDAwMDAwMjAwNCA2NTUzNSBmDQowMDAwMDAyMDA1IDY1NTM1IGYNCjAwMDAwMDIwMDYgNjU1MzUgZg0KMDAwMDAwMjAwNyA2NTUzNSBmDQowMDAwMDAyMDA4IDY1NTM1IGYNCjAwMDAwMDIwMDkgNjU1MzUgZg0KMDAwMDAwMjAxMCA2NTUzNSBmDQowMDAwMDAyMDExIDY1NTM1IGYNCjAwMDAwMDIwMTIgNjU1MzUgZg0KMDAwMDAwMjAxMyA2NTUzNSBmDQowMDAwMDAyMDE0IDY1NTM1IGYNCjAwMDAwMDIwMTUgNjU1MzUgZg0KMDAwMDAwMjAxNiA2NTUzNSBmDQowMDAwMDAyMDE3IDY1NTM1IGYNCjAwMDAwMDIwMTggNjU1MzUgZg0KMDAwMDAwMjAxOSA2NTUzNSBmDQowMDAwMDAyMDIwIDY1NTM1IGYNCjAwMDAwMDIwMjEgNjU1MzUgZg0KMDAwMDAwMjAyMiA2NTUzNSBmDQowMDAwMDAyMDIzIDY1NTM1IGYNCjAwMDAwMDIwMjQgNjU1MzUgZg0KMDAwMDAwMjAyNSA2NTUzNSBmDQowMDAwMDAyMDI2IDY1NTM1IGYNCjAwMDAwMDIwMjcgNjU1MzUgZg0KMDAwMDAwMjAyOCA2NTUzNSBmDQowMDAwMDAyMDI5IDY1NTM1IGYNCjAwMDAwMDIwMzAgNjU1MzUgZg0KMDAwMDAwMjAzMSA2NTUzNSBmDQowMDAwMDAyMDMyIDY1NTM1IGYNCjAwMDAwMDIwMzMgNjU1MzUgZg0KMDAwMDAwMjAzNCA2NTUzNSBmDQowMDAwMDAyMDM1IDY1NTM1IGYNCjAwMDAwMDIwMzYgNjU1MzUgZg0KMDAwMDAwMjAzNyA2NTUzNSBmDQowMDAwMDAyMDM4IDY1NTM1IGYNCjAwMDAwMDIwMzkgNjU1MzUgZg0KMDAwMDAwMjA0MCA2NTUzNSBmDQowMDAwMDAyMDQxIDY1NTM1IGYNCjAwMDAwMDIwNDIgNjU1MzUgZg0KMDAwMDAwMjA0MyA2NTUzNSBmDQowMDAwMDAyMDQ0IDY1NTM1IGYNCjAwMDAwMDIwNDUgNjU1MzUgZg0KMDAwMDAwMjA0NiA2NTUzNSBmDQowMDAwMDAyMDQ3IDY1NTM1IGYNCjAwMDAwMDIwNDggNjU1MzUgZg0KMDAwMDAwMjA0OSA2NTUzNSBmDQowMDAwMDAyMDUwIDY1NTM1IGYNCjAwMDAwMDIwNTEgNjU1MzUgZg0KMDAwMDAwMjA1MiA2NTUzNSBmDQowMDAwMDAyMDUzIDY1NTM1IGYNCjAwMDAwMDIwNTQgNjU1MzUgZg0KMDAwMDAwMjA1NSA2NTUzNSBmDQowMDAwMDAyMDU2IDY1NTM1IGYNCjAwMDAwMDIwNTcgNjU1MzUgZg0KMDAwMDAwMjA1OCA2NTUzNSBmDQowMDAwMDAyMDU5IDY1NTM1IGYNCjAwMDAwMDIwNjAgNjU1MzUgZg0KMDAwMDAwMjA2MSA2NTUzNSBmDQowMDAwMDAyMDYyIDY1NTM1IGYNCjAwMDAwMDIwNjMgNjU1MzUgZg0KMDAwMDAwMjA2NCA2NTUzNSBmDQowMDAwMDAyMDY1IDY1NTM1IGYNCjAwMDAwMDIwNjYgNjU1MzUgZg0KMDAwMDAwMjA2NyA2NTUzNSBmDQowMDAwMDAyMDY4IDY1NTM1IGYNCjAwMDAwMDIwNjkgNjU1MzUgZg0KMDAwMDAwMjA3MCA2NTUzNSBmDQowMDAwMDAyMDcxIDY1NTM1IGYNCjAwMDAwMDIwNzIgNjU1MzUgZg0KMDAwMDAwMjA3MyA2NTUzNSBmDQowMDAwMDAyMDc0IDY1NTM1IGYNCjAwMDAwMDIwNzUgNjU1MzUgZg0KMDAwMDAwMjA3NiA2NTUzNSBmDQowMDAwMDAyMDc3IDY1NTM1IGYNCjAwMDAwMDIwNzggNjU1MzUgZg0KMDAwMDAwMjA3OSA2NTUzNSBmDQowMDAwMDAyMDgwIDY1NTM1IGYNCjAwMDAwMDIwODEgNjU1MzUgZg0KMDAwMDAwMjA4MiA2NTUzNSBmDQowMDAwMDAyMDgzIDY1NTM1IGYNCjAwMDAwMDIwODQgNjU1MzUgZg0KMDAwMDAwMjA4NSA2NTUzNSBmDQowMDAwMDAyMDg2IDY1NTM1IGYNCjAwMDAwMDIwODcgNjU1MzUgZg0KMDAwMDAwMjA4OCA2NTUzNSBmDQowMDAwMDAyMDg5IDY1NTM1IGYNCjAwMDAwMDIwOTAgNjU1MzUgZg0KMDAwMDAwMjA5MSA2NTUzNSBmDQowMDAwMDAyMDkyIDY1NTM1IGYNCjAwMDAwMDIwOTMgNjU1MzUgZg0KMDAwMDAwMjA5NCA2NTUzNSBmDQowMDAwMDAyMDk1IDY1NTM1IGYNCjAwMDAwMDIwOTYgNjU1MzUgZg0KMDAwMDAwMjA5NyA2NTUzNSBmDQowMDAwMDAyMDk4IDY1NTM1IGYNCjAwMDAwMDIwOTkgNjU1MzUgZg0KMDAwMDAwMjEwMCA2NTUzNSBmDQowMDAwMDAyMTAxIDY1NTM1IGYNCjAwMDAwMDIxMDIgNjU1MzUgZg0KMDAwMDAwMjEwMyA2NTUzNSBmDQowMDAwMDAyMTA0IDY1NTM1IGYNCjAwMDAwMDIxMDUgNjU1MzUgZg0KMDAwMDAwMjEwNiA2NTUzNSBmDQowMDAwMDAyMTA3IDY1NTM1IGYNCjAwMDAwMDIxMDggNjU1MzUgZg0KMDAwMDAwMjEwOSA2NTUzNSBmDQowMDAwMDAyMTEwIDY1NTM1IGYNCjAwMDAwMDIxMTEgNjU1MzUgZg0KMDAwMDAwMjExMiA2NTUzNSBmDQowMDAwMDAyMTEzIDY1NTM1IGYNCjAwMDAwMDIxMTQgNjU1MzUgZg0KMDAwMDAwMjExNSA2NTUzNSBmDQowMDAwMDAyMTE2IDY1NTM1IGYNCjAwMDAwMDIxMTcgNjU1MzUgZg0KMDAwMDAwMjExOCA2NTUzNSBmDQowMDAwMDAyMTE5IDY1NTM1IGYNCjAwMDAwMDIxMjAgNjU1MzUgZg0KMDAwMDAwMjEyMSA2NTUzNSBmDQowMDAwMDAyMTIyIDY1NTM1IGYNCjAwMDAwMDIxMjMgNjU1MzUgZg0KMDAwMDAwMjEyNCA2NTUzNSBmDQowMDAwMDAyMTI1IDY1NTM1IGYNCjAwMDAwMDIxMjYgNjU1MzUgZg0KMDAwMDAwMjEyNyA2NTUzNSBmDQowMDAwMDAyMTI4IDY1NTM1IGYNCjAwMDAwMDIxMjkgNjU1MzUgZg0KMDAwMDAwMjEzMCA2NTUzNSBmDQowMDAwMDAyMTMxIDY1NTM1IGYNCjAwMDAwMDIxMzIgNjU1MzUgZg0KMDAwMDAwMjEzMyA2NTUzNSBmDQowMDAwMDAyMTM0IDY1NTM1IGYNCjAwMDAwMDIxMzUgNjU1MzUgZg0KMDAwMDAwMjEzNiA2NTUzNSBmDQowMDAwMDAyMTM3IDY1NTM1IGYNCjAwMDAwMDIxMzggNjU1MzUgZg0KMDAwMDAwMjEzOSA2NTUzNSBmDQowMDAwMDAyMTQwIDY1NTM1IGYNCjAwMDAwMDIxNDEgNjU1MzUgZg0KMDAwMDAwMjE0MiA2NTUzNSBmDQowMDAwMDAyMTQzIDY1NTM1IGYNCjAwMDAwMDIxNDQgNjU1MzUgZg0KMDAwMDAwMjE0NSA2NTUzNSBmDQowMDAwMDAyMTQ2IDY1NTM1IGYNCjAwMDAwMDIxNDcgNjU1MzUgZg0KMDAwMDAwMjE0OCA2NTUzNSBmDQowMDAwMDAyMTQ5IDY1NTM1IGYNCjAwMDAwMDIxNTAgNjU1MzUgZg0KMDAwMDAwMjE1MSA2NTUzNSBmDQowMDAwMDAyMTUyIDY1NTM1IGYNCjAwMDAwMDIxNTMgNjU1MzUgZg0KMDAwMDAwMjE1NCA2NTUzNSBmDQowMDAwMDAyMTU1IDY1NTM1IGYNCjAwMDAwMDIxNTYgNjU1MzUgZg0KMDAwMDAwMjE1NyA2NTUzNSBmDQowMDAwMDAyMTU4IDY1NTM1IGYNCjAwMDAwMDIxNTkgNjU1MzUgZg0KMDAwMDAwMjE2MCA2NTUzNSBmDQowMDAwMDAyMTYxIDY1NTM1IGYNCjAwMDAwMDIxNjIgNjU1MzUgZg0KMDAwMDAwMjE2MyA2NTUzNSBmDQowMDAwMDAyMTY0IDY1NTM1IGYNCjAwMDAwMDIxNjUgNjU1MzUgZg0KMDAwMDAwMjE2NiA2NTUzNSBmDQowMDAwMDAyMTY3IDY1NTM1IGYNCjAwMDAwMDIxNjggNjU1MzUgZg0KMDAwMDAwMjE2OSA2NTUzNSBmDQowMDAwMDAyMTcwIDY1NTM1IGYNCjAwMDAwMDIxNzEgNjU1MzUgZg0KMDAwMDAwMjE3MiA2NTUzNSBmDQowMDAwMDAyMTczIDY1NTM1IGYNCjAwMDAwMDIxNzQgNjU1MzUgZg0KMDAwMDAwMjE3NSA2NTUzNSBmDQowMDAwMDAyMTc2IDY1NTM1IGYNCjAwMDAwMDIxNzcgNjU1MzUgZg0KMDAwMDAwMjE3OCA2NTUzNSBmDQowMDAwMDAyMTc5IDY1NTM1IGYNCjAwMDAwMDIxODAgNjU1MzUgZg0KMDAwMDAwMjE4MSA2NTUzNSBmDQowMDAwMDAyMTgyIDY1NTM1IGYNCjAwMDAwMDIxODMgNjU1MzUgZg0KMDAwMDAwMjE4NCA2NTUzNSBmDQowMDAwMDAyMTg1IDY1NTM1IGYNCjAwMDAwMDIxODYgNjU1MzUgZg0KMDAwMDAwMjE4NyA2NTUzNSBmDQowMDAwMDAyMTg4IDY1NTM1IGYNCjAwMDAwMDIxODkgNjU1MzUgZg0KMDAwMDAwMjE5MCA2NTUzNSBmDQowMDAwMDAyMTkxIDY1NTM1IGYNCjAwMDAwMDIxOTIgNjU1MzUgZg0KMDAwMDAwMjE5MyA2NTUzNSBmDQowMDAwMDAyMTk0IDY1NTM1IGYNCjAwMDAwMDIxOTUgNjU1MzUgZg0KMDAwMDAwMjE5NiA2NTUzNSBmDQowMDAwMDAyMTk3IDY1NTM1IGYNCjAwMDAwMDIxOTggNjU1MzUgZg0KMDAwMDAwMjE5OSA2NTUzNSBmDQowMDAwMDAyMjAwIDY1NTM1IGYNCjAwMDAwMDIyMDEgNjU1MzUgZg0KMDAwMDAwMjIwMiA2NTUzNSBmDQowMDAwMDAyMjAzIDY1NTM1IGYNCjAwMDAwMDIyMDQgNjU1MzUgZg0KMDAwMDAwMjIwNSA2NTUzNSBmDQowMDAwMDAyMjA2IDY1NTM1IGYNCjAwMDAwMDIyMDcgNjU1MzUgZg0KMDAwMDAwMjIwOCA2NTUzNSBmDQowMDAwMDAyMjA5IDY1NTM1IGYNCjAwMDAwMDIyMTAgNjU1MzUgZg0KMDAwMDAwMjIxMSA2NTUzNSBmDQowMDAwMDAyMjEyIDY1NTM1IGYNCjAwMDAwMDIyMTMgNjU1MzUgZg0KMDAwMDAwMjIxNCA2NTUzNSBmDQowMDAwMDAyMjE1IDY1NTM1IGYNCjAwMDAwMDIyMTYgNjU1MzUgZg0KMDAwMDAwMjIxNyA2NTUzNSBmDQowMDAwMDAyMjE4IDY1NTM1IGYNCjAwMDAwMDIyMTkgNjU1MzUgZg0KMDAwMDAwMjIyMCA2NTUzNSBmDQowMDAwMDAyMjIxIDY1NTM1IGYNCjAwMDAwMDIyMjIgNjU1MzUgZg0KMDAwMDAwMjIyMyA2NTUzNSBmDQowMDAwMDAyMjI0IDY1NTM1IGYNCjAwMDAwMDIyMjUgNjU1MzUgZg0KMDAwMDAwMjIyNiA2NTUzNSBmDQowMDAwMDAyMjI3IDY1NTM1IGYNCjAwMDAwMDIyMjggNjU1MzUgZg0KMDAwMDAwMjIyOSA2NTUzNSBmDQowMDAwMDAyMjMwIDY1NTM1IGYNCjAwMDAwMDIyMzEgNjU1MzUgZg0KMDAwMDAwMjIzMiA2NTUzNSBmDQowMDAwMDAyMjMzIDY1NTM1IGYNCjAwMDAwMDIyMzQgNjU1MzUgZg0KMDAwMDAwMjIzNSA2NTUzNSBmDQowMDAwMDAyMjM2IDY1NTM1IGYNCjAwMDAwMDIyMzcgNjU1MzUgZg0KMDAwMDAwMjIzOCA2NTUzNSBmDQowMDAwMDAyMjM5IDY1NTM1IGYNCjAwMDAwMDIyNDAgNjU1MzUgZg0KMDAwMDAwMjI0MSA2NTUzNSBmDQowMDAwMDAyMjQyIDY1NTM1IGYNCjAwMDAwMDIyNDMgNjU1MzUgZg0KMDAwMDAwMjI0NCA2NTUzNSBmDQowMDAwMDAyMjQ1IDY1NTM1IGYNCjAwMDAwMDIyNDYgNjU1MzUgZg0KMDAwMDAwMjI0NyA2NTUzNSBmDQowMDAwMDAyMjQ4IDY1NTM1IGYNCjAwMDAwMDIyNDkgNjU1MzUgZg0KMDAwMDAwMjI1MCA2NTUzNSBmDQowMDAwMDAyMjUxIDY1NTM1IGYNCjAwMDAwMDIyNTIgNjU1MzUgZg0KMDAwMDAwMjI1MyA2NTUzNSBmDQowMDAwMDAyMjU0IDY1NTM1IGYNCjAwMDAwMDIyNTUgNjU1MzUgZg0KMDAwMDAwMjI1NiA2NTUzNSBmDQowMDAwMDAyMjU3IDY1NTM1IGYNCjAwMDAwMDIyNTggNjU1MzUgZg0KMDAwMDAwMjI1OSA2NTUzNSBmDQowMDAwMDAyMjYwIDY1NTM1IGYNCjAwMDAwMDIyNjEgNjU1MzUgZg0KMDAwMDAwMjI2MiA2NTUzNSBmDQowMDAwMDAyMjYzIDY1NTM1IGYNCjAwMDAwMDIyNjQgNjU1MzUgZg0KMDAwMDAwMjI2NSA2NTUzNSBmDQowMDAwMDAyMjY2IDY1NTM1IGYNCjAwMDAwMDIyNjcgNjU1MzUgZg0KMDAwMDAwMjI2OCA2NTUzNSBmDQowMDAwMDAyMjY5IDY1NTM1IGYNCjAwMDAwMDIyNzAgNjU1MzUgZg0KMDAwMDAwMjI3MSA2NTUzNSBmDQowMDAwMDAyMjcyIDY1NTM1IGYNCjAwMDAwMDIyNzMgNjU1MzUgZg0KMDAwMDAwMjI3NCA2NTUzNSBmDQowMDAwMDAyMjc1IDY1NTM1IGYNCjAwMDAwMDIyNzYgNjU1MzUgZg0KMDAwMDAwMjI3NyA2NTUzNSBmDQowMDAwMDAyMjc4IDY1NTM1IGYNCjAwMDAwMDIyNzkgNjU1MzUgZg0KMDAwMDAwMjI4MCA2NTUzNSBmDQowMDAwMDAyMjgxIDY1NTM1IGYNCjAwMDAwMDIyODIgNjU1MzUgZg0KMDAwMDAwMjI4MyA2NTUzNSBmDQowMDAwMDAyMjg0IDY1NTM1IGYNCjAwMDAwMDIyODUgNjU1MzUgZg0KMDAwMDAwMjI4NiA2NTUzNSBmDQowMDAwMDAyMjg3IDY1NTM1IGYNCjAwMDAwMDIyODggNjU1MzUgZg0KMDAwMDAwMjI4OSA2NTUzNSBmDQowMDAwMDAyMjkwIDY1NTM1IGYNCjAwMDAwMDIyOTEgNjU1MzUgZg0KMDAwMDAwMjI5MiA2NTUzNSBmDQowMDAwMDAyMjkzIDY1NTM1IGYNCjAwMDAwMDIyOTQgNjU1MzUgZg0KMDAwMDAwMjI5NSA2NTUzNSBmDQowMDAwMDAyMjk2IDY1NTM1IGYNCjAwMDAwMDIyOTcgNjU1MzUgZg0KMDAwMDAwMjI5OCA2NTUzNSBmDQowMDAwMDAyMjk5IDY1NTM1IGYNCjAwMDAwMDIzMDAgNjU1MzUgZg0KMDAwMDAwMjMwMSA2NTUzNSBmDQowMDAwMDAyMzAyIDY1NTM1IGYNCjAwMDAwMDIzMDMgNjU1MzUgZg0KMDAwMDAwMjMwNCA2NTUzNSBmDQowMDAwMDAyMzA1IDY1NTM1IGYNCjAwMDAwMDIzMDYgNjU1MzUgZg0KMDAwMDAwMjMwNyA2NTUzNSBmDQowMDAwMDAyMzA4IDY1NTM1IGYNCjAwMDAwMDIzMDkgNjU1MzUgZg0KMDAwMDAwMjMxMCA2NTUzNSBmDQowMDAwMDAyMzExIDY1NTM1IGYNCjAwMDAwMDIzMTIgNjU1MzUgZg0KMDAwMDAwMjMxMyA2NTUzNSBmDQowMDAwMDAyMzE0IDY1NTM1IGYNCjAwMDAwMDIzMTUgNjU1MzUgZg0KMDAwMDAwMjMxNiA2NTUzNSBmDQowMDAwMDAyMzE3IDY1NTM1IGYNCjAwMDAwMDIzMTggNjU1MzUgZg0KMDAwMDAwMjMxOSA2NTUzNSBmDQowMDAwMDAyMzIwIDY1NTM1IGYNCjAwMDAwMDIzMjEgNjU1MzUgZg0KMDAwMDAwMjMyMiA2NTUzNSBmDQowMDAwMDAyMzIzIDY1NTM1IGYNCjAwMDAwMDIzMjQgNjU1MzUgZg0KMDAwMDAwMjMyNSA2NTUzNSBmDQowMDAwMDAyMzI2IDY1NTM1IGYNCjAwMDAwMDIzMjcgNjU1MzUgZg0KMDAwMDAwMjMyOCA2NTUzNSBmDQowMDAwMDAyMzI5IDY1NTM1IGYNCjAwMDAwMDIzMzAgNjU1MzUgZg0KMDAwMDAwMjMzMSA2NTUzNSBmDQowMDAwMDAyMzMyIDY1NTM1IGYNCjAwMDAwMDIzMzMgNjU1MzUgZg0KMDAwMDAwMjMzNCA2NTUzNSBmDQowMDAwMDAyMzM1IDY1NTM1IGYNCjAwMDAwMDIzMzYgNjU1MzUgZg0KMDAwMDAwMjMzNyA2NTUzNSBmDQowMDAwMDAyMzM4IDY1NTM1IGYNCjAwMDAwMDIzMzkgNjU1MzUgZg0KMDAwMDAwMjM0MCA2NTUzNSBmDQowMDAwMDAyMzQxIDY1NTM1IGYNCjAwMDAwMDIzNDIgNjU1MzUgZg0KMDAwMDAwMjM0MyA2NTUzNSBmDQowMDAwMDAyMzQ0IDY1NTM1IGYNCjAwMDAwMDIzNDUgNjU1MzUgZg0KMDAwMDAwMjM0NiA2NTUzNSBmDQowMDAwMDAyMzQ3IDY1NTM1IGYNCjAwMDAwMDIzNDggNjU1MzUgZg0KMDAwMDAwMjM0OSA2NTUzNSBmDQowMDAwMDAyMzUwIDY1NTM1IGYNCjAwMDAwMDIzNTEgNjU1MzUgZg0KMDAwMDAwMjM1MiA2NTUzNSBmDQowMDAwMDAyMzUzIDY1NTM1IGYNCjAwMDAwMDIzNTQgNjU1MzUgZg0KMDAwMDAwMjM1NSA2NTUzNSBmDQowMDAwMDAyMzU2IDY1NTM1IGYNCjAwMDAwMDIzNTcgNjU1MzUgZg0KMDAwMDAwMjM1OCA2NTUzNSBmDQowMDAwMDAyMzU5IDY1NTM1IGYNCjAwMDAwMDIzNjAgNjU1MzUgZg0KMDAwMDAwMjM2MSA2NTUzNSBmDQowMDAwMDAyMzYyIDY1NTM1IGYNCjAwMDAwMDIzNjMgNjU1MzUgZg0KMDAwMDAwMjM2NCA2NTUzNSBmDQowMDAwMDAyMzY1IDY1NTM1IGYNCjAwMDAwMDIzNjYgNjU1MzUgZg0KMDAwMDAwMjM2NyA2NTUzNSBmDQowMDAwMDAyMzY4IDY1NTM1IGYNCjAwMDAwMDIzNjkgNjU1MzUgZg0KMDAwMDAwMjM3MCA2NTUzNSBmDQowMDAwMDAyMzcxIDY1NTM1IGYNCjAwMDAwMDIzNzIgNjU1MzUgZg0KMDAwMDAwMjM3MyA2NTUzNSBmDQowMDAwMDAyMzc0IDY1NTM1IGYNCjAwMDAwMDIzNzUgNjU1MzUgZg0KMDAwMDAwMjM3NiA2NTUzNSBmDQowMDAwMDAyMzc3IDY1NTM1IGYNCjAwMDAwMDIzNzggNjU1MzUgZg0KMDAwMDAwMjM3OSA2NTUzNSBmDQowMDAwMDAyMzgwIDY1NTM1IGYNCjAwMDAwMDIzODEgNjU1MzUgZg0KMDAwMDAwMjM4MiA2NTUzNSBmDQowMDAwMDAyMzgzIDY1NTM1IGYNCjAwMDAwMDIzODQgNjU1MzUgZg0KMDAwMDAwMjM4NSA2NTUzNSBmDQowMDAwMDAyMzg2IDY1NTM1IGYNCjAwMDAwMDIzODcgNjU1MzUgZg0KMDAwMDAwMjM4OCA2NTUzNSBmDQowMDAwMDAyMzg5IDY1NTM1IGYNCjAwMDAwMDIzOTAgNjU1MzUgZg0KMDAwMDAwMjM5MSA2NTUzNSBmDQowMDAwMDAyMzkyIDY1NTM1IGYNCjAwMDAwMDIzOTMgNjU1MzUgZg0KMDAwMDAwMjM5NCA2NTUzNSBmDQowMDAwMDAyMzk1IDY1NTM1IGYNCjAwMDAwMDIzOTYgNjU1MzUgZg0KMDAwMDAwMjM5NyA2NTUzNSBmDQowMDAwMDAyMzk4IDY1NTM1IGYNCjAwMDAwMDIzOTkgNjU1MzUgZg0KMDAwMDAwMjQwMCA2NTUzNSBmDQowMDAwMDAyNDAxIDY1NTM1IGYNCjAwMDAwMDI0MDIgNjU1MzUgZg0KMDAwMDAwMjQwMyA2NTUzNSBmDQowMDAwMDAyNDA0IDY1NTM1IGYNCjAwMDAwMDI0MDUgNjU1MzUgZg0KMDAwMDAwMjQwNiA2NTUzNSBmDQowMDAwMDAyNDA3IDY1NTM1IGYNCjAwMDAwMDI0MDggNjU1MzUgZg0KMDAwMDAwMjQwOSA2NTUzNSBmDQowMDAwMDAyNDEwIDY1NTM1IGYNCjAwMDAwMDI0MTEgNjU1MzUgZg0KMDAwMDAwMjQxMiA2NTUzNSBmDQowMDAwMDAyNDEzIDY1NTM1IGYNCjAwMDAwMDI0MTQgNjU1MzUgZg0KMDAwMDAwMjQxNSA2NTUzNSBmDQowMDAwMDAyNDE2IDY1NTM1IGYNCjAwMDAwMDI0MTcgNjU1MzUgZg0KMDAwMDAwMjQxOCA2NTUzNSBmDQowMDAwMDAyNDE5IDY1NTM1IGYNCjAwMDAwMDI0MjAgNjU1MzUgZg0KMDAwMDAwMjQyMSA2NTUzNSBmDQowMDAwMDAyNDIyIDY1NTM1IGYNCjAwMDAwMDI0MjMgNjU1MzUgZg0KMDAwMDAwMjQyNCA2NTUzNSBmDQowMDAwMDAyNDI1IDY1NTM1IGYNCjAwMDAwMDI0MjYgNjU1MzUgZg0KMDAwMDAwMjQyNyA2NTUzNSBmDQowMDAwMDAyNDI4IDY1NTM1IGYNCjAwMDAwMDI0MjkgNjU1MzUgZg0KMDAwMDAwMjQzMCA2NTUzNSBmDQowMDAwMDAyNDMxIDY1NTM1IGYNCjAwMDAwMDI0MzIgNjU1MzUgZg0KMDAwMDAwMjQzMyA2NTUzNSBmDQowMDAwMDAyNDM0IDY1NTM1IGYNCjAwMDAwMDI0MzUgNjU1MzUgZg0KMDAwMDAwMjQzNiA2NTUzNSBmDQowMDAwMDAyNDM3IDY1NTM1IGYNCjAwMDAwMDI0MzggNjU1MzUgZg0KMDAwMDAwMjQzOSA2NTUzNSBmDQowMDAwMDAyNDQwIDY1NTM1IGYNCjAwMDAwMDI0NDEgNjU1MzUgZg0KMDAwMDAwMjQ0MiA2NTUzNSBmDQowMDAwMDAyNDQzIDY1NTM1IGYNCjAwMDAwMDI0NDQgNjU1MzUgZg0KMDAwMDAwMjQ0NSA2NTUzNSBmDQowMDAwMDAyNDQ2IDY1NTM1IGYNCjAwMDAwMDI0NDcgNjU1MzUgZg0KMDAwMDAwMjQ0OCA2NTUzNSBmDQowMDAwMDAyNDQ5IDY1NTM1IGYNCjAwMDAwMDI0NTAgNjU1MzUgZg0KMDAwMDAwMjQ1MSA2NTUzNSBmDQowMDAwMDAyNDUyIDY1NTM1IGYNCjAwMDAwMDI0NTMgNjU1MzUgZg0KMDAwMDAwMjQ1NCA2NTUzNSBmDQowMDAwMDAyNDU1IDY1NTM1IGYNCjAwMDAwMDI0NTYgNjU1MzUgZg0KMDAwMDAwMjQ1NyA2NTUzNSBmDQowMDAwMDAyNDU4IDY1NTM1IGYNCjAwMDAwMDI0NTkgNjU1MzUgZg0KMDAwMDAwMjQ2MCA2NTUzNSBmDQowMDAwMDAyNDYxIDY1NTM1IGYNCjAwMDAwMDI0NjIgNjU1MzUgZg0KMDAwMDAwMjQ2MyA2NTUzNSBmDQowMDAwMDAyNDY0IDY1NTM1IGYNCjAwMDAwMDI0NjUgNjU1MzUgZg0KMDAwMDAwMjQ2NiA2NTUzNSBmDQowMDAwMDAyNDY3IDY1NTM1IGYNCjAwMDAwMDI0NjggNjU1MzUgZg0KMDAwMDAwMjQ2OSA2NTUzNSBmDQowMDAwMDAyNDcwIDY1NTM1IGYNCjAwMDAwMDI0NzEgNjU1MzUgZg0KMDAwMDAwMjQ3MiA2NTUzNSBmDQowMDAwMDAyNDczIDY1NTM1IGYNCjAwMDAwMDI0NzQgNjU1MzUgZg0KMDAwMDAwMjQ3NSA2NTUzNSBmDQowMDAwMDAyNDc2IDY1NTM1IGYNCjAwMDAwMDI0NzcgNjU1MzUgZg0KMDAwMDAwMjQ3OCA2NTUzNSBmDQowMDAwMDAyNDc5IDY1NTM1IGYNCjAwMDAwMDI0ODAgNjU1MzUgZg0KMDAwMDAwMjQ4MSA2NTUzNSBmDQowMDAwMDAyNDgyIDY1NTM1IGYNCjAwMDAwMDI0ODMgNjU1MzUgZg0KMDAwMDAwMjQ4NCA2NTUzNSBmDQowMDAwMDAyNDg1IDY1NTM1IGYNCjAwMDAwMDI0ODYgNjU1MzUgZg0KMDAwMDAwMjQ4NyA2NTUzNSBmDQowMDAwMDAyNDg4IDY1NTM1IGYNCjAwMDAwMDI0ODkgNjU1MzUgZg0KMDAwMDAwMjQ5MCA2NTUzNSBmDQowMDAwMDAyNDkxIDY1NTM1IGYNCjAwMDAwMDI0OTIgNjU1MzUgZg0KMDAwMDAwMjQ5MyA2NTUzNSBmDQowMDAwMDAyNDk0IDY1NTM1IGYNCjAwMDAwMDI0OTUgNjU1MzUgZg0KMDAwMDAwMjQ5NiA2NTUzNSBmDQowMDAwMDAyNDk3IDY1NTM1IGYNCjAwMDAwMDI0OTggNjU1MzUgZg0KMDAwMDAwMjQ5OSA2NTUzNSBmDQowMDAwMDAyNTAwIDY1NTM1IGYNCjAwMDAwMDI1MDEgNjU1MzUgZg0KMDAwMDAwMjUwMiA2NTUzNSBmDQowMDAwMDAyNTAzIDY1NTM1IGYNCjAwMDAwMDI1MDQgNjU1MzUgZg0KMDAwMDAwMjUwNSA2NTUzNSBmDQowMDAwMDAyNTA2IDY1NTM1IGYNCjAwMDAwMDI1MDcgNjU1MzUgZg0KMDAwMDAwMjUwOCA2NTUzNSBmDQowMDAwMDAyNTA5IDY1NTM1IGYNCjAwMDAwMDI1MTAgNjU1MzUgZg0KMDAwMDAwMjUxMSA2NTUzNSBmDQowMDAwMDAyNTEyIDY1NTM1IGYNCjAwMDAwMDI1MTMgNjU1MzUgZg0KMDAwMDAwMjUxNCA2NTUzNSBmDQowMDAwMDAyNTE1IDY1NTM1IGYNCjAwMDAwMDI1MTYgNjU1MzUgZg0KMDAwMDAwMjUxNyA2NTUzNSBmDQowMDAwMDAyNTE4IDY1NTM1IGYNCjAwMDAwMDI1MTkgNjU1MzUgZg0KMDAwMDAwMjUyMCA2NTUzNSBmDQowMDAwMDAyNTIxIDY1NTM1IGYNCjAwMDAwMDI1MjIgNjU1MzUgZg0KMDAwMDAwMjUyMyA2NTUzNSBmDQowMDAwMDAyNTI0IDY1NTM1IGYNCjAwMDAwMDI1MjUgNjU1MzUgZg0KMDAwMDAwMjUyNiA2NTUzNSBmDQowMDAwMDAyNTI3IDY1NTM1IGYNCjAwMDAwMDI1MjggNjU1MzUgZg0KMDAwMDAwMjUyOSA2NTUzNSBmDQowMDAwMDAyNTMwIDY1NTM1IGYNCjAwMDAwMDI1MzEgNjU1MzUgZg0KMDAwMDAwMjUzMiA2NTUzNSBmDQowMDAwMDAyNTMzIDY1NTM1IGYNCjAwMDAwMDI1MzQgNjU1MzUgZg0KMDAwMDAwMjUzNSA2NTUzNSBmDQowMDAwMDAyNTM2IDY1NTM1IGYNCjAwMDAwMDI1MzcgNjU1MzUgZg0KMDAwMDAwMjUzOCA2NTUzNSBmDQowMDAwMDAyNTM5IDY1NTM1IGYNCjAwMDAwMDI1NDAgNjU1MzUgZg0KMDAwMDAwMjU0MSA2NTUzNSBmDQowMDAwMDAyNTQyIDY1NTM1IGYNCjAwMDAwMDI1NDMgNjU1MzUgZg0KMDAwMDAwMjU0NCA2NTUzNSBmDQowMDAwMDAyNTQ1IDY1NTM1IGYNCjAwMDAwMDI1NDYgNjU1MzUgZg0KMDAwMDAwMjU0NyA2NTUzNSBmDQowMDAwMDAyNTQ4IDY1NTM1IGYNCjAwMDAwMDI1NDkgNjU1MzUgZg0KMDAwMDAwMjU1MCA2NTUzNSBmDQowMDAwMDAyNTUxIDY1NTM1IGYNCjAwMDAwMDI1NTIgNjU1MzUgZg0KMDAwMDAwMjU1MyA2NTUzNSBmDQowMDAwMDAyNTU0IDY1NTM1IGYNCjAwMDAwMDI1NTUgNjU1MzUgZg0KMDAwMDAwMjU1NiA2NTUzNSBmDQowMDAwMDAyNTU3IDY1NTM1IGYNCjAwMDAwMDI1NTggNjU1MzUgZg0KMDAwMDAwMjU1OSA2NTUzNSBmDQowMDAwMDAyNTYwIDY1NTM1IGYNCjAwMDAwMDI1NjEgNjU1MzUgZg0KMDAwMDAwMjU2MiA2NTUzNSBmDQowMDAwMDAyNTYzIDY1NTM1IGYNCjAwMDAwMDI1NjQgNjU1MzUgZg0KMDAwMDAwMjU2NSA2NTUzNSBmDQowMDAwMDAyNTY2IDY1NTM1IGYNCjAwMDAwMDI1NjcgNjU1MzUgZg0KMDAwMDAwMjU2OCA2NTUzNSBmDQowMDAwMDAyNTY5IDY1NTM1IGYNCjAwMDAwMDI1NzAgNjU1MzUgZg0KMDAwMDAwMjU3MSA2NTUzNSBmDQowMDAwMDAyNTcyIDY1NTM1IGYNCjAwMDAwMDI1NzMgNjU1MzUgZg0KMDAwMDAwMjU3NCA2NTUzNSBmDQowMDAwMDAyNTc1IDY1NTM1IGYNCjAwMDAwMDI1NzYgNjU1MzUgZg0KMDAwMDAwMjU3NyA2NTUzNSBmDQowMDAwMDAyNTc4IDY1NTM1IGYNCjAwMDAwMDI1NzkgNjU1MzUgZg0KMDAwMDAwMjU4MCA2NTUzNSBmDQowMDAwMDAyNTgxIDY1NTM1IGYNCjAwMDAwMDI1ODIgNjU1MzUgZg0KMDAwMDAwMjU4MyA2NTUzNSBmDQowMDAwMDAyNTg0IDY1NTM1IGYNCjAwMDAwMDI1ODUgNjU1MzUgZg0KMDAwMDAwMjU4NiA2NTUzNSBmDQowMDAwMDAyNTg3IDY1NTM1IGYNCjAwMDAwMDI1ODggNjU1MzUgZg0KMDAwMDAwMjU4OSA2NTUzNSBmDQowMDAwMDAyNTkwIDY1NTM1IGYNCjAwMDAwMDI1OTEgNjU1MzUgZg0KMDAwMDAwMjU5MiA2NTUzNSBmDQowMDAwMDAyNTkzIDY1NTM1IGYNCjAwMDAwMDI1OTQgNjU1MzUgZg0KMDAwMDAwMjU5NSA2NTUzNSBmDQowMDAwMDAyNTk2IDY1NTM1IGYNCjAwMDAwMDI1OTcgNjU1MzUgZg0KMDAwMDAwMjU5OCA2NTUzNSBmDQowMDAwMDAyNTk5IDY1NTM1IGYNCjAwMDAwMDI2MDAgNjU1MzUgZg0KMDAwMDAwMjYwMSA2NTUzNSBmDQowMDAwMDAyNjAyIDY1NTM1IGYNCjAwMDAwMDI2MDMgNjU1MzUgZg0KMDAwMDAwMjYwNCA2NTUzNSBmDQowMDAwMDAyNjA1IDY1NTM1IGYNCjAwMDAwMDI2MDYgNjU1MzUgZg0KMDAwMDAwMjYwNyA2NTUzNSBmDQowMDAwMDAyNjA4IDY1NTM1IGYNCjAwMDAwMDI2MDkgNjU1MzUgZg0KMDAwMDAwMjYxMCA2NTUzNSBmDQowMDAwMDAyNjExIDY1NTM1IGYNCjAwMDAwMDI2MTIgNjU1MzUgZg0KMDAwMDAwMjYxMyA2NTUzNSBmDQowMDAwMDAyNjE0IDY1NTM1IGYNCjAwMDAwMDI2MTUgNjU1MzUgZg0KMDAwMDAwMjYxNiA2NTUzNSBmDQowMDAwMDAyNjE3IDY1NTM1IGYNCjAwMDAwMDI2MTggNjU1MzUgZg0KMDAwMDAwMjYxOSA2NTUzNSBmDQowMDAwMDAyNjIwIDY1NTM1IGYNCjAwMDAwMDI2MjEgNjU1MzUgZg0KMDAwMDAwMjYyMiA2NTUzNSBmDQowMDAwMDAyNjIzIDY1NTM1IGYNCjAwMDAwMDI2MjQgNjU1MzUgZg0KMDAwMDAwMjYyNSA2NTUzNSBmDQowMDAwMDAyNjI2IDY1NTM1IGYNCjAwMDAwMDI2MjcgNjU1MzUgZg0KMDAwMDAwMjYyOCA2NTUzNSBmDQowMDAwMDAyNjI5IDY1NTM1IGYNCjAwMDAwMDI2MzAgNjU1MzUgZg0KMDAwMDAwMjYzMSA2NTUzNSBmDQowMDAwMDAyNjMyIDY1NTM1IGYNCjAwMDAwMDI2MzMgNjU1MzUgZg0KMDAwMDAwMjYzNCA2NTUzNSBmDQowMDAwMDAyNjM1IDY1NTM1IGYNCjAwMDAwMDI2MzYgNjU1MzUgZg0KMDAwMDAwMjYzNyA2NTUzNSBmDQowMDAwMDAyNjM4IDY1NTM1IGYNCjAwMDAwMDI2MzkgNjU1MzUgZg0KMDAwMDAwMjY0MCA2NTUzNSBmDQowMDAwMDAyNjQxIDY1NTM1IGYNCjAwMDAwMDI2NDIgNjU1MzUgZg0KMDAwMDAwMjY0MyA2NTUzNSBmDQowMDAwMDAyNjQ0IDY1NTM1IGYNCjAwMDAwMDI2NDUgNjU1MzUgZg0KMDAwMDAwMjY0NiA2NTUzNSBmDQowMDAwMDAyNjQ3IDY1NTM1IGYNCjAwMDAwMDI2NDggNjU1MzUgZg0KMDAwMDAwMjY0OSA2NTUzNSBmDQowMDAwMDAyNjUwIDY1NTM1IGYNCjAwMDAwMDI2NTEgNjU1MzUgZg0KMDAwMDAwMjY1MiA2NTUzNSBmDQowMDAwMDAyNjUzIDY1NTM1IGYNCjAwMDAwMDI2NTQgNjU1MzUgZg0KMDAwMDAwMjY1NSA2NTUzNSBmDQowMDAwMDAyNjU2IDY1NTM1IGYNCjAwMDAwMDI2NTcgNjU1MzUgZg0KMDAwMDAwMjY1OCA2NTUzNSBmDQowMDAwMDAyNjU5IDY1NTM1IGYNCjAwMDAwMDI2NjAgNjU1MzUgZg0KMDAwMDAwMjY2MSA2NTUzNSBmDQowMDAwMDAyNjYyIDY1NTM1IGYNCjAwMDAwMDI2NjMgNjU1MzUgZg0KMDAwMDAwMjY2NCA2NTUzNSBmDQowMDAwMDAyNjY1IDY1NTM1IGYNCjAwMDAwMDI2NjYgNjU1MzUgZg0KMDAwMDAwMjY2NyA2NTUzNSBmDQowMDAwMDAyNjY4IDY1NTM1IGYNCjAwMDAwMDI2NjkgNjU1MzUgZg0KMDAwMDAwMjY3MCA2NTUzNSBmDQowMDAwMDAyNjcxIDY1NTM1IGYNCjAwMDAwMDI2NzIgNjU1MzUgZg0KMDAwMDAwMjY3MyA2NTUzNSBmDQowMDAwMDAyNjc0IDY1NTM1IGYNCjAwMDAwMDI2NzUgNjU1MzUgZg0KMDAwMDAwMjY3NiA2NTUzNSBmDQowMDAwMDAyNjc3IDY1NTM1IGYNCjAwMDAwMDI2NzggNjU1MzUgZg0KMDAwMDAwMjY3OSA2NTUzNSBmDQowMDAwMDAyNjgwIDY1NTM1IGYNCjAwMDAwMDI2ODEgNjU1MzUgZg0KMDAwMDAwMjY4MiA2NTUzNSBmDQowMDAwMDAyNjgzIDY1NTM1IGYNCjAwMDAwMDI2ODQgNjU1MzUgZg0KMDAwMDAwMjY4NSA2NTUzNSBmDQowMDAwMDAyNjg2IDY1NTM1IGYNCjAwMDAwMDI2ODcgNjU1MzUgZg0KMDAwMDAwMjY4OCA2NTUzNSBmDQowMDAwMDAyNjg5IDY1NTM1IGYNCjAwMDAwMDI2OTAgNjU1MzUgZg0KMDAwMDAwMjY5MSA2NTUzNSBmDQowMDAwMDAyNjkyIDY1NTM1IGYNCjAwMDAwMDI2OTMgNjU1MzUgZg0KMDAwMDAwMjY5NCA2NTUzNSBmDQowMDAwMDAyNjk1IDY1NTM1IGYNCjAwMDAwMDI2OTYgNjU1MzUgZg0KMDAwMDAwMjY5NyA2NTUzNSBmDQowMDAwMDAyNjk4IDY1NTM1IGYNCjAwMDAwMDI2OTkgNjU1MzUgZg0KMDAwMDAwMjcwMCA2NTUzNSBmDQowMDAwMDAyNzAxIDY1NTM1IGYNCjAwMDAwMDI3MDIgNjU1MzUgZg0KMDAwMDAwMjcwMyA2NTUzNSBmDQowMDAwMDAyNzA0IDY1NTM1IGYNCjAwMDAwMDI3MDUgNjU1MzUgZg0KMDAwMDAwMjcwNiA2NTUzNSBmDQowMDAwMDAyNzA3IDY1NTM1IGYNCjAwMDAwMDI3MDggNjU1MzUgZg0KMDAwMDAwMjcwOSA2NTUzNSBmDQowMDAwMDAyNzEwIDY1NTM1IGYNCjAwMDAwMDI3MTEgNjU1MzUgZg0KMDAwMDAwMjcxMiA2NTUzNSBmDQowMDAwMDAyNzEzIDY1NTM1IGYNCjAwMDAwMDI3MTQgNjU1MzUgZg0KMDAwMDAwMjcxNSA2NTUzNSBmDQowMDAwMDAyNzE2IDY1NTM1IGYNCjAwMDAwMDI3MTcgNjU1MzUgZg0KMDAwMDAwMjcxOCA2NTUzNSBmDQowMDAwMDAyNzE5IDY1NTM1IGYNCjAwMDAwMDI3MjAgNjU1MzUgZg0KMDAwMDAwMjcyMSA2NTUzNSBmDQowMDAwMDAyNzIyIDY1NTM1IGYNCjAwMDAwMDI3MjMgNjU1MzUgZg0KMDAwMDAwMjcyNCA2NTUzNSBmDQowMDAwMDAyNzI1IDY1NTM1IGYNCjAwMDAwMDI3MjYgNjU1MzUgZg0KMDAwMDAwMjcyNyA2NTUzNSBmDQowMDAwMDAyNzI4IDY1NTM1IGYNCjAwMDAwMDI3MjkgNjU1MzUgZg0KMDAwMDAwMjczMCA2NTUzNSBmDQowMDAwMDAyNzMxIDY1NTM1IGYNCjAwMDAwMDI3MzIgNjU1MzUgZg0KMDAwMDAwMjczMyA2NTUzNSBmDQowMDAwMDAyNzM0IDY1NTM1IGYNCjAwMDAwMDI3MzUgNjU1MzUgZg0KMDAwMDAwMjczNiA2NTUzNSBmDQowMDAwMDAyNzM3IDY1NTM1IGYNCjAwMDAwMDI3MzggNjU1MzUgZg0KMDAwMDAwMjczOSA2NTUzNSBmDQowMDAwMDAyNzQwIDY1NTM1IGYNCjAwMDAwMDI3NDEgNjU1MzUgZg0KMDAwMDAwMjc0MiA2NTUzNSBmDQowMDAwMDAyNzQzIDY1NTM1IGYNCjAwMDAwMDI3NDQgNjU1MzUgZg0KMDAwMDAwMjc0NSA2NTUzNSBmDQowMDAwMDAyNzQ2IDY1NTM1IGYNCjAwMDAwMDI3NDcgNjU1MzUgZg0KMDAwMDAwMjc0OCA2NTUzNSBmDQowMDAwMDAyNzQ5IDY1NTM1IGYNCjAwMDAwMDI3NTAgNjU1MzUgZg0KMDAwMDAwMjc1MSA2NTUzNSBmDQowMDAwMDAyNzUyIDY1NTM1IGYNCjAwMDAwMDI3NTMgNjU1MzUgZg0KMDAwMDAwMjc1NCA2NTUzNSBmDQowMDAwMDAyNzU1IDY1NTM1IGYNCjAwMDAwMDI3NTYgNjU1MzUgZg0KMDAwMDAwMjc1NyA2NTUzNSBmDQowMDAwMDAyNzU4IDY1NTM1IGYNCjAwMDAwMDI3NTkgNjU1MzUgZg0KMDAwMDAwMjc2MCA2NTUzNSBmDQowMDAwMDAyNzYxIDY1NTM1IGYNCjAwMDAwMDI3NjIgNjU1MzUgZg0KMDAwMDAwMjc2MyA2NTUzNSBmDQowMDAwMDAyNzY0IDY1NTM1IGYNCjAwMDAwMDI3NjUgNjU1MzUgZg0KMDAwMDAwMjc2NiA2NTUzNSBmDQowMDAwMDAyNzY3IDY1NTM1IGYNCjAwMDAwMDI3NjggNjU1MzUgZg0KMDAwMDAwMjc2OSA2NTUzNSBmDQowMDAwMDAyNzcwIDY1NTM1IGYNCjAwMDAwMDI3NzEgNjU1MzUgZg0KMDAwMDAwMjc3MiA2NTUzNSBmDQowMDAwMDAyNzczIDY1NTM1IGYNCjAwMDAwMDI3NzQgNjU1MzUgZg0KMDAwMDAwMjc3NSA2NTUzNSBmDQowMDAwMDAyNzc2IDY1NTM1IGYNCjAwMDAwMDI3NzcgNjU1MzUgZg0KMDAwMDAwMjc3OCA2NTUzNSBmDQowMDAwMDAyNzc5IDY1NTM1IGYNCjAwMDAwMDI3ODAgNjU1MzUgZg0KMDAwMDAwMjc4MSA2NTUzNSBmDQowMDAwMDAyNzgyIDY1NTM1IGYNCjAwMDAwMDI3ODMgNjU1MzUgZg0KMDAwMDAwMjc4NCA2NTUzNSBmDQowMDAwMDAyNzg1IDY1NTM1IGYNCjAwMDAwMDI3ODYgNjU1MzUgZg0KMDAwMDAwMjc4NyA2NTUzNSBmDQowMDAwMDAyNzg4IDY1NTM1IGYNCjAwMDAwMDI3ODkgNjU1MzUgZg0KMDAwMDAwMjc5MCA2NTUzNSBmDQowMDAwMDAyNzkxIDY1NTM1IGYNCjAwMDAwMDI3OTIgNjU1MzUgZg0KMDAwMDAwMjc5MyA2NTUzNSBmDQowMDAwMDAyNzk0IDY1NTM1IGYNCjAwMDAwMDI3OTUgNjU1MzUgZg0KMDAwMDAwMjc5NiA2NTUzNSBmDQowMDAwMDAyNzk3IDY1NTM1IGYNCjAwMDAwMDI3OTggNjU1MzUgZg0KMDAwMDAwMjc5OSA2NTUzNSBmDQowMDAwMDAyODAwIDY1NTM1IGYNCjAwMDAwMDI4MDEgNjU1MzUgZg0KMDAwMDAwMjgwMiA2NTUzNSBmDQowMDAwMDAyODAzIDY1NTM1IGYNCjAwMDAwMDI4MDQgNjU1MzUgZg0KMDAwMDAwMjgwNSA2NTUzNSBmDQowMDAwMDAyODA2IDY1NTM1IGYNCjAwMDAwMDI4MDcgNjU1MzUgZg0KMDAwMDAwMjgwOCA2NTUzNSBmDQowMDAwMDAyODA5IDY1NTM1IGYNCjAwMDAwMDI4MTAgNjU1MzUgZg0KMDAwMDAwMjgxMSA2NTUzNSBmDQowMDAwMDAyODEyIDY1NTM1IGYNCjAwMDAwMDI4MTMgNjU1MzUgZg0KMDAwMDAwMjgxNCA2NTUzNSBmDQowMDAwMDAyODE1IDY1NTM1IGYNCjAwMDAwMDI4MTYgNjU1MzUgZg0KMDAwMDAwMjgxNyA2NTUzNSBmDQowMDAwMDAyODE4IDY1NTM1IGYNCjAwMDAwMDI4MTkgNjU1MzUgZg0KMDAwMDAwMjgyMCA2NTUzNSBmDQowMDAwMDAyODIxIDY1NTM1IGYNCjAwMDAwMDI4MjIgNjU1MzUgZg0KMDAwMDAwMjgyMyA2NTUzNSBmDQowMDAwMDAyODI0IDY1NTM1IGYNCjAwMDAwMDI4MjUgNjU1MzUgZg0KMDAwMDAwMjgyNiA2NTUzNSBmDQowMDAwMDAyODI3IDY1NTM1IGYNCjAwMDAwMDI4MjggNjU1MzUgZg0KMDAwMDAwMjgyOSA2NTUzNSBmDQowMDAwMDAyODMwIDY1NTM1IGYNCjAwMDAwMDI4MzEgNjU1MzUgZg0KMDAwMDAwMjgzMiA2NTUzNSBmDQowMDAwMDAyODMzIDY1NTM1IGYNCjAwMDAwMDI4MzQgNjU1MzUgZg0KMDAwMDAwMjgzNSA2NTUzNSBmDQowMDAwMDAyODM2IDY1NTM1IGYNCjAwMDAwMDI4MzcgNjU1MzUgZg0KMDAwMDAwMjgzOCA2NTUzNSBmDQowMDAwMDAyODM5IDY1NTM1IGYNCjAwMDAwMDI4NDAgNjU1MzUgZg0KMDAwMDAwMjg0MSA2NTUzNSBmDQowMDAwMDAyODQyIDY1NTM1IGYNCjAwMDAwMDI4NDMgNjU1MzUgZg0KMDAwMDAwMjg0NCA2NTUzNSBmDQowMDAwMDAyODQ1IDY1NTM1IGYNCjAwMDAwMDI4NDYgNjU1MzUgZg0KMDAwMDAwMjg0NyA2NTUzNSBmDQowMDAwMDAyODQ4IDY1NTM1IGYNCjAwMDAwMDI4NDkgNjU1MzUgZg0KMDAwMDAwMjg1MCA2NTUzNSBmDQowMDAwMDAyODUxIDY1NTM1IGYNCjAwMDAwMDI4NTIgNjU1MzUgZg0KMDAwMDAwMjg1MyA2NTUzNSBmDQowMDAwMDAyODU0IDY1NTM1IGYNCjAwMDAwMDI4NTUgNjU1MzUgZg0KMDAwMDAwMjg1NiA2NTUzNSBmDQowMDAwMDAyODU3IDY1NTM1IGYNCjAwMDAwMDI4NTggNjU1MzUgZg0KMDAwMDAwMjg1OSA2NTUzNSBmDQowMDAwMDAyODYwIDY1NTM1IGYNCjAwMDAwMDI4NjEgNjU1MzUgZg0KMDAwMDAwMjg2MiA2NTUzNSBmDQowMDAwMDAyODYzIDY1NTM1IGYNCjAwMDAwMDI4NjQgNjU1MzUgZg0KMDAwMDAwMjg2NSA2NTUzNSBmDQowMDAwMDAyODY2IDY1NTM1IGYNCjAwMDAwMDI4NjcgNjU1MzUgZg0KMDAwMDAwMjg2OCA2NTUzNSBmDQowMDAwMDAyODY5IDY1NTM1IGYNCjAwMDAwMDI4NzAgNjU1MzUgZg0KMDAwMDAwMjg3MSA2NTUzNSBmDQowMDAwMDAyODcyIDY1NTM1IGYNCjAwMDAwMDI4NzMgNjU1MzUgZg0KMDAwMDAwMjg3NCA2NTUzNSBmDQowMDAwMDAyODc1IDY1NTM1IGYNCjAwMDAwMDI4NzYgNjU1MzUgZg0KMDAwMDAwMjg3NyA2NTUzNSBmDQowMDAwMDAyODc4IDY1NTM1IGYNCjAwMDAwMDI4NzkgNjU1MzUgZg0KMDAwMDAwMjg4MCA2NTUzNSBmDQowMDAwMDAyODgxIDY1NTM1IGYNCjAwMDAwMDI4ODIgNjU1MzUgZg0KMDAwMDAwMjg4MyA2NTUzNSBmDQowMDAwMDAyODg0IDY1NTM1IGYNCjAwMDAwMDI4ODUgNjU1MzUgZg0KMDAwMDAwMjg4NiA2NTUzNSBmDQowMDAwMDAyODg3IDY1NTM1IGYNCjAwMDAwMDI4ODggNjU1MzUgZg0KMDAwMDAwMjg4OSA2NTUzNSBmDQowMDAwMDAyODkwIDY1NTM1IGYNCjAwMDAwMDI4OTEgNjU1MzUgZg0KMDAwMDAwMjg5MiA2NTUzNSBmDQowMDAwMDAyODkzIDY1NTM1IGYNCjAwMDAwMDI4OTQgNjU1MzUgZg0KMDAwMDAwMjg5NSA2NTUzNSBmDQowMDAwMDAyODk2IDY1NTM1IGYNCjAwMDAwMDI4OTcgNjU1MzUgZg0KMDAwMDAwMjg5OCA2NTUzNSBmDQowMDAwMDAyODk5IDY1NTM1IGYNCjAwMDAwMDI5MDAgNjU1MzUgZg0KMDAwMDAwMjkwMSA2NTUzNSBmDQowMDAwMDAyOTAyIDY1NTM1IGYNCjAwMDAwMDI5MDMgNjU1MzUgZg0KMDAwMDAwMjkwNCA2NTUzNSBmDQowMDAwMDAyOTA1IDY1NTM1IGYNCjAwMDAwMDI5MDYgNjU1MzUgZg0KMDAwMDAwMjkwNyA2NTUzNSBmDQowMDAwMDAyOTA4IDY1NTM1IGYNCjAwMDAwMDI5MDkgNjU1MzUgZg0KMDAwMDAwMjkxMCA2NTUzNSBmDQowMDAwMDAyOTExIDY1NTM1IGYNCjAwMDAwMDI5MTIgNjU1MzUgZg0KMDAwMDAwMjkxMyA2NTUzNSBmDQowMDAwMDAyOTE0IDY1NTM1IGYNCjAwMDAwMDI5MTUgNjU1MzUgZg0KMDAwMDAwMjkxNiA2NTUzNSBmDQowMDAwMDAyOTE3IDY1NTM1IGYNCjAwMDAwMDI5MTggNjU1MzUgZg0KMDAwMDAwMjkxOSA2NTUzNSBmDQowMDAwMDAyOTIwIDY1NTM1IGYNCjAwMDAwMDI5MjEgNjU1MzUgZg0KMDAwMDAwMjkyMiA2NTUzNSBmDQowMDAwMDAyOTIzIDY1NTM1IGYNCjAwMDAwMDI5MjQgNjU1MzUgZg0KMDAwMDAwMjkyNSA2NTUzNSBmDQowMDAwMDAyOTI2IDY1NTM1IGYNCjAwMDAwMDI5MjcgNjU1MzUgZg0KMDAwMDAwMjkyOCA2NTUzNSBmDQowMDAwMDAyOTI5IDY1NTM1IGYNCjAwMDAwMDI5MzAgNjU1MzUgZg0KMDAwMDAwMjkzMSA2NTUzNSBmDQowMDAwMDAyOTMyIDY1NTM1IGYNCjAwMDAwMDI5MzMgNjU1MzUgZg0KMDAwMDAwMjkzNCA2NTUzNSBmDQowMDAwMDAyOTM1IDY1NTM1IGYNCjAwMDAwMDI5MzYgNjU1MzUgZg0KMDAwMDAwMjkzNyA2NTUzNSBmDQowMDAwMDAyOTM4IDY1NTM1IGYNCjAwMDAwMDI5MzkgNjU1MzUgZg0KMDAwMDAwMjk0MCA2NTUzNSBmDQowMDAwMDAyOTQxIDY1NTM1IGYNCjAwMDAwMDI5NDIgNjU1MzUgZg0KMDAwMDAwMjk0MyA2NTUzNSBmDQowMDAwMDAyOTQ0IDY1NTM1IGYNCjAwMDAwMDI5NDUgNjU1MzUgZg0KMDAwMDAwMjk0NiA2NTUzNSBmDQowMDAwMDAyOTQ3IDY1NTM1IGYNCjAwMDAwMDI5NDggNjU1MzUgZg0KMDAwMDAwMjk0OSA2NTUzNSBmDQowMDAwMDAyOTUwIDY1NTM1IGYNCjAwMDAwMDI5NTEgNjU1MzUgZg0KMDAwMDAwMjk1MiA2NTUzNSBmDQowMDAwMDAyOTUzIDY1NTM1IGYNCjAwMDAwMDI5NTQgNjU1MzUgZg0KMDAwMDAwMjk1NSA2NTUzNSBmDQowMDAwMDAyOTU2IDY1NTM1IGYNCjAwMDAwMDI5NTcgNjU1MzUgZg0KMDAwMDAwMjk1OCA2NTUzNSBmDQowMDAwMDAyOTU5IDY1NTM1IGYNCjAwMDAwMDI5NjAgNjU1MzUgZg0KMDAwMDAwMjk2MSA2NTUzNSBmDQowMDAwMDAyOTYyIDY1NTM1IGYNCjAwMDAwMDI5NjMgNjU1MzUgZg0KMDAwMDAwMjk2NCA2NTUzNSBmDQowMDAwMDAyOTY1IDY1NTM1IGYNCjAwMDAwMDI5NjYgNjU1MzUgZg0KMDAwMDAwMjk2NyA2NTUzNSBmDQowMDAwMDAyOTY4IDY1NTM1IGYNCjAwMDAwMDI5NjkgNjU1MzUgZg0KMDAwMDAwMjk3MCA2NTUzNSBmDQowMDAwMDAyOTcxIDY1NTM1IGYNCjAwMDAwMDI5NzIgNjU1MzUgZg0KMDAwMDAwMjk3MyA2NTUzNSBmDQowMDAwMDAyOTc0IDY1NTM1IGYNCjAwMDAwMDI5NzUgNjU1MzUgZg0KMDAwMDAwMjk3NiA2NTUzNSBmDQowMDAwMDAyOTc3IDY1NTM1IGYNCjAwMDAwMDI5NzggNjU1MzUgZg0KMDAwMDAwMjk3OSA2NTUzNSBmDQowMDAwMDAyOTgwIDY1NTM1IGYNCjAwMDAwMDI5ODEgNjU1MzUgZg0KMDAwMDAwMjk4MiA2NTUzNSBmDQowMDAwMDAyOTgzIDY1NTM1IGYNCjAwMDAwMDI5ODQgNjU1MzUgZg0KMDAwMDAwMjk4NSA2NTUzNSBmDQowMDAwMDAyOTg2IDY1NTM1IGYNCjAwMDAwMDI5ODcgNjU1MzUgZg0KMDAwMDAwMjk4OCA2NTUzNSBmDQowMDAwMDAyOTg5IDY1NTM1IGYNCjAwMDAwMDI5OTAgNjU1MzUgZg0KMDAwMDAwMjk5MSA2NTUzNSBmDQowMDAwMDAyOTkyIDY1NTM1IGYNCjAwMDAwMDI5OTMgNjU1MzUgZg0KMDAwMDAwMjk5NCA2NTUzNSBmDQowMDAwMDAyOTk1IDY1NTM1IGYNCjAwMDAwMDI5OTYgNjU1MzUgZg0KMDAwMDAwMjk5NyA2NTUzNSBmDQowMDAwMDAyOTk4IDY1NTM1IGYNCjAwMDAwMDI5OTkgNjU1MzUgZg0KMDAwMDAwMzAwMCA2NTUzNSBmDQowMDAwMDAzMDAxIDY1NTM1IGYNCjAwMDAwMDMwMDIgNjU1MzUgZg0KMDAwMDAwMzAwMyA2NTUzNSBmDQowMDAwMDAzMDA0IDY1NTM1IGYNCjAwMDAwMDMwMDUgNjU1MzUgZg0KMDAwMDAwMzAwNiA2NTUzNSBmDQowMDAwMDAzMDA3IDY1NTM1IGYNCjAwMDAwMDMwMDggNjU1MzUgZg0KMDAwMDAwMzAwOSA2NTUzNSBmDQowMDAwMDAzMDEwIDY1NTM1IGYNCjAwMDAwMDMwMTEgNjU1MzUgZg0KMDAwMDAwMzAxMiA2NTUzNSBmDQowMDAwMDAzMDEzIDY1NTM1IGYNCjAwMDAwMDMwMTQgNjU1MzUgZg0KMDAwMDAwMzAxNSA2NTUzNSBmDQowMDAwMDAzMDE2IDY1NTM1IGYNCjAwMDAwMDMwMTcgNjU1MzUgZg0KMDAwMDAwMzAxOCA2NTUzNSBmDQowMDAwMDAzMDE5IDY1NTM1IGYNCjAwMDAwMDMwMjAgNjU1MzUgZg0KMDAwMDAwMzAyMSA2NTUzNSBmDQowMDAwMDAzMDIyIDY1NTM1IGYNCjAwMDAwMDMwMjMgNjU1MzUgZg0KMDAwMDAwMzAyNCA2NTUzNSBmDQowMDAwMDAzMDI1IDY1NTM1IGYNCjAwMDAwMDMwMjYgNjU1MzUgZg0KMDAwMDAwMzAyNyA2NTUzNSBmDQowMDAwMDAzMDI4IDY1NTM1IGYNCjAwMDAwMDMwMjkgNjU1MzUgZg0KMDAwMDAwMzAzMCA2NTUzNSBmDQowMDAwMDAzMDMxIDY1NTM1IGYNCjAwMDAwMDMwMzIgNjU1MzUgZg0KMDAwMDAwMzAzMyA2NTUzNSBmDQowMDAwMDAzMDM0IDY1NTM1IGYNCjAwMDAwMDMwMzUgNjU1MzUgZg0KMDAwMDAwMzAzNiA2NTUzNSBmDQowMDAwMDAzMDM3IDY1NTM1IGYNCjAwMDAwMDMwMzggNjU1MzUgZg0KMDAwMDAwMzAzOSA2NTUzNSBmDQowMDAwMDAzMDQwIDY1NTM1IGYNCjAwMDAwMDMwNDEgNjU1MzUgZg0KMDAwMDAwMzA0MiA2NTUzNSBmDQowMDAwMDAzMDQzIDY1NTM1IGYNCjAwMDAwMDMwNDQgNjU1MzUgZg0KMDAwMDAwMzA0NSA2NTUzNSBmDQowMDAwMDAzMDQ2IDY1NTM1IGYNCjAwMDAwMDMwNDcgNjU1MzUgZg0KMDAwMDAwMzA0OCA2NTUzNSBmDQowMDAwMDAzMDQ5IDY1NTM1IGYNCjAwMDAwMDMwNTAgNjU1MzUgZg0KMDAwMDAwMzA1MSA2NTUzNSBmDQowMDAwMDAzMDUyIDY1NTM1IGYNCjAwMDAwMDMwNTMgNjU1MzUgZg0KMDAwMDAwMzA1NCA2NTUzNSBmDQowMDAwMDAzMDU1IDY1NTM1IGYNCjAwMDAwMDMwNTYgNjU1MzUgZg0KMDAwMDAwMzA1NyA2NTUzNSBmDQowMDAwMDAzMDU4IDY1NTM1IGYNCjAwMDAwMDMwNTkgNjU1MzUgZg0KMDAwMDAwMzA2MCA2NTUzNSBmDQowMDAwMDAzMDYxIDY1NTM1IGYNCjAwMDAwMDMwNjIgNjU1MzUgZg0KMDAwMDAwMzA2MyA2NTUzNSBmDQowMDAwMDAzMDY0IDY1NTM1IGYNCjAwMDAwMDMwNjUgNjU1MzUgZg0KMDAwMDAwMzA2NiA2NTUzNSBmDQowMDAwMDAzMDY3IDY1NTM1IGYNCjAwMDAwMDMwNjggNjU1MzUgZg0KMDAwMDAwMzA2OSA2NTUzNSBmDQowMDAwMDAzMDcwIDY1NTM1IGYNCjAwMDAwMDMwNzEgNjU1MzUgZg0KMDAwMDAwMzA3MiA2NTUzNSBmDQowMDAwMDAzMDczIDY1NTM1IGYNCjAwMDAwMDMwNzQgNjU1MzUgZg0KMDAwMDAwMzA3NSA2NTUzNSBmDQowMDAwMDAzMDc2IDY1NTM1IGYNCjAwMDAwMDMwNzcgNjU1MzUgZg0KMDAwMDAwMzA3OCA2NTUzNSBmDQowMDAwMDAzMDc5IDY1NTM1IGYNCjAwMDAwMDMwODAgNjU1MzUgZg0KMDAwMDAwMzA4MSA2NTUzNSBmDQowMDAwMDAzMDgyIDY1NTM1IGYNCjAwMDAwMDMwODMgNjU1MzUgZg0KMDAwMDAwMzA4NCA2NTUzNSBmDQowMDAwMDAzMDg1IDY1NTM1IGYNCjAwMDAwMDMwODYgNjU1MzUgZg0KMDAwMDAwMzA4NyA2NTUzNSBmDQowMDAwMDAzMDg4IDY1NTM1IGYNCjAwMDAwMDMwODkgNjU1MzUgZg0KMDAwMDAwMzA5MCA2NTUzNSBmDQowMDAwMDAzMDkxIDY1NTM1IGYNCjAwMDAwMDMwOTIgNjU1MzUgZg0KMDAwMDAwMzA5MyA2NTUzNSBmDQowMDAwMDAzMDk0IDY1NTM1IGYNCjAwMDAwMDMwOTUgNjU1MzUgZg0KMDAwMDAwMzA5NiA2NTUzNSBmDQowMDAwMDAzMDk3IDY1NTM1IGYNCjAwMDAwMDMwOTggNjU1MzUgZg0KMDAwMDAwMzA5OSA2NTUzNSBmDQowMDAwMDAzMTAwIDY1NTM1IGYNCjAwMDAwMDMxMDEgNjU1MzUgZg0KMDAwMDAwMzEwMiA2NTUzNSBmDQowMDAwMDAzMTAzIDY1NTM1IGYNCjAwMDAwMDMxMDQgNjU1MzUgZg0KMDAwMDAwMzEwNSA2NTUzNSBmDQowMDAwMDAzMTA2IDY1NTM1IGYNCjAwMDAwMDMxMDcgNjU1MzUgZg0KMDAwMDAwMzEwOCA2NTUzNSBmDQowMDAwMDAzMTA5IDY1NTM1IGYNCjAwMDAwMDMxMTAgNjU1MzUgZg0KMDAwMDAwMzExMSA2NTUzNSBmDQowMDAwMDAzMTEyIDY1NTM1IGYNCjAwMDAwMDMxMTMgNjU1MzUgZg0KMDAwMDAwMzExNCA2NTUzNSBmDQowMDAwMDAzMTE1IDY1NTM1IGYNCjAwMDAwMDMxMTYgNjU1MzUgZg0KMDAwMDAwMzExNyA2NTUzNSBmDQowMDAwMDAzMTE4IDY1NTM1IGYNCjAwMDAwMDMxMTkgNjU1MzUgZg0KMDAwMDAwMzEyMCA2NTUzNSBmDQowMDAwMDAzMTIxIDY1NTM1IGYNCjAwMDAwMDMxMjIgNjU1MzUgZg0KMDAwMDAwMzEyMyA2NTUzNSBmDQowMDAwMDAzMTI0IDY1NTM1IGYNCjAwMDAwMDMxMjUgNjU1MzUgZg0KMDAwMDAwMzEyNiA2NTUzNSBmDQowMDAwMDAzMTI3IDY1NTM1IGYNCjAwMDAwMDMxMjggNjU1MzUgZg0KMDAwMDAwMzEyOSA2NTUzNSBmDQowMDAwMDAzMTMwIDY1NTM1IGYNCjAwMDAwMDMxMzEgNjU1MzUgZg0KMDAwMDAwMzEzMiA2NTUzNSBmDQowMDAwMDAzMTMzIDY1NTM1IGYNCjAwMDAwMDMxMzQgNjU1MzUgZg0KMDAwMDAwMzEzNSA2NTUzNSBmDQowMDAwMDAzMTM2IDY1NTM1IGYNCjAwMDAwMDMxMzcgNjU1MzUgZg0KMDAwMDAwMzEzOCA2NTUzNSBmDQowMDAwMDAzMTM5IDY1NTM1IGYNCjAwMDAwMDMxNDAgNjU1MzUgZg0KMDAwMDAwMzE0MSA2NTUzNSBmDQowMDAwMDAzMTQyIDY1NTM1IGYNCjAwMDAwMDMxNDMgNjU1MzUgZg0KMDAwMDAwMzE0NCA2NTUzNSBmDQowMDAwMDAzMTQ1IDY1NTM1IGYNCjAwMDAwMDMxNDYgNjU1MzUgZg0KMDAwMDAwMzE0NyA2NTUzNSBmDQowMDAwMDAzMTQ4IDY1NTM1IGYNCjAwMDAwMDMxNDkgNjU1MzUgZg0KMDAwMDAwMzE1MCA2NTUzNSBmDQowMDAwMDAzMTUxIDY1NTM1IGYNCjAwMDAwMDMxNTIgNjU1MzUgZg0KMDAwMDAwMzE1MyA2NTUzNSBmDQowMDAwMDAzMTU0IDY1NTM1IGYNCjAwMDAwMDMxNTUgNjU1MzUgZg0KMDAwMDAwMzE1NiA2NTUzNSBmDQowMDAwMDAzMTU3IDY1NTM1IGYNCjAwMDAwMDMxNTggNjU1MzUgZg0KMDAwMDAwMzE1OSA2NTUzNSBmDQowMDAwMDAzMTYwIDY1NTM1IGYNCjAwMDAwMDMxNjEgNjU1MzUgZg0KMDAwMDAwMzE2MiA2NTUzNSBmDQowMDAwMDAzMTYzIDY1NTM1IGYNCjAwMDAwMDMxNjQgNjU1MzUgZg0KMDAwMDAwMzE2NSA2NTUzNSBmDQowMDAwMDAzMTY2IDY1NTM1IGYNCjAwMDAwMDMxNjcgNjU1MzUgZg0KMDAwMDAwMzE2OCA2NTUzNSBmDQowMDAwMDAzMTY5IDY1NTM1IGYNCjAwMDAwMDMxNzAgNjU1MzUgZg0KMDAwMDAwMzE3MSA2NTUzNSBmDQowMDAwMDAzMTcyIDY1NTM1IGYNCjAwMDAwMDMxNzMgNjU1MzUgZg0KMDAwMDAwMzE3NCA2NTUzNSBmDQowMDAwMDAzMTc1IDY1NTM1IGYNCjAwMDAwMDMxNzYgNjU1MzUgZg0KMDAwMDAwMzE3NyA2NTUzNSBmDQowMDAwMDAzMTc4IDY1NTM1IGYNCjAwMDAwMDMxNzkgNjU1MzUgZg0KMDAwMDAwMzE4MCA2NTUzNSBmDQowMDAwMDAzMTgxIDY1NTM1IGYNCjAwMDAwMDMxODIgNjU1MzUgZg0KMDAwMDAwMzE4MyA2NTUzNSBmDQowMDAwMDAzMTg0IDY1NTM1IGYNCjAwMDAwMDMxODUgNjU1MzUgZg0KMDAwMDAwMzE4NiA2NTUzNSBmDQowMDAwMDAzMTg3IDY1NTM1IGYNCjAwMDAwMDMxODggNjU1MzUgZg0KMDAwMDAwMzE4OSA2NTUzNSBmDQowMDAwMDAzMTkwIDY1NTM1IGYNCjAwMDAwMDMxOTEgNjU1MzUgZg0KMDAwMDAwMzE5MiA2NTUzNSBmDQowMDAwMDAzMTkzIDY1NTM1IGYNCjAwMDAwMDMxOTQgNjU1MzUgZg0KMDAwMDAwMzE5NSA2NTUzNSBmDQowMDAwMDAzMTk2IDY1NTM1IGYNCjAwMDAwMDMxOTcgNjU1MzUgZg0KMDAwMDAwMzE5OCA2NTUzNSBmDQowMDAwMDAzMTk5IDY1NTM1IGYNCjAwMDAwMDMyMDAgNjU1MzUgZg0KMDAwMDAwMzIwMSA2NTUzNSBmDQowMDAwMDAzMjAyIDY1NTM1IGYNCjAwMDAwMDMyMDMgNjU1MzUgZg0KMDAwMDAwMzIwNCA2NTUzNSBmDQowMDAwMDAzMjA1IDY1NTM1IGYNCjAwMDAwMDMyMDYgNjU1MzUgZg0KMDAwMDAwMzIwNyA2NTUzNSBmDQowMDAwMDAzMjA4IDY1NTM1IGYNCjAwMDAwMDMyMDkgNjU1MzUgZg0KMDAwMDAwMzIxMCA2NTUzNSBmDQowMDAwMDAzMjExIDY1NTM1IGYNCjAwMDAwMDMyMTIgNjU1MzUgZg0KMDAwMDAwMzIxMyA2NTUzNSBmDQowMDAwMDAzMjE0IDY1NTM1IGYNCjAwMDAwMDMyMTUgNjU1MzUgZg0KMDAwMDAwMzIxNiA2NTUzNSBmDQowMDAwMDAzMjE3IDY1NTM1IGYNCjAwMDAwMDMyMTggNjU1MzUgZg0KMDAwMDAwMzIxOSA2NTUzNSBmDQowMDAwMDAzMjIwIDY1NTM1IGYNCjAwMDAwMDMyMjEgNjU1MzUgZg0KMDAwMDAwMzIyMiA2NTUzNSBmDQowMDAwMDAzMjIzIDY1NTM1IGYNCjAwMDAwMDMyMjQgNjU1MzUgZg0KMDAwMDAwMzIyNSA2NTUzNSBmDQowMDAwMDAzMjI2IDY1NTM1IGYNCjAwMDAwMDMyMjcgNjU1MzUgZg0KMDAwMDAwMzIyOCA2NTUzNSBmDQowMDAwMDAzMjI5IDY1NTM1IGYNCjAwMDAwMDMyMzAgNjU1MzUgZg0KMDAwMDAwMzIzMSA2NTUzNSBmDQowMDAwMDAzMjMyIDY1NTM1IGYNCjAwMDAwMDMyMzMgNjU1MzUgZg0KMDAwMDAwMzIzNCA2NTUzNSBmDQowMDAwMDAzMjM1IDY1NTM1IGYNCjAwMDAwMDMyMzYgNjU1MzUgZg0KMDAwMDAwMzIzNyA2NTUzNSBmDQowMDAwMDAzMjM4IDY1NTM1IGYNCjAwMDAwMDMyMzkgNjU1MzUgZg0KMDAwMDAwMzI0MCA2NTUzNSBmDQowMDAwMDAzMjQxIDY1NTM1IGYNCjAwMDAwMDMyNDIgNjU1MzUgZg0KMDAwMDAwMzI0MyA2NTUzNSBmDQowMDAwMDAzMjQ0IDY1NTM1IGYNCjAwMDAwMDMyNDUgNjU1MzUgZg0KMDAwMDAwMzI0NiA2NTUzNSBmDQowMDAwMDAzMjQ3IDY1NTM1IGYNCjAwMDAwMDMyNDggNjU1MzUgZg0KMDAwMDAwMzI0OSA2NTUzNSBmDQowMDAwMDAzMjUwIDY1NTM1IGYNCjAwMDAwMDMyNTEgNjU1MzUgZg0KMDAwMDAwMzI1MiA2NTUzNSBmDQowMDAwMDAzMjUzIDY1NTM1IGYNCjAwMDAwMDMyNTQgNjU1MzUgZg0KMDAwMDAwMzI1NSA2NTUzNSBmDQowMDAwMDAzMjU2IDY1NTM1IGYNCjAwMDAwMDMyNTcgNjU1MzUgZg0KMDAwMDAwMzI1OCA2NTUzNSBmDQowMDAwMDAzMjU5IDY1NTM1IGYNCjAwMDAwMDMyNjAgNjU1MzUgZg0KMDAwMDAwMzI2MSA2NTUzNSBmDQowMDAwMDAzMjYyIDY1NTM1IGYNCjAwMDAwMDMyNjMgNjU1MzUgZg0KMDAwMDAwMzI2NCA2NTUzNSBmDQowMDAwMDAzMjY1IDY1NTM1IGYNCjAwMDAwMDMyNjYgNjU1MzUgZg0KMDAwMDAwMzI2NyA2NTUzNSBmDQowMDAwMDAzMjY4IDY1NTM1IGYNCjAwMDAwMDMyNjkgNjU1MzUgZg0KMDAwMDAwMzI3MCA2NTUzNSBmDQowMDAwMDAzMjcxIDY1NTM1IGYNCjAwMDAwMDMyNzIgNjU1MzUgZg0KMDAwMDAwMzI3MyA2NTUzNSBmDQowMDAwMDAzMjc0IDY1NTM1IGYNCjAwMDAwMDMyNzUgNjU1MzUgZg0KMDAwMDAwMzI3NiA2NTUzNSBmDQowMDAwMDAzMjc3IDY1NTM1IGYNCjAwMDAwMDMyNzggNjU1MzUgZg0KMDAwMDAwMzI3OSA2NTUzNSBmDQowMDAwMDAzMjgwIDY1NTM1IGYNCjAwMDAwMDMyODEgNjU1MzUgZg0KMDAwMDAwMzI4MiA2NTUzNSBmDQowMDAwMDAzMjgzIDY1NTM1IGYNCjAwMDAwMDMyODQgNjU1MzUgZg0KMDAwMDAwMzI4NSA2NTUzNSBmDQowMDAwMDAzMjg2IDY1NTM1IGYNCjAwMDAwMDMyODcgNjU1MzUgZg0KMDAwMDAwMzI4OCA2NTUzNSBmDQowMDAwMDAzMjg5IDY1NTM1IGYNCjAwMDAwMDMyOTAgNjU1MzUgZg0KMDAwMDAwMzI5MSA2NTUzNSBmDQowMDAwMDAzMjkyIDY1NTM1IGYNCjAwMDAwMDMyOTMgNjU1MzUgZg0KMDAwMDAwMzI5NCA2NTUzNSBmDQowMDAwMDAzMjk1IDY1NTM1IGYNCjAwMDAwMDMyOTYgNjU1MzUgZg0KMDAwMDAwMzI5NyA2NTUzNSBmDQowMDAwMDAzMjk4IDY1NTM1IGYNCjAwMDAwMDMyOTkgNjU1MzUgZg0KMDAwMDAwMzMwMCA2NTUzNSBmDQowMDAwMDAzMzAxIDY1NTM1IGYNCjAwMDAwMDMzMDIgNjU1MzUgZg0KMDAwMDAwMzMwMyA2NTUzNSBmDQowMDAwMDAzMzA0IDY1NTM1IGYNCjAwMDAwMDMzMDUgNjU1MzUgZg0KMDAwMDAwMzMwNiA2NTUzNSBmDQowMDAwMDAzMzA3IDY1NTM1IGYNCjAwMDAwMDMzMDggNjU1MzUgZg0KMDAwMDAwMzMwOSA2NTUzNSBmDQowMDAwMDAzMzEwIDY1NTM1IGYNCjAwMDAwMDMzMTEgNjU1MzUgZg0KMDAwMDAwMzMxMiA2NTUzNSBmDQowMDAwMDAzMzEzIDY1NTM1IGYNCjAwMDAwMDMzMTQgNjU1MzUgZg0KMDAwMDAwMzMxNSA2NTUzNSBmDQowMDAwMDAzMzE2IDY1NTM1IGYNCjAwMDAwMDMzMTcgNjU1MzUgZg0KMDAwMDAwMzMxOCA2NTUzNSBmDQowMDAwMDAzMzE5IDY1NTM1IGYNCjAwMDAwMDMzMjAgNjU1MzUgZg0KMDAwMDAwMzMyMSA2NTUzNSBmDQowMDAwMDAzMzIyIDY1NTM1IGYNCjAwMDAwMDMzMjMgNjU1MzUgZg0KMDAwMDAwMzMyNCA2NTUzNSBmDQowMDAwMDAzMzI1IDY1NTM1IGYNCjAwMDAwMDMzMjYgNjU1MzUgZg0KMDAwMDAwMzMyNyA2NTUzNSBmDQowMDAwMDAzMzI4IDY1NTM1IGYNCjAwMDAwMDMzMjkgNjU1MzUgZg0KMDAwMDAwMzMzMCA2NTUzNSBmDQowMDAwMDAzMzMxIDY1NTM1IGYNCjAwMDAwMDMzMzIgNjU1MzUgZg0KMDAwMDAwMzMzMyA2NTUzNSBmDQowMDAwMDAzMzM0IDY1NTM1IGYNCjAwMDAwMDMzMzUgNjU1MzUgZg0KMDAwMDAwMzMzNiA2NTUzNSBmDQowMDAwMDAzMzM3IDY1NTM1IGYNCjAwMDAwMDMzMzggNjU1MzUgZg0KMDAwMDAwMzMzOSA2NTUzNSBmDQowMDAwMDAzMzQwIDY1NTM1IGYNCjAwMDAwMDMzNDEgNjU1MzUgZg0KMDAwMDAwMzM0MiA2NTUzNSBmDQowMDAwMDAzMzQzIDY1NTM1IGYNCjAwMDAwMDMzNDQgNjU1MzUgZg0KMDAwMDAwMzM0NSA2NTUzNSBmDQowMDAwMDAzMzQ2IDY1NTM1IGYNCjAwMDAwMDMzNDcgNjU1MzUgZg0KMDAwMDAwMzM0OCA2NTUzNSBmDQowMDAwMDAzMzQ5IDY1NTM1IGYNCjAwMDAwMDMzNTAgNjU1MzUgZg0KMDAwMDAwMzM1MSA2NTUzNSBmDQowMDAwMDAzMzUyIDY1NTM1IGYNCjAwMDAwMDMzNTMgNjU1MzUgZg0KMDAwMDAwMzM1NCA2NTUzNSBmDQowMDAwMDAzMzU1IDY1NTM1IGYNCjAwMDAwMDMzNTYgNjU1MzUgZg0KMDAwMDAwMzM1NyA2NTUzNSBmDQowMDAwMDAzMzU4IDY1NTM1IGYNCjAwMDAwMDMzNTkgNjU1MzUgZg0KMDAwMDAwMzM2MCA2NTUzNSBmDQowMDAwMDAzMzYxIDY1NTM1IGYNCjAwMDAwMDMzNjIgNjU1MzUgZg0KMDAwMDAwMzM2MyA2NTUzNSBmDQowMDAwMDAzMzY0IDY1NTM1IGYNCjAwMDAwMDMzNjUgNjU1MzUgZg0KMDAwMDAwMzM2NiA2NTUzNSBmDQowMDAwMDAzMzY3IDY1NTM1IGYNCjAwMDAwMDMzNjggNjU1MzUgZg0KMDAwMDAwMzM2OSA2NTUzNSBmDQowMDAwMDAzMzcwIDY1NTM1IGYNCjAwMDAwMDMzNzEgNjU1MzUgZg0KMDAwMDAwMzM3MiA2NTUzNSBmDQowMDAwMDAzMzczIDY1NTM1IGYNCjAwMDAwMDMzNzQgNjU1MzUgZg0KMDAwMDAwMzM3NSA2NTUzNSBmDQowMDAwMDAzMzc2IDY1NTM1IGYNCjAwMDAwMDMzNzcgNjU1MzUgZg0KMDAwMDAwMzM3OCA2NTUzNSBmDQowMDAwMDAzMzc5IDY1NTM1IGYNCjAwMDAwMDMzODAgNjU1MzUgZg0KMDAwMDAwMzM4MSA2NTUzNSBmDQowMDAwMDAzMzgyIDY1NTM1IGYNCjAwMDAwMDMzODMgNjU1MzUgZg0KMDAwMDAwMzM4NCA2NTUzNSBmDQowMDAwMDAzMzg1IDY1NTM1IGYNCjAwMDAwMDMzODYgNjU1MzUgZg0KMDAwMDAwMzM4NyA2NTUzNSBmDQowMDAwMDAzMzg4IDY1NTM1IGYNCjAwMDAwMDMzODkgNjU1MzUgZg0KMDAwMDAwMzM5MCA2NTUzNSBmDQowMDAwMDAzMzkxIDY1NTM1IGYNCjAwMDAwMDMzOTIgNjU1MzUgZg0KMDAwMDAwMzM5MyA2NTUzNSBmDQowMDAwMDAzMzk0IDY1NTM1IGYNCjAwMDAwMDMzOTUgNjU1MzUgZg0KMDAwMDAwMzM5NiA2NTUzNSBmDQowMDAwMDAzMzk3IDY1NTM1IGYNCjAwMDAwMDMzOTggNjU1MzUgZg0KMDAwMDAwMzM5OSA2NTUzNSBmDQowMDAwMDAzNDAwIDY1NTM1IGYNCjAwMDAwMDM0MDEgNjU1MzUgZg0KMDAwMDAwMzQwMiA2NTUzNSBmDQowMDAwMDAzNDAzIDY1NTM1IGYNCjAwMDAwMDM0MDQgNjU1MzUgZg0KMDAwMDAwMzQwNSA2NTUzNSBmDQowMDAwMDAzNDA2IDY1NTM1IGYNCjAwMDAwMDM0MDcgNjU1MzUgZg0KMDAwMDAwMzQwOCA2NTUzNSBmDQowMDAwMDAzNDA5IDY1NTM1IGYNCjAwMDAwMDM0MTAgNjU1MzUgZg0KMDAwMDAwMzQxMSA2NTUzNSBmDQowMDAwMDAzNDEyIDY1NTM1IGYNCjAwMDAwMDM0MTMgNjU1MzUgZg0KMDAwMDAwMzQxNCA2NTUzNSBmDQowMDAwMDAzNDE1IDY1NTM1IGYNCjAwMDAwMDM0MTYgNjU1MzUgZg0KMDAwMDAwMzQxNyA2NTUzNSBmDQowMDAwMDAzNDE4IDY1NTM1IGYNCjAwMDAwMDM0MTkgNjU1MzUgZg0KMDAwMDAwMzQyMCA2NTUzNSBmDQowMDAwMDAzNDIxIDY1NTM1IGYNCjAwMDAwMDM0MjIgNjU1MzUgZg0KMDAwMDAwMzQyMyA2NTUzNSBmDQowMDAwMDAzNDI0IDY1NTM1IGYNCjAwMDAwMDM0MjUgNjU1MzUgZg0KMDAwMDAwMzQyNiA2NTUzNSBmDQowMDAwMDAzNDI3IDY1NTM1IGYNCjAwMDAwMDM0MjggNjU1MzUgZg0KMDAwMDAwMzQyOSA2NTUzNSBmDQowMDAwMDAzNDMwIDY1NTM1IGYNCjAwMDAwMDM0MzEgNjU1MzUgZg0KMDAwMDAwMzQzMiA2NTUzNSBmDQowMDAwMDAzNDMzIDY1NTM1IGYNCjAwMDAwMDM0MzQgNjU1MzUgZg0KMDAwMDAwMzQzNSA2NTUzNSBmDQowMDAwMDAzNDM2IDY1NTM1IGYNCjAwMDAwMDM0MzcgNjU1MzUgZg0KMDAwMDAwMzQzOCA2NTUzNSBmDQowMDAwMDAzNDM5IDY1NTM1IGYNCjAwMDAwMDM0NDAgNjU1MzUgZg0KMDAwMDAwMzQ0MSA2NTUzNSBmDQowMDAwMDAzNDQyIDY1NTM1IGYNCjAwMDAwMDM0NDMgNjU1MzUgZg0KMDAwMDAwMzQ0NCA2NTUzNSBmDQowMDAwMDAzNDQ1IDY1NTM1IGYNCjAwMDAwMDM0NDYgNjU1MzUgZg0KMDAwMDAwMzQ0NyA2NTUzNSBmDQowMDAwMDAzNDQ4IDY1NTM1IGYNCjAwMDAwMDM0NDkgNjU1MzUgZg0KMDAwMDAwMzQ1MCA2NTUzNSBmDQowMDAwMDAzNDUxIDY1NTM1IGYNCjAwMDAwMDM0NTIgNjU1MzUgZg0KMDAwMDAwMzQ1MyA2NTUzNSBmDQowMDAwMDAzNDU0IDY1NTM1IGYNCjAwMDAwMDM0NTUgNjU1MzUgZg0KMDAwMDAwMzQ1NiA2NTUzNSBmDQowMDAwMDAzNDU3IDY1NTM1IGYNCjAwMDAwMDM0NTggNjU1MzUgZg0KMDAwMDAwMzQ1OSA2NTUzNSBmDQowMDAwMDAzNDYwIDY1NTM1IGYNCjAwMDAwMDM0NjEgNjU1MzUgZg0KMDAwMDAwMzQ2MiA2NTUzNSBmDQowMDAwMDAzNDYzIDY1NTM1IGYNCjAwMDAwMDM0NjQgNjU1MzUgZg0KMDAwMDAwMzQ2NSA2NTUzNSBmDQowMDAwMDAzNDY2IDY1NTM1IGYNCjAwMDAwMDM0NjcgNjU1MzUgZg0KMDAwMDAwMzQ2OCA2NTUzNSBmDQowMDAwMDAzNDY5IDY1NTM1IGYNCjAwMDAwMDM0NzAgNjU1MzUgZg0KMDAwMDAwMzQ3MSA2NTUzNSBmDQowMDAwMDAzNDcyIDY1NTM1IGYNCjAwMDAwMDM0NzMgNjU1MzUgZg0KMDAwMDAwMzQ3NCA2NTUzNSBmDQowMDAwMDAzNDc1IDY1NTM1IGYNCjAwMDAwMDM0NzYgNjU1MzUgZg0KMDAwMDAwMzQ3NyA2NTUzNSBmDQowMDAwMDAzNDc4IDY1NTM1IGYNCjAwMDAwMDM0NzkgNjU1MzUgZg0KMDAwMDAwMzQ4MCA2NTUzNSBmDQowMDAwMDAzNDgxIDY1NTM1IGYNCjAwMDAwMDM0ODIgNjU1MzUgZg0KMDAwMDAwMzQ4MyA2NTUzNSBmDQowMDAwMDAzNDg0IDY1NTM1IGYNCjAwMDAwMDM0ODUgNjU1MzUgZg0KMDAwMDAwMzQ4NiA2NTUzNSBmDQowMDAwMDAzNDg3IDY1NTM1IGYNCjAwMDAwMDM0ODggNjU1MzUgZg0KMDAwMDAwMzQ4OSA2NTUzNSBmDQowMDAwMDAzNDkwIDY1NTM1IGYNCjAwMDAwMDM0OTEgNjU1MzUgZg0KMDAwMDAwMzQ5MiA2NTUzNSBmDQowMDAwMDAzNDkzIDY1NTM1IGYNCjAwMDAwMDM0OTQgNjU1MzUgZg0KMDAwMDAwMzQ5NSA2NTUzNSBmDQowMDAwMDAzNDk2IDY1NTM1IGYNCjAwMDAwMDM0OTcgNjU1MzUgZg0KMDAwMDAwMzQ5OCA2NTUzNSBmDQowMDAwMDAzNDk5IDY1NTM1IGYNCjAwMDAwMDM1MDAgNjU1MzUgZg0KMDAwMDAwMzUwMSA2NTUzNSBmDQowMDAwMDAzNTAyIDY1NTM1IGYNCjAwMDAwMDM1MDMgNjU1MzUgZg0KMDAwMDAwMzUwNCA2NTUzNSBmDQowMDAwMDAzNTA1IDY1NTM1IGYNCjAwMDAwMDM1MDYgNjU1MzUgZg0KMDAwMDAwMzUwNyA2NTUzNSBmDQowMDAwMDAzNTA4IDY1NTM1IGYNCjAwMDAwMDM1MDkgNjU1MzUgZg0KMDAwMDAwMzUxMCA2NTUzNSBmDQowMDAwMDAzNTExIDY1NTM1IGYNCjAwMDAwMDM1MTIgNjU1MzUgZg0KMDAwMDAwMzUxMyA2NTUzNSBmDQowMDAwMDAzNTE0IDY1NTM1IGYNCjAwMDAwMDM1MTUgNjU1MzUgZg0KMDAwMDAwMzUxNiA2NTUzNSBmDQowMDAwMDAzNTE3IDY1NTM1IGYNCjAwMDAwMDM1MTggNjU1MzUgZg0KMDAwMDAwMzUxOSA2NTUzNSBmDQowMDAwMDAzNTIwIDY1NTM1IGYNCjAwMDAwMDM1MjEgNjU1MzUgZg0KMDAwMDAwMzUyMiA2NTUzNSBmDQowMDAwMDAzNTIzIDY1NTM1IGYNCjAwMDAwMDM1MjQgNjU1MzUgZg0KMDAwMDAwMzUyNSA2NTUzNSBmDQowMDAwMDAzNTI2IDY1NTM1IGYNCjAwMDAwMDM1MjcgNjU1MzUgZg0KMDAwMDAwMzUyOCA2NTUzNSBmDQowMDAwMDAzNTI5IDY1NTM1IGYNCjAwMDAwMDM1MzAgNjU1MzUgZg0KMDAwMDAwMzUzMSA2NTUzNSBmDQowMDAwMDAzNTMyIDY1NTM1IGYNCjAwMDAwMDM1MzMgNjU1MzUgZg0KMDAwMDAwMzUzNCA2NTUzNSBmDQowMDAwMDAzNTM1IDY1NTM1IGYNCjAwMDAwMDM1MzYgNjU1MzUgZg0KMDAwMDAwMzUzNyA2NTUzNSBmDQowMDAwMDAzNTM4IDY1NTM1IGYNCjAwMDAwMDM1MzkgNjU1MzUgZg0KMDAwMDAwMzU0MCA2NTUzNSBmDQowMDAwMDAzNTQxIDY1NTM1IGYNCjAwMDAwMDM1NDIgNjU1MzUgZg0KMDAwMDAwMzU0MyA2NTUzNSBmDQowMDAwMDAzNTQ0IDY1NTM1IGYNCjAwMDAwMDM1NDUgNjU1MzUgZg0KMDAwMDAwMzU0NiA2NTUzNSBmDQowMDAwMDAzNTQ3IDY1NTM1IGYNCjAwMDAwMDM1NDggNjU1MzUgZg0KMDAwMDAwMzU0OSA2NTUzNSBmDQowMDAwMDAzNTUwIDY1NTM1IGYNCjAwMDAwMDM1NTEgNjU1MzUgZg0KMDAwMDAwMzU1MiA2NTUzNSBmDQowMDAwMDAzNTUzIDY1NTM1IGYNCjAwMDAwMDM1NTQgNjU1MzUgZg0KMDAwMDAwMzU1NSA2NTUzNSBmDQowMDAwMDAzNTU2IDY1NTM1IGYNCjAwMDAwMDM1NTcgNjU1MzUgZg0KMDAwMDAwMzU1OCA2NTUzNSBmDQowMDAwMDAzNTU5IDY1NTM1IGYNCjAwMDAwMDM1NjAgNjU1MzUgZg0KMDAwMDAwMzU2MSA2NTUzNSBmDQowMDAwMDAzNTYyIDY1NTM1IGYNCjAwMDAwMDM1NjMgNjU1MzUgZg0KMDAwMDAwMzU2NCA2NTUzNSBmDQowMDAwMDAzNTY1IDY1NTM1IGYNCjAwMDAwMDM1NjYgNjU1MzUgZg0KMDAwMDAwMzU2NyA2NTUzNSBmDQowMDAwMDAzNTY4IDY1NTM1IGYNCjAwMDAwMDM1NjkgNjU1MzUgZg0KMDAwMDAwMzU3MCA2NTUzNSBmDQowMDAwMDAzNTcxIDY1NTM1IGYNCjAwMDAwMDM1NzIgNjU1MzUgZg0KMDAwMDAwMzU3MyA2NTUzNSBmDQowMDAwMDAzNTc0IDY1NTM1IGYNCjAwMDAwMDM1NzUgNjU1MzUgZg0KMDAwMDAwMzU3NiA2NTUzNSBmDQowMDAwMDAzNTc3IDY1NTM1IGYNCjAwMDAwMDM1NzggNjU1MzUgZg0KMDAwMDAwMzU3OSA2NTUzNSBmDQowMDAwMDAzNTgwIDY1NTM1IGYNCjAwMDAwMDM1ODEgNjU1MzUgZg0KMDAwMDAwMzU4MiA2NTUzNSBmDQowMDAwMDAzNTgzIDY1NTM1IGYNCjAwMDAwMDM1ODQgNjU1MzUgZg0KMDAwMDAwMzU4NSA2NTUzNSBmDQowMDAwMDAzNTg2IDY1NTM1IGYNCjAwMDAwMDM1ODcgNjU1MzUgZg0KMDAwMDAwMzU4OCA2NTUzNSBmDQowMDAwMDAzNTg5IDY1NTM1IGYNCjAwMDAwMDM1OTAgNjU1MzUgZg0KMDAwMDAwMzU5MSA2NTUzNSBmDQowMDAwMDAzNTkyIDY1NTM1IGYNCjAwMDAwMDM1OTMgNjU1MzUgZg0KMDAwMDAwMzU5NCA2NTUzNSBmDQowMDAwMDAzNTk1IDY1NTM1IGYNCjAwMDAwMDM1OTYgNjU1MzUgZg0KMDAwMDAwMzU5NyA2NTUzNSBmDQowMDAwMDAzNTk4IDY1NTM1IGYNCjAwMDAwMDM1OTkgNjU1MzUgZg0KMDAwMDAwMzYwMCA2NTUzNSBmDQowMDAwMDAzNjAxIDY1NTM1IGYNCjAwMDAwMDM2MDIgNjU1MzUgZg0KMDAwMDAwMzYwMyA2NTUzNSBmDQowMDAwMDAzNjA0IDY1NTM1IGYNCjAwMDAwMDM2MDUgNjU1MzUgZg0KMDAwMDAwMzYwNiA2NTUzNSBmDQowMDAwMDAzNjA3IDY1NTM1IGYNCjAwMDAwMDM2MDggNjU1MzUgZg0KMDAwMDAwMzYwOSA2NTUzNSBmDQowMDAwMDAzNjEwIDY1NTM1IGYNCjAwMDAwMDM2MTEgNjU1MzUgZg0KMDAwMDAwMzYxMiA2NTUzNSBmDQowMDAwMDAzNjEzIDY1NTM1IGYNCjAwMDAwMDM2MTQgNjU1MzUgZg0KMDAwMDAwMzYxNSA2NTUzNSBmDQowMDAwMDAzNjE2IDY1NTM1IGYNCjAwMDAwMDM2MTcgNjU1MzUgZg0KMDAwMDAwMzYxOCA2NTUzNSBmDQowMDAwMDAzNjE5IDY1NTM1IGYNCjAwMDAwMDM2MjAgNjU1MzUgZg0KMDAwMDAwMzYyMSA2NTUzNSBmDQowMDAwMDAzNjIyIDY1NTM1IGYNCjAwMDAwMDM2MjMgNjU1MzUgZg0KMDAwMDAwMzYyNCA2NTUzNSBmDQowMDAwMDAzNjI1IDY1NTM1IGYNCjAwMDAwMDM2MjYgNjU1MzUgZg0KMDAwMDAwMzYyNyA2NTUzNSBmDQowMDAwMDAzNjI4IDY1NTM1IGYNCjAwMDAwMDM2MjkgNjU1MzUgZg0KMDAwMDAwMzYzMCA2NTUzNSBmDQowMDAwMDAzNjMxIDY1NTM1IGYNCjAwMDAwMDM2MzIgNjU1MzUgZg0KMDAwMDAwMzYzMyA2NTUzNSBmDQowMDAwMDAzNjM0IDY1NTM1IGYNCjAwMDAwMDM2MzUgNjU1MzUgZg0KMDAwMDAwMzYzNiA2NTUzNSBmDQowMDAwMDAzNjM3IDY1NTM1IGYNCjAwMDAwMDM2MzggNjU1MzUgZg0KMDAwMDAwMzYzOSA2NTUzNSBmDQowMDAwMDAzNjQwIDY1NTM1IGYNCjAwMDAwMDM2NDEgNjU1MzUgZg0KMDAwMDAwMzY0MiA2NTUzNSBmDQowMDAwMDAzNjQzIDY1NTM1IGYNCjAwMDAwMDM2NDQgNjU1MzUgZg0KMDAwMDAwMzY0NSA2NTUzNSBmDQowMDAwMDAzNjQ2IDY1NTM1IGYNCjAwMDAwMDM2NDcgNjU1MzUgZg0KMDAwMDAwMzY0OCA2NTUzNSBmDQowMDAwMDAzNjQ5IDY1NTM1IGYNCjAwMDAwMDM2NTAgNjU1MzUgZg0KMDAwMDAwMzY1MSA2NTUzNSBmDQowMDAwMDAzNjUyIDY1NTM1IGYNCjAwMDAwMDM2NTMgNjU1MzUgZg0KMDAwMDAwMzY1NCA2NTUzNSBmDQowMDAwMDAzNjU1IDY1NTM1IGYNCjAwMDAwMDM2NTYgNjU1MzUgZg0KMDAwMDAwMzY1NyA2NTUzNSBmDQowMDAwMDAzNjU4IDY1NTM1IGYNCjAwMDAwMDM2NTkgNjU1MzUgZg0KMDAwMDAwMzY2MCA2NTUzNSBmDQowMDAwMDAzNjYxIDY1NTM1IGYNCjAwMDAwMDM2NjIgNjU1MzUgZg0KMDAwMDAwMzY2MyA2NTUzNSBmDQowMDAwMDAzNjY0IDY1NTM1IGYNCjAwMDAwMDM2NjUgNjU1MzUgZg0KMDAwMDAwMzY2NiA2NTUzNSBmDQowMDAwMDAzNjY3IDY1NTM1IGYNCjAwMDAwMDM2NjggNjU1MzUgZg0KMDAwMDAwMzY2OSA2NTUzNSBmDQowMDAwMDAzNjcwIDY1NTM1IGYNCjAwMDAwMDM2NzEgNjU1MzUgZg0KMDAwMDAwMzY3MiA2NTUzNSBmDQowMDAwMDAzNjczIDY1NTM1IGYNCjAwMDAwMDM2NzQgNjU1MzUgZg0KMDAwMDAwMzY3NSA2NTUzNSBmDQowMDAwMDAzNjc2IDY1NTM1IGYNCjAwMDAwMDM2NzcgNjU1MzUgZg0KMDAwMDAwMzY3OCA2NTUzNSBmDQowMDAwMDAzNjc5IDY1NTM1IGYNCjAwMDAwMDM2ODAgNjU1MzUgZg0KMDAwMDAwMzY4MSA2NTUzNSBmDQowMDAwMDAzNjgyIDY1NTM1IGYNCjAwMDAwMDM2ODMgNjU1MzUgZg0KMDAwMDAwMzY4NCA2NTUzNSBmDQowMDAwMDAzNjg1IDY1NTM1IGYNCjAwMDAwMDM2ODYgNjU1MzUgZg0KMDAwMDAwMzY4NyA2NTUzNSBmDQowMDAwMDAzNjg4IDY1NTM1IGYNCjAwMDAwMDM2ODkgNjU1MzUgZg0KMDAwMDAwMzY5MCA2NTUzNSBmDQowMDAwMDAzNjkxIDY1NTM1IGYNCjAwMDAwMDM2OTIgNjU1MzUgZg0KMDAwMDAwMzY5MyA2NTUzNSBmDQowMDAwMDAzNjk0IDY1NTM1IGYNCjAwMDAwMDM2OTUgNjU1MzUgZg0KMDAwMDAwMzY5NiA2NTUzNSBmDQowMDAwMDAzNjk3IDY1NTM1IGYNCjAwMDAwMDM2OTggNjU1MzUgZg0KMDAwMDAwMzY5OSA2NTUzNSBmDQowMDAwMDAzNzAwIDY1NTM1IGYNCjAwMDAwMDM3MDEgNjU1MzUgZg0KMDAwMDAwMzcwMiA2NTUzNSBmDQowMDAwMDAzNzAzIDY1NTM1IGYNCjAwMDAwMDM3MDQgNjU1MzUgZg0KMDAwMDAwMzcwNSA2NTUzNSBmDQowMDAwMDAzNzA2IDY1NTM1IGYNCjAwMDAwMDM3MDcgNjU1MzUgZg0KMDAwMDAwMzcwOCA2NTUzNSBmDQowMDAwMDAzNzA5IDY1NTM1IGYNCjAwMDAwMDM3MTAgNjU1MzUgZg0KMDAwMDAwMzcxMSA2NTUzNSBmDQowMDAwMDAzNzEyIDY1NTM1IGYNCjAwMDAwMDM3MTMgNjU1MzUgZg0KMDAwMDAwMzcxNCA2NTUzNSBmDQowMDAwMDAzNzE1IDY1NTM1IGYNCjAwMDAwMDM3MTYgNjU1MzUgZg0KMDAwMDAwMzcxNyA2NTUzNSBmDQowMDAwMDAzNzE4IDY1NTM1IGYNCjAwMDAwMDM3MTkgNjU1MzUgZg0KMDAwMDAwMzcyMCA2NTUzNSBmDQowMDAwMDAzNzIxIDY1NTM1IGYNCjAwMDAwMDM3MjIgNjU1MzUgZg0KMDAwMDAwMzcyMyA2NTUzNSBmDQowMDAwMDAzNzI0IDY1NTM1IGYNCjAwMDAwMDM3MjUgNjU1MzUgZg0KMDAwMDAwMzcyNiA2NTUzNSBmDQowMDAwMDAzNzI3IDY1NTM1IGYNCjAwMDAwMDM3MjggNjU1MzUgZg0KMDAwMDAwMzcyOSA2NTUzNSBmDQowMDAwMDAzNzMwIDY1NTM1IGYNCjAwMDAwMDM3MzEgNjU1MzUgZg0KMDAwMDAwMzczMiA2NTUzNSBmDQowMDAwMDAzNzMzIDY1NTM1IGYNCjAwMDAwMDM3MzQgNjU1MzUgZg0KMDAwMDAwMzczNSA2NTUzNSBmDQowMDAwMDAzNzM2IDY1NTM1IGYNCjAwMDAwMDM3MzcgNjU1MzUgZg0KMDAwMDAwMzczOCA2NTUzNSBmDQowMDAwMDAzNzM5IDY1NTM1IGYNCjAwMDAwMDM3NDAgNjU1MzUgZg0KMDAwMDAwMzc0MSA2NTUzNSBmDQowMDAwMDAzNzQyIDY1NTM1IGYNCjAwMDAwMDM3NDMgNjU1MzUgZg0KMDAwMDAwMzc0NCA2NTUzNSBmDQowMDAwMDAzNzQ1IDY1NTM1IGYNCjAwMDAwMDM3NDYgNjU1MzUgZg0KMDAwMDAwMzc0NyA2NTUzNSBmDQowMDAwMDAzNzQ4IDY1NTM1IGYNCjAwMDAwMDM3NDkgNjU1MzUgZg0KMDAwMDAwMzc1MCA2NTUzNSBmDQowMDAwMDAzNzUxIDY1NTM1IGYNCjAwMDAwMDM3NTIgNjU1MzUgZg0KMDAwMDAwMzc1MyA2NTUzNSBmDQowMDAwMDAzNzU0IDY1NTM1IGYNCjAwMDAwMDM3NTUgNjU1MzUgZg0KMDAwMDAwMzc1NiA2NTUzNSBmDQowMDAwMDAzNzU3IDY1NTM1IGYNCjAwMDAwMDM3NTggNjU1MzUgZg0KMDAwMDAwMzc1OSA2NTUzNSBmDQowMDAwMDAzNzYwIDY1NTM1IGYNCjAwMDAwMDM3NjEgNjU1MzUgZg0KMDAwMDAwMzc2MiA2NTUzNSBmDQowMDAwMDAzNzYzIDY1NTM1IGYNCjAwMDAwMDM3NjQgNjU1MzUgZg0KMDAwMDAwMzc2NSA2NTUzNSBmDQowMDAwMDAzNzY2IDY1NTM1IGYNCjAwMDAwMDM3NjcgNjU1MzUgZg0KMDAwMDAwMzc2OCA2NTUzNSBmDQowMDAwMDAzNzY5IDY1NTM1IGYNCjAwMDAwMDM3NzAgNjU1MzUgZg0KMDAwMDAwMzc3MSA2NTUzNSBmDQowMDAwMDAzNzcyIDY1NTM1IGYNCjAwMDAwMDM3NzMgNjU1MzUgZg0KMDAwMDAwMzc3NCA2NTUzNSBmDQowMDAwMDAzNzc1IDY1NTM1IGYNCjAwMDAwMDM3NzYgNjU1MzUgZg0KMDAwMDAwMzc3NyA2NTUzNSBmDQowMDAwMDAzNzc4IDY1NTM1IGYNCjAwMDAwMDM3NzkgNjU1MzUgZg0KMDAwMDAwMzc4MCA2NTUzNSBmDQowMDAwMDAzNzgxIDY1NTM1IGYNCjAwMDAwMDM3ODIgNjU1MzUgZg0KMDAwMDAwMzc4MyA2NTUzNSBmDQowMDAwMDAzNzg0IDY1NTM1IGYNCjAwMDAwMDM3ODUgNjU1MzUgZg0KMDAwMDAwMzc4NiA2NTUzNSBmDQowMDAwMDAzNzg3IDY1NTM1IGYNCjAwMDAwMDM3ODggNjU1MzUgZg0KMDAwMDAwMzc4OSA2NTUzNSBmDQowMDAwMDAzNzkwIDY1NTM1IGYNCjAwMDAwMDM3OTEgNjU1MzUgZg0KMDAwMDAwMzc5MiA2NTUzNSBmDQowMDAwMDAzNzkzIDY1NTM1IGYNCjAwMDAwMDM3OTQgNjU1MzUgZg0KMDAwMDAwMzc5NSA2NTUzNSBmDQowMDAwMDAzNzk2IDY1NTM1IGYNCjAwMDAwMDM3OTcgNjU1MzUgZg0KMDAwMDAwMzc5OCA2NTUzNSBmDQowMDAwMDAzNzk5IDY1NTM1IGYNCjAwMDAwMDM4MDAgNjU1MzUgZg0KMDAwMDAwMzgwMSA2NTUzNSBmDQowMDAwMDAzODAyIDY1NTM1IGYNCjAwMDAwMDM4MDMgNjU1MzUgZg0KMDAwMDAwMzgwNCA2NTUzNSBmDQowMDAwMDAzODA1IDY1NTM1IGYNCjAwMDAwMDM4MDYgNjU1MzUgZg0KMDAwMDAwMzgwNyA2NTUzNSBmDQowMDAwMDAzODA4IDY1NTM1IGYNCjAwMDAwMDM4MDkgNjU1MzUgZg0KMDAwMDAwMzgxMCA2NTUzNSBmDQowMDAwMDAzODExIDY1NTM1IGYNCjAwMDAwMDM4MTIgNjU1MzUgZg0KMDAwMDAwMzgxMyA2NTUzNSBmDQowMDAwMDAzODE0IDY1NTM1IGYNCjAwMDAwMDM4MTUgNjU1MzUgZg0KMDAwMDAwMzgxNiA2NTUzNSBmDQowMDAwMDAzODE3IDY1NTM1IGYNCjAwMDAwMDM4MTggNjU1MzUgZg0KMDAwMDAwMzgxOSA2NTUzNSBmDQowMDAwMDAzODIwIDY1NTM1IGYNCjAwMDAwMDM4MjEgNjU1MzUgZg0KMDAwMDAwMzgyMiA2NTUzNSBmDQowMDAwMDAzODIzIDY1NTM1IGYNCjAwMDAwMDM4MjQgNjU1MzUgZg0KMDAwMDAwMzgyNSA2NTUzNSBmDQowMDAwMDAzODI2IDY1NTM1IGYNCjAwMDAwMDM4MjcgNjU1MzUgZg0KMDAwMDAwMzgyOCA2NTUzNSBmDQowMDAwMDAzODI5IDY1NTM1IGYNCjAwMDAwMDM4MzAgNjU1MzUgZg0KMDAwMDAwMzgzMSA2NTUzNSBmDQowMDAwMDAzODMyIDY1NTM1IGYNCjAwMDAwMDM4MzMgNjU1MzUgZg0KMDAwMDAwMzgzNCA2NTUzNSBmDQowMDAwMDAzODM1IDY1NTM1IGYNCjAwMDAwMDM4MzYgNjU1MzUgZg0KMDAwMDAwMzgzNyA2NTUzNSBmDQowMDAwMDAzODM4IDY1NTM1IGYNCjAwMDAwMDM4MzkgNjU1MzUgZg0KMDAwMDAwMzg0MCA2NTUzNSBmDQowMDAwMDAzODQxIDY1NTM1IGYNCjAwMDAwMDM4NDIgNjU1MzUgZg0KMDAwMDAwMzg0MyA2NTUzNSBmDQowMDAwMDAzODQ0IDY1NTM1IGYNCjAwMDAwMDM4NDUgNjU1MzUgZg0KMDAwMDAwMzg0NiA2NTUzNSBmDQowMDAwMDAzODQ3IDY1NTM1IGYNCjAwMDAwMDM4NDggNjU1MzUgZg0KMDAwMDAwMzg0OSA2NTUzNSBmDQowMDAwMDAzODUwIDY1NTM1IGYNCjAwMDAwMDM4NTEgNjU1MzUgZg0KMDAwMDAwMzg1MiA2NTUzNSBmDQowMDAwMDAzODUzIDY1NTM1IGYNCjAwMDAwMDM4NTQgNjU1MzUgZg0KMDAwMDAwMzg1NSA2NTUzNSBmDQowMDAwMDAzODU2IDY1NTM1IGYNCjAwMDAwMDM4NTcgNjU1MzUgZg0KMDAwMDAwMzg1OCA2NTUzNSBmDQowMDAwMDAzODU5IDY1NTM1IGYNCjAwMDAwMDM4NjAgNjU1MzUgZg0KMDAwMDAwMzg2MSA2NTUzNSBmDQowMDAwMDAzODYyIDY1NTM1IGYNCjAwMDAwMDM4NjMgNjU1MzUgZg0KMDAwMDAwMzg2NCA2NTUzNSBmDQowMDAwMDAzODY1IDY1NTM1IGYNCjAwMDAwMDM4NjYgNjU1MzUgZg0KMDAwMDAwMzg2NyA2NTUzNSBmDQowMDAwMDAzODY4IDY1NTM1IGYNCjAwMDAwMDM4NjkgNjU1MzUgZg0KMDAwMDAwMzg3MCA2NTUzNSBmDQowMDAwMDAzODcxIDY1NTM1IGYNCjAwMDAwMDM4NzIgNjU1MzUgZg0KMDAwMDAwMzg3MyA2NTUzNSBmDQowMDAwMDAzODc0IDY1NTM1IGYNCjAwMDAwMDM4NzUgNjU1MzUgZg0KMDAwMDAwMzg3NiA2NTUzNSBmDQowMDAwMDAzODc3IDY1NTM1IGYNCjAwMDAwMDM4NzggNjU1MzUgZg0KMDAwMDAwMzg3OSA2NTUzNSBmDQowMDAwMDAzODgwIDY1NTM1IGYNCjAwMDAwMDM4ODEgNjU1MzUgZg0KMDAwMDAwMzg4MiA2NTUzNSBmDQowMDAwMDAzODgzIDY1NTM1IGYNCjAwMDAwMDM4ODQgNjU1MzUgZg0KMDAwMDAwMzg4NSA2NTUzNSBmDQowMDAwMDAzODg2IDY1NTM1IGYNCjAwMDAwMDM4ODcgNjU1MzUgZg0KMDAwMDAwMzg4OCA2NTUzNSBmDQowMDAwMDAzODg5IDY1NTM1IGYNCjAwMDAwMDM4OTAgNjU1MzUgZg0KMDAwMDAwMzg5MSA2NTUzNSBmDQowMDAwMDAzODkyIDY1NTM1IGYNCjAwMDAwMDM4OTMgNjU1MzUgZg0KMDAwMDAwMzg5NCA2NTUzNSBmDQowMDAwMDAzODk1IDY1NTM1IGYNCjAwMDAwMDM4OTYgNjU1MzUgZg0KMDAwMDAwMzg5NyA2NTUzNSBmDQowMDAwMDAzODk4IDY1NTM1IGYNCjAwMDAwMDM4OTkgNjU1MzUgZg0KMDAwMDAwMzkwMCA2NTUzNSBmDQowMDAwMDAzOTAxIDY1NTM1IGYNCjAwMDAwMDM5MDIgNjU1MzUgZg0KMDAwMDAwMzkwMyA2NTUzNSBmDQowMDAwMDAzOTA0IDY1NTM1IGYNCjAwMDAwMDM5MDUgNjU1MzUgZg0KMDAwMDAwMzkwNiA2NTUzNSBmDQowMDAwMDAzOTA3IDY1NTM1IGYNCjAwMDAwMDM5MDggNjU1MzUgZg0KMDAwMDAwMzkwOSA2NTUzNSBmDQowMDAwMDAzOTEwIDY1NTM1IGYNCjAwMDAwMDM5MTEgNjU1MzUgZg0KMDAwMDAwMzkxMiA2NTUzNSBmDQowMDAwMDAzOTEzIDY1NTM1IGYNCjAwMDAwMDM5MTQgNjU1MzUgZg0KMDAwMDAwMzkxNSA2NTUzNSBmDQowMDAwMDAzOTE2IDY1NTM1IGYNCjAwMDAwMDM5MTcgNjU1MzUgZg0KMDAwMDAwMzkxOCA2NTUzNSBmDQowMDAwMDAzOTE5IDY1NTM1IGYNCjAwMDAwMDM5MjAgNjU1MzUgZg0KMDAwMDAwMzkyMSA2NTUzNSBmDQowMDAwMDAzOTIyIDY1NTM1IGYNCjAwMDAwMDM5MjMgNjU1MzUgZg0KMDAwMDAwMzkyNCA2NTUzNSBmDQowMDAwMDAzOTI1IDY1NTM1IGYNCjAwMDAwMDM5MjYgNjU1MzUgZg0KMDAwMDAwMzkyNyA2NTUzNSBmDQowMDAwMDAzOTI4IDY1NTM1IGYNCjAwMDAwMDM5MjkgNjU1MzUgZg0KMDAwMDAwMzkzMCA2NTUzNSBmDQowMDAwMDAzOTMxIDY1NTM1IGYNCjAwMDAwMDM5MzIgNjU1MzUgZg0KMDAwMDAwMzkzMyA2NTUzNSBmDQowMDAwMDAzOTM0IDY1NTM1IGYNCjAwMDAwMDM5MzUgNjU1MzUgZg0KMDAwMDAwMzkzNiA2NTUzNSBmDQowMDAwMDAzOTM3IDY1NTM1IGYNCjAwMDAwMDM5MzggNjU1MzUgZg0KMDAwMDAwMzkzOSA2NTUzNSBmDQowMDAwMDAzOTQwIDY1NTM1IGYNCjAwMDAwMDM5NDEgNjU1MzUgZg0KMDAwMDAwMzk0MiA2NTUzNSBmDQowMDAwMDAzOTQzIDY1NTM1IGYNCjAwMDAwMDM5NDQgNjU1MzUgZg0KMDAwMDAwMzk0NSA2NTUzNSBmDQowMDAwMDAzOTQ2IDY1NTM1IGYNCjAwMDAwMDM5NDcgNjU1MzUgZg0KMDAwMDAwMzk0OCA2NTUzNSBmDQowMDAwMDAzOTQ5IDY1NTM1IGYNCjAwMDAwMDM5NTAgNjU1MzUgZg0KMDAwMDAwMzk1MSA2NTUzNSBmDQowMDAwMDAzOTUyIDY1NTM1IGYNCjAwMDAwMDM5NTMgNjU1MzUgZg0KMDAwMDAwMzk1NCA2NTUzNSBmDQowMDAwMDAzOTU1IDY1NTM1IGYNCjAwMDAwMDM5NTYgNjU1MzUgZg0KMDAwMDAwMzk1NyA2NTUzNSBmDQowMDAwMDAzOTU4IDY1NTM1IGYNCjAwMDAwMDM5NTkgNjU1MzUgZg0KMDAwMDAwMzk2MCA2NTUzNSBmDQowMDAwMDAzOTYxIDY1NTM1IGYNCjAwMDAwMDM5NjIgNjU1MzUgZg0KMDAwMDAwMzk2MyA2NTUzNSBmDQowMDAwMDAzOTY0IDY1NTM1IGYNCjAwMDAwMDM5NjUgNjU1MzUgZg0KMDAwMDAwMzk2NiA2NTUzNSBmDQowMDAwMDAzOTY3IDY1NTM1IGYNCjAwMDAwMDM5NjggNjU1MzUgZg0KMDAwMDAwMzk2OSA2NTUzNSBmDQowMDAwMDAzOTcwIDY1NTM1IGYNCjAwMDAwMDM5NzEgNjU1MzUgZg0KMDAwMDAwMzk3MiA2NTUzNSBmDQowMDAwMDAzOTczIDY1NTM1IGYNCjAwMDAwMDM5NzQgNjU1MzUgZg0KMDAwMDAwMzk3NSA2NTUzNSBmDQowMDAwMDAzOTc2IDY1NTM1IGYNCjAwMDAwMDM5NzcgNjU1MzUgZg0KMDAwMDAwMzk3OCA2NTUzNSBmDQowMDAwMDAzOTc5IDY1NTM1IGYNCjAwMDAwMDM5ODAgNjU1MzUgZg0KMDAwMDAwMzk4MSA2NTUzNSBmDQowMDAwMDAzOTgyIDY1NTM1IGYNCjAwMDAwMDM5ODMgNjU1MzUgZg0KMDAwMDAwMzk4NCA2NTUzNSBmDQowMDAwMDAzOTg1IDY1NTM1IGYNCjAwMDAwMDM5ODYgNjU1MzUgZg0KMDAwMDAwMzk4NyA2NTUzNSBmDQowMDAwMDAzOTg4IDY1NTM1IGYNCjAwMDAwMDM5ODkgNjU1MzUgZg0KMDAwMDAwMzk5MCA2NTUzNSBmDQowMDAwMDAzOTkxIDY1NTM1IGYNCjAwMDAwMDM5OTIgNjU1MzUgZg0KMDAwMDAwMzk5MyA2NTUzNSBmDQowMDAwMDAzOTk0IDY1NTM1IGYNCjAwMDAwMDM5OTUgNjU1MzUgZg0KMDAwMDAwMzk5NiA2NTUzNSBmDQowMDAwMDAzOTk3IDY1NTM1IGYNCjAwMDAwMDM5OTggNjU1MzUgZg0KMDAwMDAwMzk5OSA2NTUzNSBmDQowMDAwMDA0MDAwIDY1NTM1IGYNCjAwMDAwMDQwMDEgNjU1MzUgZg0KMDAwMDAwNDAwMiA2NTUzNSBmDQowMDAwMDA0MDAzIDY1NTM1IGYNCjAwMDAwMDQwMDQgNjU1MzUgZg0KMDAwMDAwNDAwNSA2NTUzNSBmDQowMDAwMDA0MDA2IDY1NTM1IGYNCjAwMDAwMDQwMDcgNjU1MzUgZg0KMDAwMDAwNDAwOCA2NTUzNSBmDQowMDAwMDA0MDA5IDY1NTM1IGYNCjAwMDAwMDQwMTAgNjU1MzUgZg0KMDAwMDAwNDAxMSA2NTUzNSBmDQowMDAwMDA0MDEyIDY1NTM1IGYNCjAwMDAwMDQwMTMgNjU1MzUgZg0KMDAwMDAwNDAxNCA2NTUzNSBmDQowMDAwMDA0MDE1IDY1NTM1IGYNCjAwMDAwMDQwMTYgNjU1MzUgZg0KMDAwMDAwNDAxNyA2NTUzNSBmDQowMDAwMDA0MDE4IDY1NTM1IGYNCjAwMDAwMDQwMTkgNjU1MzUgZg0KMDAwMDAwNDAyMCA2NTUzNSBmDQowMDAwMDA0MDIxIDY1NTM1IGYNCjAwMDAwMDQwMjIgNjU1MzUgZg0KMDAwMDAwNDAyMyA2NTUzNSBmDQowMDAwMDA0MDI0IDY1NTM1IGYNCjAwMDAwMDQwMjUgNjU1MzUgZg0KMDAwMDAwNDAyNiA2NTUzNSBmDQowMDAwMDA0MDI3IDY1NTM1IGYNCjAwMDAwMDQwMjggNjU1MzUgZg0KMDAwMDAwNDAyOSA2NTUzNSBmDQowMDAwMDA0MDMwIDY1NTM1IGYNCjAwMDAwMDQwMzEgNjU1MzUgZg0KMDAwMDAwNDAzMiA2NTUzNSBmDQowMDAwMDA0MDMzIDY1NTM1IGYNCjAwMDAwMDQwMzQgNjU1MzUgZg0KMDAwMDAwNDAzNSA2NTUzNSBmDQowMDAwMDA0MDM2IDY1NTM1IGYNCjAwMDAwMDQwMzcgNjU1MzUgZg0KMDAwMDAwNDAzOCA2NTUzNSBmDQowMDAwMDA0MDM5IDY1NTM1IGYNCjAwMDAwMDQwNDAgNjU1MzUgZg0KMDAwMDAwNDA0MSA2NTUzNSBmDQowMDAwMDA0MDQyIDY1NTM1IGYNCjAwMDAwMDQwNDMgNjU1MzUgZg0KMDAwMDAwNDA0NCA2NTUzNSBmDQowMDAwMDA0MDQ1IDY1NTM1IGYNCjAwMDAwMDQwNDYgNjU1MzUgZg0KMDAwMDAwNDA0NyA2NTUzNSBmDQowMDAwMDA0MDQ4IDY1NTM1IGYNCjAwMDAwMDQwNDkgNjU1MzUgZg0KMDAwMDAwNDA1MCA2NTUzNSBmDQowMDAwMDA0MDUxIDY1NTM1IGYNCjAwMDAwMDQwNTIgNjU1MzUgZg0KMDAwMDAwNDA1MyA2NTUzNSBmDQowMDAwMDA0MDU0IDY1NTM1IGYNCjAwMDAwMDQwNTUgNjU1MzUgZg0KMDAwMDAwNDA1NiA2NTUzNSBmDQowMDAwMDA0MDU3IDY1NTM1IGYNCjAwMDAwMDQwNTggNjU1MzUgZg0KMDAwMDAwNDA1OSA2NTUzNSBmDQowMDAwMDA0MDYwIDY1NTM1IGYNCjAwMDAwMDQwNjEgNjU1MzUgZg0KMDAwMDAwNDA2MiA2NTUzNSBmDQowMDAwMDA0MDYzIDY1NTM1IGYNCjAwMDAwMDQwNjQgNjU1MzUgZg0KMDAwMDAwNDA2NSA2NTUzNSBmDQowMDAwMDA0MDY2IDY1NTM1IGYNCjAwMDAwMDQwNjcgNjU1MzUgZg0KMDAwMDAwNDA2OCA2NTUzNSBmDQowMDAwMDA0MDY5IDY1NTM1IGYNCjAwMDAwMDQwNzAgNjU1MzUgZg0KMDAwMDAwNDA3MSA2NTUzNSBmDQowMDAwMDA0MDcyIDY1NTM1IGYNCjAwMDAwMDQwNzMgNjU1MzUgZg0KMDAwMDAwNDA3NCA2NTUzNSBmDQowMDAwMDA0MDc1IDY1NTM1IGYNCjAwMDAwMDQwNzYgNjU1MzUgZg0KMDAwMDAwNDA3NyA2NTUzNSBmDQowMDAwMDA0MDc4IDY1NTM1IGYNCjAwMDAwMDQwNzkgNjU1MzUgZg0KMDAwMDAwNDA4MCA2NTUzNSBmDQowMDAwMDA0MDgxIDY1NTM1IGYNCjAwMDAwMDQwODIgNjU1MzUgZg0KMDAwMDAwNDA4MyA2NTUzNSBmDQowMDAwMDA0MDg0IDY1NTM1IGYNCjAwMDAwMDQwODUgNjU1MzUgZg0KMDAwMDAwNDA4NiA2NTUzNSBmDQowMDAwMDA0MDg3IDY1NTM1IGYNCjAwMDAwMDQwODggNjU1MzUgZg0KMDAwMDAwNDA4OSA2NTUzNSBmDQowMDAwMDA0MDkwIDY1NTM1IGYNCjAwMDAwMDQwOTEgNjU1MzUgZg0KMDAwMDAwNDA5MiA2NTUzNSBmDQowMDAwMDA0MDkzIDY1NTM1IGYNCjAwMDAwMDQwOTQgNjU1MzUgZg0KMDAwMDAwNDA5NSA2NTUzNSBmDQowMDAwMDA0MDk2IDY1NTM1IGYNCjAwMDAwMDQwOTcgNjU1MzUgZg0KMDAwMDAwNDA5OCA2NTUzNSBmDQowMDAwMDA0MDk5IDY1NTM1IGYNCjAwMDAwMDQxMDAgNjU1MzUgZg0KMDAwMDAwNDEwMSA2NTUzNSBmDQowMDAwMDA0MTAyIDY1NTM1IGYNCjAwMDAwMDQxMDMgNjU1MzUgZg0KMDAwMDAwNDEwNCA2NTUzNSBmDQowMDAwMDA0MTA1IDY1NTM1IGYNCjAwMDAwMDQxMDYgNjU1MzUgZg0KMDAwMDAwNDEwNyA2NTUzNSBmDQowMDAwMDA0MTA4IDY1NTM1IGYNCjAwMDAwMDQxMDkgNjU1MzUgZg0KMDAwMDAwNDExMCA2NTUzNSBmDQowMDAwMDA0MTExIDY1NTM1IGYNCjAwMDAwMDQxMTIgNjU1MzUgZg0KMDAwMDAwNDExMyA2NTUzNSBmDQowMDAwMDA0MTE0IDY1NTM1IGYNCjAwMDAwMDQxMTUgNjU1MzUgZg0KMDAwMDAwNDExNiA2NTUzNSBmDQowMDAwMDA0MTE3IDY1NTM1IGYNCjAwMDAwMDQxMTggNjU1MzUgZg0KMDAwMDAwNDExOSA2NTUzNSBmDQowMDAwMDA0MTIwIDY1NTM1IGYNCjAwMDAwMDQxMjEgNjU1MzUgZg0KMDAwMDAwNDEyMiA2NTUzNSBmDQowMDAwMDA0MTIzIDY1NTM1IGYNCjAwMDAwMDQxMjQgNjU1MzUgZg0KMDAwMDAwNDEyNSA2NTUzNSBmDQowMDAwMDA0MTI2IDY1NTM1IGYNCjAwMDAwMDQxMjcgNjU1MzUgZg0KMDAwMDAwNDEyOCA2NTUzNSBmDQowMDAwMDA0MTI5IDY1NTM1IGYNCjAwMDAwMDQxMzAgNjU1MzUgZg0KMDAwMDAwNDEzMSA2NTUzNSBmDQowMDAwMDA0MTMyIDY1NTM1IGYNCjAwMDAwMDQxMzMgNjU1MzUgZg0KMDAwMDAwNDEzNCA2NTUzNSBmDQowMDAwMDA0MTM1IDY1NTM1IGYNCjAwMDAwMDQxMzYgNjU1MzUgZg0KMDAwMDAwNDEzNyA2NTUzNSBmDQowMDAwMDA0MTM4IDY1NTM1IGYNCjAwMDAwMDQxMzkgNjU1MzUgZg0KMDAwMDAwNDE0MCA2NTUzNSBmDQowMDAwMDA0MTQxIDY1NTM1IGYNCjAwMDAwMDQxNDIgNjU1MzUgZg0KMDAwMDAwNDE0MyA2NTUzNSBmDQowMDAwMDA0MTQ0IDY1NTM1IGYNCjAwMDAwMDQxNDUgNjU1MzUgZg0KMDAwMDAwNDE0NiA2NTUzNSBmDQowMDAwMDA0MTQ3IDY1NTM1IGYNCjAwMDAwMDQxNDggNjU1MzUgZg0KMDAwMDAwNDE0OSA2NTUzNSBmDQowMDAwMDA0MTUwIDY1NTM1IGYNCjAwMDAwMDQxNTEgNjU1MzUgZg0KMDAwMDAwNDE1MiA2NTUzNSBmDQowMDAwMDA0MTUzIDY1NTM1IGYNCjAwMDAwMDQxNTQgNjU1MzUgZg0KMDAwMDAwNDE1NSA2NTUzNSBmDQowMDAwMDA0MTU2IDY1NTM1IGYNCjAwMDAwMDQxNTcgNjU1MzUgZg0KMDAwMDAwNDE1OCA2NTUzNSBmDQowMDAwMDA0MTU5IDY1NTM1IGYNCjAwMDAwMDQxNjAgNjU1MzUgZg0KMDAwMDAwNDE2MSA2NTUzNSBmDQowMDAwMDA0MTYyIDY1NTM1IGYNCjAwMDAwMDQxNjMgNjU1MzUgZg0KMDAwMDAwNDE2NCA2NTUzNSBmDQowMDAwMDA0MTY1IDY1NTM1IGYNCjAwMDAwMDQxNjYgNjU1MzUgZg0KMDAwMDAwNDE2NyA2NTUzNSBmDQowMDAwMDA0MTY4IDY1NTM1IGYNCjAwMDAwMDQxNjkgNjU1MzUgZg0KMDAwMDAwNDE3MCA2NTUzNSBmDQowMDAwMDA0MTcxIDY1NTM1IGYNCjAwMDAwMDQxNzIgNjU1MzUgZg0KMDAwMDAwNDE3MyA2NTUzNSBmDQowMDAwMDA0MTc0IDY1NTM1IGYNCjAwMDAwMDQxNzUgNjU1MzUgZg0KMDAwMDAwNDE3NiA2NTUzNSBmDQowMDAwMDA0MTc3IDY1NTM1IGYNCjAwMDAwMDQxNzggNjU1MzUgZg0KMDAwMDAwNDE3OSA2NTUzNSBmDQowMDAwMDA0MTgwIDY1NTM1IGYNCjAwMDAwMDQxODEgNjU1MzUgZg0KMDAwMDAwNDE4MiA2NTUzNSBmDQowMDAwMDA0MTgzIDY1NTM1IGYNCjAwMDAwMDQxODQgNjU1MzUgZg0KMDAwMDAwNDE4NSA2NTUzNSBmDQowMDAwMDA0MTg2IDY1NTM1IGYNCjAwMDAwMDQxODcgNjU1MzUgZg0KMDAwMDAwNDE4OCA2NTUzNSBmDQowMDAwMDA0MTg5IDY1NTM1IGYNCjAwMDAwMDQxOTAgNjU1MzUgZg0KMDAwMDAwNDE5MSA2NTUzNSBmDQowMDAwMDA0MTkyIDY1NTM1IGYNCjAwMDAwMDQxOTMgNjU1MzUgZg0KMDAwMDAwNDE5NCA2NTUzNSBmDQowMDAwMDA0MTk1IDY1NTM1IGYNCjAwMDAwMDQxOTYgNjU1MzUgZg0KMDAwMDAwNDE5NyA2NTUzNSBmDQowMDAwMDA0MTk4IDY1NTM1IGYNCjAwMDAwMDQxOTkgNjU1MzUgZg0KMDAwMDAwNDIwMCA2NTUzNSBmDQowMDAwMDA0MjAxIDY1NTM1IGYNCjAwMDAwMDQyMDIgNjU1MzUgZg0KMDAwMDAwNDIwMyA2NTUzNSBmDQowMDAwMDA0MjA0IDY1NTM1IGYNCjAwMDAwMDQyMDUgNjU1MzUgZg0KMDAwMDAwNDIwNiA2NTUzNSBmDQowMDAwMDA0MjA3IDY1NTM1IGYNCjAwMDAwMDQyMDggNjU1MzUgZg0KMDAwMDAwNDIwOSA2NTUzNSBmDQowMDAwMDA0MjEwIDY1NTM1IGYNCjAwMDAwMDQyMTEgNjU1MzUgZg0KMDAwMDAwNDIxMiA2NTUzNSBmDQowMDAwMDA0MjEzIDY1NTM1IGYNCjAwMDAwMDQyMTQgNjU1MzUgZg0KMDAwMDAwNDIxNSA2NTUzNSBmDQowMDAwMDA0MjE2IDY1NTM1IGYNCjAwMDAwMDQyMTcgNjU1MzUgZg0KMDAwMDAwNDIxOCA2NTUzNSBmDQowMDAwMDA0MjE5IDY1NTM1IGYNCjAwMDAwMDQyMjAgNjU1MzUgZg0KMDAwMDAwNDIyMSA2NTUzNSBmDQowMDAwMDA0MjIyIDY1NTM1IGYNCjAwMDAwMDQyMjMgNjU1MzUgZg0KMDAwMDAwNDIyNCA2NTUzNSBmDQowMDAwMDA0MjI1IDY1NTM1IGYNCjAwMDAwMDQyMjYgNjU1MzUgZg0KMDAwMDAwNDIyNyA2NTUzNSBmDQowMDAwMDA0MjI4IDY1NTM1IGYNCjAwMDAwMDQyMjkgNjU1MzUgZg0KMDAwMDAwNDIzMCA2NTUzNSBmDQowMDAwMDA0MjMxIDY1NTM1IGYNCjAwMDAwMDQyMzIgNjU1MzUgZg0KMDAwMDAwNDIzMyA2NTUzNSBmDQowMDAwMDA0MjM0IDY1NTM1IGYNCjAwMDAwMDQyMzUgNjU1MzUgZg0KMDAwMDAwNDIzNiA2NTUzNSBmDQowMDAwMDA0MjM3IDY1NTM1IGYNCjAwMDAwMDQyMzggNjU1MzUgZg0KMDAwMDAwNDIzOSA2NTUzNSBmDQowMDAwMDA0MjQwIDY1NTM1IGYNCjAwMDAwMDQyNDEgNjU1MzUgZg0KMDAwMDAwNDI0MiA2NTUzNSBmDQowMDAwMDA0MjQzIDY1NTM1IGYNCjAwMDAwMDQyNDQgNjU1MzUgZg0KMDAwMDAwNDI0NSA2NTUzNSBmDQowMDAwMDA0MjQ2IDY1NTM1IGYNCjAwMDAwMDQyNDcgNjU1MzUgZg0KMDAwMDAwNDI0OCA2NTUzNSBmDQowMDAwMDA0MjQ5IDY1NTM1IGYNCjAwMDAwMDQyNTAgNjU1MzUgZg0KMDAwMDAwNDI1MSA2NTUzNSBmDQowMDAwMDA0MjUyIDY1NTM1IGYNCjAwMDAwMDQyNTMgNjU1MzUgZg0KMDAwMDAwNDI1NCA2NTUzNSBmDQowMDAwMDA0MjU1IDY1NTM1IGYNCjAwMDAwMDQyNTYgNjU1MzUgZg0KMDAwMDAwNDI1NyA2NTUzNSBmDQowMDAwMDA0MjU4IDY1NTM1IGYNCjAwMDAwMDQyNTkgNjU1MzUgZg0KMDAwMDAwNDI2MCA2NTUzNSBmDQowMDAwMDA0MjYxIDY1NTM1IGYNCjAwMDAwMDQyNjIgNjU1MzUgZg0KMDAwMDAwNDI2MyA2NTUzNSBmDQowMDAwMDA0MjY0IDY1NTM1IGYNCjAwMDAwMDQyNjUgNjU1MzUgZg0KMDAwMDAwNDI2NiA2NTUzNSBmDQowMDAwMDA0MjY3IDY1NTM1IGYNCjAwMDAwMDQyNjggNjU1MzUgZg0KMDAwMDAwNDI2OSA2NTUzNSBmDQowMDAwMDA0MjcwIDY1NTM1IGYNCjAwMDAwMDQyNzEgNjU1MzUgZg0KMDAwMDAwNDI3MiA2NTUzNSBmDQowMDAwMDA0MjczIDY1NTM1IGYNCjAwMDAwMDQyNzQgNjU1MzUgZg0KMDAwMDAwNDI3NSA2NTUzNSBmDQowMDAwMDA0Mjc2IDY1NTM1IGYNCjAwMDAwMDQyNzcgNjU1MzUgZg0KMDAwMDAwNDI3OCA2NTUzNSBmDQowMDAwMDA0Mjc5IDY1NTM1IGYNCjAwMDAwMDQyODAgNjU1MzUgZg0KMDAwMDAwNDI4MSA2NTUzNSBmDQowMDAwMDA0MjgyIDY1NTM1IGYNCjAwMDAwMDQyODMgNjU1MzUgZg0KMDAwMDAwNDI4NCA2NTUzNSBmDQowMDAwMDA0Mjg1IDY1NTM1IGYNCjAwMDAwMDQyODYgNjU1MzUgZg0KMDAwMDAwNDI4NyA2NTUzNSBmDQowMDAwMDA0Mjg4IDY1NTM1IGYNCjAwMDAwMDQyODkgNjU1MzUgZg0KMDAwMDAwNDI5MCA2NTUzNSBmDQowMDAwMDA0MjkxIDY1NTM1IGYNCjAwMDAwMDQyOTIgNjU1MzUgZg0KMDAwMDAwNDI5MyA2NTUzNSBmDQowMDAwMDA0Mjk0IDY1NTM1IGYNCjAwMDAwMDQyOTUgNjU1MzUgZg0KMDAwMDAwNDI5NiA2NTUzNSBmDQowMDAwMDA0Mjk3IDY1NTM1IGYNCjAwMDAwMDQyOTggNjU1MzUgZg0KMDAwMDAwNDI5OSA2NTUzNSBmDQowMDAwMDA0MzAwIDY1NTM1IGYNCjAwMDAwMDQzMDEgNjU1MzUgZg0KMDAwMDAwNDMwMiA2NTUzNSBmDQowMDAwMDA0MzAzIDY1NTM1IGYNCjAwMDAwMDQzMDQgNjU1MzUgZg0KMDAwMDAwNDMwNSA2NTUzNSBmDQowMDAwMDA0MzA2IDY1NTM1IGYNCjAwMDAwMDQzMDcgNjU1MzUgZg0KMDAwMDAwNDMwOCA2NTUzNSBmDQowMDAwMDA0MzA5IDY1NTM1IGYNCjAwMDAwMDQzMTAgNjU1MzUgZg0KMDAwMDAwNDMxMSA2NTUzNSBmDQowMDAwMDA0MzEyIDY1NTM1IGYNCjAwMDAwMDQzMTMgNjU1MzUgZg0KMDAwMDAwNDMxNCA2NTUzNSBmDQowMDAwMDA0MzE1IDY1NTM1IGYNCjAwMDAwMDQzMTYgNjU1MzUgZg0KMDAwMDAwNDMxNyA2NTUzNSBmDQowMDAwMDA0MzE4IDY1NTM1IGYNCjAwMDAwMDQzMTkgNjU1MzUgZg0KMDAwMDAwNDMyMCA2NTUzNSBmDQowMDAwMDA0MzIxIDY1NTM1IGYNCjAwMDAwMDQzMjIgNjU1MzUgZg0KMDAwMDAwNDMyMyA2NTUzNSBmDQowMDAwMDA0MzI0IDY1NTM1IGYNCjAwMDAwMDQzMjUgNjU1MzUgZg0KMDAwMDAwNDMyNiA2NTUzNSBmDQowMDAwMDA0MzI3IDY1NTM1IGYNCjAwMDAwMDQzMjggNjU1MzUgZg0KMDAwMDAwNDMyOSA2NTUzNSBmDQowMDAwMDA0MzMwIDY1NTM1IGYNCjAwMDAwMDQzMzEgNjU1MzUgZg0KMDAwMDAwNDMzMiA2NTUzNSBmDQowMDAwMDA0MzMzIDY1NTM1IGYNCjAwMDAwMDQzMzQgNjU1MzUgZg0KMDAwMDAwNDMzNSA2NTUzNSBmDQowMDAwMDA0MzM2IDY1NTM1IGYNCjAwMDAwMDQzMzcgNjU1MzUgZg0KMDAwMDAwNDMzOCA2NTUzNSBmDQowMDAwMDA0MzM5IDY1NTM1IGYNCjAwMDAwMDQzNDAgNjU1MzUgZg0KMDAwMDAwNDM0MSA2NTUzNSBmDQowMDAwMDA0MzQyIDY1NTM1IGYNCjAwMDAwMDQzNDMgNjU1MzUgZg0KMDAwMDAwNDM0NCA2NTUzNSBmDQowMDAwMDA0MzQ1IDY1NTM1IGYNCjAwMDAwMDQzNDYgNjU1MzUgZg0KMDAwMDAwNDM0NyA2NTUzNSBmDQowMDAwMDA0MzQ4IDY1NTM1IGYNCjAwMDAwMDQzNDkgNjU1MzUgZg0KMDAwMDAwNDM1MCA2NTUzNSBmDQowMDAwMDA0MzUxIDY1NTM1IGYNCjAwMDAwMDQzNTIgNjU1MzUgZg0KMDAwMDAwNDM1MyA2NTUzNSBmDQowMDAwMDA0MzU0IDY1NTM1IGYNCjAwMDAwMDQzNTUgNjU1MzUgZg0KMDAwMDAwNDM1NiA2NTUzNSBmDQowMDAwMDA0MzU3IDY1NTM1IGYNCjAwMDAwMDQzNTggNjU1MzUgZg0KMDAwMDAwNDM1OSA2NTUzNSBmDQowMDAwMDA0MzYwIDY1NTM1IGYNCjAwMDAwMDQzNjEgNjU1MzUgZg0KMDAwMDAwNDM2MiA2NTUzNSBmDQowMDAwMDA0MzYzIDY1NTM1IGYNCjAwMDAwMDQzNjQgNjU1MzUgZg0KMDAwMDAwNDM2NSA2NTUzNSBmDQowMDAwMDA0MzY2IDY1NTM1IGYNCjAwMDAwMDQzNjcgNjU1MzUgZg0KMDAwMDAwNDM2OCA2NTUzNSBmDQowMDAwMDA0MzY5IDY1NTM1IGYNCjAwMDAwMDQzNzAgNjU1MzUgZg0KMDAwMDAwNDM3MSA2NTUzNSBmDQowMDAwMDA0MzcyIDY1NTM1IGYNCjAwMDAwMDQzNzMgNjU1MzUgZg0KMDAwMDAwNDM3NCA2NTUzNSBmDQowMDAwMDA0Mzc1IDY1NTM1IGYNCjAwMDAwMDQzNzYgNjU1MzUgZg0KMDAwMDAwNDM3NyA2NTUzNSBmDQowMDAwMDA0Mzc4IDY1NTM1IGYNCjAwMDAwMDQzNzkgNjU1MzUgZg0KMDAwMDAwNDM4MCA2NTUzNSBmDQowMDAwMDA0MzgxIDY1NTM1IGYNCjAwMDAwMDQzODIgNjU1MzUgZg0KMDAwMDAwNDM4MyA2NTUzNSBmDQowMDAwMDA0Mzg0IDY1NTM1IGYNCjAwMDAwMDQzODUgNjU1MzUgZg0KMDAwMDAwNDM4NiA2NTUzNSBmDQowMDAwMDA0Mzg3IDY1NTM1IGYNCjAwMDAwMDQzODggNjU1MzUgZg0KMDAwMDAwNDM4OSA2NTUzNSBmDQowMDAwMDA0MzkwIDY1NTM1IGYNCjAwMDAwMDQzOTEgNjU1MzUgZg0KMDAwMDAwNDM5MiA2NTUzNSBmDQowMDAwMDA0MzkzIDY1NTM1IGYNCjAwMDAwMDQzOTQgNjU1MzUgZg0KMDAwMDAwNDM5NSA2NTUzNSBmDQowMDAwMDA0Mzk2IDY1NTM1IGYNCjAwMDAwMDQzOTcgNjU1MzUgZg0KMDAwMDAwNDM5OCA2NTUzNSBmDQowMDAwMDA0Mzk5IDY1NTM1IGYNCjAwMDAwMDQ0MDAgNjU1MzUgZg0KMDAwMDAwNDQwMSA2NTUzNSBmDQowMDAwMDA0NDAyIDY1NTM1IGYNCjAwMDAwMDQ0MDMgNjU1MzUgZg0KMDAwMDAwNDQwNCA2NTUzNSBmDQowMDAwMDA0NDA1IDY1NTM1IGYNCjAwMDAwMDQ0MDYgNjU1MzUgZg0KMDAwMDAwNDQwNyA2NTUzNSBmDQowMDAwMDA0NDA4IDY1NTM1IGYNCjAwMDAwMDQ0MDkgNjU1MzUgZg0KMDAwMDAwNDQxMCA2NTUzNSBmDQowMDAwMDA0NDExIDY1NTM1IGYNCjAwMDAwMDQ0MTIgNjU1MzUgZg0KMDAwMDAwNDQxMyA2NTUzNSBmDQowMDAwMDA0NDE0IDY1NTM1IGYNCjAwMDAwMDQ0MTUgNjU1MzUgZg0KMDAwMDAwNDQxNiA2NTUzNSBmDQowMDAwMDA0NDE3IDY1NTM1IGYNCjAwMDAwMDQ0MTggNjU1MzUgZg0KMDAwMDAwNDQxOSA2NTUzNSBmDQowMDAwMDA0NDIwIDY1NTM1IGYNCjAwMDAwMDQ0MjEgNjU1MzUgZg0KMDAwMDAwNDQyMiA2NTUzNSBmDQowMDAwMDA0NDIzIDY1NTM1IGYNCjAwMDAwMDQ0MjQgNjU1MzUgZg0KMDAwMDAwNDQyNSA2NTUzNSBmDQowMDAwMDA0NDI2IDY1NTM1IGYNCjAwMDAwMDQ0MjcgNjU1MzUgZg0KMDAwMDAwNDQyOCA2NTUzNSBmDQowMDAwMDA0NDI5IDY1NTM1IGYNCjAwMDAwMDQ0MzAgNjU1MzUgZg0KMDAwMDAwNDQzMSA2NTUzNSBmDQowMDAwMDA0NDMyIDY1NTM1IGYNCjAwMDAwMDQ0MzMgNjU1MzUgZg0KMDAwMDAwNDQzNCA2NTUzNSBmDQowMDAwMDA0NDM1IDY1NTM1IGYNCjAwMDAwMDQ0MzYgNjU1MzUgZg0KMDAwMDAwNDQzNyA2NTUzNSBmDQowMDAwMDA0NDM4IDY1NTM1IGYNCjAwMDAwMDQ0MzkgNjU1MzUgZg0KMDAwMDAwNDQ0MCA2NTUzNSBmDQowMDAwMDA0NDQxIDY1NTM1IGYNCjAwMDAwMDQ0NDIgNjU1MzUgZg0KMDAwMDAwNDQ0MyA2NTUzNSBmDQowMDAwMDA0NDQ0IDY1NTM1IGYNCjAwMDAwMDQ0NDUgNjU1MzUgZg0KMDAwMDAwNDQ0NiA2NTUzNSBmDQowMDAwMDA0NDQ3IDY1NTM1IGYNCjAwMDAwMDQ0NDggNjU1MzUgZg0KMDAwMDAwNDQ0OSA2NTUzNSBmDQowMDAwMDA0NDUwIDY1NTM1IGYNCjAwMDAwMDQ0NTEgNjU1MzUgZg0KMDAwMDAwNDQ1MiA2NTUzNSBmDQowMDAwMDA0NDUzIDY1NTM1IGYNCjAwMDAwMDQ0NTQgNjU1MzUgZg0KMDAwMDAwNDQ1NSA2NTUzNSBmDQowMDAwMDA0NDU2IDY1NTM1IGYNCjAwMDAwMDQ0NTcgNjU1MzUgZg0KMDAwMDAwNDQ1OCA2NTUzNSBmDQowMDAwMDA0NDU5IDY1NTM1IGYNCjAwMDAwMDQ0NjAgNjU1MzUgZg0KMDAwMDAwNDQ2MSA2NTUzNSBmDQowMDAwMDA0NDYyIDY1NTM1IGYNCjAwMDAwMDQ0NjMgNjU1MzUgZg0KMDAwMDAwNDQ2NCA2NTUzNSBmDQowMDAwMDA0NDY1IDY1NTM1IGYNCjAwMDAwMDQ0NjYgNjU1MzUgZg0KMDAwMDAwNDQ2NyA2NTUzNSBmDQowMDAwMDA0NDY4IDY1NTM1IGYNCjAwMDAwMDQ0NjkgNjU1MzUgZg0KMDAwMDAwNDQ3MCA2NTUzNSBmDQowMDAwMDA0NDcxIDY1NTM1IGYNCjAwMDAwMDQ0NzIgNjU1MzUgZg0KMDAwMDAwNDQ3MyA2NTUzNSBmDQowMDAwMDA0NDc0IDY1NTM1IGYNCjAwMDAwMDQ0NzUgNjU1MzUgZg0KMDAwMDAwNDQ3NiA2NTUzNSBmDQowMDAwMDA0NDc3IDY1NTM1IGYNCjAwMDAwMDQ0NzggNjU1MzUgZg0KMDAwMDAwNDQ3OSA2NTUzNSBmDQowMDAwMDA0NDgwIDY1NTM1IGYNCjAwMDAwMDQ0ODEgNjU1MzUgZg0KMDAwMDAwNDQ4MiA2NTUzNSBmDQowMDAwMDA0NDgzIDY1NTM1IGYNCjAwMDAwMDQ0ODQgNjU1MzUgZg0KMDAwMDAwNDQ4NSA2NTUzNSBmDQowMDAwMDA0NDg2IDY1NTM1IGYNCjAwMDAwMDQ0ODcgNjU1MzUgZg0KMDAwMDAwNDQ4OCA2NTUzNSBmDQowMDAwMDA0NDg5IDY1NTM1IGYNCjAwMDAwMDQ0OTAgNjU1MzUgZg0KMDAwMDAwNDQ5MSA2NTUzNSBmDQowMDAwMDA0NDkyIDY1NTM1IGYNCjAwMDAwMDQ0OTMgNjU1MzUgZg0KMDAwMDAwNDQ5NCA2NTUzNSBmDQowMDAwMDA0NDk1IDY1NTM1IGYNCjAwMDAwMDQ0OTYgNjU1MzUgZg0KMDAwMDAwNDQ5NyA2NTUzNSBmDQowMDAwMDA0NDk4IDY1NTM1IGYNCjAwMDAwMDQ0OTkgNjU1MzUgZg0KMDAwMDAwNDUwMCA2NTUzNSBmDQowMDAwMDA0NTAxIDY1NTM1IGYNCjAwMDAwMDQ1MDIgNjU1MzUgZg0KMDAwMDAwNDUwMyA2NTUzNSBmDQowMDAwMDA0NTA0IDY1NTM1IGYNCjAwMDAwMDQ1MDUgNjU1MzUgZg0KMDAwMDAwNDUwNiA2NTUzNSBmDQowMDAwMDA0NTA3IDY1NTM1IGYNCjAwMDAwMDQ1MDggNjU1MzUgZg0KMDAwMDAwNDUwOSA2NTUzNSBmDQowMDAwMDA0NTEwIDY1NTM1IGYNCjAwMDAwMDQ1MTEgNjU1MzUgZg0KMDAwMDAwNDUxMiA2NTUzNSBmDQowMDAwMDA0NTEzIDY1NTM1IGYNCjAwMDAwMDQ1MTQgNjU1MzUgZg0KMDAwMDAwNDUxNSA2NTUzNSBmDQowMDAwMDA0NTE2IDY1NTM1IGYNCjAwMDAwMDQ1MTcgNjU1MzUgZg0KMDAwMDAwNDUxOCA2NTUzNSBmDQowMDAwMDA0NTE5IDY1NTM1IGYNCjAwMDAwMDQ1MjAgNjU1MzUgZg0KMDAwMDAwNDUyMSA2NTUzNSBmDQowMDAwMDA0NTIyIDY1NTM1IGYNCjAwMDAwMDQ1MjMgNjU1MzUgZg0KMDAwMDAwNDUyNCA2NTUzNSBmDQowMDAwMDA0NTI1IDY1NTM1IGYNCjAwMDAwMDQ1MjYgNjU1MzUgZg0KMDAwMDAwNDUyNyA2NTUzNSBmDQowMDAwMDA0NTI4IDY1NTM1IGYNCjAwMDAwMDQ1MjkgNjU1MzUgZg0KMDAwMDAwNDUzMCA2NTUzNSBmDQowMDAwMDA0NTMxIDY1NTM1IGYNCjAwMDAwMDQ1MzIgNjU1MzUgZg0KMDAwMDAwNDUzMyA2NTUzNSBmDQowMDAwMDA0NTM0IDY1NTM1IGYNCjAwMDAwMDQ1MzUgNjU1MzUgZg0KMDAwMDAwNDUzNiA2NTUzNSBmDQowMDAwMDA0NTM3IDY1NTM1IGYNCjAwMDAwMDQ1MzggNjU1MzUgZg0KMDAwMDAwNDUzOSA2NTUzNSBmDQowMDAwMDA0NTQwIDY1NTM1IGYNCjAwMDAwMDQ1NDEgNjU1MzUgZg0KMDAwMDAwNDU0MiA2NTUzNSBmDQowMDAwMDA0NTQzIDY1NTM1IGYNCjAwMDAwMDQ1NDQgNjU1MzUgZg0KMDAwMDAwNDU0NSA2NTUzNSBmDQowMDAwMDA0NTQ2IDY1NTM1IGYNCjAwMDAwMDQ1NDcgNjU1MzUgZg0KMDAwMDAwNDU0OCA2NTUzNSBmDQowMDAwMDA0NTQ5IDY1NTM1IGYNCjAwMDAwMDQ1NTAgNjU1MzUgZg0KMDAwMDAwNDU1MSA2NTUzNSBmDQowMDAwMDA0NTUyIDY1NTM1IGYNCjAwMDAwMDQ1NTMgNjU1MzUgZg0KMDAwMDAwNDU1NCA2NTUzNSBmDQowMDAwMDA0NTU1IDY1NTM1IGYNCjAwMDAwMDQ1NTYgNjU1MzUgZg0KMDAwMDAwNDU1NyA2NTUzNSBmDQowMDAwMDA0NTU4IDY1NTM1IGYNCjAwMDAwMDQ1NTkgNjU1MzUgZg0KMDAwMDAwNDU2MCA2NTUzNSBmDQowMDAwMDA0NTYxIDY1NTM1IGYNCjAwMDAwMDQ1NjIgNjU1MzUgZg0KMDAwMDAwNDU2MyA2NTUzNSBmDQowMDAwMDA0NTY0IDY1NTM1IGYNCjAwMDAwMDQ1NjUgNjU1MzUgZg0KMDAwMDAwNDU2NiA2NTUzNSBmDQowMDAwMDA0NTY3IDY1NTM1IGYNCjAwMDAwMDQ1NjggNjU1MzUgZg0KMDAwMDAwNDU2OSA2NTUzNSBmDQowMDAwMDA0NTcwIDY1NTM1IGYNCjAwMDAwMDQ1NzEgNjU1MzUgZg0KMDAwMDAwNDU3MiA2NTUzNSBmDQowMDAwMDA0NTczIDY1NTM1IGYNCjAwMDAwMDQ1NzQgNjU1MzUgZg0KMDAwMDAwNDU3NSA2NTUzNSBmDQowMDAwMDA0NTc2IDY1NTM1IGYNCjAwMDAwMDQ1NzcgNjU1MzUgZg0KMDAwMDAwNDU3OCA2NTUzNSBmDQowMDAwMDA0NTc5IDY1NTM1IGYNCjAwMDAwMDQ1ODAgNjU1MzUgZg0KMDAwMDAwNDU4MSA2NTUzNSBmDQowMDAwMDA0NTgyIDY1NTM1IGYNCjAwMDAwMDQ1ODMgNjU1MzUgZg0KMDAwMDAwNDU4NCA2NTUzNSBmDQowMDAwMDA0NTg1IDY1NTM1IGYNCjAwMDAwMDQ1ODYgNjU1MzUgZg0KMDAwMDAwNDU4NyA2NTUzNSBmDQowMDAwMDA0NTg4IDY1NTM1IGYNCjAwMDAwMDQ1ODkgNjU1MzUgZg0KMDAwMDAwNDU5MCA2NTUzNSBmDQowMDAwMDA0NTkxIDY1NTM1IGYNCjAwMDAwMDQ1OTIgNjU1MzUgZg0KMDAwMDAwNDU5MyA2NTUzNSBmDQowMDAwMDA0NTk0IDY1NTM1IGYNCjAwMDAwMDQ1OTUgNjU1MzUgZg0KMDAwMDAwNDU5NiA2NTUzNSBmDQowMDAwMDA0NTk3IDY1NTM1IGYNCjAwMDAwMDQ1OTggNjU1MzUgZg0KMDAwMDAwNDU5OSA2NTUzNSBmDQowMDAwMDA0NjAwIDY1NTM1IGYNCjAwMDAwMDQ2MDEgNjU1MzUgZg0KMDAwMDAwNDYwMiA2NTUzNSBmDQowMDAwMDA0NjAzIDY1NTM1IGYNCjAwMDAwMDQ2MDQgNjU1MzUgZg0KMDAwMDAwNDYwNSA2NTUzNSBmDQowMDAwMDA0NjA2IDY1NTM1IGYNCjAwMDAwMDQ2MDcgNjU1MzUgZg0KMDAwMDAwNDYwOCA2NTUzNSBmDQowMDAwMDA0NjA5IDY1NTM1IGYNCjAwMDAwMDQ2MTAgNjU1MzUgZg0KMDAwMDAwNDYxMSA2NTUzNSBmDQowMDAwMDA0NjEyIDY1NTM1IGYNCjAwMDAwMDQ2MTMgNjU1MzUgZg0KMDAwMDAwNDYxNCA2NTUzNSBmDQowMDAwMDA0NjE1IDY1NTM1IGYNCjAwMDAwMDQ2MTYgNjU1MzUgZg0KMDAwMDAwNDYxNyA2NTUzNSBmDQowMDAwMDA0NjE4IDY1NTM1IGYNCjAwMDAwMDQ2MTkgNjU1MzUgZg0KMDAwMDAwNDYyMCA2NTUzNSBmDQowMDAwMDA0NjIxIDY1NTM1IGYNCjAwMDAwMDQ2MjIgNjU1MzUgZg0KMDAwMDAwNDYyMyA2NTUzNSBmDQowMDAwMDA0NjI0IDY1NTM1IGYNCjAwMDAwMDQ2MjUgNjU1MzUgZg0KMDAwMDAwNDYyNiA2NTUzNSBmDQowMDAwMDA0NjI3IDY1NTM1IGYNCjAwMDAwMDQ2MjggNjU1MzUgZg0KMDAwMDAwNDYyOSA2NTUzNSBmDQowMDAwMDA0NjMwIDY1NTM1IGYNCjAwMDAwMDQ2MzEgNjU1MzUgZg0KMDAwMDAwNDYzMiA2NTUzNSBmDQowMDAwMDA0NjMzIDY1NTM1IGYNCjAwMDAwMDQ2MzQgNjU1MzUgZg0KMDAwMDAwNDYzNSA2NTUzNSBmDQowMDAwMDA0NjM2IDY1NTM1IGYNCjAwMDAwMDQ2MzcgNjU1MzUgZg0KMDAwMDAwNDYzOCA2NTUzNSBmDQowMDAwMDA0NjM5IDY1NTM1IGYNCjAwMDAwMDQ2NDAgNjU1MzUgZg0KMDAwMDAwNDY0MSA2NTUzNSBmDQowMDAwMDA0NjQyIDY1NTM1IGYNCjAwMDAwMDQ2NDMgNjU1MzUgZg0KMDAwMDAwNDY0NCA2NTUzNSBmDQowMDAwMDA0NjQ1IDY1NTM1IGYNCjAwMDAwMDQ2NDYgNjU1MzUgZg0KMDAwMDAwNDY0NyA2NTUzNSBmDQowMDAwMDA0NjQ4IDY1NTM1IGYNCjAwMDAwMDQ2NDkgNjU1MzUgZg0KMDAwMDAwNDY1MCA2NTUzNSBmDQowMDAwMDA0NjUxIDY1NTM1IGYNCjAwMDAwMDQ2NTIgNjU1MzUgZg0KMDAwMDAwNDY1MyA2NTUzNSBmDQowMDAwMDA0NjU0IDY1NTM1IGYNCjAwMDAwMDQ2NTUgNjU1MzUgZg0KMDAwMDAwNDY1NiA2NTUzNSBmDQowMDAwMDA0NjU3IDY1NTM1IGYNCjAwMDAwMDQ2NTggNjU1MzUgZg0KMDAwMDAwNDY1OSA2NTUzNSBmDQowMDAwMDA0NjYwIDY1NTM1IGYNCjAwMDAwMDQ2NjEgNjU1MzUgZg0KMDAwMDAwNDY2MiA2NTUzNSBmDQowMDAwMDA0NjYzIDY1NTM1IGYNCjAwMDAwMDQ2NjQgNjU1MzUgZg0KMDAwMDAwNDY2NSA2NTUzNSBmDQowMDAwMDA0NjY2IDY1NTM1IGYNCjAwMDAwMDQ2NjcgNjU1MzUgZg0KMDAwMDAwNDY2OCA2NTUzNSBmDQowMDAwMDA0NjY5IDY1NTM1IGYNCjAwMDAwMDQ2NzAgNjU1MzUgZg0KMDAwMDAwNDY3MSA2NTUzNSBmDQowMDAwMDA0NjcyIDY1NTM1IGYNCjAwMDAwMDQ2NzMgNjU1MzUgZg0KMDAwMDAwNDY3NCA2NTUzNSBmDQowMDAwMDA0Njc1IDY1NTM1IGYNCjAwMDAwMDQ2NzYgNjU1MzUgZg0KMDAwMDAwNDY3NyA2NTUzNSBmDQowMDAwMDA0Njc4IDY1NTM1IGYNCjAwMDAwMDQ2NzkgNjU1MzUgZg0KMDAwMDAwNDY4MCA2NTUzNSBmDQowMDAwMDA0NjgxIDY1NTM1IGYNCjAwMDAwMDQ2ODIgNjU1MzUgZg0KMDAwMDAwNDY4MyA2NTUzNSBmDQowMDAwMDA0Njg0IDY1NTM1IGYNCjAwMDAwMDQ2ODUgNjU1MzUgZg0KMDAwMDAwNDY4NiA2NTUzNSBmDQowMDAwMDA0Njg3IDY1NTM1IGYNCjAwMDAwMDQ2ODggNjU1MzUgZg0KMDAwMDAwNDY4OSA2NTUzNSBmDQowMDAwMDA0NjkwIDY1NTM1IGYNCjAwMDAwMDQ2OTEgNjU1MzUgZg0KMDAwMDAwNDY5MiA2NTUzNSBmDQowMDAwMDA0NjkzIDY1NTM1IGYNCjAwMDAwMDQ2OTQgNjU1MzUgZg0KMDAwMDAwNDY5NSA2NTUzNSBmDQowMDAwMDA0Njk2IDY1NTM1IGYNCjAwMDAwMDQ2OTcgNjU1MzUgZg0KMDAwMDAwNDY5OCA2NTUzNSBmDQowMDAwMDA0Njk5IDY1NTM1IGYNCjAwMDAwMDQ3MDAgNjU1MzUgZg0KMDAwMDAwNDcwMSA2NTUzNSBmDQowMDAwMDA0NzAyIDY1NTM1IGYNCjAwMDAwMDQ3MDMgNjU1MzUgZg0KMDAwMDAwNDcwNCA2NTUzNSBmDQowMDAwMDA0NzA1IDY1NTM1IGYNCjAwMDAwMDQ3MDYgNjU1MzUgZg0KMDAwMDAwNDcwNyA2NTUzNSBmDQowMDAwMDA0NzA4IDY1NTM1IGYNCjAwMDAwMDQ3MDkgNjU1MzUgZg0KMDAwMDAwNDcxMCA2NTUzNSBmDQowMDAwMDA0NzExIDY1NTM1IGYNCjAwMDAwMDQ3MTIgNjU1MzUgZg0KMDAwMDAwNDcxMyA2NTUzNSBmDQowMDAwMDA0NzE0IDY1NTM1IGYNCjAwMDAwMDQ3MTUgNjU1MzUgZg0KMDAwMDAwNDcxNiA2NTUzNSBmDQowMDAwMDA0NzE3IDY1NTM1IGYNCjAwMDAwMDQ3MTggNjU1MzUgZg0KMDAwMDAwNDcxOSA2NTUzNSBmDQowMDAwMDA0NzIwIDY1NTM1IGYNCjAwMDAwMDQ3MjEgNjU1MzUgZg0KMDAwMDAwNDcyMiA2NTUzNSBmDQowMDAwMDA0NzIzIDY1NTM1IGYNCjAwMDAwMDQ3MjQgNjU1MzUgZg0KMDAwMDAwNDcyNSA2NTUzNSBmDQowMDAwMDA0NzI2IDY1NTM1IGYNCjAwMDAwMDQ3MjcgNjU1MzUgZg0KMDAwMDAwNDcyOCA2NTUzNSBmDQowMDAwMDA0NzI5IDY1NTM1IGYNCjAwMDAwMDQ3MzAgNjU1MzUgZg0KMDAwMDAwNDczMSA2NTUzNSBmDQowMDAwMDA0NzMyIDY1NTM1IGYNCjAwMDAwMDQ3MzMgNjU1MzUgZg0KMDAwMDAwNDczNCA2NTUzNSBmDQowMDAwMDA0NzM1IDY1NTM1IGYNCjAwMDAwMDQ3MzYgNjU1MzUgZg0KMDAwMDAwNDczNyA2NTUzNSBmDQowMDAwMDA0NzM4IDY1NTM1IGYNCjAwMDAwMDQ3MzkgNjU1MzUgZg0KMDAwMDAwNDc0MCA2NTUzNSBmDQowMDAwMDA0NzQxIDY1NTM1IGYNCjAwMDAwMDQ3NDIgNjU1MzUgZg0KMDAwMDAwNDc0MyA2NTUzNSBmDQowMDAwMDA0NzQ0IDY1NTM1IGYNCjAwMDAwMDQ3NDUgNjU1MzUgZg0KMDAwMDAwNDc0NiA2NTUzNSBmDQowMDAwMDA0NzQ3IDY1NTM1IGYNCjAwMDAwMDQ3NDggNjU1MzUgZg0KMDAwMDAwNDc0OSA2NTUzNSBmDQowMDAwMDA0NzUwIDY1NTM1IGYNCjAwMDAwMDQ3NTEgNjU1MzUgZg0KMDAwMDAwNDc1MiA2NTUzNSBmDQowMDAwMDA0NzUzIDY1NTM1IGYNCjAwMDAwMDQ3NTQgNjU1MzUgZg0KMDAwMDAwNDc1NSA2NTUzNSBmDQowMDAwMDA0NzU2IDY1NTM1IGYNCjAwMDAwMDQ3NTcgNjU1MzUgZg0KMDAwMDAwNDc1OCA2NTUzNSBmDQowMDAwMDA0NzU5IDY1NTM1IGYNCjAwMDAwMDQ3NjAgNjU1MzUgZg0KMDAwMDAwNDc2MSA2NTUzNSBmDQowMDAwMDA0NzYyIDY1NTM1IGYNCjAwMDAwMDQ3NjMgNjU1MzUgZg0KMDAwMDAwNDc2NCA2NTUzNSBmDQowMDAwMDA0NzY1IDY1NTM1IGYNCjAwMDAwMDQ3NjYgNjU1MzUgZg0KMDAwMDAwNDc2NyA2NTUzNSBmDQowMDAwMDA0NzY4IDY1NTM1IGYNCjAwMDAwMDQ3NjkgNjU1MzUgZg0KMDAwMDAwNDc3MCA2NTUzNSBmDQowMDAwMDA0NzcxIDY1NTM1IGYNCjAwMDAwMDQ3NzIgNjU1MzUgZg0KMDAwMDAwNDc3MyA2NTUzNSBmDQowMDAwMDA0Nzc0IDY1NTM1IGYNCjAwMDAwMDQ3NzUgNjU1MzUgZg0KMDAwMDAwNDc3NiA2NTUzNSBmDQowMDAwMDA0Nzc3IDY1NTM1IGYNCjAwMDAwMDQ3NzggNjU1MzUgZg0KMDAwMDAwNDc3OSA2NTUzNSBmDQowMDAwMDA0NzgwIDY1NTM1IGYNCjAwMDAwMDQ3ODEgNjU1MzUgZg0KMDAwMDAwNDc4MiA2NTUzNSBmDQowMDAwMDA0NzgzIDY1NTM1IGYNCjAwMDAwMDQ3ODQgNjU1MzUgZg0KMDAwMDAwNDc4NSA2NTUzNSBmDQowMDAwMDA0Nzg2IDY1NTM1IGYNCjAwMDAwMDQ3ODcgNjU1MzUgZg0KMDAwMDAwNDc4OCA2NTUzNSBmDQowMDAwMDA0Nzg5IDY1NTM1IGYNCjAwMDAwMDQ3OTAgNjU1MzUgZg0KMDAwMDAwNDc5MSA2NTUzNSBmDQowMDAwMDA0NzkyIDY1NTM1IGYNCjAwMDAwMDQ3OTMgNjU1MzUgZg0KMDAwMDAwNDc5NCA2NTUzNSBmDQowMDAwMDA0Nzk1IDY1NTM1IGYNCjAwMDAwMDQ3OTYgNjU1MzUgZg0KMDAwMDAwNDc5NyA2NTUzNSBmDQowMDAwMDA0Nzk4IDY1NTM1IGYNCjAwMDAwMDQ3OTkgNjU1MzUgZg0KMDAwMDAwNDgwMCA2NTUzNSBmDQowMDAwMDA0ODAxIDY1NTM1IGYNCjAwMDAwMDQ4MDIgNjU1MzUgZg0KMDAwMDAwNDgwMyA2NTUzNSBmDQowMDAwMDA0ODA0IDY1NTM1IGYNCjAwMDAwMDQ4MDUgNjU1MzUgZg0KMDAwMDAwNDgwNiA2NTUzNSBmDQowMDAwMDA0ODA3IDY1NTM1IGYNCjAwMDAwMDQ4MDggNjU1MzUgZg0KMDAwMDAwNDgwOSA2NTUzNSBmDQowMDAwMDA0ODEwIDY1NTM1IGYNCjAwMDAwMDQ4MTEgNjU1MzUgZg0KMDAwMDAwNDgxMiA2NTUzNSBmDQowMDAwMDA0ODEzIDY1NTM1IGYNCjAwMDAwMDQ4MTQgNjU1MzUgZg0KMDAwMDAwNDgxNSA2NTUzNSBmDQowMDAwMDA0ODE2IDY1NTM1IGYNCjAwMDAwMDQ4MTcgNjU1MzUgZg0KMDAwMDAwNDgxOCA2NTUzNSBmDQowMDAwMDA0ODE5IDY1NTM1IGYNCjAwMDAwMDQ4MjAgNjU1MzUgZg0KMDAwMDAwNDgyMSA2NTUzNSBmDQowMDAwMDA0ODIyIDY1NTM1IGYNCjAwMDAwMDQ4MjMgNjU1MzUgZg0KMDAwMDAwNDgyNCA2NTUzNSBmDQowMDAwMDA0ODI1IDY1NTM1IGYNCjAwMDAwMDQ4MjYgNjU1MzUgZg0KMDAwMDAwNDgyNyA2NTUzNSBmDQowMDAwMDA0ODI4IDY1NTM1IGYNCjAwMDAwMDQ4MjkgNjU1MzUgZg0KMDAwMDAwNDgzMCA2NTUzNSBmDQowMDAwMDA0ODMxIDY1NTM1IGYNCjAwMDAwMDQ4MzIgNjU1MzUgZg0KMDAwMDAwNDgzMyA2NTUzNSBmDQowMDAwMDA0ODM0IDY1NTM1IGYNCjAwMDAwMDQ4MzUgNjU1MzUgZg0KMDAwMDAwNDgzNiA2NTUzNSBmDQowMDAwMDA0ODM3IDY1NTM1IGYNCjAwMDAwMDQ4MzggNjU1MzUgZg0KMDAwMDAwNDgzOSA2NTUzNSBmDQowMDAwMDA0ODQwIDY1NTM1IGYNCjAwMDAwMDQ4NDEgNjU1MzUgZg0KMDAwMDAwNDg0MiA2NTUzNSBmDQowMDAwMDA0ODQzIDY1NTM1IGYNCjAwMDAwMDQ4NDQgNjU1MzUgZg0KMDAwMDAwNDg0NSA2NTUzNSBmDQowMDAwMDA0ODQ2IDY1NTM1IGYNCjAwMDAwMDQ4NDcgNjU1MzUgZg0KMDAwMDAwNDg0OCA2NTUzNSBmDQowMDAwMDA0ODQ5IDY1NTM1IGYNCjAwMDAwMDQ4NTAgNjU1MzUgZg0KMDAwMDAwNDg1MSA2NTUzNSBmDQowMDAwMDA0ODUyIDY1NTM1IGYNCjAwMDAwMDQ4NTMgNjU1MzUgZg0KMDAwMDAwNDg1NCA2NTUzNSBmDQowMDAwMDA0ODU1IDY1NTM1IGYNCjAwMDAwMDQ4NTYgNjU1MzUgZg0KMDAwMDAwNDg1NyA2NTUzNSBmDQowMDAwMDA0ODU4IDY1NTM1IGYNCjAwMDAwMDQ4NTkgNjU1MzUgZg0KMDAwMDAwNDg2MCA2NTUzNSBmDQowMDAwMDA0ODYxIDY1NTM1IGYNCjAwMDAwMDQ4NjIgNjU1MzUgZg0KMDAwMDAwNDg2MyA2NTUzNSBmDQowMDAwMDA0ODY0IDY1NTM1IGYNCjAwMDAwMDQ4NjUgNjU1MzUgZg0KMDAwMDAwNDg2NiA2NTUzNSBmDQowMDAwMDA0ODY3IDY1NTM1IGYNCjAwMDAwMDQ4NjggNjU1MzUgZg0KMDAwMDAwNDg2OSA2NTUzNSBmDQowMDAwMDA0ODcwIDY1NTM1IGYNCjAwMDAwMDQ4NzEgNjU1MzUgZg0KMDAwMDAwNDg3MiA2NTUzNSBmDQowMDAwMDA0ODczIDY1NTM1IGYNCjAwMDAwMDQ4NzQgNjU1MzUgZg0KMDAwMDAwNDg3NSA2NTUzNSBmDQowMDAwMDA0ODc2IDY1NTM1IGYNCjAwMDAwMDQ4NzcgNjU1MzUgZg0KMDAwMDAwNDg3OCA2NTUzNSBmDQowMDAwMDA0ODc5IDY1NTM1IGYNCjAwMDAwMDQ4ODAgNjU1MzUgZg0KMDAwMDAwNDg4MSA2NTUzNSBmDQowMDAwMDA0ODgyIDY1NTM1IGYNCjAwMDAwMDQ4ODMgNjU1MzUgZg0KMDAwMDAwNDg4NCA2NTUzNSBmDQowMDAwMDA0ODg1IDY1NTM1IGYNCjAwMDAwMDQ4ODYgNjU1MzUgZg0KMDAwMDAwNDg4NyA2NTUzNSBmDQowMDAwMDA0ODg4IDY1NTM1IGYNCjAwMDAwMDQ4ODkgNjU1MzUgZg0KMDAwMDAwNDg5MCA2NTUzNSBmDQowMDAwMDA0ODkxIDY1NTM1IGYNCjAwMDAwMDQ4OTIgNjU1MzUgZg0KMDAwMDAwNDg5MyA2NTUzNSBmDQowMDAwMDA0ODk0IDY1NTM1IGYNCjAwMDAwMDQ4OTUgNjU1MzUgZg0KMDAwMDAwNDg5NiA2NTUzNSBmDQowMDAwMDA0ODk3IDY1NTM1IGYNCjAwMDAwMDQ4OTggNjU1MzUgZg0KMDAwMDAwNDg5OSA2NTUzNSBmDQowMDAwMDA0OTAwIDY1NTM1IGYNCjAwMDAwMDQ5MDEgNjU1MzUgZg0KMDAwMDAwNDkwMiA2NTUzNSBmDQowMDAwMDA0OTAzIDY1NTM1IGYNCjAwMDAwMDQ5MDQgNjU1MzUgZg0KMDAwMDAwNDkwNSA2NTUzNSBmDQowMDAwMDA0OTA2IDY1NTM1IGYNCjAwMDAwMDQ5MDcgNjU1MzUgZg0KMDAwMDAwNDkwOCA2NTUzNSBmDQowMDAwMDA0OTA5IDY1NTM1IGYNCjAwMDAwMDQ5MTAgNjU1MzUgZg0KMDAwMDAwNDkxMSA2NTUzNSBmDQowMDAwMDA0OTEyIDY1NTM1IGYNCjAwMDAwMDQ5MTMgNjU1MzUgZg0KMDAwMDAwNDkxNCA2NTUzNSBmDQowMDAwMDA0OTE1IDY1NTM1IGYNCjAwMDAwMDQ5MTYgNjU1MzUgZg0KMDAwMDAwNDkxNyA2NTUzNSBmDQowMDAwMDA0OTE4IDY1NTM1IGYNCjAwMDAwMDQ5MTkgNjU1MzUgZg0KMDAwMDAwNDkyMCA2NTUzNSBmDQowMDAwMDA0OTIxIDY1NTM1IGYNCjAwMDAwMDQ5MjIgNjU1MzUgZg0KMDAwMDAwNDkyMyA2NTUzNSBmDQowMDAwMDA0OTI0IDY1NTM1IGYNCjAwMDAwMDQ5MjUgNjU1MzUgZg0KMDAwMDAwNDkyNiA2NTUzNSBmDQowMDAwMDA0OTI3IDY1NTM1IGYNCjAwMDAwMDQ5MjggNjU1MzUgZg0KMDAwMDAwNDkyOSA2NTUzNSBmDQowMDAwMDA0OTMwIDY1NTM1IGYNCjAwMDAwMDQ5MzEgNjU1MzUgZg0KMDAwMDAwNDkzMiA2NTUzNSBmDQowMDAwMDA0OTMzIDY1NTM1IGYNCjAwMDAwMDQ5MzQgNjU1MzUgZg0KMDAwMDAwNDkzNSA2NTUzNSBmDQowMDAwMDA0OTM2IDY1NTM1IGYNCjAwMDAwMDQ5MzcgNjU1MzUgZg0KMDAwMDAwNDkzOCA2NTUzNSBmDQowMDAwMDA0OTM5IDY1NTM1IGYNCjAwMDAwMDQ5NDAgNjU1MzUgZg0KMDAwMDAwNDk0MSA2NTUzNSBmDQowMDAwMDA0OTQyIDY1NTM1IGYNCjAwMDAwMDQ5NDMgNjU1MzUgZg0KMDAwMDAwNDk0NCA2NTUzNSBmDQowMDAwMDA0OTQ1IDY1NTM1IGYNCjAwMDAwMDQ5NDYgNjU1MzUgZg0KMDAwMDAwNDk0NyA2NTUzNSBmDQowMDAwMDA0OTQ4IDY1NTM1IGYNCjAwMDAwMDQ5NDkgNjU1MzUgZg0KMDAwMDAwNDk1MCA2NTUzNSBmDQowMDAwMDA0OTUxIDY1NTM1IGYNCjAwMDAwMDQ5NTIgNjU1MzUgZg0KMDAwMDAwNDk1MyA2NTUzNSBmDQowMDAwMDA0OTU0IDY1NTM1IGYNCjAwMDAwMDQ5NTUgNjU1MzUgZg0KMDAwMDAwNDk1NiA2NTUzNSBmDQowMDAwMDA0OTU3IDY1NTM1IGYNCjAwMDAwMDQ5NTggNjU1MzUgZg0KMDAwMDAwNDk1OSA2NTUzNSBmDQowMDAwMDA0OTYwIDY1NTM1IGYNCjAwMDAwMDQ5NjEgNjU1MzUgZg0KMDAwMDAwNDk2MiA2NTUzNSBmDQowMDAwMDA0OTYzIDY1NTM1IGYNCjAwMDAwMDQ5NjQgNjU1MzUgZg0KMDAwMDAwNDk2NSA2NTUzNSBmDQowMDAwMDA0OTY2IDY1NTM1IGYNCjAwMDAwMDQ5NjcgNjU1MzUgZg0KMDAwMDAwNDk2OCA2NTUzNSBmDQowMDAwMDA0OTY5IDY1NTM1IGYNCjAwMDAwMDQ5NzAgNjU1MzUgZg0KMDAwMDAwNDk3MSA2NTUzNSBmDQowMDAwMDA0OTcyIDY1NTM1IGYNCjAwMDAwMDQ5NzMgNjU1MzUgZg0KMDAwMDAwNDk3NCA2NTUzNSBmDQowMDAwMDA0OTc1IDY1NTM1IGYNCjAwMDAwMDQ5NzYgNjU1MzUgZg0KMDAwMDAwNDk3NyA2NTUzNSBmDQowMDAwMDA0OTc4IDY1NTM1IGYNCjAwMDAwMDQ5NzkgNjU1MzUgZg0KMDAwMDAwNDk4MCA2NTUzNSBmDQowMDAwMDA0OTgxIDY1NTM1IGYNCjAwMDAwMDQ5ODIgNjU1MzUgZg0KMDAwMDAwNDk4MyA2NTUzNSBmDQowMDAwMDA0OTg0IDY1NTM1IGYNCjAwMDAwMDQ5ODUgNjU1MzUgZg0KMDAwMDAwNDk4NiA2NTUzNSBmDQowMDAwMDA0OTg3IDY1NTM1IGYNCjAwMDAwMDQ5ODggNjU1MzUgZg0KMDAwMDAwNDk4OSA2NTUzNSBmDQowMDAwMDA0OTkwIDY1NTM1IGYNCjAwMDAwMDQ5OTEgNjU1MzUgZg0KMDAwMDAwNDk5MiA2NTUzNSBmDQowMDAwMDA0OTkzIDY1NTM1IGYNCjAwMDAwMDQ5OTQgNjU1MzUgZg0KMDAwMDAwNDk5NSA2NTUzNSBmDQowMDAwMDA0OTk2IDY1NTM1IGYNCjAwMDAwMDQ5OTcgNjU1MzUgZg0KMDAwMDAwNDk5OCA2NTUzNSBmDQowMDAwMDA0OTk5IDY1NTM1IGYNCjAwMDAwMDUwMDAgNjU1MzUgZg0KMDAwMDAwNTAwMSA2NTUzNSBmDQowMDAwMDA1MDAyIDY1NTM1IGYNCjAwMDAwMDUwMDMgNjU1MzUgZg0KMDAwMDAwNTAwNCA2NTUzNSBmDQowMDAwMDA1MDA1IDY1NTM1IGYNCjAwMDAwMDUwMDYgNjU1MzUgZg0KMDAwMDAwNTAwNyA2NTUzNSBmDQowMDAwMDA1MDA4IDY1NTM1IGYNCjAwMDAwMDUwMDkgNjU1MzUgZg0KMDAwMDAwNTAxMCA2NTUzNSBmDQowMDAwMDA1MDExIDY1NTM1IGYNCjAwMDAwMDUwMTIgNjU1MzUgZg0KMDAwMDAwNTAxMyA2NTUzNSBmDQowMDAwMDA1MDE0IDY1NTM1IGYNCjAwMDAwMDUwMTUgNjU1MzUgZg0KMDAwMDAwNTAxNiA2NTUzNSBmDQowMDAwMDA1MDE3IDY1NTM1IGYNCjAwMDAwMDUwMTggNjU1MzUgZg0KMDAwMDAwNTAxOSA2NTUzNSBmDQowMDAwMDA1MDIwIDY1NTM1IGYNCjAwMDAwMDUwMjEgNjU1MzUgZg0KMDAwMDAwNTAyMiA2NTUzNSBmDQowMDAwMDA1MDIzIDY1NTM1IGYNCjAwMDAwMDUwMjQgNjU1MzUgZg0KMDAwMDAwNTAyNSA2NTUzNSBmDQowMDAwMDA1MDI2IDY1NTM1IGYNCjAwMDAwMDUwMjcgNjU1MzUgZg0KMDAwMDAwNTAyOCA2NTUzNSBmDQowMDAwMDA1MDI5IDY1NTM1IGYNCjAwMDAwMDUwMzAgNjU1MzUgZg0KMDAwMDAwNTAzMSA2NTUzNSBmDQowMDAwMDA1MDMyIDY1NTM1IGYNCjAwMDAwMDUwMzMgNjU1MzUgZg0KMDAwMDAwNTAzNCA2NTUzNSBmDQowMDAwMDA1MDM1IDY1NTM1IGYNCjAwMDAwMDUwMzYgNjU1MzUgZg0KMDAwMDAwNTAzNyA2NTUzNSBmDQowMDAwMDA1MDM4IDY1NTM1IGYNCjAwMDAwMDUwMzkgNjU1MzUgZg0KMDAwMDAwNTA0MCA2NTUzNSBmDQowMDAwMDA1MDQxIDY1NTM1IGYNCjAwMDAwMDUwNDIgNjU1MzUgZg0KMDAwMDAwNTA0MyA2NTUzNSBmDQowMDAwMDA1MDQ0IDY1NTM1IGYNCjAwMDAwMDUwNDUgNjU1MzUgZg0KMDAwMDAwNTA0NiA2NTUzNSBmDQowMDAwMDA1MDQ3IDY1NTM1IGYNCjAwMDAwMDUwNDggNjU1MzUgZg0KMDAwMDAwNTA0OSA2NTUzNSBmDQowMDAwMDA1MDUwIDY1NTM1IGYNCjAwMDAwMDUwNTEgNjU1MzUgZg0KMDAwMDAwNTA1MiA2NTUzNSBmDQowMDAwMDA1MDUzIDY1NTM1IGYNCjAwMDAwMDUwNTQgNjU1MzUgZg0KMDAwMDAwNTA1NSA2NTUzNSBmDQowMDAwMDA1MDU2IDY1NTM1IGYNCjAwMDAwMDUwNTcgNjU1MzUgZg0KMDAwMDAwNTA1OCA2NTUzNSBmDQowMDAwMDA1MDU5IDY1NTM1IGYNCjAwMDAwMDUwNjAgNjU1MzUgZg0KMDAwMDAwNTA2MSA2NTUzNSBmDQowMDAwMDA1MDYyIDY1NTM1IGYNCjAwMDAwMDUwNjMgNjU1MzUgZg0KMDAwMDAwNTA2NCA2NTUzNSBmDQowMDAwMDA1MDY1IDY1NTM1IGYNCjAwMDAwMDUwNjYgNjU1MzUgZg0KMDAwMDAwNTA2NyA2NTUzNSBmDQowMDAwMDA1MDY4IDY1NTM1IGYNCjAwMDAwMDUwNjkgNjU1MzUgZg0KMDAwMDAwNTA3MCA2NTUzNSBmDQowMDAwMDA1MDcxIDY1NTM1IGYNCjAwMDAwMDUwNzIgNjU1MzUgZg0KMDAwMDAwNTA3MyA2NTUzNSBmDQowMDAwMDA1MDc0IDY1NTM1IGYNCjAwMDAwMDUwNzUgNjU1MzUgZg0KMDAwMDAwNTA3NiA2NTUzNSBmDQowMDAwMDA1MDc3IDY1NTM1IGYNCjAwMDAwMDUwNzggNjU1MzUgZg0KMDAwMDAwNTA3OSA2NTUzNSBmDQowMDAwMDA1MDgwIDY1NTM1IGYNCjAwMDAwMDUwODEgNjU1MzUgZg0KMDAwMDAwNTA4MiA2NTUzNSBmDQowMDAwMDA1MDgzIDY1NTM1IGYNCjAwMDAwMDUwODQgNjU1MzUgZg0KMDAwMDAwNTA4NSA2NTUzNSBmDQowMDAwMDA1MDg2IDY1NTM1IGYNCjAwMDAwMDUwODcgNjU1MzUgZg0KMDAwMDAwNTA4OCA2NTUzNSBmDQowMDAwMDA1MDg5IDY1NTM1IGYNCjAwMDAwMDUwOTAgNjU1MzUgZg0KMDAwMDAwNTA5MSA2NTUzNSBmDQowMDAwMDA1MDkyIDY1NTM1IGYNCjAwMDAwMDUwOTMgNjU1MzUgZg0KMDAwMDAwNTA5NCA2NTUzNSBmDQowMDAwMDA1MDk1IDY1NTM1IGYNCjAwMDAwMDUwOTYgNjU1MzUgZg0KMDAwMDAwNTA5NyA2NTUzNSBmDQowMDAwMDA1MDk4IDY1NTM1IGYNCjAwMDAwMDUwOTkgNjU1MzUgZg0KMDAwMDAwNTEwMCA2NTUzNSBmDQowMDAwMDA1MTAxIDY1NTM1IGYNCjAwMDAwMDUxMDIgNjU1MzUgZg0KMDAwMDAwNTEwMyA2NTUzNSBmDQowMDAwMDA1MTA0IDY1NTM1IGYNCjAwMDAwMDUxMDUgNjU1MzUgZg0KMDAwMDAwNTEwNiA2NTUzNSBmDQowMDAwMDA1MTA3IDY1NTM1IGYNCjAwMDAwMDUxMDggNjU1MzUgZg0KMDAwMDAwNTEwOSA2NTUzNSBmDQowMDAwMDA1MTEwIDY1NTM1IGYNCjAwMDAwMDUxMTEgNjU1MzUgZg0KMDAwMDAwNTExMiA2NTUzNSBmDQowMDAwMDA1MTEzIDY1NTM1IGYNCjAwMDAwMDUxMTQgNjU1MzUgZg0KMDAwMDAwNTExNSA2NTUzNSBmDQowMDAwMDA1MTE2IDY1NTM1IGYNCjAwMDAwMDUxMTcgNjU1MzUgZg0KMDAwMDAwNTExOCA2NTUzNSBmDQowMDAwMDA1MTE5IDY1NTM1IGYNCjAwMDAwMDUxMjAgNjU1MzUgZg0KMDAwMDAwNTEyMSA2NTUzNSBmDQowMDAwMDA1MTIyIDY1NTM1IGYNCjAwMDAwMDUxMjMgNjU1MzUgZg0KMDAwMDAwNTEyNCA2NTUzNSBmDQowMDAwMDA1MTI1IDY1NTM1IGYNCjAwMDAwMDUxMjYgNjU1MzUgZg0KMDAwMDAwNTEyNyA2NTUzNSBmDQowMDAwMDA1MTI4IDY1NTM1IGYNCjAwMDAwMDUxMjkgNjU1MzUgZg0KMDAwMDAwNTEzMCA2NTUzNSBmDQowMDAwMDA1MTMxIDY1NTM1IGYNCjAwMDAwMDUxMzIgNjU1MzUgZg0KMDAwMDAwNTEzMyA2NTUzNSBmDQowMDAwMDA1MTM0IDY1NTM1IGYNCjAwMDAwMDUxMzUgNjU1MzUgZg0KMDAwMDAwNTEzNiA2NTUzNSBmDQowMDAwMDA1MTM3IDY1NTM1IGYNCjAwMDAwMDUxMzggNjU1MzUgZg0KMDAwMDAwNTEzOSA2NTUzNSBmDQowMDAwMDA1MTQwIDY1NTM1IGYNCjAwMDAwMDUxNDEgNjU1MzUgZg0KMDAwMDAwNTE0MiA2NTUzNSBmDQowMDAwMDA1MTQzIDY1NTM1IGYNCjAwMDAwMDUxNDQgNjU1MzUgZg0KMDAwMDAwNTE0NSA2NTUzNSBmDQowMDAwMDA1MTQ2IDY1NTM1IGYNCjAwMDAwMDUxNDcgNjU1MzUgZg0KMDAwMDAwNTE0OCA2NTUzNSBmDQowMDAwMDA1MTQ5IDY1NTM1IGYNCjAwMDAwMDUxNTAgNjU1MzUgZg0KMDAwMDAwNTE1MSA2NTUzNSBmDQowMDAwMDA1MTUyIDY1NTM1IGYNCjAwMDAwMDUxNTMgNjU1MzUgZg0KMDAwMDAwNTE1NCA2NTUzNSBmDQowMDAwMDA1MTU1IDY1NTM1IGYNCjAwMDAwMDUxNTYgNjU1MzUgZg0KMDAwMDAwNTE1NyA2NTUzNSBmDQowMDAwMDA1MTU4IDY1NTM1IGYNCjAwMDAwMDUxNTkgNjU1MzUgZg0KMDAwMDAwNTE2MCA2NTUzNSBmDQowMDAwMDA1MTYxIDY1NTM1IGYNCjAwMDAwMDUxNjIgNjU1MzUgZg0KMDAwMDAwNTE2MyA2NTUzNSBmDQowMDAwMDA1MTY0IDY1NTM1IGYNCjAwMDAwMDUxNjUgNjU1MzUgZg0KMDAwMDAwNTE2NiA2NTUzNSBmDQowMDAwMDA1MTY3IDY1NTM1IGYNCjAwMDAwMDUxNjggNjU1MzUgZg0KMDAwMDAwNTE2OSA2NTUzNSBmDQowMDAwMDA1MTcwIDY1NTM1IGYNCjAwMDAwMDUxNzEgNjU1MzUgZg0KMDAwMDAwNTE3MiA2NTUzNSBmDQowMDAwMDA1MTczIDY1NTM1IGYNCjAwMDAwMDUxNzQgNjU1MzUgZg0KMDAwMDAwNTE3NSA2NTUzNSBmDQowMDAwMDA1MTc2IDY1NTM1IGYNCjAwMDAwMDUxNzcgNjU1MzUgZg0KMDAwMDAwNTE3OCA2NTUzNSBmDQowMDAwMDA1MTc5IDY1NTM1IGYNCjAwMDAwMDUxODAgNjU1MzUgZg0KMDAwMDAwNTE4MSA2NTUzNSBmDQowMDAwMDA1MTgyIDY1NTM1IGYNCjAwMDAwMDUxODMgNjU1MzUgZg0KMDAwMDAwNTE4NCA2NTUzNSBmDQowMDAwMDA1MTg1IDY1NTM1IGYNCjAwMDAwMDUxODYgNjU1MzUgZg0KMDAwMDAwNTE4NyA2NTUzNSBmDQowMDAwMDA1MTg4IDY1NTM1IGYNCjAwMDAwMDUxODkgNjU1MzUgZg0KMDAwMDAwNTE5MCA2NTUzNSBmDQowMDAwMDA1MTkxIDY1NTM1IGYNCjAwMDAwMDUxOTIgNjU1MzUgZg0KMDAwMDAwNTE5MyA2NTUzNSBmDQowMDAwMDA1MTk0IDY1NTM1IGYNCjAwMDAwMDUxOTUgNjU1MzUgZg0KMDAwMDAwNTE5NiA2NTUzNSBmDQowMDAwMDA1MTk3IDY1NTM1IGYNCjAwMDAwMDUxOTggNjU1MzUgZg0KMDAwMDAwNTE5OSA2NTUzNSBmDQowMDAwMDA1MjAwIDY1NTM1IGYNCjAwMDAwMDUyMDEgNjU1MzUgZg0KMDAwMDAwNTIwMiA2NTUzNSBmDQowMDAwMDA1MjAzIDY1NTM1IGYNCjAwMDAwMDUyMDQgNjU1MzUgZg0KMDAwMDAwNTIwNSA2NTUzNSBmDQowMDAwMDA1MjA2IDY1NTM1IGYNCjAwMDAwMDUyMDcgNjU1MzUgZg0KMDAwMDAwNTIwOCA2NTUzNSBmDQowMDAwMDA1MjA5IDY1NTM1IGYNCjAwMDAwMDUyMTAgNjU1MzUgZg0KMDAwMDAwNTIxMSA2NTUzNSBmDQowMDAwMDA1MjEyIDY1NTM1IGYNCjAwMDAwMDUyMTMgNjU1MzUgZg0KMDAwMDAwNTIxNCA2NTUzNSBmDQowMDAwMDA1MjE1IDY1NTM1IGYNCjAwMDAwMDUyMTYgNjU1MzUgZg0KMDAwMDAwNTIxNyA2NTUzNSBmDQowMDAwMDA1MjE4IDY1NTM1IGYNCjAwMDAwMDUyMTkgNjU1MzUgZg0KMDAwMDAwNTIyMCA2NTUzNSBmDQowMDAwMDA1MjIxIDY1NTM1IGYNCjAwMDAwMDUyMjIgNjU1MzUgZg0KMDAwMDAwNTIyMyA2NTUzNSBmDQowMDAwMDA1MjI0IDY1NTM1IGYNCjAwMDAwMDUyMjUgNjU1MzUgZg0KMDAwMDAwNTIyNiA2NTUzNSBmDQowMDAwMDA1MjI3IDY1NTM1IGYNCjAwMDAwMDUyMjggNjU1MzUgZg0KMDAwMDAwNTIyOSA2NTUzNSBmDQowMDAwMDA1MjMwIDY1NTM1IGYNCjAwMDAwMDUyMzEgNjU1MzUgZg0KMDAwMDAwNTIzMiA2NTUzNSBmDQowMDAwMDA1MjMzIDY1NTM1IGYNCjAwMDAwMDUyMzQgNjU1MzUgZg0KMDAwMDAwNTIzNSA2NTUzNSBmDQowMDAwMDA1MjM2IDY1NTM1IGYNCjAwMDAwMDUyMzcgNjU1MzUgZg0KMDAwMDAwNTIzOCA2NTUzNSBmDQowMDAwMDA1MjM5IDY1NTM1IGYNCjAwMDAwMDUyNDAgNjU1MzUgZg0KMDAwMDAwNTI0MSA2NTUzNSBmDQowMDAwMDA1MjQyIDY1NTM1IGYNCjAwMDAwMDUyNDMgNjU1MzUgZg0KMDAwMDAwNTI0NCA2NTUzNSBmDQowMDAwMDA1MjQ1IDY1NTM1IGYNCjAwMDAwMDUyNDYgNjU1MzUgZg0KMDAwMDAwNTI0NyA2NTUzNSBmDQowMDAwMDA1MjQ4IDY1NTM1IGYNCjAwMDAwMDUyNDkgNjU1MzUgZg0KMDAwMDAwNTI1MCA2NTUzNSBmDQowMDAwMDA1MjUxIDY1NTM1IGYNCjAwMDAwMDUyNTIgNjU1MzUgZg0KMDAwMDAwNTI1MyA2NTUzNSBmDQowMDAwMDA1MjU0IDY1NTM1IGYNCjAwMDAwMDUyNTUgNjU1MzUgZg0KMDAwMDAwNTI1NiA2NTUzNSBmDQowMDAwMDA1MjU3IDY1NTM1IGYNCjAwMDAwMDUyNTggNjU1MzUgZg0KMDAwMDAwNTI1OSA2NTUzNSBmDQowMDAwMDA1MjYwIDY1NTM1IGYNCjAwMDAwMDUyNjEgNjU1MzUgZg0KMDAwMDAwNTI2MiA2NTUzNSBmDQowMDAwMDA1MjYzIDY1NTM1IGYNCjAwMDAwMDUyNjQgNjU1MzUgZg0KMDAwMDAwNTI2NSA2NTUzNSBmDQowMDAwMDA1MjY2IDY1NTM1IGYNCjAwMDAwMDUyNjcgNjU1MzUgZg0KMDAwMDAwNTI2OCA2NTUzNSBmDQowMDAwMDA1MjY5IDY1NTM1IGYNCjAwMDAwMDUyNzAgNjU1MzUgZg0KMDAwMDAwNTI3MSA2NTUzNSBmDQowMDAwMDA1MjcyIDY1NTM1IGYNCjAwMDAwMDUyNzMgNjU1MzUgZg0KMDAwMDAwNTI3NCA2NTUzNSBmDQowMDAwMDA1Mjc1IDY1NTM1IGYNCjAwMDAwMDUyNzYgNjU1MzUgZg0KMDAwMDAwNTI3NyA2NTUzNSBmDQowMDAwMDA1Mjc4IDY1NTM1IGYNCjAwMDAwMDUyNzkgNjU1MzUgZg0KMDAwMDAwNTI4MCA2NTUzNSBmDQowMDAwMDA1MjgxIDY1NTM1IGYNCjAwMDAwMDUyODIgNjU1MzUgZg0KMDAwMDAwNTI4MyA2NTUzNSBmDQowMDAwMDA1Mjg0IDY1NTM1IGYNCjAwMDAwMDUyODUgNjU1MzUgZg0KMDAwMDAwNTI4NiA2NTUzNSBmDQowMDAwMDA1Mjg3IDY1NTM1IGYNCjAwMDAwMDUyODggNjU1MzUgZg0KMDAwMDAwNTI4OSA2NTUzNSBmDQowMDAwMDA1MjkwIDY1NTM1IGYNCjAwMDAwMDUyOTEgNjU1MzUgZg0KMDAwMDAwNTI5MiA2NTUzNSBmDQowMDAwMDA1MjkzIDY1NTM1IGYNCjAwMDAwMDUyOTQgNjU1MzUgZg0KMDAwMDAwNTI5NSA2NTUzNSBmDQowMDAwMDA1Mjk2IDY1NTM1IGYNCjAwMDAwMDUyOTcgNjU1MzUgZg0KMDAwMDAwNTI5OCA2NTUzNSBmDQowMDAwMDA1Mjk5IDY1NTM1IGYNCjAwMDAwMDUzMDAgNjU1MzUgZg0KMDAwMDAwNTMwMSA2NTUzNSBmDQowMDAwMDA1MzAyIDY1NTM1IGYNCjAwMDAwMDUzMDMgNjU1MzUgZg0KMDAwMDAwNTMwNCA2NTUzNSBmDQowMDAwMDA1MzA1IDY1NTM1IGYNCjAwMDAwMDUzMDYgNjU1MzUgZg0KMDAwMDAwNTMwNyA2NTUzNSBmDQowMDAwMDA1MzA4IDY1NTM1IGYNCjAwMDAwMDUzMDkgNjU1MzUgZg0KMDAwMDAwNTMxMCA2NTUzNSBmDQowMDAwMDA1MzExIDY1NTM1IGYNCjAwMDAwMDUzMTIgNjU1MzUgZg0KMDAwMDAwNTMxMyA2NTUzNSBmDQowMDAwMDA1MzE0IDY1NTM1IGYNCjAwMDAwMDUzMTUgNjU1MzUgZg0KMDAwMDAwNTMxNiA2NTUzNSBmDQowMDAwMDA1MzE3IDY1NTM1IGYNCjAwMDAwMDUzMTggNjU1MzUgZg0KMDAwMDAwNTMxOSA2NTUzNSBmDQowMDAwMDA1MzIwIDY1NTM1IGYNCjAwMDAwMDUzMjEgNjU1MzUgZg0KMDAwMDAwNTMyMiA2NTUzNSBmDQowMDAwMDA1MzIzIDY1NTM1IGYNCjAwMDAwMDUzMjQgNjU1MzUgZg0KMDAwMDAwNTMyNSA2NTUzNSBmDQowMDAwMDA1MzI2IDY1NTM1IGYNCjAwMDAwMDUzMjcgNjU1MzUgZg0KMDAwMDAwNTMyOCA2NTUzNSBmDQowMDAwMDA1MzI5IDY1NTM1IGYNCjAwMDAwMDUzMzAgNjU1MzUgZg0KMDAwMDAwNTMzMSA2NTUzNSBmDQowMDAwMDA1MzMyIDY1NTM1IGYNCjAwMDAwMDUzMzMgNjU1MzUgZg0KMDAwMDAwNTMzNCA2NTUzNSBmDQowMDAwMDA1MzM1IDY1NTM1IGYNCjAwMDAwMDUzMzYgNjU1MzUgZg0KMDAwMDAwNTMzNyA2NTUzNSBmDQowMDAwMDA1MzM4IDY1NTM1IGYNCjAwMDAwMDUzMzkgNjU1MzUgZg0KMDAwMDAwNTM0MCA2NTUzNSBmDQowMDAwMDA1MzQxIDY1NTM1IGYNCjAwMDAwMDUzNDIgNjU1MzUgZg0KMDAwMDAwNTM0MyA2NTUzNSBmDQowMDAwMDA1MzQ0IDY1NTM1IGYNCjAwMDAwMDUzNDUgNjU1MzUgZg0KMDAwMDAwNTM0NiA2NTUzNSBmDQowMDAwMDA1MzQ3IDY1NTM1IGYNCjAwMDAwMDUzNDggNjU1MzUgZg0KMDAwMDAwNTM0OSA2NTUzNSBmDQowMDAwMDA1MzUwIDY1NTM1IGYNCjAwMDAwMDUzNTEgNjU1MzUgZg0KMDAwMDAwNTM1MiA2NTUzNSBmDQowMDAwMDA1MzUzIDY1NTM1IGYNCjAwMDAwMDUzNTQgNjU1MzUgZg0KMDAwMDAwNTM1NSA2NTUzNSBmDQowMDAwMDA1MzU2IDY1NTM1IGYNCjAwMDAwMDUzNTcgNjU1MzUgZg0KMDAwMDAwNTM1OCA2NTUzNSBmDQowMDAwMDA1MzU5IDY1NTM1IGYNCjAwMDAwMDUzNjAgNjU1MzUgZg0KMDAwMDAwNTM2MSA2NTUzNSBmDQowMDAwMDA1MzYyIDY1NTM1IGYNCjAwMDAwMDUzNjMgNjU1MzUgZg0KMDAwMDAwNTM2NCA2NTUzNSBmDQowMDAwMDA1MzY1IDY1NTM1IGYNCjAwMDAwMDUzNjYgNjU1MzUgZg0KMDAwMDAwNTM2NyA2NTUzNSBmDQowMDAwMDA1MzY4IDY1NTM1IGYNCjAwMDAwMDUzNjkgNjU1MzUgZg0KMDAwMDAwNTM3MCA2NTUzNSBmDQowMDAwMDA1MzcxIDY1NTM1IGYNCjAwMDAwMDUzNzIgNjU1MzUgZg0KMDAwMDAwNTM3MyA2NTUzNSBmDQowMDAwMDA1Mzc0IDY1NTM1IGYNCjAwMDAwMDUzNzUgNjU1MzUgZg0KMDAwMDAwNTM3NiA2NTUzNSBmDQowMDAwMDA1Mzc3IDY1NTM1IGYNCjAwMDAwMDUzNzggNjU1MzUgZg0KMDAwMDAwNTM3OSA2NTUzNSBmDQowMDAwMDA1MzgwIDY1NTM1IGYNCjAwMDAwMDUzODEgNjU1MzUgZg0KMDAwMDAwNTM4MiA2NTUzNSBmDQowMDAwMDA1MzgzIDY1NTM1IGYNCjAwMDAwMDUzODQgNjU1MzUgZg0KMDAwMDAwNTM4NSA2NTUzNSBmDQowMDAwMDA1Mzg2IDY1NTM1IGYNCjAwMDAwMDUzODcgNjU1MzUgZg0KMDAwMDAwNTM4OCA2NTUzNSBmDQowMDAwMDA1Mzg5IDY1NTM1IGYNCjAwMDAwMDUzOTAgNjU1MzUgZg0KMDAwMDAwNTM5MSA2NTUzNSBmDQowMDAwMDA1MzkyIDY1NTM1IGYNCjAwMDAwMDUzOTMgNjU1MzUgZg0KMDAwMDAwNTM5NCA2NTUzNSBmDQowMDAwMDA1Mzk1IDY1NTM1IGYNCjAwMDAwMDUzOTYgNjU1MzUgZg0KMDAwMDAwNTM5NyA2NTUzNSBmDQowMDAwMDA1Mzk4IDY1NTM1IGYNCjAwMDAwMDUzOTkgNjU1MzUgZg0KMDAwMDAwNTQwMCA2NTUzNSBmDQowMDAwMDA1NDAxIDY1NTM1IGYNCjAwMDAwMDU0MDIgNjU1MzUgZg0KMDAwMDAwNTQwMyA2NTUzNSBmDQowMDAwMDA1NDA0IDY1NTM1IGYNCjAwMDAwMDU0MDUgNjU1MzUgZg0KMDAwMDAwNTQwNiA2NTUzNSBmDQowMDAwMDA1NDA3IDY1NTM1IGYNCjAwMDAwMDU0MDggNjU1MzUgZg0KMDAwMDAwNTQwOSA2NTUzNSBmDQowMDAwMDA1NDEwIDY1NTM1IGYNCjAwMDAwMDU0MTEgNjU1MzUgZg0KMDAwMDAwNTQxMiA2NTUzNSBmDQowMDAwMDA1NDEzIDY1NTM1IGYNCjAwMDAwMDU0MTQgNjU1MzUgZg0KMDAwMDAwNTQxNSA2NTUzNSBmDQowMDAwMDA1NDE2IDY1NTM1IGYNCjAwMDAwMDU0MTcgNjU1MzUgZg0KMDAwMDAwNTQxOCA2NTUzNSBmDQowMDAwMDA1NDE5IDY1NTM1IGYNCjAwMDAwMDU0MjAgNjU1MzUgZg0KMDAwMDAwNTQyMSA2NTUzNSBmDQowMDAwMDA1NDIyIDY1NTM1IGYNCjAwMDAwMDU0MjMgNjU1MzUgZg0KMDAwMDAwNTQyNCA2NTUzNSBmDQowMDAwMDA1NDI1IDY1NTM1IGYNCjAwMDAwMDU0MjYgNjU1MzUgZg0KMDAwMDAwNTQyNyA2NTUzNSBmDQowMDAwMDA1NDI4IDY1NTM1IGYNCjAwMDAwMDU0MjkgNjU1MzUgZg0KMDAwMDAwNTQzMCA2NTUzNSBmDQowMDAwMDA1NDMxIDY1NTM1IGYNCjAwMDAwMDU0MzIgNjU1MzUgZg0KMDAwMDAwNTQzMyA2NTUzNSBmDQowMDAwMDA1NDM0IDY1NTM1IGYNCjAwMDAwMDU0MzUgNjU1MzUgZg0KMDAwMDAwNTQzNiA2NTUzNSBmDQowMDAwMDA1NDM3IDY1NTM1IGYNCjAwMDAwMDU0MzggNjU1MzUgZg0KMDAwMDAwNTQzOSA2NTUzNSBmDQowMDAwMDA1NDQwIDY1NTM1IGYNCjAwMDAwMDU0NDEgNjU1MzUgZg0KMDAwMDAwNTQ0MiA2NTUzNSBmDQowMDAwMDA1NDQzIDY1NTM1IGYNCjAwMDAwMDU0NDQgNjU1MzUgZg0KMDAwMDAwNTQ0NSA2NTUzNSBmDQowMDAwMDA1NDQ2IDY1NTM1IGYNCjAwMDAwMDU0NDcgNjU1MzUgZg0KMDAwMDAwNTQ0OCA2NTUzNSBmDQowMDAwMDA1NDQ5IDY1NTM1IGYNCjAwMDAwMDU0NTAgNjU1MzUgZg0KMDAwMDAwNTQ1MSA2NTUzNSBmDQowMDAwMDA1NDUyIDY1NTM1IGYNCjAwMDAwMDU0NTMgNjU1MzUgZg0KMDAwMDAwNTQ1NCA2NTUzNSBmDQowMDAwMDA1NDU1IDY1NTM1IGYNCjAwMDAwMDU0NTYgNjU1MzUgZg0KMDAwMDAwNTQ1NyA2NTUzNSBmDQowMDAwMDA1NDU4IDY1NTM1IGYNCjAwMDAwMDU0NTkgNjU1MzUgZg0KMDAwMDAwNTQ2MCA2NTUzNSBmDQowMDAwMDA1NDYxIDY1NTM1IGYNCjAwMDAwMDU0NjIgNjU1MzUgZg0KMDAwMDAwNTQ2MyA2NTUzNSBmDQowMDAwMDA1NDY0IDY1NTM1IGYNCjAwMDAwMDU0NjUgNjU1MzUgZg0KMDAwMDAwNTQ2NiA2NTUzNSBmDQowMDAwMDA1NDY3IDY1NTM1IGYNCjAwMDAwMDU0NjggNjU1MzUgZg0KMDAwMDAwNTQ2OSA2NTUzNSBmDQowMDAwMDA1NDcwIDY1NTM1IGYNCjAwMDAwMDU0NzEgNjU1MzUgZg0KMDAwMDAwNTQ3MiA2NTUzNSBmDQowMDAwMDA1NDczIDY1NTM1IGYNCjAwMDAwMDU0NzQgNjU1MzUgZg0KMDAwMDAwNTQ3NSA2NTUzNSBmDQowMDAwMDA1NDc2IDY1NTM1IGYNCjAwMDAwMDU0NzcgNjU1MzUgZg0KMDAwMDAwNTQ3OCA2NTUzNSBmDQowMDAwMDA1NDc5IDY1NTM1IGYNCjAwMDAwMDU0ODAgNjU1MzUgZg0KMDAwMDAwNTQ4MSA2NTUzNSBmDQowMDAwMDA1NDgyIDY1NTM1IGYNCjAwMDAwMDU0ODMgNjU1MzUgZg0KMDAwMDAwNTQ4NCA2NTUzNSBmDQowMDAwMDA1NDg1IDY1NTM1IGYNCjAwMDAwMDU0ODYgNjU1MzUgZg0KMDAwMDAwNTQ4NyA2NTUzNSBmDQowMDAwMDA1NDg4IDY1NTM1IGYNCjAwMDAwMDU0ODkgNjU1MzUgZg0KMDAwMDAwNTQ5MCA2NTUzNSBmDQowMDAwMDA1NDkxIDY1NTM1IGYNCjAwMDAwMDU0OTIgNjU1MzUgZg0KMDAwMDAwNTQ5MyA2NTUzNSBmDQowMDAwMDA1NDk0IDY1NTM1IGYNCjAwMDAwMDU0OTUgNjU1MzUgZg0KMDAwMDAwNTQ5NiA2NTUzNSBmDQowMDAwMDA1NDk3IDY1NTM1IGYNCjAwMDAwMDU0OTggNjU1MzUgZg0KMDAwMDAwNTQ5OSA2NTUzNSBmDQowMDAwMDA1NTAwIDY1NTM1IGYNCjAwMDAwMDU1MDEgNjU1MzUgZg0KMDAwMDAwNTUwMiA2NTUzNSBmDQowMDAwMDA1NTAzIDY1NTM1IGYNCjAwMDAwMDU1MDQgNjU1MzUgZg0KMDAwMDAwNTUwNSA2NTUzNSBmDQowMDAwMDA1NTA2IDY1NTM1IGYNCjAwMDAwMDU1MDcgNjU1MzUgZg0KMDAwMDAwNTUwOCA2NTUzNSBmDQowMDAwMDA1NTA5IDY1NTM1IGYNCjAwMDAwMDU1MTAgNjU1MzUgZg0KMDAwMDAwNTUxMSA2NTUzNSBmDQowMDAwMDA1NTEyIDY1NTM1IGYNCjAwMDAwMDU1MTMgNjU1MzUgZg0KMDAwMDAwNTUxNCA2NTUzNSBmDQowMDAwMDA1NTE1IDY1NTM1IGYNCjAwMDAwMDU1MTYgNjU1MzUgZg0KMDAwMDAwNTUxNyA2NTUzNSBmDQowMDAwMDA1NTE4IDY1NTM1IGYNCjAwMDAwMDU1MTkgNjU1MzUgZg0KMDAwMDAwNTUyMCA2NTUzNSBmDQowMDAwMDA1NTIxIDY1NTM1IGYNCjAwMDAwMDU1MjIgNjU1MzUgZg0KMDAwMDAwNTUyMyA2NTUzNSBmDQowMDAwMDA1NTI0IDY1NTM1IGYNCjAwMDAwMDU1MjUgNjU1MzUgZg0KMDAwMDAwNTUyNiA2NTUzNSBmDQowMDAwMDA1NTI3IDY1NTM1IGYNCjAwMDAwMDU1MjggNjU1MzUgZg0KMDAwMDAwNTUyOSA2NTUzNSBmDQowMDAwMDA1NTMwIDY1NTM1IGYNCjAwMDAwMDU1MzEgNjU1MzUgZg0KMDAwMDAwNTUzMiA2NTUzNSBmDQowMDAwMDA1NTMzIDY1NTM1IGYNCjAwMDAwMDU1MzQgNjU1MzUgZg0KMDAwMDAwNTUzNSA2NTUzNSBmDQowMDAwMDA1NTM2IDY1NTM1IGYNCjAwMDAwMDU1MzcgNjU1MzUgZg0KMDAwMDAwNTUzOCA2NTUzNSBmDQowMDAwMDA1NTM5IDY1NTM1IGYNCjAwMDAwMDU1NDAgNjU1MzUgZg0KMDAwMDAwNTU0MSA2NTUzNSBmDQowMDAwMDA1NTQyIDY1NTM1IGYNCjAwMDAwMDU1NDMgNjU1MzUgZg0KMDAwMDAwNTU0NCA2NTUzNSBmDQowMDAwMDA1NTQ1IDY1NTM1IGYNCjAwMDAwMDU1NDYgNjU1MzUgZg0KMDAwMDAwNTU0NyA2NTUzNSBmDQowMDAwMDA1NTQ4IDY1NTM1IGYNCjAwMDAwMDU1NDkgNjU1MzUgZg0KMDAwMDAwNTU1MCA2NTUzNSBmDQowMDAwMDA1NTUxIDY1NTM1IGYNCjAwMDAwMDU1NTIgNjU1MzUgZg0KMDAwMDAwNTU1MyA2NTUzNSBmDQowMDAwMDA1NTU0IDY1NTM1IGYNCjAwMDAwMDU1NTUgNjU1MzUgZg0KMDAwMDAwNTU1NiA2NTUzNSBmDQowMDAwMDA1NTU3IDY1NTM1IGYNCjAwMDAwMDU1NTggNjU1MzUgZg0KMDAwMDAwNTU1OSA2NTUzNSBmDQowMDAwMDA1NTYwIDY1NTM1IGYNCjAwMDAwMDU1NjEgNjU1MzUgZg0KMDAwMDAwNTU2MiA2NTUzNSBmDQowMDAwMDA1NTYzIDY1NTM1IGYNCjAwMDAwMDU1NjQgNjU1MzUgZg0KMDAwMDAwNTU2NSA2NTUzNSBmDQowMDAwMDA1NTY2IDY1NTM1IGYNCjAwMDAwMDU1NjcgNjU1MzUgZg0KMDAwMDAwNTU2OCA2NTUzNSBmDQowMDAwMDA1NTY5IDY1NTM1IGYNCjAwMDAwMDU1NzAgNjU1MzUgZg0KMDAwMDAwNTU3MSA2NTUzNSBmDQowMDAwMDA1NTcyIDY1NTM1IGYNCjAwMDAwMDU1NzMgNjU1MzUgZg0KMDAwMDAwNTU3NCA2NTUzNSBmDQowMDAwMDA1NTc1IDY1NTM1IGYNCjAwMDAwMDU1NzYgNjU1MzUgZg0KMDAwMDAwNTU3NyA2NTUzNSBmDQowMDAwMDA1NTc4IDY1NTM1IGYNCjAwMDAwMDU1NzkgNjU1MzUgZg0KMDAwMDAwNTU4MCA2NTUzNSBmDQowMDAwMDA1NTgxIDY1NTM1IGYNCjAwMDAwMDU1ODIgNjU1MzUgZg0KMDAwMDAwNTU4MyA2NTUzNSBmDQowMDAwMDA1NTg0IDY1NTM1IGYNCjAwMDAwMDU1ODUgNjU1MzUgZg0KMDAwMDAwNTU4NiA2NTUzNSBmDQowMDAwMDA1NTg3IDY1NTM1IGYNCjAwMDAwMDU1ODggNjU1MzUgZg0KMDAwMDAwNTU4OSA2NTUzNSBmDQowMDAwMDA1NTkwIDY1NTM1IGYNCjAwMDAwMDU1OTEgNjU1MzUgZg0KMDAwMDAwNTU5MiA2NTUzNSBmDQowMDAwMDA1NTkzIDY1NTM1IGYNCjAwMDAwMDU1OTQgNjU1MzUgZg0KMDAwMDAwNTU5NSA2NTUzNSBmDQowMDAwMDA1NTk2IDY1NTM1IGYNCjAwMDAwMDU1OTcgNjU1MzUgZg0KMDAwMDAwNTU5OCA2NTUzNSBmDQowMDAwMDA1NTk5IDY1NTM1IGYNCjAwMDAwMDU2MDAgNjU1MzUgZg0KMDAwMDAwNTYwMSA2NTUzNSBmDQowMDAwMDA1NjAyIDY1NTM1IGYNCjAwMDAwMDU2MDMgNjU1MzUgZg0KMDAwMDAwNTYwNCA2NTUzNSBmDQowMDAwMDA1NjA1IDY1NTM1IGYNCjAwMDAwMDU2MDYgNjU1MzUgZg0KMDAwMDAwNTYwNyA2NTUzNSBmDQowMDAwMDA1NjA4IDY1NTM1IGYNCjAwMDAwMDU2MDkgNjU1MzUgZg0KMDAwMDAwNTYxMCA2NTUzNSBmDQowMDAwMDA1NjExIDY1NTM1IGYNCjAwMDAwMDU2MTIgNjU1MzUgZg0KMDAwMDAwNTYxMyA2NTUzNSBmDQowMDAwMDA1NjE0IDY1NTM1IGYNCjAwMDAwMDU2MTUgNjU1MzUgZg0KMDAwMDAwNTYxNiA2NTUzNSBmDQowMDAwMDA1NjE3IDY1NTM1IGYNCjAwMDAwMDU2MTggNjU1MzUgZg0KMDAwMDAwNTYxOSA2NTUzNSBmDQowMDAwMDA1NjIwIDY1NTM1IGYNCjAwMDAwMDU2MjEgNjU1MzUgZg0KMDAwMDAwNTYyMiA2NTUzNSBmDQowMDAwMDA1NjIzIDY1NTM1IGYNCjAwMDAwMDU2MjQgNjU1MzUgZg0KMDAwMDAwNTYyNSA2NTUzNSBmDQowMDAwMDA1NjI2IDY1NTM1IGYNCjAwMDAwMDU2MjcgNjU1MzUgZg0KMDAwMDAwNTYyOCA2NTUzNSBmDQowMDAwMDA1NjI5IDY1NTM1IGYNCjAwMDAwMDU2MzAgNjU1MzUgZg0KMDAwMDAwNTYzMSA2NTUzNSBmDQowMDAwMDA1NjMyIDY1NTM1IGYNCjAwMDAwMDU2MzMgNjU1MzUgZg0KMDAwMDAwNTYzNCA2NTUzNSBmDQowMDAwMDA1NjM1IDY1NTM1IGYNCjAwMDAwMDU2MzYgNjU1MzUgZg0KMDAwMDAwNTYzNyA2NTUzNSBmDQowMDAwMDA1NjM4IDY1NTM1IGYNCjAwMDAwMDU2MzkgNjU1MzUgZg0KMDAwMDAwNTY0MCA2NTUzNSBmDQowMDAwMDA1NjQxIDY1NTM1IGYNCjAwMDAwMDU2NDIgNjU1MzUgZg0KMDAwMDAwNTY0MyA2NTUzNSBmDQowMDAwMDA1NjQ0IDY1NTM1IGYNCjAwMDAwMDU2NDUgNjU1MzUgZg0KMDAwMDAwNTY0NiA2NTUzNSBmDQowMDAwMDA1NjQ3IDY1NTM1IGYNCjAwMDAwMDU2NDggNjU1MzUgZg0KMDAwMDAwNTY0OSA2NTUzNSBmDQowMDAwMDA1NjUwIDY1NTM1IGYNCjAwMDAwMDU2NTEgNjU1MzUgZg0KMDAwMDAwNTY1MiA2NTUzNSBmDQowMDAwMDA1NjUzIDY1NTM1IGYNCjAwMDAwMDU2NTQgNjU1MzUgZg0KMDAwMDAwNTY1NSA2NTUzNSBmDQowMDAwMDA1NjU2IDY1NTM1IGYNCjAwMDAwMDU2NTcgNjU1MzUgZg0KMDAwMDAwNTY1OCA2NTUzNSBmDQowMDAwMDA1NjU5IDY1NTM1IGYNCjAwMDAwMDU2NjAgNjU1MzUgZg0KMDAwMDAwNTY2MSA2NTUzNSBmDQowMDAwMDA1NjYyIDY1NTM1IGYNCjAwMDAwMDU2NjMgNjU1MzUgZg0KMDAwMDAwNTY2NCA2NTUzNSBmDQowMDAwMDA1NjY1IDY1NTM1IGYNCjAwMDAwMDU2NjYgNjU1MzUgZg0KMDAwMDAwNTY2NyA2NTUzNSBmDQowMDAwMDA1NjY4IDY1NTM1IGYNCjAwMDAwMDU2NjkgNjU1MzUgZg0KMDAwMDAwNTY3MCA2NTUzNSBmDQowMDAwMDA1NjcxIDY1NTM1IGYNCjAwMDAwMDU2NzIgNjU1MzUgZg0KMDAwMDAwNTY3MyA2NTUzNSBmDQowMDAwMDA1Njc0IDY1NTM1IGYNCjAwMDAwMDU2NzUgNjU1MzUgZg0KMDAwMDAwNTY3NiA2NTUzNSBmDQowMDAwMDA1Njc3IDY1NTM1IGYNCjAwMDAwMDU2NzggNjU1MzUgZg0KMDAwMDAwNTY3OSA2NTUzNSBmDQowMDAwMDA1NjgwIDY1NTM1IGYNCjAwMDAwMDU2ODEgNjU1MzUgZg0KMDAwMDAwNTY4MiA2NTUzNSBmDQowMDAwMDA1NjgzIDY1NTM1IGYNCjAwMDAwMDU2ODQgNjU1MzUgZg0KMDAwMDAwNTY4NSA2NTUzNSBmDQowMDAwMDA1Njg2IDY1NTM1IGYNCjAwMDAwMDU2ODcgNjU1MzUgZg0KMDAwMDAwNTY4OCA2NTUzNSBmDQowMDAwMDA1Njg5IDY1NTM1IGYNCjAwMDAwMDU2OTAgNjU1MzUgZg0KMDAwMDAwNTY5MSA2NTUzNSBmDQowMDAwMDA1NjkyIDY1NTM1IGYNCjAwMDAwMDU2OTMgNjU1MzUgZg0KMDAwMDAwNTY5NCA2NTUzNSBmDQowMDAwMDA1Njk1IDY1NTM1IGYNCjAwMDAwMDU2OTYgNjU1MzUgZg0KMDAwMDAwNTY5NyA2NTUzNSBmDQowMDAwMDA1Njk4IDY1NTM1IGYNCjAwMDAwMDU2OTkgNjU1MzUgZg0KMDAwMDAwNTcwMCA2NTUzNSBmDQowMDAwMDA1NzAxIDY1NTM1IGYNCjAwMDAwMDU3MDIgNjU1MzUgZg0KMDAwMDAwNTcwMyA2NTUzNSBmDQowMDAwMDA1NzA0IDY1NTM1IGYNCjAwMDAwMDU3MDUgNjU1MzUgZg0KMDAwMDAwNTcwNiA2NTUzNSBmDQowMDAwMDA1NzA3IDY1NTM1IGYNCjAwMDAwMDU3MDggNjU1MzUgZg0KMDAwMDAwNTcwOSA2NTUzNSBmDQowMDAwMDA1NzEwIDY1NTM1IGYNCjAwMDAwMDU3MTEgNjU1MzUgZg0KMDAwMDAwNTcxMiA2NTUzNSBmDQowMDAwMDA1NzEzIDY1NTM1IGYNCjAwMDAwMDU3MTQgNjU1MzUgZg0KMDAwMDAwNTcxNSA2NTUzNSBmDQowMDAwMDA1NzE2IDY1NTM1IGYNCjAwMDAwMDU3MTcgNjU1MzUgZg0KMDAwMDAwNTcxOCA2NTUzNSBmDQowMDAwMDA1NzE5IDY1NTM1IGYNCjAwMDAwMDU3MjAgNjU1MzUgZg0KMDAwMDAwNTcyMSA2NTUzNSBmDQowMDAwMDA1NzIyIDY1NTM1IGYNCjAwMDAwMDU3MjMgNjU1MzUgZg0KMDAwMDAwNTcyNCA2NTUzNSBmDQowMDAwMDA1NzI1IDY1NTM1IGYNCjAwMDAwMDU3MjYgNjU1MzUgZg0KMDAwMDAwNTcyNyA2NTUzNSBmDQowMDAwMDA1NzI4IDY1NTM1IGYNCjAwMDAwMDU3MjkgNjU1MzUgZg0KMDAwMDAwNTczMCA2NTUzNSBmDQowMDAwMDA1NzMxIDY1NTM1IGYNCjAwMDAwMDU3MzIgNjU1MzUgZg0KMDAwMDAwNTczMyA2NTUzNSBmDQowMDAwMDA1NzM0IDY1NTM1IGYNCjAwMDAwMDU3MzUgNjU1MzUgZg0KMDAwMDAwNTczNiA2NTUzNSBmDQowMDAwMDA1NzM3IDY1NTM1IGYNCjAwMDAwMDU3MzggNjU1MzUgZg0KMDAwMDAwNTczOSA2NTUzNSBmDQowMDAwMDA1NzQwIDY1NTM1IGYNCjAwMDAwMDU3NDEgNjU1MzUgZg0KMDAwMDAwNTc0MiA2NTUzNSBmDQowMDAwMDA1NzQzIDY1NTM1IGYNCjAwMDAwMDU3NDQgNjU1MzUgZg0KMDAwMDAwNTc0NSA2NTUzNSBmDQowMDAwMDA1NzQ2IDY1NTM1IGYNCjAwMDAwMDU3NDcgNjU1MzUgZg0KMDAwMDAwNTc0OCA2NTUzNSBmDQowMDAwMDA1NzQ5IDY1NTM1IGYNCjAwMDAwMDU3NTAgNjU1MzUgZg0KMDAwMDAwNTc1MSA2NTUzNSBmDQowMDAwMDA1NzUyIDY1NTM1IGYNCjAwMDAwMDU3NTMgNjU1MzUgZg0KMDAwMDAwNTc1NCA2NTUzNSBmDQowMDAwMDA1NzU1IDY1NTM1IGYNCjAwMDAwMDU3NTYgNjU1MzUgZg0KMDAwMDAwNTc1NyA2NTUzNSBmDQowMDAwMDA1NzU4IDY1NTM1IGYNCjAwMDAwMDU3NTkgNjU1MzUgZg0KMDAwMDAwNTc2MCA2NTUzNSBmDQowMDAwMDA1NzYxIDY1NTM1IGYNCjAwMDAwMDU3NjIgNjU1MzUgZg0KMDAwMDAwNTc2MyA2NTUzNSBmDQowMDAwMDA1NzY0IDY1NTM1IGYNCjAwMDAwMDU3NjUgNjU1MzUgZg0KMDAwMDAwNTc2NiA2NTUzNSBmDQowMDAwMDA1NzY3IDY1NTM1IGYNCjAwMDAwMDU3NjggNjU1MzUgZg0KMDAwMDAwNTc2OSA2NTUzNSBmDQowMDAwMDA1NzcwIDY1NTM1IGYNCjAwMDAwMDU3NzEgNjU1MzUgZg0KMDAwMDAwNTc3MiA2NTUzNSBmDQowMDAwMDA1NzczIDY1NTM1IGYNCjAwMDAwMDU3NzQgNjU1MzUgZg0KMDAwMDAwNTc3NSA2NTUzNSBmDQowMDAwMDA1Nzc2IDY1NTM1IGYNCjAwMDAwMDU3NzcgNjU1MzUgZg0KMDAwMDAwNTc3OCA2NTUzNSBmDQowMDAwMDA1Nzc5IDY1NTM1IGYNCjAwMDAwMDU3ODAgNjU1MzUgZg0KMDAwMDAwNTc4MSA2NTUzNSBmDQowMDAwMDA1NzgyIDY1NTM1IGYNCjAwMDAwMDU3ODMgNjU1MzUgZg0KMDAwMDAwNTc4NCA2NTUzNSBmDQowMDAwMDA1Nzg1IDY1NTM1IGYNCjAwMDAwMDU3ODYgNjU1MzUgZg0KMDAwMDAwNTc4NyA2NTUzNSBmDQowMDAwMDA1Nzg4IDY1NTM1IGYNCjAwMDAwMDU3ODkgNjU1MzUgZg0KMDAwMDAwNTc5MCA2NTUzNSBmDQowMDAwMDA1NzkxIDY1NTM1IGYNCjAwMDAwMDU3OTIgNjU1MzUgZg0KMDAwMDAwNTc5MyA2NTUzNSBmDQowMDAwMDA1Nzk0IDY1NTM1IGYNCjAwMDAwMDU3OTUgNjU1MzUgZg0KMDAwMDAwNTc5NiA2NTUzNSBmDQowMDAwMDA1Nzk3IDY1NTM1IGYNCjAwMDAwMDU3OTggNjU1MzUgZg0KMDAwMDAwNTc5OSA2NTUzNSBmDQowMDAwMDA1ODAwIDY1NTM1IGYNCjAwMDAwMDU4MDEgNjU1MzUgZg0KMDAwMDAwNTgwMiA2NTUzNSBmDQowMDAwMDA1ODAzIDY1NTM1IGYNCjAwMDAwMDU4MDQgNjU1MzUgZg0KMDAwMDAwNTgwNSA2NTUzNSBmDQowMDAwMDA1ODA2IDY1NTM1IGYNCjAwMDAwMDU4MDcgNjU1MzUgZg0KMDAwMDAwNTgwOCA2NTUzNSBmDQowMDAwMDA1ODA5IDY1NTM1IGYNCjAwMDAwMDU4MTAgNjU1MzUgZg0KMDAwMDAwNTgxMSA2NTUzNSBmDQowMDAwMDA1ODEyIDY1NTM1IGYNCjAwMDAwMDU4MTMgNjU1MzUgZg0KMDAwMDAwNTgxNCA2NTUzNSBmDQowMDAwMDA1ODE1IDY1NTM1IGYNCjAwMDAwMDU4MTYgNjU1MzUgZg0KMDAwMDAwNTgxNyA2NTUzNSBmDQowMDAwMDA1ODE4IDY1NTM1IGYNCjAwMDAwMDU4MTkgNjU1MzUgZg0KMDAwMDAwNTgyMCA2NTUzNSBmDQowMDAwMDA1ODIxIDY1NTM1IGYNCjAwMDAwMDU4MjIgNjU1MzUgZg0KMDAwMDAwNTgyMyA2NTUzNSBmDQowMDAwMDA1ODI0IDY1NTM1IGYNCjAwMDAwMDU4MjUgNjU1MzUgZg0KMDAwMDAwNTgyNiA2NTUzNSBmDQowMDAwMDA1ODI3IDY1NTM1IGYNCjAwMDAwMDU4MjggNjU1MzUgZg0KMDAwMDAwNTgyOSA2NTUzNSBmDQowMDAwMDA1ODMwIDY1NTM1IGYNCjAwMDAwMDU4MzEgNjU1MzUgZg0KMDAwMDAwNTgzMiA2NTUzNSBmDQowMDAwMDA1ODMzIDY1NTM1IGYNCjAwMDAwMDU4MzQgNjU1MzUgZg0KMDAwMDAwNTgzNSA2NTUzNSBmDQowMDAwMDA1ODM2IDY1NTM1IGYNCjAwMDAwMDU4MzcgNjU1MzUgZg0KMDAwMDAwNTgzOCA2NTUzNSBmDQowMDAwMDA1ODM5IDY1NTM1IGYNCjAwMDAwMDU4NDAgNjU1MzUgZg0KMDAwMDAwNTg0MSA2NTUzNSBmDQowMDAwMDA1ODQyIDY1NTM1IGYNCjAwMDAwMDU4NDMgNjU1MzUgZg0KMDAwMDAwNTg0NCA2NTUzNSBmDQowMDAwMDA1ODQ1IDY1NTM1IGYNCjAwMDAwMDU4NDYgNjU1MzUgZg0KMDAwMDAwNTg0NyA2NTUzNSBmDQowMDAwMDA1ODQ4IDY1NTM1IGYNCjAwMDAwMDU4NDkgNjU1MzUgZg0KMDAwMDAwNTg1MCA2NTUzNSBmDQowMDAwMDA1ODUxIDY1NTM1IGYNCjAwMDAwMDU4NTIgNjU1MzUgZg0KMDAwMDAwNTg1MyA2NTUzNSBmDQowMDAwMDA1ODU0IDY1NTM1IGYNCjAwMDAwMDU4NTUgNjU1MzUgZg0KMDAwMDAwNTg1NiA2NTUzNSBmDQowMDAwMDA1ODU3IDY1NTM1IGYNCjAwMDAwMDU4NTggNjU1MzUgZg0KMDAwMDAwNTg1OSA2NTUzNSBmDQowMDAwMDA1ODYwIDY1NTM1IGYNCjAwMDAwMDU4NjEgNjU1MzUgZg0KMDAwMDAwNTg2MiA2NTUzNSBmDQowMDAwMDA1ODYzIDY1NTM1IGYNCjAwMDAwMDU4NjQgNjU1MzUgZg0KMDAwMDAwNTg2NSA2NTUzNSBmDQowMDAwMDA1ODY2IDY1NTM1IGYNCjAwMDAwMDU4NjcgNjU1MzUgZg0KMDAwMDAwNTg2OCA2NTUzNSBmDQowMDAwMDA1ODY5IDY1NTM1IGYNCjAwMDAwMDU4NzAgNjU1MzUgZg0KMDAwMDAwNTg3MSA2NTUzNSBmDQowMDAwMDA1ODcyIDY1NTM1IGYNCjAwMDAwMDU4NzMgNjU1MzUgZg0KMDAwMDAwNTg3NCA2NTUzNSBmDQowMDAwMDA1ODc1IDY1NTM1IGYNCjAwMDAwMDU4NzYgNjU1MzUgZg0KMDAwMDAwNTg3NyA2NTUzNSBmDQowMDAwMDA1ODc4IDY1NTM1IGYNCjAwMDAwMDU4NzkgNjU1MzUgZg0KMDAwMDAwNTg4MCA2NTUzNSBmDQowMDAwMDA1ODgxIDY1NTM1IGYNCjAwMDAwMDU4ODIgNjU1MzUgZg0KMDAwMDAwNTg4MyA2NTUzNSBmDQowMDAwMDA1ODg0IDY1NTM1IGYNCjAwMDAwMDU4ODUgNjU1MzUgZg0KMDAwMDAwNTg4NiA2NTUzNSBmDQowMDAwMDA1ODg3IDY1NTM1IGYNCjAwMDAwMDU4ODggNjU1MzUgZg0KMDAwMDAwNTg4OSA2NTUzNSBmDQowMDAwMDA1ODkwIDY1NTM1IGYNCjAwMDAwMDU4OTEgNjU1MzUgZg0KMDAwMDAwNTg5MiA2NTUzNSBmDQowMDAwMDA1ODkzIDY1NTM1IGYNCjAwMDAwMDU4OTQgNjU1MzUgZg0KMDAwMDAwNTg5NSA2NTUzNSBmDQowMDAwMDA1ODk2IDY1NTM1IGYNCjAwMDAwMDU4OTcgNjU1MzUgZg0KMDAwMDAwNTg5OCA2NTUzNSBmDQowMDAwMDA1ODk5IDY1NTM1IGYNCjAwMDAwMDU5MDAgNjU1MzUgZg0KMDAwMDAwNTkwMSA2NTUzNSBmDQowMDAwMDA1OTAyIDY1NTM1IGYNCjAwMDAwMDU5MDMgNjU1MzUgZg0KMDAwMDAwNTkwNCA2NTUzNSBmDQowMDAwMDA1OTA1IDY1NTM1IGYNCjAwMDAwMDU5MDYgNjU1MzUgZg0KMDAwMDAwNTkwNyA2NTUzNSBmDQowMDAwMDA1OTA4IDY1NTM1IGYNCjAwMDAwMDU5MDkgNjU1MzUgZg0KMDAwMDAwNTkxMCA2NTUzNSBmDQowMDAwMDA1OTExIDY1NTM1IGYNCjAwMDAwMDU5MTIgNjU1MzUgZg0KMDAwMDAwNTkxMyA2NTUzNSBmDQowMDAwMDA1OTE0IDY1NTM1IGYNCjAwMDAwMDU5MTUgNjU1MzUgZg0KMDAwMDAwNTkxNiA2NTUzNSBmDQowMDAwMDA1OTE3IDY1NTM1IGYNCjAwMDAwMDU5MTggNjU1MzUgZg0KMDAwMDAwNTkxOSA2NTUzNSBmDQowMDAwMDA1OTIwIDY1NTM1IGYNCjAwMDAwMDU5MjEgNjU1MzUgZg0KMDAwMDAwNTkyMiA2NTUzNSBmDQowMDAwMDA1OTIzIDY1NTM1IGYNCjAwMDAwMDU5MjQgNjU1MzUgZg0KMDAwMDAwNTkyNSA2NTUzNSBmDQowMDAwMDA1OTI2IDY1NTM1IGYNCjAwMDAwMDU5MjcgNjU1MzUgZg0KMDAwMDAwNTkyOCA2NTUzNSBmDQowMDAwMDA1OTI5IDY1NTM1IGYNCjAwMDAwMDU5MzAgNjU1MzUgZg0KMDAwMDAwNTkzMSA2NTUzNSBmDQowMDAwMDA1OTMyIDY1NTM1IGYNCjAwMDAwMDU5MzMgNjU1MzUgZg0KMDAwMDAwNTkzNCA2NTUzNSBmDQowMDAwMDA1OTM1IDY1NTM1IGYNCjAwMDAwMDU5MzYgNjU1MzUgZg0KMDAwMDAwNTkzNyA2NTUzNSBmDQowMDAwMDA1OTM4IDY1NTM1IGYNCjAwMDAwMDU5MzkgNjU1MzUgZg0KMDAwMDAwNTk0MCA2NTUzNSBmDQowMDAwMDA1OTQxIDY1NTM1IGYNCjAwMDAwMDU5NDIgNjU1MzUgZg0KMDAwMDAwNTk0MyA2NTUzNSBmDQowMDAwMDA1OTQ0IDY1NTM1IGYNCjAwMDAwMDU5NDUgNjU1MzUgZg0KMDAwMDAwNTk0NiA2NTUzNSBmDQowMDAwMDA1OTQ3IDY1NTM1IGYNCjAwMDAwMDU5NDggNjU1MzUgZg0KMDAwMDAwNTk0OSA2NTUzNSBmDQowMDAwMDA1OTUwIDY1NTM1IGYNCjAwMDAwMDU5NTEgNjU1MzUgZg0KMDAwMDAwNTk1MiA2NTUzNSBmDQowMDAwMDA1OTUzIDY1NTM1IGYNCjAwMDAwMDU5NTQgNjU1MzUgZg0KMDAwMDAwNTk1NSA2NTUzNSBmDQowMDAwMDA1OTU2IDY1NTM1IGYNCjAwMDAwMDU5NTcgNjU1MzUgZg0KMDAwMDAwNTk1OCA2NTUzNSBmDQowMDAwMDA1OTU5IDY1NTM1IGYNCjAwMDAwMDU5NjAgNjU1MzUgZg0KMDAwMDAwNTk2MSA2NTUzNSBmDQowMDAwMDA1OTYyIDY1NTM1IGYNCjAwMDAwMDU5NjMgNjU1MzUgZg0KMDAwMDAwNTk2NCA2NTUzNSBmDQowMDAwMDA1OTY1IDY1NTM1IGYNCjAwMDAwMDU5NjYgNjU1MzUgZg0KMDAwMDAwNTk2NyA2NTUzNSBmDQowMDAwMDA1OTY4IDY1NTM1IGYNCjAwMDAwMDU5NjkgNjU1MzUgZg0KMDAwMDAwNTk3MCA2NTUzNSBmDQowMDAwMDA1OTcxIDY1NTM1IGYNCjAwMDAwMDU5NzIgNjU1MzUgZg0KMDAwMDAwNTk3MyA2NTUzNSBmDQowMDAwMDA1OTc0IDY1NTM1IGYNCjAwMDAwMDU5NzUgNjU1MzUgZg0KMDAwMDAwNTk3NiA2NTUzNSBmDQowMDAwMDA1OTc3IDY1NTM1IGYNCjAwMDAwMDU5NzggNjU1MzUgZg0KMDAwMDAwNTk3OSA2NTUzNSBmDQowMDAwMDA1OTgwIDY1NTM1IGYNCjAwMDAwMDU5ODEgNjU1MzUgZg0KMDAwMDAwNTk4MiA2NTUzNSBmDQowMDAwMDA1OTgzIDY1NTM1IGYNCjAwMDAwMDU5ODQgNjU1MzUgZg0KMDAwMDAwNTk4NSA2NTUzNSBmDQowMDAwMDA1OTg2IDY1NTM1IGYNCjAwMDAwMDU5ODcgNjU1MzUgZg0KMDAwMDAwNTk4OCA2NTUzNSBmDQowMDAwMDA1OTg5IDY1NTM1IGYNCjAwMDAwMDU5OTAgNjU1MzUgZg0KMDAwMDAwNTk5MSA2NTUzNSBmDQowMDAwMDA1OTkyIDY1NTM1IGYNCjAwMDAwMDU5OTMgNjU1MzUgZg0KMDAwMDAwNTk5NCA2NTUzNSBmDQowMDAwMDA1OTk1IDY1NTM1IGYNCjAwMDAwMDU5OTYgNjU1MzUgZg0KMDAwMDAwNTk5NyA2NTUzNSBmDQowMDAwMDA1OTk4IDY1NTM1IGYNCjAwMDAwMDU5OTkgNjU1MzUgZg0KMDAwMDAwNjAwMCA2NTUzNSBmDQowMDAwMDA2MDAxIDY1NTM1IGYNCjAwMDAwMDYwMDIgNjU1MzUgZg0KMDAwMDAwNjAwMyA2NTUzNSBmDQowMDAwMDA2MDA0IDY1NTM1IGYNCjAwMDAwMDYwMDUgNjU1MzUgZg0KMDAwMDAwNjAwNiA2NTUzNSBmDQowMDAwMDA2MDA3IDY1NTM1IGYNCjAwMDAwMDYwMDggNjU1MzUgZg0KMDAwMDAwNjAwOSA2NTUzNSBmDQowMDAwMDA2MDEwIDY1NTM1IGYNCjAwMDAwMDYwMTEgNjU1MzUgZg0KMDAwMDAwNjAxMiA2NTUzNSBmDQowMDAwMDA2MDEzIDY1NTM1IGYNCjAwMDAwMDYwMTQgNjU1MzUgZg0KMDAwMDAwNjAxNSA2NTUzNSBmDQowMDAwMDA2MDE2IDY1NTM1IGYNCjAwMDAwMDYwMTcgNjU1MzUgZg0KMDAwMDAwNjAxOCA2NTUzNSBmDQowMDAwMDA2MDE5IDY1NTM1IGYNCjAwMDAwMDYwMjAgNjU1MzUgZg0KMDAwMDAwNjAyMSA2NTUzNSBmDQowMDAwMDA2MDIyIDY1NTM1IGYNCjAwMDAwMDYwMjMgNjU1MzUgZg0KMDAwMDAwNjAyNCA2NTUzNSBmDQowMDAwMDA2MDI1IDY1NTM1IGYNCjAwMDAwMDYwMjYgNjU1MzUgZg0KMDAwMDAwNjAyNyA2NTUzNSBmDQowMDAwMDA2MDI4IDY1NTM1IGYNCjAwMDAwMDYwMjkgNjU1MzUgZg0KMDAwMDAwNjAzMCA2NTUzNSBmDQowMDAwMDA2MDMxIDY1NTM1IGYNCjAwMDAwMDYwMzIgNjU1MzUgZg0KMDAwMDAwNjAzMyA2NTUzNSBmDQowMDAwMDA2MDM0IDY1NTM1IGYNCjAwMDAwMDYwMzUgNjU1MzUgZg0KMDAwMDAwNjAzNiA2NTUzNSBmDQowMDAwMDA2MDM3IDY1NTM1IGYNCjAwMDAwMDYwMzggNjU1MzUgZg0KMDAwMDAwNjAzOSA2NTUzNSBmDQowMDAwMDA2MDQwIDY1NTM1IGYNCjAwMDAwMDYwNDEgNjU1MzUgZg0KMDAwMDAwNjA0MiA2NTUzNSBmDQowMDAwMDA2MDQzIDY1NTM1IGYNCjAwMDAwMDYwNDQgNjU1MzUgZg0KMDAwMDAwNjA0NSA2NTUzNSBmDQowMDAwMDA2MDQ2IDY1NTM1IGYNCjAwMDAwMDYwNDcgNjU1MzUgZg0KMDAwMDAwNjA0OCA2NTUzNSBmDQowMDAwMDA2MDQ5IDY1NTM1IGYNCjAwMDAwMDYwNTAgNjU1MzUgZg0KMDAwMDAwNjA1MSA2NTUzNSBmDQowMDAwMDA2MDUyIDY1NTM1IGYNCjAwMDAwMDYwNTMgNjU1MzUgZg0KMDAwMDAwNjA1NCA2NTUzNSBmDQowMDAwMDA2MDU1IDY1NTM1IGYNCjAwMDAwMDYwNTYgNjU1MzUgZg0KMDAwMDAwNjA1NyA2NTUzNSBmDQowMDAwMDA2MDU4IDY1NTM1IGYNCjAwMDAwMDYwNTkgNjU1MzUgZg0KMDAwMDAwNjA2MCA2NTUzNSBmDQowMDAwMDA2MDYxIDY1NTM1IGYNCjAwMDAwMDYwNjIgNjU1MzUgZg0KMDAwMDAwNjA2MyA2NTUzNSBmDQowMDAwMDA2MDY0IDY1NTM1IGYNCjAwMDAwMDYwNjUgNjU1MzUgZg0KMDAwMDAwNjA2NiA2NTUzNSBmDQowMDAwMDA2MDY3IDY1NTM1IGYNCjAwMDAwMDYwNjggNjU1MzUgZg0KMDAwMDAwNjA2OSA2NTUzNSBmDQowMDAwMDA2MDcwIDY1NTM1IGYNCjAwMDAwMDYwNzEgNjU1MzUgZg0KMDAwMDAwNjA3MiA2NTUzNSBmDQowMDAwMDA2MDczIDY1NTM1IGYNCjAwMDAwMDYwNzQgNjU1MzUgZg0KMDAwMDAwNjA3NSA2NTUzNSBmDQowMDAwMDA2MDc2IDY1NTM1IGYNCjAwMDAwMDYwNzcgNjU1MzUgZg0KMDAwMDAwNjA3OCA2NTUzNSBmDQowMDAwMDA2MDc5IDY1NTM1IGYNCjAwMDAwMDYwODAgNjU1MzUgZg0KMDAwMDAwNjA4MSA2NTUzNSBmDQowMDAwMDA2MDgyIDY1NTM1IGYNCjAwMDAwMDYwODMgNjU1MzUgZg0KMDAwMDAwNjA4NCA2NTUzNSBmDQowMDAwMDA2MDg1IDY1NTM1IGYNCjAwMDAwMDYwODYgNjU1MzUgZg0KMDAwMDAwNjA4NyA2NTUzNSBmDQowMDAwMDA2MDg4IDY1NTM1IGYNCjAwMDAwMDYwODkgNjU1MzUgZg0KMDAwMDAwNjA5MCA2NTUzNSBmDQowMDAwMDA2MDkxIDY1NTM1IGYNCjAwMDAwMDYwOTIgNjU1MzUgZg0KMDAwMDAwNjA5MyA2NTUzNSBmDQowMDAwMDA2MDk0IDY1NTM1IGYNCjAwMDAwMDYwOTUgNjU1MzUgZg0KMDAwMDAwNjA5NiA2NTUzNSBmDQowMDAwMDA2MDk3IDY1NTM1IGYNCjAwMDAwMDYwOTggNjU1MzUgZg0KMDAwMDAwNjA5OSA2NTUzNSBmDQowMDAwMDA2MTAwIDY1NTM1IGYNCjAwMDAwMDYxMDEgNjU1MzUgZg0KMDAwMDAwNjEwMiA2NTUzNSBmDQowMDAwMDA2MTAzIDY1NTM1IGYNCjAwMDAwMDYxMDQgNjU1MzUgZg0KMDAwMDAwNjEwNSA2NTUzNSBmDQowMDAwMDA2MTA2IDY1NTM1IGYNCjAwMDAwMDYxMDcgNjU1MzUgZg0KMDAwMDAwNjEwOCA2NTUzNSBmDQowMDAwMDA2MTA5IDY1NTM1IGYNCjAwMDAwMDYxMTAgNjU1MzUgZg0KMDAwMDAwNjExMSA2NTUzNSBmDQowMDAwMDA2MTEyIDY1NTM1IGYNCjAwMDAwMDYxMTMgNjU1MzUgZg0KMDAwMDAwNjExNCA2NTUzNSBmDQowMDAwMDA2MTE1IDY1NTM1IGYNCjAwMDAwMDYxMTYgNjU1MzUgZg0KMDAwMDAwNjExNyA2NTUzNSBmDQowMDAwMDA2MTE4IDY1NTM1IGYNCjAwMDAwMDYxMTkgNjU1MzUgZg0KMDAwMDAwNjEyMCA2NTUzNSBmDQowMDAwMDA2MTIxIDY1NTM1IGYNCjAwMDAwMDYxMjIgNjU1MzUgZg0KMDAwMDAwNjEyMyA2NTUzNSBmDQowMDAwMDA2MTI0IDY1NTM1IGYNCjAwMDAwMDYxMjUgNjU1MzUgZg0KMDAwMDAwNjEyNiA2NTUzNSBmDQowMDAwMDA2MTI3IDY1NTM1IGYNCjAwMDAwMDYxMjggNjU1MzUgZg0KMDAwMDAwNjEyOSA2NTUzNSBmDQowMDAwMDA2MTMwIDY1NTM1IGYNCjAwMDAwMDYxMzEgNjU1MzUgZg0KMDAwMDAwNjEzMiA2NTUzNSBmDQowMDAwMDA2MTMzIDY1NTM1IGYNCjAwMDAwMDYxMzQgNjU1MzUgZg0KMDAwMDAwNjEzNSA2NTUzNSBmDQowMDAwMDA2MTM2IDY1NTM1IGYNCjAwMDAwMDYxMzcgNjU1MzUgZg0KMDAwMDAwNjEzOCA2NTUzNSBmDQowMDAwMDA2MTM5IDY1NTM1IGYNCjAwMDAwMDYxNDAgNjU1MzUgZg0KMDAwMDAwNjE0MSA2NTUzNSBmDQowMDAwMDA2MTQyIDY1NTM1IGYNCjAwMDAwMDYxNDMgNjU1MzUgZg0KMDAwMDAwNjE0NCA2NTUzNSBmDQowMDAwMDA2MTQ1IDY1NTM1IGYNCjAwMDAwMDYxNDYgNjU1MzUgZg0KMDAwMDAwNjE0NyA2NTUzNSBmDQowMDAwMDA2MTQ4IDY1NTM1IGYNCjAwMDAwMDYxNDkgNjU1MzUgZg0KMDAwMDAwNjE1MCA2NTUzNSBmDQowMDAwMDA2MTUxIDY1NTM1IGYNCjAwMDAwMDYxNTIgNjU1MzUgZg0KMDAwMDAwNjE1MyA2NTUzNSBmDQowMDAwMDA2MTU0IDY1NTM1IGYNCjAwMDAwMDYxNTUgNjU1MzUgZg0KMDAwMDAwNjE1NiA2NTUzNSBmDQowMDAwMDA2MTU3IDY1NTM1IGYNCjAwMDAwMDYxNTggNjU1MzUgZg0KMDAwMDAwNjE1OSA2NTUzNSBmDQowMDAwMDA2MTYwIDY1NTM1IGYNCjAwMDAwMDYxNjEgNjU1MzUgZg0KMDAwMDAwNjE2MiA2NTUzNSBmDQowMDAwMDA2MTYzIDY1NTM1IGYNCjAwMDAwMDYxNjQgNjU1MzUgZg0KMDAwMDAwNjE2NSA2NTUzNSBmDQowMDAwMDA2MTY2IDY1NTM1IGYNCjAwMDAwMDYxNjcgNjU1MzUgZg0KMDAwMDAwNjE2OCA2NTUzNSBmDQowMDAwMDA2MTY5IDY1NTM1IGYNCjAwMDAwMDYxNzAgNjU1MzUgZg0KMDAwMDAwNjE3MSA2NTUzNSBmDQowMDAwMDA2MTcyIDY1NTM1IGYNCjAwMDAwMDYxNzMgNjU1MzUgZg0KMDAwMDAwNjE3NCA2NTUzNSBmDQowMDAwMDA2MTc1IDY1NTM1IGYNCjAwMDAwMDYxNzYgNjU1MzUgZg0KMDAwMDAwNjE3NyA2NTUzNSBmDQowMDAwMDA2MTc4IDY1NTM1IGYNCjAwMDAwMDYxNzkgNjU1MzUgZg0KMDAwMDAwNjE4MCA2NTUzNSBmDQowMDAwMDA2MTgxIDY1NTM1IGYNCjAwMDAwMDYxODIgNjU1MzUgZg0KMDAwMDAwNjE4MyA2NTUzNSBmDQowMDAwMDA2MTg0IDY1NTM1IGYNCjAwMDAwMDYxODUgNjU1MzUgZg0KMDAwMDAwNjE4NiA2NTUzNSBmDQowMDAwMDA2MTg3IDY1NTM1IGYNCjAwMDAwMDYxODggNjU1MzUgZg0KMDAwMDAwNjE4OSA2NTUzNSBmDQowMDAwMDA2MTkwIDY1NTM1IGYNCjAwMDAwMDYxOTEgNjU1MzUgZg0KMDAwMDAwNjE5MiA2NTUzNSBmDQowMDAwMDA2MTkzIDY1NTM1IGYNCjAwMDAwMDYxOTQgNjU1MzUgZg0KMDAwMDAwNjE5NSA2NTUzNSBmDQowMDAwMDA2MTk2IDY1NTM1IGYNCjAwMDAwMDYxOTcgNjU1MzUgZg0KMDAwMDAwNjE5OCA2NTUzNSBmDQowMDAwMDA2MTk5IDY1NTM1IGYNCjAwMDAwMDYyMDAgNjU1MzUgZg0KMDAwMDAwNjIwMSA2NTUzNSBmDQowMDAwMDA2MjAyIDY1NTM1IGYNCjAwMDAwMDYyMDMgNjU1MzUgZg0KMDAwMDAwNjIwNCA2NTUzNSBmDQowMDAwMDA2MjA1IDY1NTM1IGYNCjAwMDAwMDYyMDYgNjU1MzUgZg0KMDAwMDAwNjIwNyA2NTUzNSBmDQowMDAwMDA2MjA4IDY1NTM1IGYNCjAwMDAwMDYyMDkgNjU1MzUgZg0KMDAwMDAwNjIxMCA2NTUzNSBmDQowMDAwMDA2MjExIDY1NTM1IGYNCjAwMDAwMDYyMTIgNjU1MzUgZg0KMDAwMDAwNjIxMyA2NTUzNSBmDQowMDAwMDA2MjE0IDY1NTM1IGYNCjAwMDAwMDYyMTUgNjU1MzUgZg0KMDAwMDAwNjIxNiA2NTUzNSBmDQowMDAwMDA2MjE3IDY1NTM1IGYNCjAwMDAwMDYyMTggNjU1MzUgZg0KMDAwMDAwNjIxOSA2NTUzNSBmDQowMDAwMDA2MjIwIDY1NTM1IGYNCjAwMDAwMDYyMjEgNjU1MzUgZg0KMDAwMDAwNjIyMiA2NTUzNSBmDQowMDAwMDA2MjIzIDY1NTM1IGYNCjAwMDAwMDYyMjQgNjU1MzUgZg0KMDAwMDAwNjIyNSA2NTUzNSBmDQowMDAwMDA2MjI2IDY1NTM1IGYNCjAwMDAwMDYyMjcgNjU1MzUgZg0KMDAwMDAwNjIyOCA2NTUzNSBmDQowMDAwMDA2MjI5IDY1NTM1IGYNCjAwMDAwMDYyMzAgNjU1MzUgZg0KMDAwMDAwNjIzMSA2NTUzNSBmDQowMDAwMDA2MjMyIDY1NTM1IGYNCjAwMDAwMDYyMzMgNjU1MzUgZg0KMDAwMDAwNjIzNCA2NTUzNSBmDQowMDAwMDA2MjM1IDY1NTM1IGYNCjAwMDAwMDYyMzYgNjU1MzUgZg0KMDAwMDAwNjIzNyA2NTUzNSBmDQowMDAwMDA2MjM4IDY1NTM1IGYNCjAwMDAwMDYyMzkgNjU1MzUgZg0KMDAwMDAwNjI0MCA2NTUzNSBmDQowMDAwMDA2MjQxIDY1NTM1IGYNCjAwMDAwMDYyNDIgNjU1MzUgZg0KMDAwMDAwNjI0MyA2NTUzNSBmDQowMDAwMDA2MjQ0IDY1NTM1IGYNCjAwMDAwMDYyNDUgNjU1MzUgZg0KMDAwMDAwNjI0NiA2NTUzNSBmDQowMDAwMDA2MjQ3IDY1NTM1IGYNCjAwMDAwMDYyNDggNjU1MzUgZg0KMDAwMDAwNjI0OSA2NTUzNSBmDQowMDAwMDA2MjUwIDY1NTM1IGYNCjAwMDAwMDYyNTEgNjU1MzUgZg0KMDAwMDAwNjI1MiA2NTUzNSBmDQowMDAwMDA2MjUzIDY1NTM1IGYNCjAwMDAwMDYyNTQgNjU1MzUgZg0KMDAwMDAwNjI1NSA2NTUzNSBmDQowMDAwMDA2MjU2IDY1NTM1IGYNCjAwMDAwMDYyNTcgNjU1MzUgZg0KMDAwMDAwNjI1OCA2NTUzNSBmDQowMDAwMDA2MjU5IDY1NTM1IGYNCjAwMDAwMDYyNjAgNjU1MzUgZg0KMDAwMDAwNjI2MSA2NTUzNSBmDQowMDAwMDA2MjYyIDY1NTM1IGYNCjAwMDAwMDYyNjMgNjU1MzUgZg0KMDAwMDAwNjI2NCA2NTUzNSBmDQowMDAwMDA2MjY1IDY1NTM1IGYNCjAwMDAwMDYyNjYgNjU1MzUgZg0KMDAwMDAwNjI2NyA2NTUzNSBmDQowMDAwMDA2MjY4IDY1NTM1IGYNCjAwMDAwMDYyNjkgNjU1MzUgZg0KMDAwMDAwNjI3MCA2NTUzNSBmDQowMDAwMDA2MjcxIDY1NTM1IGYNCjAwMDAwMDYyNzIgNjU1MzUgZg0KMDAwMDAwNjI3MyA2NTUzNSBmDQowMDAwMDA2Mjc0IDY1NTM1IGYNCjAwMDAwMDYyNzUgNjU1MzUgZg0KMDAwMDAwNjI3NiA2NTUzNSBmDQowMDAwMDA2Mjc3IDY1NTM1IGYNCjAwMDAwMDYyNzggNjU1MzUgZg0KMDAwMDAwNjI3OSA2NTUzNSBmDQowMDAwMDA2MjgwIDY1NTM1IGYNCjAwMDAwMDYyODEgNjU1MzUgZg0KMDAwMDAwNjI4MiA2NTUzNSBmDQowMDAwMDA2MjgzIDY1NTM1IGYNCjAwMDAwMDYyODQgNjU1MzUgZg0KMDAwMDAwNjI4NSA2NTUzNSBmDQowMDAwMDA2Mjg2IDY1NTM1IGYNCjAwMDAwMDYyODcgNjU1MzUgZg0KMDAwMDAwNjI4OCA2NTUzNSBmDQowMDAwMDA2Mjg5IDY1NTM1IGYNCjAwMDAwMDYyOTAgNjU1MzUgZg0KMDAwMDAwNjI5MSA2NTUzNSBmDQowMDAwMDA2MjkyIDY1NTM1IGYNCjAwMDAwMDYyOTMgNjU1MzUgZg0KMDAwMDAwNjI5NCA2NTUzNSBmDQowMDAwMDA2Mjk1IDY1NTM1IGYNCjAwMDAwMDYyOTYgNjU1MzUgZg0KMDAwMDAwNjI5NyA2NTUzNSBmDQowMDAwMDA2Mjk4IDY1NTM1IGYNCjAwMDAwMDYyOTkgNjU1MzUgZg0KMDAwMDAwNjMwMCA2NTUzNSBmDQowMDAwMDA2MzAxIDY1NTM1IGYNCjAwMDAwMDYzMDIgNjU1MzUgZg0KMDAwMDAwNjMwMyA2NTUzNSBmDQowMDAwMDA2MzA0IDY1NTM1IGYNCjAwMDAwMDYzMDUgNjU1MzUgZg0KMDAwMDAwNjMwNiA2NTUzNSBmDQowMDAwMDA2MzA3IDY1NTM1IGYNCjAwMDAwMDYzMDggNjU1MzUgZg0KMDAwMDAwNjMwOSA2NTUzNSBmDQowMDAwMDA2MzEwIDY1NTM1IGYNCjAwMDAwMDYzMTEgNjU1MzUgZg0KMDAwMDAwNjMxMiA2NTUzNSBmDQowMDAwMDA2MzEzIDY1NTM1IGYNCjAwMDAwMDYzMTQgNjU1MzUgZg0KMDAwMDAwNjMxNSA2NTUzNSBmDQowMDAwMDA2MzE2IDY1NTM1IGYNCjAwMDAwMDYzMTcgNjU1MzUgZg0KMDAwMDAwNjMxOCA2NTUzNSBmDQowMDAwMDA2MzE5IDY1NTM1IGYNCjAwMDAwMDYzMjAgNjU1MzUgZg0KMDAwMDAwNjMyMSA2NTUzNSBmDQowMDAwMDA2MzIyIDY1NTM1IGYNCjAwMDAwMDYzMjMgNjU1MzUgZg0KMDAwMDAwNjMyNCA2NTUzNSBmDQowMDAwMDA2MzI1IDY1NTM1IGYNCjAwMDAwMDYzMjYgNjU1MzUgZg0KMDAwMDAwNjMyNyA2NTUzNSBmDQowMDAwMDA2MzI4IDY1NTM1IGYNCjAwMDAwMDYzMjkgNjU1MzUgZg0KMDAwMDAwNjMzMCA2NTUzNSBmDQowMDAwMDA2MzMxIDY1NTM1IGYNCjAwMDAwMDYzMzIgNjU1MzUgZg0KMDAwMDAwNjMzMyA2NTUzNSBmDQowMDAwMDA2MzM0IDY1NTM1IGYNCjAwMDAwMDYzMzUgNjU1MzUgZg0KMDAwMDAwNjMzNiA2NTUzNSBmDQowMDAwMDA2MzM3IDY1NTM1IGYNCjAwMDAwMDYzMzggNjU1MzUgZg0KMDAwMDAwNjMzOSA2NTUzNSBmDQowMDAwMDA2MzQwIDY1NTM1IGYNCjAwMDAwMDYzNDEgNjU1MzUgZg0KMDAwMDAwNjM0MiA2NTUzNSBmDQowMDAwMDA2MzQzIDY1NTM1IGYNCjAwMDAwMDYzNDQgNjU1MzUgZg0KMDAwMDAwNjM0NSA2NTUzNSBmDQowMDAwMDA2MzQ2IDY1NTM1IGYNCjAwMDAwMDYzNDcgNjU1MzUgZg0KMDAwMDAwNjM0OCA2NTUzNSBmDQowMDAwMDA2MzQ5IDY1NTM1IGYNCjAwMDAwMDYzNTAgNjU1MzUgZg0KMDAwMDAwNjM1MSA2NTUzNSBmDQowMDAwMDA2MzUyIDY1NTM1IGYNCjAwMDAwMDYzNTMgNjU1MzUgZg0KMDAwMDAwNjM1NCA2NTUzNSBmDQowMDAwMDA2MzU1IDY1NTM1IGYNCjAwMDAwMDYzNTYgNjU1MzUgZg0KMDAwMDAwNjM1NyA2NTUzNSBmDQowMDAwMDA2MzU4IDY1NTM1IGYNCjAwMDAwMDYzNTkgNjU1MzUgZg0KMDAwMDAwNjM2MCA2NTUzNSBmDQowMDAwMDA2MzYxIDY1NTM1IGYNCjAwMDAwMDYzNjIgNjU1MzUgZg0KMDAwMDAwNjM2MyA2NTUzNSBmDQowMDAwMDA2MzY0IDY1NTM1IGYNCjAwMDAwMDYzNjUgNjU1MzUgZg0KMDAwMDAwNjM2NiA2NTUzNSBmDQowMDAwMDA2MzY3IDY1NTM1IGYNCjAwMDAwMDYzNjggNjU1MzUgZg0KMDAwMDAwNjM2OSA2NTUzNSBmDQowMDAwMDA2MzcwIDY1NTM1IGYNCjAwMDAwMDYzNzEgNjU1MzUgZg0KMDAwMDAwNjM3MiA2NTUzNSBmDQowMDAwMDA2MzczIDY1NTM1IGYNCjAwMDAwMDYzNzQgNjU1MzUgZg0KMDAwMDAwNjM3NSA2NTUzNSBmDQowMDAwMDA2Mzc2IDY1NTM1IGYNCjAwMDAwMDYzNzcgNjU1MzUgZg0KMDAwMDAwNjM3OCA2NTUzNSBmDQowMDAwMDA2Mzc5IDY1NTM1IGYNCjAwMDAwMDYzODAgNjU1MzUgZg0KMDAwMDAwNjM4MSA2NTUzNSBmDQowMDAwMDA2MzgyIDY1NTM1IGYNCjAwMDAwMDYzODMgNjU1MzUgZg0KMDAwMDAwNjM4NCA2NTUzNSBmDQowMDAwMDA2Mzg1IDY1NTM1IGYNCjAwMDAwMDYzODYgNjU1MzUgZg0KMDAwMDAwNjM4NyA2NTUzNSBmDQowMDAwMDA2Mzg4IDY1NTM1IGYNCjAwMDAwMDYzODkgNjU1MzUgZg0KMDAwMDAwNjM5MCA2NTUzNSBmDQowMDAwMDA2MzkxIDY1NTM1IGYNCjAwMDAwMDYzOTIgNjU1MzUgZg0KMDAwMDAwNjM5MyA2NTUzNSBmDQowMDAwMDA2Mzk0IDY1NTM1IGYNCjAwMDAwMDYzOTUgNjU1MzUgZg0KMDAwMDAwNjM5NiA2NTUzNSBmDQowMDAwMDA2Mzk3IDY1NTM1IGYNCjAwMDAwMDYzOTggNjU1MzUgZg0KMDAwMDAwNjM5OSA2NTUzNSBmDQowMDAwMDA2NDAwIDY1NTM1IGYNCjAwMDAwMDY0MDEgNjU1MzUgZg0KMDAwMDAwNjQwMiA2NTUzNSBmDQowMDAwMDA2NDAzIDY1NTM1IGYNCjAwMDAwMDY0MDQgNjU1MzUgZg0KMDAwMDAwNjQwNSA2NTUzNSBmDQowMDAwMDA2NDA2IDY1NTM1IGYNCjAwMDAwMDY0MDcgNjU1MzUgZg0KMDAwMDAwNjQwOCA2NTUzNSBmDQowMDAwMDA2NDA5IDY1NTM1IGYNCjAwMDAwMDY0MTAgNjU1MzUgZg0KMDAwMDAwNjQxMSA2NTUzNSBmDQowMDAwMDA2NDEyIDY1NTM1IGYNCjAwMDAwMDY0MTMgNjU1MzUgZg0KMDAwMDAwNjQxNCA2NTUzNSBmDQowMDAwMDA2NDE1IDY1NTM1IGYNCjAwMDAwMDY0MTYgNjU1MzUgZg0KMDAwMDAwNjQxNyA2NTUzNSBmDQowMDAwMDA2NDE4IDY1NTM1IGYNCjAwMDAwMDY0MTkgNjU1MzUgZg0KMDAwMDAwNjQyMCA2NTUzNSBmDQowMDAwMDA2NDIxIDY1NTM1IGYNCjAwMDAwMDY0MjIgNjU1MzUgZg0KMDAwMDAwNjQyMyA2NTUzNSBmDQowMDAwMDA2NDI0IDY1NTM1IGYNCjAwMDAwMDY0MjUgNjU1MzUgZg0KMDAwMDAwNjQyNiA2NTUzNSBmDQowMDAwMDA2NDI3IDY1NTM1IGYNCjAwMDAwMDY0MjggNjU1MzUgZg0KMDAwMDAwNjQyOSA2NTUzNSBmDQowMDAwMDA2NDMwIDY1NTM1IGYNCjAwMDAwMDY0MzEgNjU1MzUgZg0KMDAwMDAwNjQzMiA2NTUzNSBmDQowMDAwMDA2NDMzIDY1NTM1IGYNCjAwMDAwMDY0MzQgNjU1MzUgZg0KMDAwMDAwNjQzNSA2NTUzNSBmDQowMDAwMDA2NDM2IDY1NTM1IGYNCjAwMDAwMDY0MzcgNjU1MzUgZg0KMDAwMDAwNjQzOCA2NTUzNSBmDQowMDAwMDA2NDM5IDY1NTM1IGYNCjAwMDAwMDY0NDAgNjU1MzUgZg0KMDAwMDAwNjQ0MSA2NTUzNSBmDQowMDAwMDA2NDQyIDY1NTM1IGYNCjAwMDAwMDY0NDMgNjU1MzUgZg0KMDAwMDAwNjQ0NCA2NTUzNSBmDQowMDAwMDA2NDQ1IDY1NTM1IGYNCjAwMDAwMDY0NDYgNjU1MzUgZg0KMDAwMDAwNjQ0NyA2NTUzNSBmDQowMDAwMDA2NDQ4IDY1NTM1IGYNCjAwMDAwMDY0NDkgNjU1MzUgZg0KMDAwMDAwNjQ1MCA2NTUzNSBmDQowMDAwMDA2NDUxIDY1NTM1IGYNCjAwMDAwMDY0NTIgNjU1MzUgZg0KMDAwMDAwNjQ1MyA2NTUzNSBmDQowMDAwMDA2NDU0IDY1NTM1IGYNCjAwMDAwMDY0NTUgNjU1MzUgZg0KMDAwMDAwNjQ1NiA2NTUzNSBmDQowMDAwMDA2NDU3IDY1NTM1IGYNCjAwMDAwMDY0NTggNjU1MzUgZg0KMDAwMDAwNjQ1OSA2NTUzNSBmDQowMDAwMDA2NDYwIDY1NTM1IGYNCjAwMDAwMDY0NjEgNjU1MzUgZg0KMDAwMDAwNjQ2MiA2NTUzNSBmDQowMDAwMDA2NDYzIDY1NTM1IGYNCjAwMDAwMDY0NjQgNjU1MzUgZg0KMDAwMDAwNjQ2NSA2NTUzNSBmDQowMDAwMDA2NDY2IDY1NTM1IGYNCjAwMDAwMDY0NjcgNjU1MzUgZg0KMDAwMDAwNjQ2OCA2NTUzNSBmDQowMDAwMDA2NDY5IDY1NTM1IGYNCjAwMDAwMDY0NzAgNjU1MzUgZg0KMDAwMDAwNjQ3MSA2NTUzNSBmDQowMDAwMDA2NDcyIDY1NTM1IGYNCjAwMDAwMDY0NzMgNjU1MzUgZg0KMDAwMDAwNjQ3NCA2NTUzNSBmDQowMDAwMDA2NDc1IDY1NTM1IGYNCjAwMDAwMDY0NzYgNjU1MzUgZg0KMDAwMDAwNjQ3NyA2NTUzNSBmDQowMDAwMDA2NDc4IDY1NTM1IGYNCjAwMDAwMDY0NzkgNjU1MzUgZg0KMDAwMDAwNjQ4MCA2NTUzNSBmDQowMDAwMDA2NDgxIDY1NTM1IGYNCjAwMDAwMDY0ODIgNjU1MzUgZg0KMDAwMDAwNjQ4MyA2NTUzNSBmDQowMDAwMDA2NDg0IDY1NTM1IGYNCjAwMDAwMDY0ODUgNjU1MzUgZg0KMDAwMDAwNjQ4NiA2NTUzNSBmDQowMDAwMDA2NDg3IDY1NTM1IGYNCjAwMDAwMDY0ODggNjU1MzUgZg0KMDAwMDAwNjQ4OSA2NTUzNSBmDQowMDAwMDA2NDkwIDY1NTM1IGYNCjAwMDAwMDY0OTEgNjU1MzUgZg0KMDAwMDAwNjQ5MiA2NTUzNSBmDQowMDAwMDA2NDkzIDY1NTM1IGYNCjAwMDAwMDY0OTQgNjU1MzUgZg0KMDAwMDAwNjQ5NSA2NTUzNSBmDQowMDAwMDA2NDk2IDY1NTM1IGYNCjAwMDAwMDY0OTcgNjU1MzUgZg0KMDAwMDAwNjQ5OCA2NTUzNSBmDQowMDAwMDA2NDk5IDY1NTM1IGYNCjAwMDAwMDY1MDAgNjU1MzUgZg0KMDAwMDAwNjUwMSA2NTUzNSBmDQowMDAwMDA2NTAyIDY1NTM1IGYNCjAwMDAwMDY1MDMgNjU1MzUgZg0KMDAwMDAwNjUwNCA2NTUzNSBmDQowMDAwMDA2NTA1IDY1NTM1IGYNCjAwMDAwMDY1MDYgNjU1MzUgZg0KMDAwMDAwNjUwNyA2NTUzNSBmDQowMDAwMDA2NTA4IDY1NTM1IGYNCjAwMDAwMDY1MDkgNjU1MzUgZg0KMDAwMDAwNjUxMCA2NTUzNSBmDQowMDAwMDA2NTExIDY1NTM1IGYNCjAwMDAwMDY1MTIgNjU1MzUgZg0KMDAwMDAwNjUxMyA2NTUzNSBmDQowMDAwMDA2NTE0IDY1NTM1IGYNCjAwMDAwMDY1MTUgNjU1MzUgZg0KMDAwMDAwNjUxNiA2NTUzNSBmDQowMDAwMDA2NTE3IDY1NTM1IGYNCjAwMDAwMDY1MTggNjU1MzUgZg0KMDAwMDAwNjUxOSA2NTUzNSBmDQowMDAwMDA2NTIwIDY1NTM1IGYNCjAwMDAwMDY1MjEgNjU1MzUgZg0KMDAwMDAwNjUyMiA2NTUzNSBmDQowMDAwMDA2NTIzIDY1NTM1IGYNCjAwMDAwMDY1MjQgNjU1MzUgZg0KMDAwMDAwNjUyNSA2NTUzNSBmDQowMDAwMDA2NTI2IDY1NTM1IGYNCjAwMDAwMDY1MjcgNjU1MzUgZg0KMDAwMDAwNjUyOCA2NTUzNSBmDQowMDAwMDA2NTI5IDY1NTM1IGYNCjAwMDAwMDY1MzAgNjU1MzUgZg0KMDAwMDAwNjUzMSA2NTUzNSBmDQowMDAwMDA2NTMyIDY1NTM1IGYNCjAwMDAwMDY1MzMgNjU1MzUgZg0KMDAwMDAwNjUzNCA2NTUzNSBmDQowMDAwMDA2NTM1IDY1NTM1IGYNCjAwMDAwMDY1MzYgNjU1MzUgZg0KMDAwMDAwNjUzNyA2NTUzNSBmDQowMDAwMDA2NTM4IDY1NTM1IGYNCjAwMDAwMDY1MzkgNjU1MzUgZg0KMDAwMDAwNjU0MCA2NTUzNSBmDQowMDAwMDA2NTQxIDY1NTM1IGYNCjAwMDAwMDY1NDIgNjU1MzUgZg0KMDAwMDAwNjU0MyA2NTUzNSBmDQowMDAwMDA2NTQ0IDY1NTM1IGYNCjAwMDAwMDY1NDUgNjU1MzUgZg0KMDAwMDAwNjU0NiA2NTUzNSBmDQowMDAwMDA2NTQ3IDY1NTM1IGYNCjAwMDAwMDY1NDggNjU1MzUgZg0KMDAwMDAwNjU0OSA2NTUzNSBmDQowMDAwMDA2NTUwIDY1NTM1IGYNCjAwMDAwMDY1NTEgNjU1MzUgZg0KMDAwMDAwNjU1MiA2NTUzNSBmDQowMDAwMDA2NTUzIDY1NTM1IGYNCjAwMDAwMDY1NTQgNjU1MzUgZg0KMDAwMDAwNjU1NSA2NTUzNSBmDQowMDAwMDA2NTU2IDY1NTM1IGYNCjAwMDAwMDY1NTcgNjU1MzUgZg0KMDAwMDAwNjU1OCA2NTUzNSBmDQowMDAwMDA2NTU5IDY1NTM1IGYNCjAwMDAwMDY1NjAgNjU1MzUgZg0KMDAwMDAwNjU2MSA2NTUzNSBmDQowMDAwMDA2NTYyIDY1NTM1IGYNCjAwMDAwMDY1NjMgNjU1MzUgZg0KMDAwMDAwNjU2NCA2NTUzNSBmDQowMDAwMDA2NTY1IDY1NTM1IGYNCjAwMDAwMDY1NjYgNjU1MzUgZg0KMDAwMDAwNjU2NyA2NTUzNSBmDQowMDAwMDA2NTY4IDY1NTM1IGYNCjAwMDAwMDY1NjkgNjU1MzUgZg0KMDAwMDAwNjU3MCA2NTUzNSBmDQowMDAwMDA2NTcxIDY1NTM1IGYNCjAwMDAwMDY1NzIgNjU1MzUgZg0KMDAwMDAwNjU3MyA2NTUzNSBmDQowMDAwMDA2NTc0IDY1NTM1IGYNCjAwMDAwMDY1NzUgNjU1MzUgZg0KMDAwMDAwNjU3NiA2NTUzNSBmDQowMDAwMDA2NTc3IDY1NTM1IGYNCjAwMDAwMDY1NzggNjU1MzUgZg0KMDAwMDAwNjU3OSA2NTUzNSBmDQowMDAwMDA2NTgwIDY1NTM1IGYNCjAwMDAwMDY1ODEgNjU1MzUgZg0KMDAwMDAwNjU4MiA2NTUzNSBmDQowMDAwMDA2NTgzIDY1NTM1IGYNCjAwMDAwMDY1ODQgNjU1MzUgZg0KMDAwMDAwNjU4NSA2NTUzNSBmDQowMDAwMDA2NTg2IDY1NTM1IGYNCjAwMDAwMDY1ODcgNjU1MzUgZg0KMDAwMDAwNjU4OCA2NTUzNSBmDQowMDAwMDA2NTg5IDY1NTM1IGYNCjAwMDAwMDY1OTAgNjU1MzUgZg0KMDAwMDAwNjU5MSA2NTUzNSBmDQowMDAwMDA2NTkyIDY1NTM1IGYNCjAwMDAwMDY1OTMgNjU1MzUgZg0KMDAwMDAwNjU5NCA2NTUzNSBmDQowMDAwMDA2NTk1IDY1NTM1IGYNCjAwMDAwMDY1OTYgNjU1MzUgZg0KMDAwMDAwNjU5NyA2NTUzNSBmDQowMDAwMDA2NTk4IDY1NTM1IGYNCjAwMDAwMDY1OTkgNjU1MzUgZg0KMDAwMDAwNjYwMCA2NTUzNSBmDQowMDAwMDA2NjAxIDY1NTM1IGYNCjAwMDAwMDY2MDIgNjU1MzUgZg0KMDAwMDAwNjYwMyA2NTUzNSBmDQowMDAwMDA2NjA0IDY1NTM1IGYNCjAwMDAwMDY2MDUgNjU1MzUgZg0KMDAwMDAwNjYwNiA2NTUzNSBmDQowMDAwMDA2NjA3IDY1NTM1IGYNCjAwMDAwMDY2MDggNjU1MzUgZg0KMDAwMDAwNjYwOSA2NTUzNSBmDQowMDAwMDA2NjEwIDY1NTM1IGYNCjAwMDAwMDY2MTEgNjU1MzUgZg0KMDAwMDAwNjYxMiA2NTUzNSBmDQowMDAwMDA2NjEzIDY1NTM1IGYNCjAwMDAwMDY2MTQgNjU1MzUgZg0KMDAwMDAwNjYxNSA2NTUzNSBmDQowMDAwMDA2NjE2IDY1NTM1IGYNCjAwMDAwMDY2MTcgNjU1MzUgZg0KMDAwMDAwNjYxOCA2NTUzNSBmDQowMDAwMDA2NjE5IDY1NTM1IGYNCjAwMDAwMDY2MjAgNjU1MzUgZg0KMDAwMDAwNjYyMSA2NTUzNSBmDQowMDAwMDA2NjIyIDY1NTM1IGYNCjAwMDAwMDY2MjMgNjU1MzUgZg0KMDAwMDAwNjYyNCA2NTUzNSBmDQowMDAwMDA2NjI1IDY1NTM1IGYNCjAwMDAwMDY2MjYgNjU1MzUgZg0KMDAwMDAwNjYyNyA2NTUzNSBmDQowMDAwMDA2NjI4IDY1NTM1IGYNCjAwMDAwMDY2MjkgNjU1MzUgZg0KMDAwMDAwNjYzMCA2NTUzNSBmDQowMDAwMDA2NjMxIDY1NTM1IGYNCjAwMDAwMDY2MzIgNjU1MzUgZg0KMDAwMDAwNjYzMyA2NTUzNSBmDQowMDAwMDA2NjM0IDY1NTM1IGYNCjAwMDAwMDY2MzUgNjU1MzUgZg0KMDAwMDAwNjYzNiA2NTUzNSBmDQowMDAwMDA2NjM3IDY1NTM1IGYNCjAwMDAwMDY2MzggNjU1MzUgZg0KMDAwMDAwNjYzOSA2NTUzNSBmDQowMDAwMDA2NjQwIDY1NTM1IGYNCjAwMDAwMDY2NDEgNjU1MzUgZg0KMDAwMDAwNjY0MiA2NTUzNSBmDQowMDAwMDA2NjQzIDY1NTM1IGYNCjAwMDAwMDY2NDQgNjU1MzUgZg0KMDAwMDAwNjY0NSA2NTUzNSBmDQowMDAwMDA2NjQ2IDY1NTM1IGYNCjAwMDAwMDY2NDcgNjU1MzUgZg0KMDAwMDAwNjY0OCA2NTUzNSBmDQowMDAwMDA2NjQ5IDY1NTM1IGYNCjAwMDAwMDY2NTAgNjU1MzUgZg0KMDAwMDAwNjY1MSA2NTUzNSBmDQowMDAwMDA2NjUyIDY1NTM1IGYNCjAwMDAwMDY2NTMgNjU1MzUgZg0KMDAwMDAwNjY1NCA2NTUzNSBmDQowMDAwMDA2NjU1IDY1NTM1IGYNCjAwMDAwMDY2NTYgNjU1MzUgZg0KMDAwMDAwNjY1NyA2NTUzNSBmDQowMDAwMDA2NjU4IDY1NTM1IGYNCjAwMDAwMDY2NTkgNjU1MzUgZg0KMDAwMDAwNjY2MCA2NTUzNSBmDQowMDAwMDA2NjYxIDY1NTM1IGYNCjAwMDAwMDY2NjIgNjU1MzUgZg0KMDAwMDAwNjY2MyA2NTUzNSBmDQowMDAwMDA2NjY0IDY1NTM1IGYNCjAwMDAwMDY2NjUgNjU1MzUgZg0KMDAwMDAwNjY2NiA2NTUzNSBmDQowMDAwMDA2NjY3IDY1NTM1IGYNCjAwMDAwMDY2NjggNjU1MzUgZg0KMDAwMDAwNjY2OSA2NTUzNSBmDQowMDAwMDA2NjcwIDY1NTM1IGYNCjAwMDAwMDY2NzEgNjU1MzUgZg0KMDAwMDAwNjY3MiA2NTUzNSBmDQowMDAwMDA2NjczIDY1NTM1IGYNCjAwMDAwMDY2NzQgNjU1MzUgZg0KMDAwMDAwNjY3NSA2NTUzNSBmDQowMDAwMDA2Njc2IDY1NTM1IGYNCjAwMDAwMDY2NzcgNjU1MzUgZg0KMDAwMDAwNjY3OCA2NTUzNSBmDQowMDAwMDA2Njc5IDY1NTM1IGYNCjAwMDAwMDY2ODAgNjU1MzUgZg0KMDAwMDAwNjY4MSA2NTUzNSBmDQowMDAwMDA2NjgyIDY1NTM1IGYNCjAwMDAwMDY2ODMgNjU1MzUgZg0KMDAwMDAwNjY4NCA2NTUzNSBmDQowMDAwMDA2Njg1IDY1NTM1IGYNCjAwMDAwMDY2ODYgNjU1MzUgZg0KMDAwMDAwNjY4NyA2NTUzNSBmDQowMDAwMDA2Njg4IDY1NTM1IGYNCjAwMDAwMDY2ODkgNjU1MzUgZg0KMDAwMDAwNjY5MCA2NTUzNSBmDQowMDAwMDA2NjkxIDY1NTM1IGYNCjAwMDAwMDY2OTIgNjU1MzUgZg0KMDAwMDAwNjY5MyA2NTUzNSBmDQowMDAwMDA2Njk0IDY1NTM1IGYNCjAwMDAwMDY2OTUgNjU1MzUgZg0KMDAwMDAwNjY5NiA2NTUzNSBmDQowMDAwMDA2Njk3IDY1NTM1IGYNCjAwMDAwMDY2OTggNjU1MzUgZg0KMDAwMDAwNjY5OSA2NTUzNSBmDQowMDAwMDA2NzAwIDY1NTM1IGYNCjAwMDAwMDY3MDEgNjU1MzUgZg0KMDAwMDAwNjcwMiA2NTUzNSBmDQowMDAwMDA2NzAzIDY1NTM1IGYNCjAwMDAwMDY3MDQgNjU1MzUgZg0KMDAwMDAwNjcwNSA2NTUzNSBmDQowMDAwMDA2NzA2IDY1NTM1IGYNCjAwMDAwMDY3MDcgNjU1MzUgZg0KMDAwMDAwNjcwOCA2NTUzNSBmDQowMDAwMDA2NzA5IDY1NTM1IGYNCjAwMDAwMDY3MTAgNjU1MzUgZg0KMDAwMDAwNjcxMSA2NTUzNSBmDQowMDAwMDA2NzEyIDY1NTM1IGYNCjAwMDAwMDY3MTMgNjU1MzUgZg0KMDAwMDAwNjcxNCA2NTUzNSBmDQowMDAwMDA2NzE1IDY1NTM1IGYNCjAwMDAwMDY3MTYgNjU1MzUgZg0KMDAwMDAwNjcxNyA2NTUzNSBmDQowMDAwMDA2NzE4IDY1NTM1IGYNCjAwMDAwMDY3MTkgNjU1MzUgZg0KMDAwMDAwNjcyMCA2NTUzNSBmDQowMDAwMDA2NzIxIDY1NTM1IGYNCjAwMDAwMDY3MjIgNjU1MzUgZg0KMDAwMDAwNjcyMyA2NTUzNSBmDQowMDAwMDA2NzI0IDY1NTM1IGYNCjAwMDAwMDY3MjUgNjU1MzUgZg0KMDAwMDAwNjcyNiA2NTUzNSBmDQowMDAwMDA2NzI3IDY1NTM1IGYNCjAwMDAwMDY3MjggNjU1MzUgZg0KMDAwMDAwNjcyOSA2NTUzNSBmDQowMDAwMDA2NzMwIDY1NTM1IGYNCjAwMDAwMDY3MzEgNjU1MzUgZg0KMDAwMDAwNjczMiA2NTUzNSBmDQowMDAwMDA2NzMzIDY1NTM1IGYNCjAwMDAwMDY3MzQgNjU1MzUgZg0KMDAwMDAwNjczNSA2NTUzNSBmDQowMDAwMDA2NzM2IDY1NTM1IGYNCjAwMDAwMDY3MzcgNjU1MzUgZg0KMDAwMDAwNjczOCA2NTUzNSBmDQowMDAwMDA2NzM5IDY1NTM1IGYNCjAwMDAwMDY3NDAgNjU1MzUgZg0KMDAwMDAwNjc0MSA2NTUzNSBmDQowMDAwMDA2NzQyIDY1NTM1IGYNCjAwMDAwMDY3NDMgNjU1MzUgZg0KMDAwMDAwNjc0NCA2NTUzNSBmDQowMDAwMDA2NzQ1IDY1NTM1IGYNCjAwMDAwMDY3NDYgNjU1MzUgZg0KMDAwMDAwNjc0NyA2NTUzNSBmDQowMDAwMDA2NzQ4IDY1NTM1IGYNCjAwMDAwMDY3NDkgNjU1MzUgZg0KMDAwMDAwNjc1MCA2NTUzNSBmDQowMDAwMDA2NzUxIDY1NTM1IGYNCjAwMDAwMDY3NTIgNjU1MzUgZg0KMDAwMDAwNjc1MyA2NTUzNSBmDQowMDAwMDA2NzU0IDY1NTM1IGYNCjAwMDAwMDY3NTUgNjU1MzUgZg0KMDAwMDAwNjc1NiA2NTUzNSBmDQowMDAwMDA2NzU3IDY1NTM1IGYNCjAwMDAwMDY3NTggNjU1MzUgZg0KMDAwMDAwNjc1OSA2NTUzNSBmDQowMDAwMDA2NzYwIDY1NTM1IGYNCjAwMDAwMDY3NjEgNjU1MzUgZg0KMDAwMDAwNjc2MiA2NTUzNSBmDQowMDAwMDA2NzYzIDY1NTM1IGYNCjAwMDAwMDY3NjQgNjU1MzUgZg0KMDAwMDAwNjc2NSA2NTUzNSBmDQowMDAwMDA2NzY2IDY1NTM1IGYNCjAwMDAwMDY3NjcgNjU1MzUgZg0KMDAwMDAwNjc2OCA2NTUzNSBmDQowMDAwMDA2NzY5IDY1NTM1IGYNCjAwMDAwMDY3NzAgNjU1MzUgZg0KMDAwMDAwNjc3MSA2NTUzNSBmDQowMDAwMDA2NzcyIDY1NTM1IGYNCjAwMDAwMDY3NzMgNjU1MzUgZg0KMDAwMDAwNjc3NCA2NTUzNSBmDQowMDAwMDA2Nzc1IDY1NTM1IGYNCjAwMDAwMDY3NzYgNjU1MzUgZg0KMDAwMDAwNjc3NyA2NTUzNSBmDQowMDAwMDA2Nzc4IDY1NTM1IGYNCjAwMDAwMDY3NzkgNjU1MzUgZg0KMDAwMDAwNjc4MCA2NTUzNSBmDQowMDAwMDA2NzgxIDY1NTM1IGYNCjAwMDAwMDY3ODIgNjU1MzUgZg0KMDAwMDAwNjc4MyA2NTUzNSBmDQowMDAwMDA2Nzg0IDY1NTM1IGYNCjAwMDAwMDY3ODUgNjU1MzUgZg0KMDAwMDAwNjc4NiA2NTUzNSBmDQowMDAwMDA2Nzg3IDY1NTM1IGYNCjAwMDAwMDY3ODggNjU1MzUgZg0KMDAwMDAwNjc4OSA2NTUzNSBmDQowMDAwMDA2NzkwIDY1NTM1IGYNCjAwMDAwMDY3OTEgNjU1MzUgZg0KMDAwMDAwNjc5MiA2NTUzNSBmDQowMDAwMDA2NzkzIDY1NTM1IGYNCjAwMDAwMDY3OTQgNjU1MzUgZg0KMDAwMDAwNjc5NSA2NTUzNSBmDQowMDAwMDA2Nzk2IDY1NTM1IGYNCjAwMDAwMDY3OTcgNjU1MzUgZg0KMDAwMDAwNjc5OCA2NTUzNSBmDQowMDAwMDA2Nzk5IDY1NTM1IGYNCjAwMDAwMDY4MDAgNjU1MzUgZg0KMDAwMDAwNjgwMSA2NTUzNSBmDQowMDAwMDA2ODAyIDY1NTM1IGYNCjAwMDAwMDY4MDMgNjU1MzUgZg0KMDAwMDAwNjgwNCA2NTUzNSBmDQowMDAwMDA2ODA1IDY1NTM1IGYNCjAwMDAwMDY4MDYgNjU1MzUgZg0KMDAwMDAwNjgwNyA2NTUzNSBmDQowMDAwMDA2ODA4IDY1NTM1IGYNCjAwMDAwMDY4MDkgNjU1MzUgZg0KMDAwMDAwNjgxMCA2NTUzNSBmDQowMDAwMDA2ODExIDY1NTM1IGYNCjAwMDAwMDY4MTIgNjU1MzUgZg0KMDAwMDAwNjgxMyA2NTUzNSBmDQowMDAwMDA2ODE0IDY1NTM1IGYNCjAwMDAwMDY4MTUgNjU1MzUgZg0KMDAwMDAwNjgxNiA2NTUzNSBmDQowMDAwMDA2ODE3IDY1NTM1IGYNCjAwMDAwMDY4MTggNjU1MzUgZg0KMDAwMDAwNjgxOSA2NTUzNSBmDQowMDAwMDA2ODIwIDY1NTM1IGYNCjAwMDAwMDY4MjEgNjU1MzUgZg0KMDAwMDAwNjgyMiA2NTUzNSBmDQowMDAwMDA2ODIzIDY1NTM1IGYNCjAwMDAwMDY4MjQgNjU1MzUgZg0KMDAwMDAwNjgyNSA2NTUzNSBmDQowMDAwMDA2ODI2IDY1NTM1IGYNCjAwMDAwMDY4MjcgNjU1MzUgZg0KMDAwMDAwNjgyOCA2NTUzNSBmDQowMDAwMDA2ODI5IDY1NTM1IGYNCjAwMDAwMDY4MzAgNjU1MzUgZg0KMDAwMDAwNjgzMSA2NTUzNSBmDQowMDAwMDA2ODMyIDY1NTM1IGYNCjAwMDAwMDY4MzMgNjU1MzUgZg0KMDAwMDAwNjgzNCA2NTUzNSBmDQowMDAwMDA2ODM1IDY1NTM1IGYNCjAwMDAwMDY4MzYgNjU1MzUgZg0KMDAwMDAwNjgzNyA2NTUzNSBmDQowMDAwMDA2ODM4IDY1NTM1IGYNCjAwMDAwMDY4MzkgNjU1MzUgZg0KMDAwMDAwNjg0MCA2NTUzNSBmDQowMDAwMDA2ODQxIDY1NTM1IGYNCjAwMDAwMDY4NDIgNjU1MzUgZg0KMDAwMDAwNjg0MyA2NTUzNSBmDQowMDAwMDA2ODQ0IDY1NTM1IGYNCjAwMDAwMDY4NDUgNjU1MzUgZg0KMDAwMDAwNjg0NiA2NTUzNSBmDQowMDAwMDA2ODQ3IDY1NTM1IGYNCjAwMDAwMDY4NDggNjU1MzUgZg0KMDAwMDAwNjg0OSA2NTUzNSBmDQowMDAwMDA2ODUwIDY1NTM1IGYNCjAwMDAwMDY4NTEgNjU1MzUgZg0KMDAwMDAwNjg1MiA2NTUzNSBmDQowMDAwMDA2ODUzIDY1NTM1IGYNCjAwMDAwMDY4NTQgNjU1MzUgZg0KMDAwMDAwNjg1NSA2NTUzNSBmDQowMDAwMDA2ODU2IDY1NTM1IGYNCjAwMDAwMDY4NTcgNjU1MzUgZg0KMDAwMDAwNjg1OCA2NTUzNSBmDQowMDAwMDA2ODU5IDY1NTM1IGYNCjAwMDAwMDY4NjAgNjU1MzUgZg0KMDAwMDAwNjg2MSA2NTUzNSBmDQowMDAwMDA2ODYyIDY1NTM1IGYNCjAwMDAwMDY4NjMgNjU1MzUgZg0KMDAwMDAwNjg2NCA2NTUzNSBmDQowMDAwMDA2ODY1IDY1NTM1IGYNCjAwMDAwMDY4NjYgNjU1MzUgZg0KMDAwMDAwNjg2NyA2NTUzNSBmDQowMDAwMDA2ODY4IDY1NTM1IGYNCjAwMDAwMDY4NjkgNjU1MzUgZg0KMDAwMDAwNjg3MCA2NTUzNSBmDQowMDAwMDA2ODcxIDY1NTM1IGYNCjAwMDAwMDY4NzIgNjU1MzUgZg0KMDAwMDAwNjg3MyA2NTUzNSBmDQowMDAwMDA2ODc0IDY1NTM1IGYNCjAwMDAwMDY4NzUgNjU1MzUgZg0KMDAwMDAwNjg3NiA2NTUzNSBmDQowMDAwMDA2ODc3IDY1NTM1IGYNCjAwMDAwMDY4NzggNjU1MzUgZg0KMDAwMDAwNjg3OSA2NTUzNSBmDQowMDAwMDA2ODgwIDY1NTM1IGYNCjAwMDAwMDY4ODEgNjU1MzUgZg0KMDAwMDAwNjg4MiA2NTUzNSBmDQowMDAwMDA2ODgzIDY1NTM1IGYNCjAwMDAwMDY4ODQgNjU1MzUgZg0KMDAwMDAwNjg4NSA2NTUzNSBmDQowMDAwMDA2ODg2IDY1NTM1IGYNCjAwMDAwMDY4ODcgNjU1MzUgZg0KMDAwMDAwNjg4OCA2NTUzNSBmDQowMDAwMDA2ODg5IDY1NTM1IGYNCjAwMDAwMDY4OTAgNjU1MzUgZg0KMDAwMDAwNjg5MSA2NTUzNSBmDQowMDAwMDA2ODkyIDY1NTM1IGYNCjAwMDAwMDY4OTMgNjU1MzUgZg0KMDAwMDAwNjg5NCA2NTUzNSBmDQowMDAwMDA2ODk1IDY1NTM1IGYNCjAwMDAwMDY4OTYgNjU1MzUgZg0KMDAwMDAwNjg5NyA2NTUzNSBmDQowMDAwMDA2ODk4IDY1NTM1IGYNCjAwMDAwMDY4OTkgNjU1MzUgZg0KMDAwMDAwNjkwMCA2NTUzNSBmDQowMDAwMDA2OTAxIDY1NTM1IGYNCjAwMDAwMDY5MDIgNjU1MzUgZg0KMDAwMDAwNjkwMyA2NTUzNSBmDQowMDAwMDA2OTA0IDY1NTM1IGYNCjAwMDAwMDY5MDUgNjU1MzUgZg0KMDAwMDAwNjkwNiA2NTUzNSBmDQowMDAwMDA2OTA3IDY1NTM1IGYNCjAwMDAwMDY5MDggNjU1MzUgZg0KMDAwMDAwNjkwOSA2NTUzNSBmDQowMDAwMDA2OTEwIDY1NTM1IGYNCjAwMDAwMDY5MTEgNjU1MzUgZg0KMDAwMDAwNjkxMiA2NTUzNSBmDQowMDAwMDA2OTEzIDY1NTM1IGYNCjAwMDAwMDY5MTQgNjU1MzUgZg0KMDAwMDAwNjkxNSA2NTUzNSBmDQowMDAwMDA2OTE2IDY1NTM1IGYNCjAwMDAwMDY5MTcgNjU1MzUgZg0KMDAwMDAwNjkxOCA2NTUzNSBmDQowMDAwMDA2OTE5IDY1NTM1IGYNCjAwMDAwMDY5MjAgNjU1MzUgZg0KMDAwMDAwNjkyMSA2NTUzNSBmDQowMDAwMDA2OTIyIDY1NTM1IGYNCjAwMDAwMDY5MjMgNjU1MzUgZg0KMDAwMDAwNjkyNCA2NTUzNSBmDQowMDAwMDA2OTI1IDY1NTM1IGYNCjAwMDAwMDY5MjYgNjU1MzUgZg0KMDAwMDAwNjkyNyA2NTUzNSBmDQowMDAwMDA2OTI4IDY1NTM1IGYNCjAwMDAwMDY5MjkgNjU1MzUgZg0KMDAwMDAwNjkzMCA2NTUzNSBmDQowMDAwMDA2OTMxIDY1NTM1IGYNCjAwMDAwMDY5MzIgNjU1MzUgZg0KMDAwMDAwNjkzMyA2NTUzNSBmDQowMDAwMDA2OTM0IDY1NTM1IGYNCjAwMDAwMDY5MzUgNjU1MzUgZg0KMDAwMDAwNjkzNiA2NTUzNSBmDQowMDAwMDA2OTM3IDY1NTM1IGYNCjAwMDAwMDY5MzggNjU1MzUgZg0KMDAwMDAwNjkzOSA2NTUzNSBmDQowMDAwMDA2OTQwIDY1NTM1IGYNCjAwMDAwMDY5NDEgNjU1MzUgZg0KMDAwMDAwNjk0MiA2NTUzNSBmDQowMDAwMDA2OTQzIDY1NTM1IGYNCjAwMDAwMDY5NDQgNjU1MzUgZg0KMDAwMDAwNjk0NSA2NTUzNSBmDQowMDAwMDA2OTQ2IDY1NTM1IGYNCjAwMDAwMDY5NDcgNjU1MzUgZg0KMDAwMDAwNjk0OCA2NTUzNSBmDQowMDAwMDA2OTQ5IDY1NTM1IGYNCjAwMDAwMDY5NTAgNjU1MzUgZg0KMDAwMDAwNjk1MSA2NTUzNSBmDQowMDAwMDA2OTUyIDY1NTM1IGYNCjAwMDAwMDY5NTMgNjU1MzUgZg0KMDAwMDAwNjk1NCA2NTUzNSBmDQowMDAwMDA2OTU1IDY1NTM1IGYNCjAwMDAwMDY5NTYgNjU1MzUgZg0KMDAwMDAwNjk1NyA2NTUzNSBmDQowMDAwMDA2OTU4IDY1NTM1IGYNCjAwMDAwMDY5NTkgNjU1MzUgZg0KMDAwMDAwNjk2MCA2NTUzNSBmDQowMDAwMDA2OTYxIDY1NTM1IGYNCjAwMDAwMDY5NjIgNjU1MzUgZg0KMDAwMDAwNjk2MyA2NTUzNSBmDQowMDAwMDA2OTY0IDY1NTM1IGYNCjAwMDAwMDY5NjUgNjU1MzUgZg0KMDAwMDAwNjk2NiA2NTUzNSBmDQowMDAwMDA2OTY3IDY1NTM1IGYNCjAwMDAwMDY5NjggNjU1MzUgZg0KMDAwMDAwNjk2OSA2NTUzNSBmDQowMDAwMDA2OTcwIDY1NTM1IGYNCjAwMDAwMDY5NzEgNjU1MzUgZg0KMDAwMDAwNjk3MiA2NTUzNSBmDQowMDAwMDA2OTczIDY1NTM1IGYNCjAwMDAwMDY5NzQgNjU1MzUgZg0KMDAwMDAwNjk3NSA2NTUzNSBmDQowMDAwMDA2OTc2IDY1NTM1IGYNCjAwMDAwMDY5NzcgNjU1MzUgZg0KMDAwMDAwNjk3OCA2NTUzNSBmDQowMDAwMDA2OTc5IDY1NTM1IGYNCjAwMDAwMDY5ODAgNjU1MzUgZg0KMDAwMDAwNjk4MSA2NTUzNSBmDQowMDAwMDA2OTgyIDY1NTM1IGYNCjAwMDAwMDY5ODMgNjU1MzUgZg0KMDAwMDAwNjk4NCA2NTUzNSBmDQowMDAwMDA2OTg1IDY1NTM1IGYNCjAwMDAwMDY5ODYgNjU1MzUgZg0KMDAwMDAwNjk4NyA2NTUzNSBmDQowMDAwMDA2OTg4IDY1NTM1IGYNCjAwMDAwMDY5ODkgNjU1MzUgZg0KMDAwMDAwNjk5MCA2NTUzNSBmDQowMDAwMDA2OTkxIDY1NTM1IGYNCjAwMDAwMDY5OTIgNjU1MzUgZg0KMDAwMDAwNjk5MyA2NTUzNSBmDQowMDAwMDA2OTk0IDY1NTM1IGYNCjAwMDAwMDY5OTUgNjU1MzUgZg0KMDAwMDAwNjk5NiA2NTUzNSBmDQowMDAwMDA2OTk3IDY1NTM1IGYNCjAwMDAwMDY5OTggNjU1MzUgZg0KMDAwMDAwNjk5OSA2NTUzNSBmDQowMDAwMDA3MDAwIDY1NTM1IGYNCjAwMDAwMDcwMDEgNjU1MzUgZg0KMDAwMDAwNzAwMiA2NTUzNSBmDQowMDAwMDA3MDAzIDY1NTM1IGYNCjAwMDAwMDcwMDQgNjU1MzUgZg0KMDAwMDAwNzAwNSA2NTUzNSBmDQowMDAwMDA3MDA2IDY1NTM1IGYNCjAwMDAwMDcwMDcgNjU1MzUgZg0KMDAwMDAwNzAwOCA2NTUzNSBmDQowMDAwMDA3MDA5IDY1NTM1IGYNCjAwMDAwMDcwMTAgNjU1MzUgZg0KMDAwMDAwNzAxMSA2NTUzNSBmDQowMDAwMDA3MDEyIDY1NTM1IGYNCjAwMDAwMDcwMTMgNjU1MzUgZg0KMDAwMDAwNzAxNCA2NTUzNSBmDQowMDAwMDA3MDE1IDY1NTM1IGYNCjAwMDAwMDcwMTYgNjU1MzUgZg0KMDAwMDAwNzAxNyA2NTUzNSBmDQowMDAwMDA3MDE4IDY1NTM1IGYNCjAwMDAwMDcwMTkgNjU1MzUgZg0KMDAwMDAwNzAyMCA2NTUzNSBmDQowMDAwMDA3MDIxIDY1NTM1IGYNCjAwMDAwMDcwMjIgNjU1MzUgZg0KMDAwMDAwNzAyMyA2NTUzNSBmDQowMDAwMDA3MDI0IDY1NTM1IGYNCjAwMDAwMDcwMjUgNjU1MzUgZg0KMDAwMDAwNzAyNiA2NTUzNSBmDQowMDAwMDA3MDI3IDY1NTM1IGYNCjAwMDAwMDcwMjggNjU1MzUgZg0KMDAwMDAwNzAyOSA2NTUzNSBmDQowMDAwMDA3MDMwIDY1NTM1IGYNCjAwMDAwMDcwMzEgNjU1MzUgZg0KMDAwMDAwNzAzMiA2NTUzNSBmDQowMDAwMDA3MDMzIDY1NTM1IGYNCjAwMDAwMDcwMzQgNjU1MzUgZg0KMDAwMDAwNzAzNSA2NTUzNSBmDQowMDAwMDA3MDM2IDY1NTM1IGYNCjAwMDAwMDcwMzcgNjU1MzUgZg0KMDAwMDAwNzAzOCA2NTUzNSBmDQowMDAwMDA3MDM5IDY1NTM1IGYNCjAwMDAwMDcwNDAgNjU1MzUgZg0KMDAwMDAwNzA0MSA2NTUzNSBmDQowMDAwMDA3MDQyIDY1NTM1IGYNCjAwMDAwMDcwNDMgNjU1MzUgZg0KMDAwMDAwNzA0NCA2NTUzNSBmDQowMDAwMDA3MDQ1IDY1NTM1IGYNCjAwMDAwMDcwNDYgNjU1MzUgZg0KMDAwMDAwNzA0NyA2NTUzNSBmDQowMDAwMDA3MDQ4IDY1NTM1IGYNCjAwMDAwMDcwNDkgNjU1MzUgZg0KMDAwMDAwNzA1MCA2NTUzNSBmDQowMDAwMDA3MDUxIDY1NTM1IGYNCjAwMDAwMDcwNTIgNjU1MzUgZg0KMDAwMDAwNzA1MyA2NTUzNSBmDQowMDAwMDA3MDU0IDY1NTM1IGYNCjAwMDAwMDcwNTUgNjU1MzUgZg0KMDAwMDAwNzA1NiA2NTUzNSBmDQowMDAwMDA3MDU3IDY1NTM1IGYNCjAwMDAwMDcwNTggNjU1MzUgZg0KMDAwMDAwNzA1OSA2NTUzNSBmDQowMDAwMDA3MDYwIDY1NTM1IGYNCjAwMDAwMDcwNjEgNjU1MzUgZg0KMDAwMDAwNzA2MiA2NTUzNSBmDQowMDAwMDA3MDYzIDY1NTM1IGYNCjAwMDAwMDcwNjQgNjU1MzUgZg0KMDAwMDAwNzA2NSA2NTUzNSBmDQowMDAwMDA3MDY2IDY1NTM1IGYNCjAwMDAwMDcwNjcgNjU1MzUgZg0KMDAwMDAwNzA2OCA2NTUzNSBmDQowMDAwMDA3MDY5IDY1NTM1IGYNCjAwMDAwMDcwNzAgNjU1MzUgZg0KMDAwMDAwNzA3MSA2NTUzNSBmDQowMDAwMDA3MDcyIDY1NTM1IGYNCjAwMDAwMDcwNzMgNjU1MzUgZg0KMDAwMDAwNzA3NCA2NTUzNSBmDQowMDAwMDA3MDc1IDY1NTM1IGYNCjAwMDAwMDcwNzYgNjU1MzUgZg0KMDAwMDAwNzA3NyA2NTUzNSBmDQowMDAwMDA3MDc4IDY1NTM1IGYNCjAwMDAwMDcwNzkgNjU1MzUgZg0KMDAwMDAwNzA4MCA2NTUzNSBmDQowMDAwMDA3MDgxIDY1NTM1IGYNCjAwMDAwMDcwODIgNjU1MzUgZg0KMDAwMDAwNzA4MyA2NTUzNSBmDQowMDAwMDA3MDg0IDY1NTM1IGYNCjAwMDAwMDcwODUgNjU1MzUgZg0KMDAwMDAwNzA4NiA2NTUzNSBmDQowMDAwMDA3MDg3IDY1NTM1IGYNCjAwMDAwMDcwODggNjU1MzUgZg0KMDAwMDAwNzA4OSA2NTUzNSBmDQowMDAwMDA3MDkwIDY1NTM1IGYNCjAwMDAwMDcwOTEgNjU1MzUgZg0KMDAwMDAwNzA5MiA2NTUzNSBmDQowMDAwMDA3MDkzIDY1NTM1IGYNCjAwMDAwMDcwOTQgNjU1MzUgZg0KMDAwMDAwNzA5NSA2NTUzNSBmDQowMDAwMDA3MDk2IDY1NTM1IGYNCjAwMDAwMDcwOTcgNjU1MzUgZg0KMDAwMDAwNzA5OCA2NTUzNSBmDQowMDAwMDA3MDk5IDY1NTM1IGYNCjAwMDAwMDcxMDAgNjU1MzUgZg0KMDAwMDAwNzEwMSA2NTUzNSBmDQowMDAwMDA3MTAyIDY1NTM1IGYNCjAwMDAwMDcxMDMgNjU1MzUgZg0KMDAwMDAwNzEwNCA2NTUzNSBmDQowMDAwMDA3MTA1IDY1NTM1IGYNCjAwMDAwMDcxMDYgNjU1MzUgZg0KMDAwMDAwNzEwNyA2NTUzNSBmDQowMDAwMDA3MTA4IDY1NTM1IGYNCjAwMDAwMDcxMDkgNjU1MzUgZg0KMDAwMDAwNzExMCA2NTUzNSBmDQowMDAwMDA3MTExIDY1NTM1IGYNCjAwMDAwMDcxMTIgNjU1MzUgZg0KMDAwMDAwNzExMyA2NTUzNSBmDQowMDAwMDA3MTE0IDY1NTM1IGYNCjAwMDAwMDcxMTUgNjU1MzUgZg0KMDAwMDAwNzExNiA2NTUzNSBmDQowMDAwMDA3MTE3IDY1NTM1IGYNCjAwMDAwMDcxMTggNjU1MzUgZg0KMDAwMDAwNzExOSA2NTUzNSBmDQowMDAwMDA3MTIwIDY1NTM1IGYNCjAwMDAwMDcxMjEgNjU1MzUgZg0KMDAwMDAwNzEyMiA2NTUzNSBmDQowMDAwMDA3MTIzIDY1NTM1IGYNCjAwMDAwMDcxMjQgNjU1MzUgZg0KMDAwMDAwNzEyNSA2NTUzNSBmDQowMDAwMDA3MTI2IDY1NTM1IGYNCjAwMDAwMDcxMjcgNjU1MzUgZg0KMDAwMDAwNzEyOCA2NTUzNSBmDQowMDAwMDA3MTI5IDY1NTM1IGYNCjAwMDAwMDcxMzAgNjU1MzUgZg0KMDAwMDAwNzEzMSA2NTUzNSBmDQowMDAwMDA3MTMyIDY1NTM1IGYNCjAwMDAwMDcxMzMgNjU1MzUgZg0KMDAwMDAwNzEzNCA2NTUzNSBmDQowMDAwMDA3MTM1IDY1NTM1IGYNCjAwMDAwMDcxMzYgNjU1MzUgZg0KMDAwMDAwNzEzNyA2NTUzNSBmDQowMDAwMDA3MTM4IDY1NTM1IGYNCjAwMDAwMDcxMzkgNjU1MzUgZg0KMDAwMDAwNzE0MCA2NTUzNSBmDQowMDAwMDA3MTQxIDY1NTM1IGYNCjAwMDAwMDcxNDIgNjU1MzUgZg0KMDAwMDAwNzE0MyA2NTUzNSBmDQowMDAwMDA3MTQ0IDY1NTM1IGYNCjAwMDAwMDcxNDUgNjU1MzUgZg0KMDAwMDAwNzE0NiA2NTUzNSBmDQowMDAwMDA3MTQ3IDY1NTM1IGYNCjAwMDAwMDcxNDggNjU1MzUgZg0KMDAwMDAwNzE0OSA2NTUzNSBmDQowMDAwMDA3MTUwIDY1NTM1IGYNCjAwMDAwMDcxNTEgNjU1MzUgZg0KMDAwMDAwNzE1MiA2NTUzNSBmDQowMDAwMDA3MTUzIDY1NTM1IGYNCjAwMDAwMDcxNTQgNjU1MzUgZg0KMDAwMDAwNzE1NSA2NTUzNSBmDQowMDAwMDA3MTU2IDY1NTM1IGYNCjAwMDAwMDcxNTcgNjU1MzUgZg0KMDAwMDAwNzE1OCA2NTUzNSBmDQowMDAwMDA3MTU5IDY1NTM1IGYNCjAwMDAwMDcxNjAgNjU1MzUgZg0KMDAwMDAwNzE2MSA2NTUzNSBmDQowMDAwMDA3MTYyIDY1NTM1IGYNCjAwMDAwMDcxNjMgNjU1MzUgZg0KMDAwMDAwNzE2NCA2NTUzNSBmDQowMDAwMDA3MTY1IDY1NTM1IGYNCjAwMDAwMDcxNjYgNjU1MzUgZg0KMDAwMDAwNzE2NyA2NTUzNSBmDQowMDAwMDA3MTY4IDY1NTM1IGYNCjAwMDAwMDcxNjkgNjU1MzUgZg0KMDAwMDAwNzE3MCA2NTUzNSBmDQowMDAwMDA3MTcxIDY1NTM1IGYNCjAwMDAwMDcxNzIgNjU1MzUgZg0KMDAwMDAwNzE3MyA2NTUzNSBmDQowMDAwMDA3MTc0IDY1NTM1IGYNCjAwMDAwMDcxNzUgNjU1MzUgZg0KMDAwMDAwNzE3NiA2NTUzNSBmDQowMDAwMDA3MTc3IDY1NTM1IGYNCjAwMDAwMDcxNzggNjU1MzUgZg0KMDAwMDAwNzE3OSA2NTUzNSBmDQowMDAwMDA3MTgwIDY1NTM1IGYNCjAwMDAwMDcxODEgNjU1MzUgZg0KMDAwMDAwNzE4MiA2NTUzNSBmDQowMDAwMDA3MTgzIDY1NTM1IGYNCjAwMDAwMDcxODQgNjU1MzUgZg0KMDAwMDAwNzE4NSA2NTUzNSBmDQowMDAwMDA3MTg2IDY1NTM1IGYNCjAwMDAwMDcxODcgNjU1MzUgZg0KMDAwMDAwNzE4OCA2NTUzNSBmDQowMDAwMDA3MTg5IDY1NTM1IGYNCjAwMDAwMDcxOTAgNjU1MzUgZg0KMDAwMDAwNzE5MSA2NTUzNSBmDQowMDAwMDA3MTkyIDY1NTM1IGYNCjAwMDAwMDcxOTMgNjU1MzUgZg0KMDAwMDAwNzE5NCA2NTUzNSBmDQowMDAwMDA3MTk1IDY1NTM1IGYNCjAwMDAwMDcxOTYgNjU1MzUgZg0KMDAwMDAwNzE5NyA2NTUzNSBmDQowMDAwMDA3MTk4IDY1NTM1IGYNCjAwMDAwMDcxOTkgNjU1MzUgZg0KMDAwMDAwNzIwMCA2NTUzNSBmDQowMDAwMDA3MjAxIDY1NTM1IGYNCjAwMDAwMDcyMDIgNjU1MzUgZg0KMDAwMDAwNzIwMyA2NTUzNSBmDQowMDAwMDA3MjA0IDY1NTM1IGYNCjAwMDAwMDcyMDUgNjU1MzUgZg0KMDAwMDAwNzIwNiA2NTUzNSBmDQowMDAwMDA3MjA3IDY1NTM1IGYNCjAwMDAwMDcyMDggNjU1MzUgZg0KMDAwMDAwNzIwOSA2NTUzNSBmDQowMDAwMDA3MjEwIDY1NTM1IGYNCjAwMDAwMDcyMTEgNjU1MzUgZg0KMDAwMDAwNzIxMiA2NTUzNSBmDQowMDAwMDA3MjEzIDY1NTM1IGYNCjAwMDAwMDcyMTQgNjU1MzUgZg0KMDAwMDAwNzIxNSA2NTUzNSBmDQowMDAwMDA3MjE2IDY1NTM1IGYNCjAwMDAwMDcyMTcgNjU1MzUgZg0KMDAwMDAwNzIxOCA2NTUzNSBmDQowMDAwMDA3MjE5IDY1NTM1IGYNCjAwMDAwMDcyMjAgNjU1MzUgZg0KMDAwMDAwNzIyMSA2NTUzNSBmDQowMDAwMDA3MjIyIDY1NTM1IGYNCjAwMDAwMDcyMjMgNjU1MzUgZg0KMDAwMDAwNzIyNCA2NTUzNSBmDQowMDAwMDA3MjI1IDY1NTM1IGYNCjAwMDAwMDcyMjYgNjU1MzUgZg0KMDAwMDAwNzIyNyA2NTUzNSBmDQowMDAwMDA3MjI4IDY1NTM1IGYNCjAwMDAwMDcyMjkgNjU1MzUgZg0KMDAwMDAwNzIzMCA2NTUzNSBmDQowMDAwMDA3MjMxIDY1NTM1IGYNCjAwMDAwMDcyMzIgNjU1MzUgZg0KMDAwMDAwNzIzMyA2NTUzNSBmDQowMDAwMDA3MjM0IDY1NTM1IGYNCjAwMDAwMDcyMzUgNjU1MzUgZg0KMDAwMDAwNzIzNiA2NTUzNSBmDQowMDAwMDA3MjM3IDY1NTM1IGYNCjAwMDAwMDcyMzggNjU1MzUgZg0KMDAwMDAwNzIzOSA2NTUzNSBmDQowMDAwMDA3MjQwIDY1NTM1IGYNCjAwMDAwMDcyNDEgNjU1MzUgZg0KMDAwMDAwNzI0MiA2NTUzNSBmDQowMDAwMDA3MjQzIDY1NTM1IGYNCjAwMDAwMDcyNDQgNjU1MzUgZg0KMDAwMDAwNzI0NSA2NTUzNSBmDQowMDAwMDA3MjQ2IDY1NTM1IGYNCjAwMDAwMDcyNDcgNjU1MzUgZg0KMDAwMDAwNzI0OCA2NTUzNSBmDQowMDAwMDA3MjQ5IDY1NTM1IGYNCjAwMDAwMDcyNTAgNjU1MzUgZg0KMDAwMDAwNzI1MSA2NTUzNSBmDQowMDAwMDA3MjUyIDY1NTM1IGYNCjAwMDAwMDcyNTMgNjU1MzUgZg0KMDAwMDAwNzI1NCA2NTUzNSBmDQowMDAwMDA3MjU1IDY1NTM1IGYNCjAwMDAwMDcyNTYgNjU1MzUgZg0KMDAwMDAwNzI1NyA2NTUzNSBmDQowMDAwMDA3MjU4IDY1NTM1IGYNCjAwMDAwMDcyNTkgNjU1MzUgZg0KMDAwMDAwNzI2MCA2NTUzNSBmDQowMDAwMDA3MjYxIDY1NTM1IGYNCjAwMDAwMDcyNjIgNjU1MzUgZg0KMDAwMDAwNzI2MyA2NTUzNSBmDQowMDAwMDA3MjY0IDY1NTM1IGYNCjAwMDAwMDcyNjUgNjU1MzUgZg0KMDAwMDAwNzI2NiA2NTUzNSBmDQowMDAwMDA3MjY3IDY1NTM1IGYNCjAwMDAwMDcyNjggNjU1MzUgZg0KMDAwMDAwNzI2OSA2NTUzNSBmDQowMDAwMDA3MjcwIDY1NTM1IGYNCjAwMDAwMDcyNzEgNjU1MzUgZg0KMDAwMDAwNzI3MiA2NTUzNSBmDQowMDAwMDA3MjczIDY1NTM1IGYNCjAwMDAwMDcyNzQgNjU1MzUgZg0KMDAwMDAwNzI3NSA2NTUzNSBmDQowMDAwMDA3Mjc2IDY1NTM1IGYNCjAwMDAwMDcyNzcgNjU1MzUgZg0KMDAwMDAwNzI3OCA2NTUzNSBmDQowMDAwMDA3Mjc5IDY1NTM1IGYNCjAwMDAwMDcyODAgNjU1MzUgZg0KMDAwMDAwNzI4MSA2NTUzNSBmDQowMDAwMDA3MjgyIDY1NTM1IGYNCjAwMDAwMDcyODMgNjU1MzUgZg0KMDAwMDAwNzI4NCA2NTUzNSBmDQowMDAwMDA3Mjg1IDY1NTM1IGYNCjAwMDAwMDcyODYgNjU1MzUgZg0KMDAwMDAwNzI4NyA2NTUzNSBmDQowMDAwMDA3Mjg4IDY1NTM1IGYNCjAwMDAwMDcyODkgNjU1MzUgZg0KMDAwMDAwNzI5MCA2NTUzNSBmDQowMDAwMDA3MjkxIDY1NTM1IGYNCjAwMDAwMDcyOTIgNjU1MzUgZg0KMDAwMDAwNzI5MyA2NTUzNSBmDQowMDAwMDA3Mjk0IDY1NTM1IGYNCjAwMDAwMDcyOTUgNjU1MzUgZg0KMDAwMDAwNzI5NiA2NTUzNSBmDQowMDAwMDA3Mjk3IDY1NTM1IGYNCjAwMDAwMDcyOTggNjU1MzUgZg0KMDAwMDAwNzI5OSA2NTUzNSBmDQowMDAwMDA3MzAwIDY1NTM1IGYNCjAwMDAwMDczMDEgNjU1MzUgZg0KMDAwMDAwNzMwMiA2NTUzNSBmDQowMDAwMDA3MzAzIDY1NTM1IGYNCjAwMDAwMDczMDQgNjU1MzUgZg0KMDAwMDAwNzMwNSA2NTUzNSBmDQowMDAwMDA3MzA2IDY1NTM1IGYNCjAwMDAwMDczMDcgNjU1MzUgZg0KMDAwMDAwNzMwOCA2NTUzNSBmDQowMDAwMDA3MzA5IDY1NTM1IGYNCjAwMDAwMDczMTAgNjU1MzUgZg0KMDAwMDAwNzMxMSA2NTUzNSBmDQowMDAwMDA3MzEyIDY1NTM1IGYNCjAwMDAwMDczMTMgNjU1MzUgZg0KMDAwMDAwNzMxNCA2NTUzNSBmDQowMDAwMDA3MzE1IDY1NTM1IGYNCjAwMDAwMDczMTYgNjU1MzUgZg0KMDAwMDAwNzMxNyA2NTUzNSBmDQowMDAwMDA3MzE4IDY1NTM1IGYNCjAwMDAwMDczMTkgNjU1MzUgZg0KMDAwMDAwNzMyMCA2NTUzNSBmDQowMDAwMDA3MzIxIDY1NTM1IGYNCjAwMDAwMDczMjIgNjU1MzUgZg0KMDAwMDAwNzMyMyA2NTUzNSBmDQowMDAwMDA3MzI0IDY1NTM1IGYNCjAwMDAwMDczMjUgNjU1MzUgZg0KMDAwMDAwNzMyNiA2NTUzNSBmDQowMDAwMDA3MzI3IDY1NTM1IGYNCjAwMDAwMDczMjggNjU1MzUgZg0KMDAwMDAwNzMyOSA2NTUzNSBmDQowMDAwMDA3MzMwIDY1NTM1IGYNCjAwMDAwMDczMzEgNjU1MzUgZg0KMDAwMDAwNzMzMiA2NTUzNSBmDQowMDAwMDA3MzMzIDY1NTM1IGYNCjAwMDAwMDczMzQgNjU1MzUgZg0KMDAwMDAwNzMzNSA2NTUzNSBmDQowMDAwMDA3MzM2IDY1NTM1IGYNCjAwMDAwMDczMzcgNjU1MzUgZg0KMDAwMDAwNzMzOCA2NTUzNSBmDQowMDAwMDA3MzM5IDY1NTM1IGYNCjAwMDAwMDczNDAgNjU1MzUgZg0KMDAwMDAwNzM0MSA2NTUzNSBmDQowMDAwMDA3MzQyIDY1NTM1IGYNCjAwMDAwMDczNDMgNjU1MzUgZg0KMDAwMDAwNzM0NCA2NTUzNSBmDQowMDAwMDA3MzQ1IDY1NTM1IGYNCjAwMDAwMDczNDYgNjU1MzUgZg0KMDAwMDAwNzM0NyA2NTUzNSBmDQowMDAwMDA3MzQ4IDY1NTM1IGYNCjAwMDAwMDczNDkgNjU1MzUgZg0KMDAwMDAwNzM1MCA2NTUzNSBmDQowMDAwMDA3MzUxIDY1NTM1IGYNCjAwMDAwMDczNTIgNjU1MzUgZg0KMDAwMDAwNzM1MyA2NTUzNSBmDQowMDAwMDA3MzU0IDY1NTM1IGYNCjAwMDAwMDczNTUgNjU1MzUgZg0KMDAwMDAwNzM1NiA2NTUzNSBmDQowMDAwMDA3MzU3IDY1NTM1IGYNCjAwMDAwMDczNTggNjU1MzUgZg0KMDAwMDAwNzM1OSA2NTUzNSBmDQowMDAwMDA3MzYwIDY1NTM1IGYNCjAwMDAwMDczNjEgNjU1MzUgZg0KMDAwMDAwNzM2MiA2NTUzNSBmDQowMDAwMDA3MzYzIDY1NTM1IGYNCjAwMDAwMDczNjQgNjU1MzUgZg0KMDAwMDAwNzM2NSA2NTUzNSBmDQowMDAwMDA3MzY2IDY1NTM1IGYNCjAwMDAwMDczNjcgNjU1MzUgZg0KMDAwMDAwNzM2OCA2NTUzNSBmDQowMDAwMDA3MzY5IDY1NTM1IGYNCjAwMDAwMDczNzAgNjU1MzUgZg0KMDAwMDAwNzM3MSA2NTUzNSBmDQowMDAwMDA3MzcyIDY1NTM1IGYNCjAwMDAwMDczNzMgNjU1MzUgZg0KMDAwMDAwNzM3NCA2NTUzNSBmDQowMDAwMDA3Mzc1IDY1NTM1IGYNCjAwMDAwMDczNzYgNjU1MzUgZg0KMDAwMDAwNzM3NyA2NTUzNSBmDQowMDAwMDA3Mzc4IDY1NTM1IGYNCjAwMDAwMDczNzkgNjU1MzUgZg0KMDAwMDAwNzM4MCA2NTUzNSBmDQowMDAwMDA3MzgxIDY1NTM1IGYNCjAwMDAwMDczODIgNjU1MzUgZg0KMDAwMDAwNzM4MyA2NTUzNSBmDQowMDAwMDA3Mzg0IDY1NTM1IGYNCjAwMDAwMDczODUgNjU1MzUgZg0KMDAwMDAwNzM4NiA2NTUzNSBmDQowMDAwMDA3Mzg3IDY1NTM1IGYNCjAwMDAwMDczODggNjU1MzUgZg0KMDAwMDAwNzM4OSA2NTUzNSBmDQowMDAwMDA3MzkwIDY1NTM1IGYNCjAwMDAwMDczOTEgNjU1MzUgZg0KMDAwMDAwNzM5MiA2NTUzNSBmDQowMDAwMDA3MzkzIDY1NTM1IGYNCjAwMDAwMDczOTQgNjU1MzUgZg0KMDAwMDAwNzM5NSA2NTUzNSBmDQowMDAwMDA3Mzk2IDY1NTM1IGYNCjAwMDAwMDczOTcgNjU1MzUgZg0KMDAwMDAwNzM5OCA2NTUzNSBmDQowMDAwMDA3Mzk5IDY1NTM1IGYNCjAwMDAwMDc0MDAgNjU1MzUgZg0KMDAwMDAwNzQwMSA2NTUzNSBmDQowMDAwMDA3NDAyIDY1NTM1IGYNCjAwMDAwMDc0MDMgNjU1MzUgZg0KMDAwMDAwNzQwNCA2NTUzNSBmDQowMDAwMDA3NDA1IDY1NTM1IGYNCjAwMDAwMDc0MDYgNjU1MzUgZg0KMDAwMDAwNzQwNyA2NTUzNSBmDQowMDAwMDA3NDA4IDY1NTM1IGYNCjAwMDAwMDc0MDkgNjU1MzUgZg0KMDAwMDAwNzQxMCA2NTUzNSBmDQowMDAwMDA3NDExIDY1NTM1IGYNCjAwMDAwMDc0MTIgNjU1MzUgZg0KMDAwMDAwNzQxMyA2NTUzNSBmDQowMDAwMDA3NDE0IDY1NTM1IGYNCjAwMDAwMDc0MTUgNjU1MzUgZg0KMDAwMDAwNzQxNiA2NTUzNSBmDQowMDAwMDA3NDE3IDY1NTM1IGYNCjAwMDAwMDc0MTggNjU1MzUgZg0KMDAwMDAwNzQxOSA2NTUzNSBmDQowMDAwMDA3NDIwIDY1NTM1IGYNCjAwMDAwMDc0MjEgNjU1MzUgZg0KMDAwMDAwNzQyMiA2NTUzNSBmDQowMDAwMDA3NDIzIDY1NTM1IGYNCjAwMDAwMDc0MjQgNjU1MzUgZg0KMDAwMDAwNzQyNSA2NTUzNSBmDQowMDAwMDA3NDI2IDY1NTM1IGYNCjAwMDAwMDc0MjcgNjU1MzUgZg0KMDAwMDAwNzQyOCA2NTUzNSBmDQowMDAwMDA3NDI5IDY1NTM1IGYNCjAwMDAwMDc0MzAgNjU1MzUgZg0KMDAwMDAwNzQzMSA2NTUzNSBmDQowMDAwMDA3NDMyIDY1NTM1IGYNCjAwMDAwMDc0MzMgNjU1MzUgZg0KMDAwMDAwNzQzNCA2NTUzNSBmDQowMDAwMDA3NDM1IDY1NTM1IGYNCjAwMDAwMDc0MzYgNjU1MzUgZg0KMDAwMDAwNzQzNyA2NTUzNSBmDQowMDAwMDA3NDM4IDY1NTM1IGYNCjAwMDAwMDc0MzkgNjU1MzUgZg0KMDAwMDAwNzQ0MCA2NTUzNSBmDQowMDAwMDA3NDQxIDY1NTM1IGYNCjAwMDAwMDc0NDIgNjU1MzUgZg0KMDAwMDAwNzQ0MyA2NTUzNSBmDQowMDAwMDA3NDQ0IDY1NTM1IGYNCjAwMDAwMDc0NDUgNjU1MzUgZg0KMDAwMDAwNzQ0NiA2NTUzNSBmDQowMDAwMDA3NDQ3IDY1NTM1IGYNCjAwMDAwMDc0NDggNjU1MzUgZg0KMDAwMDAwNzQ0OSA2NTUzNSBmDQowMDAwMDA3NDUwIDY1NTM1IGYNCjAwMDAwMDc0NTEgNjU1MzUgZg0KMDAwMDAwNzQ1MiA2NTUzNSBmDQowMDAwMDA3NDUzIDY1NTM1IGYNCjAwMDAwMDc0NTQgNjU1MzUgZg0KMDAwMDAwNzQ1NSA2NTUzNSBmDQowMDAwMDA3NDU2IDY1NTM1IGYNCjAwMDAwMDc0NTcgNjU1MzUgZg0KMDAwMDAwNzQ1OCA2NTUzNSBmDQowMDAwMDA3NDU5IDY1NTM1IGYNCjAwMDAwMDc0NjAgNjU1MzUgZg0KMDAwMDAwNzQ2MSA2NTUzNSBmDQowMDAwMDA3NDYyIDY1NTM1IGYNCjAwMDAwMDc0NjMgNjU1MzUgZg0KMDAwMDAwNzQ2NCA2NTUzNSBmDQowMDAwMDA3NDY1IDY1NTM1IGYNCjAwMDAwMDc0NjYgNjU1MzUgZg0KMDAwMDAwNzQ2NyA2NTUzNSBmDQowMDAwMDA3NDY4IDY1NTM1IGYNCjAwMDAwMDc0NjkgNjU1MzUgZg0KMDAwMDAwNzQ3MCA2NTUzNSBmDQowMDAwMDA3NDcxIDY1NTM1IGYNCjAwMDAwMDc0NzIgNjU1MzUgZg0KMDAwMDAwNzQ3MyA2NTUzNSBmDQowMDAwMDA3NDc0IDY1NTM1IGYNCjAwMDAwMDc0NzUgNjU1MzUgZg0KMDAwMDAwNzQ3NiA2NTUzNSBmDQowMDAwMDA3NDc3IDY1NTM1IGYNCjAwMDAwMDc0NzggNjU1MzUgZg0KMDAwMDAwNzQ3OSA2NTUzNSBmDQowMDAwMDA3NDgwIDY1NTM1IGYNCjAwMDAwMDc0ODEgNjU1MzUgZg0KMDAwMDAwNzQ4MiA2NTUzNSBmDQowMDAwMDA3NDgzIDY1NTM1IGYNCjAwMDAwMDc0ODQgNjU1MzUgZg0KMDAwMDAwNzQ4NSA2NTUzNSBmDQowMDAwMDA3NDg2IDY1NTM1IGYNCjAwMDAwMDc0ODcgNjU1MzUgZg0KMDAwMDAwNzQ4OCA2NTUzNSBmDQowMDAwMDA3NDg5IDY1NTM1IGYNCjAwMDAwMDc0OTAgNjU1MzUgZg0KMDAwMDAwNzQ5MSA2NTUzNSBmDQowMDAwMDA3NDkyIDY1NTM1IGYNCjAwMDAwMDc0OTMgNjU1MzUgZg0KMDAwMDAwNzQ5NCA2NTUzNSBmDQowMDAwMDA3NDk1IDY1NTM1IGYNCjAwMDAwMDc0OTYgNjU1MzUgZg0KMDAwMDAwNzQ5NyA2NTUzNSBmDQowMDAwMDA3NDk4IDY1NTM1IGYNCjAwMDAwMDc0OTkgNjU1MzUgZg0KMDAwMDAwNzUwMCA2NTUzNSBmDQowMDAwMDA3NTAxIDY1NTM1IGYNCjAwMDAwMDc1MDIgNjU1MzUgZg0KMDAwMDAwNzUwMyA2NTUzNSBmDQowMDAwMDA3NTA0IDY1NTM1IGYNCjAwMDAwMDc1MDUgNjU1MzUgZg0KMDAwMDAwNzUwNiA2NTUzNSBmDQowMDAwMDA3NTA3IDY1NTM1IGYNCjAwMDAwMDc1MDggNjU1MzUgZg0KMDAwMDAwNzUwOSA2NTUzNSBmDQowMDAwMDA3NTEwIDY1NTM1IGYNCjAwMDAwMDc1MTEgNjU1MzUgZg0KMDAwMDAwNzUxMiA2NTUzNSBmDQowMDAwMDA3NTEzIDY1NTM1IGYNCjAwMDAwMDc1MTQgNjU1MzUgZg0KMDAwMDAwNzUxNSA2NTUzNSBmDQowMDAwMDA3NTE2IDY1NTM1IGYNCjAwMDAwMDc1MTcgNjU1MzUgZg0KMDAwMDAwNzUxOCA2NTUzNSBmDQowMDAwMDA3NTE5IDY1NTM1IGYNCjAwMDAwMDc1MjAgNjU1MzUgZg0KMDAwMDAwNzUyMSA2NTUzNSBmDQowMDAwMDA3NTIyIDY1NTM1IGYNCjAwMDAwMDc1MjMgNjU1MzUgZg0KMDAwMDAwNzUyNCA2NTUzNSBmDQowMDAwMDA3NTI1IDY1NTM1IGYNCjAwMDAwMDc1MjYgNjU1MzUgZg0KMDAwMDAwNzUyNyA2NTUzNSBmDQowMDAwMDA3NTI4IDY1NTM1IGYNCjAwMDAwMDc1MjkgNjU1MzUgZg0KMDAwMDAwNzUzMCA2NTUzNSBmDQowMDAwMDA3NTMxIDY1NTM1IGYNCjAwMDAwMDc1MzIgNjU1MzUgZg0KMDAwMDAwNzUzMyA2NTUzNSBmDQowMDAwMDA3NTM0IDY1NTM1IGYNCjAwMDAwMDc1MzUgNjU1MzUgZg0KMDAwMDAwNzUzNiA2NTUzNSBmDQowMDAwMDA3NTM3IDY1NTM1IGYNCjAwMDAwMDc1MzggNjU1MzUgZg0KMDAwMDAwNzUzOSA2NTUzNSBmDQowMDAwMDA3NTQwIDY1NTM1IGYNCjAwMDAwMDc1NDEgNjU1MzUgZg0KMDAwMDAwNzU0MiA2NTUzNSBmDQowMDAwMDA3NTQzIDY1NTM1IGYNCjAwMDAwMDc1NDQgNjU1MzUgZg0KMDAwMDAwNzU0NSA2NTUzNSBmDQowMDAwMDA3NTQ2IDY1NTM1IGYNCjAwMDAwMDc1NDcgNjU1MzUgZg0KMDAwMDAwNzU0OCA2NTUzNSBmDQowMDAwMDA3NTQ5IDY1NTM1IGYNCjAwMDAwMDc1NTAgNjU1MzUgZg0KMDAwMDAwNzU1MSA2NTUzNSBmDQowMDAwMDA3NTUyIDY1NTM1IGYNCjAwMDAwMDc1NTMgNjU1MzUgZg0KMDAwMDAwNzU1NCA2NTUzNSBmDQowMDAwMDA3NTU1IDY1NTM1IGYNCjAwMDAwMDc1NTYgNjU1MzUgZg0KMDAwMDAwNzU1NyA2NTUzNSBmDQowMDAwMDA3NTU4IDY1NTM1IGYNCjAwMDAwMDc1NTkgNjU1MzUgZg0KMDAwMDAwNzU2MCA2NTUzNSBmDQowMDAwMDA3NTYxIDY1NTM1IGYNCjAwMDAwMDc1NjIgNjU1MzUgZg0KMDAwMDAwNzU2MyA2NTUzNSBmDQowMDAwMDA3NTY0IDY1NTM1IGYNCjAwMDAwMDc1NjUgNjU1MzUgZg0KMDAwMDAwNzU2NiA2NTUzNSBmDQowMDAwMDA3NTY3IDY1NTM1IGYNCjAwMDAwMDc1NjggNjU1MzUgZg0KMDAwMDAwNzU2OSA2NTUzNSBmDQowMDAwMDA3NTcwIDY1NTM1IGYNCjAwMDAwMDc1NzEgNjU1MzUgZg0KMDAwMDAwNzU3MiA2NTUzNSBmDQowMDAwMDA3NTczIDY1NTM1IGYNCjAwMDAwMDc1NzQgNjU1MzUgZg0KMDAwMDAwNzU3NSA2NTUzNSBmDQowMDAwMDA3NTc2IDY1NTM1IGYNCjAwMDAwMDc1NzcgNjU1MzUgZg0KMDAwMDAwNzU3OCA2NTUzNSBmDQowMDAwMDA3NTc5IDY1NTM1IGYNCjAwMDAwMDc1ODAgNjU1MzUgZg0KMDAwMDAwNzU4MSA2NTUzNSBmDQowMDAwMDA3NTgyIDY1NTM1IGYNCjAwMDAwMDc1ODMgNjU1MzUgZg0KMDAwMDAwNzU4NCA2NTUzNSBmDQowMDAwMDA3NTg1IDY1NTM1IGYNCjAwMDAwMDc1ODYgNjU1MzUgZg0KMDAwMDAwNzU4NyA2NTUzNSBmDQowMDAwMDA3NTg4IDY1NTM1IGYNCjAwMDAwMDc1ODkgNjU1MzUgZg0KMDAwMDAwNzU5MCA2NTUzNSBmDQowMDAwMDA3NTkxIDY1NTM1IGYNCjAwMDAwMDc1OTIgNjU1MzUgZg0KMDAwMDAwNzU5MyA2NTUzNSBmDQowMDAwMDA3NTk0IDY1NTM1IGYNCjAwMDAwMDc1OTUgNjU1MzUgZg0KMDAwMDAwMDAwMCA2NTUzNSBmDQowMDAwMzUwNDQ5IDAwMDAwIG4NCjAwMDAzNTA3MTIgMDAwMDAgbg0KMDAwMDM1MTIzNSAwMDAwMCBuDQowMDAwMzUxNTQyIDAwMDAwIG4NCjAwMDAzNTE5ODcgMDAwMDAgbg0KMDAwMDQyNTgyNCAwMDAwMCBuDQowMDAwNDI2Mjc2IDAwMDAwIG4NCjAwMDA0MjY4OTcgMDAwMDAgbg0KMDAwMDQyNjkyNiAwMDAwMCBuDQowMDAwNTA0MTEwIDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgNzYwNi9Sb290IDEgMCBSL0luZm8gNDggMCBSL0lEWzxBNTgxRTFDRTNGRTZFODRCQTdEREZCOTIxOTE4QURDMj48QTU4MUUxQ0UzRkU2RTg0QkE3RERGQjkyMTkxOEFEQzI+XSA+Pg0Kc3RhcnR4cmVmDQo1MTc5MjANCiUlRU9GDQp4cmVmDQowIDANCnRyYWlsZXINCjw8L1NpemUgNzYwNi9Sb290IDEgMCBSL0luZm8gNDggMCBSL0lEWzxBNTgxRTFDRTNGRTZFODRCQTdEREZCOTIxOTE4QURDMj48QTU4MUUxQ0UzRkU2RTg0QkE3RERGQjkyMTkxOEFEQzI+XSAvUHJldiA1MTc5MjAvWFJlZlN0bSA1MDQxMTA+Pg0Kc3RhcnR4cmVmDQo2NzAyMDINCiUlRU9G + + + + + + 123456789 + + 1238764941386 + + + Salescompany ltd. + + + Main street 34 + Suite 123 + Big city + 54321 + RegionA + + NO + + + + 123456789MVA + + VAT + + + + The Sellercompany ASA + 123456789 + + Big city + + NO + + + + + Our ref. + Antonio Salesmacher + 46211230 + 46211231 + antonio@salescompany.no + + + + + + 987654321 + + 3456789012091 + + + The Buyercompany + + + Anystreet 8 + Back door + Anytown + 101 + RegionB + + NO + + + + 987654321MVA + + VAT + + + + Buyercompany ASA + 987654321 + + Mainplace + + NO + + + + + 3150bdn + John Doe + 5121230 + 5121231 + john@buyercompany.no + + + + + + 2298740918237 + + + Ebeneser Scrooge AS + + + 989823401 + + + + + Tax handling company AS + + + Regent street + Front door + Newtown + 101 + RegionC + + NO + + + + 967611265MVA + + VAT + + + + + 2013-06-15 + + 6754238987648 + + + + 31 + 2013-07-20 + 0003434323213231 + + NO9386011117947 + + 9710 + + DNBANOKK + + + + + + 2 % discount if paid within 2 days + + + Penalty percentage 10% from due date + + + true + 94 + Freight + 100 + + S + 25 + + VAT + + + + + false + 75 + Promotion discount + 100 + + S + 25 + + VAT + + + + + 365.28 + + 1460.5 + 365.13 + + S + 25 + + VAT + + + + + 1 + 0.15 + + H + 15 + + VAT + + + + + -25 + 0 + + E + 0 + Exempt New Means of Transport + + VAT + + + + + + 1436.5 + 1436.5 + 1802.00 + 100 + 100 + 1000 + 0.22 + 802.00 + + + 1 + Scratch on box + 1 + 1273 + BookingCode001 + + 2013-06-01 + 2013-06-30 + + + 1 + + + 2013-06-15 + + 6754238987643 + + Deliverystreet 2 + Side door + DeliveryCity + 523427 + RegionD + + NO + + + + + + false + Damage + 12 + + + true + Testing + 12 + + + Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM: 3MB. Screen 1440x900 + Laptop computer + + JB007 + + + 1234567890124 + + + DE + + + 12344321 + + + 65434568 + + + S + 25 + + VAT + + + + Color + Black + + + + Company name ASA + + + 904312347 + + + + + 1273 + 1 + + false + Contract + 0.15 + 225 + 1500 + + + + + 2 + Cover is slightly damaged. + -1 + -3.96 + BookingCode002 + + 5 + + + Returned "Advanced computing" book + + JB008 + + + 1234567890125 + + + 32344324 + + + 65434567 + + + H + 15 + + VAT + + + + + 3.96 + 1 + + + + 3 + 2 + 4.96 + BookingCode003 + + 3 + + + "Computing for dummies" book + + JB009 + + + 1234567890126 + + + 32344324 + + + 65434566 + + + H + 15 + + VAT + + + + + 2.48 + 1 + + false + Contract + 0.1 + 0.275 + 2.75 + + + + + 4 + -1 + -25 + BookingCode004 + + 2 + + + Returned IBM 5150 desktop + + JB010 + + + 1234567890127 + + + 12344322 + + + 65434565 + + + E + 0 + + VAT + + + + + 25 + 1 + + + + 5 + 250 + 187.5 + BookingCode005 + + 4 + + + Network cable + + JB011 + + + 1234567890128 + + + 12344325 + + + 65434564 + + + S + 25 + + VAT + + + + Type + Cat5 + + + + 0.75 + 1 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/ehf-t10-mangler-elementer.xml b/oxalis-outbound/src/test/resources/ehf-t10-mangler-elementer.xml new file mode 100644 index 0000000000000000000000000000000000000000..7fe67b60115d40d49f0b17b63b61e3d01b8dc36c --- /dev/null +++ b/oxalis-outbound/src/test/resources/ehf-t10-mangler-elementer.xml @@ -0,0 +1,523 @@ + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0#urn:www.difi.no:ehf:faktura:ver1 + urn:www.cenbii.eu:profile:bii05:ver1.0 + TOSL108 + 2009-12-15 + 380 + Ordered in our booth at the convention. + 2009-11-30 + EUR + Project cost code 123 + + 2009-11-01 + 2009-11-30 + + + 123 + + + Contract321 + Framework agreement + + + Doc1 + Timesheet + + + http://www.suppliersite.eu/sheet001.html + + + + + Doc2 + Drawing + + JVBERi0xLjQNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyhuYi1OTykgL091dHB1dEludGVudHNbPDwvVHlwZS9PdXRwdXRJbnRlbnQvUy9HVFNfUERGQTEvT3V0cHV0Q29uZGl0aW9uSWRlbnRpZmllcihzUkdCKSAvUmVnaXN0cnlOYW1lKGh0dHA6Ly93d3cuY29sb3Iub3JnKSAvSW5mbyhDcmVhdG9yOiBIUCAgICAgTWFudWZhY3R1cmVyOklFQyAgICBNb2RlbDpzUkdCKSAvRGVzdE91dHB1dFByb2ZpbGUgMTEgMCBSPj5dIC9NZXRhZGF0YSAxMiAwIFI+Pg0KZW5kb2JqDQoyIDAgb2JqDQo8PC9UeXBlL1BhZ2VzL0NvdW50IDEvS2lkc1sgMyAwIFJdID4+DQplbmRvYmoNCjMgMCBvYmoNCjw8L1R5cGUvUGFnZS9QYXJlbnQgMiAwIFIvUmVzb3VyY2VzPDwvRm9udDw8L0YxIDUgMCBSPj4vUHJvY1NldFsvUERGL1RleHQvSW1hZ2VCL0ltYWdlQy9JbWFnZUldID4+L01lZGlhQm94WyAwIDAgNTk1LjMyIDg0MS45Ml0gL0NvbnRlbnRzIDQgMCBSPj4NCmVuZG9iag0KNCAwIG9iag0KPDwvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAxMjA+Pg0Kc3RyZWFtDQp4nHMK4eXSdzNUMDTUMzBRCEnj5TJUMABCQwVzAz0LIxMFczMDPTMLhZBcXi4DhXQQ4c7LFa3hqBCgqWus4aKpa6LhpmlorKGQkg9iJ5eCOLkgZmpeiZ5mrEKIFy+XK9AWpxCE2YYmFnpGRshmR2soIKkFAJQwHV8NCmVuZHN0cmVhbQ0KZW5kb2JqDQo1IDAgb2JqDQo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UcnVlVHlwZS9OYW1lL0YxL0Jhc2VGb250L0FCQ0RFRStDYWxpYnJpL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZy9Gb250RGVzY3JpcHRvciA2IDAgUi9GaXJzdENoYXIgMzIvTGFzdENoYXIgMTE3L1dpZHRocyA4IDAgUj4+DQplbmRvYmoNCjYgMCBvYmoNCjw8L1R5cGUvRm9udERlc2NyaXB0b3IvRm9udE5hbWUvQUJDREVFK0NhbGlicmkvRmxhZ3MgMzIvSXRhbGljQW5nbGUgMC9Bc2NlbnQgNzUwL0Rlc2NlbnQgLTI1MC9DYXBIZWlnaHQgNzUwL0F2Z1dpZHRoIDUyMS9NYXhXaWR0aCAxNzQzL0ZvbnRXZWlnaHQgNDAwL1hIZWlnaHQgMjUwL1N0ZW1WIDUyL0ZvbnRCQm94WyAtNTAzIC0yNTAgMTI0MCA3NTBdIC9Gb250RmlsZTIgOSAwIFI+Pg0KZW5kb2JqDQo3IDAgb2JqDQo8PC9BdXRob3IodGVyamVpbykgL0NyZWF0b3Io/v8ATQBpAGMAcgBvAHMAbwBmAHQArgAgAFcAbwByAGQAIAAyADAAMQAwKSAvQ3JlYXRpb25EYXRlKEQ6MjAxMTA0MDYxOTI5NDQrMDInMDAnKSAvTW9kRGF0ZShEOjIwMTEwNDA2MTkyOTQ0KzAyJzAwJykgL1Byb2R1Y2VyKP7/AE0AaQBjAHIAbwBzAG8AZgB0AK4AIABXAG8AcgBkACAAMgAwADEAMCkgPj4NCmVuZG9iag0KOCAwIG9iag0KWyAyMjYgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAyNTIgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTc5IDAgMCA2MTUgMCA0NTkgMCAwIDAgMCAwIDAgMCAwIDAgNTE3IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDQyMyA1MjUgNDk4IDAgMCAwIDAgMCAwIDAgNzk5IDUyNSA1MjcgMCAwIDAgMCAzMzUgNTI1XSANCmVuZG9iag0KOSAwIG9iag0KPDwvTWV0YWRhdGEgMTAgMCBSL0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggODAxMjIvTGVuZ3RoMSAxNzQyODQ+Pg0Kc3RyZWFtDQp4nOx7B3yURf73zLO9ZXeTbNom2d1sCpCE0EkgJAtphBAghIWEmpBQlWIgdBDBGsSKBUXFBp6IbhaQYEXFXs/zTs8KdxZOxV5ByPud57eDwKnvvffee/e/95NJvs/3O78pO/Obmd8zkZVxxpgLDy0bU1pbWXFs6TfpTNlYypj74rJhpeOuOuvTyYxtzWdMt7Ns2MiSj8++YCljWw4zphlTUVpW/tETX//ElEvGIf9ZxZjRtXOaB69j7M7DjG+xVtQGhz357l87mTL0G8Yqpo6uzevz4/v7ljHG38CnNjTNa1yYe0fuKMayQmhf2rRksTd044FXGavz4vOSZy6cNe+776qtjPVAe1PSrMZFC1ky8+PzRXvHrLOXz3zk+Z1axqYUMhY9bPaMxuYPM04MQf8YMxswGwbbTv2byG9CPn32vMXLKr8yfsGYgvlkLDlrRsv8tGe6FTG28RmUv3H2gqZGo0lnYWzBWsZSy+c1Llvoy02/Cu07UO6d3zhvRuaSGozlsq2MRcUtXLBocaebXYjxqOULW2YsPOs+5QRj/Rz4OAcTvtXd3LHuUPb50+yF37JEIxPpwU9WvSD4ybTrVxw7enyD6VPD/ciamMIooZ2enWD8gHnrsaNHt5o+VXs6JWk2C4s9jdUwnWpQmIPlsRmMOa/A56pVtNn8CpQadZt1fdFlKrHmFXahwoxMsesURdFqFO0hpnQG2D2d6giQqmu9XhaA2EpjMNysZHoZv0XtdK8uSswUvUf9PBr+MrbPrWJd/nVJ+ym7559pp9n5z7X7v0361/91n6tN+8/MoSt1pX9X0kxnE/+Retp+rOG0dsfYlP8nA+pKTN/MNsPfm3+tXJv/j63ZLyXluV/v9zfb3ct8/+xn/p8mzH3Tv+uzulJX6kpdqSv9/52UG7n5n2qnY9f9q8fy35I0/dmG//QYulJX6kpdqSt1pa7UlbpSV+pKXakrdaWu1JW6UlfqSl2pK3Wlf3PSRJAc+VbYA8hBKduYlt2MfCpzwCK+n2VjaawnG8pKWTmrZmPYDLaAtbBWtrWzU21pY97TypvYPJQvVst557f4mB6dT3S+1nmw83tmEA14EmOdTZHPTTptVNEsDs8EGqFmhOY67uBJPJW38iV8Nb+B72F6/qla+uWZ32ZDXol8901hv534z/3/inPq/jc9UNKqTzHazNPspepzwj/SBc3vDJs6W1VdCohZ/7ckzb+0t//ROzFQ0Txt6pTJkybW1wXH1Y6tGTN6VPXIqhGVwyvKy0pLhg0NFBcNKRw8qCB/4ID+eT1zc7plZqT70zwJsU6H3WYxm4wGvU6rUTjLKfOXN3hDmQ0hbaZ/+PBckfc3wtB4iqEh5IWp/PQ6IW+DWs17es0Aas48o2aAagZO1uQObyErzM3xlvm9oRdL/d4OPrGmDnpjqb/eGzqi6mpVazPVjA0Znw8tvGUJs0u9Id7gLQuVL5ndVtZQiv7aLeYSf8kMc24OazdbIC1QoW7+he28WxFXhdKtbFC7wow28bEhTUZZY3NoTE1dWanb56tXbaxE7SukLwkZ1L68c8SY2QZve87+tks7HGx6Q7a12d/cOLkupGlEozZNWVvbRSFndqi7vzTUfcX7CZjyjFCOv7QslO1HZ1VjT34AD+kyHH5v27cMg/cf+fR0S2PEos9wfMuEFFM86SaUS80wNowQ8/P5xFg2dATYdGRCa2vqKO9l091hFsjLrg8pDaJkvyxxBUXJWllysnmD3yeWqqwh8rtkdkJo7XRvbg68r/5m4Bfl3pAms2F602zBjTPa/KWl5LdxdaFAKUSgMTLXsvZeeajf2IBJzBFuqKkL5fkXhmL9w6gCDF6xBnNq69QmkWah2JIQa2iKtArllZWKcXnL2hpKaYCiL39N3T7Wt/Ngez+ve1df1o/Vi3GE4kqwKJllbXXNM0OeBncz9udMb53bFwrUw331/roZ9WKV/I5Q94P4OJ/6iWorzO2M2rKymLkhw+itU9yaerFaMHjL8fAPK0SBA8ulZsWKDiv01nE3k9XwKZEaQp3WDzKajJLhokgjmpYMd/vqfZR+Y0juyJh0GSHjKX05YDg5JvqcXx0a1RYD6u4tm1F6ygBP61QXGWCkt18epyJ8EflgtDCK5RwuizQZOLmwKehGNYlVTPCG2BhvnX+Gv96PPRQYUyfmJnytrm9Vrb+qZmKdutqRXTLutByV51MuxHwolhmlBHuwPNstl1XNV6j5k9nhZxRXymJvm9FfVdsmOvdHOmRenCBMWp9Z2bghP7ofjmY5opu/vNHvdXjL2xo7OtdOb2sPBNoWljXMHiT68Fc2t/lr6wrd6ljH1q12rxAfFc2qeNW4Ybk5iD3D2v384pr2AL+4dmLdPgdj3ovH1YUVrpQ0DKtvT0dZ3T4vYwHVqgirMIqMV2RET2ORMar13fsCjK1VS7WqQc03dXCm2ozSxllTh0I2h7QpsGnJFlBtImGREmbDxQi3Zd5msTyr6me3NdSLw8XisJT45SHuL2IhxV/UzhW9NWT2zxgWsviHCXuxsBeTXS/sBmwMHsfhHBGT2hr8iFPYUHXMzWkrakSX3o7OznF1vhfdR+p92GqTgYl1IVM2Yr8uYwTqVQg0wFwRWtvUKMbBgnWirSGjsqke21Z2iCqVIRN6MEV6QI1ytY3YjmjUhLXBAqrt1yITWlsfqs8WH1o3p17dzo4QG+4fhGWnPnWZ4oPy6tui/X3Us4mjYM64SJAJY2O1dWRxI4sPqycnGawYeZMfRU0NXnhby5pqsdUplprdZJmBkKjNnKHC7I4UMjEtTYbFZg6ZeqJD/Apt6SmOpC7DUF9Pg1dzF0Uq4LMdIQtGlHmKKyMN4B0UVYqx4PciDFVUfUx0U9PBxvqXIbKIQas9GVAcsmVUNiL4U3sLLP582dgoYoQl0scBshrEzK3wuyZjXEfndv9y3ykpN8cvXg5iYzL3PmxsVt92piE0KTs3x3im1aaa29qMtl9uQP4y2k6yMHrL8NZgLGzSeDuU83ebEvgIiPVSrJPiPCnWSnGuFGukWC3FKilWSrFCiuVSLJNiqRRLpGiVYrEUi6Q4R4qFUiyQYr4U86Q4W4qzpJgrxRwpZksxS4qZUsyQolmKJimmS9EoRYMU06SYKsUUKSZLMUmKiVLUS1EnxQQpxksRlGKcFLVSjJWiRooxUoyWYpQU1VKMlKJKihFSVEoxXIoKKcqlKJOiVIoSKYZJMVSKgBTFUhRJMUSKQikGSzFIigIp8qUYKMUAKfpL0U+KvlL0kaK3FL2kyJOipxS5UuRIkS1FDym6S9FNiiwpMqXIkCJdCr8UaVL4pPBK4ZEiVYoUKZKlcEuRJEWiFAlSxEsRJ4VLilgpYqSIlsIphUMKuxRRUtiksEphkcIshUkKoxQGKfRS6KTQSqGRQpGCS8EigndKcUKK41L8JMUxKY5K8aMUP0jxvRTfSfGtFN9I8bUUX0nxpRRfSPG5FJ9JcUSKT6X4RIqPpfibFIel+EiKD6X4QIr3pfirFH+R4pAUB6V4T4p3pXhHireleEuKN6X4sxRvSPG6FH+S4o9SvCbFH6R4VYrfS/GKFC9L8ZIUL0rxghTPS/GcFM9K8YwUT0vxlBRPSnFAiiekeFyKx6TYL8WjUjwixcNSPCTFg1I8IMU+KTqk2CvF/VLskWK3FLukCEvRLkVIivukuFeKnVLcI8UOKe6W4ndS3CXFdim2SXGnFHdIcbsUt0lxqxRbpbhFipuluEmKLVLcKMUNUmyW4noprpPiWimukWKTFFdLcZUUV0pxhRSXS3GZFBuluFSKDVK0SXGJFBdLcZEUF0pxgRTy2sPltYfLaw+X1x4urz1cXnu4vPZwee3h8trD5bWHy2sPl9ceLq89XF57uLz2cHnt4fLaw+W1h7dIIe8/XN5/uLz/cHn/4fL+w+X9h8v7D5f3Hy7vP1zef7i8/3B5/+Hy/sPl/YfL+w+X9x8u7z9c3n+4vP9wef/h8v7D5f2Hy/sPl/cfLu8/XN5/uLz/cHn/4fL+w+X9h8v7D5f3Hy6vPVxee7i89nB52+HytsPlbYfL2w6Xtx0ubztc3na4vO1wedvhJbuEwK05nFrkwZ05nOoCraPceeHUQaC1lDuXaE041QpaTblVRCuJVhAtD6cMBS0Lp5SAlhItIWqlssWUW0TUQsZzwinDQAuJFhDNpyrziM4mOiucXAaaSzSHaDbRLKKZ4eRS0AzKNRM1EU0naiRqIJpGNJXaTaHcZKJJRBOJ6onqiCYQjScKEo0jqiUaS1RDNIZoNNEoomqikURVRCPC7kpQJdHwsHsEqIKoPOyuApWF3SNBpUQlRMOobCi1CxAVU7sioiFEhVRzMNEgal5AlE80kGgAUX/qrB9RX+qlD1Fvol7UWR5RT2qXS5RDlE3Ug6g7UTeiLOo6kyiD+kwn8hOlUdc+Ii+18xClEqUQJRO5iZLCSaNAiUQJ4aTRoHiiODK6iGLJGEMUTeSkMgeRnYxRRDYiK5VZiMxEJiozEhmI9OHEMSBdOLEGpCXSkFGhHCdiKvFOohNqFX6ccj8RHSM6SmU/Uu4Hou+JviP6NpwwDvRNOKEW9DXlviL6kugLKvuccp8RHSH6lMo+IfqYjH8jOkz0EdGHVOUDyr1Pub9S7i9Eh4gOUtl7RO+S8R2it4neInqTqvyZcm8QvR6OnwD6Uzh+POiPRK+R8Q9ErxL9nugVqvIy0UtkfJHoBaLniZ6jKs8SPUPGp4meInqS6ADRE1Tzcco9RrSf6FEqe4ToYTI+RPQg0QNE+4g6qOZeyt1PtIdoN9GucFwxKByOmwRqJwoR3Ud0L9FOonuIdhDdHY5DvOa/o17uItpOZduI7iS6g+h2otuIbiXaSnQLdXYz9XIT0RYqu5HoBqLNRNdTg+sody3RNUSbqOxq6uUqoiup7Aqiy4kuI9pIdCnV3EC5NqJLiC4muojowrCrEXRB2DUddD7R+rBrJmgd0XlhVxC0NuxCMObnhl0DQGuIVlPzVdRuJdGKsKsZtJyaLyNaSrSEqJVoMdEi6rqFmp9DtDDsagItoM7mU815RGcTnUU0l2gOtZtNNItGNpOazyBqpppNRNOJGokaiKYRTaVJT6GRTSaaRJOeSF3X0wfVEU2g4Y6nDwpSL+OIaonGEtWEYwOgMeFY8Qmjw7Fie48Kx64HVYdjc0EjqUoV0YhwLO4FvJJyw4kqyFgejl0DKgvHXgQqDceeCyoJx64FDQtHl4OGEgWIiomKwtF4v/MhlCsMO+tBg4kGhZ1iaxQQ5YedFaCBYWcdaEDYORHUn8r6EfUNO3NAfahm77BTTKxX2CnOZh5RT2qeS5+QQ5RNnfUg6k6ddSPKIsokygg7hZfSifzUZxr16aPOvNSLhyiV2qUQJRO5iZKIEsOOKaCEsGMqKD7smAaKI3IRxRLFEEVTAyc1cJDRThRFZCOyUk0L1TST0URkJDIQ6ammjmpqyaghUog4EQt02qd7BE7YmzzH7c2en6CPAUeBH2H7Abbvge+Ab4FvYP8a+AplXyL/BfA58BlwBPZPgU9Q9jHyfwMOAx8BH0bN8nwQNdvzPvBX4C/AIdgOgt8D3gXeQf5t8FvAm8CfgTdsZ3let/X2/An8R9vZntdsmZ4/AK9C/96W7XkFeBl4CeUvwvaCbZ7neejnoJ+FfsY21/O0bY7nKdtsz5O2WZ4DaPsE+nsceAwIdO7H81HgEeBh6zmeh6wtngetizwPWBd79gEdwF7Y7wf2oGw3ynbBFgbagRBwn2W5517LCs9OyyrPPZbVnh2WNZ67gd8BdwHbgW3AnZZczx3g24Hb0OZW8FbLWZ5boG+GvgnYAn0j+roBfW1GX9fDdh1wLXANsAm4GrgK7a5Ef1eYR3kuN4/2XGae5dlovtNzqXm75wJNhud8Tb5nPc/3rAuuDZ63Y23w3ODq4Jodq4OW1dyy2r26avXK1TtWv7U6EK03rwquCK7csSK4PLg0uGzH0uADyoVspnJBoDC4ZEdrUNsa27q4VfNNK9/Ryktbea9WrrBWR6u3VWNdHGwJLtrREmQtY1rWtoRatINDLQdbFNbCzR2d+3e1uFPLwYFVLTZH+TnBBcGFOxYE58+cF5yLAc7JnxWcvWNWcGZ+c3DGjuZgU/70YGN+Q3Ba/pTg1B1TgpPzJwYn7ZgYrM+vC05A/fH544LBHeOCtfk1wbE7aoKj80cFR8FenV8VHLmjKjgif3iwcsfwYEV+ebAMk2fJjmRvssYhBjAqGSNhbj6slzvgPuj+wq1l7pB7v1sTbU/yJCnd7Ym8ZHQiX5B4buLliRp7wssJSiChe065Pf7l+PfiP4/XxgTiu/csZ3GOOG+cxiXmFlc9rlzl4lLi3v3VuVbH+TPL7S5ud3lcSpnHxZnzoPMLp8b1qONlh2K3c7u9064E7Khuj/JEKeLRGaUJRPUeWG63eWyKeHTaNHEBGyyixyzrmHHldovHogSLLaMtSsBSXFIesOT2Kmca7uVcfOnIyzVGMQru8pTjXO+K4zqO93n7uNrs7KoOIxtbFTKOmRTiF4cyasUzUDMxpL84xIITJ9W1c35ZfTtXSsaFYsW/2Kr5CzZuZMNSqkIptXWhrSn1VaG1EAEhOiFYSnscG1afPXVR66Ls7MVT8Zi6aHG2+oscbxW5bGEUv4sWIy9+WtU8y/7NRNVA0xYhLZbGxb/d6n964v/pAfz3p3YmvmQwtFM5nzUr64F1wHnAWuBcYA2wGlgFrARWAMuBZcBSYAnQCiwGFgHnAAuBBcB8YB5wNnAWMBeYA8wGZgEzgRlAM9AETAcagQZgGjAVmAJMBiYBE4F6oA6YAIwHgsA4oBYYC9QAY4DRwCigGhgJVAEjgEpgOFABlANlQClQAgwDhgIBoBgoAoYAhcBgYBBQAOQDA4EBQH+gH9AX6AP0BnoBeUBPIBfIAbKBHkB3oBuQBWQCGUA64AfSAB/gBTxAKpACJANuIAlIBBKAeCAOcAGxQAwQDTgBB2AHogAbYAUsgBkwAUbAAOgBHaAd2omnBlAADjDWzGHjJ4DjwE/AMeAo8CPwA/A98B3wLfAN8DXwFfAl8AXwOfAZcAT4FPgE+Bj4G3AY+Aj4EPgAeB/4K/AX4BBwEHgPeBd4B3gbeAt4E/gz8AbwOvAn4I/Aa8AfgFeB3wOvAC8DLwEvAi8AzwPPAc8CzwBPA08BTwIHgCeAx4HHgP3Ao8AjwMPAQ8CDwAPAPqAD2AvcD+wBdgO7gDDQDoSA+4B7gZ3APcAO4G7gd8BdwHZgG3AncAdwO3AbcCuwFbgFuBm4CdgC3AjcAGwGrgeuA64FrgE2AVcDVwFXAlcAlwOXARuBS4ENQBtwCXAxcBFwIXABax66luP8c5x/jvPPcf45zj/H+ec4/xznn+P8c5x/jvPPcf45zj/H+ec4/xznn+P8c5x/3gIgBnDEAI4YwBEDOGIARwzgiAEcMYAjBnDEAI4YwBEDOGIARwzgiAEcMYAjBnDEAI4YwBEDOGIARwzgiAEcMYAjBnDEAI4YwBEDOGIARwzgiAEcMYDj/HOcf47zz3H2Oc4+x9nnOPscZ5/j7HOcfY6zz3H2Oc7+fzoO/5en+v/0AP7LU8K0qYwZbmbsxNWnfcN6DJvLFrG1+LmQbWRXs0fZW2w6Ww+1mW1l29jvWIg9xp5lr/+Lvk2uphPLdfOYVbOX6VkMY51HO4+c2AZ06KJOsVyNXIzW+7Ol09H52Rm2z05c3ek40aGPZma1rU15Fdav+fHOo3i/It85QOSVi6DtaosvDTefuO/E9jN8UMMmsklsMpvCGlgj5t/MZrM58MxZ7Gw2j81Xc/NRNgvPmchNQy3EElX/XGsBW6h+F34xa2VL8LMQelEkJ8rOUfOtbCl+lrHlbAVbyVax1ZHnUtWyCiUr1PwyYA07FytzHlunKslkWc/OZxdg1S5iF7NLfjN3yUnVxjawS7HOl7HLf1VvPC13BX6uZFdhP2xi17Br2fXYFzeyLWdYr1PtN7Cb2S3YM6LsGlhuUZUofYg9xfawe9l97H7Vl03wGnlE+mWm6sOF8MEqzHD9KSMm/y096a01mLuYW1tkpstgX3dKiyURP4qa61GTeqF1EL2sPsMTV2AOpH+eEeWuUef/s/VUr/yWVfpjyymeuVHNCXWm9df0tewmnMBb8RReFeo2aFK3qPpU+80n625V87ezO9idWIvtqpJMlm3Q29ldONt3sx3sHvz8rE9VxPeynerKhVg7C7NdbDdW8n62l3Wo9t8q+yX7rog9fNKyjz3AHsQOeYTtR6R5HD/S8jBsj0asB1Qb5R9nTyAvalHuKfY0ItRz7Hn2AnuZPYncS+rzGeReYa+yP7DXuQ3q9+xveB5nr+jeZ1FsKGO6B+DnLWwqfnSISos0ryKKaJiBFbBqNopNeojZ8LqPY4P4nj2u0lJjruERvMoV5sVlwMg4LwnYtYptb1JSsX9vf/1GjbOyg+fuLjZsxDW3+Pi7x1/KO/7ukeiCvCM8751D7x5yfPmSsyCv76HXDvXuxZ0+p4rYKMVgiNX703oq/bMyB/Tt26dI6d8v058Wpai2fgMGFmn69klVNLHSUqSIPNe8+tNEzejjemWNv3h8X11qkj3WptcpyQnRuYUZjtpJGYU9Uwwag16jMxq6DRyWVnV2WdqbBmeKKy4l2miMTolzpTgNx9/SRR39Shd1rER79rFNGv3gycXpmuvNRkWr13ekJiT2GOyrHG+PcWgtMQ5nnNEQ7bR2K518/EJXsugj2eWivo5Xwy3+zqPaNbpYlsYy2U37WHrn4d1WBx/p74iIzI7OL3ZbICxSmCECSUJlOMTTpj6t6jPQjWeI4hwLr073Z2Z8Y7VYE9JS/GYbj9NamdVhVe7zP+p/2a/xW/3W6JSx0UFdkBUXF0cXFOTlTZnijC9wQjr7Oo70cfaFx7On0KuQZWdnxMXpVZdnaXyaKI0/LTNzwEBOfo43+DU+bauROzI8nowYk3bB8Q/naswx/uSUDDs38rDWlpiV6u2RFKVdyd/jjw+Jc0dpNQariQ8+8azJZtLqotxx2rAlyqjRGO2WjcdXiv8X7h7GtJdjd0UzD1saSCn28ZgEB6+OcdjxiLXhEW3FIwGTjXkQf+cxltR5eBdqJMEHu+wRtqn83S6ryod3oXbSg/iLzMQSuDUcVePu4JntunGs+Egx9twhdbqvEfXuNUXsNb8vLbO/s9+Avj5M1dCvp+L3O8WW014+/s4vtp34LL5793iecdfhm2r29Ftw94X3ta+6u6VAueGuY3eO9WRp12V5Jtx+ePOcPeeP+MlZtPYx8X/x3dN5VDMOM8tik9sNMR006pjIqGMio46JjDomMuqYDsW5x5bCUlMMHdy6KyYmUd/Bu+1Kq0kUSxg5M3kHnAU0+D5YPnXwTjFsF0l5HuRsNOO0ZpvhRCbfb7CZtaoOGGO9SQlpscbu8Uq5aj0Qk+w0nhhucLhdMW6n6fgHBptBp8NDe2+WBxs5MiN9NmZUyO4JOBqKFhYptl694vPyzD0TEpI6/sFlwQQDqem9rVazWGezWGezAxXNZtQyi3U2P4CVY537A4nIsPQBNZaEeFteQu+eek+3Gk9QbufiaGzkvsU877XsiDOwpU8qZ8GQvL59xf6eknHSIX4u9jR2N/ef5iV1e/O+YqML6dJnG2M9ifG+GKNyoq/G4kqJdaXGWpQTFRx+S0zwxhhy3LO9vdITTHypjl9oSfJkJs6zu2OsSUar8JrVqJ11bJPBbNBoDWY9Asjmk/ZtPdKtSd3cP03QbEvtkWgxxaS4xCnAXnkank1m3dmy9nR9xJn6iDP1EWfqI87UR5ypF86Md6YIT6YIT6Y4rDY+MsWLshTxdQvmzOjg5l16vdXfwS27XDXWU7YRHQDH6TvJf+b20Z5yGDRPB5buXHa1KcaXmOiLNfZI4q4e1XPmjey+Z/CEKTm33DhqVnm65urGLfMLT/Q8OeO7u6UZ4osnL58wem6/qOM/dqtoEntpYucRjVfzLOvPLmlPZuI/9mIO4INinkxERrH4WRFHZEUcAf5MOCAr4gDwx6JBVodiCdjyonhU4keegNk23JPewZXdMSM0n/RG37tNtuG9czq4vt1UjRfQa9lH1AfPm0KTP0AOwEbRn/Im0bvo9eNPg0pVhAPU941X0RkSC6vq8hqvndF/6Dmb67NrSvsnmPRKtM2eVRgctPRcX2BKYcH44myr2AK3OROdtsSMlOjAyl2tFzy6YrAjKS0hKiYhOsvj6+bbe++E9XXZ6dl+Y0yKiIcN8MsW/BWQiXfthoCneDC3uAvE+SgQ56PA4RAPeKJAnJSCB/mPiIh55LW8iLPyIs5S2RqxWwQr5oA5xlduKchya6N6iH9USxjRr4Nrd0VV60aKjYGtEV9QfEaE7FNw6iHqrz/FR3Hxzshb16XJVN/N0lMDNVsMzuRY8Tqs2Dyp6dIJ3fpMv3La6PUBQ6wnIdEbbdpWsrq0uG5goqvf+KG+IYHyrETsGK0WO2Zp9fjq9e3TFz94fkVZiWKRgeh4We2EwumrAqXrZgyJ7lHSW3hrCry1WfMcy2b92L2BHnkDigcsGKCJ8YrI6hVhNsaX44ALcoS3coQbcxx2vEOxF37cU5p9R7aSDSftQc3sftrI5tNG9piat6h8eLdopBX+8/lynl6rvUKr7NfyV7Rcq03OeztzRMLHDVELo5Qo08fJ6gabckQ9ZFPOaZGvmz7vZNNmgzny0tH7fadsK9fpm09xZQ1QHWrQbM5KPB5OLV9YE2iuzLMaLHqNojFYBow/J7Bge8ugwnO2Ns29piF3m2b50iGTi9IURcnyVS0b39OV5DJEJUbbYuxWS2JCTNGKjhWL951XVrroxrqYdZt6jpwxUJzDzZ1Hda/Ag2PYxwF3tMMSeddmOixWPjIrQTwXjuXlf/+ewt46/X32Mb3P+A+B1NQ4yNTUPhTT1eiuBnbV92b4fu+YgJNXjynKinR7ynn+4ozzrga+rAf5D6wPc3B9uGoEjrY+YBs6oqg8N78yd2TiSHXvqvebU9/vBZH3Aq6WkReE2MfqP9f8/Ebopx5vg/M3DJHlcA0YoL4m6DLk0r1ijPZiI8cYY3NKexYsKjPGeBPwxjDE5ZT0LFhcilL1RaGPTo6PS3EYRl5emV9f2suRW1NVkT5hSaUn0WgxarV4KP6CqaXpdcHjG37dojnfaDFpNCaLcWlwdFLe0G69S3vEDJl5yUhaQc1WrGAftilgpxUUj+J+vMcvrNKv3Dqwau5Ui4guFrFcFhFiLGL1LGLhLCjfywLIslSH8L45d0SPxPRK6froAuF26WbHad7+LV+f7lqXZiv5NNqY0LOyV9Gqv3fiddUTV470/ew6e/VvOQoOahBRQrxr3oWHYnAXuyuQXNydd4vm3Z0808YzrTzTyDMNvIeGd1d4aiSEpkYclhqJCamRmJAacViqCAWpeWZujhXv3ljhrlgRdWLFbTVW+Cz2AcUsbjF77ax6IZYpUXxPwT4C72GlXVcduYlOibhMvojgMpn4GX/WqK/hUwKs5t1Bi3a2LLhz/oCCRfcsAg+81100d3TlnFKfu3ju6OFzS738g/n7LqwatmZ3C3gEeFXluukF/aatqx6xrrGg39R1tHuU7fBNX9a0e2F/nmmPbA17ZKZ28SeJOLb2yN6xi70SzQIx2AziEDMxbZaEU50RMGWPyLS7vJUusSvU48jzxLv1kNwPclJqYPuFjaAeLr2yXdGbjMb4lHRXYq/+g/xnboOMoYMKUmy+9BSrVsM10+NSnSaTyRjbc+TA46G/3wjrB5Rm2TVGs9kU5RYRz9f5uTJPu5MNYpN3d2dOf25krXMjE8yNeCA3shdyI57IFRO3xttyj/iHp9iOxA/vjTdnu4GW8kUx1b6R9+WLB+gyoY3cOvGXhZhh35Oh3UUBXy9uW3HyBaDMMzq83XvGlzcHUtbYo3VGm3G1IYbOw0dGq0kbbf9oYEV8enKsUWfSaSelpDmiTPqMqkWjlChvekyS0/An/LGl1ZqsEM6kmHTvCfOUaSazSReVIOa9SdwsNA8hTlyFe0U/bskSJz1LHPIso4i9anTOcqhhmP94P62uJ+IVT8Qr4B/U/SCEcItHbhC1pmrgPwZMMbmVWRZdYiWCte7n64XYEzI+Z792Slj+u+vFyT3hVPf7gIE/XzS2GKJTXPEpTn31tWo4MMR6E7A9jPF5w3sVrSzDBQO7Jdp0MkosDY4qnHXJdCVN7ojj34yeVpJRF1RapQVRgps7v+Nv66YyF+7gUXt0Ge5qRzkG/c5LkZuxGJUmMzKImDP/o8PDBvFHf3K0wcmNLn+y2+8yRpkSu3k83RNMpoTuHk+3RBNvNVrFkKxGzQPWaKtOb3VajxX4st0Wizvb58tNtFgSc7FS13V+z+ezg8zC4tsZ7vr77xd3fpMGPnyR52U/JjaXXt1ViJtxfH5eUWFPgXkVeT3LABHzNmhmKjfoWuVs3JkVjgrM5sU+p85GhpYzLHEuZb3eER8dnWDXx5tjffEJvtj/xd65gEdVnQt77ZnJ3BNCuIWLMOEmNwMCCg2IqKjcDBEFEVudIZmEkdyYTCABgZEgoqUWb4hoFakiXoqWWFuttVEogoAihpgSqhAJKo1CPUxIKYd93rX2JEwAW3r+/znn+Z8/8/nuvfbea337u6zbRAIO7cz9Le4N6Wte3uSO9nFT6czlLe8lJqqfJD9niDb4IuXpHxZT3P+BbL4YMQ9slf9h+e35YkmPyrH/lyRuj9XXQo79M7HN/idy+L8j9lCrtEqrXIS89U+k5n9THCmt0iqt0iqt0iqt0iqt0iqt0iqt0iqt0iqt0iqt0iqt0ir/v4j6/8jy38KolH+GQ1SIOGEVFm2tvktYzDOEWyQLi14rks0z9D2iL+Wfib5aon6YYxe9nmN3nvbVFsk71Lla3EadgLiNOvs4dtE/59hd/4zjInVci87bzDPO/ENL5M4xrTvvimjFHL/V5qnjStrWcuyiH+bYXa/juEj/QluJ/qHaWp5+xbGL/g3H7vpRjov0eo5r9S+x2CLc5hmUK/HpMlNP0fTvk2Spo1l5m6CuZNkkEswW0fQv4wwxJ0XLlpg6cXh/bbRsjblvE6fMM6Nluxhg3hMtO4THcmu07DSta67vEtMtoWjZLQZYPoyW401rLCei5QSRa1vZ/K/cDLU1RsuasNkHRMsmYXMsaPr3bESy495o2RJTJ064HU9Gy9aY+zaxyPFCtGwXHRwHo2WHSHT2jJadWkZzfZcY6BwaLbtFB+dPouV4bbIzGC0niCtd78p/ScjiiMbZKBtxNspGnI2yEWejbImpY8TZKFtj7htxNspGnI2yEWejbMTZKBtxNspGnI2yEWejbMT5JeERQ8UQZCSlm9RvigVFgSiCbBHi3nXqN+yM37PzcSdAKV+k8uQakYt4xFTu5YjZPCtSV37OfmrP45hFzetol0udWdwLUCOg6vkgD11Zqm4+V0Xcy1fPjPYBLPCAj3oBNJRyNZ9SiHd51O/1zaKcS12PsrmY1lnq9wZzlJaCqNYQNfKi75Q1PPhYoN7pV78fKH2ZoHzN5o5P/d5aUHnhUWef8lK+1/AjkyeDlOY8dSdXafQRI+N+01vy0JOrIlYYtTKfO3nqrYZO6WcoxgL5xkLlS9PvNRrRNmyXbyogAh71G305KgoB9Tt88ncjQ+pKehxqzocRM+MtHmV7ftSvAhXbWarmWYtjPZJRK1HtDK/ncJ2q+kNsNi9V2vKUhlIVh+Jo5mPjLTNm+O9X9kv/jbwEVW+QZ+ONMtcedBQ2e2PYmBOtU8TVgqj2EF4YGZrXnCWf6iM+7ua18KupN2diiU+9PzP6/lTVY3NUruST88dA2nlepzWPmivE9GgvCkT72xVovJKnF+71/mj/NbzxRe3PUU8Ne/zRiEkbs1TPlVbNUTlranPhp9n/1gg+21uM3EzjKqBskO+/RfX2UIs8Do5aUBDjQWZ03IWUl37VlydzJ1P0UznuT50spf9GZZXRNoQUEsXByHwlqWqMt7Q8VWnPo06IviXtz1EeFKKhlLsyg9nKFzlyWmptup+tfrs4qPpvk77blc1Gry1Vva1IWRhS46pIzQNGa4/yQY5Jv+pRAfUOI0KzVNum6F1P/CYzIxptgzFPjPGcpWJydozOj/5W7uwfeK9xLetm0ouKVQyzmvt8lnpeqHpsaUw/L1Se5kd7uqHLr45y5J7rt3xuzBD9aNVf9c48/PI3j9nzrco/T/PFx+is9qZZ2hOdZ43ek9livjvf97P9taVdo2IiID0xfDFm/aZeH2xeQbLUHJqv5lLfD3pqxNnXIqb+aO8/dwzIqMqeV6xaZqn5SHrjb9Yja+aqOe2fZej/1rg4OyYGK2vkGDBWolSVq0JR8pJn6JAhIz03BTKDBUUF2SHPdQXBwoKgLxQoyE/1XJOb65kayJkdKvJM9Rf5g/P8WanX+XIDs4IBT6DI4/PkFWT5g/meIl9+kYfngWxPti8vkFvqmR8IzfYUFc8K5fo9wYLi/KxAfk6Rp4CqIX8eLfOzPJkFwXx/sCjVMyHkyfb7QsVBf5En6PflegIh3pFZNMhTlOfDgkxfIWXZJK84NxQoRGV+cZ4/SM0if0gpKPIUBguwW5qN9tzcgvme2RjuCeQV+jJDnkC+JyT9wDKaeHID+byrINszK5CjFBsvCvlLQjQOzPGneqJuXlrkyfPll3oyi3HesDs0m/f753uCPnwJBnCbhr48T3GhfA0ac7hTFFhA9VABDs2TLvk8833BPONdMsyZs31BDPMHU6f6c4pzfcHmDKQ1vTpNpuaK6YQIpzxXpF45NCb0fuLLa3zozwlIO/wYFvRl+fN8wTmeAvkk5jL7wglWYcGbafmBEO1vCflCho+DUVCgXpBJ7kLBgL8odXJxZj9fUX9Plt9zY7CAp6FQYdrgwfPnz0/Na1KemlmQNzhUWliQE/QVzi4dnBnKLsgPFUWrynK2DwfmyHq3FxQT2lJPcZEfI3BJPvb4yKQ/mBcISYNmlSrzrp82+RqeBtUFec4qNjI6f3Ygc3ZMW86B/Mzc4iwZiwJPVqCoMJcXyJgXBgNUyKSWPz+U6ml6d0E+HaJfoL/HnzdLNjqrKr+p8gUtUtVllyb8RYQn0+h3zW9XcY3qGqUM6BfgLXR9GfqgHCBZBfPzcwt8sS/FZp9hKYFvzkBBcaiwOETY5wUy/bLObH9u4TkOXUwuVCYGZ/mzfQyiVF9RYUnz90GhJ4vl5/9dIeq7lpnvFk7RTth0XbSJ/suiVh704/xjIZq/n134YzE/4XZr1NGWXWz9+HhV/+DF1m/TRtY3jb7Y+omJqv6ai63ftq2qf+Ji67drR32L+pdV7Xynk/Xlt+q26pgs4kVf0UWMY798mxiuJYprtC5istZd3K7+pqV5okBbJBZoK8V92lqxSvuNeNo8UbzId/k30Pg2Gt4/R/e2H9A9Gt0T0H0rumehOw/dJeguQ/dD6H4S3RvQ/Wt0/xGNf0LD7pa6tUdjdHdCdx90D0P3RHTPQHcWuovQvQTdj6D7GXS/jO430b0V3XvQ/QUaj6DhWEvdpqUxujujux+6R6A7A913oXsOuhei+350r0X3BnRvRve76N6F7mp0f43GY2hobKnbvCBGd1d0D0T3KHRPR3c2uovQvQzdD6N7A7rL0V2B7t3oPoDub9B9yvyE6ofOlroty2J0X4LuNHRPQvdsdJei+350P4nuF9H9Lrp3oXs/ur9Gd6N5omY1z9CS0d0D3f3leLLb+C8xsV+/cfcsXWq3anb78RXL+Kw4brdoduvxcJj/wmG7XbM7t2x5gc+TT9rj5JMVK1bIR1aLZo0rlHUK5X2b3V7CkxUl1jjNaitc0RgOl1jtmtX55o4H+Ki7r2+XNaIV+BRazZrVclDqCNsswmYZe3wsnyGqhqywZrZd0+wWVSEswhofc9hs1uxx69atu1gPHJrd9V74vfB65DFkBaIsjvXEanjiiNMceNLkinzgXUWdwn/tigzH6xXqjRZht4w93xeHpjmivsQ645DOOBzC4bCL9kL+ZRo92cgvEbKaw6Y5HI3LlsrPskZlHYENN6pnTs3hruDz3Njnxj6iZCXisGoOeyNxUJVscZrNWriC0opCp1Vz2i0WS2glT1eGbFbNZi9Ztux0OHyPzaHZ3OVilwqOIerx77bKiC5rqsqnxGbRbFFHww6LcMRFPR07RNVSlVaGnJrJGdfsa9ikaSZct1g0p3UVHyezO+6edXgJLsu6TrvmdJ5eeq/6LD3tjNOcZz0OO12aM77CW+ElYuse9jzseRBZhijXpNNnvbZFvXZZNfnrUv8zbrs0k6vJ7ZZ+u5TfLqdwOd0iSUkKMja8JDw2zH9jXXbN5Wxcbri+dHmjsvu01KMOYVe85mpTkVyRvK7fun6rxq8aLzvVffb77EvtLpvmMnqJ4b4cDLaR42Rx3Ei3TXM7THzSbpC96IY0NVRGjpMBGDfS7tLsCW9VbFNRbBK7TbM7frdV9bql6mLkOFmkuhxZ0SiEZXKsY8c2qjCMHakqGm1uSHNrJrc1fMFIuG0yEm6XcLsSRAIzpZTLw5eHvRVLyK1Mr9upud1nxBZGbUXM573wlvAZoRw6I6/PGLfdCZo78WC3g92Oj94zqDq3Onf75F27tq78YOUW9xa32665nae3bdmyZdtpVVsOKfvobFXOHh1v1+KdZj6jcrbIT84oh50hNzp72za0zxrtcGuONgcOfjVkWwuRlZwHjmwxPupqdLYqZ49Wo7T6YNRmVxyp93obvcZnpKobbZczKt5kireedVBUVMhMxVVUxFm1ePsu+RHR1d8p1ptmCHNmaTBXtM8J+ueItFxfKJ9v/U6h3TL1Wo/8V7PZLck1wsqa3D56pQkbUe5g/Kvp6o6JcddGdETMEzIyxoveU6fc5BFDbp06ySPGROvI/Vciq6+8MvOGts3aLcJF3+0cvYoTbnZpXUTXzMKiQvG8Or6sjq+r45vq+I46vj+HL21iuzp+pI6V6rhfHQ+q4xF1rJffH8T38qhZ1bGLOqaq47XqOF0d786bkzdHW6yOy9XxIXVcrY7PqOMGddzUvIv6V0ftIo92ImkmBlYibBfyp97/e/dM5CH+3z4niO7q54/yJ1RLxSNivdjMTm+vqBXfaybhUJ7ao97WC/mzfzPt2otu3GEPoaUZ5xXLjfMvGmPa0N++W9/iWnOfbnmd0Lflddukltft1ra87nOm5XW/c54P6NLyevgQ4TDFXp+IeW4V2o2jW15PfpCzkz7dT2TI/19CG/aLpiGmDLHE9LzpM7HO/AvzL0SlJWR5TuyL+9S6QjM7b3H6tLec97s0bbs70X296Tr3He5nTKXxWfF3m/4QvyR+pWlrginBbtqbcDLhpOnPQgs3yNhYq+LfvKDsQfbHH46Ro1HZcwE5kdCzWfohacg45G4la86V+D0J6xPeSFwdlXUx8rKUtuKC4myb0SwPtn2sWRoMSep2AUlFhrdfGyPPG6KenCPtN7ff3iwfdTiIHJHS0XIhSUrtmNSxX6cHY+QxJe9fUPZ0OtUkye2TuzTLuKhMvKBkKJkePbeUcPQo621TUtksRuvPk493HtA5q/MznTdKOVd7500XEkN75991ro3KibMi39L5lHpXWHLJ5F5pzTK519RmyYrK3Ui41929hyJj+6T2Gdfrbo6pfd7vu/3SKiUn+s1ECvv3RQb1r+3fCLX9zwzYPvAZKf1rB74z8OjAo4MsgxIGtR/0NlKZOgbJSJ05+OmovHt5eFjfYV8Pf+TK4ciYEckjZo4oGbk5Ku+M3DayMm0AMjJt+agDV1mVrLrqfSWnx1w55tWovHnVaa5fHXNcXR2/2nS1acyrVw8a+9DYd65JvX4G8vmNs69aZdTmfNyoNWGMrDdh8sSeE4dMHDNx46S+SjIm3a2kZNLySU9zLJn0IXJw8oLJ4cmf31SIrE73Uisj/aP0jyZ9yPGALCG16fXpp6aElWyYskvJ51Pq4fMpDRmWKQ08r8+YmXEgo/bmEPLIVA/1NkxpMJ5MXTClYerhqd9Ny5i+bcaMnyT9pNtP+uZYcmbmVOecajrPHoRszk/M71lYUri0sKKwtrC+sGGuZe7QuePmZs8tnLtg7oq5q+e+OvfNuVvn7g0WBh8Jbgx+XySKkorGF80qeqeoKjQ8NCv0dPH04hXF7xafmGedN2jeDfNenXdk/rj5p0q6ldxQ4i0JljxdsqmkurRn6Y9L3yytLj21wL2g44KRC65dkLVgw4LqhQMWjlt458I1C19eeGBhwz1j71lwzzuLrIvGLgouen3RtkWnF3dZPHvxhsX1S9KWlCzZFM74gbnqzXPno5azTXjeWZHzSHjdWTFmkB8YexPPHXEtx4nR0y846zTNPDHScu4IbzsrcnYIV54VY16Qc2jiy8nbOj3GPLx/zHFmTTUHqzPzbdsM5tc1CesTV8fvaZ4zqdu2oVeWbBv/ZsKas3OnESVm53Fq/jVq9UxY3xQ9eVfOxarufvlc1Y9GEL1vxh9mJl9Pi/1K2x6sW815v5Kzq8PRc1aFcTHrwNmVYL20+7zZ/+XzZn9ndM5/UM33apZXemidMI7ymqaZkHxsjOaLucmYf4z5LZpH5kRmQJm1rObZsSmjzHHJE8O1ssXZHPeaGq4N16JN1jrBs4zOtb2mnt8nmAcrY2bUC8yzsfPq+XNqdObepnqTMYtObpo/5bzOHd4aru+8kTtTkzOuHJ7+UUeLsY6pM2tWp1MdDtKrkppWn6ZVJalbR8vZFcjolXJtU7UtsgZt3++YJJ/IO7KWvJ/ULX5PU09N7pLUjRUwSbaXZePu2XU0diWVtqhVM7puxqycSWg4d518rMXquCe6MrZvsp7np4y3y/dPyuhwMHkc9rSIvoyajDGZihmxTTE2RqKMptFTemUR74kymzISyRnt16p8b5S5iRnVaZ034WvTCltpaA3XJ4fD9YbIN8hzr6kyK7Jk9DR5Dtf3Se091MBY4XoPVatSjMgVzljd1Pr43xS1psbI+TXUShsj0RW3Wc5vIVfaf0/UWnzR0rxi/4CcGykpzev4D4ha2S9a1G7jIuXc6Kg9SoycHz+1d4kR2e+NTP97cr7mf23dxYkRZ7l3SVh/lXViz6tOx++Xux4lq9Qdq9zpqKtVE3vKPVD0GcIOaqTcNRl35dwvS1LU7miG2lnJPdTxMcfV/ojdEaX3r1qldifh5l2MlA1TwukHpoTlDkZdbYjuc4zyBnZBtfKO3NHIdulRUTuekNobUVc93SCPnTdRe4PcTTFb9E0/oPZdJVHJUHf6yl2XuspIPyDnpegzhJ3bEPZqcocm2y1XJUTt0wrVfo66aqfWvF+blHG1SUXktIzFzSEjEldZlT9YbFg66UOlW75pudKl9LYciednNLYfXFplXAmrVqHvN9+kv2OeJtrIP5VpDup/M78rRggTT/ZwVadK9eZp+mGhcTwpTBx3qD+16RKv6KfFVv205hXtNJ+Yqs0SnbVMkaJlibbaHNGWmsPln9005+p/FBp6vhQW6rqp25a6buo6lb46an0nHNqdohvPe/F8Gs8v4XkvdPVBVwqtn8Kez4WL0mbsbWu+BzsW6b/F3jTzl/oT5sNiiLlODDV/JQaav9E/MR/l267UvgfttcJCyST/fCjWPIamLaJEtBETRSKkif5iFGTpnwg/ZEOR/pUI6SdEMcyD+VACpcItFuh7xUK4BxbBYiij/TK4D5bD/bACHoAH4aewEt4S14q3oZHyGdBFf02ABhlilHYzTIVb4FYIiCnaNtEDjwPm6WK0+Q5hN98FuWKFeYnobr5XeMxlorvlWX2vZR08B3tFf8unUAn7oAo+g2r4M+yHGjgAfxH94xL1T+IO6nvj/irccfWUv4Xj+l5rnJho7c95mOhvvZJzrv6JNQ/yoQCK9a+s84DYWImNldhYFwCxsb4mRllfh9/CSTHKNkD0sA2Eu0R/mxdmwVwIQimE4V4gRrZV8DA8C8+Ja22vcP4WvoPj8Df4Hk4CMbRnQhb4oVj0cAgxytFe9FB99wj92qlK35D1k6IDvbacXltOb+tLb7uG3raU3nYLvW0WvW0CvW0stZ+nv6Sap+sPmW/TF9CDrqDfPI4Gr/ldfYP5S/pZnTCbj9AHvxF3qH52mFoH2GY2jYo7xeAY/ePRPw/916N/BLVnovsxdP+WVsPQvRrdT6HvHfRNFwloOYaWY2hJRMulaMlHy2C0DEbLQLRcipWfo6kfmrLkn2FGw0bl6Q5Kr4lkdPwRHX9ERz/tLv1t9AxGz13oGY6eW9BztRbQP0bXYG2N/jta/h59FvTNw7JsdLbDsjK0/dRcq5/Aug/NXzNavxGXmY9GR2xbtA5AawCtI9B6PVp7o7Ef2j6l5aeMvJvwcppwRWeY/2QmkTPLk6JMrxfL4D5YDvfDCngAHoSfwkr4UG8UO2EX7IaP4GPYA5/AXvgUKmEfVMNfdF18Dl/AQTgEtfClvlMchjr4Xq8R/8E4PwERaICT0Mjs9neen4J/wGn4TziDLbperwnQ1Kz4pXkmPezH+jHznZy9+jHLXr3e8ilUwj6ogs+gGv4M+6EGDsBf4Gu90fINHIW/Qj18C9/BMTgOf4Pv4T/gBGCL5Qzo+s64JH2nbazeaLseJsIkSNe/st3KeRrM5PkdcCfcpdfbvDAL5vBsLucghCjPhxIo5foezmHO98JyyvcDebD9nPMqzg/Do5Qfg8dhNTyB/me5v57y85Rfofwa5d8DObKRIxs5spEjW42u2w4AObKRIxs5sh2kzSGoBXJk+0avsR2Fv+JLPXyr77F9B8d4dhzdf4Pv4QTX5M7WwPkk1+TInglZ4CdfJvGQaK9WLrN4iL47jT4sV684rn7F1USuJtDLt5o/FgOFxt0GMY6eWUPPrKFn1tAza+iZNfTMGnpmDT2zhp5ZQ8+sofZX9LRGelojPa2RntZIT2ukpzXSi+rpMQ30mAZ6TAM9poH3VfC+GvNPRJzZB7PoQZn6l/SaGnpNDb2mhl5TQ6+podfU0Gtq6DU19Joaek0NvaaGXlNDJhvIZAOZbCCLNWSxhsw1kLUaslZDthrIVAOZqiErNWSjhqg3EvVGot5I1BuJeiNRrSeq9US0gYg2ENEGolhDFBuIYg1RrCGKNWrE7hc2YnkNI9nO2vsH1t7fmPew1n7CKsRqo+J7FA8/wcNDKr73cCV/w6Mb8V2Khs/EDNbJFNbJFNbJFNbJFNbJFNbJFNbJFNbJFNbJFNbJFN50JWtlb9bK3ozZSsZsJWO2kjF7iDEbYcxGGLMRxmyEMRthPU1izNYxZusYs3WM2TrGLPkWk1g3hzNODzFOv2CcHmKcfmGeJfqaMyFXLGMd7cE62oN1tCtrZwprZwprZwprZwprZwprZwprZwprZwprZwprZwprZwprZwpjsY6xWMdYrGMsVjL2Ioy5SsZcJWOujjUuhTUuhfUthfUthXUthbFSx9qWwtrWm7FSx/qWQv+vpP9X0v8r6f+V9P9D9P9D9P8I/T/C+pfE+pdE/6+jz1fS5yP0+TrWwBTWvxTWvxTWvxTZ3/XvifX37M8e0u8jA+OZzw8xnxeTifFk4gWerqS3X2/ey06qUj9j3idmqezVUHs/tapZMR/SF3M1i7Z7afspd8fS9iHafkDbibStpN3twhodR7dRcx81K6k5Ue2vZJ95UWny8/xqnn/E8yqej0LTAzx9HU3XoulDNA1R9f+s9omfq2ODcGptRA9tJuRCHhRAIcyFIITgQVb6tlqFiOctS9Fegp4dam+0TnQy/15cYX6P/NeKXqzat7BLTGLl7sIusZf5a2aGb7DgKPf+Kq5gPQ/q79GiI3vKnnJNp32umMAKNpM+f4eYYL5T7b4miAQs64plXbGsK5Z1xbKuWNYVy7piWVcs64plXWnZnpb5tGxPy3zVMp6W8bSMp2U8LeNpGU/LeFrG0zKelvG07EvLy2nZl5aXq5ZuWrpp6aalm5ZuWrpp6aalm5ZuWrqjLYdHWw7HkzvEAEoDVIzL1R7hJNGqkb+TAzfDVLgFbhVO9m5O9m5O9m5O9m5Oh/z/tBYi3I42GdGdxlaVo0OiUuun12r9YQAMhEFwGaTCYBgCl8NQGAbD4Qq4EkbASPgRpMEoGA1XwRi4GsbCNXAtXAfj4Hq4AW6E8TABJsIkmAw3QTpMgbXwFDwNz8CzsA6eg/XwS3geXoAN8CJshJfgZXgFXoVfwSZ4DV6HX8NmKIc34Dfs1io4v6fv196HLbAV/gTbuP+Bvk/bDjvgQ9gJu/Qj2m74CD5mBzGTbyt36nssf2InsQ0+gO2wAz6EnbALduv7LB/Bx/q+uLZ6bVx76AAdoRMkQ2e91vpzeBKIgfUZ/Yh1g37M+iJshJfgZXiD+1s4s9u0/onyHn2f9VPqV1Nu0Gttl0B36AEeSNGP2XpCL+gNfaCvvs92KfTT99v6A33BRl+wkXfbUK6H8WyUfsQ2mvNU/ZjdpNfazWCBOLCCDezgACe4wA3xkABtIBHw154E7QC/7fhtx287ftvx247f9i7QFboB9tux3479duy3p0BP6AW9oQ/0xaah+hH7MPiRvs+eBqO4NxZugBvhLurN4pzNsxzqzYYA3A3FPFsEi2EJhOHn3P8l9V+k/kZ9v/0lrl+G77kX0WsdGuCro52+z4Efjg76EYeHPrRQIzoa0dGIjkZ0NKKjER2N6Gi00IiORnQ0IqN+a7EtJEE7aA8doCN0gmToDF3Ys3aHHuCBFOgJvaA39IG+cCn041t2fxgAA2EQXAapMBiGwOUwFIbBcLgCroQRMBJ+BGkwCkbDVTAGroaxcA1cC9fBOLgeboAbYTxMgIkwCSYL+a+LuLR0mAIZ+mHtZpgKt8CtMA27p8NtMANuh0X6t9piWAJhuBeWQhksg/tgOdwPK4DvG9oq/aT2MDwCj8Jj8DisBvk3Pa9ljnwKnoZn4FlYB8/BevglPA8vwAZgBdQ2wkvwMrwCr8KvYBMw12rMtdqvYTOUwxtQwVz+HrwPW2Ar/Ak+gO2wAz6EnXDuLDJN9zFLz2AdaMPMP5p1oA2z/2hm7U8szHgWZjwLM56FGc/CjGdhxrMw41mY8SzMeBZmPAsznoUZz7KJ7yivwevwa9gM5fAG/AZ+p39reQveht/DO/AHeBf+CBXwHrwPW2Ar7BZuy0fwsXDHtRXOuPbCFdcBOkInSIbOwmVdqX9r/Zleb/055dWU1+hfWZ9kTSIHajZbxzN8sb7AM2y2YrMVm63M0tbX9MPW12Ezz8pBznJvUv+33HuL52/D77l+B7DTip1q9vuA6w95tpPzLu7tho/gY9gj3NZPeTff7ax8t7NWce8z/aSaKfdjG9/nrF/Rlu8s1nrK7K6t7K6tx4DvLFa+s1j5zmL9DzgBEWjAt5P6YVuC/q2tDSRCW0jWT9o6QxfoCt3gEuG0dYce4IG+wm27FPpBf7ice0M5DwNWWRurqzHrCrfdJFx2M1ggDqxgAzs4wAkucEM8JEAbSIS2kATtoL1w2jtAR+gEydAZukBX6AbYacdOO3basdOeAj2hF/SGPnCp/q19IN/RBsFlkMo1OwX75ZSbZuLhlK+EETASfoQfaTCZ8k3A91z7FNpl6FvtN8NUuF0/ab8LO7Opd+4szfddO9937fNhETYshiUQpv4DvJvxr2bt1ZzXoPdJWAtPwYvo2whNs/gr3COH9ght/6GfdAj9sEOTf/5Tr3cQT4eTc1vutxNuNbOzQjk6cS8ZOgPzsaOb/LmkHOnRfdUiRug+tUd7v/l+PvdL1c9R5H7rOxFnGq//2HyTvoXdqVP+bItn34pBpiH6UdNwGAFXw3j9E9MEfadpEtzErnya/jm7iwPsLg44Z+g7nTPhfv2ocwU8AA/CT2El/Az4Luf8OayCh+EReBQeg8dhNTwBa+BJWAtPwdPwC3gGnoV18Bysh1/C8/pR90D9qDBjaYNpBt+Jg3yHHoX9EeyPmNL0OuyPmK7j/IB+yPQg313uEJcxf11GzZ3OW/Q6560wHX4Mmfoh592QC/lQCCG4X4/gWwTfIvgWwbcIvkXwLYJvEXyL4FsE3yL4FsG3CL5F8C2CbxF8i+BbBN8i+BbBtwi+RfAtgm8RfIvgWwTfIvgWwbcIvkVcE/VDrkkwGW6CdJgCGXCzfgjfI+RwhP4ZGdplUnnUt6ufHPbA9434vdF0h77JlAV58IBeQQwq5PdvfN+I7xvxfSO+b8T3CnyvwPcKfK/A9wp8r3CW6JucpbAQ7oX79E3YVYFdFdhVgV0V2FWBXRXYVYFdFeIaMhAgAwFs+5IMBLDvJD3oBD3oBHZ+gSXVWFJtnnbmhHnGmQirSzyZGczqEk92Bke/42+ld52gd53Aumqsq8a6aqyrxrpqrKsmMwEyEyAzATITIDMBMhMgMwEyEyAzATITIDMBMhMgMwEyEyAzATITIDMBMhMgMwEyEyAzATITIDMBMhMgMwEyEyAzATITIDMBMhMgAtVEoJoIVBOBaiJQTQSqiUA1EagmMwFxHVHwEgUvudhBFLzkY4dpvLgE79PxPj3689afRr9PDyAKHYnCMKLQkSgMi/6U+HZytYNc7SBXO8jVDqKRTjTSiUY60UgnGulEI51oeImGl2h4iYaXaHiJhpdoeImGl2h4iYaXaHiJhpdoeImGl2h4iYaXaHiJhpdoeImGl2h4iYaXaHiJhpdoeImGl2h4iYaXaHiJhpdopBONdKKRTjTSiUY60UgnGulEI51oeIWNvnACj914/DAez8PjJDxcjIfzRWditJX4bCU2VcSmijgkEYMknj6K/1vxfyv+b8X/rfhfhf9V+F+F/1X4X4X/VdhRhR1V2FGFHVXYUYUdVdhRhR1VjJWA/uI5890JcZnpZua4GRBgnrubOW4O5AK6sfhg81y3iDljib7TtVA/6roHFsFiWAJhuBeWQhksg/tgOTA3upgbXcyNLuZGF3Oji7nRxdzoYm50MTe6mBtdzIsu5kUX86KLedHFvOhiXnQxL7qYFxMc4AQXc56c2Y8q2yOM8TrGeB1jvI64ye/pfXm6l7Fbx9itY+zWMXbrGLt12B7B9gi2R7A9gu0RbI9gewTbI9gewfYItkewPYLtEWyPYHsE2yPYHsH2CLZHsD2C7RFsj2B7BNsj2B7B9gi2R7A9gu0RbI9gewTbI9gu56wZ+p+J9i4i/F7znCU9+kIMxaNyntfy/CTZOE02TpON09T9grp26roYKU48TWWkOPE2NfozoG1k6DQZOo2X5XhZjpfleFmOl+V4WY6X5XhZjpfleFmOl+V4WY6X5XhZjpfleFmOl+V4WY6X5XhZjpfleFmOl+V4WY6X5XhZjpfleFmOl+V4WY6X5XhZjpfl4go8KSM328nNdlNAdCM/2/EgkxHwd0ZAA54sw5NO0Z/MdJI/mcGTJ+RPs8jddnK3ndxtJ3fbyd12vCrDqzK8KsOrMrwqw6syvCrDqzK8KsOrMrwqw6syvCrDqzK8KsOrMrwqw6syvCrDqzK8KsOrMrwqw6syvCrDqzK8KsOrMrwqw6syvCrDqzK8KmMcz1DjeCRefBz9f043YPWjWL1ZuPB3N/7uxtfd+NUBnzrw5HH82Y0/u/FnN/7sxp/dwmoqJq/z9L+b5utHTMvoFz/TvzM9Ln/Szt1TpmV6g9A4/l30p0aDqYQeUQrL9H2m5cJuup/WK/WvTavl35ui/8P0pP4PF/tbF/tb1yXQHXqAB1KgJ2RRxw/ZkAOzIfBfxN17fNx1ne/xX2ZyaScTyqUUEBWRi7dVxOsK3tDK4rriXVFX3F1BbKXSAgXaWmgVQUUoIJeiFHCptaBtkVi00AaBYkswJWknzXQSmtA0JJn+Mk3SZDJNod/znGz1oOecxzn/nHP+eD0mM5n5/b7f9/tz+4Y0YCa+jYsxC9/BJZiNObgUl+FyzMUVuBJXYR7mhwMT+xm30u7EwtBrL7sTt4W9CSe96CuJS0X7ZZjr1avsch6uCc2JRViM7+Ha6OjEdWFNYon33Ry6ErfgVvwUS8M6+1tXmwh/rk2iElWoRg0mYTJSqEUadTgMU3A4jsCROApTcTSm4Rgci+PwKhwfCjQs0LBAwwINCzQs0LBAw0LtGaG59ky8Hx/AB/EhfBhn4SP4KKbjYzgb/4Rz8HFcYB8X4pu4CN/CDMzEt3ExZuE7uASzMQeX4jJcjrm4AlfiKszD/LAuqhQ5O6m4jYovJO4IQ2Lp2jAsTsaiT3OhxIUSB8Y5UI6wF3Scoo5T9I4ilUtULukwRR2mqMMUdZiiDlPUYYrUL1G/RP0S9UvUL1G/RP0S9UvUL1G/RP0S9UvUL1G/RP0S9UvUL1G/RP0S9UvUL1G/RP0S9UvUL1F/nPrj1B+n/jj1x6k/Tv1x6o/rckVdrqjLFXW5oi5X1OWKulxRlytSt0TdEnVL1C1Rt0TdEnVL1C1Rt0TdEnVL1C1Rt0TdEnVL1C1Rt0TdEnVL1C1Rt0TdEnVLcu4K0V3OxYU0vVp0XxsdRu1uau+i9t5oNo0baNwg0vu8czOtu2ndnZjv+cLQ71PDIj8W+bHIj0V+zIeX+dDAhwY+DCVuCptkQJsMaJMBbTKgTS79WW34E49aedTKowYeNfCogUcNPGrgUQOPGnjUwKMGHjXwqIFHDTxq4FEDjxp41MCjBh418KiBRw08auBRA48aeNTAowYeNfCogUcNPGrgUQOPGnjUzaNuHnXzqJtH3Tzq5lE3j7plSCxDYhkSy5BYhsQyJJYhsQyJZUgsQ2IZEsuQWIbEMiSWIbEMiXncwOMGHjfwuIHHDTxu4HEDjxt43MrjVh638riVx608buVxK49bedzK41Yet/K4lcetPG7lcSuPW3ncyuNWHrfyuJXHrTxu5XFrNIODPRzs4eA+fj/Jxb2cy3FuD+cKnCtwrsC5Av/T/H+YezH34sQNXruR00vCKg72cbCPg30c7OPgAAeHxMkGLnZysZOLMRdjLsZcjLkYczHmYg8Xe7jYw8UeLvZwsYeLPVzs4WIPF3u42MPFHi72cLGHiz1c7OFiDxd7uNjDxR4u9nCxh4s9XOzhYg+XClwqcKnApQKXClwqcKnApQKXClwqcKnApQKXClwqcKnApQKXYi7FXIq5FHMp5lLMpZhLMZc6udTJpU4udXKpk0udXOrkUieXOrnUyaVOLnVyqZNLnVzq5FInlzq51MmlTi51cqmTS51c6ozezqUil4oT2fhfLoxwYYgLQxwocqB8bhqi7hB1h6g7RN0h6g5Rt0jdInWL1C1St0jdInWL1C1St0jdInWL1C1St0jdInWL1C1St0jdInWL1C1St0jdInWL1C1St0idIeoMUWeIOkPUGaLOEHWGqDMUvVlleElleEn2x/p5KnGDXfzELiZW7+s7sFS/v0vfPt5U92q8Bq/FCXgdTsTrcYH3XIhv4iJ8CyZIWo/ReozWY7Qeo/UYrcdoPUbrMVqP0XqM1mO0HqP1GK3HaD1G6zFaj0XfonUfrfusOLbiWBbkZUFeFuRlQX5C/79kAN3/h8g3wSfKP9n4X0d7Hz/6+NHHjz5+9PGjjx99/OjjRx8/+vjRx48+fvTxo48fffzo40cfP/r40cePPn708aOPH3386ONHHwVjCsYUjCkYUzCmYEzBmIKxbMjLhrxsyMuGvGzIy4a8bMjLhrxsyMuGvGzIy4a8bMjLhrxsyMuG/P9BNuQ5lOdQnkN5DuU5lOdQnkN5DuU5lOdQnkN5DuU5lOdQnkN5DuU5lOdQnkN5DuU5lOdQfqLHD078V8j38CrmVazaxKpND+1j2pc1jmkc0zimcUzjmMYxjWMaxzSOaRzTOKZxTOOYxjGNYxrHNI5pHNM4pnFM45jGMY1jGsc0Lu8xtsfYHmN7jO0xtsfYHmN7jO0xtsfYHmN7jO0xtsfYHmN7jGvLsTAXV+BKiDd7jO0xjg5Xi0f/NmdE2g0TmV5UU4v/uxwxu19hRnUylW1p2VYt216QaUfLtFR07l8rylzdeCGudi6/1r1+FAZF9qB3l+TmoO484lNvo3CRwiOvmJoGRfeg6B4U3YOie1B0D/4/qjaDom9Q9A2KvkHRNyj6BkXfoOgb/L86FZVPKyVKbfrruWUkSh56rcSlA9EXaNtI20b+DfBvgLblk02OE1X07aVv70T9W+L5bc4It5uUlnrtrtBL11669tK1l669dO2lay9dG+naSNdGujbStZGujXRtpGsjXRvp2kjXRro20rWRro10baRrI10b6dpI10a6NtK1ka6NdG2kayNdG8XUgJgaEFMDYmpATA2IqQExNSCmBujeS/deuvfSvZfuvXTvpXsv3Xvp3kv3Xrr30r2X7r1076V7L9176d5L916699K9l+69dO+ley/de2vL+5yLK3AlrsI8zA+9ExrvP5QJpeioxNpoWuIJE+eT4vKpsCixKaxM7DNnjIYlif2hOalyJt/q9HpaWJN8V+j5628rfzE6PPml8t9knfidwr50e9jCseWuuxpPyoCnQiaxUaQ/jU3uudnjs6E9scVJN+NurR63oy+anOiXqaNm3KJJaAzjYSgZha5kDSbhOKf/00J38vSwL/kOvBPvDsXkmWFX+t9CnL4wNKW/DTUifYnH2aE9PQdqQnqBx4Uer4YZOv196JjpGyEr00t8/6deU/vSd3q+FHe7xvKwP/2A66/BQ2Ff+rd42Gv1nq/zaE/pZq+1YCvaPM+i3dcd6PK+gdCV3oex0FU3NRTqjsY0OB3WOR3Wnez1maGpzkxfZ11114eRuhvDvrrbcRfuD4Xonw+pmuNTiaptVB2g6gBVX6LqbqpmqdpG1X1UbaNqGzWL1Bym5jAlhyk5TMlhKu6n4igVR6k4SsEBCuYo2EbBNgrmKNhGwSwFsxTMUTD7dwrmKDhAwQEKDlAwS8EcBXMUHKDgAAXbqDdAvQHqjVJvlHIDFBul2CjFRik1SqlRSg1QaphSw5QaptQwpYYpNUypYUoNU2qYUm2HlMpRaoBSo5QapdQopYaj1yceDAsSa8NDlGoQgwcotIIqexI7w0XibG6iP9wrur+YGDFp7w8fFGd/SibDxmR1uCmZDt8R7a3JqeHE5AnRN5OnhMtF/uuTbwsfodr9ov9sMffz5AfD1cmzwlcP/XZWZ/JL4b7keWFmckbYUP79Jbt6VE16Qpd4CpvC8+74Ij92umOPO/S76qAr7nLFvXLpTLn0ASfCBzn2RGjxqXK+/HkiR/qi1/r0Vp98xid3W1uPtdW6QmYiH94VMj75RHjGp170qUd84iifeMH9Oify16l6IodPkKdv9fy0sNOnuqxyY/QakbVv4pMbRdbT2CxinvXpLaIqY4ps9bg97BYdu0XHbpGxW2S8IDJeEBUviIp9omKfqNgnIkoioiQiSiLiBZFQEgklkbCbc7s5t49r5crfFx1mPdVWvtz9HnTfP9jrOmwO43TtoGdP+qpQdP1h1x92/eH0XZ7fE4quMxxV+tSIlV/qE7vKcW8SflAtWWsvT4Vmr7YnWtSRsoY7Q55uLa7b5rpt0XnuusS7F8mp7olo+UNY6O4LfXKIEuOUGHeFbkoESowcyqsRSowksmG1K9aLpOZELHpSmBouTE7jxjE4FieFy5In45SwJ/lGPr8Jb+Ue3ZMf8v2zJn53+XSrOV3udVN3hLojcq+bwiMUDhQOcq+bCgspHSixhBJLKLFE/nVTe5za49Qep3aQf93yr5vq41Qfp9ZCyo9QbGF6lUq0Go+Fy9IbPf4ZTdiCHcjhed/r9PiCa+wKl9VF4U91VWF1XTVqcKLnp2KmCrU4LJGD3dwcr7sj7Kq7E0vxMywLq6NaETksGndx+p2qz8uqz8uqz8tcf69Mf1mmvyzTX5bVL0ev5kfZyyLtB2k/6FPVatSQGjWkRg3Z+4i9j9j7iH0P2vegfQ/a66C9DqovQ+rLkNoypLYMqS1D4ntIbRmy1hHrHFQrhtSKIbViqCLljotFwB3c/yP3b+X+rYkNHG3AE2FTYqOu+DQ2hftFwYHEVq9nxFY2zE3sCOsTObSjA89jZ7g+0elxF7pdc7fHHvSiL1osWuoTeV/vQSzyBjwWsDdclhjEkK+HsS/MUJuaVe6syp2VwV9Uo7YkDvjeS3g5bEgc9Bh04QokUK5flaKtytfV6lQqLErW+jodZk3UsykeD8cROBJTw5mi9RzReo5oPUdvvS75qnBl8njfezVOiL6cPNHj63GSmncyTgn/mjzV8zfgjZ6/CW/29T/greGjauS/qyyruLaYa4u5tli0f1K9vDH5Hu95L/4xfC/5Po9n4MxwTfL9Hj+AD4avyYpzkh/29VnhUpnxxUO/MbtKhlyZ/Ep0bPJ8zAjPqa+/Sc8IzemZmB0OyJIDMuRWGXJAlCwWJYtFyeL0Yt//Hn6IH+HH+Ek0LX0jbsIS77/da3fgTs+X4i7X+bnn93i8N8xK/wL3Y3m4Lv3LcKVudk36Qc9/jd9gVThbVp2tw10jAheLwMXmg+t0uWvSvwvfS6/FI963zmuPed96X29Ag9c3er7J65tdt9Frz+LPXmvCFjS7Vgu2Ypv3t3lvFjt8LwfVW3QvlrVnp3eG9TL3bF30Gtl7juw9O93tNTGYFoPpFyEO033oD39Mi8O0OEzHEIPpvRjEkAowjKKvS2FDej/Gff0yxFxazKkKi+rEXZ24q0uGDXWVHqvCXFVirioxt26S55NVjxTEYF06/LGuDof5egoO9/oROBJHeX1qyOr0WZ0+W3eM6x3rPcfhVTger8ZrvPcE338dTnT/13tNhVWNFtVdE5pl+OK666Npdbyu43Udr+tuwE9wo+/9NFwp8xerVGerVGerVGerAotVq7Prfu46y6z7Xte83/WXe/5LrMCvwmXRiarEparEbyc685MT/fxplaBXxi+R2V+T2Wtl7RpZ+4yeOypjH5ex3bKyRTY2ysINsnCbrPuYzDpfJq2RMTfKmKdlTK8suV2WbJMFDaL/l6L/U6L/j6K//C8V3iPin4v+Q716wEp+o2NtTazRpdaqCX/w2jo8qc895Xsbw3bVc7vO9Uc1a0DnWqsHDlhtv+61Vvdaq34tt/Kn1al+K9+iFm206qx6s0u92WXlvep1xsr3qtkZNTujnmy0+lVqwSq1YJVVHrDKz5ZnHt1ra/rfVdoLw1odbK0OtlUHWys3B+TmgA62VX4+ID8H5OcD8vMB+fmADrY1fa3P/QA34Cdhu6q+XVXfLjcHdLOtutlWFX67Cr9dbj6gm62Vmw/IpVXifpU4XyWm+/WTjH6SEbf9ekpGrPaL043icrm4XC4ul4vFfrG2S6ztEmu7xFa/2OoXV7vE1S5xtVEvyoipjTrcWjH1gA63VefYLj6Wi49+8bHLBLlBHDTgCRPapvAHSu/WHVrEwkdU8w7VvEM8PEvVLqo2U7VZTPxe5d5J2c0qdQdlN1N2s9jYIzZeVI23qcbbVONtYuQfxMiYKptTZXNiZYc46VFZm1TWJpW1Scy0qqY7VNGsyrlNRWxREVuovpvqu6m9WwVsUQFbVMAWFbBFBWyh7G5Vr0XVa1HpWlS0rCqWU8VyqlhWFWtSxZpUsKwKtkMF26Fa7VCtcqpTTnXKqU451alJdWpSnZpUpx2qUk5Vyh2qSk2qUU41yqpG27izWWXpUFk6uLSZQ5tVl52qy04VZKdq0aFadKgMHSpDh8rQwalmTjVzqllV2KkCdHCqmVPNMr+DU5tlfouMb5HxLTK+Rca3yPgWGd8k25tke06252R7TrY3yfacbO/gYrMs75DlHbK8Q5Z3OBP3mY7Lc/W7wkvRu2VZ+Zz1bRm1VEYtlVFP8nmRrNnP1xV8redrvWzJ87Wbr6t5upqnq2VESRaUeLGIF4tkQIkfi0R8SZQvFeVLRflSXiwS5SVRXhLlS0X5UtG8n16r6bRaNO+n1WpaddOqW1Tvp1e3SN5Pn3r61NOnnj7donm/aN5Po3oa1dNntegtid6lIne/Pdfb41PhRhE7ZgcbPNtn7aPhQbG5M3qVne3zrMfO+u2s384G7apJHcjbWZOdNVndPqtrsromq9tndU1Wtc+K9llRvxX1W1G/1eyzmn1W0281/VbTZBXls2x/dII7jbrTDnfqcaced+qjYfmM2uxuI+7W7G7N7jbqbs3u1uxuo+7WTIthWgy76ygtht151J173LnHnXtoMezuo+4+6u497t7j7s3uXj4f9jgj7FQv94Xn7Po5dx5xxw61bJ2K26bils8Hv5+ouNXeNXLoDJU/9G+YTkueF71jQrku3+nwna6JZ+Wz3YEJHasOfWrYs9j1t7v+kGk4a6aNKTxunylKRKgyk1ajBid6fiqWhUHX2DnhTIt3t+si5TWORKe6xtO+8wf6DbvWo97x4l/O9xP9JlJfajAJqfCoXX3Gbr5Bx2E67qTjTjqWz9c76TdsDY9aw9PW8LQ1PE3Lvz13H49Xv+L8faL3nywXT/W4zPvv9Vr5zF1hz4XoGOsbsqYha9pjTXsO/QRnr9X3W9de69prHXutY6817HXvIfcecu8h993jvnvcd4/77XG/Pe61132G3GNPdLKrP2b3f7Lzza+oshk6r3Kn4kRVTU38psgPDnm5w+5nlH+j5y/Vx443u+tj7vqYuz72P6085UpzoveVq8ypHssVY5n3/n3FmDzRRfeZA/Y7W1fz9Qth9qHf7njOnb888Ruj77Dund75e641ORdst/7HqbTmFRWk3BmylFrG63LffZFay6i1zH4ed9UbXG01F5vMbtspuIyCyzjZRMVlMiIrI7IcbbK/x2VF1h532uNOe9zJ1SYz2HYz2Hbz1va/qxxZLjdxuemvleNE1zg5LLP3x+17J5ebJqrH8VRvp3r7xE8jRlWR/eEpqx6gfLsVD1hx+Wc4A9Rup3a7VQ5Y4QCV26ncTuV2KrdTuZ3K7RRud6cBCrdTt5267dRtp267rBpVdcd1P9EjwkbD41FCFxw3Ke2PkqaRTZ4NedYbnehZwRmmZD4pmE8KOuWYTjmmU44d+hlh3swyaI4v6Xh5nS6v043pdGPm9ZJulzejl8wVBTN5SXcb093GdLcxc3fJ3F3S2cZ0tjFzR0Fny5s9CjrNmE4zpruMRZP18v1WcrfeXdCzy3Pdi+5a4OD9HLx/oqpM1u1HklNVkreG2A76vStOvjuaosI480Snu082qnSd3a5T/plrqbwDO05P/AQhX34/JabKp3eHktfLP5X1Dp/bFR3tWXn3I3Y/YvcjEzv/ilnh/ND6ip2P2PnIxK6bPbZgK9rRAbuzsxE7G7Gzkeh17raFvqP0baNv2ytP5u4du0sPbUfdoccdev56Gn944id+PbQdpW0bbUf/5oTe5nl24qeAEyd12ra5ew9t2155Wo8q7Hw0OjlZ56up4V7TUsG0VDAtFazpEWt6hFqjJqZ+E1P5p2sDdNpjMipw4CUO/JoDv3aOPNI5svzbkeWpp9/U029dj5hu+k03/aabftNNv2mm3zTTbz2PmGT6TTEFa3rERNFvoug3UfSbJvqjGqv5rTvvc8eSO+5zt/3u9qy7PRud5Lsv0K3XGndY4w7vLB76GfZ/d+jdJrszxfVZdFgeemk4TsPxv7r0sNfqPV/n8TGT1iaPr3StzfMs/uLe897T5f27wo6/cXEa1bqo1kW1Lkp1UarLujsP/UyqiyJdFOmiRhc1uqjRRY0uanRRo4sSXZTookIXFbqo0EWFruhV9vm8PT5vj8/b4157zNjjNnvcZo/bTKrlqNtmP9tMlXlTZd5enjdZliNwm71ss5dtJsm8fWyzj2328bw9PG8P2+xhmz1sm/hXlCclvx6dFC2NLgh3RRfim7gs3BfND7dEC/BdLMTV6A5Lo93owbD37A83R+M4gJfwcri54o2hueJNeDPegn/AW/E2nIa343S8A+/Eu/BuvAfvxT/ifTgDZ+L9+AA+iA/hwzgLH8FHMR0fw9n4J5yDj+Of8Qn8Cz6Jc/EpzIiOqfhjeLziifD7iifxFDbiaWwKGyo24xk04tmwofLecEvlffgFmjzfgudgr5UHEcLNVYeHu6qODEurTNlVpuwqU3bVMTgWx6Er3FIVe88ABsMt1W/Ce3BxuKt6Fr6DSzA33Fd9BehevSQ0VzeHDdVOPDWnhg01b8Abw+9r3oR34J2evx9fCUtrvorzw801d2I5ujx/AbvAs5r+cF9NHnt9b8TzYrh5UiI0T0qiElWohklxkklx0mSkUIs06nAYpuBwHIEjcRTeFzZMOgNf9/U3PS7y+CuPK8PvJ42G5smuNfko8/HXoiPDlugoqH7R0ZiGY/AGvBFvwpvxFnwC/4JP4lx8Cp/GZ/BZfA5fxJdxQbhb5N4tcu8WuVdHl4dl0VxcgStxFeaHlaJ5pWheKZpXiuaVlT8OWypvwE9wI27CEtyMW3ArforbcDvuwL0+dx9+EVZy/e6qtrClqgPPoxNdXn/RYy9i3x/AoNdeDluqq1GDyUjhWByHU3Aq6FBNB9GxsvpdHt/j8UyP/4Sv4Xx8Hf+Gi8PdIudukXO3yLlb5Fwtcq6utt9q+xVBKyddUtYmuiU0R7fip7gNt+MOrMCvsBIP4EE04ln8GU3YgufQjBZsxTZk0IosusPDasLDasLDasIz0T6MYBRFjGF/WKNOrFEn1qgTa9SJNZV9obmyH3nsQQynk8oC9mIQQxiGE0vlCMqfO4gQ1si3h2vUghq5XyPXa+R6jTyvOTc8U/N5j1/AV7znqzg/rKn5tueXYy6uxFX4Lq7D9ZBvNTSqoVENjWpoJJ/W1Pynx+Ue13h8DHSooUMNHWroINcelmsPy7WH5drDcu0ZufZMzR7E2OuzI16nh7xbU/G2qDI6IqpCNWowCZNR/uvdtUiX/8QkDsMZ0bToTFwQFojxBWJ8gRifK8ZnivGZYnymGJ8pxmdG81xhfpglzmeJ81nifJY4nxV9P5oSXYsf4Dpcjx/iR/gxbsBPsC56bfQousN8js7n6HyO3sbRlRxdydGVHF3J0ZVR+S9I7w8LubqQqwu5upCrCyt+Florfo67cQ/uxX34Bf4T92M5fokV+BVW4gE8iF/jN1iF1ViDh/BbPIx6/C60Jt4eTUmcHk1LvMvjh3BOWJD4eLgs8Ql8xvMZYXFiZrg48W1cHC42s30i+dVwubntE8mve7w8NCbnhpZkc1SVbImmJreZeludyrdHqWR3WJncbRbpid6YfNFjb/lvA3ncEx1ZeXl0ROVcXIErcRXmYT4W4LtYiKtxDe4Ns9SLWerFrMqt0ZTKbcigFdvRhix2IId2dOB50FO0LxTtC9WaBVVHhFZRP1+NmVW1J0qpLwvUlwXqy6yqA9ER1UmIreojcRROwpvCrOo3ezwd74ymqSmzqt/r64vDAvVjgfqxQP1YoH7MVT/mqh8z1Y+Z1WKpej7EUvVdobX6ZxP/gr615jV4LU7A63A6zg0rZdp8mTZfpi2smRNNqbkUi7AYt+BOr9/r8RfRa2XTwppf+7rL+1/ALog5mXObzLlN5qyUOStrBqLJNQXs9f4R3xd/MmhhzVg0ZdLU0DrpaEzDMTgWx+FVOB6vhrVOstZJ1jrJWiediNfjJJyMU/AN17oAF2Kh51fjmtA6uSK0ps4Ll6W+goXh4tQ1kDcpeZOSNyl5k5I3KXmTuhE3YQluhv2mbsVPcRtuxx24E0txF36Gn+NuLMM9oE/qPvwC/4n7sTyaUrsA38VCXI1rQNta2tZ+D/K7Vn7Xyu9a+V1rnbXWWWudtdZZa5211llrnbXWWWudtdZZa4211lhrjbXWWGuNtdZYa4211ph+SzTlsMlIobb8f3dKPidTulWj8lflvz1yTOLK8v9FeOL/LlCNGkxC+f8mm0It0hN/wT6tmqVNADkTQM4EkDMB5EwAORNAzgSQMwHkTAA5E0DOBJBT+Y5S+Y4yCeRNAnmTQN4kkDcJ5E0CeZNA3iSQNwnkTQJ5k0BelbxIlbxIlbwo+lYoRDMwE9/GxZiF7+ASzMYcXIrLwgwVdbaKOltFna2izlZRZ6um01XT6arpdNV0umo6XTVNqaYp1TSlmqZU05RqmlJNU6ppSjVNqaYpfbdD3+3Qdzv03Q59t0Pf7dB3O6LyzztW4gE8iHXRcSrvcfpvQf8t6L8F/beg/xb034L+W9B/C/pvQf8t6L8F/beg/xZU6zmq9RzVek7U6yzbh37ksQcxBlDAXgxiCMPhTpV9hcq+QmVfobKvUNlXqOrzVPV5qvo8VX2eqj7PTJ8102fN9FkzfdZMnzXTZ830WTN91kyfNdNnzfRZM33WTJ8102fN9FkzfdZMnzXTZ830WTN91kyfNdNnzfRZM33WTJ8102fN9FkzfdZMnzXTZ830WTN91kyfNdNnzfRZM33WTJ8102fN9Fkzfbbi09G0is/gs/gcPo+fhYxOlNGJMjpRRifK6EQZnSijE2V0ooxOlNGJMjpRRifK6EQZnSijE2V0ooxOlNGJMjpRRifK6EQZnSijE2V0ooxOlHGWqHeWWO8ssd5ZYr2zxHpnifXOEvXOEvXOEvXOEvXOEvUVf45SFU3YgueilC6W1sXSulg6cUb536h6/KjHc8I1utm5utm5E93sqyFOXIAZutsrulpiVoh1tg/obDN1tg/obDOdxZckLwurko+FJ5MN0WHJJ3S/55znW5zTt0XH6HJ5XS6ZbHO+/69OV6XTnTzxNybzXt+j81wepXW5tC6X1uXSulxal0vrcmldLq3LpXW5tC6X1uXSJum8STpvks6bpPMm6bxJOm+Szpuk8ybpvEk6b5LOm6TzJul85Z2hULkUd+Fn+DnuxjLcg3vDdJ1zus453bmr3rmr3rmrXhdN6aIpXTSli6Z00ZQumtJFU7poShdN6aIpXTSli6bMmQVzZsGcWTBnFsyZBXNmwZxZMGcWzJkFc2bBnFkwZxbMmYXK0RBXFjGGEvZjHAfwEuSEzjxPZ56nM1+kM2d05jnOf1nnv6zzX9b5L+v8l3X+yzol5JwSck4JeaeEnA4+vWp3KDgp5JwUcjr5RTr5RVXWVGVNOvp0HT3t1JCrOuh5CIXqCBVIIBmldfq0E0XOiSLnRJFzosjp/GmdP+1kkXOyyFW/2ntfg5O8dornp0KtdcrImQymmwzS1W/3fTFoOjjKqSNnQphuQkg7eeScPHJOHjknj5yTR87JI2dyuMjkcJHJ4SKTw0XV6mi1OlqtjlZfhssxN8wwTcwwTcw2Tcw2RUx3ns2aJDImiUz1PRN/kWla9UP43cRfZZpW/bTH5lBvyshU89K5N1s9Fk0zcWRMHBkTR8bEkXEWrncWrncWXu8svN4EknEeXu88XF9zZpRyJq53Lig4FxScCwrOBQXngg5TygrngoJzQcG0Mse0MqfmX0Nc8zWcH+Y5HxRqLva1nKr5Di7BbMxxzUthX84OHc4OBWeHgrNDwYSTMuGknCEKzhCFmh97/w0Tf1WwYOpJOU8UnCcKzhMF54mCKWieKShlCjrOuaJgEppnEko5WxScLQrOFgVni4KzRcHZomBCmmNCmmNCmmNCmlOz27V78CLU+hq13tR0p6npTlPTClPTCtPSPNPSHNPSCtPSPNNSylk/66yfddbPOutnnfWzzvpZZ/2ss37WWT/rrJ911s8662ed9bPO+lln/ayzftZZP+usnzV1ZUxdGVNXxtSVMXVlTF0ZU1fG1JUxdWVMXRlTV8bUlTF1ZUxdGVNXxtSVMXVlTF2ZSe+wpnfifaF+0hn4umt/w/MLcCG+6bWLPH4LMzATl4S8CS1jQsuY0DKTFvnMEq//yntXhvWTHvD1gxgN2clRNM0El5lsb5OPCvWTj45Sqc+F7tTn8UWcF8412Z2b+ldfXxXi1DwswF8mvcW+/gGuj9ImvrSJL23iS5v40ia+tIkvbeJLm/jSJr60iS9t4kub+NImvrSJL23iS5v40ia+tIkvbeJLm/jSJr60iS9t4kub+NImvrSJL23iS5v40ia+9P/HiS/9NxPf0dFN4f0V50efrPi36HMV/x5dVfEf0ccqvhG9v+KC6EuJc6LzEjOiLya/ED6SPC+clXw0rEg2hE8md4VnzIZTkypc8sVwS7IvbEr2R8cn885be0IxOiG66eBT0a/D1mhj2OrqHzz012Df4+pvcfW3uPqHK2aEot7a4y5Oc05lXwhnuMsH3GVucn14LLkBDQfj5B/DWj2uLflkeDr5VLjJ3a9151KyJ/S6+xnuvsTdk+5+j7s/FU1KbgnLk83W5CSf3Bq+kdwW1iUzPrU9tOuKz5tTfx3+ZG1/8s4v651bvPtO716Q3HrwoHf/wrs/ro+u9YkrfeJnE3/b8TSrXaibv0b3/njikzr5jDAj8Z0omXjQnPxU+I/EprA0sTN6d2JUR54aTUmeFn6ZXB+ldenT7OC37rTJeTSZ3Oqs2Rp+p0tXufpBO8ro1AsOderkoTNp0s56k/12lff6njBQ8aWoMqyLqlCNGkzCZKRQizTqcBimhMeiw3FGaI/OxPfDQ9G1+AGuw/X4IX6EH+MG/AQ30XBdaIkeDS0VidBekUQlqlCNGkzCZKRQizocjiNwJI7CVByNaTgGx+I4vBYn4HU4Ea/HSTgZp+BUvAGfDs9XfAafxefweSzE1bgGi7AY38P3cS1+gOtwPX6Im8OOiltwK36K23A77sCdYUfi7eGhxLvwIXwm/CHxo5BL/DjkRPkXuBKLs5fE2EOciMXYp8TYS8niwb7kmIwohZrk/oNjyfGD7ckDoTr50sHe5MvhQ8mDXg/huMqqg32V1eEjlTWhpnLSwbHKyQfbK1OhurL2v1H3JfBRFNn/r6p6ujozPSGEEEK4b9RVwWVR8Yi6Hj8FRFfx4FZRVgUPBEROj1URERAUUJBDUFdxES+QQ/AAFQ+QG4LhSIAECB2OcCak/t+q6cSEBHLA6v57Pt+e6uo6Xle/+tZ71T01eemWq5KsMOKjka6Pmmf1BfoBTwL9gaeAAcBAYBAwGBgCDAXeVpus6cAM4B3gXeA94N/A+8AHwEzgQ+A/wCzgI2A28DHwCfAp8BnwOfCFSrHmAfOBBcBC4EtgEbAY+Ar4GvgG+BZYAqxSs63VwBpgLbAOWA9sADYCycAm4DcgRc0O5Kh5tgCgv3ZALbBj8V0FaACcCzQH/qo22Rfje4RKsccBE3CM67TfQRjXY+N6bFyPjeuxP0LcbOAT4FNgLjAP8fOBBcBCALLbkN3+EeGfgJ8R/gVYDqwA1gHr1UY7GefSgT3AfuAAcBDIBg4BR1SKjAYqATFAZSBBbZTVgUSgBlATaKE2yYuBx9Vs2Rt4GngGeBWYAkxTK+VMfB9Rs50mKsU5T21yLsB3M3zfDLRD+G610bkP57sD9wMvIX4C4t8A3gQmAjOBHLUxilRKVGV8o39FoV9FJQI11abgfSo5+BDQE3gEeAzoA6C/B9Hfg+jvQfT3IPp7EP09+AowEhgFjAYgb3AMMBZ4DXgdGAeMByYAbwBvAhOBScBbwGQA1xicCkwD3gamAzPU7NBNKjnUGmgDtAVuBtoBtwC3AgPVF6FBwGBgCDAUeBp4BngWeA74F/A88ALwIjAMeAkYDrwMjABeAUYCo4DRwBhgLPAa8DowDhgPTADeUF+456nZ0VHqi+ggEFJfkIWxYjaYf7dYSxeAl3PpdRqgJtJAYBAwGBgCHFPJ8J+T4T8nw39Ohv+cDP/Zg//swX/24D978J89+M8e/GcP/rMH/9mD/+zBf/bgP3vwnz34zx78Zw/+swf/2YP/7MF/9uA/e/CfPfjPHvxnD/6zB//Zg//swX/24D978J89+M8e/GcP/rMH/9mD/+zBf/bgP3vwnz34zx78Zw/+s6dX4WLfQc7vVSZ81kz4rJnwWTPhs2bCD50AP3QC/M7V8DtXw+9czWeoDPN+ZOSto238iNqG0WwDRrGJYgXVwXi5FSPYCPhwE+HDTYQPNxE+XCZ8uEz4cNp/Sob/lAz/KRk+kwefyYPP5MFn8uAzefCZPPhIE+EHTYSfMhE+yUT4EBPhQ3jwETLhG3jwAzLhB2TKc1WyPM+sx5kJ21/b8smws5NhWyfDFk6GDZwM+9eD/evB/vVg/3qwfz3Yvx7sXw/2rwf714P968H+9WD/erB/Pdi/HuxfD/avB/vXg/3rwV7NhL2aCXvVg42a6fRF2U8j/J5eNU15sDc92JuZUXHoT3epCbAxJ8CmXA2bcrU7WGW4Q4ChKiMcp7aFqwLxQB2gLvAM4qerbcQxqnyIcR12nJhPl4oF1FksphbiK0pA+84V38CS+paaiOV0M9r6Zvj1AVgMV8K3jxVr6CK0+xZYDrVh56QiNo3Ohb1wM+yFxiKDrke53/hz2eehpq/VTKQfa+qcjXMPwapYQNGIW4ajFXpdyuJr6bIHKank9XQhT3P0jstRaxuMhzdChkhMc4yWRxB7DUbLBRgtd5s1ivfof6NEbE0cXWnmFKshbSPIoP+LYCedjxQX4GgFJeEK43CuNq5Vr/p2l/pF9KFWkP8b6wrYaxwxP+DoJ6TG2ASbMAtHKTjqSWEcHcfRD9SELEqiAGADEnCAKCAIhAAXCAPRqLE9VRUdYON1AXrimhbADvwKdubXaqXVh5KsvkA/4EmgP/AUMAAYCAwCBgNDgKGUBF8+CT57Enz2JPjoSfDRk+CTJ8H/ToLvnQR/O8n8/0UY1m02akrBVewUi3En9b+ZfK3mwLrdg2vvgzaZD7m+RCpcLa49TLHsV2rAVlIztEwXtMPfRQek6kgdRRezxlxH0VN9rVclEv1UqhhHLcV4uhj1eLjTjWDJzLIupYusVtQMrdWRaiNHbdTTAnezD9VFTXt1/aamsP+/Jt+LTsjdGem74fsefPeBhv2qNsJGzoR9fMzozzpykEuQrf8JBanjkTIeKaOQ0kOKLIqnNLAobCjaAbupN2rS97SfWg27OxN3vRIYd6Upbw3u4FrkQpnaIg7Eqlz48Lnw4XPhI+fCR86Fj5wLHzkXvm8u6myvMvQvnlDiuegp0pS2VmVTtSJ1dgJndQN64dr6wBJfofZDuixchweNq4q6DyHXUtQbQr1HS603hHpT9X+zoLRY1BtAiYdQYiZKzEaJUShtv38Vuehn7RGr1wvsBEu+G9AbZ/pQdeSMgsQ2ch5GzlzkDEOWPN1qyJmDXpFGN9B2YAdwDJp9HMgBcoETYIf28FzuUs1EJ7BFZ+oquuH7Hnz3gu/TG/L0U9PFIOjFOLoE+nA5WvxX1NjK3JtV6i1T2xq1Dn0uDl7OcV9HLrJQtpUHKGoSiKUbZAegI9CFmsjxwAxgK463AakA5JRZiMvG92HIptd/zIJkx3DNxyDZubjuY5DsXFx3Iq5bM4aD6w3iWtPFeooxWrcQOb5Bju3IkYgc25EjETkuQeoYyLzTaN4qlQO5jyLndpNrjflfgg6oryM0uQu+u+K7L1gxleqD8bLAMUEwY3UwY2Xw3ULzjzr6/iUjlUBMFu5De4TuMn1Dr4YXL56AVj2J8W4n5M5AjbuUZ/RtK/JtR74gSndQMseZZKpO3dV+uh94AHgCd7897mcHyNUF6AvN1KnToCU70dLpkGkX/MvdKGUPxskrqFogRu0PZAJ71X67J9ALeAR4FOgL9EO50f5/Am1AyckoOVk8gavqC85PxX1MgxZtRw8yVwsezkAb7VI/G1+8GuTLgXw5kC/Hv3o9p7wZpWxGKRylnAsZY1DKEZSSh1L0SvMOStim/48I8uVAvhzIlwP5ciBfDuTLgXw5dD51pzZ0P/AAMICupYHAIGAwMISuRY2VUONfwFkBtPCt4KwAWvlWcNZ7aOlP0NJfQk+/h57eCD1tIz5Qr+KafsII0TgiDcYtLU0GrIlLqRV0tJV1hdpgTaFrranANLo2EENtAlvxnYnvvcA+utY+B2gJ9KQ2di/gEeBRQMvnQKrDvt5wX2+4uVe6BXepdDMbMQtyv+univdTxUNuDykvMjMQu9RqaEbPvG/hC+6F77cVvt5e+HZbraZ5O6BrPfM8xGYhJstqqq5EqT3zNovDaOcc5M4FN5xQy62AOgK/8KgVUtlIuRwprzd5v8bZlYhZiZigyeuJ46gvB61yQq2Fj5lnRZGNvHlItRa+ZB5SJoGXeubtRC158FKzIVmmOIbvHNSaC82M5MxFrXnwTrMhcabl4DsIKUKIj5SUiys4BK3rCb/2CDGUkoVS8lCKQgkZpm6bGHJnIXcecivkzPBlOEe3U95oyJCK3A2QexNyHxbH0WO19LnQ4xPQuDzYCUqdgCypKK0BStuE0g5bUWqNuaoQ7rNLMfCUd6PkE5DpP3oUVRwlHoUcKSKPOHIdRd0pVhjhpqqeTpG3AinSUZ9uqWSkSEeZupWSUcY+tO5J9wt3379PyF3K/TFpzX1B2lLuB67xDO8D+LSc7Q+WOcvtjms8RXubMyW2M0VbcRRlVYV8CRS0ElFaDeSpCZuhFsK1ca4OztXHuYY4boRzjXGuCcYDy4pHDTVwti6+G+GeuFYcjuBDWNVQfyJqqIGadFm1EV8H8fUQ3xDxjRCPcnAXdGpdcw0/ha5JlxULuTjO7rDiEVMNSKDakC8WKXegzNqQj0M+jlw7rLo4Xw+oj/iGSNMIcY0RbqL/lRylpEBWfYXcqg5ZEyngl6Jzp0B+fYXcaoBzDXEukpvjeuOAqtC9eMicgHITcS01cPdroq5a+rpwvg7O18X5+jjfEHGNcL4xzjfB9eEqcG+qotx4xFYDEtQ6yJCH1km1auJe1sI110aaOkhTF+frAfWRpgHSNESaxkjTBCObvk+uadcEioMcusWOQo44yBGCHK5p2/o4bmha8ChkiIMMIX1XSJhrT/TbOSK9bj1hrjuSI8uXmlOliuoEeq2H9jtJL9DbL6RweXUDuZqRPJV+4GwjqnK2dASl/QVXXUE9Qe6mVPlMdQWlXKqv6OzoC+7Ej+Y+VkhnzNgQLq/eGFZvKg7n7QKTdgPj1ASrtRXH87LAateJ3LzdYJ/uYLW6YLVWViBvFxi1G9ioJlitrRWVlwVWu84K5e0GM3UHq9UFq7Wy4vIOo0XOR4ucgxY5x0rAcXX1F7RINKRqjlZpjFZpZNVGfB2kq4s09YD6OG6AdA2RrhHSNUa6JtCaKHhuLnyuJKH/1+dbqgJrNw6WbkNYFZfAVlgKa6+S+W+h+awLXca60fXsHnqZ3Yvv++C5t1eTxB3wRe5U82F5TDL/VHfOaVItNan0fyCtN7H5R7MLjjg8+UXsKzXbhPS/26UiVAle8vlE1Ao+6bl0NT7NqDXdRs3pDroTsXfDlruc/kkj6CYaSR/QozSfFuHoK3xepR9pHY2hDfhMoRR4J1MpHSW+z2qwGrSK1Wbn02rWhrWlNNaO3U47WAfWifawrqwreewe1p2yWE/2CB1kfdkEOszexCeRTcKnBpuMT032PvuA1WJfsRWsDm/GL2IX8hb8YnYRb8VbsZb8Sp7ELuZ/59eyS/n1/Hp2Gf8/3ppdztvytuwqfiu/jV3N7+B3sWt5R96R3cC78q7s/3h3fj+7kffgPVhr/iB/hLXhvXk/9g/en7/I7uQv8VdYDz6Kj2M9+QT+BuvDZ/CPWT/+KV/K/sW/5+vYeL6Bp7H3+C6+h33Ks/g+Nocf4EfYF/wYz2GLuBLEvhZcCPatkCLMlopKIpb9LOJEHPtVxItEtlLUE/XZOtFQNGIbRBNxDksWfxHnsxRxobiQbRHNxUVsq2ghWrJU0UpcxnaIK8SVLF1cJa5iu8Q14hq2W1wrrmV7RFvRjmWK28VdLEt0EPexbNFT9GJ5ord4kpMYJAZxWwwRQ7gU48R47ohZYhYPis/EZzwk5oq53BXzxLc8LJaL9TxBpIo9vL44LBT/ixWwonlLK85qyq+yrrCu4O2tPtaL/A5ruPU5f8j6wlrEx1m/WCv4W9YqawefamVYin8WCAaC/OeAG3D5L4GYQCxfHlgd2MhXBn4LbOUbAmmBNJ4S2BnYyTcHMgK7+JbAnsA+vi1wIHCApwcOBY7wjMCxwDG+J5ATyOGZgRN2gO+1pR3ND9sxdgzPs2PtqlzZCXZtIex69l9F0P6b/TdRy77YvkHUttvZ7cWFdmf7WdHS/pf9guhkv2S/LLrao+xR4l77VXuMuM9+3X5d3G+PtyeJB+yp9lTR055uTxe97Hfsd8Qj9kz7U/GoPcdeKPrbi+1vxFD7O/t78Zy9zF4rnrfX2xvEGDvZThav2ZvtLeJ1O93eLcbb++1cMVGS5OI9KWVd8YFsLFuIJfJSeYVYLa+SV4kN8u/yBrFR3iRvFpvlrfJWkSZvl7eL7fIOeYfYITvIrmKnvE92F5nyQfmg8OTDsr/IkgPkEHFCPi2fsbh8Qb5oWXK4fNmy5Sg5wXLkm/JNK1ZOkpOsKnKynGLFyRlyhhUvZ8oFVjX5rVxmNZUr5TrrQrlJHrD+JrPlcautzJXKut1p7DS27nKaOudadzsXOBdanZwWTguri3Op08rq6lzuXGHd41zlXGXd5/yfc5PV3WnjtLF6ODc77ax/Orc57a2HnLudu61ezn1OD+sR51HncesJZ4AzwOrnDHYGW086TzvPWv2dF52XrIHOy84Ia4gzyhllPe2MccZYzzjjnInWs857zr+tYc5MZ6Y13JnlzLJedg44B60RziHnkDXSOeoctUZFgfis0VFWlGWNiZJRQWtslBtVzRofVT2qujU9qkZUbWtGVN2outa/g7cFO1jvB7sFu1kfB7sHu1ufBP8ZfND6NPhw8GHr82Cv4CPWnOBjwcesL4L9gv2secEBwQHW/OCg4FBrQfDF4IfW4uBXwR+sHcG1wd8sL7g5uMM6HDwWSrTyQg1CowN1Q2NC0wIjQ3NCiwKTQytCBwLvudJNCPzknudeF0hx73L/GTjqPuw+Zke5vd0+diW3n9vfjnUHuAPsqu4g93k73h3mjrTruqPd0XYTd4z7mt3UHedOtc9z33bftlu6M9wP7Yvdj9zP7Kvcue4C+3r3S/dLu7W72F1st3G/dn+w27o/u6vs9u4ad43dyV3nbrA7u8nuFrubu83dZz/gHnSP2v3c426uPcjNC5M9NMzD3H42bIVt+7mwEw7bL4RjwvH2iHBCOMEeG04M17RfC9cON7THhxuHG9uTw0PDQ+0p4WfCz9tTw8PCr9jvhF8Nj7Vnhl8Pj7Nnhd8Iv2HPDk8MT7Q/Dr8VnmZ/Ep4efs+eG82jo+2F0bHR1exl0TWia9kroo9EH7dXEQ/Cfidyr6l8CzWlunSWNjVfpamd1ExlILypxBR5aqL6CJ8sNRxHt6iOyLMUoQz/fIbajf02/+hwsfz67G6Vjc/v52QJ9RwEXitV3oHAl0ViNqOGeF3LKTd4Xki3UeUg7GIk70RhHKcVlTH/akqo82e1VXnqF5SQiqtNL03GMmwOSh3nl75dZaqlaod/dKBY7XuAFLVFrVZH1U0UhbY7l+oVOp9XWmXqEO5dNkr4XXK0PyyWyNl31DvkAgX38KTce4EdKhllbMZhAHZWY7oSoTrm7BK1XK2D/kB34LeXXP8H6m01Gd/DgCR1geqr+iBUqB3zrx6hzGK589R3Kh0a9J36CXLgPujWK5qrIO3PpTQFwU8lijahkX6Mh7J/ydfNwlrhx2Tjyg+g7Tepg7D3KyGqBe5CQe1qj7lDe/JTF8ufqXahj3n5La5nRs33b4XTlCa3ny65yNHjRY5+KFsZ2Jqb9L6mqfW4f45aX0rNRwr17eZ0SSmpP1T/1j1afVdmmYrm36m1Q+tssTNry5AbV6ZeMKE5J/dndW8Z8kNH1GeGtzbr+1beTb1v2PR9tGvxzSlTCVlqvmHNMupFCSUcKLtWlZDbZ1i1qkK5Z5v9es0cZ337axnq3xkZy1QO9OhguWtwT3u2CfAPU0v+iLct8vHP1ykhzzn41MHnnCJSvut/r4h8TpO/eYn5/daFlhwCOx06lcDgz71qPxhsq+lTWquPmvix5nRt9ZVapNboEf0U+XMLhV+m6uD/O6md7iF+XArGhgXFubggT06h8GiMPJXoRuqG8Cw/Lg2tt/LUo2p+/Uaj30D+KLBPb5/Jdfwn6iMSau4p85+shQFYTz0Q/4p//gf1Pdr/R/+oOH8fLxQejtzVqS1pSyjJj/tSzUMJ/zll/dtLjs/DHdP8qG5VN6vuqp2fekqx/M+Cxd5R/1G/qjWFojl1pudoBEIjaZT+zQx9CM2dRXNhHS6gRXSRmVVoSd/SOrqYNtIOak3pjNFdrBvrRk/Ao/8H9dG+PPXTXjw9yR/ivegp+OMbaDDfxNNoCM/gGfQi38330DDtm9NwfpgfoRE8h+fQSO2b0yjtm9Or8M1DNFbUEXVogugkOtMbopu4hyZac6w5pL1aRZMDsYFY+tn+3P6cfrG/tBfRcnuT/Rv9aitb0Srt09Fq7dPRBnmLvJVStE9HW+DT3UlbtU9Hqdqnowzt09Fu7dPRHu3T0THt01EefLqXGcGbe5XZcqycwKK0T8cqaZ+OxWifjlWW0+UMVkX7dKyq9ulYY/h0B9j58OYUa+cIJ8A6Oo4TZF0c14lm9ziVnSqsu1PVqcZ6OIlOTfaQU9upy3o5DZxG7DHnSieJPQGv7X7WF97ZMNYf3tnLbID2v9hA7ROxQdonYoNDA0Oj2TPa02Hj3Rg3gS1wP3Q/ZEvcNHcfW6p9DbZa+xpso/Y12G/a12BbtK/Btmpfg6VpX4Pt0r4G26d9DbZf+xosW/saLEf7ESxX+xHshPYjOI+Oig5xGV01uhoPRh+NPs71M4X1RmOY0RgOjRkHj2I8vQmdnkgzEPMOPpLepQ8wSs2EPtlGn2zo00L0ui+hVUGjVUFo1TLE/0hrKERr8eHQsnWwqjfSb7CuUigVfSwNOleP0mk/evwBfOrTQTpCDegoPg3pGJ2gRpQHjaxsNLKW0UhhNNI1GulCI3tSDO8FvXSNXsZCL1Monm/mm6kK38K3UTWeylMpgadBX2safa1h9DXB6GtVo6+JRl+rcMUVVREw/ykOWsuxx0ZVobsSYdx8qi6ioMdxRo9rQI87UWPRGdrcBNrcDeF7oNNNjE7Xgk6nELM2WzuIWzutdLKtDMujkJVlZVNt65B1mCpZR6xcqmOdgPY3Mtpfz2h/LaP9tYz21zLaXwva/3eKk9fKaykkr5PXkSWvR38IoD/chJjWsjVi2sg2JGVb2ZYceTP6SQP0k1uQ91b0lijTW0J6BoTC8k70mWj0mY5UT3aSnamS7CK7UCPZFb2osulFlU0vYuhFDyNXT/kY0jwueyPmCfkEcdlH9kUt/WQ/lPwkeloIPW0gcg2SgxA/WA5G+iHoe2HT95ieT0GaYfIl1Dtcvoyzo+QoxIyWo5HrVfkq0oyV4xAzXo6HJBPkBMSgf1JQ90+UM1lORq4pcgrip8vpKGeGnIGUM+VMxHwoZyHvR/IjtMNs+Rla5nM5D3LOl/PRJgvkAkj1rVwKab+Ty1DmSgnNlGsldFKul8kobZPcQnXlVpmGNtkuM1DXLrmb6ss9MhMtuVd61FBmySzUuE8egMzZMhspD8lDOHtYHkb8EXkEkhyVx1D+cXkcJefIHJScK3OpijwhT6D2PJmHvEoq/f+qToBqaTbBHmyCPdgEe7AJ9mAT7MEm2INNsAebYA82IQY2eRH7Yc4w4ppTyNKcQkxzCrnglEHYDw4OpRjNLCTALOvIDa0PbaBwaGPoAMVoliGhWYaqg2XSqIq73d1Oce4OdweF3Z3uTop30910nM1wMyjB3eXuoprubncvwp7rIX2Wm4U0+9x9SHPQPYhwtnuIEt3D7mGkOeIeRZrj7nGczXFzKeTmuYoSwtq1rqL5C3srbGEfCNsUCxZzqFo4KhykquFQOISUbjhMNcFrVRATF46nRM1uFA92S8S+Rrgm0tQO16G4cN1wXZRTL1wf4QbhBkjfMNwQYXAf4sF9iHkrPBm1TAlPRa5p4WkoeXp4Bsp8J/weVdVsSEKzIcVoNqQYMNbHPhuOxkcYNgyADScgPBE8KAwP2mDBDxGeRV9gP4+gbWDDrxD+BhwoaCl4UIAH14Ix14FfhZm/dwwPCsODVQ0PxhseDBoerGZ4MMHwYHXDg4mGB11WiVWiMOvAOmDfk/XC/lHWG/s+rA/2w9lwCoMlbyVuWDIKLNkde82SIcOSUYYlow0nxvFMnkmVDQ/GGh6swk/wE1TJMGCMsIRFseA+B+GgCFJl0UF0oJqio3mTTXNfLcN9dUQX0QXxXc3bbZoHaxkerCPuFfdRjQIeTCcBBswmB9yXS0HDeomG9eL1rC3659XyavTea+Q1JAzHOfIGcJwFjmuNsGY3YdjNNuyWINvJdojR7CbkbfI27G+X7ZFSc5xl2C3esFvQsFsi2K0bufJeeS/298n7kP5+eT/2PWQP7DXTOYbpgj7T9ZF9ENMXTGcbjnPkU/Ip5B0gByB9PtMNRTjCcc/K5xDWTOcYphOG6YJyhByBXK/IkYjRrOcY1nN91hsjxyBec59juC/RsJ4wrGfJt8B6wme9qXIqwtPkNDDa2/JtpNc8KAwPJhbiQWF40AEPzkc4wn0L5dcIfyt/xV5znwPuS0ZYs15Vw3rxhvWChvWqGdZLMKxX3bBeomE9Vx6UB5FLc1+84b4Ew32JPvflguOE4TjXYQ4jEWGrYP/gUxQVHBgciP3g4GAKBYeCm0LBZ4LPIOb54PMUZXiKh8aE3iBuGCfO3QuuiXH3uwco1vBLjGGWODDLEYSPuseoEjglD/1cc0rlsAgLqgQ2kRRteCTW8EgcGCQWYc0gVcLVwtWQRnNHXLhWuBbi6/jcUQ8laO6INdwRY7ijsuGOWHDHWyhzSngKck0PT0f6GWCNWMManPhF+/TM68U7/96SbqK7TmXn//+xqQy1S8M/2lqS36XnecxcX3nL3q5nuIzn/ZU53pRfp9n/6nufmdr/NL5oskpV6UVndEqvN3+GTj1WfgnP7qZaw/PU36f0vYvlyICn/X3F52UKysk8+UjtN3s/Hr5iNlo2VXlAwcxeIU80rlDuZKTaQHreoxpC/gxjvnf9B23BAmkK1+vS3SZuT0mzC2p38bk5dUBtUxtxpthTiIpu+bPkRY90//G1utB8AWQXBeHMU91ltaX4rObZ2kp+glNqrhlqmvnONbPhP2jo+SH1PkLL/DT5mqV78CG1Ij++XPVsNzqa+vuxngVTKYVSvGLmg/Rc+RYT2g5pCjOU375lvb9m1jq19HTl36BphcpVh1UucFzPdakTRdKd7rnU/9j2B/f5Mmxq0hlkvqWE8lKpKXSw9hmUevqtKRlu1XxqOLXEDdxQ5meIZz5WnFReEakK970y5v9ELVKz/ecDcWqKWmRi0/ToXnj0rpD9sAHcuNXYD+nGNjFspscktRXfM/1Unnne9iOwFJ/0ojPXhsmqU/7c7BKMBcvUSmASYm9Sq9VPJn5NxIowT7TvLr+kxSTfVeTIjKHq40IxD6npqpd6Sc/yq94FsZch7gvd74o/dST9zLX4s9Dd6itcS/LZ66n5+qDHMTBYvl24jPzns4VlAC8XPBvRz1hKKfmXsyVjRTe0Uth8v6qfNxc720ctKZI28p2C0S1Na0gF6lurtd7YW6addAjj21a/1bBXD6rl5n4fIVHCGBamZsXK9NAP9vpPlwSYI/+p05HI2TMf335/Dl30eWW+laJtLzNub8fHK2Z7bjG2Zwm9Hb35LHNXSdtJfLa62Pnck2P8+MdLjqfyPEcv96YeKGeGyDsWw9Tz5jvLMMCnGgj9W82JhMy5fPvMPO/EnZpXAek+UV+AMT/3j5aoD0i/HzRXhwEwJ1hsCVgi3wrOAvv+5PNE5PlZdLEyv1efq8V+mXH6yI8vwg5KlV9akw+9VG0sOMr3XbbpUL5fGbHEDaMt0/oReUfE7z8HDCN3VreYo8Wkn+Y9BjyJ0Gg1AWPdk34phd5tQQssUAMqIO09arB6W/VC6Bv06rdVD8MPr2A0ehvtvFhNUv/E2JqlnwGaK5uvZqmpkZr9USNRfXNSmelqHbzKSM/9W0HItzvVsQjKbjEXKTvb9PeCt4KKjlJmnC7wfI3lu9W891D4jYsLir6x8kdtRZ/imjeY9pYuibmiYu9f/RFbUU9Wtyp0+GBp/GnuzlnzdMuzFbY/0Bu0l7Ue36d40l2QcveZy6veUoPUv9R4E14BfZ+m35Txx6GIvXhIfQYsOrN6TEnNIm+ynFEZaWonRkIzPuKe7oQeFtjckbuu9sHm2FeSBVjuuipgcxfK/VPkrkIWzYO/+Edb/P7jS/3n9OeSNvWAul8tVHOIm6PBqh/YulvEIlBz1VEcjVCPq0tVA/BoC/WkevAM6orYj3XPSF6fkyI+bcH7htOKnj2bm5pxFsrQ2rsuwuqwb4vdfXM+Va36fRT+czdIswl9zsx5Qoe1p1jgqUQsXZz9HjjFu6p/9AZ5RxbuubCv5v+Z8px6Q2/ro22nyJuu6glYR2vQ+yLnFpv9JjVPdVQvITRK/RaJq2Bd35+5vOWsMbvwe17/u1uBjXvgzN+uLOld97O5RaxD2N87MOqdhRmL0t5RPm3eMmqU+sjM7e+peE2FtupnpZQybbCFzthyVa+eDUlKqcNnOli3Zzwvf5buUmm1pMGy/S/3lLO3werJPmstE3sGcpyN/v4HPo+oiDbC7kmN5PR/2ZE/L7LcPGdYftrMj/hpZ5e/3j96q8hvIIqVccqnIafJY2br9UxRxBOOzOgUPAsOns4/NnO71akX2eWv1+SvwK+8VLoZO37/LVn+nFxZfbsQ3VD+Wv/ULb6iGcv/5In0Ww36uXSBZ68WmP1e8HOpTyP+1zbY/YdO/ZuJQumO/vdlKdtWNoas6Khe4m+lSq3LvEHw+28HzROLAs0KlpgpP62eq6pJHdHn/oStqO0eYQ14T6XwrHkS8yfM96n9Z7GsbeTPKJf4i6NzzK+c9BP0FSWcLa1s/Tuqbfk580Nmhn+bH5Nf52WmrpPkKnT04u9l5suif69VTCr9q6zm+ilNRbx2NUm9q+YX/A7MD2mLwJ/TXFEgR/Ni8r5b/vqK5K/Am0JqlXkq8WPBsXkHCPamXeYnfWX49d4p6i7xt8ml5NlpZq30SG64wBwtQd+LMEPwdPalGVEq0ZVl+71mCfkr8v7Dav17S4PDkWOz92fNT88O/rXULPq+EfRrv1ppMImqwSbd5T9N2hrp00bXHiq/pKVcR+QJWyFvXXVTT6r31GSzbkDBOz2qtfqknCUv+WMsZi3jqetReSU9VY48UTwpbn/pT3Equpl3ZHxmVgdgTxyAfbRBJf/ORCoTcfqZ8SXqDnP8KTRgneqslupjtVi9pr7TM+bm3NgiZafkx5dLonaql3pG3eQfmRA0sIcJv6umq97Qg0mw1uZj5NUp5qjP1Wf+qK1n5+OpmXnm3F/1NHGR9xEnw65+S98PvUpCwVtAReaC1LH8X/OXS9431Pvw1d70j5abuicZnl9u2kA/fZ2tstXXJkHkV/v+Gwa+Fv+t/LX+Wdt/5dfYxWvZls9YkefOf9ZWkedUuNN7qdCsQ8EKCWUZe6qQfn/nNhOuSS3ge9Y1eXfA6thhRpMa9Fe1Fj1Uf1LUZnUp+ksPclVkXPf9VPTOiE9VzT/+xH9SwangF9Mm/sPTXId5t0INwDjnz0Cqq1VXoLV6gKqoyBicv4bGYOA6dZlqr/xfNqgf1G/mbQndY3djTNrm+6/nUVMzcp5nUp1+dqNkuaap6di/X3A8X/tyRd6suN0PdKR/0CV0kVknppE5U/jag3mrVCjviBkpF6qH1ad6DFND1HM6hFKHF6k28g7YwxWQt6d6FNf/qDlwEOppePM5M1KvxL1Mz4v8kn6uWRUkfzMtq57wyyiDj1di3btKT1MsT6Z5I0DbCUabjDYvwbFlTruntXd0rkp0OaTntLqUdew6+OvYPUs3Ms6qUnezOl1/szrdMLM63XDWgXWm0exB9iC9Ztale531ZcNpAhvBxtMsvTodzder09ECvTodLdSr09GX7Gu2ghbzZrw5LecteEv6Va9OR6t5Ek+iNXp1OlrLb+StaT3vzZ+gZN6fP0W/8dF8LG3mM/gMSuXv8VmUxufwubSHz+PzaC9fyBeRx5fwpbSfL+PL6CD/hS+nbP4rX0mH+Wq+mo7ydXwdHROuCNNxESNiKVevMEfKrDBHZoW5gGgoGjJpVphzzKpyIdFStGRhs6pctFlVLsasKhdr1pOrIjqIjixOdBFdWbz+rRxL0Ku+sUS96hu7wJprLWId9Kpv7F690hu7X6/0xh4IxAQqsx6BuEB19qBe7409GvgtsI310+u9sUF6vTc2WK/3xobo9d7Y03q9N/ZC4FAgh72o13hjI/Uab2y8XuONTdFrvLGpeo03NkOv8cZm6jXe2CK9xhtbrNd4Y7/ane0X2Hq9uhtnenU3bunV3XhAr+7GpV7djTv2VHs6j9bruvFYva4br6LXdeM19bpuvIFe1403sZfZG/g5ekU3fqle0Y23stPtPfxyvaIbv1qv6Mbb6hXd+C16Rbf/R9n5h0V13et+zZ6ZPXtg80MkBhGJEoIECUEkSBEMEkKMsYQSYzzWMAMMMxMYhmGYGcaZYc9PRmOtsdYaaq2x1noMscYaa631ejzWWq/xejjGGmuNsR6PsdbjtdYaa6297/oOoZ4+z32ee+OzXtbz3WuvPTPAd33eP3gjdPJEN2EZ//s4QZEESRCCkijphJCULCULESlNSheiUqaUKQxKWdJEIS5NliYLK6SpUp7wJk9cE77GE9eEVTxxTXhLmiHNEL7Bc9eEtTx3Tfgmz10TviXVSnOFt3numvBtnrsmbOS5a8J3ee6a8A7PXRO2SGbJInyf564JP5BckkvYztPXhHd5+powzNPXhPekN6U3hZ3SKmmV8L70lrRG2MXT14TdPH1N+ICnrwk/5elrws+kD6SDwgHpkPSRcEw6I30snJd+Lf1GuCB9In0m/Fb6nfRH4TpPZRM+56lswl3pb3qV8Geeyibc56lswl95KptapZ+oz1Wn8Dw29Xh9nr5Qnamfri9RT9KX6cvUj+mf0T+jnqKfpZ+tnqqv0depC/T1+np1sb5BP0/9lH6+/iV1qf7L+pfVZfrX9IvVz+jteqd6VtKUpHx1NU93U8/l6W7qF3lam3o+T2tTO3ham3oZT2tTh3lam/rN5IXJ7er3+F/tqX/G09rUP5d1cpr6BM9pU/9K/qpsVd/kOW3qBzynTaPhOW0aHc9p0yTxnDZNMs9p0zzCc9o0OTynTTOZ57RppvCcNs10eav8nqaY57RpynlOm6aK57RpnuU5bZpantOmmctz2jQv8pw2TRPPadN8hee0aRbKv5UvaZbwlDXNUp6ypnmdp6xp2njKmsbKU9Y0XTxlTdOdKqRKGnuqnJqqcadmpGZqvDxZTeNP/Tz1c42SxtJUmiATVJfQ9VLh+NJYOlOxcfinZhk4hzUsC2e3Fqf6E6gX4J+OTcMpKLFidEk9+uFsJqMf8v/Pwxz6P2DwjplKHTMNHXMR7noN/8ahb76OHVtYO6tlJvTQueihTpBDH/7VMRfzskfYMvybwHxMwZOD6LBZ6LAym6hKUaWybPoL4UmqdPTcp9Bzp6FSqCpkpaonVUWoT1dNx7wYvXgi9eIZ6MUvQ5vQkZ+nvNCJqtfRl8uoL5dRX56JvhxAfUC1nJWrVqhWYM830aknoVO/xSpUa1TfYrNU69G1Z1DXnkFdewZ17VJ07XcxH0bvLkXv/gXOg6Oqo2y26peqD1m16gS6eQ11cwHdvBz6DHq6SD09nXq6QD09nXp6JvX056inP009vZJ6eg56+rvsMWFYGGaThfeEH7Kpwk50+Tzq8nnU5aegyx+A/g/0+lzq9fnU6yej1/8v6El0/Cno+CPQf0ffz6W+n0t9/3H0fZk9oU5B9y+g7l9I3X8aun8WK1JPVE9k09XZ6mxWz08CzHESsCdxEkyDFqqfxF04D1gxPw9wV5W6CjpbPRtXa9Q10DnqOViDswGKswEV/rfWL9DfWs+jv69+gf6+eh79TXUDzokgm6MJaZYzFU6LNSxN8w3NevYlzduaITZe823NJlaleUfzPfaoZovmh2yiZqfmxywbJ8pPWBlPE2Xl/Fxh1fxcYTI/V6Dp2nQ2VztOO47N4KcLK8Ppcpqptb/S/opN0Z7RnmFp2o+1HzON9qz210yLU+c8Kp9oP0HlgvYC02k/1X7KJO1F7UX2iPa32t+yZH4msRR+JmHlVe1VNk77O+3vWAZOpt8zlfa69r/wxBva/83Ga29qb7JH+VmFJ/5J+yeWpb2jvcNqtJ9rP8dru6u9i9fzZ+2fMb+nvYf5X7R/YXO0f9X+FTs/EAU2XlSLGjZH1IpapsIJp2M4LESJpYh6MYmlicliMlOLsiizLDFFTGE1YqqYijU4Bfn/1V0cj3szxUdwb5Y4EeuzxUksQ8wRJ2PnXDGX8QTUqdA8MQ87PC4+jvX5Yj7WPyEWYv2T4pPsUbFILEJ9ujidacRisZilik+JJdj/afFp3FsqlmK3GeIMrCkTy3DvTHEmk/mJi2fNEmehXilWYeVscTZ2qBZrmVacKz6PlQ1iA9OJL4gv4DW/LH4F76tZfBX7vy4a8fRWsQ1PaRfN2McidrFa0Sb2sLmiQ3ThiW7Rw+rEfhHdQ1wm+tgE0S/68WoDooL3EhRD2CcshrFDRIxgh6gYZcliTIzhKYPiINbExTieAgJgkzgBsFIQwDdYubhWXMtmcg5gE8EBb+PqkDjEssVvi+gD4nfE77BqcaO4EZ/2ZnEz9HviFlbGM2CxHqyAHd4T34PuEPFTKu4Ud+Le98Vd7HnxR+KPsPNu8QNc3Svuxb0/EX+C+j5xP1b+TDyAlf8iHsLVfxUPswoQxlHUfyn+kpWAM/4n1h8Xj6PyofghVp4Q/w0rR8QRvJ5/F09hzUfiR3iFp8Vf4TWfEc+wp8SPxY/ZLPGseBb3glFw1wXxAnb+VPwUd30mfobdrorXsP734u+x/g/in7DmjngHn8bn4ud4bXfF+2wi5xg2ExyTgnmqbhwr12XoxrNJukzdo6xCl6XLYbN0k3VT2AxQzjRWrSvUPcle1BXpprPZumJdMSpP6Z5mNbpSXSl2mKGbgZVlujKsmambiavlOnhHsNGX2DO6Kl0VnjVbNxvrq3XVuFqjq8GzeKaAijMTK+PMBAUzQcFMUDATFMwEBTNBwUxQMBPL5szEJnFmgoKZ2FOcmTAHM7FqzkxsIs+qZSXSXGku7gI5oQJywhqQExTkxCo4ObFZICc4AckiWVgN+KmHpUkOqRdrQFG4FxSFOigKK0NSCPuEpTDmESmCOogKrwdEhfVvSW+xcmmNtAZ3gavYTHDVelTelvBTJw1J38H8n6V/xrO2S9vZi5y0UAFpsSROWlCQFhSkBQVpQX8n/YE9K92SbuEpf5T+iH1AXayUUxfmf5P+xv/fW3rGnter9Co2kRMYmwQC00ElvcSe0eM/VqpP0idhLutToWl6nL/6dH06q9CP02egMl4/nlXrM/WZbKb+Ef0jrEY/Qf8o6hP1E1m5PlufzZ7ST9JPwjxHn4OnTNZPxtVcfS4qYDvMwXZ4JWA7KNgOCraDgu2gYDso2A4KtoOC7aBgOyjYDgq2Y0mc7dizYLtXWHrSwqSFTEx6NelVzBclLcL8taTXMF+ctIRlcvJDZXnSViYk/SBpB+bgP8zBf1gD/sOaPyermJAsJGez5zgFsspEdgOnQCZwCoSCAqFflb/KJstL5aVsivy6/DobJ7fILewx2SAb2OOyUTayPLlVbmVquU3uwNwsm7HeIluwxipbsaZL7sLcJnezfNku27GmR3ZgjVN24mqf7GK5IMt+1L2yF3XwJTQgB6ADssJy5KAcYlPlsBzByqgcxcqYPIgnrpC/hsoqeTV2BoPiKWvltdBvyuuwZr38Nl7zkDyEfb4tb8D8O/J3sH6jvBHz78rfxZ6b5E24+o78Dpsmb5Y3syc5ubJCkOtWNl3+gfwDVi9vk9/FfFgexpr35Pdw9X35fegu+UesWN4t78bVD+Q9uPoTeR8rkn8q70flZ/LPUAHvQsG70H+VD7Mn5J/LR7DmF/JRViD/Uv4lVh6Tj+EpJ+R/Q2VEPoU9QcPY/4x8BvqxfBZrzsm/wdXz8nns84l8AfNP5U9ZOSj5t9jtknyJTeOszHLByhGWkxJNibG8lMEUfErg5hWsOOXNFHxWKatSVrHHUr6e8nVUvpGylk1P+WbKN1k952lUwNOsmPM0y+Q8zQTO01DwNBQ8zTI5T7MykF0t8XQD8bRAJJ3g5i+ImfNxKvFxKvsn/EslMp5HZDyfyDiDyHgBkfEEIuNHiYyziIwnPpTfo6X8Honye7SU36Ol/J4kyu/RUn6PlvJ7Uii/R0v5PVrK79FSfk8a5fdoKb8njfJ7tJTf8yLl97xE+T3jKb/ny5Tf00j5PS9Tfk8T5fdkg9STwc0pqhRi9InsGVW2KhsMzUm9EqT+MqsiFn9F9arqn1DnLD5bZVaZQdhulRvqUfnAzQEQ+SwQ+QpWAxZ/E/Ovqb6G9ZzIZ4HI32a1YPGNbC4ofA/0x6ofszrVXtW/4Cqn8NeIwp8jCq8nCn8eFF7K1ETh6of4Ww3+fo74+0Xw90tE4TxhSEMJQ+MoYWgcJQw9QglD44jRv0KM/iXhTWElm8OT/dnCUVLnXD5deF94nz0p7AOXP05E/gQR+TThQ+FD8Ddn8anCKeEU6r8Cf0+l1KLJwq+FT0DknwqfQnmCUTGluhUJl4X/ROUz4TMoz3bLpWSjfOG/hBuY83yjAuEPwi3MecpRofAX4T7mPOvoMeGB8DeWS4lHeWqVWsCc5x4VqLVqLeY8/SiP0o/y1cnqZFTSQP8lxP1lxP3lxP3N6knqHNQ5/ZeoHwf9P60uAP2XEP2XqovURZgXq4uhM9Qz2Uw4gVmYV6or2VPqL8EPlJAfmKGuhh8oUT+rfhb7cz9QQk7gVXICi8gJvEpOYBF5gAbQ/3qWCu7fxDKI+LOI+CcR8Vdq9oL4Z4P4j7AazS80J1gdcX/9Q5lMWspkSqNMpvGUydRETmA+OYG5lM/0EvmBKviBj5hIHkCn/TU8gEgeQEceIJXoX0f0n6W9rL0Myr+i/QwVzv0iEf+jRPzzifgziPiziPgnam9rb0M50zcQ0+uI6TOI6RuI6QVRBNPriOZ1RPMTidobiNd1ROoZROoTic4biMt1xOVZxOUNYHH4XrEERC4Si2cQizeMUni5WI71FWIF1nMWbyAKTzC3jjhbR2w9j9h6PrF1BrH1AmLrCcTWjxJbZxFbTyR6niiuEleBKb8ufh00yem5ioi5WlwvrkedE/MzRMxzxU3iJnAkZ+UKcQtYuZpYeRKxco24TRwGx78HSp5ElPwK8XGNuEfcg7s4JVcQJb8CSt6He38KVp5ErFxJrFwj/lw8gh1+If4C6zkrVxAlTyJKriRKriFKrhdPgZKriZLnEiVXECXXECXXEiU/T5T8jPiJ+Amucj5OkPEz4nXxJiqcjyuJj6uIj18RH4gPQKicjKuJjGtAxo9izpm4lph4rm6q7glWR2RcT2T8GpHxc8TBc4mDXyMOricOnqSbpZsF5QT8PBFwve5Z3bPYkyeKpVGWmJayxNIoRSyNUsS0lCKWRClijZQipqUUMa2uWdeMp/MsMS1liaVRithLlCI2nlLEmihFLJtSxLIpRUxLKWJaShHTUopYGqWIjX8oRSyNUsSSKEUsjVLEsilFTEspYmmUIqZ9KEVMSyliaZQipqUUsfGUIpZNKWJaShFLoxSx7IdSxLSUIpZGKWJNlCKmpfww7UP5YVrKD0uh/LA0yg/TUn5Y00P5YVrKD0uj/DAt5YelUX6YlvLDtJQflkb5YVrKD3uR8sNeovyw8ZQf9mXKD2uk/LCXKT+sifLDsik/TEv5YS9Rflgj5Yc1PZQfpqX8sGzKD9PCw4xnVXAsT7C55E/qpGnSNHiDQqkQrD9dms4qpWLpKfiNEqkE9VKpdNS3VEhl0kz2PLmXCqlCqoRyD1MvzZZmYx/uYeqkBukF6DzpJey2QPoy1jRKjewZ6WU4mRqpSWqGQ3hNeg1XuZ+plQySAa+nTWrDXYkkRu5w6uFwOvEs7nBSpV7JiX36pD7c5Zbc7DmpX+pHZUAK4l1wn1NF3mYSJTdWkMOpllZLq6Hc5zxPPqda+paELkE+p4IcTo30jvQOKt+Xvo+nc7dTT27nNeldaRh3cc9TI/1Q+iHWvC/tgn4A55MsXZD+A/qf8DzJ5HleIM9TJ92WbmNn7nmqpL9If8G7454nmTzPK+R55pLnqSa3U0Fup4rcToU+BQ6nGg5nHKslh1NPDuc5cjjPw+FMgAt6VJ+FlRPhcCrJ20wiP1MHPzMNTymCn0mGnymHVuiroDXwMMnkYZLhYV6GcveSTO4lmdzLC3AvC0cdC/cqi+FDlpBjWZq0FJX2pHY2J6kzqRNqS7JB7Ul2qCPJAXUluaA8i24cZdGNoyy6RyiL7hHKohtHWXTjyPmoydt8JXlSch77UvL85K+wOcmmZB9bSEl1GnI7Gjic6XAR3MNMJw/zpNwBDzNVfkPuBKlz3zKVHMt0OJYezB1yL5yDR/agwr3K47Jf9qMyIAfhUrg/eYL8yXTyJ0/Cn6xE5WtwKU+SS5kmvyW/hfXcn0yXvyWvx9W34U+mwZ98G7txf/IE+ZOEM3mcnEmJ/D35e9Dvy9+HcmdSTs6kWX4XzmQGnMkO1H8o72Sl5ExmkDOZSc6kHM7kA1T2yD9mT8l75b1Y+VP5p6hzf/K0fAD+pEQ+KB/E1SNwJqXkScrJkzTLx+UPcfWEfBJ17kxmyh/JH2El9yTl8q/lc6j/Bp5kJjzJJ9jtApxJLjmTUvmifBHP5f6kjPzJ0/J/yGA8SgcspjzSIvmafB0VnhSYJ9+Qb2LO8wILKC8wj/ICiykvMI/yAh+jPNJc+a/yX6E8O7BY/psMAqQEwXyAOQiQcgQfo2zSXEoTnEzZpLmUKVhAmYLFlE1alJKakoY6zxcsSBmfMh4VnjJYSCmDj6VkpWTjKs8aLKaswQLKGiykrMH8lLyUPFzliYMFlDiYR4mD+SmdKZ1sKjmxJ+DEwuTE8POQsjxlORzaCrivJ8h9zSTf1Qzf9S3M16cMsVJyXzNTNqRswJwnFxZQcuFkSi4spuTCQkouLKDkQg1TTbqVEwL8yuqV7FPGjEswjBhmDBuGE8M79lXlGMZXBSOGsRJjDcZ6jI0YWzC2Y+zE2IOxH+MQxlGMExinMM5iXGBC6DgNZrxMQwiNYJzB/BrGTYw7GPcZaxUwJIxUjEyMbIwpidfQWvB/+Vqc2Ku1bHTweyox5tA11lqPMT/xeumeLYn32NqEsQhjaaI++lUInaehcuzC2Iv5pbFaYlzFuDE6P4Nxe3R+LzHCbHSIGDJGBkYWRm5ibTif1rPWNgxr4nNqtY995om1RbSOtbowfBghjPjoe1iVeF64dPS9rsUYwtg0en3r6PWK0VGNGr6Prfz9HMA4PPZeEu95L8YBjMMYxzBOYpzGOIdxEePK6NfrD339Yv0tjLujX8+N3nf3oesPGGvTYCRhpGNMwMj5+1f+/WvLwyj8f/4qhOv+/r3i762tZPR7/f87sv/7oJ/vlYnn0M9VdmIdPffhUY5R9fevY3sk9hXC81CvxWgY/fnDtbYFf//a1oyxWDOu5WL3/IERY6yHkYqkMnRlTwZ0TU8WdH1PLnRjTz50S0/RwAi/K7jUuL2nNNjWcqW7aeBMy/XuRQPnjTt7Kkirx+Z7euoGzvOrQWvLre6lA5eM+3vmDVxKzEf1bnfbwFXjoZ5G0oXQozQ/SvMTPUugp3qM0LM9ZuiFHtvAVX5X0A61Yv6g2z5ww3i5xwm91uOF3uxRBm7wetBl0HS7Bm4b7/TEoPd7VgZ9hqRu38C9VqFnDel60o1QqbUemtqzBZrZsx2a3bMTOqVnz8A9flcw1FrQs1/ZaEjvDin4ZHsOKcwwoTuuiFyDcUNO9ypFbi3rOQqt7DmhyLwSXJWoj2pe91olw1DYPaRktc7pOTWm9T1nlSxeD64d1ZLuTUpu6/yeC6SXoU00X9RzDbq05ya0recO1Npzf0ztDiE41OpySMFNhvLurUp+q8+RquTTbkWjlZAj8wvlleBWQ1X3sFLaGndkk075Ys7rwWFDbfcupaJ1laNAqeDz4C5DraMY84buvUp161pHGWnl2HzIMQe6yVEP3eqYDx12NEF3ORbRfKlSze8N7jUs6D6g1Bmauw8r81r3OtrG9ICjLXig9bDDqswzLO4+pjQaWrpP0muwk7rG5sccPrwSU/dpZWHrSUdoTE874spCQ2f3OWXJG4eWhUjjpKugR5ethZ5YNgQ9tWwT9OyyrdALy4aVJfyuQd8bl5ftGgwZHN0XFaPB031FMb9xbdle6M1lB0j5/M6yw4qZXx2MGwLd1xXxjfvLjilip9B9fXBVQg2R7luKrVNadpL0NDSV5qk0z1x2Dpq97CJ0yrIr0IJl1xUbv2twLfQu5iu6HyjOzuJlt6Bly+5CK5ehwuuDQ4bVdo3i7Zzj41rvSxrcZFhnT1KUzvm+dK6dcZpPgDb5cqCLfHnQpb5CaJuvBGr1lSsKv2twa6fdVzU4bNhguKTEOl2+WiVm2GxPV1ZyDecbttknKGs6fb4GaMi3QFnDK4O7EvVR3WHPUdYbdtvzlI2dcV/zmK7yLcbvDuqDe0d1n71Q2dK51tdCahqbD/k6oZt8DuhWnwc67AtAd/ki0L2+FYMHOg/4VgfbDAftJcr2zsO+dYOHabedo5Vjvg3Qk1x5ZfCY4Yi9XNnTedq3mXTbF3NeHzxpOG6vUvZ3nvPtUPbz+eDpzou+3YPnDCP2WuVQ5xV88lDfvrH5dd9B6C3fEehd33HoA9+IcqhL4zsDTfKdVw7xewcvGs7YG5SjhvP2BcqJrnTfpX/QCb6rygnDJXuzcspw1b5YOduV47tBentsnue7p5w13LC3KBe6Cv1sTEv8onLBcNtuUi63nnOsIl0LvUjzK44h6HXHJugtx1boXccw9IFjl3KZ3xU83KZx7A0eM9yzdyrXjMzuUG62JTkOQNNJJ5DmOA4rN/nV4EmjaPcod4yi4xhXPm/Lc5wMphple0C531boOE167h/mJY6L0HLHFWiV4zq01nFLuc/vCp42ZtgjQcGYZV8RlNoaHHehCxwPoM29Guji3qSgZMy1rw6mtrWQmnrTg+eM+fZ1wcy2zt4JpDmkecFMY35vIeaO3hKop7ccGuit4nWsv9gW6a1FZUVvQ/CKsci+IZjdtrp3AXRdb3Mw21hq36yc4hq83rahd3HwlrHCvg3rN/e2YIeKXhNXVC4m6qNabd8RnGKss+/Ga9vW2wndQbq714FPhtfvtu3r9eD0pLlxnn1fsKDtYG+ANDKmR3pXQI/3roaO9K6DnundAD3fuxl6qXdb8EHb1d4dIQ32ORgsNub27obW2Y9AG+3H8Tpv9O6D3uZKlYvGhfaRYFnbvd6D/115PQTb2nskWNAu9h4PpRuX2M8EK9vl3pFgJZ+HJhiX9KJiNNrP0/tK6KUv5u0ZvVehWb03oLm9t6H5vfegRU4GLXWKeO/83rtGs/1ScI7RZr8arG+vcMr/oNXOjGC90Wm/EZxv9NpvB5va6xxruTqzxnSeMzfYZFTs94KL2hud+dCFpEucRVCjszSUw5kklNdudlaAT8AGocJ2m7N64Gq701kH9TrnJU7wUAk/B0Pl7YqzUcltjzkXKrn8JApVta90LuGnktMIxVkTqm1f4zQrFe3rnTacL/h9CTW0b3Q6lcv85za0oH2L06vcb9/uVKA7nbHEz1iomX9/Q4vb9zhXBguM85xroPgcQi3t+53r+Wfi3AhNvNNDzi3Qo87twSY6ca50lftlnD6881/vqvJnKLauWn8WtMGfO9qfb/EuN3i3a4E/X9li2OcvgvI+86Cr2V/Ke46/AopOEtd0LfZXo3u0+OuUs/STf7H9hHNnyNR+yrkn1Nl+1rk/5Gi/4DwU8rRfdh4dON9+zXli4FL7TeepUABrzmLNHeeFUKT9vvNyaIVJcF4LrTZJzpuhdaZU552BG4YFzvtKnSmzTwhtMGX3SaHNhsV9qUqjaUpfZmibobAvO7TDUNI3Rck1FfQVBI+ZivuKQ7tNZX1loX0J3jBV9lWGDprm9M0ZGOFEETpiqu+rDx03ze+bz78LfU1fnOympr5FpEuhi/DaRkxL+9pCZ0xtfdbQeZO1zx66ZLL3uUJXTa4+X+iGydcXCt1OMG2r0BcHxSU4iijFFOpbBXYlbjTF+9ZCV/UNgeL4z8a91rY+qGlt39YwMw31DYdF06a+XWHZtJWvNGj69g7cNg33HQhnJMjNuLHv8MCIaVffMfyOE6Oa9vadHLjamt13euCe6UDfOTzd2ncRn8PhvivQY33XlXzTyb5bYLDhvrt4Paf7HkDPuTSh1cY7riTsf9GVHs4yXXFNCI3wTyCca7ruykn8bIfzTbdcedjnrqtQqTA9cJWEizo0rvJwaYIwO5JcVeGKjnRXbbia/16E6zomuBpA6WD18LyEduS4FiQIPNz4kC4kXUJPMZKaO/JczQNXOwpdiwdudJS4WgZuc6IO2zrKXabRuZPUy3+/wsroJwkeDsdIV/JXFV7TUeXqDK9JzEnXd9S6HEpGR4PLAx4GFYc3dixwBRIMHN7ykG4HqbqU/I5mVwS6mCun1vDOhHa0uFYkSDW8p8PkWq2UdnS61kFRR8Xh2pCg1lDt3zW8n//Whw+RHk1oh8e1GSwKIg2f6Ai4toE8waXhUx0R1w6lsWOFazfU4doH5jzpOgi25N+XswntWO06Er7Qluc6jt9u3plTO9a5RnB65rnOYL7BdT582ZjrusRPBNfV8LWOza4bwVsd21y3wzc7drjuhe907Haz8P2OfW4xIoz2durexiVuOSJ1HHRnoBt73VmR1EQn7Djizo1kdhx350eyO0Z6GyJTOs64iyIFCQZo63SX4iygU6bjPO/biTO645K7IlLccdVdHSnruMFP247b7jqceuhakcq2Efe8SGXHPcfpyJy2de7GYLaZuRdGskfP5W3uJcFUs+g2cpZwm5XLZtlt42e626ncN2e4vcFMc5ZbwXPPu2P8/HKjB5pz3WtQz3evD2a2l7o3fnFSmIvcWyL15lL3drw2sEQ4w1zh3hka4e8uMt9c7d6T6LTB0+Y6937sM899CKcAztxIk7nRvjuyiJ9TkaXmhe6jkTbzEveJiNVsdJ+K2PnnFnHRPj6z2X02EjLb3BfgcdDDI/EE7XANtST0C6qxeyKruCYqkbWkQ/w1RDaRbjU73ZeDgtnrvhaUzAqnEU4moRZzzH0zMcd5B8VdOAsiw7zrRobNK913ElwR2TWqeBehZvMa932cFzSn9zVsXu8RglPMGz0SiAJcEdlr3uJJTVAEXtWYRobatnkyg8Xm7Z5s6E7PlMSJj32gkQPmPZ6CxCkfOWze7ykOlpkPecqgqKNy1FOZOOUjxx7Sk/ycipwmHSI9Zz7hmYOzGyd45KL5lKceJzXO8cgV81nP/OB88wVPE/SyZxFOsUbP0uAi+syvk94a/WSuedqCleabHmuw3nzHYw82me97XMpli+DxRe52mfzz4kldnf7GWGOXw78Q6vEvUdZ0BfxGxdwV8ZsVsWuF3xZPxxonrq72e+MTutb5FVzd4I/Fc7o2+1fG87q2+dfADW32r1dWdu3wb4wXGtb5tyhK127/9nhJ1z7/znh510H/nngVTsz9ypauI/5D0RVdx/1H47VdI/4T8YaEOzAc959S9ned8Z+NL+g679sdb+665L8QX9x11X8ZPu6q/9oYh9/w34y3dN3238H8nv9+dLeNBYS4ySYGpHinTQ6kxh22jEBm3GPLCmTHA7bcwJR4JOFAO+cHCuC5Ek6HPIUtP1AcX5FwebYiVJy20kAZPBfO+vjqzq2ByvjqrsLAnPg6W0WgPr7BVh2YH+/sLOYrDasDTYrXVhdYFN+c8FlvHAos/cLPJjymbR75yvmdV7jjC7SNPX04YIWSV7I1BuxwTAmP8wAe85Btof9muLpzTsCF/ZcEfPFtNmMgBJ+FTyC+w2YOxEdZZa3NFlilbLE5A2uVszZvYCi+26YENsX3JfygLRbYGj9oWxkYjh/hnBM/blsT2AVPDWcdHyE9Y1sf2ItTAw4a5wU0fp5rkDx1/BJ/SvxqQm0bAwfwjrbAczlt2wOHFS/3v/Ebtp2BY6Pz26T3OC8tZ6OfJNzrcnFU8aqWy7Y9gZPL5cScNMO2P3BaWW87FDgH9woPuzzLdjRwMeFYl+c+pPmdxwJX8ImdCFyHnuLKPWZocUJtZwO3Er5yeZHtQuCussd2OfAAijoq1wY0CY+5vPQhreAUt7yatC6htpsDSXCO8I/L59nuDKTDJ8JFLm+03R+YoJzqFgZyoNJAnnK2O3WgMN7Cvy/LF5IuMaweKInf6M4cKFf2d2cPVCknuqcM1GJlwUCDssQieUKRB+Qd6Dyi3gXPYkn1xKMaS6ZnVTTJKHrWhjMs2Z4hfnZ4NkXTLVO4Yr41OsFS4BmO5kB3jWmxZ280z1LmORAttFTiLinh6SxzPIejJZZ6z7FouWW+52S0ytLkOR2ttWTz/kl617LIcy58k3fLaAPpgraI52Iw07LUcyXabGnzXI8uNlZ4bgUvWqyeu9EWi93zIGoi7eR9MuoY9VbQqMfi6tdEAwmfZfH1J0UjllB/enSFJd4/Ibrasqo/J7rOsrY/DzrUXxjdwHtmdDPpNsum/pLoDmh5ULBs7a+K7rYM99dGdyfOFMuu/oboPsve/gXRg5YD/c3RI5bD/Yujxy3H+lvC1dRFJcvJfpNitpzu74yOWM71O6JnLBf7PdHzRlt/IFhvudIfCc6xXO9foexJnFBco5eMCk5DzPtXR3wJcutI718XvWq51b8hesPI+jdHb1vu9m+L3rM86N8ReWAp7t8dzbNq+vdFS6xJ/QdjzJrefyQmWif0H4/J1pz+EWWNNc8zFMt4eDdrYf+ZWJa1pP98LNda3n8plm+t6r8aK7LW9t+IlVob+m/HKqwL+u/Fqq3NXharsy72irF51havHGu0mrwZ0E5vVixjVB3eXOWy1ePNjy20BrxF0Yg14i2NLbGu8FbEjNbV3uqY2brOWxezWTd458Wc1s3expiXf39jinWb0RuLWXd4F8ZWWnO86PnW3V5jbE3ie2fd5zXH1lsPem2h1dYjXmdso/W41wsd8SqxLdYzuHW79bx3ZSTTOM8Lh2W95F0PverdGNtpveHdEtvzf9j7HqiozjPv9965M4wGJ0gIUkIoIYYQQqwhlrKUEmvR4PyTWGJdQ82UufPvzp1h/guuJWrBQ61r0TXGWmNc13X5iGWtx7WWEmNdYy3lo4Qay3r8WGpdYwkf5TOUuNaa73meewdHJI09u9853zntec7vuS/vfe9z3z/Pv/t67+ger28DfmNNaVOnh9V3bBj06OqPNuo8yfWdTSc9qfUnm854MurPNMqe7Pqeph7P3Pr+pn5PQf1A04Bnvr9vQ5mnuH7wG6WesvrLTYPQchhaLqofa7qs3MVTWT/RNOyx1t9c3+epbuCbxmw6d37jhGdVg75pwlbWYHg5x2NrSGu66XE2ZDbzHrkhp1nvCbnXNett1Q0QnT31DYXNkMs1FL28wtPYUNKc5mlqKG/O9GxuqGjO8bQ2GJvzXEUNVRvGkDcXKk/9np0NK5qLPHsaappLMHtpLscspbkCd1GajYrF0Q7GFnWn4k7rOKHuFdDOQHOVZ39D7TfyMb43r8Bn8OYa1MbmWmV3iPzDdU9bbBfIp0zM09HgfvmcK6/B//I5dfeG9lU8R/2BZrfrWkOk2a889Xs6G9Y2R3Ct1y9nPJvDjXH/hzHud9wE47kb3O+ZwH3Ec0zHa3kdm8Hfxyez+/gUfjabxT/Ip7P7+Uz+ITabz+UfZQ/w+fwT7EH+Nf41NkdTqVnKMrRLtM+xTG1IG2ZZ2h9rf8yyDUDs04Ycg4XlGKoMNcxqeMnQzF40bDO8xTYazhpG2PcNo4YJdh568zwT6H8/MLD72Qw2m1Wz+9gKVsuWMZF9i9Wwv2VbWRNrZb9gm9i77Fesm/2am8l+ySVzs9hH3P3cgxzH4TdOenxvkpvDreJcXBbn4TZxBVwLt4Or5HZxr3EvcP/C/Zx7UfM9zfe4mBARotwaYb2wkWsQWoRvceuEbcI2br3wqvAdboPwuvAPXJPQIRzmvikcE37IbRHeEt7iWoW3hZ9w2+h7zB1Cv/AL7lVhUBjiviNcEX7D7RF+K/yW2yf8TviQ+3t8i447oH1A+wD3T9pfaG9xbTqtbi53Tve47nFuXPeEbh73O93ndKXc7/ELD+4j3Zd0FbygW6Kz8DrdMl0Nb9B9TSfyWTqnLsTn6KK6Rv4p3Td1W/nP6Vp1e/gv6F7XHeSN+OUEv1zXofsZ/2Vdr66XD+r6dAN8SHdRd5H/G92Qbohfp3tPN8x/Hd/H4jfoPtCN85t0E7pbfEsSS5rFb0tKTXqQfz1pTtKj/D8k5SV9lj+c9MUkmT+ZFE7azo8kvZL0iiY56dWkPZpZSW8kdWgewP9XVTMn6QdJxzVZSZ1JP9Zk4/tAmrykd5MGNAuSLiRd0ZQk/SbpQ81ifZ7+iKZa/8GMRzS/Mvze8HsBv5eTWQvwZJaNXxsvOqxCDyhkeXJt5XXZXVG59HzFfNkvR+S1lUPyenlThVzVKh+Tu+RTFZ3yWblXPidfkIfkK+aZ5lx5izkmb19sXOyWd8l75QNyu3zYnLu4ArRKAB0fIx3/HeO4j7iPGA8ancI0cO5hehOV8W/wbzCO/x7/PTh3mP8+0/Bv8m8yLb2JquN/zv+c6elLsBn8L/hzbCa9g5pMb5/O4n/F/4oZ6L3T+/nf8r8F68A3S1M1nIab/F+DtRodS6cvxzI06Zp09ilNhiaDZdKbog9p8jX57GH6KixbU6YpYzn0DdgjmoWaL7Jc+ipmLr2z8Rj0P5lLpZlDzryn2TrvaW+3t8973nvRe8l71TvqHffekJl3XNbJyXKqnEHIlufKBd5Reb5cLJfJi+RK2SpXy6tkm+yUZTkk18uNcpO8WW6Vd8p75P2ENrlDPip3yiflM3KP3C8PJJJvhTwoX5aH5bFJmpBv+nifPoEMvjRfpi8HavPuoBpfHrQt9BX5SuSbcfKV+yp8RuBIVb5aecznhrZ+X60v4lvrW+/b5NsCMvN82327fHt9B2D83AxZ9Rr4zfpsmpMMIA3LAhJYHnucaVkhUBL7DJCelQLNYGVAM1k50H2sgi2mt8tN4HXwu8v72V+zVSyFrQZKBb8jsgeYGyiNhVmEvrhcS99avkxvlH+DZYI/2sYeYq8CPcy+C5TN/pEdZJ9mbwA9wjqActkPgR5lPwKay94Eeoz9KzsN/esGyqf/DfsJNsD+jRWw/wVUyH4N9BR7D2geu8Y+gL5fZ//Jnma3gJ7heC6JLeBmgu8rpffHPw++L4WV0fvj5Vw29wh7lnuUe5R9ib73rABvWEVfdK5iS7ivcjb2HFfL1TITvUtupq87LZzMyczK1XF1bBkX5WKsivs6t5EtB9+5ia0E7/lN9tfct7gt7EWulWtlX6WvO1eDJz3OXuI6uU5m505yP2Yid4b7CXNyP+V+ytzcz7ge5iH99YIXyGeyvkBfwOro7byA/ml9EQvSG3lhfam+lEX05fpyFqUviWL0/t0avU3/Ndagt+vt7G9gba+wCdL9YvxlCekooBNwEnAG0KOiX8UAYJB9ReqUTkpnpB6pXxqQBqXL0rA0Jk0Av+nlvXoggzfNm+nN8eZ5C71F3hJvubfCa/RWeVd4a7y1XrfX741413rXezd5t3i3e3d593oPALV7D3uPebu8p7xnvb3ec94L3iHvFe+I95r3uveW3CIL8kw5RU6Xs+RcOV+eJy+QS+WFQEtks7xcXgm0WhZlSQ7IMXmdvBFoq7xD3o3/g6i2VuuBIPhVw2r6fYXF/236bQG6n7Q8hbR8Nmn5A6TlaaTlD5KWp5OWZ5CWZ5KWP0RankVank1a/mnS8hzS8lzS8kdJy+eSlj9GWp5HWv44afkTrAeogHT9SdL1QtL1eaTrnyFdn0+6/jTp+jOk658FXedZMen350i//4p7mMsGvUfNLiPN/gJpdjl9H/EsafNC0uYvkjYvIm3+Emjz18EGXuZeBhvArySeI22uJG02cn/H/R3YA+q0mb6PsJA2W0mbq7ge0OPlXC/Xy76sf0H/AqvWr9KvYi/oPXoPfq+dsj5lM6xTMsz9fYwLrga9KwKUAMoBFWqdEVAFWAGowTphtrQgWOzt/+OgNgOhc1JpsExaGFzkHbwTWCctCVZ6LwOGQxcQkjlo9Y79cWAbaXmwWloZXOWduA38W1odtHlvBm0yHxqSxKBT1v9xUBtD6IokBWU5LShLgWCIEAvWy5mAnJCfynmhEbkwdE1aF2yUNgab5KLboL9LQtelluBmufwTUBG6JRvDgrQ12ErYEdwp7Q7ukasUYBnHJq+4DRrrvuB+uSa4H4+Eg8E2ufaTge2kQ8EO6UjwqOy+E9LxYGdcbiKkE8GTsv82pNPBM/eCwOrYbqk72CP1BfunxfngACIgxvYhpIvBwXvCpeBl6Wpw+C6MBscQASm8VRoPTtwLAoHYQelG8CbCy0I8QRfSIwKx2CE81vmj7V5bqNabHDJ4U0NpUxFYFzvizQhlfhICG2PHSUZ2KIcwN5TnLQgV3oH5oaK7UBwquQNlofJ7xqJQhbcyZLwL1lCVtzq04i6sCtXcARz3PUCOhGd6nSG3Vw75pwWck9eGU+T14XRqFwpF7gn1obXextD6u4DyNgG2hLO8TaFN9wJ5ezjXuzm0ZRKtoe2TwPO7AHvD+VQ+EJ4nt4cXeHeGdlF/p0A+HC6l8p7Q3k+CfCy8UO4KL7lDxv7QgTvQFmq/C3jtqbDZ2xE6LJ8NL6djb3jldP35WBwNHfN2hrruwsnQKe+Z0Nm70BPqTYR8Lrw67tsTfXHcV076uAthcdIHDYWlRD8yqSeJ6xpfl/gcXQkHJud2JBxL7BP5khbwKWD7ga2KDwjsUOyX7Gp3KJPiBuh7YB/gYOxEXJ8Dh+AI98Hz8rXwOvl6eKN8K9ziE8JbMb74ZoZ3YD2OzZcS3u1LD+9D/+rLCh9EP+nLDR/y5YePYAzwzQsfR99OYwZ99y0In4j7Z19p+LRvYbgbx+1bEu7DufCZw+fRd6JMwvLwRd/K8CXf6vBVnxge9UnhcV8gfMMXizCcX4pBOJcwh751ECfVeObbCPFHnWdfC8jZGtGhDDq3I5Ls2x1JxbgzGWsT1mhSJkKNKfFYgH3C2OjbF8mgvh2MZMfXmdqj74e1p7gMMY/GdigyF+t8RyCGlyrAeI3zewfMSlzGeEXxGO4Tj8V4JID+0NimxFi6F8B3PNiIwBgbj6tx+E4EWxGTMRJjphobE2PlHTFSjZNx+E5DHIQ1ptgH8dDXHexEkN5inDuhYNJnAXx9kQI6no/M912MFFM9+A/fpUiZ72pkkW80Uukbj1ipHm0YYwnaLdgR2pPvRqTazyKr0Bf5dREb2UXcDlS/SLoFctDP+ZPBN6k2QusFfguvj/vAu2xril1N+pd4/0EG+k1/asSJa+7PiMiT12N7sDd/diTknxupx377CyKN/vmRJvLhOB4Yg784stlfFmml6z7J/6j98i9S/XjcxjcltFH7TGOd4o8nx4N+OI6Pu9fH+FN/pXq0hg7jmCYx1U8m+kr0j3EfmegToS3JwTZ4DubAXx02B47ETgeOx7oRmNvgelNecyLWR3Xgs/z9UUPgdOx8PH8JdMcu+psiJ8mPQd4R6ItdopwCfJq/IzLsb4x0xnOCwPnYVfJpGP8xb0BfdzE2ijE6cCk2Hrgau+E/GbkZGF3DAuNrdIEba5KDbE1qULcmI5i8JptyMtVf0rWYm6l5E+U88RwFZaky8Fwwdc1c9JfYr8ncLp6Hjd/2wYR4DqPmHigL87FgxpoCzHeC2Wvmx6+n9jAe+hvmi+wExhacu6aY6jBvjEPNE+/A1FxQzf3ugDqvU/O6SWAuFsfUvC6eo02TmwULFHxiboa5V2L+hTlXPO9KyLGwr3QttlHn5C7bAvvzr4rsvMuubJE98RzL74zs98uRNvRF8Xb+UKQD9dpfHzlK+hT3A9gGbQ70j46bI2f8rZEeKu+M9Pv3RAYQifbm3x8ZRB/hb4tcJv08Ghm7K48B+DsjEwTQRwTZIfqtM1Gejj1RfdwG0Sb8A9E0/2A0c9L+0AddjuaQrxmO5vnHooX+iWgRxp44cLz4jEX2B2P234yW1PHRcpIN/qNOH62gcart6wxRY11atKouM7qiLidag76oLi9aW1cYddcVRf11JdEIxj+KgeifICeoK4+urauIrkd/XGeMbqJnFoiFdVXRLXUrotvraqK7cL7qaqN769zRA/icUBeJHsZ5qlsbPYbt69ZHu+o2RU/VbYmexRwQ/X/cN9dtj/bW7YqeI4A8jDOo23V7oxdw3usORIfq2qNXUM/qDkdHyIfBOtYdi16jc13R6yTjVPQW+vK6szGhrjc2s+5cLKXuQiy9biiWVXcllls3Esuvuxabh/Nbdz22gPwYjv9WrBSPASG2EPUhMDO2JJASMwfSY8sDWbGVk/oDOTjmH4Hc2OpAfkwMzItJVK/63MCCWCBQGovR+oGdBBbG1gWWxDYGzLGWSV2NPwfEYxSUA8tjW7FNYGVsB9YxnnGGTYZWxv7yLyh/Rv+CMsKu3f53AHGCyY5MR44jz1HoKHKUOMqrBUeFw+ioAr7CUSNOKOTIQThqHW7xpkIOvyPiWOtY79jk2OLY7tjl2Os44Gh3HK7e6jjm6Ko+4TjlOOvodRhU2k4457jgSFNpyHHFMeK45rjuuOUUnDOdKc50Z5Yz15nvnOdc4Cx1LnQucfBxghZm53LnSudqh14hp+iUnAFoF6MeYo+wJZ7D+8EdcJ9/Vjvo9tL/ln1QC9jGMqDZtA+aSvugD9A+6IO0D5rO3Exic5gMlEm7oQ/RbujDtBv6adoNzaHd0EdoN/RR2g2dS7uhj9Fu6OO0G5pPu6FP0G5oAe2GPkm7oYVgcz1sHusFepp2Q4toN/QZ2g39LO2GFrP32G/Y59j7QKW0J/p52hP9Au2JPkt7ogtpT/SLtCf6JS6by2YVtCe6mPZEl9Ce6HO0J1pJe6JLaU/USHuiJtoTNXNf515mVm4Dt4E9T3uiy2lP9Mu0J/oC7YauAEv/AfsK90Puh2wV7Ym+SHuiX6U90ZeEzcK3mI1+abBWOC78kIlg12eYU7gq/Ia5wX4nYC45Vs8ab+uqHUZsP2+/aL9kv2ofBRq334CJ14nJYqqYIWYTOUVZDIn1YiNQk7hZbBV3invE/WKb2EE0VywQ54vFYhnRIuKVohV4tbhKtCGh3vBPgt48pepNKt0fNYaHNXoctAd1RYD5LwLtQV3Rka4kgaYsBh3CPfMZoB2rQIdQP+4j/UimffJZMC4vaBJqQwrowjbQJ9SDVNCCg6BPqAFp7PtAD5IGpJMGzIH1Pw16i/vhn4I1/zfQMFz1h2jVs2gP/GFY+WGWTWucw6XAGj9Cq5tL6/oorehc7iXOxh6jFX0cVjTA8rkYrGgB7XI/yW2BVSykVXyKVnEe7Wl/hvsBd5zNZ5y+WF+WsB4Fwmx7wVQS14rr7fPtxXES8+xlKi2aSuIme6XdqpC4xV5trxa3Q80UEneJe+2rgGxATiTxAB1leyhOYru9/m4SD5OEenujSk0Kicfsm+2bxS7grXeTeMq+075nkvZjW5XaVOqYSp4Oz1H7UXtnnJxj9pMqnZlKnk57T/xenpP2fqD9UDOFHAvsE/YBILzfIJI7XzTA8TJdQeQYvVu6/Yx7CUk4E59Z+7BCnjP2MfuYpw34xN3k6YHx3Zwkq8hPkl6haWbqrNgrGsS0STonZhJduD0TcRKHxBwxL0604lfEwik0ArgmFhGVAF1X6285BODlkyOy2hsdM8WKu8mRIhod6WKVuALJkSXWKOTIFf1QUyvWOvLF2gQ5k+SYZx8W3ZPkFyNxUmbfPggrAvrtKCXdrXQsdCxBHXOYcSYcy1E/HCuhtJpGW+gQHRL1SKKxKpJQU/pplXo8A55B0obLNPvDNNMjjgDYznyYv2J7mSNmb3Osg1k2ODZC/1ocW0GXbY4doO/1jt0i79gHutxa2+I4KJbAfbeCnjRB20OOI47j9puOE47Tjm7oMep/q6OPRmmDFTtrb3KchxZWx0XHJZCFVksjopaKreDqNtmrHVeh/6Mw5nGo3wztisHqNjtuQGm+Y7WT2cucOmeyM9WZ4cx2ziVbrlbIWeCcj/bqLHaWAS1yVoK1yorFOq3Oarob3Mm5yt7ktKFNOkEytJSdIWe9s9HZZN/p3KzaH1pgm7PVKYOuGUjfMuHsTtEoljj3iJnO/c42Z4dY4zwK6wur5djq7HSedJ6BmSsUK6BPO8VeZ4+zH1oPAA2KRc5O0kAcJa0VtgMCjcFZcl4GDIsVYMOtzgmojzhvunjnoEvvgnu70lyZrhxXnqsQ5lpyFaG+u0pc5a4Kl9FVhToOM0tr7lrhyAdtK3HVOGVXLZDb5RfLkeBcxFXkWgsjMIor4Mx6sca1CfUUeK1ri2u7a5drr3Ou64B92NUuul2HQR/9ODbXMVcX3LMWNDSC4/OM2Y96JtwieIaTnpuwPoMwngrQl1aJl/TgBdokA3iKM86drhEpzZ5h76ztdlVJmVIO2jXoDMyWlCcVSkXONqlEKgcNRc8xAd4MZ6fN0+npVFrYW919UgXIQn9HGkwtFS8DGgyy+iWjfadUZe+QVtjPiDy064T+jEk1UDrqqpFq7Scdpa4id6nklvxShLyg6smktR7yrK4ST7+nX1ovbQI/d1nxddIWaTvdDe4k7bIPS3vRmwEfk/ZKB6R26bA7XQKP7qpRPBf5Lr1nWOqStog10insiesUrBPqTo3rrKsX9Uchx1bo9xnXOfRJrguwxkNiFazOFdCrQvAHha4RmOsDrmtiueu665bd6hbc4Hfsl90p7vTa7tpudxas4AHQmzF7vTvXne+e517gLnUvFGudgzjv9qNiiXuJ22wfcy93r3Redq8G69kMDkYS/XD/QYiPV9wLwYIN4LNq4UzAHXOvEzPdG90t7q3uHfZGUe/e7d7nPmjvdx9yH3EfFw3uEyDV4D7t7rYPgORBdx/0yQB9Oe++6L7kvuoedY9DH3tAtt4+Bi1veJhHZ9/sSQZvkwq2ZAW9yYBrCkFXSjzZoL8jnrn2Dne+a8Q14tjqGrIPOvs9BZ75nrkwD7yn2FPmWeTs8VR6rJ5qzyqPzeP0VIpGOMrOCU/IUw+tG91bXb2eJs9mMeJp9ez07PHsd2/1tDlEyqae+ssT5p/RE6abBeithnT832RsbYz7Gs/SbAeA2oEOAx0D6rJ1rQKynbKdemngpQHbWaBeWy/VnQO6AIR1Q0BXgOC6laMrR20jQNds+AzLG6yGZXCPFHqiYfREw9OzjIZyXoGeZbT0FKOjnDeJnmL09BQzg55c7qMnl2TKeQ2U895POW8KPbPMpqeVBxiXIqb4aUz03qFtAeNsZjiWwnG5MLvyoG3JvcBohOMhwJGPwXEFxhoFlSfuEacB3dOgT4ExAsfz9wbjejheVHFJxVUFSweVo3EXYC+URwHjd8PYDscbnwzjMUAXyGUqdIDkO0Fjm4KlqVOQ8ScgGzB3GhRMIxcxfwqK7w1WmPelZYBFH4NKBdbzCpZa7xHVgFXTwKbACuu21HlvsMLaLpVVhFTUK7BeVY6WITj2AxoBTXfDCjqwdPMnwzquymhVsROwZwr2T4O2Kej4E3AU0DkNTgLOTIOeKei/NxivwHHARvYxLeCccQRwTW13+R4xDBibBgOqzFtwnLg3mAQ43rwNI38bk21S1GM6IAvO6W/fKxGmXPX+hk+GKR8w787rjWlTkDkN8NoFcMyBY6l6XDh9fz4OxjxA4TQoApRMg/I7YVqS4L8T/W3cX6p+zGS2TfoX03Lbnf4jrieJ66rO9+QcrUyY29V39mnSpyT6gLgNq7aFMSOu88sypuj0hHLeJAIkQEDxERhfTOuUehyTaSOgRfGvNlwv8JOmHYDdSgww7VP9+w1F300wJ3H/bIKYZjqijNd0XJ0HkIn+EmUSUC6spwn8ognmzgR9MKHcq+r8qvOJ11KcjMewSwnzDHLMTJGB58wQL8zJar+mrtOUNZqMKfF1alFiozlV6Zs5I+H6G8pY6O8jauyDv83Zat2hBByfBlPjct80OJ8QXxNi7CRGEzAlvk7Gy/9KnMy23RkLC2y3Y2BCvJv0WQDzIvUIcctsVW0M/IcZYpIZYpAZ4o/ZqdaDDWP8ILtdotiTGeKMOaT4InO9aheqHcT9IuoWykE/R/4pbiMtit/C6yd94FTbmmJXcf8yaVstav+b1DXffPt6ag/2ZobYZN6p9NsMMcmMMWhQ9Uk4BohB5g71uk/yQVP9+HRt4n2exh9PntPfxsf6uk/ypzl34i4/megrixJ8ZII/pLY5apsSZQ7QRy8D/VlWoABzG1xvzGmWzVfrQFcsFVBGP6bmL8sgNzJPqH4M1nQZ6laT4s8sOPc4X2pOsKxS9WUY/3eqfg71D2L0MpC3DORZoL/LQG+WgbxloGfLUCbo2LJG1X/G/WWHmpvF86bQbT9KslQZ1McmxV9Sv6b64Sk+eDKHifthHCfKwnOgU8taE67frI6nWJkvyrlgbMt2qnVlCaicBlNzQds0UOd1al43icYETM3r4jnafyU3O2q7M/86abuddyXmWDb12s6EOZlqW2B/5h7bXXZl7rdN5lhmtOtBxRdN+qvLil6bh1V9itdjmwlV//AIfsWi2p0FbMxiUJBob5Y0xUdYMhX9tORNk8cALIUqihSQH0T5Jeqx/LYNok1YINZZqhLsD9pZVij2ZoEYbakFuJXYEwf5o3ZlnnDMFj8gosqGcVjWquNU21vgmc6yCbAFsN1GvsiyCwDPcJYDgHYl/iHIT0JOYDkMOKb4Y0uXoqcYCy2nAGcBvep8nQNcUJ4TLFeUebKMKO0tEDss1wG3lBwQ/X/cN1shBlhnKkB5FGdAt60pyrxbIQe1Zil6Zs1V5hHX0Zqvnpunylig+HIr5IhWyA+t6HsgH7NCHmaFvMoK+ZRVVObXKql+DMZvDajHmKIPVsiFrJADWSFGWLfe1h/03ZgPWCEXskIuZN2n1qs+1wr5gPWQIh/txApzZIUcwHoiQVfjzwHxGAVl62mljbVbqcO3MWadmvX2X97G+HPaKxMKhNP4L6p8N/tnxpJyAHmAQkARoARQnnCsABgBVYAVgBpALcAN8AMigLWA9YBNgC2A7YBdgL2AA4B2FYcBxwBdgFOAs4BewDnABcAQ4Ip6z5GPOV4DXFeB7W8xpheUev1MQIratxH1CGPQpwOyALlK/eQxHzBP6at+we0x60sBCwFLAGZFjn65cj/9SsBqgKjWS4AAIKbI1a8DbAS0ALYCdgB2A/YBDgIOqccjCcd4++OAE+pxn3rdiYTzpwHdgD7AecBFwKXbR5wf/VXA6J9wjM/FuDKPfypoDRJRpQDl03oNqW2vTsEN5b+djx/j18flztABktX1hvoZqbePMzIA2eyfTZUmq6natMpkMzkJsilkqjc1mppMm02tpp2mPab9pjZTh+moqdN00nTG1GPqBxowDZoum4ZNY6YJ000zb9abDeY0cyYhx5xHfxcCFZlLAOXmCrPRXGVeYWo115jazLVmt9lPiJjXmtebN5m3mLebd5n3mg+Y282H4e9j5i7zKfNZc6/5nPmCech8xTxivma+br5lESwzLSmWdEuWJdeSb5lnWWAptSy0LLGY8TzUL7estKy2iBbJErDELOssGwktlq2WHdNit2Wf5aBJthxS6QjQdOXjQCcspy3dUO5T6bzlIuES0FWgUcu45YaVWXWEZGsqxIRPTfuLC0z9xQU9/eLCTPrFhWT6xQUD/eJCCv3iQir94kIa/eJCOv3iwhz6rYVPGXIMT7OHDM8YKthTBrvBzZ41yIYgW2yIGBqYydBoeJk9b2gyNLMvG7YZfsReMLxpOMHWG84a3mcb6dcXDv5/3DOOS+UC9L5KJ/5v8rlFKsCz5JarqFBhTCgjwGpyV6hlbFejlmtVuFWA180Fr5sLXjcXvG7uJrXtFrU91m1P+HuXetyr4kDCPdvVvw+zJ43dQH3G88aLxktAV4lfMo4CjRtvmJhJZ0pWyNhtSjVlmLJNc6G2AOqzTfNNxcZLpjLTIrBJskrjONil1WSDtbqffmmD0W9s8PQbGxpDkaGICYbFhiVMa1hqsLAk+r2NZMNLhlpYB4/Byx42hAxhlmNYa/g6yzVsNHyD5Rm6DF0s3/CW4S32hGHEMMIK/h9L5269KHwJ+CrQDu7WfVSeSeWnqfw0lZ8RKoEv0EaovpbqX6XyFuBF2u9TuZLKyrVPU7mKrv0M8HlUv0Dwkxy8tojk1wjPINe+iO8+addCOU1YhFwbBX6E2ryO9/0Dlf/wJvVhI9V7qfwMlZ+h8gKltypfSzxIbUDmH34lPAl8SB3Rk3T2ReoVjVT4KxqXh3ruxrJmgMp6Osvoqv9BNT661kQ191P5Wbp2DUm7n3ryLHEttSmmNk7g86k8n8pFQinVS1QuJglUT/wZOltEZz8nfB651ks9KaWWWH5Gc43aKPOwhaR1kTRci88IbVSv8BLiy6mNSDKPkUyYDf55vCP/lNYGvFkL1s3HqPws8QFtCHgjtuF44q9Qe+onz5BrnNTyFa0d+EGSORtruF9imfuAzm6j9oup/bepnEbSPiA+RO1vCD+Del54G/hy4RzeBcvcb6nGKfwSeBm2YRPIOSPx/yT+JnKNhlouJTkvYHvu1yShjcrfo7PPUfuPqH0Bla8QP0X8X6j9+0IdtDRr/xXK11FveZ32LSjfwnquVtsN/JIAmsBnYhv2vnYD8N8h566oNcA1RSQnk3gWXesgvo34HOEjOvs1KP8cOX+Ryl3E+4i/ItTgGuneJ36MeDvxFuKjyJMy4F4LlBWkls06/A2VWio/S3yWytuJtxDHa+dQy9N09jDVDFBNI9XsU9Ydy8CPEW8n3kJ8lDi2X0ot19FVTOHa76BWUPkV6vlBKncSP6jWtBNvIT5KvALGclLbQlrkRk53/yXxD+jabSo/RrydeAtxlLCNZuPb2Eazi/i3qc8fEB8iOUPYZ+59bQ/wceLva18jHiD+EnHSBO0ISJhD63WdWg4RH1b5BtKBU6gbVHOLJNwiCbdIwi3Sikt09hLVXFJrOoFraCyPaE+TzvQQDxB/ifg7yEkThhQdwzJoGkp7h8rvQ06PfYAavlTlMBb+J6ilfBbVZFFNFll3FkoG/jbxTtLMQzDGtYp+kuRW4tvUa9EuwqTzc/B/4oZ7vUY8QPwl4m8THyGOMi/StRdpNvpIWh+VX6Hy6yrH2eumfj6fhNJmKVzRNCofVLj2R7SyAVpHPPsBld/XfQFnWOHYK0Y18EyLPJPq+2hl+6jmCNlIHvEc8kJPk39r1uUDf5nq3yNfNE7l7RhBuP8gnzZL8YfYkpupdQF/gLxZE/E5NBsd1KaQbOFdKj9PvE31gRBfOJLPJyHXvYOrr/sWzoaWfKlgwznRHceyrhDLmquk222kJ0WkvT101XHtEbxW6KBe4VlJ8ec69JxPIgfbPEc2dY7sCK3jMSpvo7P/oY4xTP1x0rVvUPs3aJ7Jw2iv4vwgB1+NXFmvp3QQH/kYtZ9F5dPUvlH1Hu3kB1owOpANOqn+FeKziT9Gd/kl8Y+SKnE1kw7RffHsYlxlsFwsp6kcZX5W9cl7oZxBOvkO1eQQv6B7CNeX/O3rpM9fIb99FL2otp90sg9bavNJ9/RYA2uHOpyG/pzrUawYnpUhItC69OMMgx/oJB3rJKtU+NtkL53E36YIgr46E6+F+XyLrtpAFrSB9BDvEsVeaZbiWc1SxasIkKtwD5ONL6Krjus+JP+A7Uuwt6DJWHMFLR00/F2MLNTzItX/bKCWeJcDxLcRP6V7HMu6vyXLXYZRhiz3Ip3tUrlioViu1j1JZ0eoZoT6jzNcrHsHfR319jWMhtz/pJiYSb39A9V/n+b8YSrn0FguYabEVwkov1cwAL+K2SP/KeSwXhvIq+Cq7aYx7kVb0zxNcfAJ5JocAWr4n5Lk71LLD0jyv1P536n8HMnvwZkHjpKN1Gc/cnaYysPEv6KdyTCvQPmfp5UqIAm9SvzFPAryhK+R90MN30zZy7Ag0ShQ3x6ls7up5+/Qvd4kaZk4UuEXOBtamhPhQ1rfGMZ3TTpK07yLZeHzVF5C4x2lUXxIvuJDssRM6id5e74Le6hZQGOfofYWe5JL5UIBclfuJzTqHwiQDXILqW9n6VrSdr5UkNHG6apqzIH5as3/Br5DWAySy2kdjwoi6if/XSifI2nvqRylvU5yPksyiwQB+K+Rg9Y9zDArgxnQJNE8/BNdFSLeSjpwVcDZ6yAJ+cRfJTlWKkdp7K/RPC+iMUp01XvELxL34IxBloWj2IhZK5RnoFZQDPKRtFrqZzXJ0Wl3ogdQtRFH9yPqzw3dXOTaD4i/S/xNqs8lbkSfoOSc2JKfT7xU+3/ZO/c4Hav14a97rfu+ZzBW0hDj0Jicj+OQkJwaZhwSoiQpxyQ0OZONpMKWKJWEJJWESpRzEkMSkojKtstWW4WYZMs8867rez/782Z+v8+72++7/3t/H5/P97mea13rWmtd61rrvtf9PPM4xHVE5DbRXSh+PoU78LMDPzvw8yX2A7AfIBqdjaYpmo7RXavI6rz0xPFzuAl9GrLYF43ubGllU0Tuo9rip63U1d2Qu0Wy+HHchD4NlkNTlvzhfgOf3+ItFy6FK+ByX66AmfjMxGcmPjPxmYnPTKKUKZ5NdbE01YnAVjxsRV6DvEZG4aK6kP4L34nGK7Lr20L8LKTWOTyIphH9/DXOXaws6UOXoA6rVWbnYV/uNrfETwfSynb/IGuW04FYquhO/jj39qU5BWTBj/BWGv/n4UG4nLrdYRvqrkX/HdztuywN02Rc4TKhP0hs/D3BOrfSaSscFsh1qiexyiYC/8DeSlTDZazruvT2U/LkWzgrfk45xOzkkJOHmLVDRIb8lFXmIlBZZiq42nE+ZyKNZXksP0WeQutNo3xjLl4XjTHMlEHfFvtv4a9wKczhTn5peIJWRJMv8+LmV+QTcTLXyGujzBGNy4R2zGA7Ztydo9UU85k7V3YMighDd27N2ysrMW9v4GbZvMCd0i6Jid9Yrjt+f5HN2/Bp9Evlfsx/kV0Re3dvLPdF11C3PfdF92P5gZw3/R2ySxvOj6abnJf9YpS+Q61XhAll0JfEwyW4HPt7yJMJMhdmjcTWHEXOhPWFfqrMkZ9GbkzF/n0y6rAwWIJNfbIiRSzNNGb2J+RBlFajtBTZkoGH6Ky6HGbRVnPuCl7kCthGIma+5Qoylb1xG1eNHLk/MYu4I53JNWgx94fj0TzKXc0p/GyGB+Dn8DB+jsM9cDTXpsNcZ9cKgw+QJ8B17K7nuQY9Lvdvfg3u4g7H5XfhMjgVnpJSOXkFJ4l/WyyTYOPwDsfoRMYJ0ayLcxmcCsXD21iOodYa0TiKppNogl5kRU/udUfD9jCbO8Nh3H+24UzKHaxfmfzZQFtYmqmyl/poHGUU3+O5UpzvwmVwKnTegmpyJg3fJ2d2BCVdrSJ4WwT7Qs6nfjJjH4v8bpzvwmVwKqUyrrESK3+TyAnlwudhd/FPLT9OiQ9nBLNc4mCac9c3Ps4FMBveDckluXMLCzPvd2HZRvbGoFKww8mngw8cn0d/MM5seDfcDutIvlGagyYHzTS51zVvygr1/sS9dHl4IxzNvWUq56DG3LvW5K54Jhk1moydKfeBug2e30Eey+l1NX37Gv3X4sdvT/+PisYvE+cCmA3vhrK+qkiv/GvkDBu+FuW8rAh9HG9F4CLuECaxjpK5f3iQ/J9P6eE4F8BseDfcjo2Lp19BWgk+kOeKjmKzjlrrkJOJwHmidCRYxlooL6URObGekBOr/71ogk3SE/9d5NPIPnniYz8++IFZiCin171yenXRkKzY40+ib5KxCnkdPV9HabSLNoNFgmRHJfMVlA47O3mx6IMKZPLXcGx8L5WdZyN76WxspmP/OivuJ9ZREXbURuzA85A3yA7s8srVCrYwLzn45PRqnsLzELzVQH5Xzr/uhCul2VhuFCZukgxPVJy2nsMzz0wSot3+Y043U1mhJ1lBa1gd10FOx2YFHl7Dm/IfdbU24uc96ZvPcyqfE7GbC7mG9ucsPFxk5+EUPMC6PgUPsFpPwQP09h0nP0GLa4nSJbkHMC+wO+2APn3bIGdk/2U4Qmh4cmJ2hY/J9Y5VPBt5DfYvUvcJVvpU0YQDZTcI70f/AfbHYDe4KDwvTOghVzpsXpHMSSiDXBLWx9sl7OfQ58JydfCLy3Mqv06QQv6IrKVvwY8y+35x1s746LxJPiwPdkqeiN7/Nn6mlieWyzjjNGZdZ8o1IiGLufucmbpB5LBwUNSVXuCatU5OxC57ZU/IkNKELK4si2Q1uf1qPdzOvrQeyjW0Hc+RaqA/iv4o+tPoj6M/jL4n3r6mlejkNZ4r4wG4TtoNjsmIQp7HmlWcuBdzjZsr9vpDOV+7Xe5uIvwrfZZ9qbGctcOirPpTrO7NQhfJ3ewzdeiJcA+lRbgvKiJ3Pm4/zGMtLGDHkNIJcGp895Bah9g33pdzt7OZh34e/We/Cic6+V363Nov4/iS0E8l/m8x0i+ZnVHY3B63FE15zkEfyRj9K+WMbHiqbKJT2xec2nayJz9EHMoy77U4lz1PtpQK3F4UJlLrV+4Q3pTzeDDIdycLfyZ77FDqDqXuDOSl0pa+nhb7MC8vcurvx4ge54R7gBXho3lCTuV+Dfp5J/ZnaJFeBVOQx8vZ3DyAHNkMwUNDeJfcL7n7RlmV6/yr5bpAD78jz6PTdEsyIZOx1zEb3bh6iJ9wBBwn9Bf5K9g5ZUXcJHIwJhhDrySeXbGJPu/YxG4WSKkZLlexwMNPMeK/jh6+IuducwT5tJzWTV3kTDmtmzcYyxXSk4AV5N/ul3aahfR/kjntONG4TPBPyqc84cvcE/aW07obnfSnjJzZzXR8Do9TYlgU3i7n9GAdvEPOEeY3GXtYkgi04wz+DbXukXO6KYG8mdJc+vN3ergK/c98lpEqkQmr0nozeDfjHQwbxu8t5apamlq75eSuP5OTu3mc+JTm+eExetgbtmN2pjGP7WXWXPY66hVoytLPeZxiZsPmkcwJZTZrbTYnndlyqnKl7iQSVOGOeguWj8A1waPshyJb2D4iHtrjoT0eMrE8xVmvhmj8GmgOoZnnuxn3qKsrwsc4L9/KeflWTmGNOd89L2cllwnOXg/E8jAtluT+sxbeakldPwP54YhoHhZvjpvQp8FyXNldZIJPGd0g350KzXx8NsZ/NLpm8CE5e7r+Mwp81sBnDUZ6ipGeklj5t4vnMCPYDx+RLMLDWxGJTx/kLOLQPOxArIS3cH4/Iud3N4oO8uzL/5R2O7CCvsTDObx1kKuV9MrtPMIX/EqOvfzJTj+GHZXzsjtfS+k0WBZNM3+Kk7N96VstNOy3fjnm4if4s9DsEgZ7hH4t+LDUDWrTSgl8toVN4BK8TY1ihYfTsCoRHguHyI6XsEMikNiReF7g3Hc/T+mHiJwQctXrLaVBFSK8C8sM5P4iJ+wQb4kd5c4kiHEebMy4otxoxCxnMC/zkZPx0BSbN+T5gLlH4u+nMAtvkRsV5CpmTsjozArkYsgTsDkKa1ErDSYzmyWlbrBYZjxYgr4+lq8xy9NE1j+haRw2hHMk37AsLbPp8uRR9kDhPnwuR65En5OJ4UOid5YX6O0FViif1Oe/rjxl8j9CXiGfZcN6+a8hV4NT5VPyeOnrcDH245AjloKz0Ud1VyKvxNty+DWar5G/wMbpded8eSJaCz4KR8Hm8As4QehpocpFUw8qoRmA/Ax8FV4Zl+VTg0PUPYdmNmxNrSeRkyk9Bi+ioRXdBc1p5Mh/U1o/Dw9T+g+4CW8Gm7awG/pv47L0YSmaFWgykfOpVR35BNwK18AfsOyAfAE5RI7BUvCbWHW5M6Q/2KtfRGOiyJSFKaLxGLV3O9yL/ivkjXAfNlH0OsdaOg8NorkQWTeHC+GiaBaQ60EFn4GvxuTudEsUf9F4b8JzlH6C57nR6JCvjiKPTQybCtFY0ByjVyeQP42PpSXjSnR1x1F3vGgU8fEmYlkv1pFRzKPn8+jtPPomnI3mHPwBTQWhiuSyMAUep8XKMBXWhd/RVpSBTyH/DabEWjl2Rb6KmZ0S5aTo9UrkmjE5fX+O3AQ9WaEThCGZFo4W+uvwkCcRCIeIHOxirl+NIpP/gnzaiP2fo9zA21P04Vds/kGsOsuqdGuqFPkvnBXNct5ZWXGMdFScGqY6Xg2bwwmUTsDbBNG4eIq+Dfp6UMWZKtcF5GfiFMuORPtQPPKpzMJCKHJr0ZsnKc2l1nX0MMrwXEZE/L0j0Yww0hejfEbuh81qorQ/2j0kVv4BIhat32TkskRmK/ZbYy3kqRTyKPyMRF4gNKxi05YMvEDcZlPKbHrl0P8gMfQu0eeQ6KUwokSiFBO6vIpkGSOx8v4MozzsHWcqdRfiR+z34nM/pa9D4qnOMOqTcAH8JP8qxzzGWBjN28jlkFOZtU7Ie+j595SWFtntGEudpgWlw+E8ShcSAbLd1EWOVnqKRExXQx+tiI/gC3juj4f+eD4Yj5LI0c62m3W9jdX6HbPAruL5RP4G/EQ74R749/z6EknkXdEeiOV0LK+N9kBa+RQ9q8+fxNrZgfxrfqbrZ3QdWcxu87nEyr8BuQ36U/j5FZmdUBeCNWBatGax2QHfi+9O1zlypfB2YrM6WtGQHUDPIUrNsDkAo32DvNVcF1xU3ZnCsPa91+AwGO0VVeFzcCT6Ecit4CAycCz61+PXAsnnyXFZIhBdO3pizx6i+0TXFGYzJP6l4Gy4F26E7Ofe28xXPvIGeJG6+6L5QiaS3mnkAbAjUTqPXJTSTchtYbfYeekh+m/xOQuugMvj6zdqSzJ/B5l/nhXRDWai34rcCPuH8cZ1x9tO6zFygyujx05uSmO5iWxB9s6zGx9EXo6+O3K0rzL74TIyqhh8hB2G+5OwPN6iHakbvV2TP18+Y8JDfuzPjNfRy4EX2Ye7sJOsgL2wvMg+nMRYoutUcnxfTSW3ZWdoiqYp0WvKrnIefVHisClO2XsNlm3jFA9LKV0RZyrXncHEMJV+yr6USuluuIa6nXjGmMsz/LI8aSwbvuMsk+LfrpFvpzTiOzl5PFuuJt9y9PYK9TI+/93O2ZMnVN7ffPlmzhZOZHzaojPCIrLS+QRnj8j6A+Sz/hecVfnMS+7PVQ9dWeZFnkiY6v590rr/stxjiKxP+T9LNgrNWf9VJc+XnKX6SugNpFaWMFjGM40Q1vbHy9rEw1Lf3feanni4JKVhV2p1gQ34fsIFmOinyIybhyRiZpvYiKwnyV+46MFCk22O4s1Zqp1CLy2qhWa/0P9R6EYhXGyekFHgJ0OeKuicyA+l3YXBZDxcgEfhdLjKyPOc6kK90cjpPlXO9foCmuJBD/op3yJLEo3aL7L6SujsRd4p9kFT/KRSK93I9/cqm7ky+2YxfVsuz7SptQo2QVNV7IPN1Doe74mUdkez0IyT3QZ9szjle0R+3NtiiRJ9e1dk7xj9MdoTBrnyqzfIWmvReJsplW8g1/e+4Ruz8q22Tnq6Yy156qI36idl19WPS8/1K7KuRdaP6cccJ2j5dFuLvTcbdhGa+7F5RvNdRz3LsY6Z5vg2ck3zGn6c7J3Dkrq6NXWfRL4Kb+ckS72/0PpFfZWsZS1Z0V2Xop/FJP81n/Lr0Gla6itkLesqspbF3usIOwvVL0Jj8JCFt266tOyZei8+RT6vv5WrBvJyLDvgIUbda5BPwA88ifBq+nDSu9ZZ1vbkCafbF53mkiefMud5uXIt0Omyr+pJfGovvyz7g3dM+iP0WuqSotFr5crl/U2uubAsrC103hzVt8izYHHvKJZHZaUjf+WNk6sJPvd6SxzneF/K9Uh6or7Dwy/SE31JKfkWun9GGCYj/xW5KN9OL4J8Pfo30Tg//kuh8+n3gBnwR6H5Hq4QBknoLwm1D59AUxWbu4ThISyrww6UpiH3Qe6O5Qk06P3pwoTyyFUofR/moqEV8zFyf+RJsBOayXCM0KO3uhmlHyEfoz8hNrPhMkq3I7+N/BO8Bd6BnhGZPOpG3nbDR+B98HMsGyAzLvMbLT6IvI3+HIQn0byMt37UaoTlLvQVkFciLyAma5FHwxdhNWq9lOCuPmGZaHZE9n+E+dEciRwkobmE3CKaIzRPRTMlsrkL9oHZeOsVzRe1EqJZQyYm4elo1rBfAU9QmiZMKI/mffpWB8sZcFAUH1q/iR5uiWIiGndNFDmKGHH2F8OmtEi0vZ8pJZJ6Ix7IumAOzMF+EdwPb4aM2o8ybQH9nIB9JTwQ88DSB/JHVyb3CmF/HJs3kJtjGeVYK2iFiW9I3cQS9NNgk4mH92Ay+jKMuiqR2YX9M5SyRvwD1KpIW8TWzInWHTE8RF1i60+HVfDzDjbp+CeeuiV1V6NnlQVRrg6krWgllo9yDz+fIGOpp1HrB2yehlGGED0zLMpk2q1ArFYKvZ/RvEBbUR5eB2+Anam7D7k+HurB7+A/0D9GW32Rb8UP4wpoPWiI5Uz8zEUm8pr9wV8CR8Fu2EQtfgajDNlA6f2QeTGlafEBSOQT0PjnaHEc+mhPYw360epm5QZXoCkO2RkMWWHwpqOdil1Fn8Geuv4I+Dpcij7aG5HNXjQ7kI/SOnllWDv6LLXIuiBaTdGINmFTGPv5aKJ534y+C0yB9NmwZ4ZT8Rn1iqzwv4SsKZ/c8Oh5OJFaD2F/EZmV6I+HX6BnTg3xD3qiZ4/y2bV88kGzq/sD4Hrsc8mZSeRPtF8tg+xFAevIPIIm2jlPUTeaU+bdMFMhuWTuhKw1MwuSvQl7hIlkRcD1KyDbQ6KdwNhDSn3sDXuUaQxvkdaVkjOI/1JMPi3qATPgj0LzPVwhDJLQXxJqHz6Bpio2dwnDQ1hWhx0oTUPug9wdyxNo0PvThQnlkatQ+j7MRUMr5mPk/siTYCc0k+EYoUdvdTNKP0I+Rn9CbGbDZZRuR34b+Sd4C7wDPSMyedSNvO2Gj8D74OdYNkBmXOY3WnwQeRv9OQhPonkZb/2o1QjLXegrIK9EXkBM1iKPhi/CatQtQ918bFogP0VpNnIv9AmQsYSnYR1KZ8BB8CZqbaHdsvQw6jnj9RfDptRl1N7PlDIivZG6zH4wB+ZgvwjuhzfDqIfRjEfjmgAr4YGxBxafzKOuTA4Uwv44Nm8gN8cymutWkFqJlCaWoJ8Gm0w8vAeTKX0Gmcz0D2BTEc9ExtB/8w6l6fghMrol+tXoyd4gyoGBeIsyPMrVT9Bjo6eh+YHSpyGzo4mDGQZfwFs0j9fBG2BnSvch16dWPfgd/Af6x/DZF/lW/NDzgFaChljOxM9cZGKlWVn+EjgKdsMmavEzGM3pBkrvh0TSlKbFByDRS0Djn6PFceij3YDs9aN1Qc4HV6ApDllThnk0eNPRGmc96jPYU9cfAV+HS9FHuwqy2YtmB/JRWicTDBmuz1KLPAminI9GtAmbwtjPRxPN7Gb0XWAKpM+G3Sacis+oV8y7/yVkFfjMvkfPw4nUegj7i8isHX88/AI9c2qIf9ATPavbJxM0O6E/AK7Hhqz2o53kFHI0U8ymIf4hGWLuhOS8mQXJvYQ95D9zHbCfB+RqSAwTGFFIqY+9YX8wjYXqS31YyVORPa60YvQcw8x0mizO3QPkaYNZzJOEtpQulL+NNany/TQzl2cpWjT67+hnil6+YKHkry1E01MY7Bf6tdHnUjeb0u+F4TDkATALb6ciS9rtHn+aUVHJMwo5Gy5E82j8iUdt/rZOnqK04/nJRZ6HJPNsZDn6JVJX70MzgNJnkTUeTsFRcCljTxLqSUSgqzwh0Tk8tWiA3MC8J3XFRuXzvOKq+PMTR/VXsQnq4acLtTJ4QtJENN5V/nynLxl/NrKcZyDLeR7iGHsqX55TdcrfI3svcnc52+p9InutkXtQmoG8CfkLLMcjJyI3ofRDap1EUzzyhuabmJz0a2JTnFrpsA+lByNSmoJ8kdLn8VAR/SvoGyJXpzREvhf58agPInuHoz5QOkbkWJf88y4TKqNZpUo7HkFeKLK5grN8vtA0g2fRXESei+VfhMF+oe+h13A5pYlCLxf5FEzHXmEzE1aHUygdRR/mIPdBXkqLP2AzDnknpYPxUxj/W+GSeM+lJ4PQrEWzEU6HjNRkUWrRTIpt4H9hF8+bY/IkMBXPQ+N9EP1XMkemmVB9Rd2VcBbeeOKhj6PpKjZ+5Zh8V605pS1jrznGVAenL4ZNXdHoM1Gf8bxY+hCWQ7NJZG8W+i6xtyU/xd7fRulBKXVjl9lJwnMX9KXw+ST9L5N/0fVzMr39hb4dkVpBNmM5gX4RWTdBankNaWscchp+0mOX+AThksQTThe6uynhMTRlsTmBXFxobqJXDZi1HNoag+cB9PCYMPSJbdUoQ/K7SdaJjS4uGvn9HbdDssr8YjKWsBT2J0QO2mCThKZHlIdEuyytJBGZ4hIx7zFG3T0mz2YH08OlyIVjt0uOxeRp51WwI63nEI3WyH3E0sulVjryeSxz8DALeQb6g0RjN/rKaM5ROhvNEbzNRtMcy9NCt+MwX1Ee0v8OjOWv9OEYmRBl8hwZtTsFHCVKzDucxEzlYh/DQ23aakJpOvlzDH0jodvfZV7axm2Ex8mB/XjeF8U/Hg3peQZjOUasSqIvCrtjOTje7iXWxSVy7yyZEFlK3MqL7HL7LJksNr3gLDS3Y5lCWylY7qFWDjbz4FpKO8bXbz03lpA+r2aMn6AvC9+nPwMjS8Y7NBq1WLos4qk1GRXGo7qYrCYaEhlvIJ6fZR/YTPS2xtsSP/WYqZLRTkWtU9TaimWMbE/HcjWZmSxymKauINM2MOPS//nRio6vEfHWkzmqCO+hhz/Gd7zSXGukld3xNTvXlb4VrWXx5nbLZ+lVPWpF+6p4nsJT4lOqH3nVT67p+Z2dfBtZdxIb9gETraMZ1O2oPybzNzCbMsYt0d6I5UT0XYn8HKHblzawV8iuEs3IUphIaSqjbsV4j8KZ8BKeM5ivFjANtovbyC43IT6PsrM9LXumy4cNrKbXyIpLfJJ7iVy9RD5fYi5EvkDcJsWvYqXRyKjnMdKm0VWMPecUs7NRmEAWJXCVMd9j2Q9yjVNnJA/dPfDX7IFn2QNlh+lKP5uQpenk8D6ymr3IWS7GUuzfRD8Yyyzk9uiX0PODyMvRt4kdgNmsvrNyTy6txObmf8N8dZHVypzezLjSouta7EM+ry8hvaXnkxlLKpZdYtzzULesKu98psRn1sl5K8SzUvzOm/Ll73TiTxqFqjD6wqJXSjSxO+Vb1rEe8k34GH8PEiuMXBe5LnJ9+Z52rIF8l97ps9EvQ75bvj8m38x38nbkU8g/iix/xePqrpdfuUHfQL4N6Py8wW+z/MLv22wUyt8RKCV/5x5Llr/miCXL34PEVoWD5VduEh6WX7kROW+TyLHJ4ZPyKzcJZ8R/eFyYcBr5S/Gf8D3yb8iRTWdYH8vesJ/87o30Le9Y1OfwOewXI0e1TtLnXPQV0RcTJrRgdLXhacY7hdLVMAH99Vi2oq0f0e/CZz00TYhMpLlI6Z3YT6fFXUTpIpxI6y2xrEFdsUxHTkeuF+5EfwG5Bn4ifWV6chtyNeQ78HNImJiAzC/5JCZSeieaaXhbJ7+Bg4fr8VAXuS5yffl7eWf/KXJJWIJarelzPfrch1lewEh/oZS+ha+iuRtuh7mUXu1YJ+FN5LfwuRl5BjbvwKfRr0bej3xOeii/wuF6K3lYn8/lTV4+MnGTT9JjdfP+Lv3JYy7kk3enOSuleZskkpEmNhGmQmrhoW7eNiypm8eo8xYgH8fnh8gHkU9RSkblHUbzHX7kGzhKFfamJp5Upu/YYYNV8r3D+t+vJgzuPWKoWqXcye/WLq1SlTtZ5OerEipJhaqsulYVV7XVdaqxaqHaqdvVXc5HZ/WQelj1VfepB9RI9XjcvqhKUOVURXWVqqMaOi8tVXvVXfVyrXZR49Vkt3MMUtlqlJrK/zEY1bEq0e0ZlVSySlfXqxtUK7c736HuVlrdqv6kHlH91f3qQTVaTVMllWnbqVOWatfllptTVZ+uXdqnqrl4uZrfDL3G7c2Vnce6qqm6SWWqm1UPdY8yqrrqqiaoKWqAGqyGqTFqOnUKqVRVRcmV7kaVoTqqGurP6EupYi4OFVSKqur81leNVDPVWmWpW9Sdqrfrd03VTU1Uj6p71RA1XI1VM+I9uFIVUWmqjKrmPDRQzVUb1VZ1Uj1VHxWoWuo2NUk9pgaqoWqEGie/Zdq33vC+5jbYCw6AQ+EoOKFv78EjzGNwFpwHl8CVcG3f3sP7m61wJ9wDD8Aj8FjfvkOyzQmYK/Q1LAbLw5qwSb/B993rt4EdYJd+Qx8Y4neHvWA/OAhmw1Fw/IBhvfv6k+EM+CxcBJfB1XCzc9zb3wn3wAPwyOChI4f4x+AJ+CM8Cy/AmDDwBz/Qd3BQGBaDpWB5VzgsqAirw3TYEDaFrWDWA+KnI+wKe8B74AA4GA57YFi/ocEYOAFOyRb9dDgLPgvnw8VwKVw53M1RsBquh1vhTrgHHhx+39ABwVfwG/g9PAVz4cXhQ/pmhwoWhsmwPKwK6w0fnl43bAozYAfYFfaE/RzrhYPhCDgeToEz4BzH+uF8uAQuh6vhRrjNsUG4G+6HX8Cj8Dg8OXxkn+HhGXgeXhImaJgI7fCR2cMTkmEKTIWVYU1Yb4SLZEIj2AxmwHawE7wNyt24dntP8r/xatw6L6PK/l9JHj8c+n9m4HaMwO2iCSrxP/bO510ke27XK8iif5DG7XNF+M3l/xfJc7v3f8/if5iaGdHOq7zjaY9cH+Qu8Q/zyj/Mcv+Fxf4wU+mp4dX7HWUEv9fZf0njrlQlVal/U7oaSbvrU9q/9XqtqvhvvVZSlf+NV89dSf81/3VMPHcF/9e84g+xrrvbGOGu+nPUErVabVMH1HGV6/leslfRa+BleF29ft4Ib4o3x1virfa2eQe8416u9nV53UGP09P1PL1Mr9e79BF9Ul80hU2KqW6amHamhxlkxpnpZp5Z5tagtJUY5azpWOB9nwLvZxR4P/N37/0C5aFb5l+oBO937ws3uPx90uLL69vzl/tP7nH5+xLqcv8lkgu8r1zAPqvA+54F3hcYT4kjl78vWbXA+04F3o+5vP9lF11eXm7j5e8r1Szwvvbv3rv1Vym9QPlk3mu3PxSPRlilU/RaNRq573KupNurKse1++KvR+Kvx+OvZ/476+qr4q8b46858df9l/eihr18lDXWX/6+zuTL7et8dfn7ursvf1/v3QLv117+vn7XAu9vK/A+u8D7YQXeP/u7LHNCw7kF3q+/3L5hgVn6L+V7CrzfV+D9/stnsfEeR+si09d7Rg3w5rPb9nH/lFupc5QXFAuu5FpRXIVJbW1OUpbdZrfYrU4Tej95Pzm7M94Z5XlnvbNKe794vyhjW9qWyrc32ZvcdVPyQZvWJkva08V1CaeRvyCy0h9T1NWs7d6XdKeRYWq+ylHH1EUv2fUh0fUqOamz0klZSV0c2ybd6tjO9b6Y25NT3Wkh3Z15mtrvldHFXJ/+zmuOdSctXcK9/4HXHHtQaffuC8cce8RxpxurZGiKSrPHXF+3uNK/8ppjv3GvW937b3nN+Z3l8bjl3+KWJ+KW38Ut/9nf9vS3A/29mf7+s6QjJbdQ0un3JXYXPdxND/fQw3+W7KNkPyUHKNEqQbt/bpkV0fLN7WK6mItqCRdVk9QmKdNFfYvdokLXp60uUsZZyKeR0VXfLS1XvzfzpZgpz7voXXSzlu/lu2gF2t334DfAb4jfBJ2iU1SiTtNpqpCuqquqwibLzWaRoE/QRyUF/YJ+qmgwIBigbDAwGKiuCIYFw1SxYEQwQl0ZjApGqeI21aaqq2yaTXNjqmgrqhK2sq2sStqq1p35bHVbXZWyNW1NVdrWtrVVik236fwud31V1l5nr1Pl7PX2elXeNraN1TX2BnuDSrU32htVBdvcNnezI/l2LflW0WbaTFXJ3mXvUpVtX9tXVbH9bX9V1d5r71XV7GA7WFW3Q+1Qt1Fk22xV046wI1QtO8qOUrXtGDtG1bET7ASVbifZSaqunWKnqHr2cfu4qm+n2WmqgZ1hZ6jr7Ew7UzW0s+1sdb192j6tGtln7DOqsX3OPqea2Oft8+oG+4J9weXnArtA3WhftC+qZvYl+5Jqbl+2L6sW9hX7imppX7OvqVb2dfu6usm+Yd9QGXaFXaFa27fsW6qNXWVXqUy72q5WWfZd+65qa9fataqdXW/Xq/Z2k92kOjDfNzPfHV2ubFO3uFzJUZ3sTpctne0ul11d7G6XXbfaPS67utp9Lqu62f0uq26zB1xW3W4PujXS3X7h1sgd9ohbIz3sUXtU3clvYve0p+1pdZf92f6setlz9py62/5if1HyO9+T3fqY7DLpCu8KNdFL8cqpSfzPqFO8Hl5P9ag32BuipvK/oU73HvRGqD97073p6klvrve8muX97P2snvLOe+fV095v3m9qjmwy6hkd6lA9q5N0knpOX6mvVHN1SV1SPa/L6DJqnr5WX6te0NV0NTVfp+tOaoEeoUeqzXq0Hq22uPuIceoD/Sc9QW3VU/QUtU0/rh9X2/UcPUfl6Of0c2qHXqIPqZ2mqNt/LpkGpoGKmVYmQ+Wbtqatp80Cs8Az/gj/Jc8P+gZ9vXpB/6C/Vz+4N7jXaxDcF9znXRcMD4Z7DYORwUjv+mB0MNprFHwWTvUaF761cG/vdOHHi3heLKlYUms9NunOpIX6zaL9ig7S54pOLDpDX7TaJppEW8FWMFfYa+21ppitZCuZK20VW8UUt9VsNXOVrWFrmGRby9YyJWwdW8eUtHVtXXO1bWAbmFK2oW1oSttGtpFJsU1sE1PGNrVNTVnbzDYz5WwL28KUt61sK3ONzbAZJtVm2SxTwfayvUya/OfU5lo7wA4wFe1AO9BUskPsEFPZPmAfMFXsg/ZBU9WOtCNNNTvajjbV7Vg71tSwE+1EU9M+bB82teyj9lFT2061U00dO91ON+n2CfuEqWuftE+aevYp+5Spb+fYOaaBfdY+a66zc+1c09DOs/PM9Xa+nW8a2YV2oWlsF9lFpoldbBebG+wSu8Q0ta/aV82NdqldaprZZXaZaW6X2+WmhV1pV5qW9m37tmll37HvmJvsGrvGZNj37HumtV1n15k2doPdYDLtZrvZZNkP7Aemrf3Qfmja2e12u2lvd9gdpoP9yH5kbrYf249NR/uJ/cTcYvfavaaT/dR+ajrbz+xnpov93H5ubrWH7CHT1R62h003+6X90txm/2L/Ym63P9mfTHd7xp4xd9iz9qzpYXNtrrnTnre/mp7xs5Tc+TRgr63m0jnw7vLucur+Xn/l+e/57ykd5oV5yiQ2S2zmVs9/Zjd2mfs/u/H/57vx/86+FLKvutxtefeFX/5Pjv1Pjv2HcswLBrn7+WJemm5g2vjdVVnVRLVS7VQX1cOdFwa5+/dx7n5gunpKzVOL1TK1Sq1XW9UutV8dUd+ok+qsu7NXXuglFRqjTKHhhUYUGsvryELjeB1V6CFeRxf6k3sd4aQJvI4oNJHXkYX+F3vfARdFsr1boXtqphMIKIjKgjk7YALjGjDnsIZVV1FUTKCi6BrBvMY1ZxBzzuKqmHPWNWHOOecI/9PH1sVd9+2+e9+99733u9SPOtVhevp8VfWdr6p7uvuj7e6IRhvlGAC2G+w3EG2kYxDabo7BaLs7hqCNcgwD2x32+wltpGM42m6OEWi7O0aijXKMBhsF+41BG+n4GW03x1i03R3j0EY5ehMGW2Mg7+YYCnl3xyjIo/4JRCag510dEy1kJlnITLaQmWIhM9VCZpqFyHQLkRkWIrEWInEWIrMsROItRGZbiMy1EJlnITLfQmSBhchCC5HFFiJLLESWWogssxBZbiEyHvzv6piJiMxBRBb9k4istBBZZSGy2kJkjYXIWguRBAuR9VZb+cVCZoOFzEYLmU0WMokWMpstRLZYiGyzENluIbLDQmSnhcguC5E9FiJ7LUT2WYjstxA5YCGyAhFZhy1lKyKy+59E5JCFyGELkSMWIkctRI5ZiPxqIXLCQuSkhcgpC5HTFiJJFiJnLUTOWW3lvIXMBQuZixYylyxkLlvIXLEQuWYhct1C5IaFyE0LkVsWIgcRkeOIyBlsKVf/SUTuWIjctRC5ZyFy30LkgYXIIwuRxxYiTyxEnlqIPLMQeWEh8tJC5JWFyGsLkTcWIu8sRN5biHywEEm22krKR2QU8hEZhX5ERmEfkVG4hcxtROQhIvIcEXlrthTzPY3meeNsWkOSix5nsbwar8lb8za8HW/Pu/JuPIr35H34UD6M/8SH8xF8JIxdrvJr/Dq/wW/yW/w2v8Pv8nv8Pn/AH/JH/DF/wp/yZ/w5f6EXMd+jRI/So/AFM81f5/KqvCphvAavQThvxUOJxNvyMGLjXXgXYueRPJI4eHfeHZRAD96DqLw370003pcPIDqfxqcRd76BHyIeemG9MM4yeBNF8pG+kXwlPymzlEXKKmWTsks5TM/gjF7g7DolXqnmJvLgfFAHcw/4ZA5rj4yp9sibahsgyTvA3kTykMxngeWUchLV+l4PKa2UTvKUvKT0krf57DvY47fvZSQrcZHcJHdJlmySkOySQ1IkVdIkXTIkF8lVMue7JPCtH5yC+RkmlZRKEU0qI5UhBmwrQrz4PL6AL+HL+U6+i+/me/hevo/v5wf4QX7oa4ibs2V8Lp8LR5xv/q6ZL+aLAe9lHHgUkNsB33eV3/t89Lmw12LYuoFv5Jt4It/Mt/CtfBvfznd8rY7x6PP4PDj6Ar7AvCOTL4GjL+fAznCGh+Doph/m0fMTj68e9St+IGZXLczMz/3N1oWfM1sDfE7uxNaQAWQgGUQGkyFkKBkG/Xo4GYFvFx1NxpCfoZePI+PJBDKRTCKTyRTo89PIdDKDzCSxJI7MAgaYTeaQuWQemU8WkIXAB4vJErKULCPLyQqyEthhNVlD1pJ1JIGsJ78AV2wkm0gi2Uy2kK1kGzDHDrKT7CK7yR6yl+wDHjlADpJD5DA5Qo6SY8Aqv5IT5CQ5RU6TMyQJOOYcOU8ukIvkErlMrgDjXCPXyQ1yk9wit8kd4J975D55QB6SR+QxeQJs9Iw8Jy/IS/KKvCZvyFvyjrwnH0gySYEGTVltVofVZfVYffYda8AaskasMfueNWFNWTP2A2vOWrAQ1pK1YqGsNWvD2rIw1o61Zx1YR9aJhbMI1pnFsTMsiZ1l59h5doFdZJfYZXaFXWXX2HV2g91kt9htdofdZffYfa6wB+whV9kj9pg9YU/ZM/acvWAv2Sv2mr1hb9k79p59YMksBSjIvNuec4nL3MYFt3MHr83r8Lq8Hm/Cm/LmvAXvyDvzgXwQH8yH8HF8Cp/OV/CVfDVfw9fzX/hhfoQf5cf4cf4rP8FP8lP8ND/Dk/hZfo6f5xf4RX6JX+ZXpOJSCfO9rdIJ6aR0SjotnZGSpLPSOem8dEG6KF2SLktXpKvSNem6dEO6Kd2Sbkt3pLvSPem+9EB6KD2SHktPpKfSM+m59EJ6Kb2SXktvpLfSO+m99EFKllJkXXYTZURZUU6UF8GigqgoKonKooqoKqqJ6qKGqClqidqijqgr6on64jvRQDQUjURj8b1oIpqKZuIH0Vy0ECGiJaRQSG0ghYl2or3oIDqKTiJcRIjOoovoKiJFN9FdRIkeoqf4EVJv0Uf0Ff1EfxEtYsQAMVAMEoPFEDFUDBM/ieFihBgpRonRYoz4WYwV48R4MUFMFJPEZDFFTBXTxHQxQ8wUsSJOzBLxYraYIxaLJWKpWCaWixVipVglVos1Yq1YZ777VfwiNoiNYpNIFJvFFrFVbBPbxQ6xU+wSu8UesVfsE/vFAXFQHBKHxRFxVBwTx8Wv4oQ4KU6J0+KMSBJnxTlxXlwQF8UlcVlcEVfFNXFd3BA3xS1xW9wRd8U9cV88EA/FI/FYPBFPxWvxRrwV78R78UEkixQ7sVMxV8wT88UCsVAsEs/Ec/FCvBSvlB5KT+VHpZfSW+mj9FX6Kf2VaCVGGaAMVAYpg9Veam+1j9pX7af2V6PVGHWAOlAdrA5Rh6rD1J/U4eoIdaQ6Sh2tjlGnqtPU6eoMdaYaq8aps9R4dbY6R52rzlPnqwvUheoidbG6VF2mLldXqCvVVepqdY26Vt2iblW3qdvVHepOdZe6W92vHlAPqYfVI+pR9Zh6XP1VPaGeVE+pZ9Qr6jX1hnpLvaPeUx+pT9Rn6nP1hfpSfaW+Vt+ob9V36ns1WU3RiEY1pnFN0mTNpl3Trms3tJvaLe22dke7q93T7msPtIfaI+2x9kR7qj3TnmsvtJfaK+219kZ7q73T3msftGQtRSc61ZnOdUmXdZsudLvu0BVd1TVd1w3dRXfV0+huurvuoafV0+meupeeXvfWM+gZ9Uy6j/6N7qv76Zn1LHpWPZueXZ+mT9dn6DP1WD1On6XH67P1OfpcfZ4+X1+AV59xRhZnRvuxWAYMivOds3gViO8neXWI76d5Y/49SeLN+A/kHMbQCzyCR5CLEPGiySU+lo8l1/hkPplcx8h+A+PWTYxbtzBu3ca4dYev4wnkLkaI+1KQVIwSnDdlsiIr1Cm7yq7UH2dGA2xXbDfpbeEUhehDnCV9pgxRpjGmzFW2ME9ln/KaBeBcaQjOks6DaP+UOEAdZIaYXwMU0FSIAJuBneEr1EGEGfuwtARL5jUaV5KOZFT3wPJpdS/kSeo+yM+pBz/vexpK24gdtIQX8QEFkPvj1SM1yVyvnoP8gHoB8kPqJciPqA/MTxppzSMa6cwjGp7mEfFYH/Con67ROGBpl6FAvsdQv9jigltccUuaL7Z44Zb0uMUbtzDigFpzQt0FMvNtScVZccJYBVaBcFaZVSYSq8lqElkZp4wjNiVBSSBCeaw8huMxeQE79i+KsV9G2P+/4+u/J8KaMfTvxs1/Zcx0E61Ea9FW9IIIZEbOYIiZ1TCa1YbINArjZEOIkWZ0/BgbQ/9mVOz9F/Hwj9FwCsTB3yJg6ujyf1s0/BztIC5OhvidOiqWAfVhao+PysPUHbVAebyxdMc7UB2NQHHMRM0RC4rjLbTa76Cl/mC2y0+xk3X8Mm5qrloazU1z1zy0tFo6zVPz0tJr3loGLaOWSfPRvtF8NT8ts5ZFy6pl07JrObScWi4t91ej7aCvx1vDYSiG+rei7pI/xl3DxXA10vwh+u5R96r7MAYf/GoUPg1xOEk9p15QL32Kx0Y6wxNj8oM/jcof/hiXDS8jveH9D0XnL2Kz9uHfEJ1rUEbTwlDWm+YkHrQWrUey4JXSnLQZDSV5aBvahhSkYTSMFKLtaUdSmIbTH0kg7U0nkPJ0Kp1BmtG19AgJYV1YJOnDurM+pD/rx6LJUDaADSHD2TA2koxho9lYMgGveU5hExmwPY7xZ3KNu5FY7sE9yDyejucm83leXoBs4v68PNmKEf8ERvyTOHo7JcVLR8hdOY2chnrJL+WXNL38Wn5NveW38luawQZw0Yy2YbaRNJNttG0czWybYJtMc9im2mbQPLZY2yJawLbEtoYWt62z7ablbXttR2l92ynbKdrMlmQ7R3+wXbBdoiGgDT7QUFsKaIMYUUQUp+tFSVGabrbnsuem2+x57QXoDru/3Z/usRexF6F77UH2ILrPvH5G99u/tX9LD9jL2svSg/YK9gr0kL2yvTI9bK9mr0aP2OvZ69Gj9gb2BvSYvbG9MT1u/8Hekv5qD7OH0TMOGPbTJCVEaUnPKqFKW3peaadE0stKd6U7vQdxdhq9D3F2C30BcfY1TVaZ+j0TalP1R9ZCi9Wusn76SH0q2/Hx/hYYjS7DKy5NaWtrzbpUaygpRmyW9sgOmqYQbJ8LycyXgSqYi9ZcSrSWEmHpAiTzLps8NA+0mvw0P4S7QBoIx6xIK0JwqUqrEolOppPxLpu9pIXsLWeQM8qZZB/5G9lX9pMzy1nkrHI2ObucQ84p55Jzy3nkvHI+Ob9cQHbK/nKAXJD+Sk/Qk/QUPU3P0CR6lp6j5+kFepFeopfpFXqVXqPX6Q16k96it+kdepfeo/clLkn8JX/FX/M3/C1/x9/zDzyZp/wz6yRwRWI40yDhrxXS4NUsL0icZIQkAXI5wNO8xLwvrQAkO6BaDHRiCUgKKQVJJeVJMNFIVUgGaQDJhTQijUEfNoPkRlpBcidtIXmQriSSpCU9yY/Ek/SDlB56JyPe1IW6kgzQR71JJupDfYgP3tPwDfTXWsQX+mtj4odXdTNjT81CO9AOJCve5ZCNdqPdSXbah/aBPj2MDiO56HA6guSmY+gYkhd68FSSD3rwWpKfbqXbSAG6m+4h/vQgPUgK4nxTIex5RVBTV8FZp2Y469Qc58K8U82F5cO7qYqzJoBYJubP/EE5FmFFzN+IsfKwpQqrAsqxDqsDyrEBa0Bk0D+hxAbKpz0ox6HKT8SujFDGEFWZp8wnrspCZQlxU04pp0k6JUk5T7yUS8o10NS91b7ED6LIQJLVjBAkF0SIWSSPyeekAPD5KeIPLH6BFAYmv0SKAJdfI0WBz2+QQBhj3SJBwOl3SDHg9XukOHD7A6ir3/uSH32pzNqBLz5f+BLEgmCL6RFntWBMI6FHMnpkA53XmAj0yw4qrjNxoF8K+qWjX27ol4eyTFkBHq1S1pEM6KMv+phZuaXcIdmVe8oj8Mv0ND966o+eFkFPAyEOzoVxwnwYbZRGr4PR64oQn16SqhCdPsAI5ePVV/NXjq3QowKmj+aT9kgxy8cC1j45ofeOoRM/r2N0EV0BSx6f94Me8BUMSjDADZGQsG5lxMOGeAjEw454OED3NiUKoqJibWuIja40UhoRA0bmfYkLjL7GQp2PV6aRjDAGW0eyKuuVLaQIjMQekVLKE+U1CQUNMYR0BLUwhvwI6mAJiYHYv5ZMgFifRGZgna/HOv8FIvgVsgFrfiPW/Cas+USs+c1Y81uw5rdCZH9EtkF0f0K2Q4T/QHZAPLeRw6BxvMgp0DV+5CJomdzkJqgSlTwEdZGGPIEY7w0jAGBCGCF1JsQcQZKy5iwDqW3ebUPqqr20YHIYPpOJTvnb++HTLv9Fe39uDyQEa9WJbb5Wqvbg/K09kHqk1Od1jFTAa/cen/djhCvTlTnwnVuVvdDG36hmz4G1OMr/eCZ+eA5O6yw/nWsxYLN/gN3hk2mRCwlyIUUu5MiFEnKhjFxoQy4UyIV25EIHcqGCXKgiF2rIhQZyoQtyoStyoRtyoTtyoQdyYVrkQk/kQvO3zdvBA41V4hvIt395LYhRhbrBWWamuWkALUbL0iq0DpxdCG1HI2h30E8xdCgdRcfDt8bReXQJXUXX0810J91PjwI25wGH2/QhfU7fQgCyMY25MS/mw7Ky3IBxEZobvM8JWORD2xgisGmb0iC0zWgxtD/Q4mib0xJoW9CSaENoKbQtaWm0rei3aENpGbStaXm0YbQC2g4Q1U0bTmuinSp7mlZaJ3uhTZDTm9Z4Z1dNK7vbNdPa5th1tIl2A+1muwvaD3ZXtMn2NGhT7G6mBQXljra0C8XvaUdzARu5gNZgsJQX8sagOEz9ApwEXkJLBB/9IW9OAyBvQQtCHkJBy4BvhSFvRYtAHkqLQt6aljXvP6HlIG9PgyHvAJqFgVeVII+glSHvTKtA3oVWg3wqrQ75dFoD8mmyB2Hgb1rIE2Rz9uWdHSoGPIVWDX5KkCfaQfOAjzbzjiq7gDzZboc8xe4gDHwDBWYvTXJB32oCMb8DxPreZCAZQcaT6WQOWULWkE1kJzlITpDz5Dq5D/xiXVOEluQFbT0rtCUnLUJLQGuqRGvQeoBGc/CqA10EaE0FhBajbUqXoG1Gl6L9gS5D25wuRxsC7G7alnQl2hZ0FdpWdDXaULoGbWt7JtOCjz6mBS+/QZto90W72e6H9oM9M9pkexa0KfaspgWPs6EtTWdi/cVizcVhzc3CmovHmpuNdTYH62wu1uI8rLn5WHMLsOYWmvVh90DE0yLi6RBxT0TcCxFPj4h7I+IZEPGMiDglkgvBO8s5cgXBnk5dzJ+JmE8TroH39eckAagDcDaMpsO25oltxMv8bvMoNP3nUluzJZncC3wyEdsK5uZVOuoKDEVoWhhXUWQihvxixlUvMozWpw1oI9qQfkfbKg0hAjb+ODfNurG+bCibwKfyhXyV8d74YCQbKcCyM5SZSqwSp8xS4pXZyhxg3G3KdmWHslPZpexW9ih7jVcGM7ghGbJhM4RhV94ob5V3ynvlg5KspKhAe+rP6lh1nDpenaBOVCepk9Up6jo1QV2v/qJuUDeqm9REdbN6Vj2vXlQvq1fV6+pN9bZ6V72vPlQfq081odk1h6ZoqqZpumZoLloeLa+WT8uvFdCcmr8WoBXUCmmFtSJaUS1QC9KKacW1ElpJrZRWWvtWK6OV1cpp5bVgQzN0wzDcDHfDw3htvDHeGhmMjIZ5HTQ7jjwJjjZlUF1VIaa1Yx1AOUTCqFJjfWBUqeN9swaOIV1wZOiK879p+Eq+krjZlttWEHdbgi2BpLW9sr0CzQjjJeJpjpdAW11UbpBc5qgJlNRQ0A/F1KWgHMrBiD+JVINR/zlSHfVDDdQPNVE/1EL9UBv1Qx3UD3VRP9RD/VAf9cN3qB8aoH5oqCaDcmikuYJaCEG10AfVQn8jLaiFAeDnBtL479ToP1aD/5J6+lRDCqJJEE0H4uiGOGZAHLOi5/nQ8yLoeW30vB7qpAYfR58yvm0QylWIObdclvikbv+/b8V/3h4/th04QhpsKQRbCscatmF9GlifLlifrlifabA+3bA+3bE+PbA+02J9psP69MT69ML6TI/16Q315kkyWGevykaqszdA81o91uzz2E4JtlOK7ZRhO+XWZzXZJdVnvUCVfGaBTz0dmQN7AbZkGVuywJZs/ziSpk/oS/rOUgNpWDqWgWVhuXhluaUcKreRw+Sucjc5yvAzshjZjBxGLiOPkc8oYPgbhYwiRqBRzChhlDK+Ncoa5Y1KRjOjldHaaGt0NMKNzkY3I8roafQzoo1BxlDjJ2OkMdoYa4w3JhqTjanGdGOmEWfEG3OMecYCY5GxxFhmrDRWG2uNBOMXY6Ox2dhm7DB2GXuMfcYB45BxxDhm/GqcNE4bScY545LxwHhsPDWeGy//+0uP/973+X/slx6uoPlby+7GO4j5pf/Wfe3QE2k72/lUdyHbzbt0Pt/j87+4T+fzHT5wDFaSNUs102GuqQoM9Hm+gD4nr0CjF2aBsEc5WFeT1WbfsUasCWsFXBUBrNfHvK72tWReS0ud4ChfpsA/JvPKW+pkXqf7air3u1TBvIr3Rar5x2Re0UudwJc/SRAPvkjg85ep0dcSxI8vEqD0ZWqG6bflVr9LbSC1+5MU8bWkJn+ZIGp9mdL/LmX+Mln+fTxfPMJ/50f+ZH6EkosQP0tArK8EKrsePovl0xNYzKex/ETGkIkw+oknC8gyGP9sIFvJbhgBHSdnAD8nXm/+380D/6G85j+Sf3UW5OMciQZmojnuIWXMsQDEunQ4ejCvs1CaC8bRDKL9BChPpJOgPJmabxCfCSMvRtfSR+ZTaOkTGK88xfdwvKAvofyKvsGY+Q7K72kylFOY+RYUxiRoczKzQVkw88mtKoPxN9PxnSKuDMbYzI15QDktSwdlT/MdIRBXM0A5I/ODcmYGIzeW1Xz7CMTYXFDOzXJDOQ/LA+W8LC8x36qSD8r5mfk2oGlsGpSns+lQnsFmQHkmr4hPkq1MOK8iu5vPqpPBX9lbDjafrihXJFyuJLcwnxUuh0G5nflmYojVUVDuYT61Sh4kD4LyYHkrMd+yvA3K2+3AzHYGo0hmz+5oT6ijgwOUnqOjvpBQfZEOo159sb4Nytv1XVDeDUqVGj6gMzioyRQc4QEruzAXv4+/s8aaYSTE+nXwbxqEogahqEFoql+xUtQgFDUIRQ1CUYNQ/O0JRQ1CUYNQ1CAUNQhFDUJRg1DUIB/PkKESoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQoKhGKSoSiEqGoRCgqEYpKhKISoahEKCoRikqEohKhqEQ+PaPk8xNLMnQF64FrSYb2zpgMbWyO3IMrDX6lU8HiYjI0hFX1GKX+qtNhk/MYnHnLxNnCpuSxUYnGFGVUiqvrrO3Mm2pNxnif/hnxklIJUpOEkK4kHEg0lETCv3mJqZTTL9XBJI8cYnbNwGf5ht0pS7063/vp7J1yG4/GxaTL7YyR3Jwx7G0cZ5QBOWwjw0uUGJrmWKmXLe9f+tapfz5TKsE5Rfjnceay8fqS6p65XHhEzy5hbdpG+uZsmcvXPyioqG/1sJZdwruGt470LRfeJSK/v48z48ed0365JbxLi8iw8E7+fs5vzO3c3eu37XXCwyN9y3SLbBveJSyyp9PHUw8q6vT3dzqLOuGvsace4PQPKOhvLf4HziiGZk4Ni/mmqhigFVivsBhKyUKWuC3iZvGnNTLkjJ3Uo5nzbvzCkdl+eJ08odrshOQZ8b6leteOnxY/unlA+2NlW/V8uKT7vnpnn96bPjjj6NiBrVfvav9jSJZTmUpcdKFjb0/cuSVf66lT22afcrRY3i3a2obZt1W4pZQKnJh3Yc6gBfcrDyh7baDLxqkd6rdYEtN7VvN8UdXuTFnTqvjUWhn97Vk9Yhfe+jmP182Sk1t6NG8oh8ZmKlpnyKv5j8az3Rl+3VI/ePWw/luK3a83vsayD/N/7BhZY7nXwYmOnH6kwZjmYUU3VnUTJb5L+f7dnNaKfd7x6O8aPFpXvFm66Cjp7MvNy/pPSF5xqN+p+d5dmpTYv+mxfXZm52rboH2rfaPcB11iHBr+7OgFzui5zuh4QDMTlaKnOqMn9Xf9/mjEo7AuM7PU7uuxqvqolAOzuvz76y/mL9o4N+twwm1168hnk7wKP1hPs56JSvOsSfOA2JnqgVLyz0NH7yt20+/p4wbj8q6Nq7g35NH70weLF2+8sEi9sOSsHUvvO7jootz7gv/IkrGuEe02JrvV9Arb+v5ouWtpGvvWvBvSa/mi9HvzFM2Wb3PoLLefsrm0nP2qXsY3fvtOpX1WZ0mncgHiQ4zn6xttOui1XyY+qbMn8dZO53tff8fQTBNyeVc/mYnNfdL/Ml/z/fOVF/Y2eBhaeU+deuvW8JxuKWNOPbaP7rt+0q7FRfNe//H6gqhr3ePI0Xaltx0v8tPlMm4LCrfL0O5c4SsnMkrXFwRLexsXDOxUPaMekqDEj/j1ZL3SFQ5lrD8v4pxbsSHjusXOPx4HrNDcGcOrfWQFJf/iNOdrpTSZcWDrJ07J9J8iA+j3gQHwBwwQAGTgHwCLhT+RQU9kUDiIzZ3Vr+vv7kxjLtjdlQYturYN69QmEr7G1WmYK4W7qBPaqmN4p1afTkz5sxPL4vT7eGLeqbe3CvWtG9amExzVt1a5Mn/JCgk9+5xqujo4aEGhJf5n32QrXDlq67tvZu4J7vzoWIXbJ0bsaF+tTsjzKWxH9TOVOxTIWip0y+EsCWqlhH7dLgQnLhpt1NqVLc/TuFt6lm+Olcn6NmTKkfTBc8dV+WbKodUFMu+okq93eFJan+IjglyDLiTmet66eD4akJKco9K8tR3okOnvNqxq2S/mTZO46IGDRq14un787COB82oN8swxpMYF50tS8vnuNyWjNw9+0CFofv5CL9fkX670Cfm5R+vpk7vqg5c/3fnM95eabiNbHsibFBCc/uHGKhOL16rrdbh17Z6Llg7Z+12p2JhaQzvJKwtv65U1sU7rklNqHMzTt2CngRVtx2YerTKYdRpM5mwdcqmuxQpvndGvnO4mKWSTNKdis0NAk2XB+f8bVOFinqO7+dpJ2cnBODOZKwwpneRxMNPh7iTi++VPzu6sMbV2+fyzy7d87FTNzS6SBN1ocKqugxzTa/GyvlWyPz28qUZkfMMckbm7rR78YXG18T1I9Tv773mdD9tlxPd+xsrt3j/k4Ou6B7fHJn4X/rhl+YXlycOJe6eezLhejU2vjz991mdprj6PHszrumT0xaBRJSe32xTY8fjQ5Vk+XLpzKszx89DE5CtkY6Fnr3q/cXXLL9/LNXFc2fY5OycEjr4s9H1N2x5K7F+mfesFGxM2jiq0/yl37f3ji+OXy17qlXzlypLkl5dO6qsjTo29VnNdYHzvfCdKniukhhRlsdHtsgx72aTl6BWNNwadbj6i/kDvgi+KT46L0eJ/GL46b8KsuQcWn/Vdt8WZfpCvh557U53nZS43c14bmzNsyLaIq8/mLz7cv2yX7gZwTDvgmDoWx7Rw6VEdFRJP3Y9k4Jn/YK/+RDgFnU5gnIJAOM4gZ4C5WNBcdEb+S07N2s7/ZPtfck38OWXkke3bKk87tKhYoaVZGrU/12GzX+aE8XvvLtuy+2T27QFphm862zTvuyLf+aTNs2y0fsFjdqec1fqlK11mychvV1YYqidFj186yXa0QfnuTe4+eW9c7Rc5u+CByBuPrrWY1ZcnBKecLOV2csX+ZvrRXk8T3PX3zdvlHNRtRMLSTYNue64Zs/lFunUhTR+kuVTsod/3w5f377oj+NqEYVHNp91aGrWt6MiCHgXcz4XsW+a9sObkNktP+AY5O18e2abC1d0Zn+u1IssUuC1nbefXvvKKsTtXBe0pO7djE68qi0efHjWgVA+l4pk5qwZm2XH1aa/WK6tEJmYvU3V6C4/mNZx7Y54dVSN6P6xfPeq4vX73aItrXjujXyD2mVzMHgud0LY1VYd95vftqN61X9erOvmG5+l2AwrJ+bPf/jo1mTyRKYvk5UzX/+vdvLy5wzdSSWdxZ1Bc0bjCgwu2jYyMKFagQMsuHfJ3/FSH+VuGdywQ0T7MXFsgokt4q24tI7sWKFcXGlp+WOWs9OkrQYeUcBZzBn5adrLBea0DRkVFfe2AoV1SHSnydx0I2ebbBuF128z0HVCIGjc9q5ZYeu9MdL+Hes/IqJqTKno9I2nD+p4LGRP/oc2s6ddz5npb//SU5FpbmjlW/zLvQcyzyT7hjd6+eHJF+3W4vVQ6T99jW9cGV7Rnb97AUXX8Y/vBDdU7Pb5ayS1n4eF+XS79sG55mFvW8Q/vFHKc69spfKxSZ3/uapUXBeQdfHvWwabZN20qcfn7VQPUDYUz1hwYXDFl4/hZjcTCiRd6JDboN3d+jYNPl06fWubqgSZZS53vV6hijZdH9vaacW/dvuktPeouXzr10ektR+JmLZ6w/8c8Q/Ju3ZP0vgM/uyVw6ZNjTdJ7umx9tb//PFe794UxWW6tmFWt1N0VabL3MLbl/WVO+z2jSwDbzAC2GfSJbSr3foBsI//n2KZeWMfQrpEtOkakZpsiziD/Ik7/woUDUN7442KA01x0Rs/7l5xbDme2j4HSp1O5sIi2oV18y9cN9g2uW6OYv7N8YL7CgYWK5itXtkLgpx25u8+fOFE3tEv3sJahf0lQdzfILfcm9Vw2sHypuat3Pqg2M+uloO4+jlMBVRr2OJ4naa4Y8+hWyXeJ2XvPfnejT9+AI0klhwcVffr6TPFC6U6MjXlX6H7bQV28R19eX+3y+kHPCipsW3z3roWrNX2ScKVKn0zrx/c4l+IzKG3ZCp0P98vRwO3YgJrFj7y9+HL4g9Lk2smLLd54jqw6J7rEi7Bv714ZtkXU3BDZ6452o+LdxR2enGwTbX+dbn8f941drzqqvQ159yAuaGqx5Htp9rbwCWl4Rqk34GTxqlWv1k8s0Nx71Fi53Nmm92KULJMccbJ/6PBxNXzK+MWPHfMhuHxweOGVwUWXhi0MfVOo3ErP7cWDrriOeOr9P2t/HBIgbz3XcC1yAYUokOqKPujZh2k+UP2esYPxj/fDuvOP7VDKnvwXfvbTd5qs9m7r3zPn1RprR+djFygqe0qKC5ITqVL2wEwqwVaCcmCUwlgKqMyqJk4esYv3zrt16u2/aFLVWK+u4aj1+bLiJL7pa+OD4zR/vj0Y4rWi9rvwBW6Rn76f2kQZ8h43y2q4LtexNLqbP8s86p1yUH8Ic6/98jkpFt/MTog4b7Oym3GS93Bho8bntOWGj2Ji+38GBT2MeT15wtxMTp/OixfLfEx4sx7WuCzXjm4OqXdVkVQ90uV2VPWxZEOmpsg38WMflHQa3eK0v/xcdqzcTjn/57KU1r5FSbwrdeVWPJ1gV/9/Q9+f6W8+/mVZf9bzXFTJml+fheWlLc8t3nJtz5ct706s/RQm99vm44lrWi579s+xr02TOLtJIZnrlINtqpFkzaYdtgfVPPyUJGfm9Rgc/DgRtYASyOKe6X+AQXW14G1X+Yiq9EXoxdTAdL6gpZOBiYk5qHSyBHIHoPOFUXASKm/umOf9Xn/CyatQ4sQ5D7vgA79Wi+zSMdot5B90ovmtnfFNT8NJGtsmpjyQD2jZdcj7Yj3rj/el+7qPr7i6LrMgrUI97cW27e9bd559t+qv0BLuSCVN/fMON8NYpMu25qbkeoXcvvvx3v75zccb7tf7MJlP+XpgHkeYXIb72ZsHymL0a7epsmwJi86SSf7fUGPz7iqLqq9leQl77KGYG23mOqUn+V7JWXLWlP2bm5NX9eCNXf/0eYV88Vr+EkkJRvMuNftpK8VkuHbf028RCNj0c6tUb8471dnCP04LXG/l+9JUVmx2bGrVojMJbG9YN7QZb/8xJbrFsSWidUreBnkdjzP5c5wfZL2oV+vLhpQ3TYwawBBRwZ5Dh0T3S4CNEzoAKsoI6lMxIJWeWAtHSbgGESYWHjkuhmCGUoYkBmcGR9SuGUa/DksBNcVX0PBQTcBuwb6FieyMfD0Frr3vi0P22nOy6v7fERjcKvPWcuL2xWHc93q2WUtf/L1m+cntGwMVpfM5MuuymRcpub3N2ZJbo7TD7XLL517+fexdZgdf170siHWdP+nSmXN3+w483K91tubNyXVGV9t3nk4+YnZRQnF/2T3rWZuli+cpdtzYskUopOfLnEOpXrM01OYkdPFbHxdOrfDYfX5ts5X/hqSIewYvX1rKPu78dMuy8aewYk9KQzIby7RPs5ic9avdOnb9Z7qZ+tPr3i3mksmbWfN4zsy9o5FY4/FRfI6gogWTTPsatqPTjHY8dTgWbLt3Zee9F2nmvV+Ups05s6E8JNDqWpHLJuVvhk0s64GF1GomRkaDxvYB7JWh9BURY9wLGm8ZiMDjW4PRkJ2ZFbx6GZQKoJHJyWzIgzysDnQNgsdtyGeALCtqoIzQyGIITGPf+73YG70n3tvKMStgQ+f+vxr+E7capCBp4TEMMwhZoNWgweDLkMmQzFDEkA8emU9jKGFQYAhhqGQoAPLSgeKJQFYGQ+VCtQYVnNVrSWVBfnpRYkFGpQJa8cbSxMigsP/ZjkhJBiuRWVIdvuc+T90wZ7LDold8xuEs7yyK3f782bhu5vsHBo/rur6+/sJc/fVqzM+vJXMbuPM231qnz5zHUvCK+do38U7dAy1TzZeet2uJDeerPHlD8sb+v8bd8+5sVli03e31zrr5b9cfsDv2ar/L/YuOe368FJHs8v44mdH1fLwxT3f9up7Fzr0n/vj9T1476fBZQ/XQ4i0J2yeyfD/JW7bOo2Id06yGU+smmpipHXuWwrOgj+lkrnzturow0yOXhWs2OSlNnXm+yq+gbPE67aNKz6uKr8cu6F/4PtzfkElboMzl1xQ3maQpwtX9NU9alB8snu1nznLMJ23Vi6W3lkYo13YaXJQXWdjEJG/QxCSNiCM2wyYmHqAQB92TKHqNhNLBYIcm0QWxBhLIKZEbMQvECLQTLsNqyA+sai0MDYyAFa2RpbFpFEZCZPqvwnd/W2JvrF68QYer1Nf1D978QCuzQEnk/vTDXhy693eclF52U5H1OM+btDaV/05M550/7D2xUKFs2qM9Dyf3CTk8UtNatGxid2KPxM8zWhsDpNp/VE98FXzU4cVu3dj+cy6TUvLCElSduI+3MTU4vlOaWX3UqCrgXU7Hk19m4l+PdU9Kkg2ZdeWpsNDCa3PXff8fbsXs/vLqu4jPaXaO6d5x2/ftvdmq+yR8x4mJq5MKs+yXC3McOq99pvTezK7KioLmtW6zDm1u7vRzt9JuDlY0WvHv1XH7kjKmA+tWFQXH7sg4Xvfa0DZjlnrD5y1sG55f3iGo03QpZ//6+4WbXjQnrdjGWGZwi88heFM06+fvW8xSWIMVRbvT3fIEsnIjhYPytvAyAAC6XJGhDQplbmRzdHJlYW0NCmVuZG9iag0KMTAgMCBvYmoNCjw8L1R5cGUvTWV0YWRhdGEvU3VidHlwZS9YTUwvTGVuZ3RoIDE0NjM+Pg0Kc3RyZWFtDQo8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IjMuMS03MDEiPgo8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KPC9yZGY6RGVzY3JpcHRpb24+CjxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiICB4bWxuczp4bXBSaWdodHM9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9yaWdodHMvIj4KPHhtcFJpZ2h0czpNYXJrZWQ+VHJ1ZTwveG1wUmlnaHRzOk1hcmtlZD48L3JkZjpEZXNjcmlwdGlvbj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8L3JkZjpSREY+PC94OnhtcG1ldGE+PD94cGFja2V0IGVuZD0idyI/Pg0KZW5kc3RyZWFtDQplbmRvYmoNCjExIDAgb2JqDQo8PC9OIDMvRmlsdGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAyNTkzPj4NCnN0cmVhbQ0KeJydlndUVNcWh8+9d3qhzTB0GHqvUgYQ6R2kV1EYZgYYygDDDNgLIioQUUSkKYIEBQwYDUViRRQLAVEBe0CCgBKDUWyoZEbWSnx5ee/l5ffHPd/aZ+9z99l737UuACQvPy4vHZYCII0n4Ad7utAjo6Lp2H4AAzzAAHMAmKysDP8Qj1Agkre7Kz1L5AT+Ra+HASRebxl7BdLp4P+TNCuDLwAAChTxEjYniyXiPBGn5ggyxPZZEVPjU8QMo8TMFyUoYnkxJy6y0WefRXYSMzuNxxaxOOcMdhpbzD0i3pEt5IgY8RNxfjaXkyPi2yLWShWmcUX8VhybxmFmAYAiie0CDitJxGYiJvFDg11FvBQAHCnxC47/ggWc1QLxpVzTM9bwuYlJAroeS59ubmvLoHtxclI5AoFxIJOV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OmFib3V0PSIiICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgo8ZGM6Y3JlYXRvcj48cmRmOlNlcT48cmRmOmxpPnRlcmplaW88L3JkZjpsaT48L3JkZjpTZXE+PC9kYzpjcmVhdG9yPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KPHhtcDpDcmVhdG9yVG9vbD5NaWNyb3NvZnTCriBXb3JkIDIwMTA8L3htcDpDcmVhdG9yVG9vbD48eG1wOkNyZWF0ZURhdGU+MjAxMS0wNC0wNlQxOToyOTo0NCswMjowMDwveG1wOkNyZWF0ZURhdGU+PHhtcDpNb2RpZnlEYXRlPjIwMTEtMDQtMDZUMTk6Mjk6NDQrMDI6MDA8L3htcDpNb2RpZnlEYXRlPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6eGFwTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iPgo8eGFwTU06RG9jdW1lbnRJRD40MjY3QUQyNy1GNDY2LTQ2NzMtOTJEMy1BOTM3RDRCODZFNEU8L3hhcE1NOkRvY3VtZW50SUQ+PHhhcE1NOkluc3RhbmNlSUQ+NDI2N0FEMjctRjQ2Ni00NjczLTkyRDMtQTkzN0Q0Qjg2RTRFPC94YXBNTTpJbnN0YW5jZUlEPjwvcmRmOkRlc2NyaXB0aW9uPgo8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiAgeG1sbnM6cGRmYWlkPSJodHRwOi8vd3d3LmFpaW0ub3JnL3BkZmEvbnMvaWQvIj4KPHBkZmFpZDpwYXJ0PjE8L3BkZmFpZDpwYXJ0PjxwZGZhaWQ6Y29uZm9ybWFuY2U+QjwvcGRmYWlkOmNvbmZvcm1hbmNlPjwvcmRmOkRlc2NyaXB0aW9uPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPC9yZGY6UkRGPjwveDp4bXBtZXRhPjw/eHBhY2tldCBlbmQ9InciPz4NCmVuZHN0cmVhbQ0KZW5kb2JqDQp4cmVmDQowIDEzDQowMDAwMDAwMDAwIDY1NTM1IGYNCjAwMDAwMDAwMTcgMDAwMDAgbg0KMDAwMDAwMDI5MyAwMDAwMCBuDQowMDAwMDAwMzQ5IDAwMDAwIG4NCjAwMDAwMDA1MTMgMDAwMDAgbg0KMDAwMDAwMDcwNyAwMDAwMCBuDQowMDAwMDAwODc0IDAwMDAwIG4NCjAwMDAwMDExMTIgMDAwMDAgbg0KMDAwMDAwMTMzMiAwMDAwMCBuDQowMDAwMDAxNTU0IDAwMDAwIG4NCjAwMDAwODE3ODMgMDAwMDAgbg0KMDAwMDA4MzMyOSAwMDAwMCBuDQowMDAwMDg2MDAyIDAwMDAwIG4NCnRyYWlsZXINCjw8L1NpemUgMTMvUm9vdCAxIDAgUi9JbmZvIDcgMCBSL0lEWzwyN0FENjc0MjY2RjQ3MzQ2OTJEM0E5MzdENEI4NkU0RT48MjdBRDY3NDI2NkY0NzM0NjkyRDNBOTM3RDRCODZFNEU+XSA+Pg0Kc3RhcnR4cmVmDQo4OTMwMA0KJSVFT0Y= + + + + + + + Supp123 + + + Salescompany ltd. + + + 1231412341324 + 5467 + Main street + Suite 123 + 1 + Revenue department + Big city + 54321 + RegionA + + NO + + + + NO999999999MVA + + VAT + + + + The Sellercompany Incorporated + + + Big city + RegionA + + DK + + + + + O. Hansen + 46211230 + 46211231 + antonio@salescompany.dk + + + Antonio + Salemacher + M + Sales manager + + + + + + + + 345KS5324 + + + Buyercompany ltd + + + 1238764941386 + 123 + Anystreet + Back door + 8 + Accounting department + Anytown + 101 + RegionB + + BE + + + + BE54321 + + VAT + + + + The buyercompany inc. + + + Mainplace + RegionB + + BE + + + + + 3150bdn + 5121230 + 5121231 + john@buyercompany.eu + + + John + Doe + X + Purchasing manager + + + + + + 098740918237 + + + Ebeneser Scrooge Inc. + + + 6411982340 + + + + 2009-12-15 + + 6754238987648 + + Deliverystreet + Side door + 12 + DeliveryCity + 523427 + RegionC + + BE + + + + + + 31 + 2009-12-31 + SW + Payref1 + + NO9386011117947 + + 9710 + + DNBANOKK + + + + + + Penalty percentage 10% from due date + + + true + Packing cost + 100 + + S + 25 + + VAT + + + + + false + Promotion discount + 100 + + S + 25 + + VAT + + + + + 292.20 + + 1460.5 + 292.1 + + S + 25 + + VAT + + + + + 1 + 0.1 + + AA + 10 + + VAT + + + + + -25 + 0 + + E + 0 + AAM + Exempt New Means of Transport + + VAT + + + + + + 1436.5 + 1436.5 + 1729 + 100 + 100 + 1000 + 0.30 + 729 + + + 1 + Scratch on box + 1 + 1273 + BookingCode001 + + 1 + + + false + Damage + 12 + + + true + Testing + 12 + + + 254.6 + + + Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM: 3MB. Screen 1440x900 + Laptop computer + + JB007 + + + 1234567890124 + + + 12344321 + + + 65434568 + + + S + 25 + + VAT + + + + Color + Black + + + + 1273 + 1 + + false + Contract + 0.15 + 225 + 1500 + + + + + 2 + Cover is slightly damaged. + -1 + -3.96 + BookingCode002 + + 5 + + + -0.396 + + + Returned "Advanced computing" book + + JB008 + + + 1234567890125 + + + 32344324 + + + 65434567 + + + AA + 10 + + VAT + + + + + 3.96 + 1 + + + + 3 + 2 + 4.96 + BookingCode003 + + 3 + + + 0.496 + + + "Computing for dummies" book + + JB009 + + + 1234567890126 + + + 32344324 + + + 65434566 + + + AA + 10 + + VAT + + + + + 2.48 + 1 + + false + Contract + 0.1 + 0.275 + 2.75 + + + + + 4 + -1 + -25 + BookingCode004 + + 2 + + + 0 + + + Returned IBM 5150 desktop + + JB010 + + + 1234567890127 + + + 12344322 + + + 65434565 + + + E + 0 + + VAT + + + + + 25 + 1 + + + + 5 + 250 + 187.5 + BookingCode005 + + 4 + + + 37.5 + + + Network cable + + JB011 + + + 1234567890128 + + + 12344325 + + + 65434564 + + + S + 25 + + VAT + + + + Type + Cat5 + + + + 0.75 + 1 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/ehf-test-SendRegning-HelseVest2.xml b/oxalis-outbound/src/test/resources/ehf-test-SendRegning-HelseVest2.xml new file mode 100644 index 0000000000000000000000000000000000000000..49ba7f7e1dbfa347831bc5b2b8f458f4c0fd8cde --- /dev/null +++ b/oxalis-outbound/src/test/resources/ehf-test-SendRegning-HelseVest2.xml @@ -0,0 +1,522 @@ + + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 2011114 + 2011-11-14 + 380 + Demonstrasjon av forsendelse via eHandel.no + 2011-11-14 + EUR + Project cost code 123 + + 2011-10-01 + 2011-10-30 + + + 123 + + + Contract321 + Framework agreement + + + Doc1 + Timesheet + + + http://www.suppliersite.eu/sheet001.html + + + + + Doc2 + Drawing + + + UjBsR09EbGhjZ0dTQUxNQUFBUUNBRU1tQ1p0dU1GUXhEUzhi + + + + + + 1234567890123 + + Supp123 + + + SendRegning AS + + + 1231412341324 + 5467 + Østre Aker vei 243H + 3. etg. + 1 + R D + OSLO + 0976 + Akershus + + NO + + + + 976098897MVA + + VAT + + + + SendRegning AS + 5402697509 + + Big city + RegionA + + DK + + + + + 040363 + 90665793 + 22258524 + steinar@sendregning.no + + + Steinar + Cook + Overbeck + CTO + + + + + + 1234567987654 + + Kunde 1 + + + Helse Bergen HF + + + 1238764941386 + 1 + Jonas Lies vei 65 + Back door + 65 + IT department + BERGEN + 5021 + Hordaland + + NO + + + + 983974724 + + VAT + + + + Helse Bergen HF + 983974724 + + Bergen + Hordaland + + NO + + + + + 3150bdn + 5121230 + 5121231 + + + + John + Doe + X + Purchasing manager + + + + + + 098740918237 + + + Ebeneser Scrooge Inc. + + + 6411982340 + + + + 2009-12-15 + + 6754238987648 + + Deliverystreet + Side door + 12 + DeliveryCity + 523427 + RegionC + + BE + + + + + + 31 + 2011-12-31 + SW + Payref1 + + NO9386011117947 + + 9710 + + DNBANOKK + + + + + + Penalty percentage 10% from due date + + + true + Packing cost + 100 + + S + 20 + + VAT + + + + + false + Promotion discount + 100 + + S + 20 + + VAT + + + + + 292.20 + + 1460.5 + 292.1 + + S + 20 + + VAT + + + + + 1 + 0.1 + + AA + 10 + + VAT + + + + + -25 + 0 + + E + 0 + AAM + Exempt New Means of Transport + + VAT + + + + + + 1436.5 + 1436.5 + 1729 + 100 + 100 + 1000 + 0.30 + 729 + + + 1 + Scratch on box + 1 + 1273 + BookingCode001 + + 1 + + + false + Damage + 12 + + + true + Testing + 10 + + + 254.6 + + + Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM: 3MB. Screen 1440x900 + + Laptop computer + + JB007 + + + 1234567890124 + + + 12344321 + + + 65434568 + + + S + 20 + + VAT + + + + Color + Black + + + + 1273 + 1 + + false + Contract + 0.15 + 225 + 1500 + + + + + 2 + Cover is slightly damaged. + -1 + -3.96 + BookingCode002 + + 5 + + + -0.396 + + + Returned "Advanced computing" book + + JB008 + + + 1234567890125 + + + 32344324 + + + 65434567 + + + AA + 10 + + VAT + + + + + 3.96 + 1 + + + + 3 + 2 + 4.96 + BookingCode003 + + 3 + + + 0.496 + + + "Computing for dummies" book + + JB009 + + + 1234567890126 + + + 32344324 + + + 65434566 + + + AA + 10 + + VAT + + + + + 2.48 + 1 + + false + Contract + 0.1 + 0.275 + 2.75 + + + + + 4 + -1 + -25 + BookingCode004 + + 2 + + + 0 + + + Returned IBM 5150 desktop + + JB010 + + + 1234567890127 + + + 12344322 + + + 65434565 + + + E + 0 + + VAT + + + + + 25 + 1 + + + + 5 + 250 + 187.5 + BookingCode005 + + 4 + + + 37.5 + + + Network cable + + JB011 + + + 1234567890128 + + + 12344325 + + + 65434564 + + + S + 20 + + VAT + + + + Type + Cat5 + + + + 0.75 + 1 + + + \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/logback-test.xml b/oxalis-outbound/src/test/resources/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..7692180a8756e8a1563e1791c7966562f0319dff --- /dev/null +++ b/oxalis-outbound/src/test/resources/logback-test.xml @@ -0,0 +1,47 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + + + + + + diff --git a/oxalis-outbound/src/test/resources/oxalis_home/fake-oxalis.conf b/oxalis-outbound/src/test/resources/oxalis_home/fake-oxalis.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-outbound/src/test/resources/oxalis_home/logback-test.xml b/oxalis-outbound/src/test/resources/oxalis_home/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-outbound/src/test/resources/oxalis_home/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-outbound/src/test/resources/peppol-bis-invoice-sbdh.xml b/oxalis-outbound/src/test/resources/peppol-bis-invoice-sbdh.xml new file mode 100644 index 0000000000000000000000000000000000000000..95515f77c87cea5a7bdab822272676f51d6053ed --- /dev/null +++ b/oxalis-outbound/src/test/resources/peppol-bis-invoice-sbdh.xml @@ -0,0 +1,172 @@ + + + + + + 1.0 + + 9908:976098897 + + + 0208:0871221633 + + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + 2.1 + 1070e7f0-3bae-11e3-aa6e-0800200c9a66 + Invoice + 2013-02-19T05:10:10 + + + + DOCUMENTID + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1 + + + PROCESSID + urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 + + + + + 2.0 + urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0 + urn:www.cenbii.eu:profile:bii04:ver1.0 + 1 + 2012-06-08 + 380 + 2012-06-08 + SEK + SOPE + + + + 5567125082 + + + Ecru Consulting + + + Gamla Brogatan + 29 + Stockholm + 11120 + + SE + + + + SE556712508201 + + VAT + + + + 976098897 + + + Martin + Forsberg + + + + + + + 810418052 + + + EKONOMISTYRNINGSVERKET (NATIONAL FINANCIAL MANAGEMENT AUTHORITY) + + + 45316 + EFFEKTIV ADMINISTRATION + STOCKHOLM + 104 30 + + SE + + + + 810418052 + + + 08 - 123456 + 08-123457 + infomail@esv.se + + + SOREN + PEDERSEN + + + + + 31 + 2012-06-23 + + 5955559 + + + BGABSESS + + + + + + 0.25 + + 1 + 0.25 + + S + 25 + + VAT + + + + + + 1 + 1 + 1.25 + 1.25 + + + 1 + 1 + 1 + + 1 + + + TEST AV PEPPOL-FAKTURA + + + 1 + 1 + + + + diff --git a/oxalis-outbound/src/test/resources/reference.conf b/oxalis-outbound/src/test/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..2522e8cd50310542128fc305e04968acbb4535d5 --- /dev/null +++ b/oxalis-outbound/src/test/resources/reference.conf @@ -0,0 +1,26 @@ +oxalis.module.outbound.testresources.class = network.oxalis.outbound.guice.TestResourceModule + +defaults.transport.invalid = { + profile: busdox-transport-invalid + sender: invalid + enabled: false + weight: 0 +} + +defaults.transport.foo_mode_transport = { + profile: foo-mode-transport + sender: invalid + weight: 0 + modes: [foo, foo_test] +} + +defaults.transport.dummy_mode_transport = { + profile: dummy-mode-transport + sender: invalid + weight: -1 + modes: [DUMMY] +} + +oxalis.statistics.service = noop + +oxalis.asd.sender.skip = true \ No newline at end of file diff --git a/oxalis-outbound/src/test/resources/simple-sbd.xml b/oxalis-outbound/src/test/resources/simple-sbd.xml new file mode 100644 index 0000000000000000000000000000000000000000..74d4ac020fbe6cadb9c409aa8ba1703c8543b36d --- /dev/null +++ b/oxalis-outbound/src/test/resources/simple-sbd.xml @@ -0,0 +1,30 @@ + + + + 1.0 + + 0088:oxalis + + + 0208:0871221633 + + + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + 2.1 + 555bcb4c-940b-4694-9b90-d9b0ae1e937b + Invoice + 2016-10-19T11:20:05.304+02:00 + + + + DOCUMENTID + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1 + + + PROCESSID + urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 + + + + + \ No newline at end of file diff --git a/oxalis-test/pom.xml b/oxalis-test/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..9a197e20b348e88870e643390ba23550aede0c58 --- /dev/null +++ b/oxalis-test/pom.xml @@ -0,0 +1,130 @@ + + + + + oxalis + dk.erst.oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + + 4.0.0 + + oxalis-test + jar + + Oxalis :: Core :: Test resources + Test artifacts + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + dk.erst.oxalis + oxalis-api + + + + network.oxalis.vefa + peppol-mode + + + + ch.qos.logback + logback-classic + + + + com.google.inject + guice + + + + org.bouncycastle + bcprov-jdk15on + + + + org.bouncycastle + bcmail-jdk15on + test + + + + org.testng + testng + + + org.mockito + mockito-core + + + + + org.eclipse.jetty + jetty-server + + + org.eclipse.jetty + jetty-servlet + + + + com.google.inject.extensions + guice-servlet + provided + + + + javax.servlet + javax.servlet-api + provided + + + + + io.zipkin.brave + brave + provided + + + + + org.mariadb.jdbc + mariadb-java-client + + + org.hsqldb + hsqldb + + + + org.apache.httpcomponents + httpclient + + + + + diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdConstants.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..eb93b93891338ff3aecdefefd9a4cd67a4e717d3 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdConstants.java @@ -0,0 +1,23 @@ +package network.oxalis.test.asd; + +import network.oxalis.vefa.peppol.common.lang.PeppolException; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import network.oxalis.vefa.peppol.common.model.TransportProtocol; + +/** + * @author erlend + */ +public class AsdConstants { + + public static final TransportProtocol TRANSPORT_PROTOCOL; + + public static final TransportProfile TRANSPORT_PROFILE = TransportProfile.of("bdx-transport-asd"); + + static { + try { + TRANSPORT_PROTOCOL = TransportProtocol.of("ASD"); + } catch (PeppolException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdHeaders.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdHeaders.java new file mode 100644 index 0000000000000000000000000000000000000000..3baf2dda34b5108a60b1a53dd8b52475e82ded75 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdHeaders.java @@ -0,0 +1,14 @@ +package network.oxalis.test.asd; + +/** + * @author erlend + */ +public interface AsdHeaders { + + String TRANSMISSION_ID = "X-ASD-TransmissionID"; + + String STATUS = "X-ASD-Status"; + + String TIMESTAMP = "X-ASD-Timestamp"; + +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdInboundMetadata.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdInboundMetadata.java new file mode 100644 index 0000000000000000000000000000000000000000..41f5bf9225deec34eb18f6fa120d21f6ac912193 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdInboundMetadata.java @@ -0,0 +1,79 @@ +package network.oxalis.test.asd; + +import network.oxalis.api.inbound.InboundMetadata; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.tag.Tag; +import network.oxalis.vefa.peppol.common.model.*; + +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +/** + * @author erlend + */ +public class AsdInboundMetadata implements InboundMetadata { + + private TransmissionIdentifier transmissionIdentifier; + + private Header header; + + private Date timestamp; + + public AsdInboundMetadata(TransmissionIdentifier transmissionIdentifier, Header header, Date timestamp) { + this.transmissionIdentifier = transmissionIdentifier; + this.header = header; + this.timestamp = timestamp; + } + + @Override + public X509Certificate getCertificate() { + return null; + } + + @Override + public Tag getTag() { + return null; + } + + @Override + public TransmissionIdentifier getTransmissionIdentifier() { + return transmissionIdentifier; + } + + @Override + public Header getHeader() { + return header; + } + + @Override + public Date getTimestamp() { + return timestamp; + } + + @Override + public Digest getDigest() { + return null; + } + + @Override + public TransportProtocol getTransportProtocol() { + return AsdConstants.TRANSPORT_PROTOCOL; + } + + @Override + public TransportProfile getProtocol() { + return AsdConstants.TRANSPORT_PROFILE; + } + + @Override + public List getReceipts() { + return Collections.emptyList(); + } + + @Override + public Receipt primaryReceipt() { + return null; + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdInboundModule.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdInboundModule.java new file mode 100644 index 0000000000000000000000000000000000000000..843074ab0101f97a3cc6ffc26419d993bd3e5823 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdInboundModule.java @@ -0,0 +1,14 @@ +package network.oxalis.test.asd; + +import com.google.inject.servlet.ServletModule; + +/** + * @author erlend + */ +public class AsdInboundModule extends ServletModule { + + @Override + protected void configureServlets() { + serve("/asd").with(AsdServlet.class); + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdMessageSender.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdMessageSender.java new file mode 100644 index 0000000000000000000000000000000000000000..cf3a447a915b22342e7302d3975352896528bca6 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdMessageSender.java @@ -0,0 +1,54 @@ +package network.oxalis.test.asd; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.typesafe.config.Config; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.outbound.MessageSender; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.InputStreamEntity; +import org.apache.http.impl.client.CloseableHttpClient; + +/** + * @author erlend + */ +@Singleton +public class AsdMessageSender implements MessageSender { + + @Inject + private CloseableHttpClient httpClient; + + @Inject + private Config config; + + @Override + public TransmissionResponse send(TransmissionRequest transmissionRequest) throws OxalisTransmissionException { + TransmissionIdentifier transmissionIdentifier = TransmissionIdentifier.generateUUID(); + + // For use in testing when no receiver is configured. + if (config.hasPath("oxalis.asd.sender.skip") && config.getBoolean("oxalis.asd.sender.skip")) { + return new AsdTransmissionResponse(transmissionRequest, transmissionIdentifier); + } + + HttpPost httpPost = new HttpPost(transmissionRequest.getEndpoint().getAddress()); + httpPost.setHeader(AsdHeaders.TRANSMISSION_ID, transmissionIdentifier.getIdentifier()); + httpPost.setEntity(new InputStreamEntity(transmissionRequest.getPayload())); + + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + String status = response.getFirstHeader(AsdHeaders.STATUS).getValue(); + + if (!"OK".equals(status)) + throw new OxalisTransmissionException(status); + + return new AsdTransmissionResponse(transmissionRequest, transmissionIdentifier); + } catch (OxalisTransmissionException e) { + throw e; + } catch (Exception e) { + throw new OxalisTransmissionException("Unable to send message.", e); + } + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdOutboundModule.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdOutboundModule.java new file mode 100644 index 0000000000000000000000000000000000000000..b80a6027a99017dfb61591b4a00de6e96eaef742 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdOutboundModule.java @@ -0,0 +1,20 @@ +package network.oxalis.test.asd; + +import com.google.inject.AbstractModule; +import com.google.inject.Key; +import com.google.inject.Singleton; +import com.google.inject.name.Names; +import network.oxalis.api.outbound.MessageSender; + +/** + * @author erlend + */ +public class AsdOutboundModule extends AbstractModule { + + @Override + protected void configure() { + bind(Key.get(MessageSender.class, Names.named("oxalis-asd"))) + .to(AsdMessageSender.class) + .in(Singleton.class); + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdServlet.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..174e32c9a099b50a8fa7908de2743720c466f72c --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdServlet.java @@ -0,0 +1,76 @@ +package network.oxalis.test.asd; + +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import network.oxalis.api.header.HeaderParser; +import network.oxalis.api.lang.OxalisContentException; +import network.oxalis.api.lang.TimestampException; +import network.oxalis.api.model.Direction; +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.persist.PersisterHandler; +import network.oxalis.api.timestamp.Timestamp; +import network.oxalis.api.timestamp.TimestampProvider; +import network.oxalis.vefa.peppol.common.model.Header; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.file.Path; + +/** + * @author erlend + */ +@Singleton +public class AsdServlet extends HttpServlet { + + @Inject + private Provider persisterHandlerProvider; + + @Inject + private TimestampProvider timestampProvider; + + @Inject + private HeaderParser headerParser; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.getWriter().write("Hello ASD world!"); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + PersisterHandler persisterHandler = persisterHandlerProvider.get(); + + TransmissionIdentifier transmissionIdentifier = null; + + Header header = null; + + Path path = null; + + try { + Timestamp timestamp = timestampProvider.generate(null, Direction.IN); + + byte[] content = ByteStreams.toByteArray(req.getInputStream()); + + transmissionIdentifier = TransmissionIdentifier.of(req.getHeader(AsdHeaders.TRANSMISSION_ID)); + + header = headerParser.parse(new ByteArrayInputStream(content)); + + path = persisterHandler.persist(transmissionIdentifier, header, new ByteArrayInputStream(content)); + + persisterHandler.persist(new AsdInboundMetadata(transmissionIdentifier, header, timestamp.getDate()), path); + + resp.setStatus(HttpServletResponse.SC_OK); + resp.setHeader(AsdHeaders.STATUS, "OK"); + resp.setHeader(AsdHeaders.TIMESTAMP, timestamp.getDate().toString()); + } catch (TimestampException | OxalisContentException e) { + persisterHandler.persist(transmissionIdentifier, header, path, e); + resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); + resp.setHeader(AsdHeaders.STATUS, String.format("ERROR: %s", e.getMessage())); + } + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/asd/AsdTransmissionResponse.java b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdTransmissionResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..48a46d9305ba03b7382616af982f23bc53d5e972 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/asd/AsdTransmissionResponse.java @@ -0,0 +1,68 @@ +package network.oxalis.test.asd; + +import network.oxalis.api.model.TransmissionIdentifier; +import network.oxalis.api.outbound.TransmissionRequest; +import network.oxalis.api.outbound.TransmissionResponse; +import network.oxalis.vefa.peppol.common.model.*; + +import java.util.Date; +import java.util.List; + +/** + * @author erlend + */ +public class AsdTransmissionResponse implements TransmissionResponse { + + private Endpoint endpoint; + + private Header header; + + private TransmissionIdentifier transmissionIdentifier; + + public AsdTransmissionResponse(TransmissionRequest transmissionRequest, + TransmissionIdentifier transmissionIdentifier) { + this.endpoint = transmissionRequest.getEndpoint(); + this.header = transmissionRequest.getHeader(); + this.transmissionIdentifier = transmissionIdentifier; + } + + @Override + public Endpoint getEndpoint() { + return endpoint; + } + + @Override + public TransmissionIdentifier getTransmissionIdentifier() { + return transmissionIdentifier; + } + + @Override + public Header getHeader() { + return header; + } + + @Override + public Date getTimestamp() { + return null; + } + + @Override + public Digest getDigest() { + return null; + } + + @Override + public TransportProtocol getTransportProtocol() { + return AsdConstants.TRANSPORT_PROTOCOL; + } + + @Override + public List getReceipts() { + return null; + } + + @Override + public Receipt primaryReceipt() { + return null; + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/config/TestConfigModule.java b/oxalis-test/src/main/java/network/oxalis/test/config/TestConfigModule.java new file mode 100644 index 0000000000000000000000000000000000000000..c72c196fd99cea12f46a058d906f76053419258e --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/config/TestConfigModule.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.config; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; + +/** + * @author erlend + */ +public class TestConfigModule extends AbstractModule { + + @Override + protected void configure() { + // No action. + } + + @Provides + @Singleton + protected Config getconfig() { + return ConfigFactory.defaultReference(); + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/dummy/DummyPkiModule.java b/oxalis-test/src/main/java/network/oxalis/test/dummy/DummyPkiModule.java new file mode 100644 index 0000000000000000000000000000000000000000..d3b4e34ed83e399dd7111e66a18acbd2399269d3 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/dummy/DummyPkiModule.java @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.dummy; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import network.oxalis.api.model.AccessPointIdentifier; + +import java.io.InputStream; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; + +public class DummyPkiModule extends AbstractModule { + + @Override + protected void configure() { + // No action. + } + + @Provides + @Singleton + protected KeyStore getKeyStore() throws Exception { + KeyStore keystore = KeyStore.getInstance("JKS"); + try (InputStream inputStream = getClass().getResourceAsStream("/dummy/app_0000000001.jks")) { + keystore.load(inputStream, "changeit".toCharArray()); + } + return keystore; + } + + @Provides + @Singleton + protected PrivateKey getPrivateKeyEntry(KeyStore keyStore) throws Exception { + return (PrivateKey) keyStore.getKey("ap", "changeit".toCharArray()); + } + + @Provides + @Singleton + protected X509Certificate getCertificate(KeyStore keyStore) throws Exception { + return (X509Certificate) keyStore.getCertificate("ap"); + } + + @Provides + @Singleton + protected AccessPointIdentifier provideOurAccessPointIdentifier(X509Certificate certificate) { + return new AccessPointIdentifier("APP_0000000001"); + } + + @Provides + @Singleton + protected KeyStore.PrivateKeyEntry getPrivateKey(PrivateKey privateKey, X509Certificate certificate) throws Exception { + return new KeyStore.PrivateKeyEntry( + privateKey, + new Certificate[]{certificate} + ); + } +} + diff --git a/oxalis-test/src/main/java/network/oxalis/test/filesystem/FakeHomeDetector.java b/oxalis-test/src/main/java/network/oxalis/test/filesystem/FakeHomeDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..9710a5ca04d74030bc57891f7dec0e25dc98e5b9 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/filesystem/FakeHomeDetector.java @@ -0,0 +1,23 @@ +package network.oxalis.test.filesystem; + +import network.oxalis.api.filesystem.HomeDetector; +import org.kohsuke.MetaInfServices; + +import java.io.File; +import java.nio.file.Paths; + +/** + * @author erlend + */ +@MetaInfServices +public class FakeHomeDetector implements HomeDetector { + + @Override + public File detect() { + try { + return Paths.get(getClass().getResource("/oxalis_home/fake-oxalis.conf").toURI()).getParent().toFile(); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/filesystem/TestFileSystemModule.java b/oxalis-test/src/main/java/network/oxalis/test/filesystem/TestFileSystemModule.java new file mode 100644 index 0000000000000000000000000000000000000000..a74d950d31e0601148b068072d95694e1a9cc9c7 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/filesystem/TestFileSystemModule.java @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.filesystem; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; +import network.oxalis.api.lang.OxalisLoadingException; + +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * @author erlend + */ +public class TestFileSystemModule extends AbstractModule { + + @Override + protected void configure() { + // No action + } + + @Provides + @Singleton + @Named("home") + protected Path getHomeFolder() { + try { + return Paths.get(getClass().getResource("/oxalis_home/fake-oxalis.conf").toURI()).getParent(); + } catch (URISyntaxException e) { + throw new OxalisLoadingException(e.getMessage(), e); + } + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/identifier/PeppolDocumentTypeIdAcronym.java b/oxalis-test/src/main/java/network/oxalis/test/identifier/PeppolDocumentTypeIdAcronym.java new file mode 100644 index 0000000000000000000000000000000000000000..fd209b2b773bd5be2dd3aa86941b39676cdbb816 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/identifier/PeppolDocumentTypeIdAcronym.java @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.identifier; + +import network.oxalis.vefa.peppol.common.model.DocumentTypeIdentifier; + +/** + * Represents a PEPPOL Document Identifier acronym, textually represented thus: + *
+ *     {@literal ::##::}
+ * 
+ *

+ * Provides short hand notation for PEPPOL Document Type Identifiers, which are otherwise fairly lengthy and complex. + * This is just a simple helper class to make life easier :-) + * + * @author Steinar Overbeck Cook + * @see "PEPPOL Policy for us of Identifiers v2.2, POLICY 13" + */ +public enum PeppolDocumentTypeIdAcronym { + + // PEPPOL Catalogues (PEPPOL BIS profile 1a) + PEPPOL_CATALOGUE("urn:oasis:names:specification:ubl:schema:xsd:Catalogue-2::Catalogue" + + "##urn:www.cenbii.eu:transaction:biicoretrdm019:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol1a:ver1.0" + + "::2.0"), + + // Basic Order according to PEPPOL BIS 3a + ORDER("urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order" + + "##urn:www.cenbii.eu:transaction:biicoretrdm001:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol3a:ver1.0" + + "::2.0"), + + // Standard PEPPOL BIS profile 4a invoice + INVOICE("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biitrns010:ver2.0" + + ":extended:urn:www.peppol.eu:bis:peppol4a:ver2.0" + + "::2.1"), + + // EHF Invoice + EHF_INVOICE("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol4a:ver1.0" + + "#urn:www.difi.no:ehf:faktura:ver1" + + "::2.0"), + + // Standalone Credit Note according to EHF + EHF_CREDIT_NOTE("urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.cenbii.eu:profile:biixx:ver1.0" + + "#urn:www.difi.no:ehf:kreditnota:ver1" + + "::2.0"), + + // PEPPOL Billing (PEPPOL BIS Profile 5a) + INVOICE_BILLING("urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice" + + "##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "::2.0"), + + // PEPPOL Billing (PEPPOL BIS Profile 5a) + CREDIT_NOTE_BILLLING("urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol5a:ver1.0" + + "::2.0"), + + // Credit invoice according to PEPPOL BIS 6a (Procurement) + CREDIT_NOTE("urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2::CreditNote" + + "##urn:www.cenbii.eu:transaction:biicoretrdm014:ver1.0" + + ":#urn:www.peppol.eu:bis:peppol6a:ver1.0" + + "::2.0"), + + // Tender (trdm090) + TENDER("urn:oasis:names:specification:ubl:schema:xsd:Tender-2::Tender" + + "##urn:www.cenbii.eu:transaction:biitrdm090:ver3.0" + + "::2.1"); + + private final DocumentTypeIdentifier documentTypeIdentifier; + + PeppolDocumentTypeIdAcronym(String identifier) { + documentTypeIdentifier = DocumentTypeIdentifier.of(identifier); + } + + @Override + public String toString() { + return documentTypeIdentifier.toString(); + } + + public DocumentTypeIdentifier toVefa() { + return documentTypeIdentifier; + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/identifier/PeppolProcessTypeIdAcronym.java b/oxalis-test/src/main/java/network/oxalis/test/identifier/PeppolProcessTypeIdAcronym.java new file mode 100644 index 0000000000000000000000000000000000000000..dad65ddee8f0e60bfddbe7dbeb3c82bb99966ce7 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/identifier/PeppolProcessTypeIdAcronym.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.identifier; + +import network.oxalis.vefa.peppol.common.model.ProcessIdentifier; + +/** + * Acronyms for the various PEPPOL processes. Makes life a little easier, as the + * ProcessIdentifier only represents a type safe value of any kind of string. + *

+ * According to Policy 16: + * PEPPOL processes are identified by the respective BII processes. + * The process identifier has to match the BII profile ID. + * + * @author Steinar Overbeck Cook + * @see "Tranport Policy for using Identifiers" + */ +public enum PeppolProcessTypeIdAcronym { + ORDER_ONLY("urn:www.cenbii.eu:profile:bii03:ver1.0"), + INVOICE_ONLY("urn:www.cenbii.eu:profile:bii04:ver1.0"), + PROCUREMENT("urn:www.cenbii.eu:profile:bii06:ver1.0"); + + private ProcessIdentifier processIdentifier; + + PeppolProcessTypeIdAcronym(String profileId) { + processIdentifier = ProcessIdentifier.of(profileId); + } + + public ProcessIdentifier toVefa() { + return processIdentifier; + } + + @Override + public String toString() { + return processIdentifier.toString(); + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/identifier/WellKnownParticipant.java b/oxalis-test/src/main/java/network/oxalis/test/identifier/WellKnownParticipant.java new file mode 100644 index 0000000000000000000000000000000000000000..d1a4a47f6e48d50ea0390770b0f42e29eae5d91f --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/identifier/WellKnownParticipant.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.identifier; + +import network.oxalis.vefa.peppol.common.model.ParticipantIdentifier; + +/** + * @author steinar + * Date: 05.11.13 + * Time: 14:00 + */ +public class WellKnownParticipant { + + public static final ParticipantIdentifier U4_TEST = ParticipantIdentifier.of("9908:810017902"); + + + public static final ParticipantIdentifier DIFI = ParticipantIdentifier.of("9908:991825827"); + + /** + * Use this in test mode + */ + public static final ParticipantIdentifier DIFI_TEST = ParticipantIdentifier.of("9908:810418052"); + + /** + * Random endpoint in test mode + */ + public static final ParticipantIdentifier RANDOM_TEST = ParticipantIdentifier.of("0208:0871221633"); + + /** + * Old organisation number for Balder Treindustri + */ + public static final ParticipantIdentifier DUMMY = ParticipantIdentifier.of("9908:976098897"); + +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/jetty/AbstractJettyServerTest.java b/oxalis-test/src/main/java/network/oxalis/test/jetty/AbstractJettyServerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ef21e9d802a91fa60d91b4a68e1adb462d78ffd2 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/jetty/AbstractJettyServerTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.jetty; + +import com.google.inject.Injector; +import com.google.inject.servlet.GuiceFilter; +import com.google.inject.servlet.GuiceServletContextListener; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; + +import javax.servlet.DispatcherType; +import java.util.EnumSet; + +public abstract class AbstractJettyServerTest { + + protected Injector injector; + + protected Server server; + + public abstract Injector getInjector(); + + @BeforeClass + public void beforeClass() throws Exception { + injector = getInjector(); + + server = new Server(8080); + + ServletContextHandler handler = new ServletContextHandler(server, "/"); + handler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class)); + handler.addEventListener(new GuiceServletContextListener() { + @Override + protected Injector getInjector() { + return injector; + } + }); + handler.addServlet(DefaultServlet.class, "/"); + + server.start(); + } + + @AfterClass + public void afterClass() throws Exception { + server.stop(); + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/lookup/MockLookupModule.java b/oxalis-test/src/main/java/network/oxalis/test/lookup/MockLookupModule.java new file mode 100644 index 0000000000000000000000000000000000000000..32792657bbd01aada7a70d0894a1bc32671cb628 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/lookup/MockLookupModule.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.lookup; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import io.opentracing.Span; +import network.oxalis.api.lang.OxalisTransmissionException; +import network.oxalis.api.lookup.LookupService; +import network.oxalis.test.security.CertificateMock; +import network.oxalis.vefa.peppol.common.model.Endpoint; +import network.oxalis.vefa.peppol.common.model.Header; +import network.oxalis.vefa.peppol.common.model.TransportProfile; +import org.mockito.Mockito; + +import javax.inject.Singleton; +import java.net.URI; + +public class MockLookupModule extends AbstractModule { + + private static LookupService lookupService = Mockito.mock(LookupService.class); + + public static void resetService() { + try { + Endpoint endpoint = Endpoint.of( + TransportProfile.of("bdx-transport-asd"), + URI.create("http://localhost/"), + CertificateMock.withCN("APP_00000042")); + + Mockito.reset(lookupService); + Mockito.when(lookupService.lookup(Mockito.any(Header.class))).thenReturn(endpoint); + Mockito.when(lookupService.lookup(Mockito.any(Header.class), Mockito.any(Span.class))).thenReturn(endpoint); + + } catch (OxalisTransmissionException e) { + // No action + } + } + + @Override + protected void configure() { + // No action. + } + + @Provides + @Singleton + LookupService providesLookupService() { + return lookupService; + } +} diff --git a/oxalis-test/src/main/java/network/oxalis/test/security/CertificateMock.java b/oxalis-test/src/main/java/network/oxalis/test/security/CertificateMock.java new file mode 100644 index 0000000000000000000000000000000000000000..20dcf5d8f7a164b9d1895ca96d5fc75562166cb9 --- /dev/null +++ b/oxalis-test/src/main/java/network/oxalis/test/security/CertificateMock.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.security; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.x509.X509V1CertificateGenerator; + +import javax.security.auth.x500.X500Principal; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.util.Date; + +public class CertificateMock { + + static { + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) + Security.addProvider(new BouncyCastleProvider()); + } + + public static X509Certificate withCN(String cn) { + try { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC"); + keyPairGenerator.initialize(1024, new SecureRandom()); // No ment to be secure! + + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + + X509V1CertificateGenerator certGen = new X509V1CertificateGenerator(); + X500Principal dnName = new X500Principal(String.format("CN=%s, C=NO", cn)); + + certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis())); + certGen.setSubjectDN(dnName); + certGen.setIssuerDN(dnName); // use the same + certGen.setNotBefore(new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000)); + certGen.setNotAfter(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000)); + certGen.setPublicKey(keyPair.getPublic()); + certGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); + + return certGen.generate(keyPair.getPrivate(), "BC"); + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } +} diff --git a/oxalis-test/src/main/resources/dummy/app_0000000001.cer b/oxalis-test/src/main/resources/dummy/app_0000000001.cer new file mode 100644 index 0000000000000000000000000000000000000000..08f93e4bac12c7ab42966b486e632027d6cf11b5 --- /dev/null +++ b/oxalis-test/src/main/resources/dummy/app_0000000001.cer @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC6zCCAdOgAwIBAgIEYfVWajANBgkqhkiG9w0BAQsFADAtMQswCQYDVQQGEwJO +TzEeMBwGA1UEAwwVRHVtbXkgQUNDRVNTIFBPSU5UIENBMB4XDTIyMDEyOTE0NTk1 +NFoXDTIzMDEyOTE0NTk1NFowQjELMAkGA1UEBhMCTk8xGjAYBgNVBAoMEU94YWxp +cyBUZXN0aW5nIDAxMRcwFQYDVQQDDA5BUFBfMDAwMDAwMDAwMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAK4+hVa0WEH3knaZ+OLBznmGaAK9WEXD4lV7 +0eoyWcKN38k066/6w0VBrZnU7PDaeVTTdfUYBXjeoVtUG8iY+4l5PE01vWEMXTYh +CD9jQAcUXFOGDblN32BlNjjbKSZD3lqEyd+l67+Ejp18P6pscxi8k3VFTgVmEawx +2KbLVa8FNvq9mvrtY9EUUxmgnVWZryV6Ygqt9AODjdxx5K0itwM45T94a8VwcprF +U72S8dfmLP1vO2XKp9C5QIqUq6heYIKGuj3J1eo4THQJ8ktLNBhypt0vWJSSS07J +2k/cUD/C7LB5lF5qxbZ82K1eYlOl7NvtSUxaQL/TChmNj6+/Ub8CAwEAATANBgkq +hkiG9w0BAQsFAAOCAQEAWW7tNtoFtCOUWLGgTYRJZNue6+ECnHTSX7ubxUMLTSJq +qyTkaAuMo2HlT2eOnIz+Saoufsb0ljeUFnVWHunwRUxqe4+GmnEKc42lDAqc2r5O +ayrSE6Otin1v3qnMmuDOPb2KqQBbfk+QA9g1vv/mVsA+LBfCAbdDm/vAevV8DF2m +zYB4ZY0yvQFSp4Wk6VP7akSLerhspvRsEjK2kMyU/KioUTI8OAiL7+hd3xZul354 +nTor1IHuKVY3pplSg246mo+yERhxHRKrtEVMnqdecpKChMED6X01NwvenYl20YHI +zyiO8v7ei6tGJqMmwybCDA6MlT0/d3eTu+rWckCHvA== +-----END CERTIFICATE----- diff --git a/oxalis-test/src/main/resources/dummy/app_0000000001.jks b/oxalis-test/src/main/resources/dummy/app_0000000001.jks new file mode 100644 index 0000000000000000000000000000000000000000..6b9b4ab5c8dfaaf5fcf8fc0e8f8d9624f7b47b21 Binary files /dev/null and b/oxalis-test/src/main/resources/dummy/app_0000000001.jks differ diff --git a/oxalis-test/src/main/resources/dummy/app_0000000002.cer b/oxalis-test/src/main/resources/dummy/app_0000000002.cer new file mode 100644 index 0000000000000000000000000000000000000000..480e1e4e6ac5bdeaf4d06011113f8b3aa4ecc86a --- /dev/null +++ b/oxalis-test/src/main/resources/dummy/app_0000000002.cer @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC6zCCAdOgAwIBAgIEYfVYVTANBgkqhkiG9w0BAQsFADAtMQswCQYDVQQGEwJO +TzEeMBwGA1UEAwwVRHVtbXkgQUNDRVNTIFBPSU5UIENBMB4XDTIyMDEyOTE1MDgw +NVoXDTIzMDEyOTE1MDgwNVowQjELMAkGA1UEBhMCTk8xGjAYBgNVBAoMEU94YWxp +cyBUZXN0aW5nIDAxMRcwFQYDVQQDDA5BUFBfMDAwMDAwMDAwMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAN450ML94QRXT8ClmRoaok9lpctOUD0UOh2m +GwSesdjkLG5zl3GIAkRJpclp4ZJlJ7bXA5GMU5NMCW5F133+PjTVNB6MEPv0+RDh +Is6MvSEQ0gn16324cxLwmYcAVtEcKO37tzaw+QjmcnpvpQTaOBfOLbVtO0/30RVb +6gO7ODK1WVFJGpcrWQJN9hX8Z3XXVx959Y4SfI+Ir4fPOOqCSVhTvHjyliGo647u +fsjrF7Fyxnx3Vi8RlbJhs+d2eq+s1S0RvpFI5uSQt4P6GF5RQ0U36AARw4RdIN/4 +vV3Wbl3lSMv8++nIkCZ0j8+GQ+GRov/NZ7HNHJyfXhjxUq2MEUsCAwEAATANBgkq +hkiG9w0BAQsFAAOCAQEAZoFXrnyyJWVWHHjksDRNbG0pgXxrDx/zNGgSq0jzN4Hd +8MvhiAhZdzJKLzfH1BCgnieNQMOKehuMsfBnwM1Ugyw7og9pHuUw3C1q23RICySV +UO7DNduAC7M517UW7gzjYOqW8Bo61ro3D+va7WxW5t2IBwwRvfBaSd31LZAqDPgY +5Q7ZjyI8zVzR1WijtHaDzhfeJBoF6Stt+lUrW9HscrL7O00IfaDQzOdLcNxSNmqz +LZ8sKQ7yhWV/ASF97nocRXfaktedn3Qe7o3W9f8+2Uofs03N+rbh1RPFrnnJ6QZZ +AeumcCcVlv/anuQJ3OEr7tju9iKAiw6+LjyizZFAag== +-----END CERTIFICATE----- diff --git a/oxalis-test/src/main/resources/dummy/app_0000000002.jks b/oxalis-test/src/main/resources/dummy/app_0000000002.jks new file mode 100644 index 0000000000000000000000000000000000000000..ac4e5a5a614d6c97b105b348243cdcdbd0751e02 Binary files /dev/null and b/oxalis-test/src/main/resources/dummy/app_0000000002.jks differ diff --git a/oxalis-test/src/main/resources/dummy/pki.xml b/oxalis-test/src/main/resources/dummy/pki.xml new file mode 100644 index 0000000000000000000000000000000000000000..05f7681e180b10b767c60824103a3931592e689f --- /dev/null +++ b/oxalis-test/src/main/resources/dummy/pki.xml @@ -0,0 +1,153 @@ + + + + + + + default + + + default + + + + + + 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 + g2XAc9hM + + + + MIIEYTCCA0mgAwIBAgIQFMW/Rg5g+LxmsCz1WMWIoTANBgkqhkiG9w0BAQUFADB1 + MQswCQYDVQQGEwJESzEnMCUGA1UEChMeTkFUSU9OQUwgSVQgQU5EIFRFTEVDT00g + QUdFTkNZMR8wHQYDVQQLExZGT1IgVEVTVCBQVVJQT1NFUyBPTkxZMRwwGgYDVQQD + ExNQRVBQT0wgUm9vdCBURVNUIENBMB4XDTEwMDIwMzAwMDAwMFoXDTIwMDEyNTIz + NTk1OVowgYsxCzAJBgNVBAYTAkRLMScwJQYDVQQKEx5OQVRJT05BTCBJVCBBTkQg + VEVMRUNPTSBBR0VOQ1kxHzAdBgNVBAsTFkZPUiBURVNUIFBVUlBPU0VTIE9OTFkx + MjAwBgNVBAMTKVBFUFBPTCBTRVJWSUNFIE1FVEFEQVRBIFBVQkxJU0hFUiBURVNU + IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnecW7XqU1we2+dcM + HnrKta+HM+dMCiBTA+/SoVG3zBF68w6V+hzMWRn7kOPvMbsGBbTnKwF68gl2QOOL + wfvsMWU/bAxIuwxlg0FQWVJ+Cc0NVwGIm67LKaZ09WnexzbC436Cluo+Bwc5hWch + L8FqXldPHcNG3i5FGIx9K/zn5FGA5AYSlOXb3M9SP3rcumOdOu/6FOvDmn2tzVRf + qS5mq9/wTYqZgftWNUHqN7OP0vMLMwPq/SepM9UfulRJbuXzmtXcd7d0B+DJ7qf2 + aiFgxkvYiTEbuAH39nFzRvatYD55AoDRFpr2h7E/hT5DEhH8Qcc6/kNxqfaKDdYm + GiO0MQIDAQABo4HVMIHSMBIGA1UdEwEB/wQIMAYBAf8CAQAwbAYDVR0fBGUwYzBh + oF+gXYZbaHR0cDovL3BpbG90b25zaXRlY3JsLnZlcmlzaWduLmNvbS9PZmZsaW5l + Q0EvTkFUSU9OQUxJVEFORFRFTEVDT01BR0VOQ1lQRVBQT0xSb290VEVTVENBLmNy + bDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFODHhUA1Ov0c8/Zewh8w0PJkoQJ3 + MB8GA1UdIwQYMBaAFOOv2HrEZHwZBv2rE5NkrOs/kKmEMA0GCSqGSIb3DQEBBQUA + A4IBAQCm1EKhpLur7bXGka0zPcOBuiQIVt06WZjVXo47VBn/bRaNRhprKUqjH6zF + 3KOzeXrVD/QQI119vy7GZMj2OSbGC77zHtozMxehKuZy0Yd5HUdqHljxVzAY9hf4 + lVyISGuNrZRK+Sb/NqmOtZVaSjc47DebLCWY550hI5F9n1wUZQgQZe6td7MQKFId + YLjGbscMPBYGjK0oJWBrc0qx4yc8kiH+hdk07KKSuHSLSVbve/lXUGSLc/vkkPlN + OWyU5xr8PnAhirE1rgVdKcqii7E8K+D0jh/eOaItTKuN3mhDBXA8EcUbgWZ6bIaG + aJKDCgyOoqIl//8hri15oX7rIFQI + + + + MIICzjCCAbagAwIBAgIEYfVWHzANBgkqhkiG9w0BAQsFADAlMQswCQYDVQQGEwJO + TzEWMBQGA1UEAwwNRHVtbXkgUm9vdCBDQTAeFw0yMjAxMjkxNDU4MzlaFw0yMzAx + MjkxNDU4MzlaMC0xCzAJBgNVBAYTAk5PMR4wHAYDVQQDDBVEdW1teSBBQ0NFU1Mg + UE9JTlQgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIdtJKWrBZ + EziKaIpJOI+PSKvh88zFZ/uk76pFUioU17z3dMYPxLZZO6oRbprBd/USBfsaxKbi + jS91zw6+MFM/3O3XeXlu3DSQzDc6fjYBPEHhbCSTZg4uT+IuoeBBQ1uaeoNvA5W+ + d8xJv7zaZkWTfbFGDNxuH9oBf3z6+oSFAcBmAYe4adHXpKBwDgZAIvSRUAgD9E40 + pms6pwDkZ8VDqiZcGdR0Yh7nFFf7j85KeuUm08r1M5Em8WHokJiIt8Z4o/d74HEp + 3E9uMmCl0kbpwIzwiyt8oiyh8KCBfO37AUGbVs1AJCMlQsjXJTlx+xhc9UGEk2up + oVw/o9UnN4N9AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAL67tnp6cNGwXPMjTu0J + 2KdnphXLmjJY/ALMzacvscchvGsHbq6DTrfta0IxZqOwNXym5DkgHql1oI1SvkNC + gUwhU3N3tATtRkrqIJTo72DiKqwXSGGY/CPRcmKUUkPdmpVeKHekHl+LSul0Dgki + Q/EXuAGGEQtElOoOGUipb1JnpWAJwbFhLn8r55T0xFEwxWkzUxsI4RzteCYe/I4e + 6eHrPsMo+s/sgXGde2FjXBGc1S9fXqiyEH3bhg8KYYRkMZbcn4QQXG61MoAAPbmP + hxchUIlQdX92tU5X1F0c2/10rvAjhPfCtRoFqvitHJ5THcbX0ShIkUmsGto7vFhy + Z8g= + + + + MIIC3DCCAcSgAwIBAgIEWIjvzDANBgkqhkiG9w0BAQsFADAlMQswCQYDVQQGEwJO + TzEWMBQGA1UEAwwNRHVtbXkgUm9vdCBDQTAeFw0xNzAxMjUxODM1MDdaFw0yNjAx + MjUxODM1MDdaMDsxCzAJBgNVBAYTAk5PMSwwKgYDVQQDDCNEdW1teSBTRVJWSUNF + IE1FVEFEQVRBIFBVQkxJU0hFUiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC + AQoCggEBAK3/okbXSCfaEV5wwsND8dgdnYSejMGiFH/WUAKamgqIto5kAr69/+u1 + rN6w9jKqsBFcrqRQD9M6LmsOsXlLXK5ySzSDAD+59nFXxABr1OrN2hV2YwRZYLVE + I/N/04spaTw6OmjNF/nmJdeGLAikWByYF8KDcOajmtz+j9+0xzjQm0GdoN0uIKdR + aFi68ZnSw5M7aPagFFiQb/kw/XEEYomEppcV089nssbiw88ooXPLYa9FxvPm135W + wrasNlSKIemQ8q7DW0LejRN9pAcj7NN0pkhGhA/oHmkFJG/hhZ486m3wTHc14+Fm + Kq9+qMXvENy4m+Uw/pOGqd75a6EqZW8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA + JFsrQEtoU39u9bx2NF4k22mUdswQ+/l6JNv/GIVPu8pY2NRF0Z2HM3a0MATglTlF + 1j9BXqhUr78IzTfQmmHHezdeklMKeZgJ+YjZs1ienw65Uqrxjb9Ik7Er/zJT9S4t + Gh9s4gfMUtVvNqe/+DBqhRw/B/nij3KNW1MmmVn0gcncWJQcq1Rjr1HfhQa4Bj0I + hpRaI/KHbpIFuWRcEaLm2EQg92+TfE0Iry6Fb/DrnBvwBROROUQZuvIDY4cNF4Da + 2BaLmu/wgxpJwGhojDQWLdXkoZHFNykFPo/0x9K/UiKxIKZy3nAezjPvJW5iEcX1 + VTLLVZ01Yt4/wctwPHoZ6w== + + + \ No newline at end of file diff --git a/oxalis-test/src/main/resources/oxalis_home/fake-oxalis.conf b/oxalis-test/src/main/resources/oxalis_home/fake-oxalis.conf new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/oxalis-test/src/main/resources/oxalis_home/logback-test.xml b/oxalis-test/src/main/resources/oxalis_home/logback-test.xml new file mode 100644 index 0000000000000000000000000000000000000000..9ba0de5fc0e2ef9287cc084396a4efa80f319e31 --- /dev/null +++ b/oxalis-test/src/main/resources/oxalis_home/logback-test.xml @@ -0,0 +1,42 @@ + + + + + + + + + %d %p [%c] %m %n + + + + + + + + + + + + + diff --git a/oxalis-test/src/main/resources/reference.conf b/oxalis-test/src/main/resources/reference.conf new file mode 100644 index 0000000000000000000000000000000000000000..987a2e4ca76b6c45bf40210071f96cf828a41407 --- /dev/null +++ b/oxalis-test/src/main/resources/reference.conf @@ -0,0 +1,26 @@ +oxalis.module.core.filesystem.override = network.oxalis.test.filesystem.TestFileSystemModule +oxalis.module.core.security.override = network.oxalis.test.dummy.DummyPkiModule + +mode.DUMMY.inherit = TEST +mode.DUMMY.security.pki = /dummy/pki.xml +mode.DUMMY.lookup.reader.class = network.oxalis.vefa.peppol.lookup.reader.BusdoxReader +mode.DUMMY.brave.reporter = slf4j + +oxalis.jdbc.connection.uri = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1" + + + +oxalis.module.test-asd.inbound = { + class = network.oxalis.test.asd.AsdInboundModule + dependency = inbound.servlet +} +oxalis.module.test-asd.outbound = { + class = network.oxalis.test.asd.AsdOutboundModule + dependency = outbound.lookup +} + +defaults.transport.asd = { + profile: bdx-transport-asd + sender: oxalis-asd + weight: -10000 +} diff --git a/oxalis-test/src/main/resources/security/oxalis-dummy-ca.jks b/oxalis-test/src/main/resources/security/oxalis-dummy-ca.jks new file mode 100644 index 0000000000000000000000000000000000000000..2cf8769ff03b0d456e3041ff60fdf8a80779d44d Binary files /dev/null and b/oxalis-test/src/main/resources/security/oxalis-dummy-ca.jks differ diff --git a/oxalis-test/src/main/resources/security/oxalis-dummy-keystore.jks b/oxalis-test/src/main/resources/security/oxalis-dummy-keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..a708d2d20063db7e6492b289774080c5b7efbecc Binary files /dev/null and b/oxalis-test/src/main/resources/security/oxalis-dummy-keystore.jks differ diff --git a/oxalis-test/src/test/java/network/oxalis/test/dummy/DummyPkiModuleTest.java b/oxalis-test/src/test/java/network/oxalis/test/dummy/DummyPkiModuleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2ff58240fca3f86bfb6af213ae703deb3fc31cf1 --- /dev/null +++ b/oxalis-test/src/test/java/network/oxalis/test/dummy/DummyPkiModuleTest.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.dummy; + +import com.google.inject.Inject; +import org.testng.Assert; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.security.KeyStore; + +@Guice(modules = DummyPkiModule.class) +public class DummyPkiModuleTest { + + @Inject + private KeyStore.PrivateKeyEntry privateKeyEntry; + + @Test + public void simple() { + Assert.assertNotNull(privateKeyEntry); + } +} diff --git a/oxalis-test/src/test/java/network/oxalis/test/identifier/PeppolDocumentTypeIdAcronymTest.java b/oxalis-test/src/test/java/network/oxalis/test/identifier/PeppolDocumentTypeIdAcronymTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c6e429e884e046c87f7152c5a7cf17af154cf2cc --- /dev/null +++ b/oxalis-test/src/test/java/network/oxalis/test/identifier/PeppolDocumentTypeIdAcronymTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.identifier; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class PeppolDocumentTypeIdAcronymTest { + + @Test + public void simple() { + Assert.assertEquals(PeppolDocumentTypeIdAcronym.valueOf("INVOICE"), PeppolDocumentTypeIdAcronym.INVOICE); + Assert.assertNotNull(PeppolDocumentTypeIdAcronym.INVOICE.toVefa()); + Assert.assertNotNull(PeppolDocumentTypeIdAcronym.INVOICE.toString()); + } +} diff --git a/oxalis-test/src/test/java/network/oxalis/test/identifier/PeppolProcessTypeIdAcronymTest.java b/oxalis-test/src/test/java/network/oxalis/test/identifier/PeppolProcessTypeIdAcronymTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c0efb3ec996773096bd1e0807bd7a6b191331305 --- /dev/null +++ b/oxalis-test/src/test/java/network/oxalis/test/identifier/PeppolProcessTypeIdAcronymTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2018 Norwegian Agency for Public Management and eGovernment (Difi) + * + * Licensed under the EUPL, Version 1.1 or – as soon they + * will be approved by the European Commission - subsequent + * versions of the EUPL (the "Licence"); + * + * You may not use this work except in compliance with the Licence. + * + * You may obtain a copy of the Licence at: + * + * https://joinup.ec.europa.eu/community/eupl/og_page/eupl + * + * Unless required by applicable law or agreed to in + * writing, software distributed under the Licence is + * distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the Licence for the specific language governing + * permissions and limitations under the Licence. + */ + +package network.oxalis.test.identifier; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class PeppolProcessTypeIdAcronymTest { + + @Test + public void simple() { + Assert.assertEquals( + PeppolProcessTypeIdAcronym.valueOf("INVOICE_ONLY"), + PeppolProcessTypeIdAcronym.INVOICE_ONLY + ); + Assert.assertNotNull(PeppolProcessTypeIdAcronym.INVOICE_ONLY.toVefa()); + Assert.assertNotNull(PeppolProcessTypeIdAcronym.INVOICE_ONLY.toString()); + } +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..d50809f2754dc314cfddb605bc3479762f461817 --- /dev/null +++ b/pom.xml @@ -0,0 +1,674 @@ + + + + + + 4.0.0 + + dk.erst.oxalis + oxalis + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + pom + + Oxalis :: Parent + Nemhandel e-Delivery Oxalis reference implementation + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + scm:git:https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis.git + https://rep.erst.dk/git/openebusiness/nemhandeledelivery/oxalis + + + + oxalis-api + oxalis-test + oxalis-commons + oxalis-inbound + oxalis-dist/oxalis-war + oxalis-outbound + oxalis-dist/oxalis-standalone + oxalis-dist/oxalis-server + oxalis-dist/oxalis-distribution + oxalis-legacy/oxalis-statistics + oxalis-legacy/oxalis-persistence + oxalis-legacy/oxalis-document-sniffer + oxalis-extension + + + + UTF-8 + 1.8 + 1.18.24 + 1.9 + 0.9.0-e2f4121ccb55b5a60e6edebf7b28d277741d6789 + 2.0.6 + 1.3.5 + 31.1-jre + 5.0.4 + 2.12.2 + 5.1.0 + 1 + 2.9.0 + 1.70 + 2.5.0 + 4.0.1 + 1.6.7 + 1.2.2 + 4.5.13 + 1.15 + 9.4.48.v20220622 + 2.7.3 + 2.1.214 + 2.7.1 + 0.33.0 + 1.0.0 + 0.3.3 + 0.4.1 + 0.0.5 + 5.14.1 + 2.16.3 + 7.5 + 4.9.0 + + + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + org.kohsuke.metainf-services + metainf-services + ${metainf-services.version} + provided + + + org.jetbrains + annotations + RELEASE + compile + + + + + + + + dk.erst.oxalis + oxalis-api + ${network.oxalis.version} + + + + + dk.erst.oxalis + oxalis-commons + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-inbound + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-outbound + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-persistence + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-persistence + test-jar + ${network.oxalis.version} + test + + + dk.erst.oxalis + oxalis-standalone + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-statistics + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-test + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-document-sniffer + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-extension-testbed + ${network.oxalis.version} + + + dk.erst.oxalis + oxalis-war + ${network.oxalis.version} + classes + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + com.google.guava + guava + ${guava.version} + + + + + net.sf.jopt-simple + jopt-simple + ${jopt-simple.version} + + + + + joda-time + joda-time + ${joda-time.version} + + + + + com.google.inject + guice + ${google.guice.version} + + + com.google.inject.extensions + guice-servlet + ${google.guice.version} + + + + javax.inject + javax.inject + ${javax.inject.version} + + + + org.apache.commons + commons-dbcp2 + ${commons-dbcp2.version} + + + + + org.bouncycastle + bcmail-jdk15on + ${bouncycastle.version} + + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + + + + + network.oxalis.vefa + peppol-common + ${vefa.peppol.version} + + + network.oxalis.vefa + peppol-evidence + ${vefa.peppol.version} + + + network.oxalis.vefa + peppol-icd + ${vefa.peppol.version} + + + network.oxalis.vefa + peppol-mode + ${vefa.peppol.version} + + + network.oxalis.vefa + peppol-lookup + ${vefa.peppol.version} + + + network.oxalis.vefa + peppol-sbdh + ${vefa.peppol.version} + + + network.oxalis.vefa + peppol-security + ${vefa.peppol.version} + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + + + + com.sun.mail + jakarta.mail + ${jakarta.mail.version} + + + jakarta.activation + jakarta.activation-api + ${jakarta.activation.version} + + + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-logging + commons-logging + + + + + commons-codec + commons-codec + ${commons-codec.version} + + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-servlet + ${jetty.version} + + + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb-java-client-version} + + + + + com.h2database + h2 + ${h2.version} + + + + + org.hsqldb + hsqldb + ${hsqldb.version} + + + + + io.opentracing + opentracing-api + ${opentracing.version} + + + io.opentracing + opentracing-noop + ${opentracing.version} + + + io.opentracing.brave + brave-opentracing + ${brave-opentracing.version} + + + io.opentracing.contrib + opentracing-apache-httpclient + ${opentracing-apache-httpclient.version} + + + io.opentracing.contrib + opentracing-web-servlet-filter + ${opentracing-web-servlet-filter.version} + + + io.opentracing.contrib + opentracing-spanmanager + ${opentracing-spanmanager.version} + + + + + io.zipkin.brave + brave + ${brave.version} + + + io.zipkin.reporter2 + zipkin-sender-urlconnection + ${zipkin-sender-urlconnection.version} + + + + + org.testng + testng + ${testng.version} + + + org.mockito + mockito-core + ${mockito-core.version} + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.4.2 + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + + org.apache.maven.scm + maven-scm-provider-gitexe + 1.13.0 + + + org.apache.maven.scm + maven-scm-api + 1.13.0 + + + + -Pdist + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.2 + + + org.apache.maven.plugins + maven-site-plugin + 3.12.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + + package-javadoc + package + + jar + + + + + ${java.encoding} + + true + *.jaxb.*:*.jaxb + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + false + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + ${java.encoding} + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.0 + + ${java.encoding} + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + enforce-maven + + enforce + + + + + + + [3.3,) + + + [1.8,) + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.8 + + + + prepare-agent + + + + report + test + + report + + + + + + + + + Erhvervsstyrelsen + https://nemhandel.dk/ + + + + + GNU Lesser General Public License (LGPL), Version 3.0 + http://www.gnu.org/licenses/lgpl-3.0.txt + repo + + + European Union Public Licence (EUPL v.1.1) + https://joinup.ec.europa.eu/community/eupl/og_page/european-union-public-licence-eupl-v11 + repo + + + + + + release-sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + + attach-javadocs + + jar + + + + + ${java.encoding} + + -Xdoclint:none + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + + --pinentry-mode + loopback + + + + + sign-artifacts + verify + + sign + + + + + + + + + + + + erst-artifactory-snapshots + erst-artifactory-snapshots + https://dev.erst.dk/artifactory/erst-snapshots-local + + + erst-artifactory + erst-artifactory + https://dev.erst.dk/artifactory/erst-components-local + + + +