Importing WformServices and GlemmServices

Change-Id: Ifa95576d69e0d3863f63d3fdedb48c2c21cf64bc
diff --git a/Utils/.classpath b/Utils/.classpath
new file mode 100644
index 0000000..1ff5a38
--- /dev/null
+++ b/Utils/.classpath
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="org.eclipse.jst.component.nondependency" value=""/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v9.0">
+		<attributes>
+			<attribute name="owner.project.facets" value="jst.utility"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.8.0_231">
+		<attributes>
+			<attribute name="owner.project.facets" value="java"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/Utils/.project b/Utils/.project
new file mode 100644
index 0000000..2a33a7e
--- /dev/null
+++ b/Utils/.project
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Utils</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>
diff --git a/Utils/.settings/org.eclipse.jdt.core.prefs b/Utils/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..4e4a3ad
--- /dev/null
+++ b/Utils/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,9 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/Utils/.settings/org.eclipse.m2e.core.prefs b/Utils/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/Utils/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/Utils/.settings/org.eclipse.wst.common.component b/Utils/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..6bd211b
--- /dev/null
+++ b/Utils/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="Utils">
+        <wb-resource deploy-path="/" source-path="/src"/>
+    </wb-module>
+</project-modules>
diff --git a/Utils/.settings/org.eclipse.wst.common.project.facet.core.xml b/Utils/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..3eca3e1
--- /dev/null
+++ b/Utils/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <runtime name="Apache Tomcat v9.0"/>
+  <installed facet="java" version="1.8"/>
+  <installed facet="jst.utility" version="1.0"/>
+</faceted-project>
diff --git a/Utils/.settings/org.eclipse.wst.validation.prefs b/Utils/.settings/org.eclipse.wst.validation.prefs
new file mode 100644
index 0000000..04cad8c
--- /dev/null
+++ b/Utils/.settings/org.eclipse.wst.validation.prefs
@@ -0,0 +1,2 @@
+disabled=06target
+eclipse.preferences.version=1
diff --git a/Utils/pom.xml b/Utils/pom.xml
new file mode 100644
index 0000000..0fd46d3
--- /dev/null
+++ b/Utils/pom.xml
@@ -0,0 +1,31 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>de.korap.services</groupId>
+  <artifactId>utils</artifactId>
+  <version>0.1-SNAPSHOT</version>
+  <packaging>jar</packaging>
+  <name>utils</name>
+  <description>Utilitys for the KorAp Services.</description>
+  <build>
+    <sourceDirectory>src</sourceDirectory>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.7.0</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <dependencies>
+    <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.6</version>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/Utils/src/de/korap/services/utils/Utils.java b/Utils/src/de/korap/services/utils/Utils.java
new file mode 100644
index 0000000..9585864
--- /dev/null
+++ b/Utils/src/de/korap/services/utils/Utils.java
@@ -0,0 +1,276 @@
+package de.korap.services.utils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Locale;
+
+import java.util.Properties;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.apache.commons.io.FileUtils;
+
+
+public final class Utils
+{
+	
+	/*
+	 * set Err and Out Streams.
+	 * 
+	 * 12.12.19/FB
+	 * The PrintWriter class should be used in situations that require writing characters rather than bytes.
+	 * 05.10.21/FB
+	 */
+	
+	public static void setStdFileStreams(String fnameErr, String fnameOut)
+	
+	{
+	FileOutputStream
+		fosOut, fosErr;
+
+	try { // open in append mode:
+		fosErr = new FileOutputStream(fnameErr, true);
+		System.setErr(new PrintStream(fosErr));
+		fosOut = new FileOutputStream(fnameOut, true);
+		System.setOut(new PrintStream(fosOut));
+		} 
+	catch (FileNotFoundException e) {
+		e.printStackTrace();
+		}
+	
+	} // setStdFileStreams
+	
+	/*
+	 * setLogStream:
+	 * 
+	 * - open a PrintStream for fname.
+	 * 
+	 * 25.10.21/FB
+	 */
+	
+	public static PrintStream setLogStream(String fname)
+	
+	{
+	PrintStream
+		f = null;
+	
+	try {
+		f = new PrintStream(new FileOutputStream(fname, true));
+		} 
+	catch (FileNotFoundException e) {
+		e.printStackTrace();
+		f = System.out;
+		f.printf("Error: setLogStream: cannot create PrintStream for '%s'!\n", fname);
+		}
+	
+	return f;
+	} // setLogStream
+
+	/*
+	 * executeShellScript.
+	 * 12.12.19/FB
+	 */
+	public static int executeShellScript(String fnameScript, String arg, final PrintStream fout, final PrintStream ferr)
+	
+	{
+	final String 
+		func = "executeShellScript";
+	ProcessBuilder 	
+		builder;
+    Process 
+    	process = null;
+    int 
+    	status;
+    
+    fout.printf("Debug: %s: script name = '%s'...\n", func, fnameScript);
+	fout.printf("Debug: %s: script arg  = '%s'...\n", func, arg);
+		
+	if (!new File(fnameScript).canExecute()) {
+        System.err.printf("GlemmUtils.executeShellScript: cannot find shell script '%s'!\n", fnameScript);
+        return 1;
+	}
+	
+	builder = new ProcessBuilder(fnameScript, arg);
+    process = null;
+    
+    try {
+        process = builder.start();
+        status = process.waitFor();
+        
+        fout.println("Debug: script executed successfully.\n");
+
+        //InputStream is = process.getInputStream();
+        //InputStreamReader isr = new InputStreamReader(is);
+        //BufferedReader br = new BufferedReader(isr);
+        //String line;
+        //while ((line = br.readLine()) != null) {
+        //    System.out.println(line);
+        //}
+    	}
+    catch (IOException e) {
+    	ferr.printf("Error: executeShellScript: '%s' failed due to IOException!\n", fnameScript); 
+    	e.printStackTrace();
+    	return 1;
+    }
+    catch (InterruptedException e) {
+    	ferr.printf("Error: executeShellScript: '%s' failed due to Interrupt!\n", fnameScript); 
+    	e.printStackTrace();
+    	return 1;
+    }
+        
+	// OK
+	return 0;
+		
+	}
+
+	/*
+	 * readFromInputStream:
+	 * 
+	 * - reads full content of a file into a string and return that string.
+	 * - only apply on small files.
+	 * 
+	 * 27.04.20/FB
+	 */
+	
+	public static String readFromInputStream(String filename)
+			  throws IOException 
+	
+	{
+    byte[]
+    	encoded;
+    
+    encoded = Files.readAllBytes(Paths.get(filename));
+    return new String(encoded);
+    
+	/* alternative:  
+    try (BufferedReader br = new BufferedReader(new InputStreamReader(ins))) 
+    	{
+        String line;
+        while ((line = br.readLine()) != null) 
+        	{
+            resultStringBuilder.append(line).append("\n");
+        	}
+    	}
+    return resultStringBuilder.toString();
+    */
+	
+	} // readFromInputStream
+
+	/*
+	 * writeToOutputStream:
+	 * - writes a String to file.
+	 * 27.04.10/FB
+	 */
+	
+	public static void writeToOutputStream(String filename, String s, final PrintStream fout)
+	
+	{
+	final String func = "writeToOutputStream";
+	File
+		file = new File(filename);
+	
+	try {
+		FileUtils.writeStringToFile(file, s, (String)null, false);
+		} 
+	catch (IOException e) {
+		fout.printf("Error: %s: cannot write to file '%s'!\n", func, filename);
+		e.printStackTrace();
+		}
+	
+	} // writeToOutputStream
+	
+	/*
+	 * loadProperties
+	 * 
+	 * - load properties using InputStream is.
+	 * - InputStream must be opened by calling Services using their Servlet Context.
+	 * - name used to open InputStream is fnameProps (used here only for logging).
+	 * - realPath only available if fnamesProps was found (used here only for logging).
+	 * - bPrint: if true: log properties found.
+	 * Returns:
+	 * - set of loaded properties. May the null if fnameProps were not found.
+	 * 15.10.21/FB
+	 * Notes:
+	 * - as long as the properties are loading, we don't know where to redirect
+	 *   System.out/err, so we have to write to System.out/err.
+	 * 27.10.21/FB
+	 */
+	
+	public static Properties loadProperties(InputStream is, String fnameProps, String realPath, boolean bPrint)
+	
+	{
+	final String
+		func = "Utils.loadProperties";
+	Properties
+		props = new Properties();
+	
+	/* does not find the properties file:
+	 * inProp = GlemmServices.class.getClassLoader().getResourceAsStream(propName);
+	 * inProp = HttpServletRequest.class.getResourceAsStream(propName);
+	 */
+	
+	if( is == null )
+		{
+		System.err.printf("Error: %s: cannot load '%s' (realPath='%s')!\n", func, fnameProps, realPath);
+		return props; // return empty list of props.
+		}
+	
+	try {
+		props.load(is);
+		Set<Entry<Object,Object>>
+			propsSet = props.entrySet();
+		
+		for(Entry<Object, Object> propEntry : propsSet)
+			{
+			if( bPrint )
+				System.out.printf("Debug: %s: prop %s = '%s'.\n", func, propEntry.getKey(), propEntry.getValue());
+			}
+		} 
+	catch (IOException e) {
+		System.err.printf("Error: %s: cannot load props from '%s'!",  func, fnameProps);
+		e.printStackTrace();
+		}
+
+	return props;	
+	} // loadProperties
+	
+	/*
+	 * getConstantFromProperties
+	 * 
+	 * if key prop is found in props, return val found.
+	 * else return default value propDefault.
+	 * 
+	 * 15.10.21/FB
+	 * Notes:
+	 * - if loging is reactivated here, do not use System.out/err as they are set JVM-wide.
+	 */
+	
+	public static String getConstantFromProperties(Properties props, String prop, String propDefault)
+	
+	{
+	final String
+		func = "init_ConstantFromProperties";
+	String
+		val = (String)props.getProperty(prop);
+	
+	if( val != null )
+		{
+		//System.out.printf("Debug: %s: %s = '%s' (from properties).\n",  func, prop, val);
+		return val;
+		}	
+	else
+		{
+		//System.err.printf("Error: %s: set constant %s = '%s' (from default)!\n", func, prop, propDefault);
+		return propDefault;
+		}
+	
+	} // init_ConstantFromProperties
+	
+
+}
\ No newline at end of file