44 changed files with 4253 additions and 2 deletions
@ -1,3 +1,24 @@
@@ -1,3 +1,24 @@
|
||||
# docmanagement |
||||
# docman |
||||
|
||||
DMS-Anbindung |
||||
DMS-Anbindung für SuperX |
||||
|
||||
|
||||
|
||||
Zur Installation |
||||
* Kopieren Sie die superx-docmanagement${version}.jar nach webapps/superx/WEB-INF/lib, und binden Sie das Servlet in der web.xml ein: |
||||
<servlet> |
||||
<servlet-name>DocMan</servlet-name> |
||||
<servlet-class>de.superx.docmanagement.DocMan</servlet-class> |
||||
</servlet> |
||||
<servlet-mapping> |
||||
<servlet-name>DocMan</servlet-name> |
||||
<url-pattern>/servlet/DocMan</url-pattern> |
||||
</servlet-mapping> |
||||
|
||||
* Starten Sie Tomcat neu |
||||
|
||||
Zum Build der Java Quellen installieren Sie |
||||
* Installieren Sie ANT, wenn noch nicht geschehen |
||||
* SuperX mit Java 17, und führen Sie aus: |
||||
ant -DWEBAPP=./superx ant distDocman |
||||
Damit wird die superx-docmanagement*.jar erzeugt und in den Ordner WEB-INF/lib kopiert. |
||||
@ -0,0 +1,103 @@
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project name="ModuleCreation" default="all" basedir="."> |
||||
<!-- |
||||
docman-JAR erzeugen: |
||||
. SQL_ENV_JAVA17 |
||||
ant -DWEBAPP=./superx distDocman |
||||
ant -DWEBAPP=./superx cleanBuildPath |
||||
--> |
||||
<dirname file="${ant.file.superx}" property="superxBuildBaseDir" /> |
||||
<property name="distDir" location="${superxBuildBaseDir}/superx/WEB-INF/lib" /> |
||||
|
||||
<property environment="env" /> |
||||
<!-- set global properties for this build --> |
||||
<property name="BASE_DIR" value="." /> |
||||
<property name="SUPERX_DIR" value="${WEBAPP}"/> |
||||
<property name="BUILD_PATH" value="${WEBAPP}/WEB-INF/classes"/> |
||||
<property name="SRC_DIR" value="${BASE_DIR}/src" /> |
||||
<property name="SRC_DIR_TEST" value="${BASE_DIR}/test-src"/> |
||||
<property name="LIB_SUPERX_DIR" value="${WEBAPP}/WEB-INF/lib"/> |
||||
<property name="LIB_WEBAPP_DIR" value="${WEBAPP}"/> |
||||
<property name="LIB_EXT_SUPERX_DIR" value="${WEBAPP}/WEB-INF/lib_ext"/> |
||||
|
||||
<property name="superx-classes" value="${WEBAPP}/WEB-INF/classes" /> |
||||
<property name="build_cobertura" value="${superxBuildBaseDir}/cobertura_build_classes" /> |
||||
<property name="test-target" value="${superxBuildBaseDir}/cobertura_build_tests"/> |
||||
<property name="superx-lib" value="${WEBAPP}/WEB-INF/lib" /> |
||||
<property name="build-results" value="${superxBuildBaseDir}/results" /> |
||||
<property name="build_cobertura_report" value="${superxBuildBaseDir}/coveragereport" /> |
||||
<property name="src-java" value="${SRC_DIR}"/> |
||||
<property name="test-resource" location="resource"/> |
||||
|
||||
|
||||
<property name="version" value="1.4" /> |
||||
|
||||
|
||||
|
||||
<dirname file="${ant.file}" property="moduleCreateBaseDir" /> |
||||
<property name="BASE_DIR" value="${moduleCreateBaseDir}/../.." /> |
||||
<property name="WEBAPP" value="" /> |
||||
<path id="classpath"> |
||||
<!--WEB-INF/lib--> |
||||
<fileset dir="${WEBAPP}/WEB-INF"> |
||||
<include name="lib/**/*.jar" /> |
||||
<include name="classes" /> |
||||
</fileset> |
||||
<fileset dir="${LIB_EXT_SUPERX_DIR}"> |
||||
<include name="**/*.jar" /> |
||||
</fileset> |
||||
<fileset dir="/home/superx/git/superx/superx/WEB-INF/lib"> |
||||
<include name="*.jar" /> |
||||
<exclude name="jarheaven_backup/**/*.jar" /> |
||||
</fileset> |
||||
</path> |
||||
|
||||
<taskdef name="groovy" |
||||
classname="org.codehaus.groovy.ant.Groovy" |
||||
classpathref="classpath"/> |
||||
<target name="initTimestamp"> |
||||
<tstamp> |
||||
<format property="SX_TIMESTAMP" pattern="dd.MM.yyyy HH:mm" /> |
||||
</tstamp> |
||||
</target> |
||||
<target name="distDocman" depends="compileSuperx" description="Erzeugt die superx-docman.jar. "> |
||||
<delete> |
||||
<fileset dir="${distDir}" includes="superx-etl*.jar" /> |
||||
</delete> |
||||
<jar destfile="${distDir}/superx-docmanagement${version}.jar" basedir="${BUILD_PATH}" includes="de/superx/docmanagement/**" excludes="**/*.java"> |
||||
<manifest> |
||||
<!-- Who is building this jar? --> |
||||
<attribute name="Built-By" value="superx"/> |
||||
<!-- Information about the program itself --> |
||||
<attribute name="Implementation-Date" value="${SX_TIMESTAMP}"/> |
||||
<attribute name="Implementation-Title" value="SuperX"/> |
||||
<attribute name="Implementation-Version" value="${version}"/> |
||||
</manifest> |
||||
</jar> |
||||
</target> |
||||
<target name="compileSuperx" depends="cleanBuildPath" description="Compile all classes for superx."> |
||||
<filter token="sxtimestamp" value="${SX_TIMESTAMP}" /> |
||||
<filter token="version" value="${etl_version}" /> |
||||
<copy todir="${BUILD_PATH}" filtering="true"> |
||||
<fileset dir="${SRC_DIR}"> |
||||
<include name="**/*.java" /> |
||||
|
||||
|
||||
</fileset> |
||||
</copy> |
||||
<!--source="1.8" target="1.8"--> |
||||
|
||||
<javac source="17" target="17" |
||||
srcdir="${BUILD_PATH}" excludes="**/*Test*.java,test/**/*" |
||||
destdir="${BUILD_PATH}" |
||||
listfiles="false" encoding="UTF-8" debug="yes"> |
||||
<classpath refid="classpath" /> |
||||
</javac> |
||||
</target> |
||||
<target name="cleanBuildPath" depends="initTimestamp" description="Löscht alle *.class-Dateien in WEB-INF/classes"> |
||||
<delete failonerror="false" includeemptydirs="true"> |
||||
<fileset dir="${BUILD_PATH}" includes="**/*.class,**/*.java" excludes="*.properties" /> |
||||
</delete> |
||||
</target> |
||||
|
||||
</project> |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
java -cp superx-docmanagement1.3.jar de.superx.docmanagement.HISConnektorTest $1 $2 |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
java -cp superx-docmanagement1.3.jar de.superx.docmanagement.Encryptor $1 |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
java -cp superx-docmanagement1.3.jar de.superx.docmanagement.ArchivePropHandler $1 $2 $3 |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopMetadatenLoader "$@" |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopDownloadTester $1 $2 |
||||
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopDownloadTester2 $1 $2 |
||||
Binary file not shown.
@ -0,0 +1,248 @@
@@ -0,0 +1,248 @@
|
||||
CampusSource · AGB und Lizenz |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Allgemeine Geschäftsbedingungen (AGB) und Lizenz |
||||
|
||||
|
||||
|
||||
|
||||
Mit CampusSource wird die Nutzung universitärer Entwicklungen durch Dritte zu |
||||
den Bedingungen der General GNU Public Licence (GPL) ermöglicht, die eine der |
||||
bekanntesten Opensource-Lizenzen ist. |
||||
Die GPL ist eine Lizenz, die dem amerikanischen Recht, nicht jedoch dem |
||||
deutschen Recht genügt. So sind einige Passagen der GPL nach dem deutschen Recht |
||||
nicht wirksam. CampusSource hat aus diesem Grunde Allgemeine |
||||
Geschäftsbedingungen formuliert, die die Interpretation der GPL unter deutschem |
||||
Recht vornimmt und ergänzt. |
||||
|
||||
|
||||
|
||||
Allgemeine Geschäftsbedingungen für die |
||||
Nutzung der Software der Initiative CampusSource |
||||
|
||||
|
||||
1. Vorbemerkung |
||||
Diese Allgemeinen Geschäftsbedingungen regeln die Rechtsbeziehungen zwischen dem |
||||
Land Nordrhein-Westfalen, vertreten durch die FernUniversität Hagen, diese |
||||
wiederum vertreten durch die Geschäftsstelle der Initiative CampusSource bei der |
||||
FernUniversität Hagen, Universitätsstraße 11, D-58097 Hagen (im Folgenden |
||||
»Lizenzgeber« genannt) und dem Nutzer (im Folgenden »Lizenznehmer« genannt) der |
||||
CampusSource-Software. Sie sind ebenso wie die GNU General Public License (siehe |
||||
dazu Abschnitt 4 »Lizenz«) Bestandteil des zwischen dem Lizenzgeber und dem |
||||
Lizenznehmer geschlossenen Vertrages. |
||||
Die GNU General Public License (im Folgenden GPL genannt) finden Sie im Internet |
||||
unter www.gnu.org/copyleft/gpl.html, eine deutsche Übersetzung unter |
||||
www.gnu.de/gpl-ger.html. |
||||
|
||||
|
||||
|
||||
2. Vertragsgegenstand |
||||
Gegenstand des Vertragsangebotes des Lizenzgebers ist die auf diesem Server |
||||
befindliche Software des CampusSource-Projektes (im Folgenden »Software« |
||||
genannt) und dazugehöriges Begleitmaterial. |
||||
Der Lizenzgeber bietet dem Lizenznehmer nach erfolgter Registrierung die |
||||
folgenden Leistungen an: |
||||
Der Lizenzgeber verschafft dem Lizenznehmer die Möglichkeit, auf |
||||
elektronischem Weg Zugang zur Software, deren Dokumentation und zu |
||||
Erfahrungsberichten zu erhalten und sich einen Überblick über das |
||||
Softwareangebot zu verschaffen. |
||||
|
||||
|
||||
Der Lizenzgeber gestattet dem Lizenznehmer, die Software physikalisch |
||||
downzuloaden. |
||||
|
||||
|
||||
Der Lizenzgeber überträgt die in Abschnitt 4 »Lizenz« näher bezeichneten |
||||
Nutzungsrechte auf den Lizenznehmer. |
||||
|
||||
|
||||
Lizenzgeber und Lizenznehmer sind sich einig darüber, dass die Inanspruchnahme |
||||
der unter 1.) bis 3.) angebotenen Leistungen unentgeltlich, schenkungsweise |
||||
erfolgen soll. Dies bedeutet jedoch nicht, dass der Lizenzgeber irgendwelche |
||||
durch die Nutzung des Angebots entstandenen Kosten übernimmt. |
||||
Sofern der Lizenznehmer die Software bearbeitet und diese Bearbeitung Dritten |
||||
zugänglich macht, ist er verpflichtet, dem Lizenzgeber auch eine Kopie der |
||||
Bearbeitung kostenlos zukommen zu lassen, oder, sofern die Bearbeitung |
||||
öffentlich und kostenlos zugänglich ist, dem Lizenzgeber die Quelle mitzuteilen. |
||||
Die in diesen Allgemeinen Geschäftsbedingungen festgelegten Nebenpflichten |
||||
stellen keine Gegenleistung im Sinne des Bürgerlichen Rechts dar und sind für |
||||
den Lizenznehmer verbindlich. Nicht Gegenstand des Vertrages sind irgendeine |
||||
Form von Softwareinstallation, Softwarepflege oder Beratung im Zusammenhang mit |
||||
der Software. Insbesondere wird durch die mit der Software beigefügte oder für |
||||
die Software bereitgestellte Information oder Dokumentation kein |
||||
Beratungsvertrag angeboten. Wenn Sie solche Dienstleistungen wünschen, wenden |
||||
Sie sich an die Geschäftsstelle der Initiative CampusSource. |
||||
Der Lizenzgeber behält sich vor, das Leistungsangebot jederzeit einzustellen. |
||||
Bezüglich bereits empfangener Leistungen bleiben die Verpflichtungen beider |
||||
Parteien hiervon unberührt, insbesondere entfallen dadurch nicht die in diesen |
||||
Allgemeinen Geschäftsbedingungen festgelegten Nebenpflichten des Lizenznehmers. |
||||
Diese Allgemeinen Geschäftsbedingungen gelten auch dann, wenn der Lizenznehmer |
||||
das oben genannte Leistungspaket nur teilweise in Anspruch nimmt. |
||||
|
||||
|
||||
|
||||
3. Sorgfaltspflichten des Lizenznehmers |
||||
Der Lizenznehmer ist verpflichtet, sein Passwort sorgfältig aufzubewahren und |
||||
Dritten nicht zugänglich zu machen. Der Lizenznehmer haftet für alle Schäden, |
||||
die aus der Verletzung dieser Sorgfaltspflicht entstehen. |
||||
|
||||
|
||||
|
||||
4. Lizenz |
||||
Die Nutzungsrechte, welche der Lizenznehmer erhält, ergeben sich aus der GNU |
||||
General Public License. Diese Nutzungsrechte sind dinglich - im Sinne des |
||||
Urheberrechts - mit der Software verknüpft und gelten auch dann, wenn der |
||||
Lizenznehmer keine Kenntnis davon nimmt. Die GNU General Public License (im |
||||
Folgenden GPL genannt) finden Sie im Internet unter |
||||
www.gnu.org/copyleft/gpl.html, eine deutsche Übersetzung unter |
||||
www.gnu.de/gpl-ger.html. |
||||
Die GPL ist zu dem Zweck entworfen worden, dass Sie die unter diese Lizenz |
||||
gestellte Software weitergeben und verändern dürfen. Wenn Sie die Software |
||||
verändern und weitergeben, müssen Sie den Quellcode der bearbeiteten Software |
||||
wieder unter die GPL stellen und den Quellcode zugänglich machen, so dass auch |
||||
andere von Ihrem Werk profitieren, wie auch Sie von der erhaltenen Software |
||||
profitiert haben. Auf diese Art und Weise soll ein System von jedermann frei |
||||
zugänglicher Software geschaffen werden. |
||||
Der Lizenzgeber weist den Lizenznehmer darauf hin, dass die GPL in den USA |
||||
entworfen wurde und daher einige Bestimmungen nach deutschem Recht nicht wirksam |
||||
sind oder in Deutschland rechtlich anders beurteilt werden als in den USA: |
||||
Die Formulierung »You may charge a fee for the physical act of transferring a |
||||
copy« in Abschnitt 1 der GPL ist nach deutschem Recht so zu verstehen, dass |
||||
nur eine angemessene, marktübliche Gegenleistung für die Anfertigung einer |
||||
Kopie verlangt werden darf. Sofern eine das marktübliche überschreitende |
||||
Gegenleistung für das Anfertigen von Kopien verlangt werden würde, hätte dies |
||||
neben einer möglichen Lizenzverletzung zur Folge, dass die durch die |
||||
kostenlose Weitergabe bestehende Haftungsprivilegierung wegfallen könnte und |
||||
der Lizenznehmer wie ein Verkäufer oder Unternehmer (Werkvertrag) bei Mängeln |
||||
auf Schadensersatz haftet. |
||||
|
||||
|
||||
Abschnitt 11 und 12 der GPL (Haftungsausschluss) verstoßen gegen das »Gesetz |
||||
zur Regelung des Rechts der Allgemeinen Geschäftsbedingungen« (AGBG) und sind |
||||
nach deutschem Recht unwirksam. An ihre Stelle treten die entsprechenden |
||||
Bestimmungen des Bürgerlichen Rechts §§ 521ff. (Haftung des Schenkers). |
||||
|
||||
|
||||
Es folgt eine kurze unvollständige Zusammenfassung der GPL. Der Lizenznehmer ist |
||||
verpflichtet, die weiterführenden und präziseren Bestimmungen der GPL zu |
||||
beachten. Der Lizenznehmer wird darauf hingewiesen, dass die GPL einige |
||||
(auflösende) Bedingungen enthält, bei deren Verletzung die dem Lizenznehmer |
||||
übertragenen Nutzungsrechte automatisch ohne jeden Widerruf erlöschen und eine |
||||
weitere Nutzung des Programms zu einer (strafbaren) Urheberrechtsverletzung |
||||
wird. |
||||
Die Lizenz erlaubt dem Lizenznehmer das Ausführen der Programme zu jedem |
||||
Zweck. Gesetzliche Einschränkungen werden hiervon nicht berührt. |
||||
|
||||
|
||||
Der Lizenznehmer darf unveränderte Kopien des Quellcodes anfertigen und |
||||
weiterverbreiten, unter der Bedingung, dass mit der Kopie ein entsprechender |
||||
Urheberrechtsvermerk sowie ein Haftungsausschluß veröffentlicht wird und dass |
||||
alle die GPL betreffenden Hinweise unverändert weitergegeben werden. Ein |
||||
Entgelt darf nur für die Anfertigung von Kopien oder für das Anbieten einer |
||||
Garantie genommen werden. Näheres enthält § 1 GPL. |
||||
|
||||
|
||||
Der Lizenznehmer darf das Programm verändern und die so entstandene |
||||
Bearbeitung unter der Bedingung vervielfältigen und verbreiten, dass er einen |
||||
auffälligen Vermerk über die vorgenommenen Modifizierungen anbringt, die |
||||
Kopien der Bearbeitung ohne Lizenzgebühren unter den Bedingungen der GPL |
||||
verbreitet und dafür sorgt, dass das Programm bei interaktiver Nutzung einen |
||||
Urheberrechtsvermerk ausgibt. Näheres regelt § 2 GPL. |
||||
|
||||
|
||||
Der Lizenznehmer darf das Programm oder eine Bearbeitung als Objectcode oder |
||||
in ausführbarer Form unter Berücksichtigung der letzten beiden Abschnitte |
||||
unter der Bedingung vervielfältigen und verbreiten, dass er den Quelltext |
||||
beifügt oder eine der in § 3 GPL genannten Alternativen erfüllt. Näheres |
||||
regelt § 3 GPL. |
||||
|
||||
|
||||
Sollte dem Lizenznehmer infolge eines Gerichtsurteils oder durch einen |
||||
gerichtlichen Vergleich Bedingungen auferlegt werden, die der GPL |
||||
widersprechen, so entbindet dies den Lizenznehmer nicht von der Einhaltung der |
||||
GPL. Näheres regelt § 7 GPL. |
||||
|
||||
|
||||
Wenn die Verbreitung oder die Benutzung des Programms in bestimmten Staaten |
||||
durch Patent- oder Urheberrecht eingeschränkt ist, kann der Lizenznehmer bei |
||||
der Verbreitung des Programms durch einen entsprechenden Vermerk bestimmen, |
||||
dass die Verbreitung des Programms in bestimmten Staaten ausgeschlossen ist. |
||||
Näheres regelt § 8 GPL. |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5. Schutzrechte Dritter |
||||
Der Lizenzgeber geht davon aus, dass der Besitz und der vertragsgemäße Gebrauch |
||||
der Software keine Schutzrechte Dritter für den Bereich der BRD beeinträchtigt. |
||||
Im Zusammenhang mit einer möglichen Beeinträchtigung der Schutzrechte Dritter |
||||
werden die folgenden Nebenpflichten vereinbart: |
||||
Der Lizenznehmer verpflichtet sich, dass er weder für sich noch im Auftrag |
||||
eines Dritten die Software zu dem Zweck verwendet, diese nach |
||||
Schutzrechtsverletzungen zu untersuchen oder untersuchen zu lassen. |
||||
|
||||
|
||||
Der Lizenznehmer verpflichtet sich, den Lizenzgeber unverzüglich zu |
||||
benachrichtigen, wenn Dritte Schutzrechtsverletzungen geltend machen. |
||||
|
||||
|
||||
Hat der Lizenznehmer den Eindruck, dass die Software Patente oder andere |
||||
Schutzrechte Dritter verletzt, so ist er verpflichtet, den Lizenzgeber |
||||
unverzüglich schriftlich unter Beifügung einer genauen Beschreibung der |
||||
Verletzungshandlung zu unterrichten. Es ist dem Lizenznehmer untersagt, andere |
||||
natürliche oder juristische Personen ohne schriftliches Einverständnis des |
||||
Lizenzgebers zu informieren. |
||||
|
||||
|
||||
Bei Verletzung einer der obigen Nebenpflichten verpflichtet sich der |
||||
Lizenznehmer, dem Lizenzgeber Schadensersatz für alle durch die Verletzung |
||||
entstandenen Schäden (einschließlich der Prozeßkosten) zu leisten. Ist die |
||||
Verletzung einer solchen Nebenpflicht festgestellt, so genügt es, wenn der |
||||
Lizenzgeber plausibel darlegt, dass der Schaden durch die Verletzung entstanden |
||||
ist. Den Lizenznehmer trifft die volle Beweislast für das Gegenteil. Der |
||||
Lizenznehmer verpflichtet sich, dem Lizenzgeber alle Auskünfte im Zusammenhang |
||||
mit der Verletzung einer der obigen Nebenpflichten zu erteilen. |
||||
Der Lizenzgeber weist darauf hin, dass zur CampusSource-Software nicht die |
||||
Software anderer Hersteller gehört, mit der die CampusSource-Software |
||||
zusammenarbeiten kann oder die für den Betrieb der CampusSource-Software |
||||
notwendigerweise vorhanden sein muss, wie z. B. WWW-Server, |
||||
Funktionsbibliotheken, Werkzeugsysteme und Datenbankmanagementsysteme. Die |
||||
Lizenzen für diese Software müssen vom jeweiligen Hersteller separat erworben |
||||
werden. Die GPL gilt für diese Software in der Regel nicht. |
||||
|
||||
|
||||
|
||||
6. Datenschutz |
||||
Der Lizenzgeber verpflichtet sich, bezüglich der bei der Registrierung |
||||
angegebenen Daten die einschlägigen landes- und bundesrechtlichen |
||||
Datenschutzbestimmungen einzuhalten. Alle Verbindungen zu diesem Server im |
||||
Download- und Registrierbereich werden in einem LOG-File aufgezeichnet. |
||||
|
||||
|
||||
|
||||
7. Schriftform |
||||
Alle Nebenabreden, die zwischen dem Lizenzgeber und dem Lizenznehmer |
||||
abgeschlossen werden, bedürfen der Schriftform. Eine Abänderung oder Aufhebung |
||||
dieser Klausel bedarf ebenfalls der Schriftform. |
||||
|
||||
|
||||
|
||||
8. Gerichtsstand |
||||
Gerichtsstand für alle Streitigkeiten aus diesem Vertrag ist Hagen, sofern der |
||||
Lizenznehmer Kaufmann, eine juristische Person des öffentlichen Rechts oder ein |
||||
öffentlich-rechtliches Sondervermögen ist. |
||||
Die Parteien vereinbaren die Anwendung deutschen Rechts. Sollte nach |
||||
Internationalem Verfahrensrecht die Zuständigkeit eines deutschen Gerichts |
||||
möglich sein, so vereinbaren die Parteien die Zuständigkeit der deutschen |
||||
Gerichtsbarkeit und innerhalb Deutschlands die Zuständigkeit des Amtsgerichtes |
||||
bzw. Landgerichtes Hagen. Bezüglich der in Abschnitt 5 »Schutzrechte Dritter« |
||||
festgelegten Nebenpflichten des Lizenznehmers kann der Lizenzgeber abweichend |
||||
von Satz 3 ein beliebiges international zuständiges Gericht anrufen. |
||||
© 2000 CampusSource Alle Rechte vorbehalten |
||||
|
||||
|
||||
|
||||
@ -0,0 +1,603 @@
@@ -0,0 +1,603 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.Proxy; |
||||
import java.net.URL; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.ResultSetMetaData; |
||||
import java.sql.SQLException; |
||||
import java.sql.Statement; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
import jakarta.servlet.ServletException; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
|
||||
import de.memtext.util.DateUtils; |
||||
import de.superx.common.SxUser; |
||||
import de.superx.servlet.SxPools; |
||||
|
||||
public abstract class AbstractDocPresenter { |
||||
private static final long serialVersionUID = 1; |
||||
static final String MANDANTENID = "default"; |
||||
final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman"); |
||||
private Proxy proxy = null; |
||||
private String sys; |
||||
// Vorlage für einzelne URLS zum DokuServer in der z.B: DocID ersetzt werden
|
||||
// muss
|
||||
private String urlVorlage; |
||||
// HTML+Freemarker Vorlage für ein HTML-Menü, falls es mehrere Subdokumente
|
||||
// gibt.
|
||||
private String menuVorlage; |
||||
// SQL zum Lesen der Anzahl von Dokumenten pro ID
|
||||
private String readDocumentCountSql; |
||||
// Lesen von Dokumenten mit optional auch mehreren Attributen
|
||||
private String readDocumentListSql; |
||||
// optional: SQL zum Löschen abgelaufener Berechtigungen
|
||||
private String deleteOldRightsSql; |
||||
// SQL zum Lesen der Berechtigungen auf eine ID für einen User
|
||||
private String readIdRightSql; |
||||
// SQL zum Lesen der Berechtigungen auf eine docId für einen User (für
|
||||
// Untermenü)
|
||||
private String readDocIdRightSql; |
||||
// ID to DocID
|
||||
private String readDocIdSql; |
||||
// HauptDokumentID für eine ID suchen
|
||||
private String readMainDocIdSql; |
||||
private boolean isDirectLinkToDocMWanted = true; |
||||
private boolean isDocMenuAlwaysWanted=false; |
||||
private boolean isRenewAuthentificationOnErrorWanted=false; |
||||
|
||||
|
||||
protected AbstractDocPresenter(String sys, String params) throws ServletException { |
||||
setSys(sys); |
||||
initSystem(); |
||||
checkConfiguration(); |
||||
} |
||||
|
||||
protected boolean isRenewAuthentificationOnErrorWanted() |
||||
{ |
||||
return isRenewAuthentificationOnErrorWanted; |
||||
} |
||||
protected void setRenewAuthentificationOnErrorWanted(boolean b) |
||||
{ |
||||
this.isRenewAuthentificationOnErrorWanted=b; |
||||
} |
||||
protected void renewAuthentification() throws IOException |
||||
{ |
||||
throw new IllegalStateException("nicht unterstützt"); |
||||
} |
||||
|
||||
protected void setDocMenuAlwaysWanted(boolean isDocMenuAlwaysWanted) |
||||
{ |
||||
this.isDocMenuAlwaysWanted=isDocMenuAlwaysWanted; |
||||
} |
||||
protected void setProxy(Proxy proxy) { |
||||
this.proxy = proxy; |
||||
} |
||||
|
||||
protected void checkConfiguration() { |
||||
if (urlVorlage == null) |
||||
throw new IllegalStateException("urlVorlage ist null"); |
||||
if (readDocumentCountSql == null) |
||||
throw new IllegalStateException("readDocumentCountSql ist null"); |
||||
if (readDocumentListSql == null) |
||||
throw new IllegalStateException("readDocumentListSql ist null"); |
||||
if (readIdRightSql == null) |
||||
throw new IllegalStateException("readIdRightSql ist null"); |
||||
if (readDocIdSql == null) |
||||
throw new IllegalStateException("readDocIdSql ist null"); |
||||
if (readMainDocIdSql == null) |
||||
throw new IllegalStateException("readMainDocIdSql ist null"); |
||||
// menuVorlage und readDocumentListSql dürfen null sein, wenn für konkreten Fall
|
||||
// nicht genutzt
|
||||
} |
||||
|
||||
abstract void initSystem() throws ServletException; |
||||
|
||||
protected boolean isDirectLinkToDocMWanted() { |
||||
return isDirectLinkToDocMWanted; |
||||
} |
||||
|
||||
protected void setDirectLinkToDocMWanted(boolean isDirectLinkToDocMWanted) { |
||||
this.isDirectLinkToDocMWanted = isDirectLinkToDocMWanted; |
||||
} |
||||
|
||||
protected DocPresentationResult getReply(HttpServletRequest request, SxUser user) { |
||||
DocPresentationResult dpresult = new DocPresentationResult(); |
||||
Map<String, String> params = readParams(request); |
||||
if (isAccessAllowed(user, params)) { |
||||
try { |
||||
updateDocResult(params, dpresult); |
||||
} catch (Exception e) { |
||||
String id = getId(params); |
||||
String doc_id = params.get("doc_id"); |
||||
logger.severe("sys:"+sys+" Berechtigung vorhanden, aber Fehler bei der Ermittlung von Dokument " |
||||
+ (id != null ? " ID=" + id : "") + (doc_id != null ? " docID:" + doc_id : "") + " " |
||||
+ getExceptionStackTrace(e)); |
||||
} |
||||
} else { |
||||
dpresult.setMessage("Berechtigungsfehler in sys:"+sys); |
||||
} |
||||
if (!dpresult.isOK()) { |
||||
dpresult.setMessage("Es konnte keine DocManagement URL ermittelt werden in sys:"+sys); |
||||
} |
||||
return dpresult; |
||||
} |
||||
|
||||
/** |
||||
* TODO ggfs. in utils auslagern |
||||
* |
||||
* @param e |
||||
* @return |
||||
*/ |
||||
String getExceptionStackTrace(Exception e) { |
||||
String result = ""; |
||||
StringWriter sw = new StringWriter(); |
||||
PrintWriter pw = new PrintWriter(sw); |
||||
e.printStackTrace(pw); |
||||
result = sw.toString(); |
||||
pw.close(); |
||||
return result; |
||||
} |
||||
|
||||
protected Map<String, String> readParams(HttpServletRequest request) { |
||||
logger.info("DocPresenter ("+sys+"): Lese Parameter aus Request"); |
||||
Map<String, String> params = new HashMap<String, String>(); |
||||
|
||||
String id = DocMan.getParameter(request, "id"); |
||||
String doc_id = DocMan.getParameter(request, "doc_id"); |
||||
if ((id == null || id.length() == 0) && (doc_id == null || doc_id.length() == 0)) |
||||
throw new IllegalArgumentException("Param id oder doc_id muss angegeben werden"); |
||||
params.put("id", id); |
||||
if (doc_id != null) |
||||
params.put("doc_id", doc_id); |
||||
|
||||
String main_doc_only = DocMan.getParameter(request, "main_doc_only"); |
||||
if (main_doc_only != null && main_doc_only.equalsIgnoreCase("false")) { |
||||
params.put("main_doc_only", "false"); |
||||
} else { |
||||
params.put("main_doc_only", "true"); |
||||
} |
||||
return params; |
||||
} |
||||
|
||||
/** |
||||
* Wenn in den params eine id vorhanden ist, wird die Berechtigung dafür |
||||
* geprüft, ist es eine doc_id auch dafür |
||||
* |
||||
* @param user |
||||
* @param params |
||||
* @return |
||||
*/ |
||||
protected boolean isAccessAllowed(SxUser user, Map<String, String> params) { |
||||
boolean isAccessAllowed = false; |
||||
if (deleteOldRightsSql != null) { |
||||
logger.fine("DocPresenter ("+sys+"): Lösche etwaige abgelaufene Berechtigungen"); |
||||
executeUpdate(deleteOldRightsSql); |
||||
} |
||||
String id = getId(params); |
||||
if (id != null) { |
||||
isAccessAllowed = isIdAllowed(user, id); |
||||
} |
||||
String doc_id = params.get("doc_id"); |
||||
if (doc_id != null) { |
||||
isAccessAllowed = isDocIdAllowed(user, doc_id); |
||||
} |
||||
|
||||
return isAccessAllowed; |
||||
} |
||||
|
||||
boolean isDocIdAllowed(SxUser user, String doc_id) { |
||||
boolean isAccessAllowed = false; |
||||
int count = readIntFromDB("Berechtigung für DocId suchen sys:"+sys, readDocIdRightSql, (Integer) user.getId(), doc_id); |
||||
if (count > 0) |
||||
isAccessAllowed = true; |
||||
logger.info("DocPresenter: Für User " + user.getName() + " (userinfo.tid=" + user.getId() + ") aktuell " + count |
||||
+ " Rechte für DocId " + doc_id + " gefunden (sys:"+sys+")"); |
||||
return isAccessAllowed; |
||||
} |
||||
|
||||
private boolean isIdAllowed(SxUser user, String id) { |
||||
boolean isAccessAllowed = false; |
||||
int count = readIntFromDB("Berechtigung für ID suchen sys:"+sys, readIdRightSql, (Integer) user.getId(), id); |
||||
if (count > 0) |
||||
isAccessAllowed = true; |
||||
logger.fine("DocPresenter: Für User " + user.getName() + " (userinfo.tid=" + user.getId() + ") aktuell " + count |
||||
+ " Rechte für "+id+" gefunden (sys:"+sys+")"); |
||||
return isAccessAllowed; |
||||
} |
||||
|
||||
String getSys() { |
||||
return sys; |
||||
} |
||||
|
||||
private void setSys(String sys) { |
||||
this.sys = sys; |
||||
} |
||||
|
||||
protected void updateDocResult(Map<String, String> params, DocPresentationResult result) throws Exception { |
||||
if (hasDocId(params)) { |
||||
String doc_id = params.get("doc_id"); |
||||
logger.info("DocPresenter ("+sys+"): Für doc_id " + doc_id + " direkt ausgeliefert"); |
||||
updateDocLink(result, doc_id); |
||||
} |
||||
|
||||
else { |
||||
if (params.get("main_doc_only").contentEquals("true")) { |
||||
logger.info("DocPresenter ("+sys+"): Liefere nur Hauptdokument"); |
||||
updateDocLink(result, getMainDocId(getId(params))); |
||||
|
||||
} else { |
||||
int docCount = readDocumentCount(getId(params)); |
||||
if (docCount==1&&isDocMenuAlwaysWanted) docCount=99; |
||||
switch (docCount) { |
||||
case 0: |
||||
logger.info("DocPresenter ("+sys+"): Für id " + getId(params) + " keine relevanten Angaben in Datenbank gefunden"); |
||||
result.setMessage("Keine relevanten Angaben in der Datenbank gefunden"); |
||||
break; |
||||
|
||||
case 1: |
||||
// wenn es für eine ID nur eine einzige DocId gibt, diese direkt liefern
|
||||
logger.info("DocPresenter ("+sys+"): Für id " + getId(params) |
||||
+ " für ein Dokument gefunden, wird direkt ausgeliefert"); |
||||
updateDocLink(result, readDocIdFromDatabase(params)); |
||||
|
||||
break; |
||||
// mehr als ein Dokument oder Menü auf jeden Fall gewünscht
|
||||
default: |
||||
logger.info("DocPresenter ("+sys+"): Für id " + getId(params) |
||||
+ " wird Auswahlmenü mit Einzeldokumenten dargestellt"); |
||||
result.setMessage(getDocumentMenu(params)); |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
private String getDocumentMenu(Map<String, String> params) { |
||||
String result; |
||||
String id = getId(params); |
||||
logger.info("DocPresenter ("+sys+"): Ermittle DokumentenListe für id " + id); |
||||
List<Map<String, String>> doclist = readDocumentList(getId(params)); |
||||
try { |
||||
for (Map<String, String> einEintrag : doclist) { |
||||
if (!einEintrag.containsKey("doc_id")) throw new IllegalStateException("Liste für Einzeldokumente sys="+sys+" enhält keine doc_id,ReadDocumentListSql anpassen!"); |
||||
String urlString = ""; // Freemarker arbeitet mit LeerString nicht null
|
||||
DocPresentationResult dpResult = new DocPresentationResult(); |
||||
String doc_id=einEintrag.get("doc_id"); |
||||
if (doc_id==null||doc_id.length()==0) throw new IllegalStateException("Keine doc_id zu id "+id+ " gefunden! sys="+sys); |
||||
updateDocLink(dpResult,doc_id ); |
||||
|
||||
// interner/externer Link
|
||||
if (dpResult.getDocManagementUrl() != null) { |
||||
if (isDirectLinkToDocMWanted) { |
||||
urlString = dpResult.getDocManagementUrl().toString(); |
||||
} else { |
||||
// verweis auf eine konkrete DocID,da für eine id (UFR vim) mehrere Dokumente
|
||||
// geben kann
|
||||
urlString = "/superx/servlet/DocMan?sys=" + getSys() + "&doc_id=" + einEintrag.get("doc_id"); |
||||
} |
||||
} |
||||
einEintrag.put("doc_link", urlString); |
||||
} |
||||
HashMap map = new HashMap(); |
||||
map.put("doclist", doclist); |
||||
|
||||
logger.info("DocPresenter ("+sys+"): Erstellte HTML für DokumentenListe für id " + id + " mittels Freemarker"); |
||||
result = SxPools.get(MANDANTENID).getTemplateProcessor().process(map, null, "DocManagementMenu", |
||||
menuVorlage, null, SxPools.get(MANDANTENID).getRepository(), |
||||
SxPools.get(MANDANTENID).getSqlDialect()); |
||||
} catch (Exception e) { |
||||
result = "Fehler bei der Erzeugung von Menü für Einzeldokumente"; |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
abstract protected void updateDocLink(DocPresentationResult result, String id) throws Exception; |
||||
|
||||
/** |
||||
* HauptDokument für eine id Berechtigungskontrolle is vorher schon gelaufen |
||||
* |
||||
* @param id |
||||
* @return |
||||
*/ |
||||
private String getMainDocId(String id) { |
||||
return readStringFromDB(readMainDocIdSql, id); |
||||
} |
||||
|
||||
protected String adaptUrl(String marker, String value) { |
||||
if (urlVorlage == null || urlVorlage.trim().length() == 0) |
||||
throw new IllegalStateException("Keine URL-Vorlage für Dokumentenmanagesystem gefunden (sys:"+sys+")"); |
||||
return urlVorlage.replaceAll(marker, value); |
||||
} |
||||
|
||||
/** |
||||
* Liefert zu einer als Parameter übergebenen ID, die zugehörige DocID des |
||||
* DokumentenManagement-Servers |
||||
* |
||||
* @param params |
||||
* @return |
||||
*/ |
||||
|
||||
protected String readDocIdFromDatabase(Map<String, String> params) { |
||||
return readStringFromDB(readDocIdSql, getId(params)); |
||||
} |
||||
|
||||
/** |
||||
* Liefert, wieviele Einzeldokument für eine als Parameter übergebene ID gibt |
||||
* |
||||
* @param id |
||||
* @return |
||||
*/ |
||||
protected int readDocumentCount(String id) { |
||||
return readIntFromDB("Ermittlung Anzahl der Dokument für ID " + id+ "(sys:"+sys+")", readDocumentCountSql, null, id); |
||||
} |
||||
|
||||
/** |
||||
* Liest Liste von Infos zu einzelnen Doc zu einer VIM-Nummer |
||||
*/ |
||||
protected List<Map<String, String>> readDocumentList(String id) { |
||||
return readAttribMapsFromDB(readDocumentListSql, id); |
||||
} |
||||
|
||||
String getReadDocIdRightSql() { |
||||
return readDocIdRightSql; |
||||
} |
||||
|
||||
void setReadDocIdRightSql(String readDocIdRightSql) { |
||||
this.readDocIdRightSql = readDocIdRightSql; |
||||
} |
||||
|
||||
protected String getId(Map<String, String> params) { |
||||
return params.get("id"); |
||||
} |
||||
|
||||
boolean hasDocId(Map<String, String> params) { |
||||
return params.containsKey("doc_id"); |
||||
} |
||||
|
||||
protected void setMenuVorlage(String vorlage) { |
||||
menuVorlage = vorlage; |
||||
logger.info("DocPresenter ("+sys+"): MenuVorlage gesetzt"); |
||||
} |
||||
|
||||
protected void setUrlVorlage(String vorlage) { |
||||
urlVorlage = vorlage; |
||||
if (urlVorlage == null || urlVorlage.trim().length() == 0) |
||||
throw new IllegalStateException("Keine URL-Vorlage für Dokumentenmanagesystem gefunden für sys="+sys); |
||||
logger.info("DocPresenter ("+sys+"): UrlVorlage gesetzt"); |
||||
} |
||||
|
||||
String getUrlVorlage() { |
||||
return urlVorlage; |
||||
} |
||||
|
||||
protected void setReadMainDocIdSql(String readMainDocIdSql) { |
||||
this.readMainDocIdSql = readMainDocIdSql; |
||||
} |
||||
|
||||
protected void setReadDocIdSql(String readDocIdSql) { |
||||
this.readDocIdSql = readDocIdSql; |
||||
} |
||||
|
||||
protected void setReadIdRightSql(String readIdRightSql) { |
||||
this.readIdRightSql = readIdRightSql; |
||||
} |
||||
|
||||
protected void setDeleteOldRightsSql(String deleteOldRightsSql) { |
||||
this.deleteOldRightsSql = deleteOldRightsSql; |
||||
} |
||||
|
||||
protected void setReadDocumentListSql(String readDocumentListSql) { |
||||
this.readDocumentListSql = readDocumentListSql; |
||||
} |
||||
|
||||
protected void setReadDocumentCountSql(String readDocumentCountSql) { |
||||
this.readDocumentCountSql = readDocumentCountSql; |
||||
} |
||||
|
||||
protected String readStringFromDB(String sql, String param1) { |
||||
return readStringFromDB(sql, param1, null); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param sql |
||||
* @param param1 - kann null sein, wird dann nicht gesetzt |
||||
* @return |
||||
*/ |
||||
protected String readStringFromDB(String sql, String param1, String param2) { |
||||
String result = "NICHTS_GEFUNDEN"; |
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
PreparedStatement pst = con.prepareStatement(sql); |
||||
if (param1 != null) |
||||
pst.setString(1, param1); |
||||
if (param2 != null) |
||||
pst.setString(2, param2); |
||||
ResultSet rs = pst.executeQuery(); |
||||
while (rs.next()) { |
||||
result = rs.getString(1); |
||||
} |
||||
rs.close(); |
||||
pst.close(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
throw new IllegalStateException("Fehler bei DocManagement (sys:"+sys+")"); |
||||
} |
||||
if (result.equals("NICHTS_GEFUNDEN")) |
||||
throw new IllegalArgumentException("DocManagement ("+sys+"): Keine Angaben in der Datenbank gefunden ("+sql+" "+param1+" "+param2==null?"":param2); |
||||
return result; |
||||
} |
||||
|
||||
protected void executeUpdate(String sql) { |
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
Statement stm = con.createStatement(); |
||||
stm.executeUpdate(sql); |
||||
stm.close(); |
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
throw new IllegalStateException("Fehler bei DocManagement ("+sys+")"); |
||||
} |
||||
} |
||||
|
||||
protected List<String> readStringsFromDB(String sql, String param1) { |
||||
List<String> result = new LinkedList<String>(); |
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
PreparedStatement pst = con.prepareStatement(sql); |
||||
if (param1 != null) |
||||
pst.setString(1, param1); |
||||
ResultSet rs = pst.executeQuery(); |
||||
while (rs.next()) { |
||||
result.add(rs.getString(1)); |
||||
} |
||||
rs.close(); |
||||
pst.close(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
throw new IllegalStateException("Fehler bei DocManagement ("+sys+") "); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
protected List<Map<String, String>> readAttribMapsFromDB(String sql, String param1) { |
||||
List<Map<String, String>> result = new LinkedList<Map<String, String>>(); |
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
PreparedStatement pst = con.prepareStatement(sql); |
||||
if (param1 != null) |
||||
pst.setString(1, param1); |
||||
ResultSet rs = pst.executeQuery(); |
||||
while (rs.next()) { |
||||
result.add(getHashMap(rs)); |
||||
} |
||||
rs.close(); |
||||
pst.close(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
throw new IllegalStateException("Fehler bei DocManagement ("+sys+") " + e); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
Map<String, String> readMapFromDB(String sql, String param1) { |
||||
Map<String, String> result = new HashMap<String, String>(); |
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
PreparedStatement pst = con.prepareStatement(sql); |
||||
if (param1 != null) |
||||
pst.setString(1, param1); |
||||
ResultSet rs = pst.executeQuery(); |
||||
while (rs.next()) { |
||||
result.put(rs.getString(1), rs.getString(2)); |
||||
} |
||||
rs.close(); |
||||
pst.close(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
throw new IllegalStateException("Fehler bei DocManagement ("+sys+") " + e); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private HashMap<String, String> getHashMap(ResultSet rs) throws SQLException { |
||||
HashMap<String, String> einEintrag = new HashMap<String, String>(); |
||||
ResultSetMetaData rsmd = rs.getMetaData(); |
||||
for (int i = 1; i <= rsmd.getColumnCount(); i++) { |
||||
String label = rsmd.getColumnLabel(i); |
||||
Object value = rs.getObject(i); |
||||
// Null-Werte führen in Freemarker absicht zu Fehler "has evaluated to null"
|
||||
// daher Leerstring
|
||||
String valueString = ""; |
||||
if (value != null) |
||||
if (value instanceof Date) { |
||||
valueString = DateUtils.formatGerman((Date) value); |
||||
} else { |
||||
valueString = value.toString(); |
||||
} |
||||
einEintrag.put(label, valueString); |
||||
|
||||
} |
||||
return einEintrag; |
||||
} |
||||
|
||||
protected String readVorlageFromRepository(String vorlagenName) { |
||||
return readStringFromDB( |
||||
"select content from sx_repository where aktiv=1 and today() between gueltig_seit and gueltig_bis and id=?", |
||||
vorlagenName); |
||||
} |
||||
|
||||
/** |
||||
* Lesen aus der Datenbank per PreparedStatement |
||||
* |
||||
* @param task |
||||
* @param query |
||||
* @param Integer param1 - falls null wird param2 als erster Param für das |
||||
* PreparedStatement genutzt |
||||
* @param param2 |
||||
* @return int result |
||||
*/ |
||||
protected int readIntFromDB(String task, String query, Integer param1, String param2) { |
||||
int result = -1; |
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
PreparedStatement pst = con.prepareStatement(query); |
||||
if (param1 != null) { |
||||
pst.setInt(1, param1.intValue()); |
||||
if (param2 != null) |
||||
pst.setString(2, param2); |
||||
} else { |
||||
pst.setString(1, param2); |
||||
} |
||||
ResultSet rs = pst.executeQuery(); |
||||
while (rs.next()) { |
||||
result = rs.getInt(1); |
||||
} |
||||
rs.close(); |
||||
pst.close(); |
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
throw new IllegalStateException(task); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Öffnet URLConnection mit/ohne Proxy und Timeout von 15 Sekunden |
||||
* |
||||
* @param url |
||||
* @return URLConnection |
||||
*/ |
||||
public HttpURLConnection openConnection(URL url) { |
||||
HttpURLConnection con = null; |
||||
try { |
||||
if (proxy == null) |
||||
con = (HttpURLConnection) url.openConnection(); |
||||
else { |
||||
con = (HttpURLConnection) url.openConnection(proxy); |
||||
} |
||||
con.setConnectTimeout(15 * 1000); |
||||
} catch (IOException e) { |
||||
logger.severe("sys: "+sys+" Fehler bei Verbindungsaufbau mit " + url + " " + proxy != null ? "(Proxy gesetzt)" : ""); |
||||
logger.severe(getExceptionStackTrace(e)); |
||||
} |
||||
return con; |
||||
} |
||||
|
||||
protected abstract void setHeaderAuthorisation(HttpURLConnection urlConnection) throws IOException; |
||||
|
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.util.Properties; |
||||
import java.util.StringTokenizer; |
||||
|
||||
import javax.crypto.Cipher; |
||||
import javax.crypto.spec.SecretKeySpec; |
||||
|
||||
|
||||
|
||||
public class ArchivePropHandler { |
||||
//from memtext.util.CryptUtils;
|
||||
private static Cipher desCipher; |
||||
//geaendert im Vergleich zu Vorlage
|
||||
// private static final byte[] KEY_DATA = { -118, -55, -53, -71, -92, 28, -112, 107 };
|
||||
private static final byte[] KEY_DATA = { -108, -50, -5, -75, -98, 28, -116, 107 }; |
||||
private static final SecretKeySpec KEY = new SecretKeySpec(KEY_DATA, "DES"); |
||||
|
||||
|
||||
public ArchivePropHandler() { |
||||
try { |
||||
if (desCipher == null) desCipher = Cipher.getInstance("DES"); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
|
||||
} |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
if (args.length != 3) { |
||||
System.out.println("Usage: URL username password"); |
||||
System.exit(-1); |
||||
} else { |
||||
ArchivePropHandler ph = new ArchivePropHandler(); |
||||
ph.createPropFile(args); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* |
||||
* @param propfile |
||||
* @return Passwort bleibt verschluesselt, wird von aufrufender Methode entschluesselt |
||||
* @throws IOException |
||||
*/ |
||||
public String getUrlVorlage(String propfile) throws IOException { |
||||
if (!new File(propfile).exists()) { |
||||
throw new IOException("Properties Datei " + propfile + " nicht gefunden"); |
||||
} |
||||
String urlVorlage = ""; |
||||
Properties props = new Properties(); |
||||
FileInputStream is = new FileInputStream(propfile); |
||||
props.load(is); |
||||
is.close(); |
||||
urlVorlage = props.getProperty("URL") + "|" + props.getProperty("username") + "|"; |
||||
String passwd = props.getProperty("password"); |
||||
if (passwd == null || !passwd.startsWith("sx_des")) { |
||||
throw new IOException("Passwort nicht gefunden oder nicht verschluesselt"); |
||||
} |
||||
|
||||
|
||||
urlVorlage += passwd; |
||||
|
||||
|
||||
return urlVorlage; |
||||
} |
||||
|
||||
private void createPropFile(String args[]) { |
||||
try { |
||||
Properties props = new Properties(); |
||||
props.put("URL", args[0]); |
||||
props.put("username", args[1]); |
||||
String verschl = encryptStringDES(args[2]); |
||||
props.put("password", "sx_des" + verschl); |
||||
OutputStream os = new FileOutputStream("docman_mbsarchive.properties"); |
||||
props.store(os, "DocMan MBSArchive"); |
||||
os.close(); |
||||
System.out.println("Verschluesseltes Passwort: sx_des"+verschl); |
||||
System.out.println("Datei docman_mbsarchive.properties erzeugt"); |
||||
} catch (Exception e) { |
||||
System.out.println("Fehler bei der Verschluesselung"); |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
public String decryptStringDES(String aValue) throws Exception { |
||||
if (aValue == null) return null; |
||||
|
||||
desCipher.init(Cipher.DECRYPT_MODE, KEY); |
||||
byte[] encrypted = makeArrayDES(aValue); |
||||
byte[] decrypted = desCipher.doFinal(encrypted); |
||||
String result = new String(decrypted); |
||||
return result; |
||||
|
||||
} |
||||
|
||||
public String encryptStringDES(String aValue) throws Exception { |
||||
if (aValue == null) return null; |
||||
|
||||
|
||||
desCipher.init(Cipher.ENCRYPT_MODE, KEY); |
||||
byte[] values = aValue.getBytes(); |
||||
byte[] encrypted = desCipher.doFinal(values); |
||||
return makeStringDES(encrypted); |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Creates a String from the given array which can be used to store the |
||||
* array in a text file |
||||
* |
||||
* @see #makeArrayDES(String) |
||||
*/ |
||||
private String makeStringDES(byte[] values) { |
||||
StringBuffer buff = new StringBuffer(values.length * 3); |
||||
for (int i = 0; i < values.length; i++) { |
||||
buff.append('#'); |
||||
buff.append(values[i]); |
||||
} |
||||
return buff.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Internal method which converts an "Array String" into a byte array which |
||||
* can be used for decoding |
||||
* |
||||
* @see #makeString(byte[]) |
||||
*/ |
||||
private byte[] makeArrayDES(String values) { |
||||
StringTokenizer tok = new StringTokenizer(values, "#"); |
||||
byte[] result = new byte[tok.countTokens()]; |
||||
byte b; |
||||
String c; |
||||
int i = 0; |
||||
while (tok.hasMoreTokens()) { |
||||
c = tok.nextToken(); |
||||
try { |
||||
b = Byte.parseByte(c); |
||||
result[i] = b; |
||||
i++; |
||||
} catch (NumberFormatException e) { |
||||
return new byte[1]; |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,174 @@
@@ -0,0 +1,174 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.DataOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.time.Duration; |
||||
import java.time.Instant; |
||||
import java.util.StringTokenizer; |
||||
|
||||
import jakarta.servlet.ServletException; |
||||
|
||||
public class BasicAuthTokenRequester { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private String url, basicAuthString; |
||||
|
||||
private static boolean isTestModus = false; |
||||
|
||||
private static boolean isDebug = false; |
||||
|
||||
|
||||
private String token = null; |
||||
private Instant tokenCreationTime ; |
||||
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman"); |
||||
public static void main(String[] args) { |
||||
System.out.println("Tokentester Version 2023-08-22"); |
||||
if (args.length != 2) { |
||||
System.out.println("Parameter URL BasicAuthString"); |
||||
} else { |
||||
isTestModus = true; |
||||
BasicAuthTokenRequester batr = new BasicAuthTokenRequester(args[0], args[1]); |
||||
|
||||
String token; |
||||
try { |
||||
batr.authenticateAndInitToken(); |
||||
token = batr.getToken(); |
||||
System.out.println(""); |
||||
System.out.println("Token:"); |
||||
System.out.println(token); |
||||
} catch (IOException e) { |
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
|
||||
} |
||||
} |
||||
|
||||
BasicAuthTokenRequester(String vorlage) throws IOException { |
||||
StringTokenizer st = new StringTokenizer(vorlage, "|"); |
||||
String tokenURL = null, basicAuthString = null; |
||||
int i = 1; |
||||
while (st.hasMoreTokens()) { |
||||
String val = st.nextToken(); |
||||
if (i == 1) tokenURL = val; |
||||
if (i == 2) basicAuthString = val; |
||||
i++; |
||||
} |
||||
if (tokenURL == null || basicAuthString == null) { |
||||
throw new IOException("Fehler beim Initialisieren der Tokenvorlage, URL|BasicAuthString benötigt"); |
||||
} |
||||
if (basicAuthString.startsWith("sx_des")) { |
||||
try { |
||||
if (isDebug) { |
||||
System.out.println("Verschluesselter String " + basicAuthString); |
||||
} |
||||
basicAuthString = new ArchivePropHandler().decryptStringDES(basicAuthString.substring(6)); |
||||
if (isDebug) { |
||||
System.out.println("Entschluesselt: " + basicAuthString); |
||||
} |
||||
} catch (Exception e) { |
||||
throw new IOException("Fehler beim Initialisieren der Tokenvorlage, basicAuthString nicht verarbeitet " + e); |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("basicAuthString nicht verschluesselt"); |
||||
} |
||||
if (isDebug) { |
||||
System.out.println("Ziel URL " + tokenURL); |
||||
} |
||||
this.url = tokenURL; |
||||
this.basicAuthString = basicAuthString; |
||||
} |
||||
|
||||
BasicAuthTokenRequester(String url, String basicAuthString) { |
||||
this.url = url; |
||||
this.basicAuthString = basicAuthString; |
||||
|
||||
} |
||||
|
||||
public void authenticateAndInitToken() throws IOException { |
||||
HttpURLConnection con = null; |
||||
try { |
||||
|
||||
URL myurl = new URL(url); |
||||
con = (HttpURLConnection) myurl.openConnection(); |
||||
|
||||
con.setDoOutput(true); |
||||
con.setRequestMethod("POST"); |
||||
con.setRequestProperty("User-Agent", "Java client"); |
||||
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
||||
con.setRequestProperty("charset", "utf-8"); |
||||
con.setRequestProperty("Content-Length", "0"); |
||||
con.setUseCaches(false); |
||||
con.setRequestProperty("Authorization", "Basic " + basicAuthString); |
||||
|
||||
DataOutputStream wr = new DataOutputStream(con.getOutputStream()); |
||||
byte[] postData = new byte[0]; |
||||
wr.write(postData); |
||||
wr.write(postData); |
||||
|
||||
StringBuilder content; |
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); |
||||
|
||||
String line; |
||||
content = new StringBuilder(); |
||||
|
||||
while ((line = br.readLine()) != null) { |
||||
content.append(line); |
||||
content.append(System.lineSeparator()); |
||||
} |
||||
if (isTestModus) { |
||||
System.out.println("Serverantwort:"); |
||||
System.out.println(content.toString()); |
||||
} |
||||
|
||||
token = extractToken(content.toString()); |
||||
tokenCreationTime= Instant.now(); |
||||
logger.info("Neues Token erzeugt"); |
||||
|
||||
if (isDebug) { |
||||
System.out.println("Token: " + token); |
||||
} |
||||
} catch (Exception e) { |
||||
// System.out.println("Fehler: " + e.toString());
|
||||
// e.printStackTrace();
|
||||
throw new IOException("Token konnte nicht ermittelt werden " + e); |
||||
} finally { |
||||
if (con != null) con.disconnect(); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
public String getToken() throws IOException { |
||||
if (token == null) { |
||||
authenticateAndInitToken(); |
||||
} |
||||
long hoursElapsed = Duration.between(tokenCreationTime, Instant.now()).toHours(); |
||||
if (hoursElapsed>20) |
||||
{ |
||||
logger.info("Token älter als 20 Stunden, erzeuge neues"); |
||||
authenticateAndInitToken(); |
||||
} |
||||
return token; |
||||
} |
||||
|
||||
private String extractToken(String input) { |
||||
String result = ""; |
||||
if (input != null) { |
||||
result = input.replaceAll("<ticket>", ""); |
||||
result = result.replaceAll("</ticket>", ""); |
||||
result = result.replaceAll("\n", ""); |
||||
result = result.replaceAll("\r", ""); |
||||
} |
||||
|
||||
return result; |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,138 @@
@@ -0,0 +1,138 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.BufferedInputStream; |
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.net.InetAddress; |
||||
import java.net.InetSocketAddress; |
||||
import java.net.NetworkInterface; |
||||
import java.net.Proxy; |
||||
import java.net.Proxy.Type; |
||||
import java.net.SocketException; |
||||
import java.net.URL; |
||||
import java.net.URLConnection; |
||||
import java.nio.charset.Charset; |
||||
import java.util.Enumeration; |
||||
|
||||
public class ConnectionTest { |
||||
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
|
||||
// false
|
||||
private static boolean isSocksDebug = false; |
||||
|
||||
private static Proxy proxy; |
||||
private static Type proxyType = Proxy.Type.HTTP; |
||||
|
||||
public static void main(String[] args) { |
||||
if (isSocksDebug) |
||||
proxyType = Proxy.Type.SOCKS; |
||||
if (args.length < 2) { |
||||
System.out.println( |
||||
"Usage URL outfile z.B. https://saphost.de:8090/ out.html optional 3. Parameter ProxyHost 4. Parameter ProxyPort" |
||||
+ |
||||
|
||||
"\n+ Beispiel 1 https://saphost.de:8090/ out.html" |
||||
+ "\n+ Beispiel 2 https://saphost.de:8090/ out.html proxy.uni-freiburg.de 8080" |
||||
+ "\n Wenn eine TestURL sehr lang, ist kann man als 1.Parameter eine Quelldatei angeben, in der die URL steht (wird erkannt, wenn Parameter nicht mit http startet),z.B." |
||||
+ "\n Beispiel 2 testurl.txt out.html proxy.uni-freiburg.de 8080\"+"); |
||||
System.exit(-1); |
||||
} |
||||
try { |
||||
System.out.println("Version " + DocMan.VERSION); |
||||
printIPs(); |
||||
initProxyIfFound(args); |
||||
System.out.print("Starte Abruf.."); |
||||
String urlparam = args[0]; |
||||
if (!urlparam.startsWith("http")) { |
||||
urlparam = readFile(new File(urlparam)); |
||||
} |
||||
System.out.println(" ZielURL:"+urlparam); |
||||
URL url = new URL(urlparam); |
||||
FileOutputStream fout = new FileOutputStream(args[1]); |
||||
URLConnection con = null; |
||||
if (proxy == null) |
||||
con = url.openConnection(); |
||||
else { |
||||
con = url.openConnection(proxy); |
||||
} |
||||
con.setConnectTimeout(15 * 1000); |
||||
// BufferedInputStream bis = new BufferedInputStream(url.openStream());
|
||||
BufferedInputStream bis = new BufferedInputStream(con.getInputStream()); |
||||
|
||||
byte[] res = new byte[1024 * 8]; |
||||
int got; |
||||
while ((got = bis.read(res)) != -1) { |
||||
fout.write(res, 0, got); |
||||
} |
||||
|
||||
fout.flush(); |
||||
fout.close(); |
||||
bis.close(); |
||||
|
||||
System.out.println("..Erledigt"); |
||||
} catch (Exception e) { |
||||
System.out.println("Fehler " + e); |
||||
} |
||||
} |
||||
|
||||
private static void initProxyIfFound(String[] args) { |
||||
|
||||
if (args.length > 2 && args[2] != null) { |
||||
String host = args[2]; |
||||
int port = 8080; |
||||
|
||||
if (args.length > 3 && args[3] != null) { |
||||
port = Integer.parseInt(args[3]); |
||||
} |
||||
System.out.println(" versuche mit Proxy " + host + " port " + port); |
||||
proxy = new Proxy(proxyType, new InetSocketAddress(host, port)); |
||||
} |
||||
} |
||||
|
||||
private static void printIPs() throws SocketException { |
||||
System.out.println("IP Adressen dieser Maschine:"); |
||||
Enumeration e = NetworkInterface.getNetworkInterfaces(); |
||||
while (e.hasMoreElements()) { |
||||
NetworkInterface n = (NetworkInterface) e.nextElement(); |
||||
Enumeration ee = n.getInetAddresses(); |
||||
while (ee.hasMoreElements()) { |
||||
InetAddress i = (InetAddress) ee.nextElement(); |
||||
System.out.println(i.getHostAddress()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* from de.memtext.util.StringUtils /** Reads the contents of a file and returns |
||||
* them as a string |
||||
* |
||||
* @param filename |
||||
* @return String with content of files |
||||
* @throws IOException |
||||
*/ |
||||
private static String readFile(File file) throws IOException { |
||||
Charset charset = Charset.defaultCharset(); |
||||
return readFile(file, charset); |
||||
} |
||||
|
||||
private static String readFile(File file, Charset charset) throws IOException { |
||||
FileInputStream fileinputstream = new FileInputStream(file); |
||||
InputStreamReader inputstreamreader = new InputStreamReader(fileinputstream, charset); |
||||
BufferedReader bufferedreader = new BufferedReader(inputstreamreader); |
||||
String line; |
||||
StringBuffer result = new StringBuffer(); |
||||
while ((line = bufferedreader.readLine()) != null) { |
||||
result.append(line + "\n"); |
||||
|
||||
} |
||||
bufferedreader.close(); |
||||
inputstreamreader.close(); |
||||
fileinputstream.close(); |
||||
return result.toString(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,526 @@
@@ -0,0 +1,526 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.io.PrintWriter; |
||||
import java.io.StringWriter; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.sql.Statement; |
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.Locale; |
||||
import java.util.logging.FileHandler; |
||||
import java.util.logging.Handler; |
||||
import java.util.logging.Level; |
||||
import java.util.logging.LogRecord; |
||||
import java.util.logging.Logger; |
||||
import java.util.logging.SimpleFormatter; |
||||
import java.util.zip.GZIPOutputStream; |
||||
import java.util.zip.ZipOutputStream; |
||||
|
||||
import jakarta.servlet.ServletConfig; |
||||
import jakarta.servlet.ServletException; |
||||
import jakarta.servlet.ServletOutputStream; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
|
||||
import org.apache.commons.io.IOUtils; |
||||
|
||||
import de.memtext.util.DateUtils; |
||||
import de.memtext.util.FileUtils; |
||||
import de.memtext.util.TimeUtils; |
||||
import de.superx.common.SxUser; |
||||
import de.superx.servlet.AbstractSuperXServlet; |
||||
import de.superx.servlet.ServletUtils; |
||||
import de.superx.servlet.SuperXManager; |
||||
import de.superx.servlet.SxPools; |
||||
import de.superx.util.SqlStringUtils; |
||||
|
||||
public class DocMan extends AbstractSuperXServlet { |
||||
private static final long serialVersionUID = 2; |
||||
|
||||
private static final String LOGFILE = "docman.log"; |
||||
|
||||
private static final String MANDANTENID = "default"; |
||||
|
||||
private HashMap<String, AbstractDocPresenter> docPresenters = new HashMap<String, AbstractDocPresenter>(); |
||||
|
||||
private boolean isInitOk = false; |
||||
|
||||
private String initExceptionText = ""; |
||||
|
||||
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman"); |
||||
|
||||
final static String VERSION = "1.3 (2025-03-07)"; |
||||
public void init(ServletConfig config) { |
||||
logger.info("start initSubsystem"); |
||||
try { |
||||
super.init(config); |
||||
System.out.println("Starte DocManagement-Servlet Version " + VERSION); |
||||
// Bei Bedarf Zugriff auf ServletCOnfig möglich via
|
||||
// this.getServletConfig()
|
||||
|
||||
initLogging(); |
||||
initDocPresenters(); |
||||
isInitOk = true; |
||||
} catch (ServletException e) { |
||||
initExceptionText = "Fehler bei Initialisierung der DokumentenManagementServlet " + e; |
||||
logger.severe(initExceptionText + "\n" + getExceptionStackTrace(e)); |
||||
} |
||||
|
||||
} |
||||
|
||||
private void initDocPresenters() throws ServletException { |
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
String hs_nr=""; |
||||
Statement stm=con.createStatement(); |
||||
ResultSet rs_hsinfo=stm.executeQuery("select hs_nr from hochschulinfo"); |
||||
while (rs_hsinfo.next()) |
||||
{ |
||||
hs_nr=rs_hsinfo.getString(1); |
||||
} |
||||
rs_hsinfo.close(); |
||||
stm.close(); |
||||
PreparedStatement pst = con.prepareStatement("select count(*) from sx_repository where aktiv=1 and id=?"); |
||||
pst.setString(1, "SAP_ARCHIV1_URLVORLAGE"); |
||||
ResultSet rs = pst.executeQuery(); |
||||
int count = 0; |
||||
while (rs.next()) { |
||||
count = rs.getInt(1); |
||||
} |
||||
rs.close(); |
||||
if (count > 0) { |
||||
// Uni FR/Mannheim
|
||||
AbstractDocPresenter p = new SAPArchiv1("gxstage"); |
||||
docPresenters.put("gxstage", p); |
||||
logger.info(" SAPArchiv1 initialisiert"); |
||||
} |
||||
pst.setString(1, "MBS_ARCHIV1_URLVORLAGE"); |
||||
rs = pst.executeQuery(); |
||||
count = 0; |
||||
while (rs.next()) { |
||||
count = rs.getInt(1); |
||||
} |
||||
rs.close(); |
||||
if (count > 0) { |
||||
|
||||
AbstractDocPresenter p = new MBSArchiv1("mbs"); |
||||
docPresenters.put("mbs", p); |
||||
logger.info(" MBSArchiv1 initialisiert"); |
||||
|
||||
//Für Regensburg zusätzlicher Presenter mit barcodes
|
||||
if (hs_nr.equals("1341")) |
||||
{ |
||||
p = new MBSBusinessTransactionArchiv("mbs_business_transaction"); |
||||
docPresenters.put("mbs_business_transaction", p); |
||||
logger.info(" MBSBusinessTransactionArchiv initialisiert"); |
||||
} |
||||
} |
||||
|
||||
pst.setString(1, "DVELOP_ARCHIV1_URLVORLAGE"); |
||||
rs = pst.executeQuery(); |
||||
count = 0; |
||||
while (rs.next()) { |
||||
count = rs.getInt(1); |
||||
} |
||||
rs.close(); |
||||
if (count > 0) { |
||||
|
||||
AbstractDocPresenter p = new DvelopArchiv1("gxstage"); |
||||
docPresenters.put("gxstage", p); |
||||
logger.info(" DVELOP_ARCHIV1 initialisiert"); |
||||
} |
||||
|
||||
|
||||
pst.close(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
throw new IllegalStateException("Fehler bei DocManagement " + e); |
||||
} |
||||
} |
||||
|
||||
private void initLogging() { |
||||
try { |
||||
String logfile = getLogDir() + "/docman.log"; |
||||
File f = new File(logfile + ".lck"); |
||||
if (f.exists()) f.delete(); |
||||
f = new File(logfile); |
||||
if (f.exists()) f.delete(); |
||||
initRawFileDateTime("docman", logfile, 20000, 1, true, true); |
||||
} catch (IOException e) { |
||||
throw new IllegalStateException("Konnte docman Logging nicht aufbauen", e); |
||||
} |
||||
logger.setLevel(java.util.logging.Level.FINEST); |
||||
logger.info("Starte DocManagement-Servlet Version " + VERSION); |
||||
} |
||||
|
||||
|
||||
private String getLogDir() { |
||||
String targetDir = SuperXManager.getWEB_INFPfad() + File.separator + "logs"; |
||||
File f = new File(targetDir); |
||||
if (!f.exists()) f.mkdir(); |
||||
|
||||
if (System.getProperty("SX_LOG_TO_TMP") != null && System.getProperty("SX_LOG_TO_TMP").equalsIgnoreCase("true")) targetDir = System.getProperty("java.io.tmpdir"); |
||||
return targetDir; |
||||
} |
||||
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
||||
if (!isInitOk) { |
||||
sendBack(request, response, initExceptionText, "text/html"); |
||||
} else { |
||||
String mand = getMandantenID(request); |
||||
if (!"default".contentEquals(mand)) throw new IllegalArgumentException("Funktion derzeit nur für Mandant default implementiert"); |
||||
setEncoding(request); |
||||
|
||||
SxUser user = (SxUser) request.getSession().getAttribute("user"); |
||||
if ("true".equals(getParameter(request, "refresh"))) { |
||||
String result = doPresenterRefresh(user); |
||||
sendHtmlMessage(request, response, result); |
||||
} else { |
||||
try { |
||||
docPresentation(request, response, user); |
||||
} catch (IOException e) { |
||||
|
||||
response.reset(); |
||||
sendErrorMessage(request, response, "Es ist ein Fehler beim Dokumentenabruf aufgetreten: " + e + " Logdatei " + LOGFILE + " pruefen", e); |
||||
|
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
/** |
||||
* TODO ggfs. in utils auslagern |
||||
* |
||||
* @param e |
||||
* @return |
||||
*/ |
||||
String getExceptionStackTrace(Exception e) { |
||||
String result = ""; |
||||
StringWriter sw = new StringWriter(); |
||||
PrintWriter pw = new PrintWriter(sw); |
||||
e.printStackTrace(pw); |
||||
result = sw.toString(); |
||||
pw.close(); |
||||
return result; |
||||
} |
||||
|
||||
private void docPresentation(HttpServletRequest request, HttpServletResponse response, SxUser user) throws IOException { |
||||
logger.info("Verarbeite DocAbruf"); |
||||
String sys = getParameter(request, "sys"); |
||||
if (sys == null || sys.length() == 0) throw new IllegalArgumentException("Param sys fehlt"); |
||||
if (!docPresenters.containsKey(sys)) { |
||||
StringBuffer msg = new StringBuffer("Kein DocPresenter für " + sys + " definiert. Aktiv: "); |
||||
Iterator<String> it = docPresenters.keySet().iterator(); |
||||
while (it.hasNext()) { |
||||
msg.append(it.next() + ""); |
||||
} |
||||
throw new IllegalArgumentException(msg.toString()); |
||||
} else { |
||||
AbstractDocPresenter presenter = docPresenters.get(sys); |
||||
DocPresentationResult dpresult = presenter.getReply(request, user); |
||||
if (dpresult.hasMessage()) { |
||||
sendHtmlMessage(request, response, dpresult.getMessage()); |
||||
} else { |
||||
if (presenter.isDirectLinkToDocMWanted()) { |
||||
response.sendRedirect(dpresult.getDocManagementUrl().toString()); |
||||
} else { |
||||
try { |
||||
loadAndDeliverContent(true, presenter, request, response, dpresult); |
||||
} catch (IOException e) { |
||||
if (presenter.isRenewAuthentificationOnErrorWanted()) { |
||||
presenter.renewAuthentification(); |
||||
} |
||||
//2. Versuch
|
||||
loadAndDeliverContent(false, presenter, request, response, dpresult); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
private void loadAndDeliverContent(boolean tryAgainOnError, AbstractDocPresenter presenter, HttpServletRequest request, HttpServletResponse response, |
||||
DocPresentationResult dpresult) |
||||
throws IOException { |
||||
|
||||
URL url = dpresult.getDocManagementUrl(); |
||||
//Abgelaufene Test-URL
|
||||
// url = new URL(
|
||||
// "https://saphost-pot.bwhsrw.de:8090/archive?get&pVersion=0046&contRep=PF&docId=aaabk3kvy63gcleb33aaaiiew6tii&accessMode=r&authId=bi-superx-freiburg&expiration=20211013094020&secKey=MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAMYIB2zCCAdcCAQEwKTAdMRswGQYDVQQDDBJiaS1zdXBlcngtZnJlaWJ1cmcCCGD%2Bp%2BaHNNcPMAkGBSsOAwIaBQCggYgwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjExMDEzMDkyMjAyWjAjBgkqhkiG9w0BCQQxFgQUCAxB%2FtRhmBRnNvrBZ8wrjQfn3mswKQYJKoZIhvcNAQk0MRwwGjAJBgUrDgMCGgUAoQ0GCSqGSIb3DQEBAQUAMA0GCSqGSIb3DQEBAQUABIIBAJZVtVIUF3SihW2NZG%2F48aJPjXEeEVcuuBIlRdVfhC7lssmQFMrLqJoKOXcvLXv6Bi4OUTqH60LaSkS8ramG%2Fxh7up%2FURR%2B93oJ2lmTvMp7HA5FmKiW5pBajgRq4MClM%2Fd9PpeMNHMfhZMQUNue3lk%2Fo9hucfS%2B%2Fd9V67TlBXRNQaBouyNR88ZfJdvuN4zR16Jjs4UoX0v0wPVgDGCdhmRF9r4zflssxEhxiIjmrY%2FaVjFA%2BU8mL4isGmVdyzBp%2FjPXjyKgIpwbKPuk5GyFqd6Dpv3ZA0Vgp87Pf6IDOs2Zh1QlPqTENe6Dg%2BbPGelb5l3YUXoQnnx33d7nLcAl0EvoAAAAAAAA%3D");
|
||||
|
||||
logger.info("interner Download und Auslieferung von " + url); |
||||
String targetMimeType = dpresult.getMimetype(); |
||||
logger.info(" Ziel Mimetype " + targetMimeType); |
||||
HttpURLConnection urlConnection = presenter.openConnection(url); |
||||
presenter.setHeaderAuthorisation(urlConnection); |
||||
response.reset(); |
||||
|
||||
byte[] bytes = new byte[0]; |
||||
|
||||
try { |
||||
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
|
||||
bytes = IOUtils.toByteArray(urlConnection.getInputStream()); |
||||
logger.fine(" " + bytes.length + " Bytes an Daten erhalten"); |
||||
logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode()); |
||||
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |
||||
if (targetMimeType != null) { |
||||
response.setContentType(targetMimeType); |
||||
} |
||||
String desiredFilename = FileUtils.removeProblemChars(dpresult.getDesiredFilename()); |
||||
logger.fine(" Sende aus: " + desiredFilename); |
||||
response.setHeader("Content-disposition", "attachment; filename=" + desiredFilename); |
||||
response.setHeader("Cache-Control", "expires=0"); |
||||
// response.setContentLength(outStream.size()); //evtl. bytes.size()
|
||||
|
||||
ServletOutputStream sos = response.getOutputStream(); |
||||
sos.write(bytes); |
||||
sos.flush(); |
||||
sos.close(); |
||||
} else { |
||||
if (tryAgainOnError) { |
||||
String msg = "Fehler beim Lesen der Daten vom DocServer " + new IOException("Http Status " + urlConnection.getResponseCode() + "versuche erneut"); |
||||
logger.warning(msg); |
||||
throw new IOException(msg); |
||||
} else { |
||||
sendErrorMessage(request, response, "Fehler beim Lesen der Daten vom DocServer ", new IOException("Http Status " + urlConnection.getResponseCode())); |
||||
} |
||||
/* |
||||
* ursprüngliche Idee bei 401 genauen Text ausliefern, für Hackerversuche nicht |
||||
* so gut IO-Utils oder urlConnection.inputStream oben wirft IO Exception wenn |
||||
* nicht http-Status-OK else { |
||||
* logger.severe("Es ist ein Fehler beim DocServer aufgetreten " + |
||||
* urlConnection.getResponseMessage()); String responsedata = new String(bytes, |
||||
* StandardCharsets.UTF_8); logger.severe(" Details:\n" + responsedata); |
||||
* sendBack(request, response, responsedata, "text/html"); } |
||||
*/ |
||||
} |
||||
} catch (IOException e) { |
||||
if (tryAgainOnError) { |
||||
String msg = "Fehler beim Lesen der Daten vom DocServer Http Status " + urlConnection.getResponseCode() + " "+e+" versuche erneut"; |
||||
logger.warning(msg); |
||||
throw new IOException(msg); |
||||
} else { |
||||
sendErrorMessage(request, response, "Fehler beim Lesen der Daten vom DocServer ", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void sendErrorMessage(HttpServletRequest request, HttpServletResponse response, String message, Exception e) throws IOException { |
||||
String logme = message; |
||||
if (e != null) { |
||||
logme += "\n" + getExceptionStackTrace(e); |
||||
} |
||||
logger.severe(logme); |
||||
message = message + " " + e; |
||||
//Falls in Datenbank ein Errortext hinterlegt ist, diesen anzeigen
|
||||
try (Connection con = SxPools.get(MANDANTENID).getConnection();) { |
||||
Statement st = con.createStatement(); |
||||
ResultSet rs = st.executeQuery("select content from sx_repository where id='DMS_ERRORTEXT' and aktiv=1 and today() between gueltig_seit and gueltig_bis"); |
||||
while (rs.next()) { |
||||
message = rs.getString(1); |
||||
} |
||||
rs.close(); |
||||
st.close(); |
||||
|
||||
} catch (SQLException ex) { |
||||
ex.printStackTrace(); |
||||
logger.severe("Fehler bei DocManagement : Lesen von möglichem DMS_ERRORTEXT " + ex); |
||||
} |
||||
sendBack(request, response, message, "text/html; charset=utf-8"); |
||||
} |
||||
|
||||
private void sendHtmlMessage(HttpServletRequest request, HttpServletResponse response, String message) throws IOException { |
||||
logger.fine("HTML Darstellung Lokalisierung und Ausliererung von HTML"); |
||||
Locale desiredLocale = getDesiredLocale(request); |
||||
String txt = SxPools.get(getMandantenID(request)).localize(message, desiredLocale); |
||||
// TODO Optimal mit csrfToken, Methode aber in älteren Kernmodul nicht vorhanden
|
||||
// da aktuell nicht benötigt, auskommentiert
|
||||
// sendBack(request, response, insertCsrfToken(request, result), "text/html");
|
||||
|
||||
sendBack(request, response, txt, "text/html"); |
||||
} |
||||
|
||||
private String doPresenterRefresh(SxUser user) throws ServletException { |
||||
String result; |
||||
if (user.isAdmin()) { |
||||
logger.info("Refresh wird gestartet"); |
||||
Iterator<String> it = docPresenters.keySet().iterator(); |
||||
while (it.hasNext()) { |
||||
AbstractDocPresenter p = docPresenters.get(it.next()); |
||||
p.initSystem(); |
||||
} |
||||
result = "Refresh erfolgreich (" + new java.util.Date() + ")"; |
||||
} else { |
||||
result = "Diese Funktion steht nur Administratoren zur Verfügung"; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { |
||||
|
||||
} |
||||
|
||||
public void destroy() { |
||||
java.util.logging.Handler[] h = logger.getHandlers(); |
||||
for (int i = 0; i < h.length; i++) { |
||||
h[i].close(); |
||||
} |
||||
} |
||||
|
||||
public String getMandantenID(HttpServletRequest request) { |
||||
return ServletUtils.getMandantenID(request); |
||||
} |
||||
|
||||
/** |
||||
* TODO Methoden in de.superx.servlet.ServletBasics auf public setzen, damit |
||||
* wiederverwendet werden kann |
||||
* |
||||
* @return |
||||
*/ |
||||
|
||||
protected void sendBack(HttpServletRequest request, HttpServletResponse response, String txt, String contenttype) throws IOException { |
||||
|
||||
OutputStream out = null; |
||||
TimeUtils t = new TimeUtils(); |
||||
t.start(); |
||||
|
||||
// Check the Accepting-Encoding header from the HTTP request.
|
||||
// If the header includes gzip, choose GZIP.
|
||||
// If the header includes compress, choose ZIP.
|
||||
// Otherwise choose no compression.
|
||||
byte[] stuff = txt.getBytes(SqlStringUtils.getEncoding()); |
||||
|
||||
String encoding = request.getHeader("Accept-Encoding"); |
||||
if (!SuperXManager.isResponseCompressionWanted) encoding = "none"; |
||||
if (encoding != null && encoding.indexOf("gzip") != -1) { |
||||
response.setHeader("Content-Encoding", "gzip"); |
||||
out = new GZIPOutputStream(response.getOutputStream()); |
||||
} else if (encoding != null && encoding.indexOf("compress") != -1) { |
||||
response.setHeader("Content-Encoding", "compress"); |
||||
out = new ZipOutputStream(response.getOutputStream()); |
||||
} else { |
||||
|
||||
response.setContentLength(stuff.length); |
||||
out = response.getOutputStream(); |
||||
} |
||||
if (contenttype != null) { |
||||
response.setContentType(contenttype); |
||||
} |
||||
out.write(stuff); |
||||
out.close(); |
||||
} |
||||
|
||||
public Locale getDesiredLocale(HttpServletRequest request) { |
||||
// locale of browser
|
||||
Locale desiredLocale = request.getLocale(); |
||||
|
||||
// if a locale is defined in session, it has priority
|
||||
if (request.getSession() != null && request.getSession().getAttribute("locale") != null) { |
||||
desiredLocale = new Locale((String) request.getSession().getAttribute("locale")); |
||||
} |
||||
// if a locale parameter is in the current request
|
||||
String locale_param = (String) request.getParameter("locale"); |
||||
if (locale_param != null) desiredLocale = new Locale(locale_param); |
||||
|
||||
return desiredLocale; |
||||
} |
||||
|
||||
//aus de.superx.servlet.ServletBasics
|
||||
public static String getParameter(HttpServletRequest request, String name) { |
||||
String p = request.getParameter(name); |
||||
//Parameter auf unterlaubte Tags kontrollieren
|
||||
//ausser bei SuperX-Standalone Formularfeldern passwort,passwort2, altes_passwort
|
||||
//dort können Sonderzeichen genutzt werden
|
||||
// vergl. servlet.SuperXmlPwChanger
|
||||
if (name.indexOf("passwort") == -1) { |
||||
if (p != null && containsTags(p)) { |
||||
throw new IllegalArgumentException("Parameter " + name + " enthält unerlaubte Tags"); |
||||
} |
||||
} |
||||
return p; |
||||
} |
||||
|
||||
/** |
||||
* aus de.memtext.util.StringUtils |
||||
* Prüft ob Tags <***> enthalten sind, \n wird auch moniert Text javascript |
||||
* wird auch moniert |
||||
* |
||||
* @param source |
||||
* @return |
||||
*/ |
||||
private static boolean containsTags(String source) { |
||||
|
||||
// return source.replaceAll("<[^>]+>", "");
|
||||
|
||||
boolean result = false; |
||||
if (source != null) { |
||||
int startpos = 0; |
||||
|
||||
while (source.indexOf("<", startpos) > -1) { |
||||
startpos = source.indexOf("<", startpos); |
||||
int tagend = source.indexOf(">", startpos); |
||||
if (tagend > -1 && tagend > startpos + 1 && source.substring(startpos, tagend).indexOf(" ") == -1) { |
||||
result = true; |
||||
break; |
||||
} else if (tagend > -1) |
||||
startpos = tagend + 1; |
||||
else |
||||
startpos++; |
||||
} |
||||
if (source.indexOf("javascript") > -1) result = true; |
||||
// gab Probleme mit csv upload
|
||||
// if (source.indexOf("\n")>-1) result=true;
|
||||
if (source.indexOf("\u0000") > -1) result = true; |
||||
/* |
||||
* StringTokenizer st = new StringTokenizer(source, " <", true); |
||||
* while (st.hasMoreTokens()) { String tok = st.nextToken(); int pos = |
||||
* tok.indexOf(">"); //größer 0 damit nicht ">1996" als tag zählt if
|
||||
* (pos > 0 && tok.substring(0, pos).indexOf(" ") == -1) { result = |
||||
* true; break; } } |
||||
*/ |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
// aus de.memtext.util.LogUtils
|
||||
private void initRawFileDateTime(String loggername, String filename, int maxKB, int count, boolean append, boolean tryLckDeletion) throws SecurityException, IOException { |
||||
if (tryLckDeletion) { |
||||
if (count > 1) throw new IllegalArgumentException("tryLckDeletion doesn't work for >1 file"); |
||||
File f = new File(filename + ".lck"); |
||||
if (f.exists()) f.delete(); |
||||
} |
||||
if (count > 1) filename = FileUtils.addToEndOfFileName(filename, "%g"); |
||||
Handler fh = new FileHandler(filename, maxKB * 1024, count, append); |
||||
fh.setFormatter(new SimpleFormatter() { |
||||
public String format(LogRecord l) { |
||||
String result = DateUtils.getTodayString() + " " + DateUtils.getNowString() + ":" + l.getMessage() + "\n"; |
||||
return result; |
||||
} |
||||
|
||||
public String formatMessage(LogRecord l) { |
||||
return format(l); |
||||
} |
||||
|
||||
}); |
||||
Logger.getLogger(loggername).addHandler(fh); |
||||
Logger.getLogger(loggername).setLevel(Level.FINEST); |
||||
} |
||||
|
||||
public static String exceptionToString(Exception e) { |
||||
StringWriter sw = new StringWriter(); |
||||
PrintWriter pw = new PrintWriter(sw); |
||||
e.printStackTrace(pw); |
||||
return sw.toString(); |
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.net.URL; |
||||
|
||||
public class DocPresentationResult { |
||||
private static final long serialVersionUID = 1; |
||||
private String message, mimetype, desiredFilename; |
||||
private URL docManagementUrl; |
||||
|
||||
String getDesiredFilename() { |
||||
return desiredFilename; |
||||
} |
||||
|
||||
void setDesiredFilename(String desiredFilename) { |
||||
this.desiredFilename = desiredFilename; |
||||
} |
||||
|
||||
String getMessage() { |
||||
return message; |
||||
} |
||||
|
||||
void setMessage(String message) { |
||||
this.message = message; |
||||
} |
||||
|
||||
String getMimetype() { |
||||
return mimetype; |
||||
} |
||||
|
||||
void setMimetype(String mimetype) { |
||||
this.mimetype = mimetype; |
||||
} |
||||
|
||||
URL getDocManagementUrl() { |
||||
return docManagementUrl; |
||||
} |
||||
|
||||
void setDocManagementUrl(URL docManagementUrl) { |
||||
this.docManagementUrl = docManagementUrl; |
||||
} |
||||
|
||||
/** |
||||
* Prüft ob eine vernünftige Antwort geliefert werden kann dann muss entweder |
||||
* eine Message oder eine URL bereit liegen |
||||
* |
||||
* @return |
||||
*/ |
||||
boolean isOK() { |
||||
return getMessage() != null || getDocManagementUrl() != null; |
||||
} |
||||
|
||||
public boolean hasMessage() { |
||||
return getMessage() != null; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
public class DocumentMetadata { |
||||
private String filename, mimetyp, docid,art; |
||||
|
||||
String getArt() { |
||||
return art; |
||||
} |
||||
|
||||
void setArt(String art) { |
||||
this.art = art; |
||||
} |
||||
|
||||
String getFilename() { |
||||
return filename; |
||||
} |
||||
|
||||
void setFilename(String filename) { |
||||
this.filename = filename; |
||||
} |
||||
|
||||
String getMimetyp() { |
||||
return mimetyp; |
||||
} |
||||
|
||||
void setMimetyp(String mimetyp) { |
||||
this.mimetyp = mimetyp; |
||||
} |
||||
|
||||
String getDocid() { |
||||
return docid; |
||||
} |
||||
|
||||
void setDocid(String docid) { |
||||
this.docid = docid; |
||||
} |
||||
public boolean isValid() { |
||||
|
||||
return getFilename()!=null&&getMimetyp()!=null&&getDocid()!=null&&getArt()!=null; |
||||
} |
||||
public void clear() { |
||||
setFilename(null); |
||||
setMimetyp(null); |
||||
setDocid(null); |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,177 @@
@@ -0,0 +1,177 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.InetSocketAddress; |
||||
import java.net.Proxy; |
||||
import java.net.Proxy.Type; |
||||
import java.net.URL; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.StringTokenizer; |
||||
|
||||
import jakarta.servlet.ServletException; |
||||
|
||||
public class DvelopArchiv1 extends AbstractDocPresenter { |
||||
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
|
||||
// false
|
||||
private static boolean isSocksDebug = false; |
||||
|
||||
private static Type proxyType = Proxy.Type.HTTP; |
||||
|
||||
private static final long serialVersionUID = 3L; |
||||
|
||||
private final boolean isDebug = false; // true schaltet Authentication Header ab!
|
||||
|
||||
private Map<String, String> doctyp_Mimetype; |
||||
|
||||
private BasicAuthTokenRequester tokenrequester; |
||||
|
||||
void initSystem() throws ServletException { |
||||
if (isSocksDebug) proxyType = Proxy.Type.SOCKS; |
||||
//URL zum Abruf der Dokumente
|
||||
setUrlVorlage(readVorlageFromRepository("DVELOP_ARCHIV1_URLVORLAGE")); |
||||
//Token URL username und passwort
|
||||
initTokenRequester(); |
||||
|
||||
setDirectLinkToDocMWanted(false); |
||||
setMenuVorlage(readVorlageFromRepository("DVELOP_ARCHIV1_MENU_VORLAGE")); |
||||
setReadDocumentCountSql("select count(*) from gxstage_dms_metadata where id_jahr_belegnr=? and anzeige_relevant=1"); |
||||
//Hier wichtig, die ID im DokumentenManageManageSystem muss doc_id sein, für MenüVorlage daher "as doc_id"
|
||||
// keine Unterstriche, da übersichtlicher in Freemarker
|
||||
setReadDocumentListSql("select docid as doc_id,filename,art from gxstage_dms_metadata where id_jahr_belegnr=? and anzeige_relevant=1 order by filename"); |
||||
|
||||
setDeleteOldRightsSql("delete from gxstage_dms_rights where gueltig_bis<today()"); |
||||
setReadIdRightSql("select count(*) from gxstage_dms_rights where userinfo_id=?::integer and id_jahr_belegnr=? and gueltig_bis>=today()"); |
||||
setReadDocIdRightSql("select count(*) from gxstage_dms_rights R,gxstage_dms_metadata M where userinfo_id=?::integer and R.id_jahr_belegnr=M.id_jahr_belegnr and M.anzeige_relevant=1 and gueltig_bis>=today() " |
||||
+ "and M.docid=?"); |
||||
|
||||
|
||||
setReadDocIdSql("select docid from gxstage_dms_metadata where id_jahr_belegnr=? and anzeige_relevant=1"); |
||||
setReadMainDocIdSql("select distinct docid from gxstage_dms_metadata where id_jahr_belegnr=? and maindoc=1 and anzeige_relevant=1"); |
||||
// default=false setDocMenuAlwaysWanted(true);
|
||||
|
||||
setRenewAuthentificationOnErrorWanted(true); |
||||
initMimeTypes(); |
||||
|
||||
initProxy(); |
||||
} |
||||
|
||||
|
||||
private void initTokenRequester() throws ServletException { |
||||
|
||||
String tokenvorlage = readVorlageFromRepository("DVELOP_ARCHIV1_TOKENURL"); |
||||
//TODO ggfs aus Datei
|
||||
/*if (tokenvorlage.equals("docman_mbsarchive.properties")) { |
||||
try { |
||||
logger.info("Lese Tokeninformationen aus Datei "+SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties"); |
||||
tokenvorlage = ph.getUrlVorlage(SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties"); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
throw new ServletException("Fehler bei Lesen von Properties-Datei " + e); |
||||
} |
||||
}*/ |
||||
StringTokenizer st = new StringTokenizer(tokenvorlage, "|"); |
||||
String tokenURL = null, basicAuthString = null; |
||||
int i = 1; |
||||
while (st.hasMoreTokens()) { |
||||
String val = st.nextToken(); |
||||
if (i == 1) tokenURL = val; |
||||
if (i == 2) basicAuthString = val; |
||||
i++; |
||||
} |
||||
if (tokenURL == null || basicAuthString == null) { |
||||
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, URL|basicAuthString bzw. Properties-Datei benötigt"); |
||||
} |
||||
if (basicAuthString.startsWith("sx_des")) { |
||||
try { |
||||
if (isDebug) { |
||||
logger.info("Verschluesseltes Passwort " + basicAuthString); |
||||
} |
||||
basicAuthString = new ArchivePropHandler().decryptStringDES(basicAuthString.substring(6)); |
||||
if (isDebug) { |
||||
logger.info("Entschluesseltes Passwort " + basicAuthString); |
||||
} |
||||
} catch (Exception e) { |
||||
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, Password nicht verarbeitet " + e); |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("Passwort nicht verschluesselt"); |
||||
} |
||||
tokenrequester = new BasicAuthTokenRequester(tokenURL, basicAuthString); |
||||
} |
||||
|
||||
protected void renewAuthentification() throws IOException { |
||||
if (!isDebug) { |
||||
logger.info("Erneuere Token mittels Authentification-String"); |
||||
tokenrequester.authenticateAndInitToken(); |
||||
} |
||||
} |
||||
|
||||
private void initProxy() { |
||||
String[] params = getUrlVorlage().split("\\|"); |
||||
if (params.length > 5) { |
||||
logger.info("Intialisierung mit Proxy für das DocManagement"); |
||||
int port = 8080; |
||||
String host = params[5]; |
||||
if (params.length > 6 && params[6] != null) { |
||||
|
||||
try { |
||||
port = Integer.parseInt(params[6]); |
||||
} catch (NumberFormatException e) { |
||||
String msg = "Konnte Portnummer für Proxy nicht in Integer umwandeln: " + params[6]; |
||||
logger.severe(msg); |
||||
throw new IllegalStateException(msg); |
||||
} |
||||
|
||||
} |
||||
logger.info(" ProxyHost: " + host + " Port: " + port); |
||||
|
||||
setProxy(new Proxy(proxyType, new InetSocketAddress(host, port))); |
||||
} |
||||
} |
||||
|
||||
private void initMimeTypes() { |
||||
// Hier erst initialisieren wegen komplexem Ablauf von Kontruktoren und
|
||||
// initSystem
|
||||
if (doctyp_Mimetype == null) doctyp_Mimetype = new HashMap<String, String>(); |
||||
doctyp_Mimetype.clear(); |
||||
// doctyp_Mimetype.putAll(readMapFromDB("SELECT lower(endung),mimetype FROM fin_dms_mimetypes", null));
|
||||
// logger.fine(" Mimetype Zuordnungen gefunden:" + doctyp_Mimetype);
|
||||
} |
||||
|
||||
public DvelopArchiv1(String sys) throws ServletException { |
||||
super(sys, null); |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* |
||||
* |
||||
* @param doc_id - Hier eine docId! |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception { |
||||
result.setDocManagementUrl(new URL(getUrlVorlage().replaceFirst("<<DOCID>>", doc_id))); |
||||
String filename = readStringFromDB("select filename from gxstage_dms_metadata where docid=?", doc_id); |
||||
result.setDesiredFilename(filename); |
||||
String mt = readStringFromDB("select mimetype from gxstage_dms_metadata where docid=?", doc_id); |
||||
logger.fine(" Ermittelte minetype: " + mt + ""); |
||||
if (!mt.contentEquals("")) result.setMimetype(mt); |
||||
} |
||||
|
||||
|
||||
protected void setHeaderAuthorisation(HttpURLConnection urlConnection) throws IOException { |
||||
String token = ""; |
||||
if (!isDebug) { |
||||
//macht auch authentifizierung falls token noch null
|
||||
token = tokenrequester.getToken(); |
||||
|
||||
} |
||||
logger.info(" set Header Authorization Bearer " + token); |
||||
urlConnection.setRequestProperty("Authorization", "Bearer " + token); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
public class DvelopDocumentMetadata extends DocumentMetadata { |
||||
private int gejahr = 0; |
||||
|
||||
int getGejahr() { |
||||
return gejahr; |
||||
} |
||||
|
||||
void setGejahr(int gejahr) { |
||||
this.gejahr = gejahr; |
||||
} |
||||
|
||||
String getBelegnummer() { |
||||
return belegnummer; |
||||
} |
||||
|
||||
void setBelegnummer(String belegnummer) { |
||||
this.belegnummer = belegnummer; |
||||
} |
||||
|
||||
private String belegnummer; |
||||
|
||||
public boolean isValid() { |
||||
return super.isValid() && getGejahr() != 0 && getBelegnummer() != null; |
||||
} |
||||
|
||||
public void clear() { |
||||
super.clear(); |
||||
setGejahr(0); |
||||
setBelegnummer(null); |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
|
||||
import org.apache.commons.io.IOUtils; |
||||
|
||||
public class DvelopDownloadTester { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private String token; |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println("Version 1.0 11.9.2023"); |
||||
if (args.length !=2) { |
||||
System.out.println("Parameter DownloadURL token"); |
||||
} else { |
||||
try { |
||||
DvelopDownloadTester fdr = new DvelopDownloadTester(); |
||||
fdr.setToken(args[1]); |
||||
fdr.test(args[0]); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public void setToken(String token) |
||||
{ |
||||
this.token=token; |
||||
} |
||||
|
||||
|
||||
public void test(String currentURL) throws IOException { |
||||
System.out.println("Rufe ab "+currentURL); |
||||
URL url=new URL(currentURL); |
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); |
||||
System.out.println(" set Header Authorization Bearer "+token); |
||||
urlConnection.setRequestProperty ("Authorization", "Bearer "+token); |
||||
byte[] bytes = new byte[0]; |
||||
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
|
||||
bytes = IOUtils.toByteArray(urlConnection.getInputStream()); |
||||
// logger.fine(" " + bytes.length + " Bytes an Daten erhalten");
|
||||
// logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode());
|
||||
System.out.println(" " + bytes.length + " Bytes an Daten erhalten"); |
||||
System.out.println("HTTP-StatusCode: " + urlConnection.getResponseCode()); |
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |
||||
File outputFile = new File("test.pdf"); |
||||
if (outputFile.exists()) { |
||||
outputFile.delete(); |
||||
} |
||||
FileOutputStream outputStream = new FileOutputStream(outputFile); |
||||
outputStream.write(bytes); |
||||
outputStream.close(); |
||||
System.out.println("als test.pdf gespeichert"); |
||||
|
||||
} else { |
||||
System.out.println("Fehler StatusCode nicht OK"); |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import java.sql.Connection; |
||||
import java.sql.ResultSet; |
||||
|
||||
import org.apache.commons.io.IOUtils; |
||||
|
||||
import de.superx.bin.SxConnection; |
||||
|
||||
public class DvelopDownloadTester2 { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private String token; |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println("Version 1.0 11.9.2023"); |
||||
if (args.length !=2) { |
||||
System.out.println("Parameter DownloadURL /pfad/zur/db.properties"); |
||||
} else { |
||||
try { |
||||
DvelopDownloadTester2 fdr = new DvelopDownloadTester2(); |
||||
SxConnection myConnection = new SxConnection(); |
||||
myConnection.setPropfile(args[1]); |
||||
Connection con = myConnection.getConnection(); |
||||
java.sql.Statement st = con.createStatement(); |
||||
ResultSet rs=st.executeQuery("select content from sx_repository where id='DVELOP_ARCHIV1_TOKENURL' and aktiv=1 and today() between gueltig_seit and gueltig_bis"); |
||||
String input=null; |
||||
while (rs.next()) { |
||||
input = rs.getString("content"); |
||||
} |
||||
if (input == null || input.trim().length() == 0) { |
||||
throw new IllegalStateException("Keine aktive DVELOP_ARCHIV1_TOKENURL im Repository gefunden"); |
||||
} |
||||
BasicAuthTokenRequester tokenrequester=new BasicAuthTokenRequester(input); |
||||
st.close(); |
||||
con.close(); |
||||
fdr.setToken(tokenrequester.getToken()); |
||||
fdr.test(args[0]); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public void setToken(String token) |
||||
{ |
||||
this.token=token; |
||||
} |
||||
|
||||
|
||||
public void test(String currentURL) throws IOException { |
||||
System.out.println("Rufe ab "+currentURL); |
||||
URL url=new URL(currentURL); |
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); |
||||
System.out.println(" set Header Authorization Bearer "+token); |
||||
urlConnection.setRequestProperty ("Authorization", "Bearer "+token); |
||||
byte[] bytes = new byte[0]; |
||||
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
|
||||
bytes = IOUtils.toByteArray(urlConnection.getInputStream()); |
||||
// logger.fine(" " + bytes.length + " Bytes an Daten erhalten");
|
||||
// logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode());
|
||||
System.out.println(" " + bytes.length + " Bytes an Daten erhalten"); |
||||
System.out.println("HTTP-StatusCode: " + urlConnection.getResponseCode()); |
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |
||||
File outputFile = new File("test.pdf"); |
||||
if (outputFile.exists()) { |
||||
outputFile.delete(); |
||||
} |
||||
FileOutputStream outputStream = new FileOutputStream(outputFile); |
||||
outputStream.write(bytes); |
||||
outputStream.close(); |
||||
System.out.println("als test.pdf gespeichert"); |
||||
|
||||
} else { |
||||
System.out.println("Fehler StatusCode nicht OK"); |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,432 @@
@@ -0,0 +1,432 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.File; |
||||
import java.io.FileWriter; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.sql.Statement; |
||||
import java.time.Year; |
||||
import java.util.logging.FileHandler; |
||||
import java.util.logging.Handler; |
||||
import java.util.logging.LogRecord; |
||||
import java.util.logging.Logger; |
||||
import java.util.logging.SimpleFormatter; |
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory; |
||||
import com.fasterxml.jackson.core.JsonParseException; |
||||
import com.fasterxml.jackson.core.JsonParser; |
||||
import com.fasterxml.jackson.core.JsonToken; |
||||
|
||||
import de.memtext.util.DateUtils; |
||||
import de.memtext.util.FileUtils; |
||||
import de.superx.bin.SxConnection; |
||||
|
||||
/** |
||||
* |
||||
* "http://www.mbisping.de/tmp/page1.out"; |
||||
// ohne nextPage
|
||||
"http://www.mbisping.de/tmp/page2.out"; |
||||
* |
||||
*/ |
||||
public class DvelopMetadatenLoader { |
||||
private final static String VERSION="Version 2023-09-11"; |
||||
private BasicAuthTokenRequester tokenrequester; |
||||
|
||||
private Connection con; |
||||
|
||||
private Statement stmt; |
||||
|
||||
private PreparedStatement pst; |
||||
|
||||
private int counter = 0; |
||||
|
||||
private String urlBase; |
||||
|
||||
private String firstRelativeUrl; |
||||
|
||||
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman_metadata"); |
||||
|
||||
//Zum Testen kann deaktiviert werden
|
||||
private boolean isTokenNeeded = true; |
||||
|
||||
|
||||
public static void main(String[] args) { |
||||
if (args.length < 4 || args.length > 5) { |
||||
System.err.println("Parameter /pfad/zur/db.properties URLBase RelativeURL loglevel (info,fine,finest) Startjahr(optional)"); |
||||
System.err.println("Parameter /home/superx/tomcat/webapps/superx/WEB-INF/db.properties \"https://dms-test.verw.uni-xy.de\" \"/dms/metadata\" info 2021 "); |
||||
System.exit(1); |
||||
} |
||||
System.out.println(VERSION); |
||||
System.out.println("Logfile: docman_metadata.log"); |
||||
try { |
||||
int startjahr = Year.now().getValue() - 1; |
||||
if (args.length == 5) { |
||||
startjahr = Integer.parseInt(args[4]); |
||||
} |
||||
String loglevel = args[3]; |
||||
DvelopMetadatenLoader dml = new DvelopMetadatenLoader(args[1], args[2], loglevel); |
||||
if (loglevel.equalsIgnoreCase("finest")) { |
||||
dml.deleteTmpJsonFiles(); |
||||
} |
||||
dml.prepareDbAndPreparedStatement(args[0]); |
||||
for (int einjahr = startjahr; einjahr <= Year.now().getValue(); einjahr++) { |
||||
dml.update(einjahr); |
||||
} |
||||
dml.finishWorkinDb(); |
||||
} catch (Exception e) { |
||||
System.out.println("Fehler bei der Metadatenverarbeitung"); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
} |
||||
|
||||
private void deleteTmpJsonFiles() { |
||||
File directory = new File("."); |
||||
for (File f : directory.listFiles()) { |
||||
if (f.getName().startsWith("tmpMetadata")) { |
||||
f.delete(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public DvelopMetadatenLoader(String urlbase, String relativeUrl, String loglevel) { |
||||
this.urlBase = urlbase; |
||||
this.firstRelativeUrl = relativeUrl; |
||||
initLogging(loglevel); |
||||
} |
||||
|
||||
private void initLogging(String loglevel) { |
||||
if (loglevel.equalsIgnoreCase("info")) { |
||||
logger.setLevel(java.util.logging.Level.INFO); |
||||
} else if (loglevel.equalsIgnoreCase("fine")) { |
||||
logger.setLevel(java.util.logging.Level.FINE); |
||||
} else if (loglevel.equalsIgnoreCase("finest")) { |
||||
logger.setLevel(java.util.logging.Level.FINEST); |
||||
} else { |
||||
System.out.println("als Loglevel info,fine oder finest angeben"); |
||||
System.exit(-1); |
||||
} |
||||
|
||||
try { |
||||
String logfile = "docman_metadata.log"; |
||||
File f = new File(logfile + ".lck"); |
||||
if (f.exists()) f.delete(); |
||||
f = new File(logfile); |
||||
if (f.exists()) f.delete(); |
||||
initRawFileDateTime("docman_metadata", logfile, 20000, 1, false, false); |
||||
} catch (IOException e) { |
||||
throw new IllegalStateException("Konnte docman Logging nicht aufbauen", e); |
||||
} |
||||
|
||||
//deaktivierung von Console handler
|
||||
logger.setUseParentHandlers(false); |
||||
logger.info(VERSION); |
||||
} |
||||
|
||||
// aus de.memtext.util.LogUtils
|
||||
private void initRawFileDateTime(String loggername, String filename, int maxKB, int count, boolean append, boolean tryLckDeletion) throws SecurityException, IOException { |
||||
if (tryLckDeletion) { |
||||
if (count > 1) throw new IllegalArgumentException("tryLckDeletion doesn't work for >1 file"); |
||||
File f = new File(filename + ".lck"); |
||||
if (f.exists()) f.delete(); |
||||
} |
||||
if (count > 1) filename = FileUtils.addToEndOfFileName(filename, "%g"); |
||||
Handler fh = new FileHandler(filename, maxKB * 1024, count, append); |
||||
fh.setFormatter(new SimpleFormatter() { |
||||
public String format(LogRecord l) { |
||||
String result = DateUtils.getTodayString() + " " + DateUtils.getNowString() + ":" + l.getMessage() + "\n"; |
||||
return result; |
||||
} |
||||
|
||||
public String formatMessage(LogRecord l) { |
||||
return format(l); |
||||
} |
||||
|
||||
}); |
||||
Logger.getLogger(loggername).addHandler(fh); |
||||
// Logger.getLogger(loggername).setLevel(Level.FINEST);
|
||||
} |
||||
|
||||
private void update(int gejahr) throws JsonParseException, IOException, SQLException { |
||||
System.out.println("Update fuer Geschaeftsjahr " + gejahr); |
||||
logger.info("Update fuer Geschaeftsjahr " + gejahr); |
||||
String firstOrNextPage = firstRelativeUrl.replaceFirst("<<GEJAHR>>", gejahr + ""); //die erste aufzurufendeSeite
|
||||
try { |
||||
|
||||
stmt.execute("begin transaction"); |
||||
stmt.execute("delete from gxstage_dms_metadata where gejahr=" + gejahr); |
||||
int pageCount = 1; |
||||
while (firstOrNextPage != null) { |
||||
System.out.println("Lade page " + pageCount + " via " + urlBase + firstOrNextPage); |
||||
logger.info("\nLade page " + pageCount + " via " + urlBase + firstOrNextPage); |
||||
String json = getMetadata(gejahr, firstOrNextPage); |
||||
if (logger.getLevel() == java.util.logging.Level.FINEST) { |
||||
saveJsonToDisk(gejahr, pageCount, json); |
||||
} |
||||
firstOrNextPage = parse(gejahr, json); |
||||
pageCount++; |
||||
} |
||||
stmt.execute("commit"); |
||||
|
||||
} catch (Exception e) { |
||||
if (stmt != null) { |
||||
stmt.execute("rollback"); |
||||
stmt.close(); |
||||
} |
||||
e.printStackTrace(); |
||||
System.exit(-1); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
private void saveJsonToDisk(int gejahr, int pageCount, String json) throws IOException { |
||||
String filename = "tmpMetadata-" + gejahr + "-" + pageCount + ".json"; |
||||
logger.info(" Speichere json in " + filename); |
||||
File outfile = new File(filename); |
||||
FileWriter writer = new FileWriter(outfile); |
||||
writer.append(json); |
||||
writer.close(); |
||||
|
||||
} |
||||
|
||||
private String getMetadata(int gejahr, String relUrl) throws IOException { |
||||
StringBuffer json = new StringBuffer(); |
||||
URL myurl = new URL(urlBase + relUrl.replaceAll("PARAMGEJAHR", gejahr + "")); |
||||
|
||||
HttpURLConnection urlConnection = (HttpURLConnection) myurl.openConnection(); |
||||
|
||||
urlConnection.setDoOutput(true); |
||||
urlConnection.setRequestMethod("GET"); |
||||
urlConnection.setRequestProperty("User-Agent", "Java client"); |
||||
urlConnection.setRequestProperty("charset", "utf-8"); |
||||
urlConnection.setRequestProperty("Accept", "application/json"); |
||||
// httpcon.setRequestProperty("Content-Length", "0");
|
||||
urlConnection.setUseCaches(false); |
||||
if (isTokenNeeded) { |
||||
urlConnection.setRequestProperty("Authorization", "Bearer " + getToken()); |
||||
} |
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |
||||
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); |
||||
String line; |
||||
while ((line = br.readLine()) != null) { |
||||
json.append(line); |
||||
} |
||||
} else { |
||||
throw new IOException("Fehler beim Lesen von Metadaten " + urlConnection.getResponseMessage() + "Status Code " + urlConnection.getResponseCode()); |
||||
} |
||||
|
||||
|
||||
return json.toString(); |
||||
} |
||||
|
||||
protected String getToken() { |
||||
String token = null; |
||||
try { |
||||
token = tokenrequester.getToken(); |
||||
//logger.finest("Token: "+token);
|
||||
} catch (IOException e) { |
||||
System.out.println("Fehler bei der Tokenermittlung"); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
|
||||
return token; |
||||
} |
||||
|
||||
|
||||
private void prepareDbAndPreparedStatement(String dbpropfile) throws Exception { |
||||
logger.info("Vorbereitung der Datenbankverbindung"); |
||||
SxConnection myConnection = new SxConnection(); |
||||
myConnection.setPropfile(dbpropfile); |
||||
con = myConnection.getConnection(); |
||||
con.setAutoCommit(false); |
||||
stmt = con.createStatement(); |
||||
initTokenRequester(stmt); |
||||
|
||||
pst = con.prepareStatement("insert into gxstage_dms_metadata (gejahr, belegnummer,id_jahr_belegnr,filename,mimetype,docid,art) values (?,?,?,?,?,?,?)"); |
||||
|
||||
|
||||
} |
||||
|
||||
private void initTokenRequester(Statement st) throws SQLException, IOException { |
||||
ResultSet rs = st.executeQuery("select content from sx_repository where id='DVELOP_ARCHIV1_TOKENURL' and aktiv=1 and today() between gueltig_seit and gueltig_bis"); |
||||
String input = null; |
||||
while (rs.next()) { |
||||
input = rs.getString("content"); |
||||
} |
||||
if (input == null || input.trim().length() == 0) { |
||||
throw new IllegalStateException("Keine aktive DVELOP_ARCHIV1_TOKENURL im Repository gefunden"); |
||||
} |
||||
tokenrequester = new BasicAuthTokenRequester(input); |
||||
logger.fine("Tokenermittler vorbereitet "); |
||||
|
||||
} |
||||
|
||||
|
||||
private void finishWorkinDb() throws SQLException { |
||||
stmt.close(); |
||||
pst.close(); |
||||
con.close(); |
||||
} |
||||
|
||||
private String parse(int gejahr, String json) throws JsonParseException, IOException, SQLException { |
||||
JsonFactory jfactory = new JsonFactory(); |
||||
JsonParser jParser = jfactory.createParser(json); |
||||
DvelopDocumentMetadata d = new DvelopDocumentMetadata(); |
||||
d.setGejahr(gejahr); |
||||
String nextPage = null; |
||||
|
||||
while (jParser.nextToken() != JsonToken.END_OBJECT) { |
||||
String fieldname = jParser.getCurrentName(); |
||||
logger.finest(" Verarbeite JSON Fieldname " + fieldname); |
||||
if ("items".equals(fieldname)) { |
||||
JsonToken tok = jParser.nextToken(); |
||||
|
||||
while (tok != JsonToken.END_ARRAY) { |
||||
|
||||
if ("sourceProperties".equals(jParser.getCurrentName())) { |
||||
//logger.finest(" analysiere sourceProperties");
|
||||
tok = jParser.nextToken(); |
||||
String value = ""; |
||||
String key = ""; |
||||
while (tok != JsonToken.END_ARRAY) { |
||||
|
||||
if ("key".equals(jParser.currentName())) { |
||||
jParser.nextToken(); |
||||
key = jParser.getText(); |
||||
jParser.nextToken(); |
||||
if ("value".equals(jParser.currentName())) { |
||||
jParser.nextToken(); |
||||
value = jParser.getText(); |
||||
} |
||||
} |
||||
|
||||
if ("docid".equals(key) && d.getDocid() == null) { |
||||
d.setDocid(value); |
||||
logger.fine(" DocID:" + d.getDocid()); |
||||
|
||||
} |
||||
if ("belnr".equals(key) && d.getBelegnummer() == null) { |
||||
d.setBelegnummer(value); |
||||
logger.fine(" Belegnr " + d.getBelegnummer()); |
||||
} |
||||
if ("mimetype".equals(key) && d.getMimetyp() == null) { |
||||
d.setMimetyp(value); |
||||
logger.fine(" MimeType:" + d.getMimetyp()); |
||||
|
||||
} |
||||
if ("filename".equals(key) && d.getFilename() == null) { |
||||
d.setFilename(value); |
||||
logger.fine(" Filename " + d.getFilename()); |
||||
} |
||||
if ("docart".equals(key) && d.getArt() == null) { |
||||
d.setArt(value); |
||||
logger.fine(" Art " + d.getArt()); |
||||
} |
||||
|
||||
|
||||
if (d.isValid()) { |
||||
counter++; |
||||
logger.info(" Speichere Eintrag " + counter); |
||||
insertIntoDb(d); |
||||
d = new DvelopDocumentMetadata(); |
||||
d.setGejahr(gejahr); |
||||
key = null; |
||||
value = null; |
||||
//sourceCategories überspringen
|
||||
|
||||
|
||||
} |
||||
tok = jParser.nextToken(); |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
|
||||
tok = jParser.nextToken(); |
||||
if ("sourceCategories".equals(jParser.getCurrentName())) { |
||||
jParser.skipChildren(); |
||||
|
||||
tok = jParser.nextToken(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
//nur wenn nextPage noch nicht gesetzt ist
|
||||
if ("_links".equals(fieldname) && nextPage == null) { |
||||
nextPage = parseLinksForNextPage(jParser); |
||||
} |
||||
} |
||||
jParser.close(); |
||||
return nextPage; |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
protected String parseLinksForNextPage(JsonParser jParser) throws IOException { |
||||
String nextPage = null; |
||||
JsonToken tok4 = jParser.nextToken(); |
||||
int i = 0; |
||||
while (!("_links".equals(jParser.currentName()) && tok4 == JsonToken.END_OBJECT) && i < 500000) { |
||||
if ("next".equals(jParser.currentName())) break; |
||||
tok4 = jParser.nextToken(); |
||||
i++; |
||||
} |
||||
if (i == 500000) throw new IOException("Endlosschleife entdeckt (pos 6)"); |
||||
if ("next".equals(jParser.currentName())) { |
||||
jParser.nextToken(); |
||||
jParser.nextToken(); |
||||
if ("href".equals(jParser.currentName())) { |
||||
jParser.nextToken(); |
||||
nextPage = jParser.getText(); |
||||
|
||||
logger.info(" NextPage-Eintrag gefunden " + nextPage); |
||||
} |
||||
|
||||
} |
||||
//Ans Ende von _links springen
|
||||
i = 0; |
||||
while (!"_links".equals(jParser.currentName()) && i < 500000) { |
||||
// System.out.println(jParser.currentName() + " " + tok4);
|
||||
tok4 = jParser.nextToken(); |
||||
i++; |
||||
} |
||||
|
||||
if (i == 500000) throw new IOException("Endlosschleife entdeckt (pos 7)"); |
||||
if (tok4 == JsonToken.END_OBJECT) { |
||||
jParser.nextToken(); |
||||
} |
||||
; |
||||
return nextPage; |
||||
} |
||||
|
||||
|
||||
|
||||
private void insertIntoDb(DvelopDocumentMetadata d) throws SQLException { |
||||
// System.out.println(" einfügen von Datensatz "+counter);
|
||||
pst.clearParameters(); |
||||
pst.setInt(1, d.getGejahr()); |
||||
pst.setString(2, d.getBelegnummer()); |
||||
pst.setString(3, d.getGejahr() + "-" + d.getBelegnummer()); |
||||
pst.setString(4, d.getFilename()); |
||||
pst.setString(5, d.getMimetyp()); |
||||
pst.setString(6, d.getDocid()); |
||||
pst.setString(7, d.getArt()); |
||||
pst.execute(); |
||||
logger.finest(" Eintrag in Datenbank gespeichert"); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
public class Encryptor { |
||||
|
||||
public static void main(String[] args) { |
||||
if (args.length==1) |
||||
|
||||
{ |
||||
try { |
||||
System.out.println("sx_des"+new ArchivePropHandler().encryptStringDES(args[0])); |
||||
} catch (Exception e) { |
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
System.out.println("Usage 1 Parameter: Quellstring"); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.MalformedURLException; |
||||
import java.net.URL; |
||||
|
||||
import org.apache.commons.io.IOUtils; |
||||
|
||||
public class FSVDocumentRetriever { |
||||
private static final long serialVersionUID = 1L; |
||||
private String urlbase; |
||||
private String token; |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println("Version 1.0 11.9.2023"); |
||||
if (args.length != 3) { |
||||
System.out.println("Parameter URLBase token docID"); |
||||
} else { |
||||
try { |
||||
FSVDocumentRetriever fdr = new FSVDocumentRetriever(args[0]); |
||||
fdr.setToken(args[1]); |
||||
fdr.test(args[2]); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public void setToken(String token) |
||||
{ |
||||
this.token=token; |
||||
} |
||||
public FSVDocumentRetriever(String urlbase) throws MalformedURLException { |
||||
this.urlbase = urlbase; |
||||
} |
||||
|
||||
public void test(String id) throws IOException { |
||||
String currentURL=urlbase+"?id="+id; |
||||
System.out.println("Rufe ab "+currentURL); |
||||
URL url=new URL(currentURL); |
||||
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); |
||||
System.out.println(" set Header Authorization Bearer "+token); |
||||
urlConnection.setRequestProperty ("Authorization", "Bearer "+token); |
||||
byte[] bytes = new byte[0]; |
||||
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
|
||||
bytes = IOUtils.toByteArray(urlConnection.getInputStream()); |
||||
// logger.fine(" " + bytes.length + " Bytes an Daten erhalten");
|
||||
// logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode());
|
||||
System.out.println(" " + bytes.length + " Bytes an Daten erhalten"); |
||||
System.out.println("HTTP-StatusCode: " + urlConnection.getResponseCode()); |
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { |
||||
File outputFile = new File("test.pdf"); |
||||
if (outputFile.exists()) { |
||||
outputFile.delete(); |
||||
} |
||||
FileOutputStream outputStream = new FileOutputStream(outputFile); |
||||
outputStream.write(bytes); |
||||
outputStream.close(); |
||||
System.out.println("als test.pdf gespeichert"); |
||||
|
||||
} else { |
||||
System.out.println("Fehler StatusCode nicht OK"); |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,106 @@
@@ -0,0 +1,106 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.DataOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
public class FSVTokenRequester { |
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private String url, username, password; |
||||
|
||||
private static boolean isTestModus = false; |
||||
|
||||
public static void main(String[] args) { |
||||
System.out.println("Tokentester Version 2023-09-11"); |
||||
if (args.length != 3) { |
||||
System.out.println("Parameter URL username Passwort"); |
||||
} else { |
||||
isTestModus = true; |
||||
FSVTokenRequester FSVtr = new FSVTokenRequester(args[0], args[1], args[2]); |
||||
|
||||
String token; |
||||
try { |
||||
token = FSVtr.authenticateAndGetToken(); |
||||
System.out.println(""); |
||||
System.out.println("Token:"); |
||||
System.out.println(token); |
||||
} catch (IOException e) { |
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
|
||||
} |
||||
} |
||||
|
||||
FSVTokenRequester(String url, String username, String password) { |
||||
this.url = url; |
||||
this.username = username; |
||||
this.password = password; |
||||
|
||||
} |
||||
|
||||
public String authenticateAndGetToken() throws IOException { |
||||
String token = null; |
||||
String urlParameters = "u=" + username + "&pw=" + password; |
||||
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8); |
||||
int postDataLength = postData.length; |
||||
HttpURLConnection con = null; |
||||
try { |
||||
|
||||
URL myurl = new URL(url); |
||||
con = (HttpURLConnection) myurl.openConnection(); |
||||
|
||||
con.setDoOutput(true); |
||||
con.setRequestMethod("POST"); |
||||
con.setRequestProperty("User-Agent", "Java client"); |
||||
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
||||
con.setRequestProperty("charset", "utf-8"); |
||||
con.setRequestProperty("Content-Length", Integer.toString(postDataLength)); |
||||
con.setUseCaches(false); |
||||
DataOutputStream wr = new DataOutputStream(con.getOutputStream()); |
||||
wr.write(postData); |
||||
|
||||
StringBuilder content; |
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); |
||||
|
||||
String line; |
||||
content = new StringBuilder(); |
||||
|
||||
while ((line = br.readLine()) != null) { |
||||
content.append(line); |
||||
content.append(System.lineSeparator()); |
||||
} |
||||
if (isTestModus) { |
||||
System.out.println("Serverantwort:"); |
||||
System.out.println(content.toString()); |
||||
} |
||||
token = extractToken(content.toString()); |
||||
} catch (Exception e) { |
||||
System.out.println("Fehler: " + e.toString()); |
||||
e.printStackTrace(); |
||||
throw new IOException("Token konnte nicht ermittelt werden " + e); |
||||
} finally { |
||||
if (con != null) con.disconnect(); |
||||
} |
||||
|
||||
return token; |
||||
} |
||||
|
||||
private String extractToken(String input) { |
||||
String result = ""; |
||||
if (input != null) { |
||||
result = input.replaceAll("<ticket>", ""); |
||||
result = result.replaceAll("</ticket>", ""); |
||||
} |
||||
|
||||
return result; |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.DataOutputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
|
||||
public class HISConnektorTest { |
||||
public static void main(String[] args) { |
||||
System.out.println("Version 2023-09-11"); |
||||
if (args.length != 2) { |
||||
System.out.println("Parameter URL basic_authentification_string"); |
||||
} else { |
||||
testtoken(args[0],args[1]); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
private static void testtoken(String url,String basicAuthentificationString) |
||||
{ |
||||
|
||||
HttpURLConnection con = null; |
||||
try { |
||||
URL myurl = new URL(url); |
||||
con = (HttpURLConnection) myurl.openConnection(); |
||||
|
||||
con.setDoOutput(true); |
||||
con.setRequestMethod("POST"); |
||||
con.setRequestProperty("User-Agent", "Java client"); |
||||
con.setRequestProperty("Accept", "application/json"); |
||||
con.setRequestProperty("charset", "utf-8"); |
||||
con.setRequestProperty("Content-Length", "0"); |
||||
con.setUseCaches(false); |
||||
con.setRequestProperty("Authorization", "Basic " + basicAuthentificationString); |
||||
DataOutputStream wr = new DataOutputStream(con.getOutputStream()); |
||||
byte[] postData=new byte[0]; |
||||
wr.write(postData); |
||||
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); |
||||
|
||||
String line; |
||||
|
||||
|
||||
while ((line = br.readLine()) != null) { |
||||
System.out.println(line); |
||||
} |
||||
|
||||
} catch (Exception e) { |
||||
System.out.println("Fehler: " + e.toString()); |
||||
e.printStackTrace(); |
||||
|
||||
} finally { |
||||
if (con != null) con.disconnect(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,180 @@
@@ -0,0 +1,180 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.InetSocketAddress; |
||||
import java.net.Proxy; |
||||
import java.net.Proxy.Type; |
||||
import java.net.URL; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.StringTokenizer; |
||||
|
||||
import jakarta.servlet.ServletException; |
||||
|
||||
import de.superx.servlet.SuperXManager; |
||||
|
||||
public class MBSArchiv1 extends AbstractDocPresenter { |
||||
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
|
||||
// false
|
||||
static boolean isSocksDebug = false; |
||||
|
||||
static Type proxyType = Proxy.Type.HTTP; |
||||
|
||||
private static final long serialVersionUID = 2L; |
||||
|
||||
private final boolean isDebug = false; |
||||
|
||||
Map<String, String> doctyp_Mimetype; |
||||
|
||||
private MBSArchiv1TokenRequester tokenrequester; |
||||
|
||||
void initSystem() throws ServletException { |
||||
if (isSocksDebug) proxyType = Proxy.Type.SOCKS; |
||||
//URL zum Abruf der Dokumente
|
||||
setUrlVorlage(readVorlageFromRepository("MBS_ARCHIV1_URLVORLAGE")); |
||||
//Token URL username und passwort
|
||||
initTokenRequester(); |
||||
|
||||
setDirectLinkToDocMWanted(false); |
||||
setMenuVorlage(readVorlageFromRepository("MBS_ARCHIV1_MENU_VORLAGE")); |
||||
setReadDocumentCountSql("select count(*) from fin_r_dokumente rd , fin_dokumente d where rd.dokumente_join_id = d.dokumente_serial " |
||||
+ " and rd.rechnungseingangsbuch_join_id::varchar(200)=?"); |
||||
//Hier wichtig, die ID im DokumentenManageManageSystem muss doc_id sein, für MenüVorlage daher "as doc_id"
|
||||
// keine Unterstriche, da übersichtlicher in Freemarker
|
||||
setReadDocumentListSql("select dokumente_dms_join_id::varchar(200) as doc_id,dokumente_filename as filename , dokumente_zeitstempel as zeitstempel from fin_r_dokumente rd , fin_dokumente d where rd.dokumente_join_id = d.dokumente_serial " |
||||
+ " and rd.rechnungseingangsbuch_join_id::varchar(200)=? order by dokumente_serial"); |
||||
|
||||
setDeleteOldRightsSql("delete from fin_user_rdrights where gueltig_bis<today()"); |
||||
setReadIdRightSql("select count(*) from fin_user_rdrights where userinfo_id=?::integer and rechnungseingangsbuch_id::varchar(200)=?"); |
||||
setReadDocIdRightSql("select count(*) from fin_dokumente D,fin_r_dokumente RD, fin_user_rdrights R where userinfo_id=?::integer " |
||||
+ "and D.dokumente_serial=RD.dokumente_join_id and RD.rechnungseingangsbuch_join_id=R.rechnungseingangsbuch_id " |
||||
+ "and D.dokumente_dms_join_id::varchar(200)=?"); |
||||
|
||||
|
||||
setReadDocIdSql("select dokumente_dms_join_id::varchar(200) from fin_r_dokumente rd , fin_dokumente d where rd.dokumente_join_id = d.dokumente_serial " |
||||
+ " and rd.rechnungseingangsbuch_join_id::varchar(200)=?"); |
||||
setReadMainDocIdSql("'not implemented' --select distinct doc_id from gxstage_ufr_docmanagement where maindoc=1 and vim=? and anzeige_relevant=1"); |
||||
// default=false setDocMenuAlwaysWanted(true);
|
||||
|
||||
initMimeTypes(); |
||||
|
||||
initProxy(); |
||||
} |
||||
|
||||
|
||||
void initTokenRequester() throws ServletException { |
||||
ArchivePropHandler ph = new ArchivePropHandler(); |
||||
String tokenvorlage = readVorlageFromRepository("MBS_ARCHIV1_TOKENURL"); |
||||
if (tokenvorlage.equals("docman_mbsarchive.properties")) { |
||||
try { |
||||
logger.info("Lese Tokeninformationen aus Datei "+SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties"); |
||||
tokenvorlage = ph.getUrlVorlage(SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties"); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
throw new ServletException("Fehler bei Lesen von Properties-Datei " + e); |
||||
} |
||||
} |
||||
StringTokenizer st = new StringTokenizer(tokenvorlage, "|"); |
||||
String tokenURL = null, tokenUsername = null, tokenPassword = null; |
||||
int i = 1; |
||||
while (st.hasMoreTokens()) { |
||||
String val = st.nextToken(); |
||||
if (i == 1) tokenURL = val; |
||||
if (i == 2) tokenUsername = val; |
||||
if (i == 3) tokenPassword = val; |
||||
i++; |
||||
} |
||||
if (tokenURL == null || tokenUsername == null || tokenPassword == null) { |
||||
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, URL|Username|Password bzw. Properties-Datei benötigt"); |
||||
} |
||||
if (tokenPassword.startsWith("sx_des")) { |
||||
try { |
||||
if (isDebug) |
||||
{ |
||||
logger.info("Verschluesseltes Passwort "+tokenPassword); |
||||
} |
||||
tokenPassword = ph.decryptStringDES(tokenPassword.substring(6)); |
||||
if (isDebug) |
||||
{ |
||||
logger.info("Entchluesseltes Passwort "+tokenPassword); |
||||
} |
||||
} catch (Exception e) { |
||||
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, Password nicht verarbeitet " + e); |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("Passwort nicht verschluesselt"); |
||||
} |
||||
tokenrequester = new MBSArchiv1TokenRequester(tokenURL, tokenUsername, tokenPassword); |
||||
} |
||||
|
||||
void initProxy() { |
||||
String[] params = getUrlVorlage().split("\\|"); |
||||
if (params.length > 5) { |
||||
logger.info("Intialisierung mit Proxy für das DocManagement"); |
||||
int port = 8080; |
||||
String host = params[5]; |
||||
if (params.length > 6 && params[6] != null) { |
||||
|
||||
try { |
||||
port = Integer.parseInt(params[6]); |
||||
} catch (NumberFormatException e) { |
||||
String msg = "Konnte Portnummer für Proxy nicht in Integer umwandeln: " + params[6]; |
||||
logger.severe(msg); |
||||
throw new IllegalStateException(msg); |
||||
} |
||||
|
||||
} |
||||
logger.info(" ProxyHost: " + host + " Port: " + port); |
||||
|
||||
setProxy(new Proxy(proxyType, new InetSocketAddress(host, port))); |
||||
} |
||||
} |
||||
|
||||
void initMimeTypes() { |
||||
// Hier erst initialisieren wegen komplexem Ablauf von Kontruktoren und
|
||||
// initSystem
|
||||
if (doctyp_Mimetype == null) doctyp_Mimetype = new HashMap<String, String>(); |
||||
doctyp_Mimetype.clear(); |
||||
doctyp_Mimetype.putAll(readMapFromDB("SELECT lower(endung),mimetype FROM fin_dms_mimetypes", null)); |
||||
logger.fine(" Mimetype Zuordnungen gefunden:" + doctyp_Mimetype); |
||||
} |
||||
|
||||
public MBSArchiv1(String sys) throws ServletException { |
||||
super(sys, null); |
||||
} |
||||
|
||||
|
||||
|
||||
/** |
||||
* |
||||
* |
||||
* @param doc_id - Hier eine docId! |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception { |
||||
result.setDocManagementUrl(new URL(getUrlVorlage() + "?id=" + doc_id)); |
||||
String filename = readStringFromDB("select dokumente_filename from fin_dokumente where dokumente_dms_join_id::varchar(200)=?", doc_id); |
||||
result.setDesiredFilename(filename); |
||||
String mt = ""; |
||||
if (filename.indexOf(".") > -1) { |
||||
String endung = filename.substring(filename.lastIndexOf(".") + 1, filename.length()).toLowerCase(); |
||||
if (doctyp_Mimetype.containsKey(endung)) { |
||||
mt = doctyp_Mimetype.get(endung); |
||||
} |
||||
} |
||||
|
||||
logger.fine(" Ermittelte minetype: " + mt + ""); |
||||
if (!mt.contentEquals("")) result.setMimetype(mt); |
||||
} |
||||
|
||||
|
||||
protected void setHeaderAuthorisation(HttpURLConnection urlConnection) throws IOException { |
||||
String token = tokenrequester.getToken(); |
||||
logger.info(" set Header Authorization Bearer " + token); |
||||
urlConnection.setRequestProperty("Authorization", "Bearer " + token); |
||||
} |
||||
} |
||||
|
||||
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.DataOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStreamReader; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
public class MBSArchiv1TokenRequester { |
||||
private String tokenURL,tokenUsername,tokenPassword; |
||||
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman"); |
||||
private final boolean isDebug=false; |
||||
public MBSArchiv1TokenRequester(String tokenURL,String tokenUsername,String tokenPassword) |
||||
{ |
||||
this.tokenURL=tokenURL; |
||||
this.tokenUsername=tokenUsername; |
||||
this.tokenPassword=tokenPassword; |
||||
} |
||||
|
||||
public String getToken() throws IOException { |
||||
String token = null; |
||||
String urlParameters = "u=" + tokenUsername + "&pw=" + tokenPassword; |
||||
if (isDebug) |
||||
{ |
||||
logger.info("Tokenermittlung parameter "+urlParameters); |
||||
} |
||||
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8); |
||||
int postDataLength = postData.length; |
||||
HttpURLConnection con = null; |
||||
try { |
||||
|
||||
URL myurl = new URL(tokenURL); |
||||
con = (HttpURLConnection) myurl.openConnection(); |
||||
|
||||
con.setDoOutput(true); |
||||
con.setRequestMethod("POST"); |
||||
con.setRequestProperty("User-Agent", "Java client"); |
||||
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
||||
con.setRequestProperty("charset", "utf-8"); |
||||
con.setRequestProperty("Content-Length", Integer.toString(postDataLength)); |
||||
con.setUseCaches(false); |
||||
DataOutputStream wr = new DataOutputStream(con.getOutputStream()); |
||||
wr.write(postData); |
||||
|
||||
StringBuilder content; |
||||
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); |
||||
|
||||
String line; |
||||
content = new StringBuilder(); |
||||
|
||||
while ((line = br.readLine()) != null) { |
||||
content.append(line); |
||||
content.append(System.lineSeparator()); |
||||
} |
||||
if (isDebug) |
||||
{ |
||||
logger.info("Server lieferte als Token-Response: "+content); |
||||
} |
||||
token = extractToken(content.toString()); |
||||
if (isDebug) |
||||
{ |
||||
logger.info("extrahiertes Token: "+token); |
||||
} |
||||
} catch (Exception e) { |
||||
System.out.println("Fehler: " + e.toString()); |
||||
e.printStackTrace(); |
||||
throw new IOException("Token konnte nicht ermittelt werden " + e); |
||||
} finally { |
||||
if (con != null) con.disconnect(); |
||||
} |
||||
|
||||
return token; |
||||
} |
||||
|
||||
private String extractToken(String input) { |
||||
String result = ""; |
||||
if (input != null) { |
||||
result = input.replaceAll("<ticket>", ""); |
||||
result = result.replaceAll("</ticket>", ""); |
||||
result = result.replaceAll("\n", ""); |
||||
result = result.replaceAll("\r", ""); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.net.Proxy; |
||||
import java.net.URL; |
||||
|
||||
import jakarta.servlet.ServletException; |
||||
|
||||
public class MBSBusinessTransactionArchiv extends MBSArchiv1 { |
||||
|
||||
public MBSBusinessTransactionArchiv(String sys) throws ServletException { |
||||
super(sys); |
||||
|
||||
} |
||||
void initSystem() throws ServletException { |
||||
if (isSocksDebug) proxyType = Proxy.Type.SOCKS; |
||||
//URL zum Abruf der Dokumente
|
||||
setUrlVorlage(readVorlageFromRepository("MBS_ARCHIV1_URLVORLAGE")); |
||||
//Token URL username und passwort
|
||||
initTokenRequester(); |
||||
|
||||
setDirectLinkToDocMWanted(false); |
||||
setMenuVorlage(readVorlageFromRepository("MBS_ARCHIV1_MENU_VORLAGE")); |
||||
setReadDocumentCountSql("select count(*) from fin_dms_ext where ref_business_transaction::varchar(200)=?"); |
||||
//Hier wichtig, die ID im DokumentenManageManageSystem muss doc_id sein, für MenüVorlage daher "as doc_id"
|
||||
// keine Unterstriche, da übersichtlicher in Freemarker
|
||||
setReadDocumentListSql("select doc_id,filename from fin_dms_ext " |
||||
+ " where ref_business_transaction::varchar(200)=? order by 1"); |
||||
|
||||
setDeleteOldRightsSql("delete from fin_user_rdrights where gueltig_bis<today()"); |
||||
setReadIdRightSql("select count(*) from fin_user_rdrights where userinfo_id=?::integer and ref_business_transaction::varchar(200)=?"); |
||||
setReadDocIdRightSql("select count(*) from fin_dms_ext D, fin_user_rdrights R where userinfo_id=?::integer " |
||||
+ "D.ref_business_transaction=R.ref_business_transaction " |
||||
+ "and D.ref_business_transaction::varchar(200)=?"); |
||||
|
||||
|
||||
setReadDocIdSql("select doc_id::varchar(200) from fin_dms_ext where ref_business_transaction::varchar(200)=?"); |
||||
setReadMainDocIdSql("'not implemented' --select distinct doc_id from gxstage_ufr_docmanagement where maindoc=1 and vim=? and anzeige_relevant=1"); |
||||
// default=false setDocMenuAlwaysWanted(true);
|
||||
|
||||
initMimeTypes(); |
||||
|
||||
initProxy(); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* |
||||
* @param doc_id - Hier eine docId! |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception { |
||||
result.setDocManagementUrl(new URL(getUrlVorlage() + "?id=" + doc_id)); |
||||
String filename = readStringFromDB("select filename from fin_dms_ext where doc_id::varchar(200)=?", doc_id); |
||||
result.setDesiredFilename(filename); |
||||
String mt = ""; |
||||
if (filename.indexOf(".") > -1) { |
||||
String endung = filename.substring(filename.lastIndexOf(".") + 1, filename.length()).toLowerCase(); |
||||
if (doctyp_Mimetype.containsKey(endung)) { |
||||
mt = doctyp_Mimetype.get(endung); |
||||
} |
||||
} |
||||
|
||||
logger.fine(" Ermittelte minetype: " + mt + ""); |
||||
if (!mt.contentEquals("")) result.setMimetype(mt); |
||||
} |
||||
} |
||||
@ -0,0 +1,84 @@
@@ -0,0 +1,84 @@
|
||||
|
||||
package de.superx.docmanagement; |
||||
|
||||
|
||||
|
||||
import java.io.ByteArrayOutputStream; |
||||
import java.io.FileInputStream; |
||||
import java.math.BigInteger; |
||||
import java.security.KeyStore; |
||||
import java.security.PrivateKey; |
||||
import java.security.Signature; |
||||
import java.security.cert.X509Certificate; |
||||
import java.util.Enumeration; |
||||
|
||||
import sun.security.pkcs.ContentInfo; |
||||
import sun.security.pkcs.PKCS7; |
||||
import sun.security.pkcs.SignerInfo; |
||||
import sun.security.util.DerOutputStream; |
||||
import sun.security.util.DerValue; |
||||
import sun.security.x509.AlgorithmId; |
||||
import sun.security.x509.X500Name; |
||||
|
||||
public class PCKSSigner { |
||||
|
||||
static final String STORENAME = "/home/superx/git/Memtext-Interna/Projekte/freiburg_uni/muster/SAP/documentenManagementAnbindung/tls/sapdokserver.jks"; |
||||
static final String STOREPASS = "$Anfang202020"; |
||||
|
||||
public static void main(String[] args) throws Exception{ |
||||
|
||||
//First load the keystore object by providing the p12 file path
|
||||
KeyStore clientStore = KeyStore.getInstance("PKCS12"); |
||||
//replace testPass with the p12 password/pin
|
||||
clientStore.load(new FileInputStream(STORENAME), STOREPASS.toCharArray()); |
||||
|
||||
String aliaz = "sapdokserver"; |
||||
//optional find first KeyEntry
|
||||
// Enumeration<String> aliases = clientStore.aliases();
|
||||
// String aliaz = "";
|
||||
// while(aliases.hasMoreElements()){
|
||||
|
||||
// aliaz = aliases.nextElement();
|
||||
// System.out.println(aliaz);
|
||||
// if(clientStore.isKeyEntry(aliaz)){
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
X509Certificate c = (X509Certificate)clientStore.getCertificate(aliaz); |
||||
|
||||
//Data to sign
|
||||
byte[] dataToSign = "kjasdflkjasdflkjasdflkjasdlkfjasöldkfj".getBytes(); |
||||
//compute signature:
|
||||
Signature signature = Signature.getInstance("Sha1WithRSA"); |
||||
signature.initSign((PrivateKey)clientStore.getKey(aliaz, STOREPASS.toCharArray())); |
||||
signature.update(dataToSign); |
||||
byte[] signedData = signature.sign(); |
||||
|
||||
//load X500Name
|
||||
X500Name xName = X500Name.asX500Name(c.getSubjectX500Principal()); |
||||
//load serial number
|
||||
BigInteger serial = c.getSerialNumber(); |
||||
//laod digest algorithm
|
||||
AlgorithmId digestAlgorithmId = new AlgorithmId(AlgorithmId.MD5_oid); |
||||
//load signing algorithm
|
||||
//AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.RSAEncryption_oid);
|
||||
AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.MD5_oid); |
||||
|
||||
//Create SignerInfo:
|
||||
SignerInfo sInfo = new SignerInfo(xName, serial, digestAlgorithmId, signAlgorithmId, signedData); |
||||
//Create ContentInfo:
|
||||
ContentInfo cInfo = new ContentInfo(ContentInfo.DIGESTED_DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign)); |
||||
// ContentInfo cInfo = new ContentInfo(ContentInfo.DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign));
|
||||
//Create PKCS7 Signed data
|
||||
PKCS7 p7 = new PKCS7(new AlgorithmId[] { digestAlgorithmId }, cInfo, |
||||
new java.security.cert.X509Certificate[] { c }, |
||||
new SignerInfo[] { sInfo }); |
||||
//Write PKCS7 to bYteArray
|
||||
ByteArrayOutputStream bOut = new DerOutputStream(); |
||||
p7.encodeSignedData(bOut); |
||||
byte[] encodedPKCS7 = bOut.toByteArray(); |
||||
System.out.println(new String(encodedPKCS7)); |
||||
} |
||||
} |
||||
|
||||
|
||||
@ -0,0 +1,141 @@
@@ -0,0 +1,141 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.File; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.InetSocketAddress; |
||||
import java.net.Proxy; |
||||
import java.net.Proxy.Type; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import jakarta.servlet.ServletException; |
||||
|
||||
import de.superx.servlet.SuperXManager; |
||||
|
||||
public class SAPArchiv1 extends AbstractDocPresenter { |
||||
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
|
||||
// false
|
||||
private static boolean isSocksDebug = false; |
||||
private static Type proxyType = Proxy.Type.HTTP; |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
private UniFrSecKeyGenerator secKeyGenerator; |
||||
private Map<String, String> doctyp_Mimetype; |
||||
|
||||
void initSystem() throws ServletException { |
||||
if (isSocksDebug) |
||||
proxyType = Proxy.Type.SOCKS; |
||||
setUrlVorlage(readVorlageFromRepository("SAP_ARCHIV1_URLVORLAGE")); |
||||
setDirectLinkToDocMWanted(false); |
||||
// setUrlVorlage(
|
||||
// "https://saphost-qot.bwhsrw.de:8090/archive?|pVersion=0046|authId=superx-test|expiration=10m"); + ggfs. Proxy und Port
|
||||
setMenuVorlage(readVorlageFromRepository("SAP_ARCHIV1_MENU_VORLAGE")); |
||||
setReadDocumentCountSql("select count(*) from gxstage_ufr_docmanagement where vim=? and anzeige_relevant=1"); |
||||
setReadDocumentListSql( |
||||
"select doc_id, CASE WHEN a.label IS NOT NULL THEN a.label ELSE d.dokumentenart END as dokumentenart," |
||||
+ "dokumententyp,ablagedatum,loeschdatum," |
||||
+ "CASE WHEN a.sort_nr IS NOT NULL THEN a.sort_nr ELSE 99 END as sort " |
||||
+ "from gxstage_ufr_docmanagement d " |
||||
+ "left join gxstage_ufr_dokart a on (d.dokumentenart = a.dokumentenart) " + "where vim=? " |
||||
+" and anzeige_relevant=1 " |
||||
+ " order by sort asc;"); |
||||
setDeleteOldRightsSql("delete from gxstage_ufr_user_vimrights where gueltig_bis<today()"); |
||||
setReadIdRightSql("select count(*) from gxstage_ufr_user_vimrights where userinfo_id=?::integer and vim=?"); |
||||
setReadDocIdRightSql( |
||||
"select count(*) from gxstage_ufr_docmanagement D, gxstage_ufr_user_vimrights R where userinfo_id=?::integer and D.vim=R.vim and D.doc_id=? and D.anzeige_relevant=1"); |
||||
|
||||
setReadDocIdSql("select doc_id from gxstage_ufr_docmanagement where vim=? and anzeige_relevant=1"); |
||||
setReadMainDocIdSql("select distinct doc_id from gxstage_ufr_docmanagement where maindoc=1 and vim=? and anzeige_relevant=1"); |
||||
setDocMenuAlwaysWanted(true); |
||||
initMimeTypes(); |
||||
initSecKeyGenerator(); |
||||
initProxy(); |
||||
} |
||||
|
||||
private void initProxy() { |
||||
String[] params = getUrlVorlage().split("\\|"); |
||||
if (params.length > 5) { |
||||
logger.info("Intialisierung mit Proxy für das DocManagement"); |
||||
int port = 8080; |
||||
String host = params[5]; |
||||
if (params.length > 6 && params[6] != null) { |
||||
|
||||
try { |
||||
port = Integer.parseInt(params[6]); |
||||
} catch (NumberFormatException e) { |
||||
String msg = "Konnte Portnummer für Proxy nicht in Integer umwandeln: " + params[6]; |
||||
logger.severe(msg); |
||||
throw new IllegalStateException(msg); |
||||
} |
||||
|
||||
} |
||||
logger.info(" ProxyHost: " + host + " Port: " + port); |
||||
|
||||
setProxy(new Proxy(proxyType, new InetSocketAddress(host, port))); |
||||
} |
||||
} |
||||
|
||||
private void initMimeTypes() { |
||||
// Hier erst initialisieren wegen komplexem Ablauf von Kontruktoren und
|
||||
// initSystem
|
||||
if (doctyp_Mimetype == null) |
||||
doctyp_Mimetype = new HashMap<String, String>(); |
||||
doctyp_Mimetype.clear(); |
||||
doctyp_Mimetype.putAll( |
||||
readMapFromDB("SELECT lower(dokumententyp),mimetype FROM gxstage_ufr_dokumententyp_mimetype", null)); |
||||
logger.fine(" Mimetype Zuordnungen gefunden:" + doctyp_Mimetype); |
||||
} |
||||
|
||||
public SAPArchiv1(String sys) throws ServletException { |
||||
super(sys, null); |
||||
} |
||||
|
||||
private void initSecKeyGenerator() throws ServletException { |
||||
try { |
||||
String privateKeyFile = SuperXManager.getWEB_INFPfad() + File.separator + "conf" + File.separator |
||||
+ "superx.p12"; |
||||
logger.info("Initing secKeyGenerator with " + privateKeyFile); |
||||
secKeyGenerator = new UniFrSecKeyGenerator(privateKeyFile, getUrlVorlage()); |
||||
} catch (Exception e) { |
||||
logger.severe("Fehler bei Intialisieren von SecKeyGenerator " + getExceptionStackTrace(e)); |
||||
throw new ServletException("Fehler bei Intialisieren von SecKeyGenerator " + e.toString()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* |
||||
* @param doc_id - Hier eine docId! |
||||
* @return |
||||
* @throws Exception |
||||
*/ |
||||
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception { |
||||
String loeschdatumUberschritten = readStringFromDB( |
||||
"select 'ja' from gxstage_ufr_docmanagement where doc_id=? and loeschdatum<today() union select 'nein' from gxstage_ufr_docmanagement where doc_id=? and (loeschdatum is null or loeschdatum>=today())", |
||||
doc_id, doc_id); |
||||
|
||||
if ("ja".contentEquals(loeschdatumUberschritten)) { |
||||
result.setMessage("Es kann kein Dokument geladen werden, da das Löschdatum für die DocID " + doc_id |
||||
+ " überschritten ist"); |
||||
} else { |
||||
String contentRep = readStringFromDB("select contentRep from gxstage_ufr_docmanagement where doc_id=?", |
||||
doc_id); |
||||
result.setDocManagementUrl(secKeyGenerator.getUrl(doc_id, contentRep)); |
||||
String doctyp = readStringFromDB("select dokumententyp from gxstage_ufr_docmanagement where doc_id=?", |
||||
doc_id); |
||||
result.setDesiredFilename(doc_id + "." + doctyp.toLowerCase()); |
||||
|
||||
String mt = doctyp_Mimetype.get(doctyp.toLowerCase()); |
||||
logger.fine(" Ermittelter Dokumententyp " + doctyp + " (minetype: " + mt + ")"); |
||||
result.setMimetype(mt); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Bei SAP-Achriv keine HeaderAuthorisation nötig, wird über secKey gemacht |
||||
*/ |
||||
protected void setHeaderAuthorisation(HttpURLConnection urlConnection) { |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
package de.superx.docmanagement; |
||||
import java.io.File; |
||||
import java.nio.charset.Charset; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Paths; |
||||
import java.security.KeyFactory; |
||||
import java.security.KeyPair; |
||||
import java.security.KeyPairGenerator; |
||||
import java.security.NoSuchAlgorithmException; |
||||
import java.security.PrivateKey; |
||||
import java.security.PublicKey; |
||||
import java.security.Signature; |
||||
import java.security.interfaces.RSAPrivateKey; |
||||
import java.security.spec.PKCS8EncodedKeySpec; |
||||
import java.security.spec.X509EncodedKeySpec; |
||||
import java.util.Base64; |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class SignerTest { |
||||
|
||||
|
||||
public static void main(String[] args) throws Exception { |
||||
|
||||
// KeyPair keyPair = getTestKeyPair();
|
||||
RSAPrivateKey privateKey=readPrivateKey2("/home/superx/git/Memtext-Interna/Projekte/freiburg_uni/muster/SAP/documentenManagementAnbindung/tls/private.der"); |
||||
byte[] data = "test".getBytes("UTF8"); |
||||
|
||||
Signature sig = Signature.getInstance("SHA1WithRSA"); |
||||
sig.initSign(privateKey); |
||||
sig.update(data); |
||||
byte[] signatureBytes = sig.sign(); |
||||
System.out.println("Signature:" +Base64.getEncoder().encodeToString(signatureBytes)); |
||||
|
||||
// sig.initVerify(keyPair.getPublic());
|
||||
// sig.update(data);
|
||||
|
||||
// System.out.println(sig.verify(signatureBytes));
|
||||
} |
||||
|
||||
public static PrivateKey getPrivateKey(String filename) |
||||
throws Exception { |
||||
|
||||
byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); |
||||
|
||||
PKCS8EncodedKeySpec spec = |
||||
new PKCS8EncodedKeySpec(keyBytes); |
||||
|
||||
KeyFactory kf = KeyFactory.getInstance("RSA"); |
||||
return kf.generatePrivate(spec); |
||||
} |
||||
|
||||
public static RSAPrivateKey readPrivateKey2(String filename) throws Exception { |
||||
File file=new File(filename); |
||||
String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset()); |
||||
|
||||
String privateKeyPEM = key |
||||
.replace("-----BEGIN PRIVATE KEY-----", "") |
||||
.replaceAll(System.lineSeparator(), "") |
||||
.replace("-----END PRIVATE KEY-----", ""); |
||||
|
||||
byte[] encoded = Base64.getDecoder().decode(privateKeyPEM); |
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); |
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); |
||||
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); |
||||
} |
||||
public static PublicKey getPublicKey(String filename) |
||||
throws Exception { |
||||
|
||||
byte[] keyBytes = Files.readAllBytes(Paths.get(filename)); |
||||
|
||||
X509EncodedKeySpec spec = |
||||
new X509EncodedKeySpec(keyBytes); |
||||
KeyFactory kf = KeyFactory.getInstance("RSA"); |
||||
return kf.generatePublic(spec); |
||||
} |
||||
|
||||
private static KeyPair getTestKeyPair() throws NoSuchAlgorithmException { |
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); |
||||
kpg.initialize(1024); |
||||
return kpg.genKeyPair(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,226 @@
@@ -0,0 +1,226 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.FileInputStream; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URL; |
||||
import java.net.URLEncoder; |
||||
import java.security.GeneralSecurityException; |
||||
import java.security.KeyStore; |
||||
import java.security.KeyStoreException; |
||||
import java.security.PrivateKey; |
||||
import java.security.Security; |
||||
import java.security.cert.X509Certificate; |
||||
import java.text.SimpleDateFormat; |
||||
import java.time.ZoneId; |
||||
import java.util.Base64; |
||||
import java.util.Date; |
||||
import java.util.StringTokenizer; |
||||
import java.util.TimeZone; |
||||
|
||||
import org.bouncycastle.cms.CMSException; |
||||
import org.bouncycastle.cms.CMSProcessableByteArray; |
||||
import org.bouncycastle.cms.CMSSignedData; |
||||
import org.bouncycastle.cms.CMSSignedDataGenerator; |
||||
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; |
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider; |
||||
import org.bouncycastle.operator.ContentSigner; |
||||
import org.bouncycastle.operator.OperatorCreationException; |
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; |
||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; |
||||
|
||||
public class UniFrSecKeyGenerator { |
||||
private final BouncyCastleProvider BCPROVIDER=new BouncyCastleProvider(); |
||||
private PrivateKey privateKey; |
||||
private X509Certificate certificate; |
||||
private String urlstart; |
||||
private String pVersion; |
||||
private String authId; |
||||
private String expiration; |
||||
private String compId; |
||||
public UniFrSecKeyGenerator(String p12path,String urlVorlage) throws Exception { |
||||
initKeystore(p12path); |
||||
initGeneralParams(urlVorlage); |
||||
|
||||
} |
||||
private void initGeneralParams(String urlVorlage) { |
||||
//Erwartet
|
||||
//"https://saphost-pot.bwhsrw.de/superx/archive|pVersion=0046|authId=superx|expiration=20210801000000");
|
||||
StringTokenizer st=new StringTokenizer(urlVorlage,"|"); |
||||
int i=0; |
||||
while (st.hasMoreTokens()) |
||||
{ |
||||
String param=st.nextToken(); |
||||
i++; |
||||
if (i==1) urlstart=param; |
||||
if (i==2) pVersion=param.substring(param.indexOf("=")+1); |
||||
if (i==3) authId=param.substring(param.indexOf("=")+1); |
||||
if (i==4) compId=param.substring(param.indexOf("=")+1); |
||||
if (i==5) expiration=param.substring(param.indexOf("=")+1); |
||||
//Param 6 und 7 können noch Proxy und desses Port sein, hier irrelevant
|
||||
} |
||||
if (this.urlstart==null) throw new IllegalStateException("URL Anfang nicht gefunden"); |
||||
if (this.pVersion==null) throw new IllegalStateException("pVersion nicht gefunden"); |
||||
if (this.authId==null) throw new IllegalStateException("authId nicht gefunden"); |
||||
if (this.compId==null) throw new IllegalStateException("compId nicht gefunden - wenn nicht genutzt werden soll compId=false übergeben"); |
||||
if (this.expiration==null) throw new IllegalStateException("expiration nicht gefunden"); |
||||
} |
||||
private void initKeystore(String p12path) throws Exception |
||||
{ |
||||
final KeyStore ks = KeyStore.getInstance("PKCS12"); |
||||
try (final InputStream in = new FileInputStream(p12path)) { |
||||
final char[] pwd = "sUp3rx!".toCharArray(); |
||||
ks.load(in, pwd); |
||||
final String alias = "1"; |
||||
privateKey = (PrivateKey) ks.getKey(alias, pwd); |
||||
certificate = (X509Certificate) ks.getCertificate(alias); |
||||
} |
||||
} |
||||
|
||||
public URL getUrl(String docId,String contRep) throws Exception { |
||||
// Refactoring möglich, für etwaige Abstimmung mit GISA nah am Beispielcode bleiben
|
||||
UrlParams params = new UrlParams(); |
||||
params.command = "get"; |
||||
params.accessModes = "r"; |
||||
params.pVersion=pVersion; |
||||
params.contRep=contRep; |
||||
params.docId=docId; |
||||
|
||||
SecKeyParams secKeyParams = new SecKeyParams(); |
||||
secKeyParams.authId = authId; |
||||
secKeyParams.privateKey = privateKey; |
||||
secKeyParams.certificate = certificate; |
||||
|
||||
String query = build(params, secKeyParams); |
||||
URL url = new URL(urlstart + query); |
||||
|
||||
return(url); |
||||
} |
||||
|
||||
|
||||
|
||||
private String build(UrlParams params, SecKeyParams secKeyParams) throws IOException, GeneralSecurityException { |
||||
boolean sign = secKeyParams != null; |
||||
StringBuilder query = new StringBuilder(1000); |
||||
StringBuilder sigData = sign ? new StringBuilder(1000) : null; |
||||
|
||||
query.append(params.command); |
||||
|
||||
addUrlParameter(query, "pVersion", params.pVersion, null); |
||||
addUrlParameter(query, "contRep", params.contRep, sigData); |
||||
addUrlParameter(query, "docId", params.docId, sigData); |
||||
if (compId!=null&&compId.length()>0&&!compId.contentEquals(("false"))) |
||||
{ |
||||
// Sonderlocke für create im PUT-Modus: compId mit signieren
|
||||
boolean needSignCompId = sign && "create".equals(params.command) && "PUT".equals(params.method); |
||||
addUrlParameter(query, "compId", compId, needSignCompId ? sigData : null); |
||||
} |
||||
if (sign) { |
||||
addUrlParameter(query, "accessMode", params.accessModes, sigData); |
||||
addUrlParameter(query, "authId", secKeyParams.authId, sigData); |
||||
addUrlParameter(query, "expiration", getExpiration(secKeyParams), sigData); |
||||
|
||||
byte[] sigBlock = sign(secKeyParams.privateKey, secKeyParams.certificate, sigData.toString().getBytes()); |
||||
String seckey = Base64.getEncoder().encodeToString(sigBlock); |
||||
addUrlParameter(query, "secKey", seckey, null); |
||||
} |
||||
|
||||
return query.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Zu Testzwecken festen Zeitpunkt |
||||
* @param secKeyParams |
||||
* @return |
||||
*/ |
||||
private String getExpiration(SecKeyParams secKeyParams) { |
||||
String result; |
||||
if (expiration.indexOf("m")>-1) //in Minuten
|
||||
{ |
||||
//TODO Datum aktuelle Zeitzone oder UTC?
|
||||
int minuten=Integer.parseInt(expiration.replaceAll("m", "")); |
||||
int expirationSekunden=60*minuten; |
||||
Date expires = new Date(System.currentTimeMillis() + expirationSekunden * 1000L); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); |
||||
sdf.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Z"))); // UTC
|
||||
result = sdf.format(expires); |
||||
} |
||||
else //fester Wert
|
||||
{ |
||||
if (expiration.length()!=14) throw new IllegalStateException("Fester Parameter für expiration muss 14stellig sein oder m für Minuten enthalten, ist "+expiration); |
||||
|
||||
result=expiration; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private byte[] sign(PrivateKey privateKey, X509Certificate certificate, byte[] dataToSign) |
||||
throws GeneralSecurityException, IOException { |
||||
try { |
||||
String sigAlgName = certificate.getSigAlgName(); |
||||
CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); |
||||
//Original Beispielcode
|
||||
// ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider("BC").build(privateKey);
|
||||
//Sicherheitshalber explizit als Objekt setzen,damit nicht Systemweiter Provider BC nötig
|
||||
ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider(BCPROVIDER).build(privateKey); |
||||
//Original Beispielcode
|
||||
//JcaDigestCalculatorProviderBuilder cpb = new JcaDigestCalculatorProviderBuilder().setProvider("BC");
|
||||
//Sicherheitshalber explizit als Objekt setzen,damit nicht Systemweiter Provider BC nötig
|
||||
JcaDigestCalculatorProviderBuilder cpb = new JcaDigestCalculatorProviderBuilder().setProvider(BCPROVIDER); |
||||
JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(cpb.build()); |
||||
generator.addSignerInfoGenerator(sigb.build(signer, certificate)); |
||||
CMSProcessableByteArray content = new CMSProcessableByteArray(dataToSign); |
||||
CMSSignedData signedData = generator.generate(content, false); |
||||
return signedData.getEncoded(); |
||||
} catch (CMSException | OperatorCreationException | Error ex) { |
||||
throw new GeneralSecurityException(ex); |
||||
} |
||||
} |
||||
|
||||
private void addUrlParameter(StringBuilder query, String key, String value, StringBuilder sigData) |
||||
throws UnsupportedEncodingException { |
||||
if (value != null && !value.isEmpty()) { |
||||
query.append('&').append(key).append('='); |
||||
String encoded = URLEncoder.encode(value, "UTF-8"); |
||||
int i = encoded.indexOf('+'); |
||||
if (i < 0) { |
||||
query.append(encoded); |
||||
} else { |
||||
int pos = query.length(); |
||||
query.append(encoded, 0, i).append("%20"); |
||||
++i; |
||||
for (int len = encoded.length(); i < len; ++i) { |
||||
char ch = encoded.charAt(i); |
||||
if (ch == '+') { |
||||
query.append("%20"); |
||||
} else { |
||||
query.append(ch); |
||||
} |
||||
} |
||||
encoded = query.substring(pos); |
||||
} |
||||
if (sigData != null) { |
||||
sigData.append(encoded); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static class UrlParams { |
||||
public String method; // GET, POST, PUT
|
||||
public String command; // get, docGet, info, create etc.
|
||||
public String contRep; |
||||
public String docId; |
||||
public String pVersion; |
||||
public String compId = "data"; |
||||
public String accessModes; // r,c,u,d (any combination of)
|
||||
} |
||||
|
||||
private static class SecKeyParams { |
||||
public String authId; |
||||
public PrivateKey privateKey; |
||||
public X509Certificate certificate; |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,224 @@
@@ -0,0 +1,224 @@
|
||||
package de.superx.docmanagement; |
||||
|
||||
import java.io.FileInputStream; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.UnsupportedEncodingException; |
||||
import java.net.URL; |
||||
import java.net.URLEncoder; |
||||
import java.security.GeneralSecurityException; |
||||
import java.security.KeyStore; |
||||
import java.security.PrivateKey; |
||||
import java.security.Security; |
||||
import java.security.cert.X509Certificate; |
||||
import java.text.SimpleDateFormat; |
||||
import java.time.ZoneId; |
||||
import java.util.Base64; |
||||
import java.util.Date; |
||||
import java.util.TimeZone; |
||||
|
||||
import org.bouncycastle.cms.CMSException; |
||||
import org.bouncycastle.cms.CMSProcessableByteArray; |
||||
import org.bouncycastle.cms.CMSSignedData; |
||||
import org.bouncycastle.cms.CMSSignedDataGenerator; |
||||
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; |
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider; |
||||
import org.bouncycastle.operator.ContentSigner; |
||||
import org.bouncycastle.operator.OperatorCreationException; |
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; |
||||
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; |
||||
|
||||
public class UniFrSecKeyGeneratorTest { |
||||
private String p12path="bi-superx.p12"; |
||||
private static String expirationSecs; |
||||
private static final String[] IDS= {"005056B5CBB01EEBA1C4963349F29CBF", "005056B5CBB01EEBA1C4983423EC7CD9", |
||||
"005056B5CBB01EEBA1C4983423EDDCD9", "005056B5CBB01EEBA1C4983423EF3CD9", |
||||
"005056B5CBB01EDBA1C8C4E5C2318381", "005056B5CBB01EEBA1B6526415B14239", |
||||
"005056B5CBB01EEBA1B653DA414E823D", "005056B5CBB01EEBA1B653DA414FE23D", |
||||
"005056B5CBB01EDBA1B25629173A1AF1", "005056B5CBB01EDBA1B257EB1AFEDAF4", |
||||
"005056B5CBB01EDBA1B2580A57DB1AF4", "005056B5CBB01EDBA1B2580A57DB3AF4", |
||||
"005056B5CBB01EEBA1E007B8D56C0DBE", "005056B5CBB01EDBA0E7A3151C561357", |
||||
"005056B5CBB01EEBA1E7B756E82D5B90" |
||||
}; |
||||
|
||||
|
||||
|
||||
public static void main(String a[]) { |
||||
if (a.length!=5) |
||||
{ |
||||
System.out.println(" Argumente: URL-Anfang (https://saphost-qot.bwhsrw.de:8090/archive?) docId contentRep auth-id sekunden bis expiration (3600=1h)"); |
||||
System.out.println(" Beispiel"); |
||||
System.out.println(" https://saphost-qot.bwhsrw.de:8090/archive? 005056B5CBB01EEBA1C4963349F29CBF QM superx-test 3600"); |
||||
System.exit(-1); |
||||
} |
||||
String urlstart=a[0]; |
||||
String docId=a[1]; |
||||
String contentRep=a[2]; |
||||
String authId=a[3]; |
||||
expirationSecs=a[4]; |
||||
|
||||
try { |
||||
UniFrSecKeyGeneratorTest test = new UniFrSecKeyGeneratorTest(); |
||||
URL url=test.getUrl(urlstart,"0046",docId ,contentRep,authId); |
||||
System.out.println(url); |
||||
/* for (int i=0;i<IDS.length;i++) |
||||
{ |
||||
System.out.println(test.getUrl("https://saphost-qot.bwhsrw.de:8090/archive?","0046",IDS[i] ,"QM","superx-test")); |
||||
}*/ |
||||
|
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public UniFrSecKeyGeneratorTest() { |
||||
|
||||
try { |
||||
//TODO setPath SuperXManager.getWEB_INFPfad()+File.separator+"conf"+File.separator+"superx.p12"
|
||||
//TODO prüfen, ob ohne explizites setzen von BouncyCastleProvider geht.
|
||||
Security.addProvider(new BouncyCastleProvider()); |
||||
} catch (Throwable ex) { |
||||
ex.printStackTrace(System.err); |
||||
} |
||||
} |
||||
//Params in DB 'urlstart=https://saphost-pot.bwhsrw.de/superx/archive|get=null|pVersion=0046|contRep=<<CONTENTREP>>|docId=<<DOCID>>|compId=data|accessMode=r|authId=superx|expiration=20210801000000',
|
||||
public URL getUrl(String urlstart,String pVersion,String docId,String contRep,String authId) throws FileNotFoundException, IOException, GeneralSecurityException { |
||||
UrlParams params = new UrlParams(); |
||||
params.command = "get"; |
||||
params.accessModes = "r"; |
||||
params.pVersion=pVersion; |
||||
params.contRep=contRep; |
||||
params.docId=docId; |
||||
|
||||
SecKeyParams secKeyParams = new SecKeyParams(); |
||||
secKeyParams.authId = authId; |
||||
final KeyStore ks = KeyStore.getInstance("PKCS12"); |
||||
try (final InputStream in = new FileInputStream(p12path)) { |
||||
final char[] pwd = "sUp3rx!".toCharArray(); |
||||
ks.load(in, pwd); |
||||
final String alias = "1"; |
||||
secKeyParams.privateKey = (PrivateKey) ks.getKey(alias, pwd); |
||||
secKeyParams.certificate = (X509Certificate) ks.getCertificate(alias); |
||||
} |
||||
catch(Exception e) |
||||
{ |
||||
System.out.println("Konnte bisuperx.p12 nicht einlesen"); |
||||
System.out.println(e); |
||||
System.exit(-1); |
||||
} |
||||
String query = build(params, secKeyParams); |
||||
URL url = new URL(urlstart + query); |
||||
// todo SSL/TLS setup etc.
|
||||
return(url); |
||||
} |
||||
|
||||
|
||||
|
||||
private String build(UrlParams params, SecKeyParams secKeyParams) throws IOException, GeneralSecurityException { |
||||
boolean sign = secKeyParams != null; |
||||
StringBuilder query = new StringBuilder(1000); |
||||
StringBuilder sigData = sign ? new StringBuilder(1000) : null; |
||||
|
||||
query.append(params.command); |
||||
|
||||
addUrlParameter(query, "pVersion", params.pVersion, null); |
||||
addUrlParameter(query, "contRep", params.contRep, sigData); |
||||
addUrlParameter(query, "docId", params.docId, sigData); |
||||
// Sonderlocke für create im PUT-Modus: compId mit signieren
|
||||
boolean needSignCompId = sign && "create".equals(params.command) && "PUT".equals(params.method); |
||||
addUrlParameter(query, "compId", params.compId, needSignCompId ? sigData : null); |
||||
|
||||
if (sign) { |
||||
addUrlParameter(query, "accessMode", params.accessModes, sigData); |
||||
addUrlParameter(query, "authId", secKeyParams.authId, sigData); |
||||
addUrlParameter(query, "expiration", getExpiration(secKeyParams), sigData); |
||||
|
||||
byte[] sigBlock = sign(secKeyParams.privateKey, secKeyParams.certificate, sigData.toString().getBytes()); |
||||
String seckey = Base64.getEncoder().encodeToString(sigBlock); |
||||
addUrlParameter(query, "secKey", seckey, null); |
||||
} |
||||
|
||||
return query.toString(); |
||||
} |
||||
|
||||
/** |
||||
* Zu Testzwecken festen Zeitpunkt |
||||
* @param secKeyParams |
||||
* @return |
||||
*/ |
||||
private String getExpiration(SecKeyParams secKeyParams) { |
||||
//TODO Datum aktuelle Zeitzone oder UTC?
|
||||
int secs=secKeyParams.expirationSeconds; |
||||
secs=Integer.parseInt(expirationSecs); |
||||
Date expires = new Date(System.currentTimeMillis() + secs * 1000L); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); |
||||
sdf.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Z"))); // UTC
|
||||
String expiration = sdf.format(expires); |
||||
|
||||
|
||||
return expiration; |
||||
} |
||||
|
||||
private byte[] sign(PrivateKey privateKey, X509Certificate certificate, byte[] dataToSign) |
||||
throws GeneralSecurityException, IOException { |
||||
try { |
||||
String sigAlgName = certificate.getSigAlgName(); |
||||
CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); |
||||
ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider("BC").build(privateKey); |
||||
JcaDigestCalculatorProviderBuilder cpb = new JcaDigestCalculatorProviderBuilder().setProvider("BC"); |
||||
JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(cpb.build()); |
||||
generator.addSignerInfoGenerator(sigb.build(signer, certificate)); |
||||
CMSProcessableByteArray content = new CMSProcessableByteArray(dataToSign); |
||||
CMSSignedData signedData = generator.generate(content, false); |
||||
return signedData.getEncoded(); |
||||
} catch (CMSException | OperatorCreationException | Error ex) { |
||||
throw new GeneralSecurityException(ex); |
||||
} |
||||
} |
||||
|
||||
private void addUrlParameter(StringBuilder query, String key, String value, StringBuilder sigData) |
||||
throws UnsupportedEncodingException { |
||||
if (value != null && !value.isEmpty()) { |
||||
query.append('&').append(key).append('='); |
||||
String encoded = URLEncoder.encode(value, "UTF-8"); |
||||
int i = encoded.indexOf('+'); |
||||
if (i < 0) { |
||||
query.append(encoded); |
||||
} else { |
||||
int pos = query.length(); |
||||
query.append(encoded, 0, i).append("%20"); |
||||
++i; |
||||
for (int len = encoded.length(); i < len; ++i) { |
||||
char ch = encoded.charAt(i); |
||||
if (ch == '+') { |
||||
query.append("%20"); |
||||
} else { |
||||
query.append(ch); |
||||
} |
||||
} |
||||
encoded = query.substring(pos); |
||||
} |
||||
if (sigData != null) { |
||||
sigData.append(encoded); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static class UrlParams { |
||||
public String method; // GET, POST, PUT
|
||||
public String command; // get, docGet, info, create etc.
|
||||
public String contRep; |
||||
public String docId; |
||||
public String pVersion; |
||||
public String compId = "data"; |
||||
public String accessModes; // r,c,u,d (any combination of)
|
||||
} |
||||
|
||||
private static class SecKeyParams { |
||||
public String authId; |
||||
public PrivateKey privateKey; |
||||
public X509Certificate certificate; |
||||
public int expirationSeconds = 3600; // 1h
|
||||
} |
||||
} |
||||
Binary file not shown.
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
Die jars bcpkix-jdk15on-169.jar bcprov-jdk15on-169.jar bcutil-jdk15on-169.jar sind BouncyCastle Klassen für das Documentenmangementanbindung in Freiburg/Mannheim nötig. |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
/* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
Apache Commons CLI |
||||
Copyright 2001-2009 The Apache Software Foundation |
||||
|
||||
This product includes software developed by |
||||
The Apache Software Foundation (http://www.apache.org/). |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue