835 changed files with 123577 additions and 124172 deletions
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType"> |
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="get_git_info,"/> |
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="get_git_info,"/> |
||||
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/> |
||||
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/> |
||||
<booleanAttribute key="org.eclipse.debug.core.ATTR_REFRESH_RECURSIVE" value="false"/> |
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources/>}"/> |
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/> |
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/> |
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/> |
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="superx"/> |
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="/home/superx/git/kern/superx-build/build.xml"/> |
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/> |
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/> |
||||
</launchConfiguration> |
||||
@ -1,46 +1,270 @@
@@ -1,46 +1,270 @@
|
||||
# ignore all log files |
||||
*.log |
||||
*.err |
||||
*.log.* |
||||
# agent and copilot context - local/temporary files |
||||
.github/ |
||||
|
||||
# Gradle build output and wrapper cache |
||||
build/ |
||||
.gradle/ |
||||
|
||||
# ignore all CVS + sub dirs |
||||
*CVS/ |
||||
# ignore /dist/* |
||||
*dist/ |
||||
|
||||
# ignore java classes |
||||
*classes/ |
||||
# ignore swap files |
||||
superx/WEB-INF/reports/swap_* |
||||
|
||||
# ignore files in directory rohdaten |
||||
superx/WEB-INF/conf/edustore/db/module/*/rohdaten/unl/*.unl |
||||
superx/WEB-INF/conf/edustore/db/install/rohdaten/unl/*.unl |
||||
# ignore eclipse settings |
||||
.settings/org.eclipse.ltk.core.refactoring.prefs |
||||
|
||||
# ignore temporary files |
||||
*.tmp |
||||
*.tmp.sql |
||||
temp.xml |
||||
tmp.fo |
||||
# vim .swp files |
||||
*.swp |
||||
|
||||
# ignore auto generated files |
||||
db.properties |
||||
dbforms-config.xml |
||||
superx/WEB-INF/dbforms-config.old |
||||
superx.datum |
||||
# ignore gradle bin |
||||
scripts/gradle/bin/ |
||||
scripts/gradle/.gradle/ |
||||
|
||||
# ignore iReport Designer |
||||
*.jasper |
||||
# cobertura |
||||
superx-build/cobertura* |
||||
|
||||
# ignore /dist/* |
||||
*dist/ |
||||
# classes |
||||
superx/WEB-INF/classes/ |
||||
|
||||
# ignore swap files |
||||
superx/WEB-INF/reports/swap_* |
||||
# tag files |
||||
**/tags |
||||
|
||||
src/edustore/edustore_*.xml |
||||
# .orig files |
||||
**/*.orig |
||||
|
||||
# ignore eclipse settings |
||||
.settings/org.eclipse.ltk.core.refactoring.prefs |
||||
#rpta files: |
||||
superx/WEB-INF/reports/simple_table.jrtx |
||||
superx/WEB-INF/reports/tabelle_jrxml_a4_quer.xsl.jrxml |
||||
superx/xml/jr_templates.xsl |
||||
superx/xml/rpta_assistent.xsl |
||||
# datum.alt files |
||||
**/superx.datum.alt |
||||
|
||||
# script artefacts |
||||
scripts/**/build/ |
||||
scripts/**/log/ |
||||
|
||||
# build artefacts |
||||
superx-build/declared-jars.txt |
||||
superx-build/cobertura_build_tests/ |
||||
superx-build/cobertura_build_classes/ |
||||
superx-build/coveragereport/ |
||||
superx-build/results/ |
||||
superx-build/tmp_build/ |
||||
|
||||
# Eclipse launch configurations are causing conflicts on 'pull' if you've got local ones; so they should not be under SCM |
||||
scripts/eclipseExternalTools/ |
||||
|
||||
# extracted h1-modules. These should only be links to folders in cs.bia.his_components |
||||
src-modules/module/prom/ |
||||
src-modules/module/res/ |
||||
src-modules/module/astat/ |
||||
src-modules/module/tt/ |
||||
src-modules/module/star/ |
||||
src-modules/module/kern_s/ |
||||
src-modules/module/res_s/ |
||||
# also ignore symlinks on linux |
||||
src-modules/module/prom |
||||
src-modules/module/res |
||||
src-modules/module/astat |
||||
src-modules/module/tt |
||||
src-modules/module/star |
||||
src-modules/module/kern_s |
||||
src-modules/module/res_s |
||||
src-modules/module/biad |
||||
|
||||
# artifact folders for reduced/cleaned modules |
||||
superx/WEB-INF/conf/edustore/db/module/prom/ |
||||
superx/WEB-INF/conf/edustore/db/module/res/ |
||||
superx/WEB-INF/conf/edustore/db/module/zul/ |
||||
superx/WEB-INF/conf/edustore/db/module/sos/ |
||||
superx/WEB-INF/conf/edustore/db/module/sva/ |
||||
superx/WEB-INF/conf/edustore/db/module/ivs/ |
||||
superx/WEB-INF/conf/edustore/db/module/astat/ |
||||
superx/WEB-INF/conf/edustore/db/module/tt/ |
||||
superx/WEB-INF/conf/edustore/db/module/lm/ |
||||
superx/WEB-INF/conf/edustore/db/module/etl/ |
||||
superx/WEB-INF/conf/edustore/db/module/star/ |
||||
superx/WEB-INF/conf/edustore/db/module/cob/ |
||||
superx/WEB-INF/conf/edustore/db/module/kern_s/ |
||||
superx/WEB-INF/conf/edustore/db/module/res_s/ |
||||
superx/WEB-INF/conf/edustore/db/module/bau/ |
||||
superx/WEB-INF/conf/edustore/db/module/fin/ |
||||
superx/WEB-INF/conf/edustore/db/module/biad/ |
||||
superx/WEB-INF/conf/edustore/db/module/gang/ |
||||
superx/WEB-INF/conf/edustore/db/module/erfolg/ |
||||
superx/WEB-INF/conf/edustore/db/module/man/ |
||||
superx/WEB-INF/conf/edustore/db/module/kenn/ |
||||
superx/WEB-INF/conf/edustore/db/module/kennx/ |
||||
|
||||
# module generation artifacts for module fin |
||||
src/edustore/edustore_fin.xml |
||||
superx/WEB-INF/fin_dbforms-config_ids.xml |
||||
superx/WEB-INF/fin_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module bau |
||||
src/edustore/edustore_bau.xml |
||||
superx/WEB-INF/bau_dbforms-config_ids.xml |
||||
superx/WEB-INF/bau_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module prom |
||||
src/edustore/edustore_prom.xml |
||||
superx/WEB-INF/prom_dbforms-config_ids.xml |
||||
superx/WEB-INF/prom_dbforms-config_pg.xml |
||||
superx/edit/prom/ |
||||
|
||||
# module generation artifacts for module res |
||||
src/edustore/edustore_res.xml |
||||
superx/WEB-INF/res_dbforms-config_ids.xml |
||||
superx/WEB-INF/res_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module gang |
||||
src/edustore/edustore_gang.xml |
||||
superx/WEB-INF/gang_dbforms-config_ids.xml |
||||
superx/WEB-INF/gang_dbforms-config_pg.xml |
||||
superx/edit/gang/*edit.jsp |
||||
superx/edit/gang/*list.jsp |
||||
|
||||
|
||||
# module generation artifacts for module kenn |
||||
src/edustore/edustore_kenn.xml |
||||
superx/WEB-INF/kenn_dbforms-config_ids.xml |
||||
superx/WEB-INF/kenn_dbforms-config_pg.xml |
||||
superx/edit/kenn/*edit.jsp |
||||
superx/edit/kenn/*list.jsp |
||||
|
||||
# module generation artifacts for module kennx |
||||
src/edustore/edustore_kennx.xml |
||||
superx/WEB-INF/kennx_dbforms-config_ids.xml |
||||
superx/WEB-INF/kennx_dbforms-config_pg.xml |
||||
superx/edit/kennx/*edit.jsp |
||||
superx/edit/kennx/*list.jsp |
||||
|
||||
|
||||
# module generation artifacts for module man |
||||
src/edustore/edustore_man.xml |
||||
superx/WEB-INF/man_dbforms-config_ids.xml |
||||
superx/WEB-INF/man_dbforms-config_pg.xml |
||||
superx/edit/man/catdesc.jsp |
||||
superx/edit/man/cat.jsp |
||||
superx/edit/man/grouping.jsp |
||||
superx/edit/man/man_reports.jsp |
||||
superx/edit/man/organigramm_dialog.jsp |
||||
superx/edit/man/rpt.jsp |
||||
superx/edit/man/*edit.jsp |
||||
superx/edit/man/*list.jsp |
||||
|
||||
# module generation artifacts for module erfolg |
||||
src/edustore/edustore_erfolg.xml |
||||
superx/WEB-INF/erfolg_dbforms-config_ids.xml |
||||
superx/WEB-INF/erfolg_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module sos |
||||
src/edustore/edustore_sos.xml |
||||
superx/WEB-INF/sos_dbforms-config_ids.xml |
||||
superx/WEB-INF/sos_dbforms-config_pg.xml |
||||
superx/edit/sos/hoererstatus_edit.jsp |
||||
superx/edit/sos/koepfe_oder_faelle_edit.jsp |
||||
superx/edit/sos/lehr_stg_ab_edit.jsp |
||||
superx/edit/sos/semester_edit.jsp |
||||
superx/edit/sos/semester_list.jsp |
||||
superx/edit/sos/sos_status_edit.jsp |
||||
superx/edit/sos/sos_stichtag_edit.jsp |
||||
superx/edit/sos/sos_stichtag_list.jsp |
||||
superx/edit/sos/statistik_edit.jsp |
||||
superx/edit/sos/studierendenuebertragung_edit.jsp |
||||
|
||||
# module generation artifacts for module sva |
||||
src/edustore/edustore_sva.xml |
||||
superx/WEB-INF/sva_dbforms-config_ids.xml |
||||
superx/WEB-INF/sva_dbforms-config_pg.xml |
||||
superx/edit/sva/konstanten_sva_edit.jsp |
||||
superx/edit/sva/sichten_sva_dienstart_edit.jsp |
||||
superx/edit/sva/sichten_sva_klr_geldgeber_kurz_edit.jsp |
||||
superx/edit/sva/sva_stichtag_list.jsp |
||||
superx/edit/sva/sx_repository_sva_edit.jsp |
||||
superx/edit/sva/user_sva.jsp |
||||
superx/edit/sva/user_sva_manuell.jsp |
||||
|
||||
# module generation artifacts for module ivs |
||||
src/edustore/edustore_ivs.xml |
||||
superx/edit/ivs/user_inventar_edit.jsp |
||||
superx/WEB-INF/ivs_dbforms-config_ids.xml |
||||
superx/WEB-INF/ivs_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module zul |
||||
src/edustore/edustore_zul.xml |
||||
superx/WEB-INF/zul_dbforms-config_ids.xml |
||||
superx/WEB-INF/zul_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module astat |
||||
src/edustore/edustore_astat.xml |
||||
superx/WEB-INF/astat_dbforms-config_ids.xml |
||||
superx/WEB-INF/astat_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module tt |
||||
src/edustore/edustore_tt.xml |
||||
superx/WEB-INF/tt_dbforms-config_ids.xml |
||||
superx/WEB-INF/tt_dbforms-config_pg.xml |
||||
superx/edit/tt/ |
||||
|
||||
# module generation artifacts for module lm |
||||
src/edustore/edustore_lm.xml |
||||
superx/WEB-INF/lm_dbforms-config_ids.xml |
||||
superx/WEB-INF/lm_dbforms-config_pg.xml |
||||
superx/edit/lm/ |
||||
|
||||
# module generation artifacts for module etl |
||||
src/edustore/edustore_etl.xml |
||||
superx/WEB-INF/etl_dbforms-config_ids.xml |
||||
superx/WEB-INF/etl_dbforms-config_pg.xml |
||||
superx/edit/etl/etl_job_edit.jsp |
||||
superx/edit/etl/etl_step_edit.jsp |
||||
superx/edit/etl/etl_step_type_list.jsp |
||||
|
||||
# module generation artifacts for module star |
||||
src/edustore/edustore_star.xml |
||||
superx/WEB-INF/star_dbforms-config_ids.xml |
||||
superx/WEB-INF/star_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module cob |
||||
src/edustore/edustore_cob.xml |
||||
superx/WEB-INF/cob_dbforms-config_ids.xml |
||||
superx/WEB-INF/cob_dbforms-config_pg.xml |
||||
superx/edit/cob/sx_repository_cob_edit.jsp |
||||
|
||||
# module generation artifacts for module kern_s |
||||
src/edustore/edustore_kern_s.xml |
||||
superx/WEB-INF/kern_s_dbforms-config_ids.xml |
||||
superx/WEB-INF/kern_s_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module res_s |
||||
src/edustore/edustore_res_s.xml |
||||
superx/WEB-INF/res_s_dbforms-config_ids.xml |
||||
superx/WEB-INF/res_s_dbforms-config_pg.xml |
||||
|
||||
# module generation artifacts for module biad |
||||
src/edustore/edustore_biad.xml |
||||
superx/WEB-INF/biad_dbforms-config_ids.xml |
||||
superx/WEB-INF/biad_dbforms-config_pg.xml |
||||
|
||||
# dbt project generation backups |
||||
superx/dbt/projects/*_backup/ |
||||
|
||||
# Saiku his icons |
||||
superx/saiku/css/saiku/src/saiku_his.css |
||||
|
||||
# Dateifunktionalität im kenn und kennx Modul |
||||
superx\WEB-INF\downloads |
||||
|
||||
# vscode personal settings |
||||
.vscode/ |
||||
.metadata/ |
||||
|
||||
# edustore.xml soll nicht mehr ausgeliefert werden siehe #313658 |
||||
src/edustore/edustore.xml |
||||
|
||||
# package folder und config file für statisch generierte JSPs |
||||
src/de/superx/jsp/ |
||||
superx/WEB-INF/jsp_servlet_config.xml |
||||
|
||||
# jaspers werden nicht mehr commitet, sondern im build gebaut |
||||
*.jasper |
||||
# updateUnmodifiedJars backup |
||||
superx/WEB-INF/lib/backup/ |
||||
|
||||
@ -1,36 +1,58 @@
@@ -1,36 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<projectDescription> |
||||
<name>eduStore_superX</name> |
||||
<comment></comment> |
||||
<projects> |
||||
</projects> |
||||
<buildSpec> |
||||
<buildCommand> |
||||
<name>org.eclipse.jdt.core.javabuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>org.eclipse.babel.editor.rbeBuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
</buildSpec> |
||||
<natures> |
||||
<nature>org.eclipse.jdt.groovy.core.groovyNature</nature> |
||||
<nature>org.eclipse.jdt.core.javanature</nature> |
||||
<nature>com.sysdeo.eclipse.tomcat.tomcatnature</nature> |
||||
<nature>com.jaspersoft.studio.babel.editor.rbeNature</nature> |
||||
</natures> |
||||
<filteredResources> |
||||
<filter> |
||||
<id>1459344926910</id> |
||||
<name></name> |
||||
<type>10</type> |
||||
<matcher> |
||||
<id>org.eclipse.ui.ide.multiFilter</id> |
||||
<arguments>1.0-name-matches-false-false-dist</arguments> |
||||
</matcher> |
||||
</filter> |
||||
</filteredResources> |
||||
</projectDescription> |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<projectDescription> |
||||
<name>eduStore_superX</name> |
||||
<comment></comment> |
||||
<projects> |
||||
</projects> |
||||
<buildSpec> |
||||
<buildCommand> |
||||
<name>org.eclipse.jdt.core.javabuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> |
||||
<triggers>full,incremental,</triggers> |
||||
<arguments> |
||||
<dictionary> |
||||
<key>LaunchConfigHandle</key> |
||||
<value><project>/.externalToolBuilders/Ant Superx Version.launch</value> |
||||
</dictionary> |
||||
</arguments> |
||||
</buildCommand> |
||||
</buildSpec> |
||||
<natures> |
||||
<nature>org.eclipse.jdt.core.javanature</nature> |
||||
<nature>com.sysdeo.eclipse.tomcat.tomcatnature</nature> |
||||
<nature>com.jaspersoft.studio.babel.editor.rbeNature</nature> |
||||
</natures> |
||||
<filteredResources> |
||||
<filter> |
||||
<id>1617792163171</id> |
||||
<name></name> |
||||
<type>10</type> |
||||
<matcher> |
||||
<id>org.eclipse.ui.ide.multiFilter</id> |
||||
<arguments>1.0-name-matches-false-false-dist</arguments> |
||||
</matcher> |
||||
</filter> |
||||
<filter> |
||||
<id>1617792163186</id> |
||||
<name></name> |
||||
<type>6</type> |
||||
<matcher> |
||||
<id>org.eclipse.ui.ide.multiFilter</id> |
||||
<arguments>1.0-name-matches-false-true-.+\.class</arguments> |
||||
</matcher> |
||||
</filter> |
||||
<filter> |
||||
<id>1687335947806</id> |
||||
<name></name> |
||||
<type>30</type> |
||||
<matcher> |
||||
<id>org.eclipse.core.resources.regexFilterMatcher</id> |
||||
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments> |
||||
</matcher> |
||||
</filter> |
||||
</filteredResources> |
||||
</projectDescription> |
||||
|
||||
@ -0,0 +1,901 @@
@@ -0,0 +1,901 @@
|
||||
/* |
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
||||
* |
||||
* Copyright (c) 2010-2013 Oracle and/or its affiliates. All rights reserved. |
||||
* |
||||
* The contents of this file are subject to the terms of either the GNU |
||||
* General Public License Version 2 only ("GPL") or the Common Development |
||||
* and Distribution License("CDDL") (collectively, the "License"). You |
||||
* may not use this file except in compliance with the License. You can |
||||
* obtain a copy of the License at |
||||
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
|
||||
* or packager/legal/LICENSE.txt. See the License for the specific |
||||
* language governing permissions and limitations under the License. |
||||
* |
||||
* When distributing the software, include this License Header Notice in each |
||||
* file and include the License file at packager/legal/LICENSE.txt. |
||||
* |
||||
* GPL Classpath Exception: |
||||
* Oracle designates this particular file as subject to the "Classpath" |
||||
* exception as provided by Oracle in the GPL Version 2 section of the License |
||||
* file that accompanied this code. |
||||
* |
||||
* Modifications: |
||||
* If applicable, add the following below the License Header, with the fields |
||||
* enclosed by brackets [] replaced by your own identifying information: |
||||
* "Portions Copyright [year] [name of copyright owner]" |
||||
* |
||||
* Contributor(s): |
||||
* If you wish your version of this file to be governed by only the CDDL or |
||||
* only the GPL Version 2, indicate your decision by adding "[Contributor] |
||||
* elects to include this software in this distribution under the [CDDL or GPL |
||||
* Version 2] license." If you don't indicate a single choice of license, a |
||||
* recipient has the option to distribute your version of this file under |
||||
* either the CDDL, the GPL Version 2 or to extend the choice of license to |
||||
* its licensees as provided above. However, if you add GPL Version 2 code |
||||
* and therefore, elected the GPL Version 2 license, then the option applies |
||||
* only if the new code is made subject to such option by the copyright |
||||
* holder. |
||||
*/ |
||||
|
||||
/* gepatchtes class-File: |
||||
* im Rahmen von #331613 muss mit dem Update auf Tomcat 10 auch die Anwendung von Serlvet API 4.0 auf 6.0 umgestellt werden. |
||||
* Dies leistet ein Migrationstool, welches in erster Linie den Packagenamen von 'javax' auf 'jakarta' umstellt. |
||||
* Allerdings bestand danach immer noch in der 'jersey-bunde-1.19.4.jar' ein Zugriff auf die entfernte Methode |
||||
* 'HttpServletResponse.setStatus(int, String)', welcher beim Laden von Saiku zu einer Exception geführt hat, |
||||
* wodurch das Frontend in der Ladeanzeige geblieben ist. |
||||
* Der Patch ändert die Klasse derart, dass sie die noch vorhandene Methode 'HttpServletResponse.setStatus(int)' aufruft, |
||||
* was zu funktionieren scheint. |
||||
* Ursprung entspricht https://github.com/javaee/jersey-1.x/blob/864a01d7be490ab93d2424da3e446ad8eb84b1e8/jersey-servlet/src/main/java/com/sun/jersey/spi/container/servlet/WebComponent.java
|
||||
*/ |
||||
|
||||
package com.sun.jersey.spi.container.servlet; |
||||
|
||||
import java.io.BufferedInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.OutputStream; |
||||
import java.lang.reflect.Constructor; |
||||
import java.lang.reflect.Proxy; |
||||
import java.lang.reflect.Type; |
||||
import java.net.URI; |
||||
import java.security.Principal; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Enumeration; |
||||
import java.util.HashMap; |
||||
import java.util.Iterator; |
||||
import java.util.LinkedList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.logging.Level; |
||||
import java.util.logging.Logger; |
||||
|
||||
import javax.ws.rs.WebApplicationException; |
||||
import javax.ws.rs.core.Application; |
||||
import javax.ws.rs.core.Context; |
||||
import javax.ws.rs.core.GenericEntity; |
||||
import javax.ws.rs.core.MediaType; |
||||
import javax.ws.rs.core.MultivaluedMap; |
||||
import javax.ws.rs.core.Response; |
||||
import javax.ws.rs.core.SecurityContext; |
||||
|
||||
import javax.naming.NamingException; |
||||
import jakarta.servlet.ServletContext; |
||||
import jakarta.servlet.ServletException; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
|
||||
import com.sun.jersey.api.container.ContainerException; |
||||
import com.sun.jersey.api.container.MappableContainerException; |
||||
import com.sun.jersey.api.core.ApplicationAdapter; |
||||
import com.sun.jersey.api.core.ClasspathResourceConfig; |
||||
import com.sun.jersey.api.core.PackagesResourceConfig; |
||||
import com.sun.jersey.api.core.ResourceConfig; |
||||
import com.sun.jersey.api.core.TraceInformation; |
||||
import com.sun.jersey.api.core.servlet.WebAppResourceConfig; |
||||
import com.sun.jersey.api.representation.Form; |
||||
import com.sun.jersey.core.header.InBoundHeaders; |
||||
import com.sun.jersey.core.header.MediaTypes; |
||||
import com.sun.jersey.core.reflection.ReflectionHelper; |
||||
import com.sun.jersey.core.util.ReaderWriter; |
||||
import com.sun.jersey.server.impl.InitialContextHelper; |
||||
import com.sun.jersey.server.impl.ThreadLocalInvoker; |
||||
import com.sun.jersey.server.impl.application.DeferredResourceConfig; |
||||
import com.sun.jersey.server.impl.cdi.CDIComponentProviderFactoryInitializer; |
||||
import com.sun.jersey.server.impl.container.servlet.JSPTemplateProcessor; |
||||
import com.sun.jersey.server.impl.ejb.EJBComponentProviderFactoryInitilizer; |
||||
import com.sun.jersey.server.impl.managedbeans.ManagedBeanComponentProviderFactoryInitilizer; |
||||
import com.sun.jersey.server.impl.model.method.dispatch.FormDispatchProvider; |
||||
import com.sun.jersey.server.impl.monitoring.GlassFishMonitoringInitializer; |
||||
import com.sun.jersey.server.probes.UriRuleProbeProvider; |
||||
import com.sun.jersey.spi.container.ContainerListener; |
||||
import com.sun.jersey.spi.container.ContainerNotifier; |
||||
import com.sun.jersey.spi.container.ContainerRequest; |
||||
import com.sun.jersey.spi.container.ContainerResponse; |
||||
import com.sun.jersey.spi.container.ContainerResponseWriter; |
||||
import com.sun.jersey.spi.container.ReloadListener; |
||||
import com.sun.jersey.spi.container.WebApplication; |
||||
import com.sun.jersey.spi.container.WebApplicationFactory; |
||||
import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider; |
||||
import java.security.AccessController; |
||||
import java.security.PrivilegedActionException; |
||||
|
||||
/** |
||||
* An abstract Web component that may be extended a Servlet and/or |
||||
* Filter implementation, or encapsulated by a Servlet or Filter implementation. |
||||
* |
||||
* @author Paul Sandoz (paul.sandoz at oracle.com) |
||||
*/ |
||||
public class WebComponent implements ContainerListener { |
||||
/** |
||||
* The servlet initialization property whose value is a fully qualified |
||||
* class name of a class that implements {@link ResourceConfig} or |
||||
* {@link Application}. |
||||
*/ |
||||
public static final String APPLICATION_CONFIG_CLASS = |
||||
"javax.ws.rs.Application"; |
||||
|
||||
/** |
||||
* The servlet initialization property whose value is a fully qualified |
||||
* class name of a class that implements {@link ResourceConfig} or |
||||
* {@link Application}. |
||||
*/ |
||||
public static final String RESOURCE_CONFIG_CLASS = |
||||
"com.sun.jersey.config.property.resourceConfigClass"; |
||||
|
||||
/** |
||||
* The base path in the Web Pages where JSP templates, associated with |
||||
* viewables of resource classes, are located. |
||||
* <p/> |
||||
* If this property is not set then the base path will be the root path |
||||
* of the Web Pages. |
||||
*/ |
||||
public static final String JSP_TEMPLATES_BASE_PATH = |
||||
"com.sun.jersey.config.property.JSPTemplatesBasePath"; |
||||
|
||||
|
||||
private static final Logger LOGGER = |
||||
Logger.getLogger(WebComponent.class.getName()); |
||||
|
||||
private final ThreadLocalInvoker<HttpServletRequest> requestInvoker = |
||||
new ThreadLocalInvoker<HttpServletRequest>(); |
||||
|
||||
private final ThreadLocalInvoker<HttpServletResponse> responseInvoker = |
||||
new ThreadLocalInvoker<HttpServletResponse>(); |
||||
|
||||
|
||||
private WebConfig config; |
||||
|
||||
private ResourceConfig resourceConfig; |
||||
|
||||
private WebApplication application; |
||||
|
||||
public WebComponent() { |
||||
} |
||||
|
||||
public WebComponent(Application app) { |
||||
if (app == null) |
||||
throw new IllegalArgumentException(); |
||||
|
||||
if (app instanceof ResourceConfig) { |
||||
resourceConfig = (ResourceConfig) app; |
||||
} else { |
||||
resourceConfig = new ApplicationAdapter(app); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Get the Web configuration. |
||||
* |
||||
* @return the Web configuration. |
||||
*/ |
||||
public WebConfig getWebConfig() { |
||||
return config; |
||||
} |
||||
|
||||
/** |
||||
* Get the resource configuration. |
||||
* |
||||
* @return the resource configuration. |
||||
*/ |
||||
public ResourceConfig getResourceConfig() { |
||||
return resourceConfig; |
||||
} |
||||
|
||||
/** |
||||
* Initiate the Web component. |
||||
* |
||||
* @param webConfig the Web configuration. |
||||
* @throws javax.servlet.ServletException in case of any initialization error |
||||
*/ |
||||
public void init(WebConfig webConfig) throws ServletException { |
||||
config = webConfig; |
||||
|
||||
if (resourceConfig == null) |
||||
resourceConfig = createResourceConfig(config); |
||||
|
||||
load(); |
||||
|
||||
Object o = resourceConfig.getProperties().get( |
||||
ResourceConfig.PROPERTY_CONTAINER_NOTIFIER); |
||||
if (o instanceof List) { |
||||
List list = (List) o; |
||||
for (Object elem : list) { |
||||
if (elem instanceof ContainerNotifier) { |
||||
ContainerNotifier crf = (ContainerNotifier) elem; |
||||
crf.addListener(this); |
||||
} |
||||
} |
||||
} else if (o instanceof ContainerNotifier) { |
||||
ContainerNotifier crf = (ContainerNotifier) o; |
||||
crf.addListener(this); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Destroy this Web component. |
||||
* <p/> |
||||
* This will destroy the Web application created by this this Web component. |
||||
*/ |
||||
public void destroy() { |
||||
if (application != null) |
||||
application.destroy(); |
||||
} |
||||
|
||||
private final static class Writer extends OutputStream implements ContainerResponseWriter { |
||||
final HttpServletResponse response; |
||||
|
||||
ContainerResponse cResponse; |
||||
|
||||
long contentLength; |
||||
|
||||
OutputStream out; |
||||
|
||||
boolean statusAndHeadersWritten = false; |
||||
|
||||
Writer(HttpServletResponse response) { |
||||
this.response = response; |
||||
} |
||||
|
||||
public OutputStream writeStatusAndHeaders(long contentLength, |
||||
ContainerResponse cResponse) throws IOException { |
||||
this.contentLength = contentLength; |
||||
this.cResponse = cResponse; |
||||
this.statusAndHeadersWritten = false; |
||||
return this; |
||||
} |
||||
|
||||
public void finish() throws IOException { |
||||
if (statusAndHeadersWritten) |
||||
return; |
||||
|
||||
// Note that the writing of headers MUST be performed before
|
||||
// the invocation of sendError as on some Servlet implementations
|
||||
// modification of the response headers will have no effect
|
||||
// after the invocation of sendError.
|
||||
writeHeaders(); |
||||
|
||||
|
||||
writeStatus(); |
||||
} |
||||
|
||||
private void writeStatus() { |
||||
Response.StatusType statusType = cResponse.getStatusType(); |
||||
final String reasonPhrase = statusType.getReasonPhrase(); |
||||
|
||||
// if (reasonPhrase != null) {
|
||||
// response.setStatus(statusType.getStatusCode(), reasonPhrase);
|
||||
// } else {
|
||||
response.setStatus(statusType.getStatusCode()); |
||||
// }
|
||||
} |
||||
|
||||
public void write(int b) throws IOException { |
||||
initiate(); |
||||
out.write(b); |
||||
} |
||||
|
||||
@Override |
||||
public void write(byte b[]) throws IOException { |
||||
if (b.length > 0) { |
||||
initiate(); |
||||
out.write(b); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void write(byte b[], int off, int len) throws IOException { |
||||
if (len > 0) { |
||||
initiate(); |
||||
out.write(b, off, len); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void flush() throws IOException { |
||||
writeStatusAndHeaders(); |
||||
if (out != null) |
||||
out.flush(); |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
initiate(); |
||||
out.close(); |
||||
} |
||||
|
||||
void initiate() throws IOException { |
||||
if (out == null) { |
||||
writeStatusAndHeaders(); |
||||
out = response.getOutputStream(); |
||||
} |
||||
} |
||||
|
||||
void writeStatusAndHeaders() { |
||||
if (statusAndHeadersWritten) |
||||
return; |
||||
|
||||
writeHeaders(); |
||||
writeStatus(); |
||||
statusAndHeadersWritten = true; |
||||
} |
||||
|
||||
void writeHeaders() { |
||||
if (contentLength != -1 && contentLength < Integer.MAX_VALUE) |
||||
response.setContentLength((int) contentLength); |
||||
|
||||
MultivaluedMap<String, Object> headers = cResponse.getHttpHeaders(); |
||||
for (Map.Entry<String, List<Object>> e : headers.entrySet()) { |
||||
for (Object v : e.getValue()) { |
||||
response.addHeader(e.getKey(), ContainerResponse.getHeaderValue(v)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Dispatch client requests to a resource class. |
||||
* |
||||
* @param baseUri the base URI of the request. |
||||
* @param requestUri the URI of the request. |
||||
* @param request the {@link HttpServletRequest} object that |
||||
* contains the request the client made to |
||||
* the Web component. |
||||
* @param response the {@link HttpServletResponse} object that |
||||
* contains the response the Web component returns |
||||
* to the client. |
||||
* @return the status code of the response. |
||||
* @throws IOException if an input or output error occurs |
||||
* while the Web component is handling the |
||||
* HTTP request. |
||||
* @throws ServletException if the HTTP request cannot |
||||
* be handled. |
||||
*/ |
||||
public int service(URI baseUri, URI requestUri, |
||||
final HttpServletRequest request, |
||||
final HttpServletResponse response) |
||||
throws ServletException, IOException { |
||||
// Copy the application field to local instance to ensure that the
|
||||
// currently loaded web application is used to process
|
||||
// request
|
||||
final WebApplication _application = application; |
||||
|
||||
final ContainerRequest cRequest = createRequest( |
||||
_application, |
||||
request, |
||||
baseUri, |
||||
requestUri); |
||||
|
||||
cRequest.setSecurityContext(new SecurityContext() { |
||||
public Principal getUserPrincipal() { |
||||
return request.getUserPrincipal(); |
||||
} |
||||
|
||||
public boolean isUserInRole(String role) { |
||||
return request.isUserInRole(role); |
||||
} |
||||
|
||||
public boolean isSecure() { |
||||
return request.isSecure(); |
||||
} |
||||
|
||||
public String getAuthenticationScheme() { |
||||
return request.getAuthType(); |
||||
} |
||||
}); |
||||
|
||||
try { |
||||
// Check if any servlet filters have consumed a request entity
|
||||
// of the media type application/x-www-form-urlencoded
|
||||
// This can happen if a filter calls request.getParameter(...)
|
||||
filterFormParameters(request, cRequest); |
||||
|
||||
UriRuleProbeProvider.requestStart(requestUri); |
||||
|
||||
requestInvoker.set(request); |
||||
responseInvoker.set(response); |
||||
|
||||
final Writer w = new Writer(response); |
||||
_application.handleRequest(cRequest, w); |
||||
return w.cResponse.getStatus(); |
||||
} catch (WebApplicationException ex) { |
||||
final Response exResponse = ex.getResponse(); |
||||
final String entity = exResponse.getEntity() != null ? exResponse.getEntity().toString() : null; |
||||
|
||||
response.sendError(exResponse.getStatus(), entity); |
||||
|
||||
return exResponse.getStatus(); |
||||
} catch (MappableContainerException ex) { |
||||
traceOnException(cRequest, response); |
||||
throw new ServletException(ex.getCause()); |
||||
} catch (ContainerException ex) { |
||||
traceOnException(cRequest, response); |
||||
throw new ServletException(ex); |
||||
} catch (RuntimeException ex) { |
||||
traceOnException(cRequest, response); |
||||
throw ex; |
||||
} finally { |
||||
UriRuleProbeProvider.requestEnd(); |
||||
requestInvoker.set(null); |
||||
responseInvoker.set(null); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Extension point for creating your custom container request. |
||||
* |
||||
* @param app the web app |
||||
* @param request the current servlet api request |
||||
* @param baseUri the base uri |
||||
* @param requestUri the request uri |
||||
* @return the request container |
||||
* @throws IOException if any error occurs when getting the input stream |
||||
*/ |
||||
protected ContainerRequest createRequest(WebApplication app, |
||||
HttpServletRequest request, URI baseUri, URI requestUri) throws IOException { |
||||
return new ContainerRequest( |
||||
app, |
||||
request.getMethod(), |
||||
baseUri, |
||||
requestUri, |
||||
getHeaders(request), |
||||
request.getInputStream()); |
||||
} |
||||
|
||||
private void traceOnException(final ContainerRequest cRequest, final HttpServletResponse response) { |
||||
if (cRequest.isTracingEnabled()) { |
||||
final TraceInformation ti = (TraceInformation) cRequest.getProperties(). |
||||
get(TraceInformation.class.getName()); |
||||
|
||||
ti.addTraceHeaders(new TraceInformation.TraceHeaderListener() { |
||||
public void onHeader(String name, String value) { |
||||
response.addHeader(name, value); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Create a new instance of a {@link WebApplication}. |
||||
* |
||||
* @return the {@link WebApplication} instance. |
||||
*/ |
||||
protected WebApplication create() { |
||||
return WebApplicationFactory.createWebApplication(); |
||||
} |
||||
|
||||
/** |
||||
* A helper class for creating an injectable provider that supports |
||||
* {@link Context} with a type and constant value. |
||||
* |
||||
* @param <T> the type of the constant value. |
||||
*/ |
||||
protected static class ContextInjectableProvider<T> extends |
||||
SingletonTypeInjectableProvider<Context, T> { |
||||
|
||||
/** |
||||
* Create a new instance. |
||||
* |
||||
* @param type the type of the constant value. |
||||
* @param instance the constant value. |
||||
*/ |
||||
protected ContextInjectableProvider(Type type, T instance) { |
||||
super(type, instance); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Configure the {@link ResourceConfig}. |
||||
* <p/> |
||||
* The {@link ResourceConfig} is configured such that the following classes |
||||
* may be injected onto the field of a root resource class or a parameter |
||||
* of a method of root resource class that is annotated with |
||||
* {@link javax.ws.rs.core.Context}: {@link HttpServletRequest}, {@link HttpServletResponse} |
||||
* , {@link ServletContext} and {@link WebConfig}. |
||||
* <p/> |
||||
* Any root resource class in registered in the resource configuration |
||||
* that is an interface is processed as follows. |
||||
* If the class is an interface and there exists a JNDI named object |
||||
* with the fully qualified class name as the JNDI name then that named |
||||
* object is added as a singleton root resource and the class is removed |
||||
* from the set of root resource classes. |
||||
* <p/> |
||||
* An inheriting class may override this method to configure the |
||||
* {@link ResourceConfig} to provide alternative or additional instances |
||||
* that are resource or provider classes or instances, and may modify the |
||||
* features and properties of the {@link ResourceConfig}. For an inheriting |
||||
* class to extend configuration behaviour the overriding method MUST call |
||||
* <code>super.configure(servletConfig, rc, wa)</code> as the first statement |
||||
* of that method. |
||||
* <p/> |
||||
* This method will be called only once at initiation. Subsequent |
||||
* reloads of the Web application will not result in subsequence calls to |
||||
* this method. |
||||
* |
||||
* @param wc the Web configuration |
||||
* @param rc the Resource configuration |
||||
* @param wa the Web application |
||||
*/ |
||||
protected void configure(WebConfig wc, ResourceConfig rc, WebApplication wa) { |
||||
configureJndiResources(rc); |
||||
|
||||
rc.getSingletons().add(new ContextInjectableProvider<HttpServletRequest>( |
||||
HttpServletRequest.class, |
||||
(HttpServletRequest) Proxy.newProxyInstance( |
||||
this.getClass().getClassLoader(), |
||||
new Class[]{HttpServletRequest.class}, |
||||
requestInvoker))); |
||||
|
||||
rc.getSingletons().add(new ContextInjectableProvider<HttpServletResponse>( |
||||
HttpServletResponse.class, |
||||
(HttpServletResponse) Proxy.newProxyInstance( |
||||
this.getClass().getClassLoader(), |
||||
new Class[]{HttpServletResponse.class}, |
||||
responseInvoker))); |
||||
|
||||
GenericEntity<ThreadLocal<HttpServletRequest>> requestThreadLocal = |
||||
new GenericEntity<ThreadLocal<HttpServletRequest>>(requestInvoker.getImmutableThreadLocal()) { |
||||
}; |
||||
rc.getSingletons().add(new ContextInjectableProvider<ThreadLocal<HttpServletRequest>>( |
||||
requestThreadLocal.getType(), requestThreadLocal.getEntity())); |
||||
|
||||
GenericEntity<ThreadLocal<HttpServletResponse>> responseThreadLocal = |
||||
new GenericEntity<ThreadLocal<HttpServletResponse>>(responseInvoker.getImmutableThreadLocal()) { |
||||
}; |
||||
rc.getSingletons().add(new ContextInjectableProvider<ThreadLocal<HttpServletResponse>>( |
||||
responseThreadLocal.getType(), responseThreadLocal.getEntity())); |
||||
|
||||
rc.getSingletons().add(new ContextInjectableProvider<ServletContext>( |
||||
ServletContext.class, |
||||
wc.getServletContext())); |
||||
|
||||
rc.getSingletons().add(new ContextInjectableProvider<WebConfig>( |
||||
WebConfig.class, |
||||
wc)); |
||||
|
||||
rc.getClasses().add(JSPTemplateProcessor.class); |
||||
|
||||
// TODO
|
||||
// If CDI is enabled should EJB injection be disabled?
|
||||
EJBComponentProviderFactoryInitilizer.initialize(rc); |
||||
|
||||
CDIComponentProviderFactoryInitializer.initialize(wc, rc, wa); |
||||
|
||||
// TODO
|
||||
// If CDI is enabled then no need to initialize managed beans
|
||||
ManagedBeanComponentProviderFactoryInitilizer.initialize(rc); |
||||
|
||||
GlassFishMonitoringInitializer.initialize(); |
||||
} |
||||
|
||||
/** |
||||
* Initiate the {@link WebApplication}. |
||||
* <p/> |
||||
* This method will be called once at initiation and for |
||||
* each reload of the Web application. |
||||
* <p/> |
||||
* An inheriting class may override this method to initiate the |
||||
* Web application with different parameters. |
||||
* |
||||
* @param rc the Resource configuration |
||||
* @param wa the Web application |
||||
*/ |
||||
protected void initiate(ResourceConfig rc, WebApplication wa) { |
||||
wa.initiate(rc); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Load the Web application. This will create, configure and initiate |
||||
* the web application. |
||||
*/ |
||||
public void load() { |
||||
WebApplication _application = create(); |
||||
configure(config, resourceConfig, _application); |
||||
initiate(resourceConfig, _application); |
||||
application = _application; |
||||
} |
||||
|
||||
/** |
||||
* Get the default resource configuration if one is not declared in the |
||||
* web.xml. |
||||
* <p/> |
||||
* This implementation returns an instance of {@link WebAppResourceConfig} |
||||
* that scans in files and directories as declared by the |
||||
* {@link ClasspathResourceConfig#PROPERTY_CLASSPATH} if present, otherwise |
||||
* in the "WEB-INF/lib" and "WEB-INF/classes" directories. |
||||
* <p/> |
||||
* An inheriting class may override this method to supply a different |
||||
* default resource configuration implementation. |
||||
* |
||||
* @param props the properties to pass to the resource configuration. |
||||
* @param wc the web configuration. |
||||
* @return the default resource configuration. |
||||
* @throws javax.servlet.ServletException in case of any issues with providing \ |
||||
* the default resource configuration |
||||
*/ |
||||
protected ResourceConfig getDefaultResourceConfig(Map<String, Object> props, |
||||
WebConfig wc) throws ServletException { |
||||
return getWebAppResourceConfig(props, wc); |
||||
} |
||||
|
||||
|
||||
// ContainerListener
|
||||
|
||||
/** |
||||
* Reload the Web application. This will create and initiate the web |
||||
* application using the same {@link ResourceConfig} implementation |
||||
* that was used to load the Web application. |
||||
* <p/> |
||||
* This method may be called at runtime, more than once, to reload the |
||||
* Web application. For example, if a {@link ResourceConfig} implementation |
||||
* is capable of detecting changes to resource classes (addition or removal) |
||||
* or providers then this method may be invoked to reload the web |
||||
* application for such changes to take effect. |
||||
* <p/> |
||||
* If this method is called when there are pending requests then such |
||||
* requests will be processed using the previously loaded web application. |
||||
*/ |
||||
public void onReload() { |
||||
WebApplication oldApplication = application; |
||||
WebApplication newApplication = create(); |
||||
initiate(resourceConfig, newApplication); |
||||
application = newApplication; |
||||
|
||||
if (resourceConfig instanceof ReloadListener) |
||||
((ReloadListener) resourceConfig).onReload(); |
||||
|
||||
oldApplication.destroy(); |
||||
|
||||
} |
||||
|
||||
|
||||
//
|
||||
|
||||
/* package */ ResourceConfig getWebAppResourceConfig(Map<String, Object> props, |
||||
WebConfig webConfig) throws ServletException { |
||||
// Default to using Web app resource config
|
||||
return new WebAppResourceConfig(props, webConfig.getServletContext()); |
||||
} |
||||
|
||||
private ResourceConfig createResourceConfig(WebConfig webConfig) |
||||
throws ServletException { |
||||
final Map<String, Object> props = getInitParams(webConfig); |
||||
final ResourceConfig rc = createResourceConfig(webConfig, props); |
||||
rc.setPropertiesAndFeatures(props); |
||||
return rc; |
||||
} |
||||
|
||||
private ResourceConfig createResourceConfig(WebConfig webConfig, Map<String, Object> props) |
||||
throws ServletException { |
||||
// Check if the resource config class property is present
|
||||
String resourceConfigClassName = webConfig.getInitParameter(RESOURCE_CONFIG_CLASS); |
||||
// Otherwise check if the JAX-RS application config class property is
|
||||
// present
|
||||
if (resourceConfigClassName == null) |
||||
resourceConfigClassName = webConfig.getInitParameter(APPLICATION_CONFIG_CLASS); |
||||
|
||||
// If no resource config class property is present
|
||||
if (resourceConfigClassName == null) { |
||||
// If the packages property is present then
|
||||
// use the packages resource config
|
||||
String packages = webConfig.getInitParameter( |
||||
PackagesResourceConfig.PROPERTY_PACKAGES); |
||||
if (packages != null) { |
||||
props.put(PackagesResourceConfig.PROPERTY_PACKAGES, packages); |
||||
return new PackagesResourceConfig(props); |
||||
} |
||||
|
||||
ResourceConfig defaultConfig = webConfig.getDefaultResourceConfig(props); |
||||
if (defaultConfig != null) |
||||
return defaultConfig; |
||||
|
||||
return getDefaultResourceConfig(props, webConfig); |
||||
} |
||||
|
||||
try { |
||||
Class<?> resourceConfigClass = AccessController.doPrivileged(ReflectionHelper. |
||||
classForNameWithExceptionPEA(resourceConfigClassName)); |
||||
|
||||
// TODO add support for WebAppResourceConfig
|
||||
if (resourceConfigClass == ClasspathResourceConfig.class) { |
||||
String[] paths = getPaths(webConfig.getInitParameter( |
||||
ClasspathResourceConfig.PROPERTY_CLASSPATH)); |
||||
props.put(ClasspathResourceConfig.PROPERTY_CLASSPATH, paths); |
||||
return new ClasspathResourceConfig(props); |
||||
} else if (ResourceConfig.class.isAssignableFrom(resourceConfigClass)) { |
||||
try { |
||||
Constructor constructor = resourceConfigClass.getConstructor(Map.class); |
||||
if (ClasspathResourceConfig.class.isAssignableFrom(resourceConfigClass)) { |
||||
String[] paths = getPaths(webConfig.getInitParameter( |
||||
ClasspathResourceConfig.PROPERTY_CLASSPATH)); |
||||
props.put(ClasspathResourceConfig.PROPERTY_CLASSPATH, paths); |
||||
} |
||||
return (ResourceConfig) constructor.newInstance(props); |
||||
} catch (NoSuchMethodException ex) { |
||||
// Pass through and try the default constructor
|
||||
} catch (Exception e) { |
||||
throw new ServletException(e); |
||||
} |
||||
|
||||
return new DeferredResourceConfig(resourceConfigClass.asSubclass(ResourceConfig.class)); |
||||
} else if (Application.class.isAssignableFrom(resourceConfigClass)) { |
||||
return new DeferredResourceConfig(resourceConfigClass.asSubclass(Application.class)); |
||||
} else { |
||||
String message = "Resource configuration class, " + resourceConfigClassName + |
||||
", is not a super class of " + Application.class; |
||||
throw new ServletException(message); |
||||
} |
||||
} catch (ClassNotFoundException e) { |
||||
String message = "Resource configuration class, " + resourceConfigClassName + |
||||
", could not be loaded"; |
||||
throw new ServletException(message, e); |
||||
} catch (PrivilegedActionException e) { |
||||
String message = "Resource configuration class, " + resourceConfigClassName + |
||||
", could not be loaded"; |
||||
throw new ServletException(message, e.getCause()); |
||||
} |
||||
} |
||||
|
||||
private Map<String, Object> getInitParams(WebConfig webConfig) { |
||||
Map<String, Object> props = new HashMap<String, Object>(); |
||||
Enumeration names = webConfig.getInitParameterNames(); |
||||
while (names.hasMoreElements()) { |
||||
String name = (String) names.nextElement(); |
||||
props.put(name, webConfig.getInitParameter(name)); |
||||
} |
||||
return props; |
||||
} |
||||
|
||||
private String[] getPaths(String classpath) throws ServletException { |
||||
final ServletContext context = config.getServletContext(); |
||||
if (classpath == null) { |
||||
String[] paths = { |
||||
context.getRealPath("/WEB-INF/lib"), |
||||
context.getRealPath("/WEB-INF/classes") |
||||
}; |
||||
if (paths[0] == null && paths[1] == null) { |
||||
String message = "The default deployment configuration that scans for " + |
||||
"classes in /WEB-INF/lib and /WEB-INF/classes is not supported " + |
||||
"for the application server." + |
||||
"Try using the package scanning configuration, see the JavaDoc for " + |
||||
PackagesResourceConfig.class.getName() + " and the property " + |
||||
PackagesResourceConfig.PROPERTY_PACKAGES + "."; |
||||
throw new ServletException(message); |
||||
} |
||||
return paths; |
||||
} else { |
||||
String[] virtualPaths = classpath.split(";"); |
||||
List<String> resourcePaths = new ArrayList<String>(); |
||||
for (String virtualPath : virtualPaths) { |
||||
virtualPath = virtualPath.trim(); |
||||
if (virtualPath.length() == 0) continue; |
||||
String path = context.getRealPath(virtualPath); |
||||
if (path != null) resourcePaths.add(path); |
||||
} |
||||
if (resourcePaths.isEmpty()) { |
||||
String message = "None of the declared classpath locations, " + |
||||
classpath + |
||||
", could be resolved. " + |
||||
"This could be because the default deployment configuration that scans for " + |
||||
"classes in classpath locations is not supported. " + |
||||
"Try using the package scanning configuration, see the JavaDoc for " + |
||||
PackagesResourceConfig.class.getName() + " and the property " + |
||||
PackagesResourceConfig.PROPERTY_PACKAGES + "."; |
||||
throw new ServletException(message); |
||||
} |
||||
return resourcePaths.toArray(new String[resourcePaths.size()]); |
||||
} |
||||
} |
||||
|
||||
private void configureJndiResources(ResourceConfig rc) { |
||||
// Obtain any instances that are registered in JNDI
|
||||
// Assumes such instances are singletons
|
||||
// Registered classes have to be interfaces
|
||||
javax.naming.Context x = InitialContextHelper.getInitialContext(); |
||||
if (x != null) { |
||||
Iterator<Class<?>> i = rc.getClasses().iterator(); |
||||
while (i.hasNext()) { |
||||
Class<?> c = i.next(); |
||||
if (!c.isInterface()) continue; |
||||
|
||||
try { |
||||
Object o = x.lookup(c.getName()); |
||||
if (o != null) { |
||||
i.remove(); |
||||
rc.getSingletons().add(o); |
||||
LOGGER.log(Level.INFO, |
||||
"An instance of the class " + c.getName() + |
||||
" is found by JNDI look up using the class name as the JNDI name. " + |
||||
"The instance will be registered as a singleton."); |
||||
} |
||||
} catch (NamingException ex) { |
||||
LOGGER.log(Level.CONFIG, |
||||
"JNDI lookup failed for Jersey application resource " + c.getName(), |
||||
ex); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void filterFormParameters(HttpServletRequest servletRequest, ContainerRequest containerRequet) throws IOException { |
||||
if (MediaTypes.typeEquals(MediaType.APPLICATION_FORM_URLENCODED_TYPE, containerRequet.getMediaType()) |
||||
&& !isEntityPresent(containerRequet)) { |
||||
Form f = new Form(); |
||||
|
||||
Enumeration e = servletRequest.getParameterNames(); |
||||
while (e.hasMoreElements()) { |
||||
String name = (String) e.nextElement(); |
||||
String[] values = servletRequest.getParameterValues(name); |
||||
|
||||
f.put(name, Arrays.asList(values)); |
||||
} |
||||
|
||||
if (!f.isEmpty()) { |
||||
containerRequet.getProperties().put(FormDispatchProvider.FORM_PROPERTY, f); |
||||
if (LOGGER.isLoggable(Level.WARNING)) { |
||||
LOGGER.log(Level.WARNING, |
||||
"A servlet request, to the URI " + containerRequet.getRequestUri() + ", " + |
||||
"contains form parameters in " + |
||||
"the request body but the request body has been consumed " + |
||||
"by the servlet or a servlet filter accessing the request " + |
||||
"parameters. Only resource methods using @FormParam " + |
||||
"will work as expected. Resource methods consuming the " + |
||||
"request body by other means will not work as expected."); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private boolean isEntityPresent(ContainerRequest cr) throws IOException { |
||||
InputStream in = cr.getEntityInputStream(); |
||||
if (!in.markSupported()) { |
||||
in = new BufferedInputStream(in, ReaderWriter.BUFFER_SIZE); |
||||
cr.setEntityInputStream(in); |
||||
} |
||||
|
||||
in.mark(1); |
||||
if (in.read() == -1) |
||||
return false; |
||||
else { |
||||
in.reset(); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
private InBoundHeaders getHeaders(HttpServletRequest request) { |
||||
InBoundHeaders rh = new InBoundHeaders(); |
||||
|
||||
for (Enumeration<String> names = request.getHeaderNames(); names.hasMoreElements();) { |
||||
String name = names.nextElement(); |
||||
List<String> valueList = new LinkedList<String>(); |
||||
for (Enumeration<String> values = request.getHeaders(name); values.hasMoreElements();) { |
||||
valueList.add(values.nextElement()); |
||||
} |
||||
rh.put(name, valueList); |
||||
} |
||||
|
||||
return rh; |
||||
} |
||||
} |
||||
@ -0,0 +1,366 @@
@@ -0,0 +1,366 @@
|
||||
/* |
||||
* $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/util/MultipartRequest.java,v 1.19 2005/02/19 21:26:32 hkollmann Exp $ |
||||
* $Revision: 1.19 $ |
||||
* $Date: 2005/02/19 21:26:32 $ |
||||
* |
||||
* DbForms - a Rapid Application Development Framework |
||||
* Copyright (C) 2001 Joachim Peer <joepeer@excite.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
*/ |
||||
|
||||
package org.dbforms.util; |
||||
|
||||
import org.apache.commons.fileupload.DiskFileUpload; |
||||
import org.apache.commons.fileupload.FileItem; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import java.util.Enumeration; |
||||
import java.util.Hashtable; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import java.util.Vector; |
||||
|
||||
import jakarta.servlet.ServletRequest; |
||||
import jakarta.servlet.ServletRequestWrapper; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import org.dbforms.util.external.FileUtil; |
||||
|
||||
import de.superx.util.multipart.support.DefaultMultipartHttpServletRequest; |
||||
|
||||
|
||||
/** |
||||
* A utility class to handle <code>multipart/form-data</code> requests, the |
||||
* kind of requests that support file uploads. This class emulates the interface
|
||||
* of <code>HttpServletRequest</code>, making it familiar to use. It uses a |
||||
* "push" model where any incoming files are read and saved directly to disk in |
||||
* the constructor. If you wish to have more flexibility, e.g. write the files |
||||
* to a database, use the "pull" model <code>MultipartParser</code> instead. |
||||
* <p> |
||||
* This class can receive arbitrarily large files (up to an artificial limit you |
||||
* can set), and fairly efficiently too. It cannot handle nested data (multipart |
||||
* content within multipart content) or internationalized content (such as non |
||||
* Latin-1 filenames). |
||||
* </p> |
||||
* <p> |
||||
* See the included <a href="upload.war">upload.war </a> for an example of how |
||||
* to use this class. |
||||
* <p> |
||||
* The full file upload specification is contained in experimental RFC 1867, |
||||
* available at <a href="http://www.ietf.org/rfc/rfc1867.txt" |
||||
* http://www.ietf.org/rfc/rfc1867.txt </a>.
|
||||
* </p> |
||||
* <p> |
||||
* PLEASE NOTE: this class uses Multipart Support Classes by Jason Hunter. |
||||
* Copyright (C) 1998 by Jason Hunter. All rights reserved. |
||||
* Use of this class is limited. Please see the LICENSE for more information. |
||||
* Make sure that you project meets the requierements defined by Jason Hunter |
||||
* respective O'reilly! |
||||
* </p> |
||||
* |
||||
* @see MultipartParser |
||||
* |
||||
* @author Jason Hunter |
||||
* @author Geoff Soutter |
||||
* @author Joe Peer - _changed_ it for use in DbForms (i apologize) |
||||
*/ |
||||
/* Witt: am 28.05.2026 als Basis für gepatchte Datei nach 'src-patches' übernommen, Basis waren meine |
||||
* lokalen 'dbforms_2.5_20050226' Sourcen */ |
||||
public class MultipartRequest { |
||||
private static Log logCat = LogFactory.getLog(MultipartRequest.class); // logging category
|
||||
private Hashtable files = new Hashtable(); // name - UploadedFile
|
||||
|
||||
// for this class
|
||||
//private File dir;
|
||||
private Hashtable parameters = new Hashtable(); // name - Vector of values
|
||||
|
||||
/** |
||||
* Constructs a new MultipartRequest to handle the specified request, |
||||
* {saving any uploaded files to the given directory}, and limiting the |
||||
* upload size to the specified length. If the content is too large, an |
||||
* IOException is thrown. This constructor actually parses the |
||||
* <tt>multipart/form-data</tt> and throws an IOException if there's any |
||||
* problem reading or parsing the request. |
||||
* |
||||
* @param request |
||||
* the servlet request. |
||||
* @param maxPostSize |
||||
* the maximum size of the POST content. |
||||
* @exception IOException |
||||
* if the uploaded content is larger than |
||||
* <tt>maxPostSize</tt> or there's a problem reading or |
||||
* parsing the request. |
||||
*/ |
||||
public MultipartRequest(HttpServletRequest request, |
||||
int maxPostSize) |
||||
throws IOException { |
||||
// Sanity check values
|
||||
if (request == null) { |
||||
throw new IllegalArgumentException("request cannot be null"); |
||||
} |
||||
|
||||
// Create a new file upload handler
|
||||
DiskFileUpload upload = new DiskFileUpload(); |
||||
|
||||
// Set upload parameters
|
||||
upload.setSizeMax(maxPostSize); |
||||
|
||||
String tmpDir = System.getProperty("java.io.tmpdir"); |
||||
upload.setRepositoryPath(tmpDir); |
||||
|
||||
// Parse the request
|
||||
try { |
||||
// we initilize this list with 'null', as the following unwrapping code should do the work - contrary to the 'org.dbforms.util.MultipartRequest code, from which this is copied
|
||||
List<FileItem> items = null; //upload.parseRequest(request);
|
||||
|
||||
if (items == null || items.size() == 0) { |
||||
ServletRequest originalRequest = request; |
||||
DefaultMultipartHttpServletRequest dmhsr = null; |
||||
while (originalRequest instanceof ServletRequestWrapper) { |
||||
if (originalRequest instanceof DefaultMultipartHttpServletRequest) { |
||||
dmhsr = (DefaultMultipartHttpServletRequest) originalRequest; |
||||
items = dmhsr.getFileItems(); |
||||
break; |
||||
} |
||||
originalRequest = ((ServletRequestWrapper) originalRequest).getRequest(); |
||||
} |
||||
} |
||||
|
||||
Iterator iter = items.iterator(); |
||||
|
||||
while (iter.hasNext()) { |
||||
FileItem item = (FileItem) iter.next(); |
||||
String name = item.getFieldName(); |
||||
|
||||
if (item.isFormField()) { |
||||
String value = item.getString(); |
||||
|
||||
// plain parameters get allways into parameters structure
|
||||
Vector existingValues = (Vector) parameters.get(name); |
||||
|
||||
if (existingValues == null) { |
||||
existingValues = new Vector(); |
||||
parameters.put(name, existingValues); |
||||
} |
||||
|
||||
existingValues.addElement(value); |
||||
} else { |
||||
String fileName = item.getName(); |
||||
|
||||
if (!Util.isNull(fileName)) { |
||||
File f = new File(fileName); |
||||
// 2004-08-05-HKK/Dziugas Baltrunas:
|
||||
// FileItem always returns the full pathname!
|
||||
fileName = FileUtil.filename(f.getName()); |
||||
|
||||
// The part actually contained a file
|
||||
// #changes by joe peer:
|
||||
// we must delay storing the file-inputstream (into
|
||||
// database, filesystem or whatever)
|
||||
// until we know exactly what should happen with it
|
||||
FileHolder fileHolder = new FileHolder(fileName, item); |
||||
files.put(name, fileHolder); |
||||
logCat.info("buffered and now added as " + name |
||||
+ " the following fileHolder:" |
||||
+ fileHolder.getFileName()); |
||||
|
||||
// #changes by joe peer:
|
||||
// if a file parameter is not null it gets into the
|
||||
// parameters structures as well
|
||||
// this is important to provide a simple access to
|
||||
// request (no distinction between files and plain
|
||||
// params)
|
||||
Vector existingValues = (Vector) parameters.get(name); |
||||
|
||||
if (existingValues == null) { |
||||
existingValues = new Vector(); |
||||
parameters.put(name, existingValues); |
||||
} |
||||
|
||||
existingValues.addElement(fileName); |
||||
} |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logCat.error("MultipartRequest", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the content type of the specified file (as supplied by the client |
||||
* browser), or null if the file was not included in the upload. |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return the content type of the file. |
||||
*/ |
||||
public String getContentType(String name) { |
||||
try { |
||||
//#changed by joe peer
|
||||
//UploadedFile file = (UploadedFile)files.get(name);
|
||||
FileHolder filePart = (FileHolder) files.get(name); |
||||
|
||||
return filePart.getContentType(); // may be null
|
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns a FilePart object for the specified file this method was added by |
||||
* joe peer |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return a FilePart object for the named file. |
||||
*/ |
||||
public FileHolder getFileHolder(String name) { |
||||
try { |
||||
return (FileHolder) files.get(name); |
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns a InputStream object for the specified file saved on the server's |
||||
* filesystem, or null if the file was not included in the upload. |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return a InputStream object for the named file. |
||||
*/ |
||||
public InputStream getFileInputStream(String name) { |
||||
try { |
||||
//#changed by joe peer
|
||||
//UploadedFile file = (UploadedFile)files.get(name);
|
||||
FileHolder filePart = (FileHolder) files.get(name); |
||||
|
||||
return filePart.getInputStreamFromBuffer(); // may be null
|
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the names of all the uploaded files as an Enumeration of Strings. |
||||
* It returns an empty Enumeration if there are no uploaded files. Each file |
||||
* name is the name specified by the form, not by the user. |
||||
* |
||||
* @return the names of all the uploaded files as an Enumeration of Strings. |
||||
*/ |
||||
public Enumeration getFileNames() { |
||||
return files.keys(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the filesystem name of the specified file, or null if the file |
||||
* was not included in the upload. A filesystem name is the name specified |
||||
* by the user. It is also the name under which the file is actually saved. |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return the filesystem name of the file. |
||||
*/ |
||||
public String getFilesystemName(String name) { |
||||
try { |
||||
//#changed by joe peer
|
||||
//UploadedFile file = (UploadedFile)files.get(name);
|
||||
FileHolder filePart = (FileHolder) files.get(name); |
||||
|
||||
return filePart.getFileName(); // may be null
|
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the value of the named parameter as a String, or null if the |
||||
* parameter was not sent or was sent without a value. The value is |
||||
* guaranteed to be in its normal, decoded form. If the parameter has |
||||
* multiple values, only the last one is returned (for backward |
||||
* compatibility). For parameters with multiple values, it's possible the |
||||
* last "value" may be null. |
||||
* |
||||
* @param name |
||||
* the parameter name. |
||||
* @return the parameter value. |
||||
*/ |
||||
public String getParameter(String name) { |
||||
try { |
||||
Vector values = (Vector) parameters.get(name); |
||||
|
||||
if ((values == null) || (values.size() == 0)) { |
||||
return null; |
||||
} |
||||
|
||||
String value = (String) values.elementAt(0); |
||||
|
||||
return value; |
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the names of all the parameters as an Enumeration of Strings. It |
||||
* returns an empty Enumeration if there are no parameters. |
||||
* |
||||
* @return the names of all the parameters as an Enumeration of Strings. |
||||
*/ |
||||
public Enumeration getParameterNames() { |
||||
return parameters.keys(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the values of the named parameter as a String array, or null if |
||||
* the parameter was not sent. The array has one entry for each parameter |
||||
* field sent. If any field was sent without a value that entry is stored in |
||||
* the array as a null. The values are guaranteed to be in their normal, |
||||
* decoded form. A single value is returned as a one-element array. |
||||
* |
||||
* @param name |
||||
* the parameter name. |
||||
* @return the parameter values. |
||||
*/ |
||||
public String[] getParameterValues(String name) { |
||||
try { |
||||
Vector values = (Vector) parameters.get(name); |
||||
|
||||
if ((values == null) || (values.size() == 0)) { |
||||
return null; |
||||
} |
||||
|
||||
String[] valuesArray = new String[values.size()]; |
||||
values.copyInto(valuesArray); |
||||
|
||||
return valuesArray; |
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,699 @@
@@ -0,0 +1,699 @@
|
||||
/* |
||||
* Copyright 2002-2016 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
/* taken/copied from 'spring-security-web-6.2.8.jar' as a base for patching */ |
||||
|
||||
package org.springframework.security.web.util; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
import java.util.Locale; |
||||
|
||||
import jakarta.servlet.ServletOutputStream; |
||||
import jakarta.servlet.WriteListener; |
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
import jakarta.servlet.http.HttpServletResponseWrapper; |
||||
|
||||
/** |
||||
* Base class for response wrappers which encapsulate the logic for handling an event when |
||||
* the {@link jakarta.servlet.http.HttpServletResponse} is committed. |
||||
* |
||||
* @author Rob Winch |
||||
* @since 4.0.2 |
||||
*/ |
||||
public abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper { |
||||
|
||||
private boolean disableOnCommitted; |
||||
|
||||
/** |
||||
* The Content-Length response header. If this is greater than 0, then once |
||||
* {@link #contentWritten} is larger than or equal the response is considered |
||||
* committed. |
||||
*/ |
||||
private long contentLength; |
||||
|
||||
/** |
||||
* The size of data written to the response body. The field will only be updated when |
||||
* {@link #disableOnCommitted} is false. |
||||
*/ |
||||
private long contentWritten; |
||||
|
||||
/** |
||||
* @param response the response to be wrapped |
||||
*/ |
||||
public OnCommittedResponseWrapper(HttpServletResponse response) { |
||||
super(response); |
||||
} |
||||
|
||||
@Override |
||||
public void addHeader(String name, String value) { |
||||
checkContentLengthHeader(name, value); |
||||
super.addHeader(name, value); |
||||
} |
||||
|
||||
@Override |
||||
public void addIntHeader(String name, int value) { |
||||
checkContentLengthHeader(name, value); |
||||
super.addIntHeader(name, value); |
||||
} |
||||
|
||||
@Override |
||||
public void setHeader(String name, String value) { |
||||
checkContentLengthHeader(name, value); |
||||
super.setHeader(name, value); |
||||
} |
||||
|
||||
@Override |
||||
public void setIntHeader(String name, int value) { |
||||
checkContentLengthHeader(name, value); |
||||
super.setIntHeader(name, value); |
||||
} |
||||
|
||||
private void checkContentLengthHeader(String name, int value) { |
||||
if ("Content-Length".equalsIgnoreCase(name)) { |
||||
setContentLength(value); |
||||
} |
||||
} |
||||
|
||||
private void checkContentLengthHeader(String name, String value) { |
||||
if ("Content-Length".equalsIgnoreCase(name)) { |
||||
setContentLength(Long.parseLong(value)); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void setContentLength(int len) { |
||||
setContentLength((long) len); |
||||
super.setContentLength(len); |
||||
} |
||||
|
||||
@Override |
||||
public void setContentLengthLong(long len) { |
||||
setContentLength(len); |
||||
super.setContentLengthLong(len); |
||||
} |
||||
|
||||
private void setContentLength(long len) { |
||||
this.contentLength = len; |
||||
checkContentLength(0); |
||||
} |
||||
|
||||
/** |
||||
* Invoke this method to disable invoking |
||||
* {@link OnCommittedResponseWrapper#onResponseCommitted()} when the |
||||
* {@link jakarta.servlet.http.HttpServletResponse} is committed. This can be useful |
||||
* in the event that Async Web Requests are made. |
||||
*/ |
||||
protected void disableOnResponseCommitted() { |
||||
this.disableOnCommitted = true; |
||||
} |
||||
|
||||
/** |
||||
* Returns true if {@link #onResponseCommitted()} will be invoked when the response is |
||||
* committed, else false. |
||||
* @return if {@link #onResponseCommitted()} is enabled |
||||
*/ |
||||
protected boolean isDisableOnResponseCommitted() { |
||||
return this.disableOnCommitted; |
||||
} |
||||
|
||||
/** |
||||
* Implement the logic for handling the |
||||
* {@link jakarta.servlet.http.HttpServletResponse} being committed |
||||
*/ |
||||
protected abstract void onResponseCommitted(); |
||||
|
||||
/** |
||||
* Makes sure {@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked |
||||
* before calling the superclass <code>sendError()</code> |
||||
*/ |
||||
@Override |
||||
public final void sendError(int sc) throws IOException { |
||||
doOnResponseCommitted(); |
||||
super.sendError(sc); |
||||
} |
||||
|
||||
/** |
||||
* Makes sure {@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked |
||||
* before calling the superclass <code>sendError()</code> |
||||
*/ |
||||
@Override |
||||
public final void sendError(int sc, String msg) throws IOException { |
||||
doOnResponseCommitted(); |
||||
super.sendError(sc, msg); |
||||
} |
||||
|
||||
/** |
||||
* Makes sure {@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked |
||||
* before calling the superclass <code>sendRedirect()</code> |
||||
*/ |
||||
@Override |
||||
public final void sendRedirect(String location) throws IOException { |
||||
doOnResponseCommitted(); |
||||
super.sendRedirect(location); |
||||
} |
||||
|
||||
/** |
||||
* Makes sure {@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked |
||||
* before calling the calling <code>getOutputStream().close()</code> or |
||||
* <code>getOutputStream().flush()</code> |
||||
*/ |
||||
@Override |
||||
public ServletOutputStream getOutputStream() throws IOException { |
||||
return new SaveContextServletOutputStream(super.getOutputStream()); |
||||
} |
||||
|
||||
/** |
||||
* Makes sure {@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked |
||||
* before calling the <code>getWriter().close()</code> or |
||||
* <code>getWriter().flush()</code> |
||||
*/ |
||||
@Override |
||||
public PrintWriter getWriter() throws IOException { |
||||
return new SaveContextPrintWriter(super.getWriter()); |
||||
} |
||||
|
||||
/** |
||||
* Makes sure {@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked |
||||
* before calling the superclass <code>flushBuffer()</code> |
||||
*/ |
||||
@Override |
||||
public void flushBuffer() throws IOException { |
||||
doOnResponseCommitted(); |
||||
super.flushBuffer(); |
||||
} |
||||
|
||||
private void trackContentLength(boolean content) { |
||||
if (!this.disableOnCommitted) { |
||||
checkContentLength(content ? 4 : 5); // TODO Localization
|
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(char content) { |
||||
if (!this.disableOnCommitted) { |
||||
checkContentLength(1); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(Object content) { |
||||
if (!this.disableOnCommitted) { |
||||
trackContentLength(String.valueOf(content)); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(byte[] content) { |
||||
if (!this.disableOnCommitted) { |
||||
checkContentLength((content != null) ? content.length : 0); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(char[] content) { |
||||
if (!this.disableOnCommitted) { |
||||
checkContentLength((content != null) ? content.length : 0); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(int content) { |
||||
if (!this.disableOnCommitted) { |
||||
trackContentLength(String.valueOf(content)); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(float content) { |
||||
if (!this.disableOnCommitted) { |
||||
trackContentLength(String.valueOf(content)); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(double content) { |
||||
if (!this.disableOnCommitted) { |
||||
trackContentLength(String.valueOf(content)); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLengthLn() { |
||||
if (!this.disableOnCommitted) { |
||||
trackContentLength("\r\n"); |
||||
} |
||||
} |
||||
|
||||
private void trackContentLength(String content) { |
||||
if (!this.disableOnCommitted) { |
||||
int contentLength = (content != null) ? content.length() : 4; |
||||
checkContentLength(contentLength); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Adds the contentLengthToWrite to the total contentWritten size and checks to see if |
||||
* the response should be written. |
||||
* @param contentLengthToWrite the size of the content that is about to be written. |
||||
*/ |
||||
private void checkContentLength(long contentLengthToWrite) { |
||||
this.contentWritten += contentLengthToWrite; |
||||
boolean isBodyFullyWritten = this.contentLength > 0 && this.contentWritten >= this.contentLength; |
||||
int bufferSize = getBufferSize(); |
||||
boolean requiresFlush = bufferSize > 0 && this.contentWritten >= bufferSize; |
||||
if (isBodyFullyWritten || requiresFlush) { |
||||
doOnResponseCommitted(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Calls <code>onResponseCommmitted()</code> with the current contents as long as |
||||
* {@link #disableOnResponseCommitted()} was not invoked. |
||||
*/ |
||||
private void doOnResponseCommitted() { |
||||
if (!this.disableOnCommitted) { |
||||
onResponseCommitted(); |
||||
disableOnResponseCommitted(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Ensures {@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked before |
||||
* calling the prior to methods that commit the response. We delegate all methods to |
||||
* the original {@link java.io.PrintWriter} to ensure that the behavior is as close to |
||||
* the original {@link java.io.PrintWriter} as possible. See SEC-2039 |
||||
* |
||||
* @author Rob Winch |
||||
*/ |
||||
private class SaveContextPrintWriter extends PrintWriter { |
||||
|
||||
private final PrintWriter delegate; |
||||
|
||||
SaveContextPrintWriter(PrintWriter delegate) { |
||||
super(delegate); |
||||
this.delegate = delegate; |
||||
} |
||||
|
||||
@Override |
||||
public void flush() { |
||||
doOnResponseCommitted(); |
||||
this.delegate.flush(); |
||||
} |
||||
|
||||
@Override |
||||
public void close() { |
||||
doOnResponseCommitted(); |
||||
this.delegate.close(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
return this.delegate.equals(obj); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return this.delegate.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return getClass().getName() + "[delegate=" + this.delegate.toString() + "]"; |
||||
} |
||||
|
||||
@Override |
||||
public boolean checkError() { |
||||
return this.delegate.checkError(); |
||||
} |
||||
|
||||
@Override |
||||
public void write(int c) { |
||||
trackContentLength(c); |
||||
this.delegate.write(c); |
||||
} |
||||
|
||||
@Override |
||||
public void write(char[] buf, int off, int len) { |
||||
checkContentLength(len); |
||||
this.delegate.write(buf, off, len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(char[] buf) { |
||||
trackContentLength(buf); |
||||
this.delegate.write(buf); |
||||
} |
||||
|
||||
@Override |
||||
public void write(String s, int off, int len) { |
||||
checkContentLength(len); |
||||
this.delegate.write(s, off, len); |
||||
} |
||||
|
||||
@Override |
||||
public void write(String s) { |
||||
trackContentLength(s); |
||||
this.delegate.write(s); |
||||
} |
||||
|
||||
@Override |
||||
public void print(boolean b) { |
||||
trackContentLength(b); |
||||
this.delegate.print(b); |
||||
} |
||||
|
||||
@Override |
||||
public void print(char c) { |
||||
trackContentLength(c); |
||||
this.delegate.print(c); |
||||
} |
||||
|
||||
@Override |
||||
public void print(int i) { |
||||
trackContentLength(i); |
||||
this.delegate.print(i); |
||||
} |
||||
|
||||
@Override |
||||
public void print(long l) { |
||||
trackContentLength(l); |
||||
this.delegate.print(l); |
||||
} |
||||
|
||||
@Override |
||||
public void print(float f) { |
||||
trackContentLength(f); |
||||
this.delegate.print(f); |
||||
} |
||||
|
||||
@Override |
||||
public void print(double d) { |
||||
trackContentLength(d); |
||||
this.delegate.print(d); |
||||
} |
||||
|
||||
@Override |
||||
public void print(char[] s) { |
||||
trackContentLength(s); |
||||
this.delegate.print(s); |
||||
} |
||||
|
||||
@Override |
||||
public void print(String s) { |
||||
trackContentLength(s); |
||||
this.delegate.print(s); |
||||
} |
||||
|
||||
@Override |
||||
public void print(Object obj) { |
||||
trackContentLength(obj); |
||||
this.delegate.print(obj); |
||||
} |
||||
|
||||
@Override |
||||
public void println() { |
||||
trackContentLengthLn(); |
||||
this.delegate.println(); |
||||
} |
||||
|
||||
@Override |
||||
public void println(boolean x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(char x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(int x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(long x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(float x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(double x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(char[] x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(String x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public void println(Object x) { |
||||
trackContentLength(x); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(x); |
||||
} |
||||
|
||||
@Override |
||||
public PrintWriter printf(String format, Object... args) { |
||||
return this.delegate.printf(format, args); |
||||
} |
||||
|
||||
@Override |
||||
public PrintWriter printf(Locale l, String format, Object... args) { |
||||
return this.delegate.printf(l, format, args); |
||||
} |
||||
|
||||
@Override |
||||
public PrintWriter format(String format, Object... args) { |
||||
return this.delegate.format(format, args); |
||||
} |
||||
|
||||
@Override |
||||
public PrintWriter format(Locale l, String format, Object... args) { |
||||
return this.delegate.format(l, format, args); |
||||
} |
||||
|
||||
@Override |
||||
public PrintWriter append(CharSequence csq) { |
||||
checkContentLength(csq.length()); |
||||
return this.delegate.append(csq); |
||||
} |
||||
|
||||
@Override |
||||
public PrintWriter append(CharSequence csq, int start, int end) { |
||||
checkContentLength(end - start); |
||||
return this.delegate.append(csq, start, end); |
||||
} |
||||
|
||||
@Override |
||||
public PrintWriter append(char c) { |
||||
trackContentLength(c); |
||||
return this.delegate.append(c); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* Ensures{@link OnCommittedResponseWrapper#onResponseCommitted()} is invoked before |
||||
* calling methods that commit the response. We delegate all methods to the original |
||||
* {@link jakarta.servlet.ServletOutputStream} to ensure that the behavior is as close |
||||
* to the original {@link jakarta.servlet.ServletOutputStream} as possible. See |
||||
* SEC-2039 |
||||
* |
||||
* @author Rob Winch |
||||
*/ |
||||
private class SaveContextServletOutputStream extends ServletOutputStream { |
||||
|
||||
private final ServletOutputStream delegate; |
||||
|
||||
SaveContextServletOutputStream(ServletOutputStream delegate) { |
||||
this.delegate = delegate; |
||||
} |
||||
|
||||
@Override |
||||
public void write(int b) throws IOException { |
||||
trackContentLength(b); |
||||
this.delegate.write(b); |
||||
} |
||||
|
||||
@Override |
||||
public void flush() throws IOException { |
||||
doOnResponseCommitted(); |
||||
this.delegate.flush(); |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
doOnResponseCommitted(); |
||||
this.delegate.close(); |
||||
} |
||||
|
||||
@Override |
||||
public void print(boolean b) throws IOException { |
||||
trackContentLength(b); |
||||
this.delegate.print(b); |
||||
} |
||||
|
||||
@Override |
||||
public void print(char c) throws IOException { |
||||
trackContentLength(c); |
||||
this.delegate.print(c); |
||||
} |
||||
|
||||
@Override |
||||
public void print(double d) throws IOException { |
||||
trackContentLength(d); |
||||
this.delegate.print(d); |
||||
} |
||||
|
||||
@Override |
||||
public void print(float f) throws IOException { |
||||
trackContentLength(f); |
||||
this.delegate.print(f); |
||||
} |
||||
|
||||
@Override |
||||
public void print(int i) throws IOException { |
||||
trackContentLength(i); |
||||
this.delegate.print(i); |
||||
} |
||||
|
||||
@Override |
||||
public void print(long l) throws IOException { |
||||
trackContentLength(l); |
||||
this.delegate.print(l); |
||||
} |
||||
|
||||
@Override |
||||
public void print(String s) throws IOException { |
||||
trackContentLength(s); |
||||
this.delegate.print(s); |
||||
} |
||||
|
||||
@Override |
||||
public void println() throws IOException { |
||||
trackContentLengthLn(); |
||||
this.delegate.println(); |
||||
} |
||||
|
||||
@Override |
||||
public void println(boolean b) throws IOException { |
||||
trackContentLength(b); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(b); |
||||
} |
||||
|
||||
@Override |
||||
public void println(char c) throws IOException { |
||||
trackContentLength(c); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(c); |
||||
} |
||||
|
||||
@Override |
||||
public void println(double d) throws IOException { |
||||
trackContentLength(d); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(d); |
||||
} |
||||
|
||||
@Override |
||||
public void println(float f) throws IOException { |
||||
trackContentLength(f); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(f); |
||||
} |
||||
|
||||
@Override |
||||
public void println(int i) throws IOException { |
||||
trackContentLength(i); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(i); |
||||
} |
||||
|
||||
@Override |
||||
public void println(long l) throws IOException { |
||||
trackContentLength(l); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(l); |
||||
} |
||||
|
||||
@Override |
||||
public void println(String s) throws IOException { |
||||
trackContentLength(s); |
||||
trackContentLengthLn(); |
||||
this.delegate.println(s); |
||||
} |
||||
|
||||
@Override |
||||
public void write(byte[] b) throws IOException { |
||||
trackContentLength(b); |
||||
this.delegate.write(b); |
||||
} |
||||
|
||||
@Override |
||||
public void write(byte[] b, int off, int len) throws IOException { |
||||
checkContentLength(len); |
||||
this.delegate.write(b, off, len); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isReady() { |
||||
return this.delegate.isReady(); |
||||
} |
||||
|
||||
@Override |
||||
public void setWriteListener(WriteListener writeListener) { |
||||
this.delegate.setWriteListener(writeListener); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
return this.delegate.equals(obj); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return this.delegate.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return getClass().getName() + "[delegate=" + this.delegate.toString() + "]"; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
Can't render this file because it is too large.
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
package de.superx.bianalysis.service; |
||||
|
||||
public class IllegalMetaDataOperation extends Exception { |
||||
|
||||
private static final long serialVersionUID = 1L; |
||||
|
||||
public IllegalMetaDataOperation(String message) { |
||||
super(message); |
||||
} |
||||
|
||||
} |
||||
@ -1,233 +1,225 @@
@@ -1,233 +1,225 @@
|
||||
package de.superx.bin; |
||||
|
||||
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.sql.Connection; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.sql.Statement; |
||||
import java.util.HashMap; |
||||
import java.util.Hashtable; |
||||
import java.util.Iterator; |
||||
import java.util.Properties; |
||||
|
||||
import org.apache.commons.io.FileUtils; |
||||
import org.apache.log4j.Level; |
||||
|
||||
import de.memtext.db.ConnectionCreator; |
||||
import de.memtext.util.DateUtils; |
||||
import de.memtext.util.GetOpts; |
||||
import de.memtext.util.GetOpts.Options; |
||||
import de.memtext.util.StringUtils; |
||||
import de.superx.common.FieldContainer; |
||||
import de.superx.common.Sichten; |
||||
import de.superx.common.StandaloneSicht; |
||||
import de.superx.common.SuperX_el; |
||||
import de.superx.common.SxResultRow; |
||||
import de.superx.common.SxResultSet; |
||||
import de.superx.common.SxSqlHelper; |
||||
import de.superx.common.SxUser; |
||||
import de.superx.common.TableFieldExists; |
||||
import de.superx.common.TemplateProcessor; |
||||
import de.superx.servlet.SxPools; |
||||
import de.superx.util.PropsReader; |
||||
import de.superx.util.SqlStringUtils; |
||||
|
||||
public class FMParser extends TemplateProcessor { |
||||
private String dbprop, infile, outfile; |
||||
|
||||
private Properties props; |
||||
|
||||
private Statement stm; |
||||
|
||||
private String isSimpleParser; |
||||
private String myParams=""; |
||||
private static String sqlDialect; |
||||
|
||||
public FMParser(String mandantenId, Connection con) throws SQLException { |
||||
super(mandantenId, con); |
||||
if (con.getMetaData().getDatabaseProductName().toLowerCase().contains("postgres")) { |
||||
sqlDialect = "Postgres"; |
||||
} |
||||
} |
||||
|
||||
public FMParser(String mandantenId) { |
||||
super(mandantenId); |
||||
} |
||||
|
||||
private void run() throws FileNotFoundException, IOException, Exception { |
||||
dbprop = GetOpts.getValue(Options.opt_dbprops); |
||||
props = PropsReader.prepareProps(new File(dbprop)); |
||||
infile = GetOpts.getValue(Options.opt_in); |
||||
outfile = GetOpts.getValue(Options.opt_out); |
||||
if (GetOpts.isPresent(Options.opt_simpPars)) |
||||
isSimpleParser = GetOpts.getValue(Options.opt_simpPars); |
||||
if (GetOpts.isPresent(Options.opt_params)) |
||||
myParams = GetOpts.getValue(Options.opt_params); |
||||
String input = StringUtils.readFile(new File(infile)); |
||||
if(myParams !="") |
||||
{ |
||||
String paramName = "<<" +myParams.substring(0, myParams.indexOf("="))+">>"; |
||||
String paramVal = "'"+myParams.substring(myParams.indexOf("=") + 1)+"'"; |
||||
input=de.memtext.util.StringUtils.replace(input, paramName, paramVal); |
||||
} |
||||
String output = ""; |
||||
if (isSimpleParser != null && isSimpleParser.equalsIgnoreCase("true")) { |
||||
output = simpleParser(dbprop, input); |
||||
} else { |
||||
SxPools.initTesting(props); |
||||
initConAndParser(dbprop); |
||||
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props.getProperty("driverName")); |
||||
HashMap map = new HashMap(); |
||||
map.put("TableFieldExists", new TableFieldExists(con)); |
||||
output = "--automatically created by SuperX/Freemarker for " + sqlDialect + " (" |
||||
+ DateUtils.getTodayString() + " " + DateUtils.getNowString() + ")\n" |
||||
+ process("FM-Parsing " + infile, input, map, sqlDialect); |
||||
stm.close(); |
||||
con.close(); |
||||
} |
||||
FileUtils.writeStringToFile(new File(outfile), output); |
||||
} |
||||
|
||||
private void initConAndParser(String dbprop) throws IOException, SQLException, ClassNotFoundException { |
||||
super.con = ConnectionCreator.getConnectionCryptPassword(dbprop, "driverName", "connectionURL", |
||||
"connectionName", "connectionPassword"); |
||||
stm = con.createStatement(); |
||||
if (SqlStringUtils.tableExists(con, "fm_templates", mandantenID)) { |
||||
setTemplates(readFromDb("select trim(both from id),content from fm_templates")); |
||||
repositoryToMap(readFromDb(REPOSITORY_SELECT), repositoryMap); |
||||
} |
||||
if (SqlStringUtils.tableExists(con, "konstanten", mandantenID)) { |
||||
SxResultSet rs = readFromDb("select trim(both from beschreibung),apnr from konstanten"); |
||||
for (Iterator it = rs.iterator(); it.hasNext();) { |
||||
SxResultRow row = (SxResultRow) it.next(); |
||||
String beschreibung = (String) row.get(0); |
||||
repositoryMap.put("K_" + beschreibung.trim(), row.get(1)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected SxResultSet readFromDb(String sql) throws SQLException { |
||||
SuperX_el el = new SuperX_el(); |
||||
SxSqlHelper sh = new SxSqlHelper(); |
||||
sh.execute(sql, this.con, el); |
||||
if (el.getError_String() != null && !el.getError_String().trim().equals("")) { |
||||
throw new SQLException("\nProblem bei:" + "\n\n Meldung:" + el.getError_String() + "\n sql:" + sql); |
||||
} |
||||
return el.getResultSet(); |
||||
} |
||||
|
||||
/** |
||||
* @deprecated |
||||
* @param sql |
||||
* @return |
||||
* @throws SQLException |
||||
*/ |
||||
@Deprecated |
||||
protected SxResultSet readFromDbAlt(String sql) throws SQLException { |
||||
SxResultSet result = new SxResultSet(); |
||||
ResultSet rs = stm.executeQuery(sql); |
||||
|
||||
result.setColumnNames(rs.getMetaData()); |
||||
int naturalOrder = 0; |
||||
while (rs.next()) { |
||||
SxResultRow row = new SxResultRow(rs.getMetaData().getColumnCount(), naturalOrder++); |
||||
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { |
||||
if (rs.getMetaData().getColumnType(i) == java.sql.Types.LONGVARCHAR) |
||||
row.add(rs.getString(i)); |
||||
else |
||||
row.add(rs.getObject(i)); |
||||
} |
||||
result.add(row); |
||||
} |
||||
rs.close(); |
||||
return result; |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
GetOpts.setOpts(args); |
||||
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[]{Options.opt_dbprops, Options.opt_in, Options.opt_out}); |
||||
if (isdrin != null) { |
||||
System.err.println("-dbproperties: -in: -out:"); |
||||
System.exit(1); |
||||
} |
||||
try { |
||||
new FMParser(DEFAULT_MANDANTEN_ID).run(); |
||||
} catch (Exception e) { |
||||
System.err.println("Fehler beim FM-Parsen "); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Einfacher Parser für Fremddatenbanken, nur sqlDialect wird übergeben wird von |
||||
* DOSQL direkt aufgerufen |
||||
*/ |
||||
public static String simpleParser(String dbprop, String input) |
||||
throws FileNotFoundException, IOException, Exception { |
||||
Properties props = PropsReader.prepareProps(new File(dbprop)); |
||||
FMParser myParser=new FMParser(DEFAULT_MANDANTEN_ID); |
||||
myParser.initConAndParser(dbprop); |
||||
String output = ""; |
||||
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props.getProperty("driverName")); |
||||
HashMap map = new HashMap(); |
||||
try { |
||||
output = "--automatically created by SuperX/Freemarker for " + sqlDialect + " (" |
||||
+ DateUtils.getTodayString() + " " + DateUtils.getNowString() + ")\n" |
||||
+ myParser.process("FM-Parsing ", input, map, sqlDialect); |
||||
} catch (Exception e) { |
||||
System.err.println("Fehler beim FM-Parsen "); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
return output; |
||||
} |
||||
|
||||
/** |
||||
* Methode war ursprünglich für direktes Einspielen einer einzelnen konkret mit |
||||
* name_intern benannten Sicht. Jetzt erweitert, dass aufgebaute Sicht auch |
||||
* zurückgeliefert wird, damit eine sichtsequence aufgebaut werden kann |
||||
*/ |
||||
@Override |
||||
protected StandaloneSicht addSqlVarSicht(HashMap hmap, String varname, String name_intern, String gewuenschterStand) |
||||
throws SQLException { |
||||
String sql = "select tid,name,label,'',beschreibung,quelle,standbutton,art \n" |
||||
+ " ,type,alt_hier_id,treecfgtable,treecfgid,gueltig_seit,gueltig_bis,xmlmaxentries,name_intern,attribut1,attribut2,attribut3,cacheapplet,cachexml \n" |
||||
+ "from sichten where name_intern='" |
||||
+ name_intern |
||||
+ "' and aktiv=1 order by type"; |
||||
SxResultSet roh = new SxResultSet(); |
||||
StandaloneSicht sicht = null; |
||||
roh = readFromDb(sql); |
||||
Sichten sichten = new Sichten(); |
||||
SxUser user = new SxUser(); |
||||
user.setAdmin(true); // Adminuser ok weil nur von DOSQL gebraucht
|
||||
sichten.setUser(user); |
||||
for (Iterator iter = roh.iterator(); iter.hasNext();) { |
||||
SxResultRow row = (SxResultRow) iter.next(); |
||||
Integer id = Integer.valueOf(1); |
||||
try { |
||||
sichten.initNonInternalSicht(DEFAULT_MANDANTEN_ID, StandaloneSicht.class, row, id); |
||||
sicht = (StandaloneSicht) sichten.getById(id); |
||||
sicht.setConnection(con); |
||||
sicht.setSqlDialect(sqlDialect); |
||||
if (gewuenschterStand.trim().startsWith("today")) { |
||||
gewuenschterStand = DateUtils.getTodayString(); |
||||
} |
||||
sicht.setStand(new Hashtable(), hmap, new FieldContainer(), gewuenschterStand); |
||||
hmap.put(varname, sicht); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
throw new SQLException("Fehler beim Aufbau von Sicht " + name_intern + " " + e); |
||||
} |
||||
} |
||||
return sicht; |
||||
} |
||||
} |
||||
|
||||
// Created on 08.12.2006 at 18:03:46
|
||||
package de.superx.bin; |
||||
|
||||
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.IOException; |
||||
import java.sql.Connection; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.sql.Statement; |
||||
import java.util.HashMap; |
||||
import java.util.Hashtable; |
||||
import java.util.Iterator; |
||||
import java.util.Properties; |
||||
|
||||
import org.apache.commons.io.FileUtils; |
||||
import org.apache.log4j.Level; |
||||
|
||||
import de.memtext.db.ConnectionCreator; |
||||
import de.memtext.util.DateUtils; |
||||
import de.memtext.util.GetOpts; |
||||
import de.memtext.util.GetOpts.Options; |
||||
import de.memtext.util.StringUtils; |
||||
import de.superx.common.FieldContainer; |
||||
import de.superx.common.Sichten; |
||||
import de.superx.common.StandaloneSicht; |
||||
import de.superx.common.SuperX_el; |
||||
import de.superx.common.SxResultRow; |
||||
import de.superx.common.SxResultSet; |
||||
import de.superx.common.SxSqlHelper; |
||||
import de.superx.common.SxUser; |
||||
import de.superx.common.TableFieldExists; |
||||
import de.superx.common.TemplateProcessor; |
||||
import de.superx.servlet.SxPools; |
||||
import de.superx.util.PropsReader; |
||||
import de.superx.util.SqlStringUtils; |
||||
|
||||
public class FMParser extends TemplateProcessor { |
||||
private String dbprop, infile, outfile; |
||||
|
||||
private Properties props; |
||||
|
||||
private Statement stm; |
||||
|
||||
private String isSimpleParser; |
||||
|
||||
private static String sqlDialect; |
||||
|
||||
public FMParser(String mandantenId, Connection con) throws SQLException { |
||||
super(mandantenId, con); |
||||
if (con.getMetaData().getDatabaseProductName().toLowerCase().contains("postgres")) { |
||||
sqlDialect = "Postgres"; |
||||
} |
||||
} |
||||
|
||||
public FMParser(String mandantenId) { |
||||
super(mandantenId); |
||||
} |
||||
|
||||
private void run() throws FileNotFoundException, IOException, Exception { |
||||
dbprop = GetOpts.getValue(Options.opt_dbprops); |
||||
props = PropsReader.prepareProps(new File(dbprop)); |
||||
infile = GetOpts.getValue(Options.opt_in); |
||||
outfile = GetOpts.getValue(Options.opt_out); |
||||
if (GetOpts.isPresent(Options.opt_simpPars)) |
||||
isSimpleParser = GetOpts.getValue(Options.opt_simpPars); |
||||
String input = StringUtils.readFile(new File(infile)); |
||||
String output = ""; |
||||
if (isSimpleParser != null && isSimpleParser.equalsIgnoreCase("true")) { |
||||
output = simpleParser(dbprop, input); |
||||
} else { |
||||
SxPools.initTesting(props); |
||||
initConAndParser(dbprop); |
||||
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props.getProperty("driverName")); |
||||
HashMap map = new HashMap(); |
||||
map.put("TableFieldExists", new TableFieldExists(con)); |
||||
output = "--automatically created by SuperX/Freemarker for " + sqlDialect + " (" |
||||
+ DateUtils.getTodayString() + " " + DateUtils.getNowString() + ")\n" |
||||
+ process("FM-Parsing " + infile, input, map, sqlDialect); |
||||
stm.close(); |
||||
con.close(); |
||||
} |
||||
FileUtils.writeStringToFile(new File(outfile), output); |
||||
} |
||||
|
||||
private void initConAndParser(String dbprop) throws IOException, SQLException, ClassNotFoundException { |
||||
super.con = ConnectionCreator.getConnectionCryptPassword(dbprop, "driverName", "connectionURL", |
||||
"connectionName", "connectionPassword"); |
||||
stm = con.createStatement(); |
||||
if (SqlStringUtils.tableExists(con, "fm_templates", mandantenID)) { |
||||
setTemplates(readFromDb("select trim(both from id),content from fm_templates")); |
||||
repositoryToMap(readFromDb(REPOSITORY_SELECT), repositoryMap); |
||||
} |
||||
if (SqlStringUtils.tableExists(con, "konstanten", mandantenID)) { |
||||
SxResultSet rs = readFromDb("select trim(both from beschreibung),apnr from konstanten"); |
||||
for (Iterator it = rs.iterator(); it.hasNext();) { |
||||
SxResultRow row = (SxResultRow) it.next(); |
||||
String beschreibung = (String) row.get(0); |
||||
repositoryMap.put("K_" + beschreibung.trim(), row.get(1)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected SxResultSet readFromDb(String sql) throws SQLException { |
||||
SuperX_el el = new SuperX_el(); |
||||
SxSqlHelper sh = new SxSqlHelper(); |
||||
sh.execute(sql, this.con, el); |
||||
if (el.getError_String() != null && !el.getError_String().trim().equals("")) { |
||||
throw new SQLException("\nProblem bei:" + "\n\n Meldung:" + el.getError_String() + "\n sql:" + sql); |
||||
} |
||||
return el.getResultSet(); |
||||
} |
||||
|
||||
/** |
||||
* @deprecated |
||||
* @param sql |
||||
* @return |
||||
* @throws SQLException |
||||
*/ |
||||
@Deprecated |
||||
protected SxResultSet readFromDbAlt(String sql) throws SQLException { |
||||
SxResultSet result = new SxResultSet(); |
||||
ResultSet rs = stm.executeQuery(sql); |
||||
|
||||
result.setColumnNames(rs.getMetaData()); |
||||
int naturalOrder = 0; |
||||
while (rs.next()) { |
||||
SxResultRow row = new SxResultRow(rs.getMetaData().getColumnCount(), naturalOrder++); |
||||
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { |
||||
if (rs.getMetaData().getColumnType(i) == java.sql.Types.LONGVARCHAR) |
||||
row.add(rs.getString(i)); |
||||
else |
||||
row.add(rs.getObject(i)); |
||||
} |
||||
result.add(row); |
||||
} |
||||
rs.close(); |
||||
return result; |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
GetOpts.setOpts(args); |
||||
String isdrin = GetOpts.isAllRequiredOptionsPresent(new Options[]{Options.opt_dbprops, Options.opt_in, Options.opt_out}); |
||||
if (isdrin != null) { |
||||
System.err.println("-dbproperties: -in: -out:"); |
||||
System.exit(1); |
||||
} |
||||
try { |
||||
new FMParser(DEFAULT_MANDANTEN_ID).run(); |
||||
} catch (Exception e) { |
||||
System.err.println("Fehler beim FM-Parsen "); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
} |
||||
|
||||
/* |
||||
* Einfacher Parser für Fremddatenbanken, nur sqlDialect wird übergeben wird von |
||||
* DOSQL direkt aufgerufen |
||||
*/ |
||||
public static String simpleParser(String dbprop, String input) |
||||
throws FileNotFoundException, IOException, Exception { |
||||
Properties props = PropsReader.prepareProps(new File(dbprop)); |
||||
FMParser myParser=new FMParser(DEFAULT_MANDANTEN_ID); |
||||
myParser.initConAndParser(dbprop); |
||||
String output = ""; |
||||
sqlDialect = de.superx.util.SqlStringUtils.getSqlDialect(props.getProperty("driverName")); |
||||
HashMap map = new HashMap(); |
||||
try { |
||||
output = "--automatically created by SuperX/Freemarker for " + sqlDialect + " (" |
||||
+ DateUtils.getTodayString() + " " + DateUtils.getNowString() + ")\n" |
||||
+ myParser.process("FM-Parsing ", input, map, sqlDialect); |
||||
} catch (Exception e) { |
||||
System.err.println("Fehler beim FM-Parsen "); |
||||
e.printStackTrace(); |
||||
System.exit(1); |
||||
} |
||||
return output; |
||||
} |
||||
|
||||
/** |
||||
* Methode war ursprünglich für direktes Einspielen einer einzelnen konkret mit |
||||
* name_intern benannten Sicht. Jetzt erweitert, dass aufgebaute Sicht auch |
||||
* zurückgeliefert wird, damit eine sichtsequence aufgebaut werden kann |
||||
*/ |
||||
@Override |
||||
protected StandaloneSicht addSqlVarSicht(HashMap hmap, String varname, String name_intern, String gewuenschterStand) |
||||
throws SQLException { |
||||
String sql = "select tid,name,label,'',beschreibung,quelle,standbutton,art \n" |
||||
+ " ,type,alt_hier_id,treecfgtable,treecfgid,gueltig_seit,gueltig_bis,xmlmaxentries,name_intern,attribut1,attribut2,attribut3,cacheapplet,cachexml \n" |
||||
+ "from sichten where name_intern='" |
||||
+ name_intern |
||||
+ "' and aktiv=1 order by type"; |
||||
SxResultSet roh = new SxResultSet(); |
||||
StandaloneSicht sicht = null; |
||||
roh = readFromDb(sql); |
||||
Sichten sichten = new Sichten(); |
||||
SxUser user = new SxUser(); |
||||
user.setAdmin(true); // Adminuser ok weil nur von DOSQL gebraucht
|
||||
sichten.setUser(user); |
||||
for (Iterator iter = roh.iterator(); iter.hasNext();) { |
||||
SxResultRow row = (SxResultRow) iter.next(); |
||||
Integer id = Integer.valueOf(1); |
||||
try { |
||||
sichten.initNonInternalSicht(DEFAULT_MANDANTEN_ID, StandaloneSicht.class, row, id); |
||||
sicht = (StandaloneSicht) sichten.getById(id); |
||||
sicht.setConnection(con); |
||||
sicht.setSqlDialect(sqlDialect); |
||||
if (gewuenschterStand.trim().startsWith("today")) { |
||||
gewuenschterStand = DateUtils.getTodayString(); |
||||
} |
||||
sicht.setStand(new Hashtable(), hmap, new FieldContainer(), gewuenschterStand); |
||||
hmap.put(varname, sicht); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
throw new SQLException("Fehler beim Aufbau von Sicht " + name_intern + " " + e); |
||||
} |
||||
} |
||||
return sicht; |
||||
} |
||||
} |
||||
|
||||
// Created on 08.12.2006 at 18:03:46
|
||||
|
||||
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
package de.superx.db.export; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileOutputStream; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.util.List; |
||||
|
||||
import org.jdom2.Document; |
||||
import org.jdom2.Element; |
||||
import org.jdom2.output.Format; |
||||
import org.jdom2.output.XMLOutputter; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* Writes an {@link ExportConfig} to XML, producing the same format |
||||
* that {@link ExportConfigReader} can parse. |
||||
* |
||||
* <p>Example output: |
||||
* <pre>{@code |
||||
* <export-config> |
||||
* <group name="my_group" schema="staging"> |
||||
* <filter column="tid" source="SELECT tid FROM organigramm"/> |
||||
* <table column="id" columns="id, name" orderBy="name ASC">my_table</table> |
||||
* </group> |
||||
* </export-config> |
||||
* }</pre> |
||||
*/ |
||||
@Component |
||||
public class ExportConfigWriter { |
||||
|
||||
/** |
||||
* Write the config to a file. |
||||
*/ |
||||
public void write(ExportConfig config, File outputFile) throws IOException { |
||||
try (FileOutputStream fos = new FileOutputStream(outputFile)) { |
||||
write(config, fos); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Write the config to an output stream. |
||||
*/ |
||||
public void write(ExportConfig config, OutputStream out) throws IOException { |
||||
Document doc = buildDocument(config); |
||||
XMLOutputter outputter = new XMLOutputter( |
||||
Format.getPrettyFormat().setEncoding("UTF-8")); |
||||
outputter.output(doc, out); |
||||
} |
||||
|
||||
/** |
||||
* Build the JDOM2 Document representing the config. |
||||
*/ |
||||
public Document buildDocument(ExportConfig config) { |
||||
Document doc = new Document(); |
||||
Element root = new Element("export-config"); |
||||
doc.setRootElement(root); |
||||
|
||||
for (ExportGroup group : config.getGroups()) { |
||||
root.addContent(buildGroupElement(group)); |
||||
} |
||||
|
||||
return doc; |
||||
} |
||||
|
||||
private Element buildGroupElement(ExportGroup group) { |
||||
Element groupEl = new Element("group"); |
||||
groupEl.setAttribute("name", group.getName()); |
||||
|
||||
if (group.getSchema() != null) { |
||||
groupEl.setAttribute("schema", group.getSchema()); |
||||
} |
||||
|
||||
if (group.hasFilter()) { |
||||
Element filterEl = new Element("filter"); |
||||
filterEl.setAttribute("column", group.getFilterColumn()); |
||||
filterEl.setAttribute("source", group.getFilterSource()); |
||||
groupEl.addContent(filterEl); |
||||
} |
||||
|
||||
for (ExportTableConfig tableConfig : group.getTableConfigs()) { |
||||
groupEl.addContent(buildTableElement(tableConfig)); |
||||
} |
||||
|
||||
return groupEl; |
||||
} |
||||
|
||||
private Element buildTableElement(ExportTableConfig tableConfig) { |
||||
Element tableEl = new Element("table"); |
||||
tableEl.setText(tableConfig.getTableName()); |
||||
|
||||
if (tableConfig.getFilterColumn() != null) { |
||||
tableEl.setAttribute("column", tableConfig.getFilterColumn()); |
||||
} |
||||
|
||||
if (tableConfig.hasFilterSource()) { |
||||
tableEl.setAttribute("source", tableConfig.getFilterSource()); |
||||
} |
||||
|
||||
if (tableConfig.hasColumns()) { |
||||
tableEl.setAttribute("columns", String.join(", ", tableConfig.getColumns())); |
||||
} |
||||
|
||||
if (tableConfig.hasOrderBy()) { |
||||
tableEl.setAttribute("orderBy", tableConfig.getOrderBy()); |
||||
} |
||||
|
||||
return tableEl; |
||||
} |
||||
} |
||||
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
package de.superx.dbt; |
||||
|
||||
public enum DbtAction { |
||||
BUILD, |
||||
TEST, |
||||
GENERATE_DOCS, |
||||
STAGING_TABLES, |
||||
SQLFLUFF_LINT, |
||||
NODE_COUNT_BUILD, |
||||
NODE_COUNT_TEST |
||||
} |
||||
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
package de.superx.dbt; |
||||
|
||||
public enum DbtExecutionState { |
||||
ACTIVE, // dbt-Lauf ist noch nicht beendet - evtl. braucht es mehr als nur "active"!?
|
||||
SUCCESS, // dbt-Lauf wurde erfolgreich abgeschlossen
|
||||
FAILURE, // dbt-Lauf endete in einem Fehler
|
||||
TIMEOUT |
||||
} |
||||
@ -1,59 +0,0 @@
@@ -1,59 +0,0 @@
|
||||
package de.superx.dbt; |
||||
|
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
|
||||
public class DbtMetrics { |
||||
|
||||
private static final String METRICS_LINE = "Found (\\d+) models, (\\d+) snapshots, (\\d+) data tests, (\\d+) seeds," |
||||
+ " (\\d+) sources, (\\d+) macros"; |
||||
private static final Pattern METRICS_PATTERN = Pattern.compile(METRICS_LINE); |
||||
|
||||
private int models; |
||||
private int snapshots; |
||||
private int tests; |
||||
private int seeds; |
||||
private int sources; |
||||
private int macros; |
||||
|
||||
public DbtMetrics(String metricLine) { |
||||
Matcher metricsMatcher = METRICS_PATTERN.matcher(metricLine); |
||||
if (metricsMatcher.find()) { |
||||
models = Integer.parseInt(metricsMatcher.group(1)); |
||||
snapshots = Integer.parseInt(metricsMatcher.group(2)); |
||||
tests = Integer.parseInt(metricsMatcher.group(3)); |
||||
seeds = Integer.parseInt(metricsMatcher.group(4)); |
||||
sources = Integer.parseInt(metricsMatcher.group(5)); |
||||
macros = Integer.parseInt(metricsMatcher.group(6)); |
||||
} |
||||
} |
||||
|
||||
public int getExecCount(boolean isTests) { |
||||
return isTests ? tests : models + snapshots + seeds; |
||||
} |
||||
|
||||
public int getModels() { |
||||
return models; |
||||
} |
||||
|
||||
public int getSnapshots() { |
||||
return snapshots; |
||||
} |
||||
|
||||
public int getTests() { |
||||
return tests; |
||||
} |
||||
|
||||
public int getSeeds() { |
||||
return seeds; |
||||
} |
||||
|
||||
public int getSources() { |
||||
return sources; |
||||
} |
||||
|
||||
public int getMacros() { |
||||
return macros; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
package de.superx.dbt; |
||||
|
||||
public class DbtPermissionException extends Exception { |
||||
DbtPermissionException(String message, Throwable cause) { |
||||
super(message, cause); |
||||
} |
||||
} |
||||
@ -0,0 +1,443 @@
@@ -0,0 +1,443 @@
|
||||
package de.superx.dbt; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.nio.file.Path; |
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Optional; |
||||
import java.util.concurrent.Callable; |
||||
import java.util.concurrent.CompletableFuture; |
||||
import java.util.stream.Collectors; |
||||
|
||||
import org.apache.commons.lang.SystemUtils; |
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode; |
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
||||
|
||||
public final class DbtRun implements Callable<DbtRunResult> { |
||||
|
||||
static Logger logger = LoggerFactory.getLogger(DbtRun.class); |
||||
private static final boolean isLinux = SystemUtils.IS_OS_LINUX; |
||||
|
||||
private final DbtRunRequest request; |
||||
private final Map<String, String> environment; |
||||
private final Path projectPath; |
||||
|
||||
public Process process; |
||||
|
||||
DbtRun(DbtRunRequest request, Map<String, String> environment, Path projectPath) { |
||||
this.request = request; |
||||
this.environment = environment; |
||||
this.projectPath = projectPath; |
||||
} |
||||
|
||||
@Override |
||||
public DbtRunResult call() throws Exception { |
||||
return execute(); |
||||
} |
||||
|
||||
private DbtRunResult execute() { |
||||
return switch (request.action()) { |
||||
case BUILD -> runDbtCommand(createBuildCommand()); |
||||
case TEST -> runDbtCommand(createTestCommand()); |
||||
case NODE_COUNT_BUILD -> nodeCount(true); |
||||
case NODE_COUNT_TEST -> nodeCount(false); |
||||
case GENERATE_DOCS -> generateDocs(); |
||||
case STAGING_TABLES -> findDbtStagingTablesForSelection(); |
||||
case SQLFLUFF_LINT -> lintDbtModelsUsingSQLFluff(); |
||||
}; |
||||
} |
||||
|
||||
private List<String> createTestCommand() { |
||||
List<String> baseCommand = new ArrayList<>(DbtUtils.getDbtCommandBase()); |
||||
baseCommand.addAll(Arrays.asList( "--log-format", "json", "--no-use-colors", "test")); |
||||
if(request.select() != null && !request.select().isBlank()) { |
||||
baseCommand.add("--select"); |
||||
baseCommand.add(request.select()); |
||||
} |
||||
return baseCommand; |
||||
} |
||||
|
||||
private List<String> createBuildCommand() { |
||||
List<String> baseCommand = new ArrayList<>(DbtUtils.getDbtCommandBase()); |
||||
baseCommand.addAll(Arrays.asList( |
||||
"--log-format", "json", |
||||
"--no-use-colors", |
||||
"build", |
||||
"--resource-types", |
||||
"snapshot", |
||||
"seed", |
||||
"model" |
||||
)); |
||||
|
||||
if(request.select() != null && !request.select().isBlank()) { |
||||
baseCommand.add("--select"); |
||||
baseCommand.add(request.select()); |
||||
} |
||||
return baseCommand; |
||||
} |
||||
|
||||
public DbtRunResult runDbtCommand(List<String> pbCommand) { |
||||
DbtRunResult result = new DbtRunResult(); |
||||
logger.info(Arrays.toString(pbCommand.toArray())); |
||||
ProcessBuilder p = new ProcessBuilder(pbCommand).directory(projectPath.toFile()); |
||||
p.environment().putAll(this.environment); |
||||
p.redirectErrorStream(false); |
||||
List<JsonNode> dbtLog = new ArrayList<>(); |
||||
JsonNode stats = null; |
||||
try { |
||||
int progress = 0; |
||||
|
||||
process = p.start(); |
||||
logger.info("ProcessBuilder start"); |
||||
logger.info("PYTHONUSERBASE: " + p.environment().get("PYTHONUSERBASE")); |
||||
logger.info("PATH: " + p.environment().get((isLinux) ? "PATH" : "Path")); |
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); |
||||
CompletableFuture<String> errFuture = readOutStream(process.getErrorStream()); |
||||
|
||||
var line = ""; |
||||
ObjectMapper objectMapper = new ObjectMapper(); |
||||
while ((line = reader.readLine()) != null) { |
||||
JsonNode node = objectMapper.readTree(line.getBytes()); |
||||
logger.info(node.get("info").get("msg").asText()); |
||||
JsonNode data = node.get("data"); |
||||
if (data.get("stats") != null) { |
||||
stats = node; |
||||
} else { |
||||
if (data.has("index")) { |
||||
progress = Math.max(progress, data.get("index").asInt()); |
||||
if(request.progressCallback() != null) { |
||||
request.progressCallback().accept(Integer.valueOf(progress)); |
||||
} |
||||
} |
||||
dbtLog.add(node); |
||||
} |
||||
} |
||||
|
||||
int exitCode = process.waitFor(); |
||||
String error = errFuture.join(); |
||||
|
||||
result.setErrorMessages(getErrorMessages(dbtLog, error)); |
||||
result.setState(getExecutionState(stats)); |
||||
result.setExitCode(Integer.valueOf(exitCode)); |
||||
} catch (Exception e) { |
||||
logger.error("Couldn't start dbt run!", e); |
||||
result.setErrorMessages(List.of(e.getMessage())); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public DbtRunResult generateDocs() { |
||||
DbtRunResult result = new DbtRunResult(); |
||||
try { |
||||
List<String> pbCommand = new ArrayList<>(DbtUtils.getDbtCommandBase()); |
||||
pbCommand.addAll(Arrays.asList("--no-use-colors", "docs", "generate")); |
||||
if(request.select() != null && !request.select().isBlank()) { |
||||
pbCommand.add("--select"); |
||||
pbCommand.add(request.select()); |
||||
} |
||||
ProcessBuilder pb = new ProcessBuilder(pbCommand).directory(projectPath.toFile()); |
||||
pb.environment().putAll(environment); |
||||
pb.redirectErrorStream(true); |
||||
Process p = pb.start(); |
||||
final InputStream stdoutInputStream = p.getInputStream(); |
||||
final BufferedReader stdoutReader = |
||||
new BufferedReader(new InputStreamReader(stdoutInputStream)); |
||||
String line = null; |
||||
while ((line = stdoutReader.readLine()) != null) { |
||||
logger.info(line); |
||||
} |
||||
result.setState(DbtExecutionState.SUCCESS); |
||||
} catch (Exception iox) { |
||||
String message = "Couldn't run dbt generate docs "; |
||||
logger.error(message, iox); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
result.setErrorMessages(List.of(message)); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public DbtRunResult nodeCount(boolean test) { |
||||
DbtRunResult result = new DbtRunResult(); |
||||
int lineNr = 0; |
||||
try { |
||||
List<String> pbCommand = new ArrayList<>(DbtUtils.getDbtCommandBase()); |
||||
pbCommand.addAll(Arrays.asList("ls", "--resource-types")); |
||||
if(test) { |
||||
pbCommand.add("test"); |
||||
} else { |
||||
pbCommand.addAll(Arrays.asList( |
||||
"snapshot", |
||||
"seed", |
||||
"model" |
||||
)); |
||||
} |
||||
if(request.select() != null && !request.select().isBlank()) { |
||||
pbCommand.add("--select"); |
||||
pbCommand.add(request.select()); |
||||
} |
||||
ProcessBuilder pb = new ProcessBuilder(pbCommand).directory(projectPath.toFile()); |
||||
pb.environment().putAll(environment); |
||||
pb.redirectErrorStream(true); |
||||
Process p = pb.start(); |
||||
final InputStream stdoutInputStream = p.getInputStream(); |
||||
final BufferedReader stdoutReader = |
||||
new BufferedReader(new InputStreamReader(stdoutInputStream)); |
||||
String line = ""; |
||||
while ((line = stdoutReader.readLine()) != null) { |
||||
if (!line.matches("(\\w+\\.)+\\w+$")) { |
||||
continue; |
||||
} |
||||
lineNr += 1; |
||||
logger.info(line); |
||||
} |
||||
result.setNodeCount(lineNr); |
||||
result.setState(DbtExecutionState.SUCCESS); |
||||
} catch (Exception iox) { |
||||
String message = "Couldn't run dbt ls "; |
||||
logger.error(message, iox); |
||||
result.setErrorMessages(List.of(message)); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private static CompletableFuture<String> readOutStream(InputStream is) { |
||||
return CompletableFuture.supplyAsync(() -> { |
||||
try ( |
||||
InputStreamReader isr = new InputStreamReader(is); |
||||
BufferedReader br = new BufferedReader(isr); |
||||
) { |
||||
StringBuilder res = new StringBuilder(); |
||||
String inputLine; |
||||
while ((inputLine = br.readLine()) != null) { |
||||
res.append(inputLine).append(System.lineSeparator()); |
||||
} |
||||
return res.toString(); |
||||
} catch (Throwable e) { |
||||
throw new RuntimeException("problem with executing program", e); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Finds staging tables for a dbt selection by running {@code dbt ls}. |
||||
* <p> |
||||
* Matches models from staging schemas such as {@code staging}, |
||||
* {@code staging_xyz}, or {@code staging_vmpostgres}, and returns only the |
||||
* table name without the schema prefix. |
||||
* |
||||
* @param selectOption the dbt selector to inspect |
||||
* @return |
||||
* @return staging table names without schema prefix |
||||
*/ |
||||
public DbtRunResult findDbtStagingTablesForSelection() { |
||||
DbtRunResult result = new DbtRunResult(); |
||||
logger.info("Finding dbt staging tables for selection: {}", request.select()); |
||||
try { |
||||
List<String> command = new ArrayList<>(DbtUtils.getDbtCommandBase()); |
||||
command.addAll(Arrays.asList( |
||||
"ls", |
||||
"--select", request.select(), |
||||
"--output", "name" |
||||
)); |
||||
|
||||
logger.info("Dbt transform Dir: {}", projectPath); |
||||
logger.info("Command: {}", String.join(" ", command)); |
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(command) |
||||
.directory(projectPath.toFile()); |
||||
|
||||
builder.environment().putAll(environment); |
||||
|
||||
this.process = builder.start(); |
||||
|
||||
CompletableFuture<String> errFuture = readOutStream(process.getErrorStream()); |
||||
|
||||
List<String> results; |
||||
try (BufferedReader reader = new BufferedReader( |
||||
new InputStreamReader(process.getInputStream()) |
||||
)) { |
||||
results = reader.lines().collect(Collectors.toList()); |
||||
} |
||||
|
||||
int exitCode = process.waitFor(); |
||||
String error = errFuture.join(); |
||||
|
||||
String output = String.join(System.lineSeparator(), results); |
||||
|
||||
if (exitCode != 0) { |
||||
String message = "dbt ls failed for selection '" + request.select() + "' with exit code " + exitCode |
||||
+ "\n\nstdout:\n" + output |
||||
+ "\n\nstderr:\n" + error; |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
result.setErrorMessages(List.of(message)); |
||||
return result; |
||||
} |
||||
|
||||
if (!error.isBlank()) { |
||||
logger.debug("dbt ls stderr for selection '{}': {}", request.select(), error); |
||||
} |
||||
|
||||
List<String> tables = new ArrayList<>(); |
||||
|
||||
for (String model : results) { |
||||
int dotIndex = model.indexOf("."); |
||||
if (dotIndex > 0 && model.substring(0, dotIndex).startsWith("staging")) { |
||||
tables.add(model.substring(dotIndex + 1)); |
||||
} |
||||
} |
||||
|
||||
logger.info( |
||||
"Found {} dbt staging table(s) for selection '{}': {}", |
||||
new Object[] { Integer.valueOf(tables.size()), request.select(), tables } |
||||
); |
||||
|
||||
result.setOutputMessages(tables); |
||||
result.setExitCode(Integer.valueOf(exitCode)); |
||||
if(!error.isBlank()) { |
||||
result.setErrorMessages(List.of(error)); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
} else { |
||||
result.setState(DbtExecutionState.SUCCESS); |
||||
} |
||||
} catch (InterruptedException e) { |
||||
Thread.currentThread().interrupt(); |
||||
String message = "Interrupted while running dbt ls for selection: " + request.select(); |
||||
logger.error(message, e); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
result.setErrorMessages(List.of(message)); |
||||
} catch (IOException e) { |
||||
String message = "Could not start dbt ls for selection: " + request.select(); |
||||
logger.error(message , e); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
result.setErrorMessages(List.of(message)); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public DbtRunResult lintDbtModelsUsingSQLFluff() { |
||||
DbtRunResult result = new DbtRunResult(); |
||||
List<String> command = new ArrayList<>(DbtUtils.getSqlFluffCommandBase()); |
||||
command.addAll(Arrays.asList( |
||||
"lint", |
||||
"--verbose", |
||||
"--nocolor", |
||||
"--disable-progress-bar" |
||||
)); |
||||
logger.info("sqlfluff command: " + command); |
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(command) |
||||
.directory(projectPath.toFile()); |
||||
|
||||
builder.environment().putAll(environment); |
||||
|
||||
try { |
||||
this.process = builder.start(); |
||||
|
||||
// read stdout
|
||||
List<String> lintingErrors = new ArrayList<String>(); |
||||
int progress = 0; |
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))){ |
||||
String line; |
||||
while((line = reader.readLine()) != null) { |
||||
logger.info(line); |
||||
if(line.contains(".sql")) { |
||||
if (line.contains("FAIL")) { |
||||
lintingErrors.add(line); |
||||
} |
||||
if(request.progressCallback() != null) { |
||||
request.progressCallback().accept(Integer.valueOf(progress++)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
List<String> errorsFromErrorStream = new ArrayList<String>(); |
||||
// read stderr
|
||||
try (InputStream es = process.getErrorStream(); |
||||
InputStreamReader esr = new InputStreamReader(es); |
||||
BufferedReader errReader = new BufferedReader(esr)) { |
||||
String line; |
||||
while ((line = errReader.readLine()) != null) { |
||||
logger.error(line); |
||||
errorsFromErrorStream.add(line); |
||||
} |
||||
} |
||||
|
||||
// SQLFluff exit codes: 0 = clean, 1 = linting issues found, 2 = execution failed.
|
||||
int exitCode = process.waitFor(); |
||||
result.setExitCode(Integer.valueOf(exitCode)); |
||||
|
||||
if(exitCode == 0) { |
||||
result.setState(DbtExecutionState.SUCCESS); |
||||
} else if(exitCode == 1) { |
||||
result.setErrorMessages(lintingErrors); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
} else { |
||||
result.setErrorMessages(errorsFromErrorStream); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
} |
||||
|
||||
return result; |
||||
} catch (Exception e) { |
||||
logger.error("Failed running sqlfluff.", e); |
||||
result.setErrorMessages(List.of(e.getMessage())); |
||||
result.setState(DbtExecutionState.FAILURE); |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
public DbtExecutionState getExecutionState(JsonNode stats) { |
||||
if (stats == null) { |
||||
return DbtExecutionState.ACTIVE; |
||||
} |
||||
if (stats.get("data").get("stats").get("error").asInt() == 0) { |
||||
return DbtExecutionState.SUCCESS; |
||||
} |
||||
return DbtExecutionState.FAILURE; |
||||
} |
||||
|
||||
private List<String> getErrorMessages(List<JsonNode> dbtLog, String errors) { |
||||
var result = new ArrayList<String>(); |
||||
if(errors == null) { |
||||
return result; |
||||
} |
||||
if (!errors.isEmpty()) { |
||||
// stderr was not empty!
|
||||
result.add(errors); |
||||
} else { |
||||
// "regular" errors during dbt execution
|
||||
for (var node : dbtLog) { |
||||
var level = findFirstOccurence("level", node); |
||||
if (level.isPresent() && "error".equals(level.get().asText())) { |
||||
var msg = findFirstOccurence("msg", node); |
||||
if (msg.isPresent()) { |
||||
result.add(msg.get().asText()); |
||||
} else { |
||||
logger.warn("No msg property found in dbt log " + node); |
||||
} |
||||
} else { |
||||
logger.warn("No level property found in dbt log " + node); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private static Optional<JsonNode> findFirstOccurence(String name, JsonNode searchNode) { |
||||
JsonNode parent = searchNode.findParent(name); |
||||
JsonNode result = parent != null ? parent.get(name) : null; |
||||
return Optional.of(result); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
package de.superx.dbt; |
||||
|
||||
import java.util.function.Consumer; |
||||
|
||||
public record DbtRunRequest( |
||||
DbtAction action, |
||||
String project, |
||||
String select, |
||||
long timeoutMillis, |
||||
Consumer<Integer> progressCallback |
||||
) { |
||||
|
||||
public DbtRunRequest(DbtAction action, String project, String select, long timeoutMillis) { |
||||
this(action, project, select, timeoutMillis, null); |
||||
} |
||||
|
||||
public DbtRunRequest(DbtAction action, String project, Consumer<Integer> progressCallback) { |
||||
this(action, project, null, 0, progressCallback); |
||||
} |
||||
|
||||
public DbtRunRequest(DbtAction action, String project, String select) { |
||||
this(action, project, select, 0, null); |
||||
} |
||||
} |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
package de.superx.dbt; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class DbtRunResult { |
||||
private Integer exitCode; |
||||
private DbtExecutionState state; |
||||
private List<String> outputMessages; |
||||
private List<String> errorMessages; |
||||
|
||||
private int nodeCount; // used for DbtAction.NODE_COUNT*
|
||||
// private List<String> stagingTables;// used for DbtAction.STAGING_TABLES
|
||||
|
||||
public Integer getExitCode() { |
||||
return exitCode; |
||||
} |
||||
|
||||
public void setExitCode(Integer exitCode) { |
||||
this.exitCode = exitCode; |
||||
} |
||||
|
||||
public DbtExecutionState getState() { |
||||
return state; |
||||
} |
||||
|
||||
public void setState(DbtExecutionState state) { |
||||
this.state = state; |
||||
} |
||||
|
||||
public List<String> getErrorMessages() { |
||||
return errorMessages; |
||||
} |
||||
|
||||
public void setErrorMessages(List<String> errorMessages) { |
||||
this.errorMessages = errorMessages; |
||||
} |
||||
|
||||
public int getNodeCount() { |
||||
return nodeCount; |
||||
} |
||||
|
||||
public void setNodeCount(int nodeCount) { |
||||
this.nodeCount = nodeCount; |
||||
} |
||||
|
||||
//public List<String> getStagingTables() {
|
||||
// return stagingTables;
|
||||
//}
|
||||
|
||||
//public void setStagingTables(List<String> stagingTables) {
|
||||
// this.stagingTables = stagingTables;
|
||||
//}
|
||||
|
||||
public List<String> getOutputMessages() { |
||||
return outputMessages; |
||||
} |
||||
|
||||
public void setOutputMessages(List<String> outputMessages) { |
||||
this.outputMessages = outputMessages; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
package de.superx.jdbc.entity; |
||||
|
||||
import org.springframework.data.annotation.Id; |
||||
import org.springframework.data.relational.core.mapping.Table; |
||||
|
||||
import de.superx.jdbc.model.DynamicFieldType; |
||||
import de.superx.jdbc.model.EntityDescriptor; |
||||
|
||||
@Table("cifx_customize") |
||||
public class CifxCustomize extends EntityBase { |
||||
|
||||
@Id |
||||
@DynamicFieldType(label = "ID", visibleInSimplifiedForm = false, readOnly = true) |
||||
public Integer tid; |
||||
|
||||
@DynamicFieldType(label = "CIFX Tabelle") |
||||
public String cifx_table; |
||||
|
||||
@DynamicFieldType(label = "Schlüsselgruppe (key)") |
||||
public Integer key; |
||||
|
||||
@EntityDescriptor |
||||
@DynamicFieldType(label = "Schlüssel (apnr)") |
||||
public String apnr; |
||||
|
||||
@DynamicFieldType(label = "Kurztext") |
||||
public String kurz; |
||||
|
||||
@DynamicFieldType(label = "Drucktext") |
||||
public String druck; |
||||
|
||||
@DynamicFieldType(label = "Langbesch. 1", visibleInSimplifiedForm = false) |
||||
public String lang_1; |
||||
|
||||
@DynamicFieldType(label = "Schlüssel (uniquename)") |
||||
public String uniquename; |
||||
|
||||
@DynamicFieldType(label = "struktur_c", visibleInSimplifiedForm = true) |
||||
public String struktur_c; |
||||
|
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
package de.superx.jdbc.repository; |
||||
|
||||
import org.springframework.data.repository.RepositoryDefinition; |
||||
|
||||
import de.superx.jdbc.entity.CifxCustomize; |
||||
|
||||
@RepositoryDefinition(domainClass = CifxCustomize.class, idClass = Integer.class) |
||||
public interface CifxCustomizeRepository extends BiaAdminCrudRepository<CifxCustomize> { |
||||
} |
||||
@ -1,446 +0,0 @@
@@ -1,446 +0,0 @@
|
||||
package de.superx.servlet; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.dbforms.config.DbFormsConfig; |
||||
import org.dbforms.config.DbFormsConfigRegistry; |
||||
import org.dbforms.config.MultipleValidationException; |
||||
import org.dbforms.config.Table; |
||||
|
||||
import org.dbforms.event.DatabaseEvent; |
||||
import org.dbforms.event.EventEngine; |
||||
import org.dbforms.event.WebEvent; |
||||
|
||||
import org.dbforms.util.MessageResources; |
||||
import org.dbforms.util.MultipartRequest; |
||||
import org.dbforms.util.ParseUtil; |
||||
import org.dbforms.util.SqlUtil; |
||||
import org.dbforms.util.Util; |
||||
|
||||
import org.dbforms.validation.ValidatorConstants; |
||||
|
||||
import de.superx.util.DbFormsMultipartRequest; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.PrintWriter; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
|
||||
import java.util.Enumeration; |
||||
import java.util.Hashtable; |
||||
import java.util.Locale; |
||||
import java.util.Vector; |
||||
|
||||
import jakarta.servlet.ServletException; |
||||
import jakarta.servlet.http.HttpServlet; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
import jakarta.servlet.http.HttpSession; |
||||
import static de.superx.servlet.SxSQL_Server.DEFAULT_MANDANTEN_ID; |
||||
|
||||
/** |
||||
* |
||||
* @author Witt |
||||
* This class inherits from the DbForms Controller: |
||||
* As CSRF protection broke the file upload, we need to adjust some classes...and this is the way we "inject" them to DbForms... |
||||
*/ |
||||
public class DbFormsController extends HttpServlet { |
||||
/** logging category for this class */ |
||||
private static Log logCat = LogFactory.getLog(DbFormsController.class.getName()); |
||||
|
||||
/** 100KB default upload size */ |
||||
private int maxUploadSize = 102400; |
||||
|
||||
/** |
||||
* Process an HTTP "GET" request. |
||||
* |
||||
* @param request The servlet request we are processing |
||||
* @param response The servlet response we are creating |
||||
* |
||||
* @exception IOException if an input/output error occurs |
||||
* @exception ServletException if a servlet exception occurs |
||||
*/ |
||||
@Override |
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { |
||||
process(request, response); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Process an HTTP "POST" request. |
||||
* |
||||
* @param request The servlet request we are processing |
||||
* @param response The servlet response we are creating |
||||
* |
||||
* @exception IOException if an input/output error occurs |
||||
* @exception ServletException if a servlet exception occurs |
||||
*/ |
||||
@Override |
||||
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { |
||||
process(request, response); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Initialize this servlet. |
||||
* |
||||
* @exception ServletException if the initialization fails |
||||
*/ |
||||
@Override |
||||
public void init() throws ServletException { |
||||
// if existing and valid, override default maxUploadSize, which determinates how
|
||||
// big the http/multipart uploads may get
|
||||
String maxUploadSizeStr = this.getServletConfig().getInitParameter("maxUploadSize"); |
||||
|
||||
if (maxUploadSizeStr != null) { |
||||
try { |
||||
this.maxUploadSize = Integer.parseInt(maxUploadSizeStr); |
||||
} catch (NumberFormatException nfe) { |
||||
logCat.error("maxUploadSize not a valid number => using default."); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Gets the connection object. Holds a list of all used connections. So they |
||||
* stay open between calls an can be reused |
||||
* |
||||
* @param request the request object |
||||
* @param tableId the table identifier |
||||
* @param connectionsTable the connections hash table |
||||
* |
||||
* @return The connection object |
||||
*/ |
||||
private Connection getConnection(DbFormsConfig config, HttpServletRequest request, int tableId, Hashtable connectionsTable) throws SQLException { |
||||
String connectionName = null; |
||||
Connection con = null; |
||||
|
||||
// get the connection name from the request;
|
||||
if (tableId != -1) { |
||||
connectionName = ParseUtil.getParameter(request, "invname_" + tableId); |
||||
} |
||||
|
||||
connectionName = Util.isNull(connectionName) ? DEFAULT_MANDANTEN_ID : connectionName; |
||||
|
||||
if ((con = (Connection) connectionsTable.get(connectionName)) == null) { |
||||
con = config.getConnection(connectionName); |
||||
connectionsTable.put(connectionName, con); |
||||
} |
||||
|
||||
return con; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* In our development, we sometimes set the connection object to autoCommit |
||||
* = false in the interceptor (Pre... methods). This allows us to have |
||||
* dbForms do part of the required transaction (other parts are done via |
||||
* jdbc calls). If the database throws an exception, then we need to make |
||||
* sure that the connection is reinitialized (rollbacked) before it is sent |
||||
* back into the connection pool. Grunikiewicz.philip&at;hydro.qc.ca |
||||
* 2001-10-29 |
||||
* |
||||
* @param con the connection object |
||||
*/ |
||||
private void cleanUpConnectionAfterException(Connection con) { |
||||
try { |
||||
// Do only if autoCommit is disabled
|
||||
if ((con != null) && (!con.getAutoCommit())) { |
||||
con.rollback(); |
||||
con.setAutoCommit(true); |
||||
} |
||||
} catch (java.sql.SQLException e) { |
||||
SqlUtil.logSqlException(e); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Close all the connections stored into the the connections HashTable. |
||||
* |
||||
* @param connectionsTable the connections HashTable |
||||
*/ |
||||
private void closeConnections(Hashtable connectionsTable) { |
||||
Enumeration cons = connectionsTable.keys(); |
||||
|
||||
while (cons.hasMoreElements()) { |
||||
String dbConnectionName = (String) cons.nextElement(); |
||||
Connection con = (Connection) connectionsTable.get(dbConnectionName); |
||||
|
||||
try { |
||||
// Do only if autoCommit is disabled
|
||||
if ((con != null) && (!con.getAutoCommit())) { |
||||
con.commit(); |
||||
con.setAutoCommit(true); |
||||
} |
||||
} catch (java.sql.SQLException e) { |
||||
SqlUtil.logSqlException(e); |
||||
} |
||||
|
||||
SqlUtil.closeConnection(con); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Process the incoming requests. |
||||
* |
||||
* @param request the request object |
||||
* @param response the response object |
||||
* |
||||
* @throws IOException |
||||
* @throws ServletException |
||||
*/ |
||||
private void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { |
||||
HttpSession session = request.getSession(true); |
||||
logCat.debug("session timeout: " + session.getMaxInactiveInterval()); |
||||
|
||||
// take Config-Object from application context - this object should have been
|
||||
// initalized by Config-Servlet on Webapp/server-startup!
|
||||
DbFormsConfig config = null; |
||||
|
||||
try { |
||||
config = DbFormsConfigRegistry.instance().lookup(); |
||||
} catch (Exception e) { |
||||
logCat.error(e); |
||||
throw new ServletException(e); |
||||
} |
||||
|
||||
// create RFC-1867 data wrapper for the case the form was sent in multipart mode
|
||||
// this is needed because common HttpServletRequestImpl - classes do not support it
|
||||
// the whole application has to access Request via the "ParseUtil" class
|
||||
// this is also true for jsp files written by the user
|
||||
// #fixme taglib needed for convenient access to ParseUtil wrapper methods
|
||||
Hashtable connections = new Hashtable(); |
||||
String contentType = request.getContentType(); |
||||
|
||||
// Verify if Locale have been setted in session with "LOCALE_KEY"
|
||||
// if not, take the request.getLocale() as default and put it in session
|
||||
// Verify if Locale have been setted in session with "LOCALE_KEY"
|
||||
// if not, take the request.getLocale() as default and put it in session
|
||||
processLocale(request); |
||||
|
||||
if ((contentType != null) && contentType.startsWith("multipart")) { |
||||
try { |
||||
MultipartRequest multipartRequest = new DbFormsMultipartRequest(request, maxUploadSize); |
||||
request.setAttribute("multipartRequest", multipartRequest); |
||||
} catch (IOException ioe) { |
||||
logCat.error("::process - check if uploaded file(s) exceeded allowed size", ioe); |
||||
sendErrorMessage("Check if uploaded file(s) exceeded allowed size.", response); |
||||
|
||||
return; |
||||
} |
||||
} |
||||
|
||||
Connection con = null; |
||||
WebEvent e = null; |
||||
Vector errors = new Vector(); |
||||
|
||||
try { |
||||
request.setAttribute("errors", errors); |
||||
|
||||
EventEngine engine = new EventEngine(request, config); |
||||
e = engine.generatePrimaryEvent(); |
||||
|
||||
// send as info to dbForms (=> Taglib)
|
||||
if (e != null) { |
||||
request.setAttribute("webEvent", e); |
||||
} |
||||
|
||||
try { |
||||
con = getConnection(config, request, ((e == null) || (e.getTable() == null)) ? (-1) : e.getTable().getId(), connections); |
||||
|
||||
// primary event can be any kind of event (database, navigation...)
|
||||
if (e instanceof DatabaseEvent) { |
||||
try { |
||||
// if hidden formValidatorName exist and it's an Update or Insert event,
|
||||
// doValidation with Commons-Validator
|
||||
String formValidatorName = request.getParameter(ValidatorConstants.FORM_VALIDATOR_NAME + "_" + e.getTable().getId()); |
||||
|
||||
if (formValidatorName != null) { |
||||
((DatabaseEvent) e).doValidation(formValidatorName, getServletContext()); |
||||
} |
||||
|
||||
((DatabaseEvent) e).processEvent(con); |
||||
} catch (SQLException sqle) { |
||||
logCat.error("::process - SQLException:", sqle); |
||||
errors.addElement(sqle); |
||||
cleanUpConnectionAfterException(con); |
||||
} catch (MultipleValidationException mve) { |
||||
processMultipleValidationException(con, errors, mve); |
||||
} |
||||
} |
||||
|
||||
//else
|
||||
//{
|
||||
// currently, we support db events ONLY
|
||||
// but in future there may be events with processEvent() method which do not need a jdbc con!
|
||||
// (you may think: "what about navigation events?" - well they are created by the
|
||||
// controller but they get executed in the referncing "DbFormTag" at the jsp -- that's why we
|
||||
// do not any further operations on them right here...we just put them into the request)
|
||||
//}
|
||||
// secondary Events are always database events
|
||||
// (in fact, they all are SQL UPDATEs)
|
||||
if (engine.getInvolvedTables() != null) { |
||||
processInvolvedTables(config, request, connections, e, errors, engine); |
||||
} |
||||
} catch (SQLException exc) { |
||||
throw new ServletException(exc); |
||||
} |
||||
} finally { |
||||
// close all the connections stored into the connections hash table;
|
||||
closeConnections(connections); |
||||
|
||||
if (e != null) { |
||||
// PG - if form contained errors, use followupOnError (if available!)
|
||||
String followUp = null; |
||||
|
||||
if (errors.size() != 0) { |
||||
followUp = e.getFollowUpOnError(); |
||||
} |
||||
|
||||
if (Util.isNull(followUp)) { |
||||
followUp = e.getFollowUp(); |
||||
} |
||||
|
||||
logCat.info("*** e = " + e + "*** e.getFollowUp() = " + e.getFollowUp()); |
||||
|
||||
if (!Util.isNull(followUp)) { |
||||
request.getRequestDispatcher(followUp).forward(request, response); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* PRIVATE METHODS here |
||||
* |
||||
* @param request DOCUMENT ME! |
||||
* @param connections DOCUMENT ME! |
||||
* @param e DOCUMENT ME! |
||||
* @param errors DOCUMENT ME! |
||||
* @param engine DOCUMENT ME! |
||||
*/ |
||||
/** |
||||
* Process tables related to the main event table. <br> |
||||
* For every table related to the parent one, generate secundary (update) |
||||
* events for that table and execute them. |
||||
* |
||||
* @param request the request object |
||||
* @param connections the connections hashTable |
||||
* @param e the main webEvent object |
||||
* @param errors the errors vector |
||||
* @param engine the eventEngine reference |
||||
*/ |
||||
private void processInvolvedTables(DbFormsConfig config, HttpServletRequest request, Hashtable connections, WebEvent e, Vector errors, EventEngine engine) throws SQLException { |
||||
Connection con; |
||||
|
||||
// may be null if empty form!
|
||||
Enumeration tableEnum = engine.getInvolvedTables().elements(); |
||||
|
||||
while (tableEnum.hasMoreElements()) { |
||||
Table t = (Table) tableEnum.nextElement(); |
||||
Enumeration eventEnum = engine.generateSecundaryEvents(t, e); |
||||
|
||||
// scan all the secundary events for the current secundary table;
|
||||
while (eventEnum.hasMoreElements()) { |
||||
DatabaseEvent dbE = (DatabaseEvent) eventEnum.nextElement(); |
||||
|
||||
// 2003-02-03 HKK: do not do the work twice - without this every event
|
||||
// would be generated for each table and event
|
||||
if (t.getId() == dbE.getTable().getId()) { |
||||
con = getConnection(config, request, dbE.getTable().getId(), connections); |
||||
|
||||
// 2003-02-03 HKK: do not do the work twice!!!
|
||||
String formValidatorName = request.getParameter(ValidatorConstants.FORM_VALIDATOR_NAME + "_" + dbE.getTable().getId()); |
||||
|
||||
try { |
||||
// if hidden formValidatorName exist and it's an Update or Insert event,
|
||||
// doValidation with Commons-Validator
|
||||
if (formValidatorName != null) { |
||||
dbE.doValidation(formValidatorName, getServletContext()); |
||||
} |
||||
|
||||
dbE.processEvent(con); |
||||
} catch (SQLException sqle2) { |
||||
SqlUtil.logSqlException(sqle2, "::process - exception while process secundary events"); |
||||
errors.addElement(sqle2); |
||||
cleanUpConnectionAfterException(con); |
||||
} catch (MultipleValidationException mve) { |
||||
processMultipleValidationException(con, errors, mve); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Set the default locale |
||||
* |
||||
* @param request the request object |
||||
*/ |
||||
private void processLocale(HttpServletRequest request) { |
||||
String lang = ParseUtil.getParameter(request, "lang"); |
||||
String country = ParseUtil.getParameter(request, "country", ""); |
||||
Locale locale = null; |
||||
|
||||
if (!Util.isNull(lang)) { |
||||
locale = new Locale(lang, country); |
||||
} else if (MessageResources.getLocale(request) == null) { |
||||
MessageResources.setLocale(request, request.getLocale()); |
||||
} |
||||
|
||||
if (locale != null) { |
||||
MessageResources.setLocale(request, locale); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Process the input MultipleValidationException object. |
||||
* |
||||
* @param con the connection object to close |
||||
* @param errors the errors vector to fill |
||||
* @param mve the MultipleValidationException to process |
||||
*/ |
||||
private void processMultipleValidationException(Connection con, Vector errors, MultipleValidationException mve) { |
||||
java.util.Vector v = null; |
||||
|
||||
logCat.error("::processMultipleValidationException - exception", mve); |
||||
|
||||
if ((v = mve.getMessages()) != null) { |
||||
Enumeration e = v.elements(); |
||||
|
||||
while (e.hasMoreElements()) { |
||||
errors.addElement(e.nextElement()); |
||||
} |
||||
} |
||||
|
||||
cleanUpConnectionAfterException(con); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Send error messages to the servlet's output stream |
||||
* |
||||
* @param message the message to display |
||||
* @param response the response object |
||||
*/ |
||||
private void sendErrorMessage(String message, HttpServletResponse response) { |
||||
try { |
||||
PrintWriter out = response.getWriter(); |
||||
|
||||
response.setContentType("text/html"); |
||||
out.println("<html><body><h1>ERROR:</h1><p>"); |
||||
out.println(message); |
||||
out.println("</p></body></html>"); |
||||
} catch (IOException ioe) { |
||||
logCat.error("::sendErrorMessage - senderror message crashed", ioe); |
||||
} |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,130 @@
@@ -0,0 +1,130 @@
|
||||
package de.superx.spring; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.IOException; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.security.NoSuchAlgorithmException; |
||||
import java.security.InvalidKeyException; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.List; |
||||
import java.util.Properties; |
||||
import org.apache.log4j.Logger; |
||||
import de.superx.util.PathAndFileUtils; |
||||
import java.util.regex.Matcher; |
||||
import java.util.regex.Pattern; |
||||
import java.util.stream.Collectors; |
||||
import javax.crypto.Cipher; |
||||
|
||||
import javax.crypto.BadPaddingException; |
||||
import javax.crypto.IllegalBlockSizeException; |
||||
import javax.crypto.NoSuchPaddingException; |
||||
import javax.crypto.spec.SecretKeySpec; |
||||
|
||||
import java.util.Set; |
||||
|
||||
public class CustomDatabases{ |
||||
|
||||
private static Logger logger = Logger.getLogger(CustomDatabases.class); |
||||
private static SecretKeySpec KEY; |
||||
private static Cipher desCipher; |
||||
|
||||
public static Map<String, Map<String,String>> getCustomConnections() throws |
||||
InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{ |
||||
Map<String,Map<String,String>> connections = new HashMap<>(); |
||||
//loop over all properties and map them to connections
|
||||
//automatically compute dbconnections from the name property
|
||||
Properties props = fetchProperties(); |
||||
List<String> dbconnections = getDBConnectionsFromNameProperty(props); |
||||
final Set<String> propertyNames = props.stringPropertyNames(); |
||||
for (String s : dbconnections) { |
||||
Map<String,String> properties = new HashMap<>(); |
||||
logger.info(String.format("%s connection retrieved from HISinOne", s)); |
||||
List<String> keys = propertyNames.stream().filter(it -> it.startsWith("db." + s + ".")).collect(Collectors.toList()); |
||||
for (String key : keys) { |
||||
String value = props.getProperty(key); |
||||
if (key.endsWith("password")) { |
||||
value = decryptDbPassword(value.trim()); |
||||
} |
||||
properties.put(key.substring(key.lastIndexOf('.') + 1), value); |
||||
} |
||||
connections.put(s, properties); |
||||
} |
||||
|
||||
return connections; |
||||
} |
||||
|
||||
private static List<String> getPropertyValuesByRegex(Properties properties, String regex) { |
||||
List<String> values = new ArrayList<>(); |
||||
Pattern pattern = Pattern.compile(regex); |
||||
|
||||
for (String key : properties.stringPropertyNames()) { |
||||
Matcher matcher = pattern.matcher(key); |
||||
if (matcher.matches()) { |
||||
values.add(properties.getProperty(key)); |
||||
} |
||||
} |
||||
return values; |
||||
} |
||||
|
||||
public static List<String> getDBConnectionsFromNameProperty(Properties props){ |
||||
ArrayList<String> connection_names = new ArrayList<String>(); |
||||
String regex = "db.*.name"; |
||||
connection_names = (ArrayList<String>) getPropertyValuesByRegex(props, regex); |
||||
|
||||
//check for duplicate names
|
||||
Set<String> seen = new HashSet<>(); |
||||
for (String db_name : connection_names) { |
||||
if(!seen.add(db_name)) { |
||||
logger.warn("Found atleast two databases with the name" + db_name); |
||||
} |
||||
} |
||||
|
||||
return connection_names; |
||||
} |
||||
|
||||
private static String decryptDbPassword(String password) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { |
||||
if(password == null || password.equals("")) { |
||||
return null; |
||||
}else if(!password.startsWith("sx_des")) { |
||||
return password; |
||||
} |
||||
|
||||
if(desCipher == null) { |
||||
desCipher = getDesCipher(); |
||||
} |
||||
|
||||
String[] stext = password.substring(7).split("#"); |
||||
byte[] bstext = new byte[stext.length]; |
||||
for(int i = 0; i<stext.length;i++) { |
||||
bstext[i] = Byte.parseByte(stext[i]); |
||||
} |
||||
desCipher.init(Cipher.DECRYPT_MODE, KEY); |
||||
byte[] decrypted = desCipher.doFinal(bstext); |
||||
return new String(decrypted, StandardCharsets.UTF_8); |
||||
} |
||||
|
||||
public static void copy_encryption_key(SecretKeySpec key){ |
||||
KEY = key; |
||||
} |
||||
|
||||
private static Cipher getDesCipher() throws NoSuchAlgorithmException, NoSuchPaddingException { |
||||
return Cipher.getInstance("DES"); |
||||
} |
||||
|
||||
private static Properties fetchProperties(){ |
||||
Properties props = new Properties(); |
||||
String FileName = "extra_connections.properties"; |
||||
File extra_connections_file_path = new File(PathAndFileUtils.getWebinfPath() + File.separator + "conf" + File.separator + FileName); |
||||
try (FileInputStream s = new FileInputStream(extra_connections_file_path)){ |
||||
props.load(s); |
||||
} catch (IOException e1) { |
||||
logger.info("Unable to access properties file where extra connections as described: " + e1.getMessage()); |
||||
} |
||||
|
||||
return props; |
||||
} |
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
package de.superx.spring.service; |
||||
|
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.ApplicationContextAware; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
/** |
||||
* Holds the Spring ApplicationContext in a static field. |
||||
* Implemented as a Spring bean so Spring itself injects the context. |
||||
*/ |
||||
@Component |
||||
public class ApplicationContextHolder implements ApplicationContextAware { |
||||
|
||||
private static volatile ApplicationContext context; |
||||
|
||||
@Override |
||||
public void setApplicationContext(ApplicationContext ctx) { |
||||
context = ctx; // called once during startup
|
||||
} |
||||
|
||||
public static <T> T getBean(String beanName, Class<T> requiredType) { |
||||
if (getContext() != null) { |
||||
if (beanName != null && !beanName.isEmpty()) { |
||||
return getContext().getBean(beanName, requiredType); |
||||
} |
||||
return getContext().getBean(requiredType); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public static Object getBean(String name) { |
||||
return getContext().getBean(name); |
||||
} |
||||
|
||||
public static <T> T getBean(Class<T> requiredType) { |
||||
return getContext().getBean(requiredType); |
||||
} |
||||
|
||||
/** Public static accessor */ |
||||
public static ApplicationContext getContext() { |
||||
return context; |
||||
} |
||||
|
||||
/** Optional: clear the reference when the webapp stops (helps GC) */ |
||||
public static void clear() { |
||||
context = null; |
||||
} |
||||
} |
||||
@ -1,375 +0,0 @@
@@ -1,375 +0,0 @@
|
||||
/* |
||||
* $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/util/MultipartRequest.java,v 1.19 2005/02/19 21:26:32 hkollmann Exp $ |
||||
* $Revision: 1.19 $ |
||||
* $Date: 2005/02/19 21:26:32 $ |
||||
* |
||||
* DbForms - a Rapid Application Development Framework |
||||
* Copyright (C) 2001 Joachim Peer <joepeer@excite.com> |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2.1 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
*/ |
||||
|
||||
package de.superx.util; |
||||
|
||||
import org.apache.commons.fileupload.DiskFileUpload; |
||||
import org.apache.commons.fileupload.FileItem; |
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
import java.util.Enumeration; |
||||
import java.util.Hashtable; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import java.util.Vector; |
||||
|
||||
import jakarta.servlet.ServletRequest; |
||||
import jakarta.servlet.ServletRequestWrapper; |
||||
import jakarta.servlet.http.HttpServletRequest; |
||||
|
||||
import org.dbforms.util.FileHolder; |
||||
import org.dbforms.util.MultipartRequest; |
||||
import org.dbforms.util.Util; |
||||
import org.dbforms.util.external.FileUtil; |
||||
|
||||
import de.superx.util.multipart.support.DefaultMultipartHttpServletRequest; |
||||
|
||||
|
||||
/** |
||||
* A utility class to handle <code>multipart/form-data</code> requests, the |
||||
* kind of requests that support file uploads. This class emulates the interface
|
||||
* of <code>HttpServletRequest</code>, making it familiar to use. It uses a |
||||
* "push" model where any incoming files are read and saved directly to disk in |
||||
* the constructor. If you wish to have more flexibility, e.g. write the files |
||||
* to a database, use the "pull" model <code>MultipartParser</code> instead. |
||||
* <p> |
||||
* This class can receive arbitrarily large files (up to an artificial limit you |
||||
* can set), and fairly efficiently too. It cannot handle nested data (multipart |
||||
* content within multipart content) or internationalized content (such as non |
||||
* Latin-1 filenames). |
||||
* </p> |
||||
* <p> |
||||
* See the included <a href="upload.war">upload.war </a> for an example of how |
||||
* to use this class. |
||||
* <p> |
||||
* The full file upload specification is contained in experimental RFC 1867, |
||||
* available at <a href="http://www.ietf.org/rfc/rfc1867.txt" |
||||
* http://www.ietf.org/rfc/rfc1867.txt </a>.
|
||||
* </p> |
||||
* <p> |
||||
* PLEASE NOTE: this class uses Multipart Support Classes by Jason Hunter. |
||||
* Copyright (C) 1998 by Jason Hunter. All rights reserved. |
||||
* Use of this class is limited. Please see the LICENSE for more information. |
||||
* Make sure that you project meets the requierements defined by Jason Hunter |
||||
* respective O'reilly! |
||||
* </p> |
||||
* |
||||
* @see MultipartParser |
||||
* |
||||
* @author Jason Hunter |
||||
* @author Geoff Soutter |
||||
* @author Joe Peer - _changed_ it for use in DbForms (i apologize) |
||||
*/ |
||||
public class DbFormsMultipartRequest extends MultipartRequest { |
||||
private static Log logCat = LogFactory.getLog(DbFormsMultipartRequest.class); // logging category
|
||||
|
||||
private Hashtable files = new Hashtable(); // name - UploadedFile
|
||||
|
||||
// for this class
|
||||
//private File dir;
|
||||
private Hashtable parameters = new Hashtable(); // name - Vector of values
|
||||
|
||||
/** |
||||
* Constructs a new MultipartRequest to handle the specified request, |
||||
* {saving any uploaded files to the given directory}, and limiting the |
||||
* upload size to the specified length. If the content is too large, an |
||||
* IOException is thrown. This constructor actually parses the |
||||
* <tt>multipart/form-data</tt> and throws an IOException if there's any |
||||
* problem reading or parsing the request. |
||||
* |
||||
* @param request |
||||
* the servlet request. |
||||
* @param maxPostSize |
||||
* the maximum size of the POST content. |
||||
* @exception IOException |
||||
* if the uploaded content is larger than |
||||
* <tt>maxPostSize</tt> or there's a problem reading or |
||||
* parsing the request. |
||||
*/ |
||||
public DbFormsMultipartRequest(HttpServletRequest request, int maxPostSize) throws IOException { |
||||
super(request, maxPostSize); |
||||
// Sanity check values
|
||||
if (request == null) { |
||||
throw new IllegalArgumentException("request cannot be null"); |
||||
} |
||||
|
||||
// Create a new file upload handler
|
||||
DiskFileUpload upload = new DiskFileUpload(); |
||||
|
||||
// Set upload parameters
|
||||
upload.setSizeMax(maxPostSize); |
||||
|
||||
String tmpDir = System.getProperty("java.io.tmpdir"); |
||||
upload.setRepositoryPath(tmpDir); |
||||
|
||||
// Parse the request
|
||||
try { |
||||
|
||||
// we initilize this list with 'null', as the following unwrapping code should do the work - contrary to the 'org.dbforms.util.MultipartRequest code, from which this is copied
|
||||
List<FileItem> items = null; //upload.parseRequest(request);
|
||||
|
||||
if (items == null || items.size() == 0) { |
||||
ServletRequest originalRequest = request; |
||||
DefaultMultipartHttpServletRequest dmhsr = null; |
||||
while (originalRequest instanceof ServletRequestWrapper) { |
||||
if (originalRequest instanceof DefaultMultipartHttpServletRequest) { |
||||
dmhsr = (DefaultMultipartHttpServletRequest) originalRequest; |
||||
items = dmhsr.getFileItems(); |
||||
break; |
||||
} |
||||
originalRequest = ((ServletRequestWrapper) originalRequest).getRequest(); |
||||
} |
||||
} |
||||
|
||||
Iterator iter = items.iterator(); |
||||
|
||||
while (iter.hasNext()) { |
||||
FileItem item = (FileItem) iter.next(); |
||||
String name = item.getFieldName(); |
||||
|
||||
if (item.isFormField()) { |
||||
String value = item.getString(); |
||||
|
||||
// plain parameters get allways into parameters structure
|
||||
Vector existingValues = (Vector) parameters.get(name); |
||||
|
||||
if (existingValues == null) { |
||||
existingValues = new Vector(); |
||||
parameters.put(name, existingValues); |
||||
} |
||||
|
||||
existingValues.addElement(value); |
||||
} else { |
||||
String fileName = item.getName(); |
||||
|
||||
if (!Util.isNull(fileName)) { |
||||
File f = new File(fileName); |
||||
// 2004-08-05-HKK/Dziugas Baltrunas:
|
||||
// FileItem always returns the full pathname!
|
||||
fileName = FileUtil.filename(f.getName()); |
||||
|
||||
// The part actually contained a file
|
||||
// #changes by joe peer:
|
||||
// we must delay storing the file-inputstream (into
|
||||
// database, filesystem or whatever)
|
||||
// until we know exactly what should happen with it
|
||||
FileHolder fileHolder = new FileHolder(fileName, item); |
||||
files.put(name, fileHolder); |
||||
logCat.info("buffered and now added as " + name + " the following fileHolder:" + fileHolder.getFileName()); |
||||
|
||||
// #changes by joe peer:
|
||||
// if a file parameter is not null it gets into the
|
||||
// parameters structures as well
|
||||
// this is important to provide a simple access to
|
||||
// request (no distinction between files and plain
|
||||
// params)
|
||||
Vector existingValues = (Vector) parameters.get(name); |
||||
|
||||
if (existingValues == null) { |
||||
existingValues = new Vector(); |
||||
parameters.put(name, existingValues); |
||||
} |
||||
|
||||
existingValues.addElement(fileName); |
||||
} |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
logCat.error("MultipartRequest", e); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the content type of the specified file (as supplied by the client |
||||
* browser), or null if the file was not included in the upload. |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return the content type of the file. |
||||
*/ |
||||
@Override |
||||
public String getContentType(String name) { |
||||
try { |
||||
//#changed by joe peer
|
||||
//UploadedFile file = (UploadedFile)files.get(name);
|
||||
FileHolder filePart = (FileHolder) files.get(name); |
||||
|
||||
return filePart.getContentType(); // may be null
|
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns a FilePart object for the specified file this method was added by |
||||
* joe peer |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return a FilePart object for the named file. |
||||
*/ |
||||
@Override |
||||
public FileHolder getFileHolder(String name) { |
||||
try { |
||||
return (FileHolder) files.get(name); |
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns a InputStream object for the specified file saved on the server's |
||||
* filesystem, or null if the file was not included in the upload. |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return a InputStream object for the named file. |
||||
*/ |
||||
@Override |
||||
public InputStream getFileInputStream(String name) { |
||||
try { |
||||
//#changed by joe peer
|
||||
//UploadedFile file = (UploadedFile)files.get(name);
|
||||
FileHolder filePart = (FileHolder) files.get(name); |
||||
|
||||
return filePart.getInputStreamFromBuffer(); // may be null
|
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the names of all the uploaded files as an Enumeration of Strings. |
||||
* It returns an empty Enumeration if there are no uploaded files. Each file |
||||
* name is the name specified by the form, not by the user. |
||||
* |
||||
* @return the names of all the uploaded files as an Enumeration of Strings. |
||||
*/ |
||||
@Override |
||||
public Enumeration getFileNames() { |
||||
return files.keys(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the filesystem name of the specified file, or null if the file |
||||
* was not included in the upload. A filesystem name is the name specified |
||||
* by the user. It is also the name under which the file is actually saved. |
||||
* |
||||
* @param name |
||||
* the file name. |
||||
* @return the filesystem name of the file. |
||||
*/ |
||||
@Override |
||||
public String getFilesystemName(String name) { |
||||
try { |
||||
//#changed by joe peer
|
||||
//UploadedFile file = (UploadedFile)files.get(name);
|
||||
FileHolder filePart = (FileHolder) files.get(name); |
||||
|
||||
return filePart.getFileName(); // may be null
|
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the value of the named parameter as a String, or null if the |
||||
* parameter was not sent or was sent without a value. The value is |
||||
* guaranteed to be in its normal, decoded form. If the parameter has |
||||
* multiple values, only the last one is returned (for backward |
||||
* compatibility). For parameters with multiple values, it's possible the |
||||
* last "value" may be null. |
||||
* |
||||
* @param name |
||||
* the parameter name. |
||||
* @return the parameter value. |
||||
*/ |
||||
@Override |
||||
public String getParameter(String name) { |
||||
try { |
||||
Vector values = (Vector) parameters.get(name); |
||||
|
||||
if ((values == null) || (values.size() == 0)) { |
||||
return null; |
||||
} |
||||
|
||||
String value = (String) values.elementAt(0); |
||||
|
||||
return value; |
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the names of all the parameters as an Enumeration of Strings. It |
||||
* returns an empty Enumeration if there are no parameters. |
||||
* |
||||
* @return the names of all the parameters as an Enumeration of Strings. |
||||
*/ |
||||
@Override |
||||
public Enumeration getParameterNames() { |
||||
return parameters.keys(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the values of the named parameter as a String array, or null if |
||||
* the parameter was not sent. The array has one entry for each parameter |
||||
* field sent. If any field was sent without a value that entry is stored in |
||||
* the array as a null. The values are guaranteed to be in their normal, |
||||
* decoded form. A single value is returned as a one-element array. |
||||
* |
||||
* @param name |
||||
* the parameter name. |
||||
* @return the parameter values. |
||||
*/ |
||||
@Override |
||||
public String[] getParameterValues(String name) { |
||||
try { |
||||
Vector values = (Vector) parameters.get(name); |
||||
|
||||
if ((values == null) || (values.size() == 0)) { |
||||
return null; |
||||
} |
||||
|
||||
String[] valuesArray = new String[values.size()]; |
||||
values.copyInto(valuesArray); |
||||
|
||||
return valuesArray; |
||||
} catch (Exception e) { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
package de.superx.util; |
||||
|
||||
import javax.sql.DataSource; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
||||
public final class DbUtils { |
||||
|
||||
private DbUtils() { } |
||||
|
||||
public static boolean isModuleInstalled(DataSource dataSource, String moduleAbbreviation) { |
||||
String sql = "SELECT COUNT(*) FROM db_version WHERE his_system = ?"; |
||||
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); |
||||
Integer count = jdbcTemplate.queryForObject(sql, Integer.class, moduleAbbreviation); |
||||
|
||||
return count != null && count.intValue() > 0; |
||||
} |
||||
} |
||||
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!--Automatisch generiert von Edustore durch mondrian_schema_3.xsl 01.07.2023 10:52:04--> |
||||
<Schema name="HISinOne"> |
||||
</Schema> |
||||
@ -1,24 +0,0 @@
@@ -1,24 +0,0 @@
|
||||
clean |
||||
cleanBuildPath |
||||
cleanTestDirs |
||||
compile |
||||
compile-testclasses |
||||
compileJasperFiles |
||||
compileSuperx |
||||
create_all_modules |
||||
create_test_db_eduetl |
||||
cvs_checkout_eduetl_dbconv_sch |
||||
delete_test_db_eduetl |
||||
distApplet |
||||
distApplet2 |
||||
distServer |
||||
dist_his1 |
||||
his_icons_for_saiku |
||||
initTestDirs |
||||
initTimestamp |
||||
module_checksum |
||||
standalone |
||||
test |
||||
testcase |
||||
war |
||||
war_his1 |
||||
@ -1,3 +0,0 @@
@@ -1,3 +0,0 @@
|
||||
Application-Name: SuperX |
||||
Main-Class: de.superx.applet.SuperX |
||||
Permissions: all-permissions |
||||
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
de/memtext/**/*.* |
||||
de/superx/applet/*.class |
||||
de/superx/common/*.class |
||||
*.properties |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue