Introducing Java Servlet Container beta.
This commit is contained in:
@@ -29,6 +29,10 @@ case "$nxt_module" in
|
||||
. auto/modules/nodejs
|
||||
;;
|
||||
|
||||
java)
|
||||
. auto/modules/java
|
||||
;;
|
||||
|
||||
*)
|
||||
echo
|
||||
echo $0: error: invalid module \"$nxt_module\".
|
||||
|
||||
458
auto/modules/java
Normal file
458
auto/modules/java
Normal file
@@ -0,0 +1,458 @@
|
||||
|
||||
# Copyright (C) NGINX, Inc.
|
||||
|
||||
|
||||
shift
|
||||
|
||||
NXT_JAVA_HOME=${JAVA_HOME-}
|
||||
NXT_JAR_REPO=http://central.maven.org/maven2/
|
||||
NXT_JAR_LOCAL_REPO=$HOME/.m2/repository/
|
||||
|
||||
for nxt_option; do
|
||||
|
||||
case "$nxt_option" in
|
||||
-*=*) value=`echo "$nxt_option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
|
||||
*) value="" ;;
|
||||
esac
|
||||
|
||||
case "$nxt_option" in
|
||||
|
||||
--module=*) NXT_JAVA_MODULE="$value" ;;
|
||||
--home=*) NXT_JAVA_HOME="$value" ;;
|
||||
--lib-path=*) NXT_JAVA_LIB_PATH="$value" ;;
|
||||
--repo=*) NXT_JAR_REPO="$value" ;;
|
||||
--local-repo=*) NXT_JAR_LOCAL_REPO="$value" ;;
|
||||
--jars=*) NXT_JARS="$value" ;;
|
||||
|
||||
--help)
|
||||
cat << END
|
||||
|
||||
--module=NAME set unit Java module name
|
||||
--home=DIR set Java home directory
|
||||
--lib-path=DIRECTORY set directory path to libjvm.so library
|
||||
--repo=URL set Maven remote repository URL
|
||||
default: "$NXT_JAR_REPO"
|
||||
--local-repo=DIR set local repository directory
|
||||
default: "$NXT_JAR_LOCAL_REPO"
|
||||
--jars=DIR set jars install/search directory
|
||||
|
||||
END
|
||||
exit 0
|
||||
;;
|
||||
|
||||
*)
|
||||
echo
|
||||
echo $0: error: invalid Java option \"$nxt_option\"
|
||||
echo
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
|
||||
if [ ! -f $NXT_AUTOCONF_DATA ]; then
|
||||
echo
|
||||
echo Please run common $0 before configuring module \"$nxt_module\".
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
. $NXT_AUTOCONF_DATA
|
||||
|
||||
|
||||
NXT_JARS=${NXT_JARS=$NXT_MODULES}
|
||||
NXT_JAVA_MODULE=${NXT_JAVA_MODULE=java}
|
||||
NXT_JAVA_LIB_PATH=${NXT_JAVA_LIB_PATH=}
|
||||
|
||||
$echo "configuring Java module"
|
||||
$echo "configuring Java module ..." >> $NXT_AUTOCONF_ERR
|
||||
|
||||
if [ -n "${NXT_JAVA_HOME}" ]; then
|
||||
$echo "using java.home ${NXT_JAVA_HOME}"
|
||||
$echo "using java.home ${NXT_JAVA_HOME}" >> $NXT_AUTOCONF_ERR
|
||||
|
||||
if [ ! -d "${NXT_JAVA_HOME}" ]; then
|
||||
$echo
|
||||
$echo $0: error: Java home directory not found.
|
||||
$echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NXT_JAVA="${NXT_JAVA_HOME}/bin/java"
|
||||
|
||||
else
|
||||
$echo -n "checking for java executable"
|
||||
$echo "checking for java executable ..." >> $NXT_AUTOCONF_ERR
|
||||
|
||||
NXT_JAVA=`which java || :`
|
||||
if [ -z "$NXT_JAVA" -o ! -x "$NXT_JAVA" ]; then
|
||||
$echo
|
||||
$echo $0: error: java executable not found.
|
||||
$echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$echo " found $NXT_JAVA"
|
||||
$echo "found $NXT_JAVA" >> $NXT_AUTOCONF_ERR
|
||||
|
||||
"$NXT_JAVA" -version
|
||||
|
||||
$echo -n "checking java.home"
|
||||
$echo "checking java.home ..." >> $NXT_AUTOCONF_ERR
|
||||
|
||||
NXT_JAVA_HOME=`$NXT_JAVA -XshowSettings 2>&1 | grep -F -e java.home | sed -e 's/^.*= //'`
|
||||
if [ -z "$NXT_JAVA_HOME" ]; then
|
||||
$echo
|
||||
$echo $0: error: java.home not found.
|
||||
$echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$echo " $NXT_JAVA_HOME"
|
||||
$echo "got java.home $NXT_JAVA_HOME" >> $NXT_AUTOCONF_ERR
|
||||
|
||||
if [ ! -x "${NXT_JAVA_HOME}/bin/javac" ]; then
|
||||
NXT_JAVA_HOME_=${NXT_JAVA_HOME%/jre}
|
||||
if [ -x "${NXT_JAVA_HOME_}/bin/javac" ]; then
|
||||
$echo "adjust java.home $NXT_JAVA_HOME_"
|
||||
$echo "adjust java.home $NXT_JAVA_HOME_" >> $NXT_AUTOCONF_ERR
|
||||
|
||||
NXT_JAVA_HOME="$NXT_JAVA_HOME_"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
NXT_JAVAC="${NXT_JAVA_HOME}/bin/javac"
|
||||
|
||||
if [ ! -x "$NXT_JAVAC" ]; then
|
||||
$echo
|
||||
$echo $0: error: javac not found.
|
||||
$echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NXT_JAVA_INCLUDE="-I${NXT_JAVA_HOME}/include"
|
||||
|
||||
case "$NXT_SYSTEM" in
|
||||
Linux)
|
||||
NXT_JAVA_INCLUDE="${NXT_JAVA_INCLUDE} -I${NXT_JAVA_HOME}/include/linux"
|
||||
;;
|
||||
Darwin)
|
||||
NXT_JAVA_INCLUDE="${NXT_JAVA_INCLUDE} -I${NXT_JAVA_HOME}/include/darwin"
|
||||
;;
|
||||
FreeBSD)
|
||||
NXT_JAVA_INCLUDE="${NXT_JAVA_INCLUDE} -I${NXT_JAVA_HOME}/include/freebsd"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$NXT_JAVA_LIB_PATH" ]; then
|
||||
$echo -n "checking library path"
|
||||
$echo "checking library path ..." >> $NXT_AUTOCONF_ERR
|
||||
|
||||
if [ ! -x "$NXT_JAVA" ]; then
|
||||
$echo
|
||||
$echo $0: error: java executable not found.
|
||||
$echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NXT_JAVA_LIB_PATH=`$NXT_JAVA -XshowSettings 2>&1 | grep -F -e sun.boot.library.path | sed -e 's/^.*= //'`
|
||||
|
||||
if [ -z "$NXT_JAVA_LIB_PATH" ]; then
|
||||
$echo
|
||||
$echo $0: error: library path not found.
|
||||
$echo
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NXT_JAVA_LIB_PATH="${NXT_JAVA_LIB_PATH}/server"
|
||||
|
||||
$echo " $NXT_JAVA_LIB_PATH"
|
||||
$echo "got library path $NXT_JAVA_LIB_PATH" >> $NXT_AUTOCONF_ERR
|
||||
fi
|
||||
|
||||
NXT_JAVA_LDFLAGS="-L${NXT_JAVA_LIB_PATH} -Wl,-rpath ${NXT_JAVA_LIB_PATH} -ljvm"
|
||||
|
||||
|
||||
nxt_found=no
|
||||
|
||||
nxt_feature="JNI"
|
||||
nxt_feature_name=""
|
||||
nxt_feature_run=no
|
||||
nxt_feature_incs="${NXT_JAVA_INCLUDE}"
|
||||
nxt_feature_libs="${NXT_JAVA_LDFLAGS}"
|
||||
nxt_feature_test="
|
||||
#include <jni.h>
|
||||
|
||||
int main() {
|
||||
JNI_CreateJavaVM(NULL, NULL, NULL);
|
||||
return 0;
|
||||
}"
|
||||
|
||||
. auto/feature
|
||||
|
||||
|
||||
if [ $nxt_found = no ]; then
|
||||
$echo
|
||||
$echo $0: error: no JNI found.
|
||||
$echo
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
NXT_JAVA_VERSION=`$NXT_JAVAC -version 2>&1`
|
||||
NXT_JAVA_VERSION=${NXT_JAVA_VERSION#javac }
|
||||
NXT_JAVA_INCLUDE="$NXT_JAVA_INCLUDE -I$NXT_BUILD_DIR/$NXT_JAVA_MODULE -DNXT_JAVA_VERSION=$NXT_JAVA_VERSION"
|
||||
|
||||
if grep ^$NXT_JAVA_MODULE: $NXT_MAKEFILE 2>&1 > /dev/null; then
|
||||
$echo
|
||||
$echo $0: error: duplicate \"$NXT_JAVA_MODULE\" module configured.
|
||||
$echo
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
. ./version
|
||||
|
||||
NXT_UNIT_JAR=nginx-unit-jsc-${NXT_JAVA_MODULE}-$NXT_VERSION.jar
|
||||
|
||||
NXT_JAVA_BUILD_CP=$NXT_BUILD_DIR/$NXT_JAVA_MODULE
|
||||
NXT_JAVA_INSTALL_JARS=
|
||||
NXT_JAVA_UNINSTALL_JARS=
|
||||
|
||||
NXT_JAVA_JARS=$NXT_BUILD_DIR/$NXT_JAVA_MODULE/nxt_jars.h
|
||||
mkdir -p $NXT_BUILD_DIR/$NXT_JAVA_MODULE
|
||||
|
||||
cat << END > $NXT_JAVA_JARS
|
||||
#ifndef _NXT_JAVA_JARS_INCLUDED_
|
||||
#define _NXT_JAVA_JARS_INCLUDED_
|
||||
|
||||
#define NXT_JARS "$NXT_JARS"
|
||||
|
||||
static const char *nxt_java_system_jars[] = {
|
||||
END
|
||||
|
||||
NXT_TOMCAT_VERSION=9.0.13
|
||||
|
||||
NXT_JAR_VERSION=$NXT_TOMCAT_VERSION
|
||||
|
||||
NXT_JAR_NAME=tomcat-servlet-api
|
||||
NXT_JAR_NAMESPACE=org/apache/tomcat/
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-el-api
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-jsp-api
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-jasper
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-jasper-el
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-juli
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-api
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-util-scan
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=tomcat-util
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=ecj
|
||||
NXT_JAR_VERSION=3.13.102
|
||||
NXT_JAR_NAMESPACE=org/eclipse/jdt/
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
cat << END >> $NXT_JAVA_JARS
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *nxt_java_unit_jars[] = {
|
||||
"$NXT_UNIT_JAR",
|
||||
END
|
||||
|
||||
NXT_JAR_VERSION=9.4.12.v20180830
|
||||
NXT_JAR_NAMESPACE=org/eclipse/jetty/
|
||||
|
||||
NXT_JAR_NAME=jetty-util
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=jetty-server
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=jetty-http
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
NXT_JAR_NAME=classgraph
|
||||
NXT_JAR_VERSION=4.4.11
|
||||
NXT_JAR_NAMESPACE=io/github/classgraph/
|
||||
. auto/modules/java_get_jar
|
||||
|
||||
cat << END >> $NXT_JAVA_JARS
|
||||
NULL
|
||||
};
|
||||
|
||||
#endif /* _NXT_JAVA_JARS_INCLUDED_ */
|
||||
END
|
||||
|
||||
$echo " + Java module: ${NXT_JAVA_MODULE}.unit.so"
|
||||
|
||||
. auto/cc/deps
|
||||
|
||||
$echo >> $NXT_MAKEFILE
|
||||
|
||||
NXT_JAVA_MODULE_SRCS=" \
|
||||
src/nxt_java.c \
|
||||
src/java/nxt_jni.c \
|
||||
src/java/nxt_jni_Context.c \
|
||||
src/java/nxt_jni_HeaderNamesEnumeration.c \
|
||||
src/java/nxt_jni_HeadersEnumeration.c \
|
||||
src/java/nxt_jni_InputStream.c \
|
||||
src/java/nxt_jni_OutputStream.c \
|
||||
src/java/nxt_jni_Request.c \
|
||||
src/java/nxt_jni_Response.c \
|
||||
src/java/nxt_jni_Thread.c \
|
||||
src/java/nxt_jni_URLClassLoader.c \
|
||||
"
|
||||
|
||||
# The Java module object files.
|
||||
|
||||
nxt_objs=$NXT_BUILD_DIR/src/nxt_unit.o
|
||||
|
||||
for nxt_src in $NXT_JAVA_MODULE_SRCS; do
|
||||
|
||||
nxt_obj=${nxt_src%.c}-$NXT_JAVA_MODULE.o
|
||||
nxt_dep=${nxt_src%.c}-$NXT_JAVA_MODULE.dep
|
||||
nxt_dep_flags=`nxt_gen_dep_flags`
|
||||
nxt_dep_post=`nxt_gen_dep_post`
|
||||
nxt_objs="$nxt_objs $NXT_BUILD_DIR/$nxt_obj"
|
||||
|
||||
cat << END >> $NXT_MAKEFILE
|
||||
|
||||
$NXT_BUILD_DIR/$nxt_obj: $nxt_src
|
||||
mkdir -p $NXT_BUILD_DIR/src/java
|
||||
\$(CC) -c \$(CFLAGS) \$(NXT_INCS) $NXT_JAVA_INCLUDE \\
|
||||
$nxt_dep_flags \\
|
||||
-o $NXT_BUILD_DIR/$nxt_obj $nxt_src
|
||||
$nxt_dep_post
|
||||
|
||||
-include $NXT_BUILD_DIR/$nxt_dep
|
||||
|
||||
END
|
||||
|
||||
done
|
||||
|
||||
NXT_JAVA_SRCS=" \
|
||||
src/java/nginx/unit/Context.java \
|
||||
src/java/nginx/unit/DynamicDispatcherRequest.java \
|
||||
src/java/nginx/unit/DynamicPathRequest.java \
|
||||
src/java/nginx/unit/ForwardRequestWrapper.java \
|
||||
src/java/nginx/unit/HeaderNamesEnumeration.java \
|
||||
src/java/nginx/unit/HeadersEnumeration.java \
|
||||
src/java/nginx/unit/IncludeRequestWrapper.java \
|
||||
src/java/nginx/unit/IncludeResponseWrapper.java \
|
||||
src/java/nginx/unit/InitParams.java \
|
||||
src/java/nginx/unit/InputStream.java \
|
||||
src/java/nginx/unit/JspPropertyGroup.java \
|
||||
src/java/nginx/unit/OutputStream.java \
|
||||
src/java/nginx/unit/Request.java \
|
||||
src/java/nginx/unit/RequestAttrProxy.java \
|
||||
src/java/nginx/unit/Response.java \
|
||||
src/java/nginx/unit/Session.java \
|
||||
src/java/nginx/unit/SessionAttrProxy.java \
|
||||
src/java/nginx/unit/Taglib.java \
|
||||
src/java/nginx/unit/UnitSessionCookieConfig.java \
|
||||
"
|
||||
|
||||
cat << END >> $NXT_MAKEFILE
|
||||
|
||||
.PHONY: ${NXT_JAVA_MODULE}
|
||||
.PHONY: ${NXT_JAVA_MODULE}-install
|
||||
.PHONY: ${NXT_JAVA_MODULE}-uninstall
|
||||
|
||||
all: ${NXT_JAVA_MODULE}
|
||||
|
||||
${NXT_JAVA_MODULE}: $NXT_BUILD_DIR/${NXT_JAVA_MODULE}.unit.so \
|
||||
$NXT_BUILD_DIR/$NXT_UNIT_JAR
|
||||
|
||||
$NXT_BUILD_DIR/${NXT_JAVA_MODULE}.unit.so: $nxt_objs
|
||||
\$(NXT_MODULE_LINK) -o $NXT_BUILD_DIR/${NXT_JAVA_MODULE}.unit.so \\
|
||||
$nxt_objs $NXT_JAVA_LDFLAGS $NXT_LD_OPT
|
||||
|
||||
|
||||
install: ${NXT_JAVA_MODULE}-install
|
||||
|
||||
${NXT_JAVA_MODULE}-install: $NXT_BUILD_DIR/${NXT_JAVA_MODULE}.unit.so \\
|
||||
$NXT_BUILD_DIR/$NXT_UNIT_JAR java-shared-install
|
||||
install -d \$(DESTDIR)$NXT_MODULES
|
||||
install -p $NXT_BUILD_DIR/${NXT_JAVA_MODULE}.unit.so \\
|
||||
\$(DESTDIR)$NXT_MODULES/
|
||||
install -d \$(DESTDIR)$NXT_JARS
|
||||
install -p -m 0644 $NXT_BUILD_DIR/$NXT_UNIT_JAR \$(DESTDIR)$NXT_JARS/
|
||||
|
||||
|
||||
uninstall: ${NXT_JAVA_MODULE}-uninstall
|
||||
|
||||
${NXT_JAVA_MODULE}-uninstall: java-shared-uninstall
|
||||
rm -f \$(DESTDIR)$NXT_MODULES/${NXT_JAVA_MODULE}.unit.so
|
||||
@rmdir -p \$(DESTDIR)$NXT_MODULES 2>/dev/null || true
|
||||
rm -f \$(DESTDIR)$NXT_JARS/$NXT_UNIT_JAR
|
||||
@rmdir -p \$(DESTDIR)$NXT_JARS 2>/dev/null || true
|
||||
|
||||
END
|
||||
|
||||
if ! grep ^$NXT_BUILD_DIR/$NXT_UNIT_JAR: $NXT_MAKEFILE 2>&1 > /dev/null; then
|
||||
|
||||
cat << END >> $NXT_MAKEFILE
|
||||
|
||||
.INTERMEDIATE: $NXT_BUILD_DIR/$NXT_JAVA_MODULE/.classes
|
||||
|
||||
NXT_JAVA_SRCS = $NXT_JAVA_SRCS
|
||||
|
||||
$NXT_BUILD_DIR/$NXT_JAVA_MODULE/.classes: \$(NXT_JAVA_SRCS)
|
||||
rm -rf $NXT_BUILD_DIR/$NXT_JAVA_MODULE/nginx
|
||||
$NXT_JAVAC -d $NXT_BUILD_DIR/$NXT_JAVA_MODULE -cp $NXT_JAVA_BUILD_CP \\
|
||||
\$(NXT_JAVA_SRCS)
|
||||
|
||||
$NXT_BUILD_DIR/$NXT_JAVA_MODULE/META-INF/LICENSE: LICENSE
|
||||
mkdir -p $NXT_BUILD_DIR/$NXT_JAVA_MODULE/META-INF
|
||||
cp -p LICENSE \$@
|
||||
|
||||
$NXT_BUILD_DIR/$NXT_JAVA_MODULE/META-INF/NOTICE: NOTICE
|
||||
mkdir -p $NXT_BUILD_DIR/$NXT_JAVA_MODULE/META-INF
|
||||
cp -p NOTICE \$@
|
||||
|
||||
|
||||
$NXT_BUILD_DIR/$NXT_UNIT_JAR: $NXT_BUILD_DIR/$NXT_JAVA_MODULE/.classes \\
|
||||
$NXT_BUILD_DIR/$NXT_JAVA_MODULE/META-INF/LICENSE \\
|
||||
$NXT_BUILD_DIR/$NXT_JAVA_MODULE/META-INF/NOTICE
|
||||
$NXT_JAVA_HOME/bin/jar c -C $NXT_BUILD_DIR/$NXT_JAVA_MODULE META-INF \\
|
||||
-C $NXT_BUILD_DIR/$NXT_JAVA_MODULE nginx/unit > \$@
|
||||
|
||||
END
|
||||
|
||||
fi
|
||||
|
||||
if ! grep ^java-shared-install: $NXT_MAKEFILE 2>&1 > /dev/null; then
|
||||
|
||||
cat << END >> $NXT_MAKEFILE
|
||||
|
||||
.PHONY: java-shared-install
|
||||
.PHONY: java-shared-uninstall
|
||||
|
||||
java-shared-install: $NXT_JAVA_INSTALL_JARS
|
||||
install -d \$(DESTDIR)$NXT_JARS
|
||||
install -p -m 0644 $NXT_JAVA_INSTALL_JARS \$(DESTDIR)$NXT_JARS/
|
||||
|
||||
java-shared-uninstall:
|
||||
rm -f $NXT_JAVA_UNINSTALL_JARS
|
||||
@rmdir -p \$(DESTDIR)$NXT_JARS 2>/dev/null || true
|
||||
|
||||
END
|
||||
|
||||
fi
|
||||
33
auto/modules/java_get_jar
Normal file
33
auto/modules/java_get_jar
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
# Copyright (C) NGINX, Inc.
|
||||
|
||||
# NXT_JAR_NAME=
|
||||
# NXT_JAR_VERSION=
|
||||
# NXT_JAR_NAMESPACE=
|
||||
# NXT_JAR_REPO=http://central.maven.org/maven2/
|
||||
# NXT_JAR_LOCAL_REPO=$HOME/.m2/repository/
|
||||
|
||||
NXT_JAR_FILE=${NXT_JAR_NAME}-${NXT_JAR_VERSION}.jar
|
||||
NXT_JAR_LOCAL="${NXT_JAR_LOCAL_REPO}${NXT_JAR_NAMESPACE}${NXT_JAR_NAME}/${NXT_JAR_VERSION}/${NXT_JAR_FILE}"
|
||||
NXT_JAR_URL=${NXT_JAR_REPO}${NXT_JAR_NAMESPACE}${NXT_JAR_NAME}/${NXT_JAR_VERSION}/${NXT_JAR_FILE}
|
||||
|
||||
if [ ! -f "$NXT_BUILD_DIR/$NXT_JAR_FILE" ]; then
|
||||
if [ ! -f "$NXT_JAR_LOCAL" ]; then
|
||||
$echo "getting remote $NXT_JAR_FILE ... "
|
||||
$echo "getting remote $NXT_JAR_FILE ..." >> $NXT_AUTOCONF_ERR
|
||||
|
||||
mkdir -p "${NXT_JAR_LOCAL_REPO}${NXT_JAR_NAMESPACE}${NXT_JAR_NAME}/${NXT_JAR_VERSION}/"
|
||||
curl --progress-bar "$NXT_JAR_URL" -o "$NXT_JAR_LOCAL"
|
||||
else
|
||||
$echo "getting local $NXT_JAR_FILE"
|
||||
$echo "getting local $NXT_JAR_FILE ..." >> $NXT_AUTOCONF_ERR
|
||||
fi
|
||||
|
||||
cp "$NXT_JAR_LOCAL" "$NXT_BUILD_DIR/$NXT_JAR_FILE"
|
||||
fi
|
||||
|
||||
NXT_JAVA_BUILD_CP="${NXT_JAVA_BUILD_CP}:$NXT_BUILD_DIR/$NXT_JAR_FILE"
|
||||
NXT_JAVA_INSTALL_JARS="$NXT_JAVA_INSTALL_JARS $NXT_BUILD_DIR/$NXT_JAR_FILE"
|
||||
NXT_JAVA_UNINSTALL_JARS="$NXT_JAVA_UNINSTALL_JARS \$(DESTDIR)$NXT_JARS/$NXT_JAR_FILE"
|
||||
|
||||
$echo " \"$NXT_JAR_FILE\"," >> $NXT_JAVA_JARS
|
||||
3502
src/java/nginx/unit/Context.java
Normal file
3502
src/java/nginx/unit/Context.java
Normal file
File diff suppressed because it is too large
Load Diff
8
src/java/nginx/unit/DynamicDispatcherRequest.java
Normal file
8
src/java/nginx/unit/DynamicDispatcherRequest.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package nginx.unit;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
public interface DynamicDispatcherRequest
|
||||
{
|
||||
public void setDispatcherType(DispatcherType type);
|
||||
}
|
||||
15
src/java/nginx/unit/DynamicPathRequest.java
Normal file
15
src/java/nginx/unit/DynamicPathRequest.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package nginx.unit;
|
||||
|
||||
public interface DynamicPathRequest
|
||||
extends DynamicDispatcherRequest
|
||||
{
|
||||
public void setServletPath(String servlet_path, String path_info);
|
||||
|
||||
public void setServletPath(String filter_path, String servlet_path, String path_info);
|
||||
|
||||
public void setRequestURI(String uri);
|
||||
|
||||
public void setQueryString(String query);
|
||||
|
||||
public String getFilterPath();
|
||||
}
|
||||
150
src/java/nginx/unit/ForwardRequestWrapper.java
Normal file
150
src/java/nginx/unit/ForwardRequestWrapper.java
Normal file
@@ -0,0 +1,150 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.UrlEncoded;
|
||||
|
||||
public class ForwardRequestWrapper implements DynamicPathRequest
|
||||
{
|
||||
private final Request request_;
|
||||
|
||||
private final boolean keep_attrs;
|
||||
|
||||
private final String orig_filter_path;
|
||||
private final String orig_servlet_path;
|
||||
private final String orig_path_info;
|
||||
private final String orig_uri;
|
||||
private final String orig_context_path;
|
||||
private final String orig_query;
|
||||
|
||||
private final DispatcherType orig_dtype;
|
||||
|
||||
private MultiMap<String> orig_parameters;
|
||||
|
||||
public ForwardRequestWrapper(ServletRequest request)
|
||||
{
|
||||
if (request instanceof Request) {
|
||||
request_ = (Request) request;
|
||||
} else {
|
||||
request_ = (Request) request.getAttribute(Request.BARE);
|
||||
}
|
||||
|
||||
keep_attrs = request_.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) != null;
|
||||
|
||||
orig_dtype = request_.getDispatcherType();
|
||||
|
||||
orig_filter_path = request_.getFilterPath();
|
||||
orig_servlet_path = request_.getServletPath();
|
||||
orig_path_info = request_.getPathInfo();
|
||||
orig_uri = request_.getRequestURI();
|
||||
orig_context_path = request_.getContextPath();
|
||||
orig_query = request_.getQueryString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDispatcherType(DispatcherType type)
|
||||
{
|
||||
request_.setDispatcherType(type);
|
||||
|
||||
/*
|
||||
9.4.2 Forwarded Request Parameters
|
||||
...
|
||||
Note that these attributes must always reflect the information in
|
||||
the original request even under the situation that multiple
|
||||
forwards and subsequent includes are called.
|
||||
*/
|
||||
|
||||
if (keep_attrs) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
9.4.2 Forwarded Request Parameters
|
||||
...
|
||||
The values of these attributes must be equal to the return values
|
||||
of the HttpServletRequest methods getRequestURI, getContextPath,
|
||||
getServletPath, getPathInfo, getQueryString respectively, invoked
|
||||
on the request object passed to the first servlet object in the
|
||||
call chain that received the request from the client.
|
||||
*/
|
||||
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_SERVLET_PATH, orig_servlet_path);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_PATH_INFO, orig_path_info);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_REQUEST_URI, orig_uri);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_CONTEXT_PATH, orig_context_path);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_QUERY_STRING, orig_query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletPath(String servlet_path, String path_info)
|
||||
{
|
||||
request_.setServletPath(servlet_path, path_info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletPath(String filter_path, String servlet_path, String path_info)
|
||||
{
|
||||
request_.setServletPath(filter_path, servlet_path, path_info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestURI(String uri)
|
||||
{
|
||||
request_.setRequestURI(uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQueryString(String query)
|
||||
{
|
||||
if (query != null) {
|
||||
orig_parameters = request_.getParameters();
|
||||
|
||||
MultiMap<String> parameters = new MultiMap<>();
|
||||
UrlEncoded.decodeUtf8To(query, parameters);
|
||||
|
||||
for (Map.Entry<String, List<String>> e: orig_parameters.entrySet()) {
|
||||
parameters.addValues(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
request_.setParameters(parameters);
|
||||
|
||||
request_.setQueryString(query);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterPath()
|
||||
{
|
||||
return request_.getFilterPath();
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
request_.setDispatcherType(orig_dtype);
|
||||
|
||||
request_.setRequestURI(orig_uri);
|
||||
request_.setServletPath(orig_filter_path, orig_servlet_path, orig_path_info);
|
||||
request_.setQueryString(orig_query);
|
||||
|
||||
if (orig_parameters != null) {
|
||||
request_.setParameters(orig_parameters);
|
||||
}
|
||||
|
||||
if (keep_attrs) {
|
||||
return;
|
||||
}
|
||||
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_SERVLET_PATH, null);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_PATH_INFO, null);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_REQUEST_URI, null);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_CONTEXT_PATH, null);
|
||||
request_.setAttribute_(RequestDispatcher.FORWARD_QUERY_STRING, null);
|
||||
}
|
||||
}
|
||||
42
src/java/nginx/unit/HeaderNamesEnumeration.java
Normal file
42
src/java/nginx/unit/HeaderNamesEnumeration.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class HeaderNamesEnumeration implements Enumeration<String> {
|
||||
|
||||
private long headers_ptr;
|
||||
private long size;
|
||||
private long pos = 0;
|
||||
|
||||
public HeaderNamesEnumeration(long _headers_ptr, long _size) {
|
||||
headers_ptr = _headers_ptr;
|
||||
size = _size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
if (pos >= size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pos = nextElementPos(headers_ptr, size, pos);
|
||||
return pos < size;
|
||||
}
|
||||
|
||||
static private native long nextElementPos(long headers_ptr, long size, long pos);
|
||||
|
||||
@Override
|
||||
public String nextElement()
|
||||
{
|
||||
if (pos >= size) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
return nextElement(headers_ptr, size, pos++);
|
||||
}
|
||||
|
||||
static private native String nextElement(long headers_ptr, long size, long pos);
|
||||
}
|
||||
40
src/java/nginx/unit/HeadersEnumeration.java
Normal file
40
src/java/nginx/unit/HeadersEnumeration.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class HeadersEnumeration implements Enumeration<String> {
|
||||
|
||||
private long headers_ptr;
|
||||
private long size;
|
||||
private long initial_pos;
|
||||
private long pos;
|
||||
|
||||
public HeadersEnumeration(long _headers_ptr, long _size, long _initial_pos) {
|
||||
headers_ptr = _headers_ptr;
|
||||
size = _size;
|
||||
initial_pos = _initial_pos;
|
||||
pos = _initial_pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
if (pos >= size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pos = nextElementPos(headers_ptr, size, initial_pos, pos);
|
||||
return pos < size;
|
||||
}
|
||||
|
||||
static private native long nextElementPos(long headers_ptr, long size, long initial_pos, long pos);
|
||||
|
||||
@Override
|
||||
public String nextElement()
|
||||
{
|
||||
return nextElement(headers_ptr, size, initial_pos, pos++);
|
||||
}
|
||||
|
||||
static private native String nextElement(long headers_ptr, long size, long initial_pos, long pos);
|
||||
}
|
||||
88
src/java/nginx/unit/IncludeRequestWrapper.java
Normal file
88
src/java/nginx/unit/IncludeRequestWrapper.java
Normal file
@@ -0,0 +1,88 @@
|
||||
package nginx.unit;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
public class IncludeRequestWrapper implements DynamicPathRequest
|
||||
{
|
||||
private final Request request_;
|
||||
|
||||
private final Object orig_servlet_path_attr;
|
||||
private final Object orig_path_info_attr;
|
||||
private final Object orig_uri_attr;
|
||||
private final Object orig_context_path_attr;
|
||||
private final Object orig_query_string_attr;
|
||||
|
||||
private final DispatcherType orig_dtype;
|
||||
|
||||
private String filter_path_;
|
||||
|
||||
public IncludeRequestWrapper(ServletRequest request)
|
||||
{
|
||||
if (request instanceof Request) {
|
||||
request_ = (Request) request;
|
||||
} else {
|
||||
request_ = (Request) request.getAttribute(Request.BARE);
|
||||
}
|
||||
|
||||
orig_servlet_path_attr = request_.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH);
|
||||
orig_path_info_attr = request_.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO);
|
||||
orig_uri_attr = request_.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);
|
||||
orig_context_path_attr = request_.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH);
|
||||
orig_query_string_attr = request_.getAttribute(RequestDispatcher.INCLUDE_QUERY_STRING);
|
||||
|
||||
orig_dtype = request_.getDispatcherType();
|
||||
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_CONTEXT_PATH, request_.getContextPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDispatcherType(DispatcherType type)
|
||||
{
|
||||
request_.setDispatcherType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletPath(String servlet_path, String path_info)
|
||||
{
|
||||
setServletPath(servlet_path, servlet_path, path_info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletPath(String filter_path, String servlet_path, String path_info)
|
||||
{
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_SERVLET_PATH, servlet_path);
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_PATH_INFO, path_info);
|
||||
filter_path_ = filter_path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRequestURI(String uri)
|
||||
{
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_REQUEST_URI, uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQueryString(String query)
|
||||
{
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_QUERY_STRING, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilterPath()
|
||||
{
|
||||
return filter_path_;
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
request_.setDispatcherType(orig_dtype);
|
||||
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_SERVLET_PATH, orig_servlet_path_attr);
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_PATH_INFO, orig_path_info_attr);
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_REQUEST_URI, orig_uri_attr);
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_CONTEXT_PATH, orig_context_path_attr);
|
||||
request_.setAttribute_(RequestDispatcher.INCLUDE_QUERY_STRING, orig_query_string_attr);
|
||||
}
|
||||
}
|
||||
117
src/java/nginx/unit/IncludeResponseWrapper.java
Normal file
117
src/java/nginx/unit/IncludeResponseWrapper.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
public class IncludeResponseWrapper extends HttpServletResponseWrapper {
|
||||
private static final Charset UTF_8 = StandardCharsets.UTF_8;
|
||||
|
||||
public IncludeResponseWrapper(ServletResponse response)
|
||||
{
|
||||
super((HttpServletResponse) response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCookie(Cookie cookie)
|
||||
{
|
||||
trace("addCookie: " + cookie.getName() + "=" + cookie.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDateHeader(String name, long date)
|
||||
{
|
||||
trace("addDateHeader: " + name + ": " + date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
trace("addHeader: " + name + ": " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIntHeader(String name, int value)
|
||||
{
|
||||
trace("addIntHeader: " + name + ": " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException
|
||||
{
|
||||
trace("sendRedirect: " + location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDateHeader(String name, long date)
|
||||
{
|
||||
trace("setDateHeader: " + name + ": " + date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
trace("setHeader: " + name + ": " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIntHeader(String name, int value)
|
||||
{
|
||||
trace("setIntHeader: " + name + ": " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(int sc)
|
||||
{
|
||||
trace("setStatus: " + sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void setStatus(int sc, String sm)
|
||||
{
|
||||
trace("setStatus: " + sc + "; " + sm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
trace("reset");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterEncoding(String charset)
|
||||
{
|
||||
trace("setCharacterEncoding " + charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLength(int len)
|
||||
{
|
||||
trace("setContentLength: " + len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLengthLong(long len)
|
||||
{
|
||||
trace("setContentLengthLong: " + len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentType(String type)
|
||||
{
|
||||
trace("setContentType: " + type);
|
||||
}
|
||||
|
||||
private void trace(String msg)
|
||||
{
|
||||
msg = "IncludeResponse." + msg;
|
||||
Response.trace(0, msg.getBytes(UTF_8));
|
||||
}
|
||||
}
|
||||
7
src/java/nginx/unit/InitParams.java
Normal file
7
src/java/nginx/unit/InitParams.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package nginx.unit;
|
||||
|
||||
public interface InitParams {
|
||||
public boolean setInitParameter(String name, String value);
|
||||
|
||||
public String getInitParameter(String name);
|
||||
}
|
||||
90
src/java/nginx/unit/InputStream.java
Normal file
90
src/java/nginx/unit/InputStream.java
Normal file
@@ -0,0 +1,90 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
|
||||
public class InputStream extends ServletInputStream {
|
||||
|
||||
private long req_info_ptr;
|
||||
|
||||
public InputStream(long ptr)
|
||||
{
|
||||
req_info_ptr = ptr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readLine(byte[] b, int off, int len) throws IOException {
|
||||
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return readLine(req_info_ptr, b, off, len);
|
||||
}
|
||||
|
||||
private static native int readLine(long req_info_ptr, byte[] b, int off, int len);
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFinished()
|
||||
{
|
||||
return isFinished(req_info_ptr);
|
||||
}
|
||||
|
||||
private static native boolean isFinished(long req_info_ptr);
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isReady()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener listener)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int read() throws IOException
|
||||
{
|
||||
return read(req_info_ptr);
|
||||
}
|
||||
|
||||
private static native int read(long req_info_ptr);
|
||||
|
||||
|
||||
@Override
|
||||
public int read(byte b[], int off, int len) throws IOException {
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
} else if (off < 0 || len < 0 || len > b.length - off) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return read(req_info_ptr, b, off, len);
|
||||
}
|
||||
|
||||
private static native int read(long req_info_ptr, byte b[], int off, int len);
|
||||
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
return skip(req_info_ptr, n);
|
||||
}
|
||||
|
||||
private static native long skip(long req_info_ptr, long n);
|
||||
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return available(req_info_ptr);
|
||||
}
|
||||
|
||||
private static native int available(long req_info_ptr);
|
||||
}
|
||||
169
src/java/nginx/unit/JspPropertyGroup.java
Normal file
169
src/java/nginx/unit/JspPropertyGroup.java
Normal file
@@ -0,0 +1,169 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.descriptor.JspPropertyGroupDescriptor;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public class JspPropertyGroup implements JspPropertyGroupDescriptor
|
||||
{
|
||||
private final List<String> url_patterns_ = new ArrayList<>();
|
||||
private String el_ignored_ = null;
|
||||
private String page_encoding_ = null;
|
||||
private String scripting_invalid_ = null;
|
||||
private String is_xml_ = null;
|
||||
private final List<String> include_preludes_ = new ArrayList<>();
|
||||
private final List<String> include_codas_ = new ArrayList<>();
|
||||
|
||||
private String deffered_syntax_allowed_as_literal_ = null;
|
||||
private String trim_directive_whitespaces_ = null;
|
||||
private String default_content_type_ = null;
|
||||
private String buffer_ = null;
|
||||
private String error_on_undeclared_namespace_ = null;
|
||||
|
||||
public JspPropertyGroup(NodeList nodes)
|
||||
{
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Node node = nodes.item(i);
|
||||
String tag_name = node.getNodeName();
|
||||
|
||||
if (tag_name.equals("url-pattern")) {
|
||||
url_patterns_.add(node.getTextContent().trim());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("el-ignored")) {
|
||||
el_ignored_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("page-encoding")) {
|
||||
page_encoding_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("scripting-invalid")) {
|
||||
scripting_invalid_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("is-xml")) {
|
||||
is_xml_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("include-prelude")) {
|
||||
include_preludes_.add(node.getTextContent().trim());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("include-coda")) {
|
||||
include_codas_.add(node.getTextContent().trim());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("deferred-syntax-allowed-as-literal")) {
|
||||
deffered_syntax_allowed_as_literal_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("trim-directive-whitespaces")) {
|
||||
trim_directive_whitespaces_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("default-content-type")) {
|
||||
default_content_type_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("buffer")) {
|
||||
buffer_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("error-on-undeclared-namespace")) {
|
||||
error_on_undeclared_namespace_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getUrlPatterns()
|
||||
{
|
||||
return new ArrayList<>(url_patterns_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElIgnored()
|
||||
{
|
||||
return el_ignored_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPageEncoding()
|
||||
{
|
||||
return page_encoding_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScriptingInvalid()
|
||||
{
|
||||
return scripting_invalid_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIsXml()
|
||||
{
|
||||
return is_xml_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getIncludePreludes()
|
||||
{
|
||||
return new ArrayList<>(include_preludes_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getIncludeCodas()
|
||||
{
|
||||
return new ArrayList<>(include_codas_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeferredSyntaxAllowedAsLiteral()
|
||||
{
|
||||
return deffered_syntax_allowed_as_literal_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTrimDirectiveWhitespaces()
|
||||
{
|
||||
return trim_directive_whitespaces_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultContentType()
|
||||
{
|
||||
return default_content_type_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBuffer()
|
||||
{
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorOnUndeclaredNamespace()
|
||||
{
|
||||
return error_on_undeclared_namespace_;
|
||||
}
|
||||
}
|
||||
|
||||
68
src/java/nginx/unit/OutputStream.java
Normal file
68
src/java/nginx/unit/OutputStream.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
|
||||
public class OutputStream extends ServletOutputStream {
|
||||
|
||||
private long req_info_ptr;
|
||||
|
||||
public OutputStream(long ptr) {
|
||||
req_info_ptr = ptr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
write(req_info_ptr, b);
|
||||
}
|
||||
|
||||
private static native void write(long req_info_ptr, int b);
|
||||
|
||||
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException
|
||||
{
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
} else if ((off < 0) || (off > b.length) || (len < 0) ||
|
||||
((off + len) > b.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
write(req_info_ptr, b, off, len);
|
||||
}
|
||||
|
||||
private static native void write(long req_info_ptr, byte b[], int off, int len);
|
||||
|
||||
@Override
|
||||
public void flush()
|
||||
{
|
||||
flush(req_info_ptr);
|
||||
}
|
||||
|
||||
private static native void flush(long req_info_ptr);
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
close(req_info_ptr);
|
||||
}
|
||||
|
||||
private static native void close(long req_info_ptr);
|
||||
|
||||
@Override
|
||||
public boolean isReady()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWriteListener(WriteListener listener)
|
||||
{
|
||||
}
|
||||
}
|
||||
1123
src/java/nginx/unit/Request.java
Normal file
1123
src/java/nginx/unit/Request.java
Normal file
File diff suppressed because it is too large
Load Diff
40
src/java/nginx/unit/RequestAttrProxy.java
Normal file
40
src/java/nginx/unit/RequestAttrProxy.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletRequestAttributeEvent;
|
||||
import javax.servlet.ServletRequestAttributeListener;
|
||||
|
||||
public class RequestAttrProxy implements ServletRequestAttributeListener
|
||||
{
|
||||
private final List<ServletRequestAttributeListener> listeners_;
|
||||
|
||||
public RequestAttrProxy(List<ServletRequestAttributeListener> listeners)
|
||||
{
|
||||
listeners_ = listeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(ServletRequestAttributeEvent srae)
|
||||
{
|
||||
for (ServletRequestAttributeListener l : listeners_) {
|
||||
l.attributeAdded(srae);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(ServletRequestAttributeEvent srae)
|
||||
{
|
||||
for (ServletRequestAttributeListener l : listeners_) {
|
||||
l.attributeReplaced(srae);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(ServletRequestAttributeEvent srae)
|
||||
{
|
||||
for (ServletRequestAttributeListener l : listeners_) {
|
||||
l.attributeRemoved(srae);
|
||||
}
|
||||
}
|
||||
}
|
||||
817
src/java/nginx/unit/Response.java
Normal file
817
src/java/nginx/unit/Response.java
Normal file
@@ -0,0 +1,817 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.String;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
public class Response implements HttpServletResponse {
|
||||
|
||||
private long req_info_ptr;
|
||||
|
||||
private static final String defaultCharacterEncoding = "iso-8859-1";
|
||||
private String characterEncoding = defaultCharacterEncoding;
|
||||
private String contentType = null;
|
||||
private String contentTypeHeader = null;
|
||||
|
||||
private static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
|
||||
private static final Charset UTF_8 = StandardCharsets.UTF_8;
|
||||
|
||||
private static final String CONTENT_TYPE = "Content-Type";
|
||||
private static final byte[] SET_COOKIE_BYTES = "Set-Cookie".getBytes(ISO_8859_1);
|
||||
private static final byte[] EXPIRES_BYTES = "Expires".getBytes(ISO_8859_1);
|
||||
|
||||
/**
|
||||
* The only date format permitted when generating HTTP headers.
|
||||
*/
|
||||
public static final String RFC1123_DATE =
|
||||
"EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||
|
||||
private static final SimpleDateFormat format =
|
||||
new SimpleDateFormat(RFC1123_DATE, Locale.US);
|
||||
|
||||
private static final String ZERO_DATE_STRING = dateToString(0);
|
||||
private static final byte[] ZERO_DATE_BYTES = ZERO_DATE_STRING.getBytes(ISO_8859_1);
|
||||
|
||||
/**
|
||||
* If this string is found within the comment of a cookie added with {@link #addCookie(Cookie)}, then the cookie
|
||||
* will be set as HTTP ONLY.
|
||||
*/
|
||||
public final static String HTTP_ONLY_COMMENT = "__HTTP_ONLY__";
|
||||
|
||||
private OutputStream outputStream = null;
|
||||
|
||||
private PrintWriter writer = null;
|
||||
|
||||
|
||||
public Response(long ptr) {
|
||||
req_info_ptr = ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a set cookie value by RFC6265
|
||||
*
|
||||
* @param name the name
|
||||
* @param value the value
|
||||
* @param domain the domain
|
||||
* @param path the path
|
||||
* @param maxAge the maximum age
|
||||
* @param isSecure true if secure cookie
|
||||
* @param isHttpOnly true if for http only
|
||||
*/
|
||||
public void addSetRFC6265Cookie(
|
||||
final String name,
|
||||
final String value,
|
||||
final String domain,
|
||||
final String path,
|
||||
final long maxAge,
|
||||
final boolean isSecure,
|
||||
final boolean isHttpOnly)
|
||||
{
|
||||
// Check arguments
|
||||
if (name == null || name.length() == 0) {
|
||||
throw new IllegalArgumentException("Bad cookie name");
|
||||
}
|
||||
|
||||
// Name is checked for legality by servlet spec, but can also be passed directly so check again for quoting
|
||||
// Per RFC6265, Cookie.name follows RFC2616 Section 2.2 token rules
|
||||
//Syntax.requireValidRFC2616Token(name, "RFC6265 Cookie name");
|
||||
// Ensure that Per RFC6265, Cookie.value follows syntax rules
|
||||
//Syntax.requireValidRFC6265CookieValue(value);
|
||||
|
||||
// Format value and params
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(name).append('=').append(value == null ? "" : value);
|
||||
|
||||
// Append path
|
||||
if (path != null && path.length() > 0) {
|
||||
buf.append(";Path=").append(path);
|
||||
}
|
||||
|
||||
// Append domain
|
||||
if (domain != null && domain.length() > 0) {
|
||||
buf.append(";Domain=").append(domain);
|
||||
}
|
||||
|
||||
// Handle max-age and/or expires
|
||||
if (maxAge >= 0) {
|
||||
// Always use expires
|
||||
// This is required as some browser (M$ this means you!) don't handle max-age even with v1 cookies
|
||||
buf.append(";Expires=");
|
||||
if (maxAge == 0)
|
||||
buf.append(ZERO_DATE_STRING);
|
||||
else
|
||||
buf.append(dateToString(System.currentTimeMillis() + 1000L * maxAge));
|
||||
|
||||
buf.append(";Max-Age=");
|
||||
buf.append(maxAge);
|
||||
}
|
||||
|
||||
// add the other fields
|
||||
if (isSecure)
|
||||
buf.append(";Secure");
|
||||
if (isHttpOnly)
|
||||
buf.append(";HttpOnly");
|
||||
|
||||
// add the set cookie
|
||||
addHeader(req_info_ptr, SET_COOKIE_BYTES,
|
||||
buf.toString().getBytes(ISO_8859_1));
|
||||
|
||||
// Expire responses with set-cookie headers so they do not get cached.
|
||||
setHeader(req_info_ptr, EXPIRES_BYTES, ZERO_DATE_BYTES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCookie(Cookie cookie)
|
||||
{
|
||||
trace("addCookie: " + cookie.getName() + "=" + cookie.getValue());
|
||||
|
||||
if (StringUtil.isBlank(cookie.getName())) {
|
||||
throw new IllegalArgumentException("Cookie.name cannot be blank/null");
|
||||
}
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
addCookie_(cookie);
|
||||
}
|
||||
|
||||
private void addCookie_(Cookie cookie)
|
||||
{
|
||||
String comment = cookie.getComment();
|
||||
boolean httpOnly = false;
|
||||
|
||||
if (comment != null && comment.contains(HTTP_ONLY_COMMENT)) {
|
||||
httpOnly = true;
|
||||
}
|
||||
|
||||
addSetRFC6265Cookie(cookie.getName(),
|
||||
cookie.getValue(),
|
||||
cookie.getDomain(),
|
||||
cookie.getPath(),
|
||||
cookie.getMaxAge(),
|
||||
cookie.getSecure(),
|
||||
httpOnly || cookie.isHttpOnly());
|
||||
}
|
||||
|
||||
public void addSessionIdCookie(Cookie cookie)
|
||||
{
|
||||
trace("addSessionIdCookie: " + cookie.getName() + "=" + cookie.getValue());
|
||||
|
||||
if (isCommitted()) {
|
||||
/*
|
||||
9.3 The Include Method
|
||||
|
||||
... any call to HttpServletRequest.getSession() or
|
||||
HttpServletRequest.getSession(boolean) that would require
|
||||
adding a Cookie response header must throw an
|
||||
IllegalStateException if the response has been committed.
|
||||
*/
|
||||
throw new IllegalStateException("Response already sent");
|
||||
}
|
||||
|
||||
addCookie_(cookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDateHeader(String name, long date)
|
||||
{
|
||||
trace("addDateHeader: " + name + ": " + date);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String value = dateToString(date);
|
||||
|
||||
addHeader(req_info_ptr, name.getBytes(ISO_8859_1),
|
||||
value.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
private static String dateToString(long date)
|
||||
{
|
||||
Date dateValue = new Date(date);
|
||||
format.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
return format.format(dateValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
trace("addHeader: " + name + ": " + value);
|
||||
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CONTENT_TYPE.equalsIgnoreCase(name)) {
|
||||
setContentType(value);
|
||||
return;
|
||||
}
|
||||
|
||||
addHeader(req_info_ptr, name.getBytes(ISO_8859_1),
|
||||
value.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
private static native void addHeader(long req_info_ptr, byte[] name, byte[] value);
|
||||
|
||||
|
||||
@Override
|
||||
public void addIntHeader(String name, int value)
|
||||
{
|
||||
trace("addIntHeader: " + name + ": " + value);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
addIntHeader(req_info_ptr, name.getBytes(ISO_8859_1), value);
|
||||
}
|
||||
|
||||
private static native void addIntHeader(long req_info_ptr, byte[] name, int value);
|
||||
|
||||
|
||||
@Override
|
||||
public boolean containsHeader(String name)
|
||||
{
|
||||
trace("containsHeader: " + name);
|
||||
|
||||
return containsHeader(req_info_ptr, name.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
private static native boolean containsHeader(long req_info_ptr, byte[] name);
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String encodeRedirectUrl(String url)
|
||||
{
|
||||
return encodeRedirectURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeRedirectURL(String url)
|
||||
{
|
||||
log("encodeRedirectURL: " + url);
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String encodeUrl(String url)
|
||||
{
|
||||
return encodeURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeURL(String url)
|
||||
{
|
||||
log("encodeURL: " + url);
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
trace("getHeader: " + name);
|
||||
|
||||
return getHeader(req_info_ptr, name.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
private static native String getHeader(long req_info_ptr, byte[] name);
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<String> getHeaderNames()
|
||||
{
|
||||
trace("getHeaderNames");
|
||||
|
||||
Enumeration<String> e = getHeaderNames(req_info_ptr);
|
||||
if (e == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.list(e);
|
||||
}
|
||||
|
||||
private static native Enumeration<String> getHeaderNames(long req_info_ptr);
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<String> getHeaders(String name)
|
||||
{
|
||||
trace("getHeaders: " + name);
|
||||
|
||||
Enumeration<String> e = getHeaders(req_info_ptr, name.getBytes(ISO_8859_1));
|
||||
if (e == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.list(e);
|
||||
}
|
||||
|
||||
private static native Enumeration<String> getHeaders(long req_info_ptr, byte[] name);
|
||||
|
||||
|
||||
@Override
|
||||
public int getStatus()
|
||||
{
|
||||
trace("getStatus");
|
||||
|
||||
return getStatus(req_info_ptr);
|
||||
}
|
||||
|
||||
private static native int getStatus(long req_info_ptr);
|
||||
|
||||
|
||||
@Override
|
||||
public void sendError(int sc) throws IOException
|
||||
{
|
||||
sendError(sc, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int sc, String msg) throws IOException
|
||||
{
|
||||
trace("sendError: " + sc + ", " + msg);
|
||||
|
||||
if (isCommitted()) {
|
||||
throw new IllegalStateException("Response already sent");
|
||||
}
|
||||
|
||||
setStatus(sc);
|
||||
|
||||
Request request = getRequest(req_info_ptr);
|
||||
|
||||
// If we are allowed to have a body, then produce the error page.
|
||||
if (sc != SC_NO_CONTENT && sc != SC_NOT_MODIFIED &&
|
||||
sc != SC_PARTIAL_CONTENT && sc >= SC_OK)
|
||||
{
|
||||
request.setAttribute_(RequestDispatcher.ERROR_STATUS_CODE, sc);
|
||||
request.setAttribute_(RequestDispatcher.ERROR_MESSAGE, msg);
|
||||
request.setAttribute_(RequestDispatcher.ERROR_REQUEST_URI,
|
||||
request.getRequestURI());
|
||||
/*
|
||||
request.setAttribute_(RequestDispatcher.ERROR_SERVLET_NAME,
|
||||
request.getServletName());
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
Avoid commit and give chance for error handlers.
|
||||
|
||||
if (!request.isAsyncStarted()) {
|
||||
commit();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private static native Request getRequest(long req_info_ptr);
|
||||
|
||||
private void commit()
|
||||
{
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
|
||||
} else if (outputStream != null) {
|
||||
outputStream.close();
|
||||
|
||||
} else {
|
||||
commit(req_info_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
private static native void commit(long req_info_ptr);
|
||||
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException
|
||||
{
|
||||
trace("sendRedirect: " + location);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
URI uri = new URI(location);
|
||||
|
||||
if (!uri.isAbsolute()) {
|
||||
URI req_uri = new URI(getRequest(req_info_ptr).getRequestURL().toString());
|
||||
uri = req_uri.resolve(uri);
|
||||
|
||||
location = uri.toString();
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
log("sendRedirect: failed to send redirect: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
sendRedirect(req_info_ptr, location.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
private static native void sendRedirect(long req_info_ptr, byte[] location);
|
||||
|
||||
|
||||
@Override
|
||||
public void setDateHeader(String name, long date)
|
||||
{
|
||||
trace("setDateHeader: " + name + ": " + date);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String value = dateToString(date);
|
||||
|
||||
setHeader(req_info_ptr, name.getBytes(ISO_8859_1),
|
||||
value.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
trace("setHeader: " + name + ": " + value);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CONTENT_TYPE.equalsIgnoreCase(name)) {
|
||||
setContentType(value);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* When value is null container behaviour is undefined.
|
||||
* - Tomcat ignores setHeader call;
|
||||
* - Jetty & Resin acts as removeHeader;
|
||||
*/
|
||||
if (value == null) {
|
||||
removeHeader(req_info_ptr, name.getBytes(ISO_8859_1));
|
||||
return;
|
||||
}
|
||||
|
||||
setHeader(req_info_ptr, name.getBytes(ISO_8859_1),
|
||||
value.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
private static native void setHeader(long req_info_ptr, byte[] name, byte[] value);
|
||||
|
||||
private static native void removeHeader(long req_info_ptr, byte[] name);
|
||||
|
||||
@Override
|
||||
public void setIntHeader(String name, int value)
|
||||
{
|
||||
trace("setIntHeader: " + name + ": " + value);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIntHeader(req_info_ptr, name.getBytes(ISO_8859_1), value);
|
||||
}
|
||||
|
||||
private static native void setIntHeader(long req_info_ptr, byte[] name, int value);
|
||||
|
||||
|
||||
@Override
|
||||
public void setStatus(int sc)
|
||||
{
|
||||
trace("setStatus: " + sc);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(req_info_ptr, sc);
|
||||
}
|
||||
|
||||
private static native void setStatus(long req_info_ptr, int sc);
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void setStatus(int sc, String sm)
|
||||
{
|
||||
trace("setStatus: " + sc + "; " + sm);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(req_info_ptr, sc);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flushBuffer() throws IOException
|
||||
{
|
||||
trace("flushBuffer");
|
||||
|
||||
if (writer != null) {
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
if (outputStream != null) {
|
||||
outputStream.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferSize()
|
||||
{
|
||||
trace("getBufferSize");
|
||||
|
||||
return getBufferSize(req_info_ptr);
|
||||
}
|
||||
|
||||
public static native int getBufferSize(long req_info_ptr);
|
||||
|
||||
|
||||
@Override
|
||||
public String getCharacterEncoding()
|
||||
{
|
||||
trace("getCharacterEncoding");
|
||||
|
||||
return characterEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType()
|
||||
{
|
||||
/* In JIRA decorator get content type called after commit. */
|
||||
|
||||
String res = contentTypeHeader;
|
||||
|
||||
trace("getContentType: " + res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static native String getContentType(long req_info_ptr);
|
||||
|
||||
@Override
|
||||
public Locale getLocale()
|
||||
{
|
||||
log("getLocale");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException
|
||||
{
|
||||
trace("getOutputStream");
|
||||
|
||||
if (writer != null) {
|
||||
throw new IllegalStateException("Writer already created");
|
||||
}
|
||||
|
||||
if (outputStream == null) {
|
||||
outputStream = new OutputStream(req_info_ptr);
|
||||
}
|
||||
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter getWriter() throws IOException
|
||||
{
|
||||
trace("getWriter ( characterEncoding = '" + characterEncoding + "' )");
|
||||
|
||||
if (outputStream != null) {
|
||||
throw new IllegalStateException("OutputStream already created");
|
||||
}
|
||||
|
||||
if (writer == null) {
|
||||
ServletOutputStream stream = new OutputStream(req_info_ptr);
|
||||
|
||||
writer = new PrintWriter(
|
||||
new OutputStreamWriter(stream, Charset.forName(characterEncoding)),
|
||||
false);
|
||||
}
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommitted()
|
||||
{
|
||||
trace("isCommitted");
|
||||
|
||||
return isCommitted(req_info_ptr);
|
||||
}
|
||||
|
||||
public static native boolean isCommitted(long req_info_ptr);
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
trace("reset");
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
reset(req_info_ptr);
|
||||
|
||||
writer = null;
|
||||
outputStream = null;
|
||||
}
|
||||
|
||||
public static native void reset(long req_info_ptr);
|
||||
|
||||
@Override
|
||||
public void resetBuffer()
|
||||
{
|
||||
trace("resetBuffer");
|
||||
|
||||
resetBuffer(req_info_ptr);
|
||||
|
||||
writer = null;
|
||||
outputStream = null;
|
||||
}
|
||||
|
||||
public static native void resetBuffer(long req_info_ptr);
|
||||
|
||||
@Override
|
||||
public void setBufferSize(int size)
|
||||
{
|
||||
trace("setBufferSize: " + size);
|
||||
|
||||
setBufferSize(req_info_ptr, size);
|
||||
}
|
||||
|
||||
public static native void setBufferSize(long req_info_ptr, int size);
|
||||
|
||||
@Override
|
||||
public void setCharacterEncoding(String charset)
|
||||
{
|
||||
trace("setCharacterEncoding " + charset);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (charset == null) {
|
||||
if (writer != null
|
||||
&& !characterEncoding.equalsIgnoreCase(defaultCharacterEncoding))
|
||||
{
|
||||
/* TODO throw */
|
||||
return;
|
||||
}
|
||||
|
||||
characterEncoding = defaultCharacterEncoding;
|
||||
} else {
|
||||
if (writer != null
|
||||
&& !characterEncoding.equalsIgnoreCase(charset))
|
||||
{
|
||||
/* TODO throw */
|
||||
return;
|
||||
}
|
||||
|
||||
characterEncoding = charset;
|
||||
}
|
||||
|
||||
if (contentType != null) {
|
||||
String type = contentType + ";charset=" + characterEncoding;
|
||||
|
||||
contentTypeHeader = type;
|
||||
|
||||
setContentType(req_info_ptr, type.getBytes(ISO_8859_1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setContentLength(int len)
|
||||
{
|
||||
trace("setContentLength: " + len);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setContentLength(req_info_ptr, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLengthLong(long len)
|
||||
{
|
||||
trace("setContentLengthLong: " + len);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setContentLength(req_info_ptr, len);
|
||||
}
|
||||
|
||||
private static native void setContentLength(long req_info_ptr, long len);
|
||||
|
||||
|
||||
@Override
|
||||
public void setContentType(String type)
|
||||
{
|
||||
trace("setContentType: " + type);
|
||||
|
||||
if (isCommitted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
removeContentType(req_info_ptr);
|
||||
contentType = null;
|
||||
contentTypeHeader = null;
|
||||
return;
|
||||
}
|
||||
|
||||
String charset = MimeTypes.getCharsetFromContentType(type);
|
||||
String ctype = MimeTypes.getContentTypeWithoutCharset(type);
|
||||
|
||||
if (writer != null
|
||||
&& charset != null
|
||||
&& !characterEncoding.equalsIgnoreCase(charset))
|
||||
{
|
||||
/* To late to change character encoding */
|
||||
charset = characterEncoding;
|
||||
type = ctype + ";charset=" + characterEncoding;
|
||||
}
|
||||
|
||||
if (charset == null) {
|
||||
type = type + ";charset=" + characterEncoding;
|
||||
} else {
|
||||
characterEncoding = charset;
|
||||
}
|
||||
|
||||
contentType = ctype;
|
||||
contentTypeHeader = type;
|
||||
|
||||
setContentType(req_info_ptr, type.getBytes(ISO_8859_1));
|
||||
}
|
||||
|
||||
private static native void setContentType(long req_info_ptr, byte[] type);
|
||||
|
||||
private static native void removeContentType(long req_info_ptr);
|
||||
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale loc)
|
||||
{
|
||||
log("setLocale: " + loc);
|
||||
}
|
||||
|
||||
private void log(String msg)
|
||||
{
|
||||
msg = "Response." + msg;
|
||||
log(req_info_ptr, msg.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
public static native void log(long req_info_ptr, byte[] msg);
|
||||
|
||||
|
||||
private void trace(String msg)
|
||||
{
|
||||
msg = "Response." + msg;
|
||||
trace(req_info_ptr, msg.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
public static native void trace(long req_info_ptr, byte[] msg);
|
||||
}
|
||||
251
src/java/nginx/unit/Session.java
Normal file
251
src/java/nginx/unit/Session.java
Normal file
@@ -0,0 +1,251 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Andrey Kazankov
|
||||
*/
|
||||
public class Session implements HttpSession, Serializable
|
||||
{
|
||||
private final Map<String, Object> attributes = new HashMap<>();
|
||||
private final long creation_time = new Date().getTime();
|
||||
private long last_access_time = creation_time;
|
||||
private long access_time = creation_time;
|
||||
private int max_inactive_interval;
|
||||
private String id;
|
||||
private final Context context;
|
||||
private boolean is_new = true;
|
||||
private final HttpSessionAttributeListener attr_listener;
|
||||
|
||||
public Session(Context context, String id,
|
||||
HttpSessionAttributeListener al, int max_inactive_interval)
|
||||
{
|
||||
this.id = id;
|
||||
this.context = context;
|
||||
attr_listener = al;
|
||||
this.max_inactive_interval = max_inactive_interval;
|
||||
}
|
||||
|
||||
public void setId(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCreationTime()
|
||||
{
|
||||
return creation_time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastAccessedTime()
|
||||
{
|
||||
return last_access_time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxInactiveInterval(int i)
|
||||
{
|
||||
max_inactive_interval = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxInactiveInterval()
|
||||
{
|
||||
return max_inactive_interval;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public javax.servlet.http.HttpSessionContext getSessionContext()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String s)
|
||||
{
|
||||
synchronized (attributes) {
|
||||
return attributes.get(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public Object getValue(String s)
|
||||
{
|
||||
return getAttribute(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames()
|
||||
{
|
||||
synchronized (attributes) {
|
||||
return Collections.enumeration(attributes.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public String[] getValueNames()
|
||||
{
|
||||
synchronized (attributes) {
|
||||
return attributes.keySet().toArray(new String[attributes.keySet().size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String s, Object o)
|
||||
{
|
||||
Object old;
|
||||
|
||||
if (o != null && o instanceof HttpSessionBindingListener) {
|
||||
HttpSessionBindingListener l = (HttpSessionBindingListener) o;
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, s);
|
||||
|
||||
l.valueBound(e);
|
||||
}
|
||||
|
||||
synchronized (attributes) {
|
||||
if (o != null) {
|
||||
old = attributes.put(s, o);
|
||||
} else {
|
||||
old = attributes.remove(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (old != null && old instanceof HttpSessionBindingListener) {
|
||||
HttpSessionBindingListener l = (HttpSessionBindingListener) old;
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, s);
|
||||
|
||||
l.valueUnbound(e);
|
||||
}
|
||||
|
||||
if (attr_listener == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (o == null) {
|
||||
if (old != null) {
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, s, old);
|
||||
attr_listener.attributeRemoved(e);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (old != null) {
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, s, old);
|
||||
attr_listener.attributeReplaced(e);
|
||||
} else {
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, s, o);
|
||||
attr_listener.attributeAdded(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void putValue(String s, Object o)
|
||||
{
|
||||
setAttribute(s,o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String s)
|
||||
{
|
||||
Object o;
|
||||
|
||||
synchronized (attributes) {
|
||||
o = attributes.remove(s);
|
||||
}
|
||||
|
||||
if (o != null && o instanceof HttpSessionBindingListener) {
|
||||
HttpSessionBindingListener l = (HttpSessionBindingListener) o;
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, s);
|
||||
|
||||
l.valueUnbound(e);
|
||||
}
|
||||
|
||||
if (attr_listener == null || o == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, s, o);
|
||||
attr_listener.attributeRemoved(e);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void removeValue(String s)
|
||||
{
|
||||
removeAttribute(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate()
|
||||
{
|
||||
context.invalidateSession(this);
|
||||
|
||||
unboundAttributes();
|
||||
}
|
||||
|
||||
private void unboundAttributes()
|
||||
{
|
||||
for (Map.Entry<String, Object> a : attributes.entrySet()) {
|
||||
Object o = a.getValue();
|
||||
if (o != null && o instanceof HttpSessionBindingListener) {
|
||||
HttpSessionBindingListener l = (HttpSessionBindingListener) o;
|
||||
HttpSessionBindingEvent e = new HttpSessionBindingEvent(this, a.getKey());
|
||||
|
||||
l.valueUnbound(e);
|
||||
}
|
||||
}
|
||||
|
||||
attributes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNew()
|
||||
{
|
||||
return is_new;
|
||||
}
|
||||
|
||||
public void accessed() {
|
||||
synchronized (this) {
|
||||
is_new = false;
|
||||
|
||||
last_access_time = access_time;
|
||||
access_time = new Date().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkTimeOut()
|
||||
{
|
||||
return (max_inactive_interval > 0) &&
|
||||
(access_time - last_access_time > max_inactive_interval * 1000);
|
||||
}
|
||||
}
|
||||
40
src/java/nginx/unit/SessionAttrProxy.java
Normal file
40
src/java/nginx/unit/SessionAttrProxy.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package nginx.unit;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
|
||||
public class SessionAttrProxy implements HttpSessionAttributeListener
|
||||
{
|
||||
private final List<HttpSessionAttributeListener> listeners_;
|
||||
|
||||
public SessionAttrProxy(List<HttpSessionAttributeListener> listeners)
|
||||
{
|
||||
listeners_ = listeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(HttpSessionBindingEvent event)
|
||||
{
|
||||
for (HttpSessionAttributeListener l : listeners_) {
|
||||
l.attributeAdded(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(HttpSessionBindingEvent event)
|
||||
{
|
||||
for (HttpSessionAttributeListener l : listeners_) {
|
||||
l.attributeRemoved(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(HttpSessionBindingEvent event)
|
||||
{
|
||||
for (HttpSessionAttributeListener l : listeners_) {
|
||||
l.attributeReplaced(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/java/nginx/unit/Taglib.java
Normal file
44
src/java/nginx/unit/Taglib.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package nginx.unit;
|
||||
|
||||
import javax.servlet.descriptor.TaglibDescriptor;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
public class Taglib implements TaglibDescriptor
|
||||
{
|
||||
private String uri_ = null;
|
||||
private String location_ = null;
|
||||
|
||||
public Taglib(NodeList nodes)
|
||||
{
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Node node = nodes.item(i);
|
||||
String tag_name = node.getNodeName();
|
||||
|
||||
if (tag_name.equals("taglib-uri")) {
|
||||
uri_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tag_name.equals("taglib-location")) {
|
||||
location_ = node.getTextContent().trim();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaglibURI()
|
||||
{
|
||||
return uri_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaglibLocation()
|
||||
{
|
||||
return location_;
|
||||
}
|
||||
}
|
||||
|
||||
110
src/java/nginx/unit/UnitSessionCookieConfig.java
Normal file
110
src/java/nginx/unit/UnitSessionCookieConfig.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package nginx.unit;
|
||||
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
|
||||
/*
|
||||
|
||||
<session-config>
|
||||
<session-timeout>60</session-timeout>
|
||||
<cookie-config></cookie-config>
|
||||
<tracking-mode></tracking-mode>
|
||||
</session-config>
|
||||
|
||||
|
||||
*/
|
||||
public class UnitSessionCookieConfig implements SessionCookieConfig {
|
||||
|
||||
private static final String default_name = "JSESSIONID";
|
||||
|
||||
private String name = default_name;
|
||||
private String domain;
|
||||
private String path;
|
||||
private String comment;
|
||||
private boolean httpOnly = true;
|
||||
private boolean secure = false;
|
||||
private int maxAge = -1;
|
||||
|
||||
@Override
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDomain(String domain)
|
||||
{
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDomain()
|
||||
{
|
||||
return domain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPath(String path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComment(String comment)
|
||||
{
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComment()
|
||||
{
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHttpOnly(boolean httpOnly)
|
||||
{
|
||||
this.httpOnly = httpOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHttpOnly()
|
||||
{
|
||||
return httpOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSecure(boolean secure)
|
||||
{
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure()
|
||||
{
|
||||
return secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxAge(int maxAge)
|
||||
{
|
||||
this.maxAge = maxAge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxAge()
|
||||
{
|
||||
return maxAge;
|
||||
}
|
||||
}
|
||||
175
src/java/nxt_jni.c
Normal file
175
src/java/nxt_jni.c
Normal file
@@ -0,0 +1,175 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_auto_config.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit.h>
|
||||
#include <nxt_unit_field.h>
|
||||
|
||||
#include "nxt_jni.h"
|
||||
|
||||
|
||||
static jclass nxt_java_NoSuchElementException_class;
|
||||
static jclass nxt_java_IOException_class;
|
||||
static jclass nxt_java_IllegalStateException_class;
|
||||
static jclass nxt_java_File_class;
|
||||
static jmethodID nxt_java_File_ctor;
|
||||
|
||||
static inline char nxt_java_lowcase(char c);
|
||||
|
||||
|
||||
int
|
||||
nxt_java_jni_init(JNIEnv *env)
|
||||
{
|
||||
jclass cls;
|
||||
|
||||
cls = (*env)->FindClass(env, "java/util/NoSuchElementException");
|
||||
if (cls == NULL) {
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_NoSuchElementException_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
|
||||
|
||||
cls = (*env)->FindClass(env, "java/io/IOException");
|
||||
if (cls == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_IOException_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
|
||||
|
||||
cls = (*env)->FindClass(env, "java/lang/IllegalStateException");
|
||||
if (cls == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class);
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_IOException_class);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_IllegalStateException_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
|
||||
|
||||
cls = (*env)->FindClass(env, "java/io/File");
|
||||
if (cls == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class);
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_IOException_class);
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_IllegalStateException_class);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_File_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
|
||||
|
||||
nxt_java_File_ctor = (*env)->GetMethodID(env, nxt_java_File_class, "<init>",
|
||||
"(Ljava/lang/String;)V");
|
||||
if (nxt_java_File_ctor == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_NoSuchElementException_class);
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_IOException_class);
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_IllegalStateException_class);
|
||||
(*env)->DeleteGlobalRef(env, nxt_java_File_class);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_java_throw_NoSuchElementException(JNIEnv *env, const char *msg)
|
||||
{
|
||||
(*env)->ThrowNew(env, nxt_java_NoSuchElementException_class, msg);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_java_throw_IOException(JNIEnv *env, const char *msg)
|
||||
{
|
||||
(*env)->ThrowNew(env, nxt_java_IOException_class, msg);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_java_throw_IllegalStateException(JNIEnv *env, const char *msg)
|
||||
{
|
||||
(*env)->ThrowNew(env, nxt_java_IllegalStateException_class, msg);
|
||||
}
|
||||
|
||||
|
||||
nxt_unit_field_t *
|
||||
nxt_java_findHeader(nxt_unit_field_t *f, nxt_unit_field_t *end,
|
||||
const char *name, uint8_t name_len)
|
||||
{
|
||||
const char *field_name;
|
||||
|
||||
for (/* void */ ; f < end; f++) {
|
||||
if (f->skip != 0 || f->name_length != name_len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
field_name = nxt_unit_sptr_get(&f->name);
|
||||
|
||||
if (nxt_java_strcaseeq(name, field_name, name_len)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nxt_java_strcaseeq(const char *str1, const char *str2, int len)
|
||||
{
|
||||
char c1, c2;
|
||||
const char *end1;
|
||||
|
||||
end1 = str1 + len;
|
||||
|
||||
while (str1 < end1) {
|
||||
c1 = nxt_java_lowcase(*str1++);
|
||||
c2 = nxt_java_lowcase(*str2++);
|
||||
|
||||
if (c1 != c2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static inline char
|
||||
nxt_java_lowcase(char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') ? c | 0x20 : c;
|
||||
}
|
||||
|
||||
|
||||
jstring
|
||||
nxt_java_newString(JNIEnv *env, char *str, uint32_t len)
|
||||
{
|
||||
char tmp;
|
||||
jstring res;
|
||||
|
||||
tmp = str[len];
|
||||
|
||||
if (tmp != '\0') {
|
||||
str[len] = '\0';
|
||||
}
|
||||
|
||||
res = (*env)->NewStringUTF(env, str);
|
||||
|
||||
if (tmp != '\0') {
|
||||
str[len] = tmp;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
55
src/java/nxt_jni.h
Normal file
55
src/java/nxt_jni.h
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_JNI_H_INCLUDED_
|
||||
#define _NXT_JAVA_JNI_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit_typedefs.h>
|
||||
|
||||
|
||||
int nxt_java_jni_init(JNIEnv *env);
|
||||
|
||||
void nxt_java_throw_NoSuchElementException(JNIEnv *env, const char *msg);
|
||||
|
||||
void nxt_java_throw_IOException(JNIEnv *env, const char *msg);
|
||||
|
||||
void nxt_java_throw_IllegalStateException(JNIEnv *env, const char *msg);
|
||||
|
||||
nxt_unit_field_t *nxt_java_findHeader(nxt_unit_field_t *f, nxt_unit_field_t *e,
|
||||
const char *name, uint8_t name_len);
|
||||
|
||||
int nxt_java_strcaseeq(const char *str1, const char *str2, int len);
|
||||
|
||||
jstring nxt_java_newString(JNIEnv *env, char *str, uint32_t len);
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t header_size;
|
||||
uint32_t buf_size;
|
||||
|
||||
jobject jreq;
|
||||
jobject jresp;
|
||||
|
||||
nxt_unit_buf_t *first;
|
||||
nxt_unit_buf_t *buf;
|
||||
|
||||
} nxt_java_request_data_t;
|
||||
|
||||
|
||||
static inline jlong
|
||||
nxt_ptr2jlong(void *ptr)
|
||||
{
|
||||
return (jlong) (intptr_t) ptr;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
nxt_jlong2ptr(jlong l)
|
||||
{
|
||||
return (void *) (intptr_t) l;
|
||||
}
|
||||
|
||||
#endif /* _NXT_JAVA_JNI_H_INCLUDED_ */
|
||||
164
src/java/nxt_jni_Context.c
Normal file
164
src/java/nxt_jni_Context.c
Normal file
@@ -0,0 +1,164 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_auto_config.h>
|
||||
|
||||
#include <nxt_unit.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include "nxt_jni.h"
|
||||
#include "nxt_jni_Context.h"
|
||||
#include "nxt_jni_URLClassLoader.h"
|
||||
|
||||
|
||||
static jclass nxt_java_Context_class;
|
||||
static jmethodID nxt_java_Context_start;
|
||||
static jmethodID nxt_java_Context_service;
|
||||
static jmethodID nxt_java_Context_stop;
|
||||
|
||||
static void JNICALL nxt_java_Context_log(JNIEnv *env, jclass cls,
|
||||
jlong ctx_ptr, jstring msg, jint msg_len);
|
||||
static void JNICALL nxt_java_Context_trace(JNIEnv *env, jclass cls,
|
||||
jlong ctx_ptr, jstring msg, jint msg_len);
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initContext(JNIEnv *env, jobject cl)
|
||||
{
|
||||
int res;
|
||||
jclass cls;
|
||||
|
||||
cls = nxt_java_loadClass(env, cl, "nginx.unit.Context");
|
||||
if (cls == NULL) {
|
||||
nxt_unit_warn(NULL, "nginx.unit.Context not found");
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_Context_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
cls = nxt_java_Context_class;
|
||||
|
||||
nxt_java_Context_start = (*env)->GetStaticMethodID(env, cls, "start",
|
||||
"(Ljava/lang/String;[Ljava/net/URL;)Lnginx/unit/Context;");
|
||||
if (nxt_java_Context_start == NULL) {
|
||||
nxt_unit_warn(NULL, "nginx.unit.Context.start() not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nxt_java_Context_service = (*env)->GetMethodID(env, cls, "service",
|
||||
"(Lnginx/unit/Request;Lnginx/unit/Response;)V");
|
||||
if (nxt_java_Context_service == NULL) {
|
||||
nxt_unit_warn(NULL, "nginx.unit.Context.service() not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nxt_java_Context_stop = (*env)->GetMethodID(env, cls, "stop", "()V");
|
||||
if (nxt_java_Context_service == NULL) {
|
||||
nxt_unit_warn(NULL, "nginx.unit.Context.stop() not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
JNINativeMethod context_methods[] = {
|
||||
{ (char *) "log",
|
||||
(char *) "(JLjava/lang/String;I)V",
|
||||
nxt_java_Context_log },
|
||||
|
||||
{ (char *) "trace",
|
||||
(char *) "(JLjava/lang/String;I)V",
|
||||
nxt_java_Context_trace },
|
||||
|
||||
};
|
||||
|
||||
res = (*env)->RegisterNatives(env, nxt_java_Context_class,
|
||||
context_methods,
|
||||
sizeof(context_methods)
|
||||
/ sizeof(context_methods[0]));
|
||||
|
||||
nxt_unit_debug(NULL, "registered Context methods: %d", res);
|
||||
|
||||
if (res != 0) {
|
||||
nxt_unit_warn(NULL, "registering natives for Context failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
|
||||
failed:
|
||||
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
jobject
|
||||
nxt_java_startContext(JNIEnv *env, const char *webapp, jobject classpaths)
|
||||
{
|
||||
jstring webapp_str;
|
||||
|
||||
webapp_str = (*env)->NewStringUTF(env, webapp);
|
||||
if (webapp_str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (*env)->CallStaticObjectMethod(env, nxt_java_Context_class,
|
||||
nxt_java_Context_start, webapp_str,
|
||||
classpaths);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_java_service(JNIEnv *env, jobject ctx, jobject jreq, jobject jresp)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, ctx, nxt_java_Context_service, jreq, jresp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_java_stopContext(JNIEnv *env, jobject ctx)
|
||||
{
|
||||
(*env)->CallVoidMethod(env, ctx, nxt_java_Context_stop);
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_Context_log(JNIEnv *env, jclass cls, jlong ctx_ptr, jstring msg,
|
||||
jint msg_len)
|
||||
{
|
||||
const char *msg_str;
|
||||
nxt_unit_ctx_t *ctx;
|
||||
|
||||
ctx = nxt_jlong2ptr(ctx_ptr);
|
||||
|
||||
msg_str = (*env)->GetStringUTFChars(env, msg, NULL);
|
||||
if (msg_str == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
nxt_unit_log(ctx, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, msg, msg_str);
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_Context_trace(JNIEnv *env, jclass cls, jlong ctx_ptr, jstring msg,
|
||||
jint msg_len)
|
||||
{
|
||||
#if (NXT_DEBUG)
|
||||
const char *msg_str;
|
||||
nxt_unit_ctx_t *ctx;
|
||||
|
||||
ctx = nxt_jlong2ptr(ctx_ptr);
|
||||
|
||||
msg_str = (*env)->GetStringUTFChars(env, msg, NULL);
|
||||
if (msg_str == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
nxt_unit_debug(ctx, "%.*s", msg_len, msg_str);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, msg, msg_str);
|
||||
#endif
|
||||
}
|
||||
23
src/java/nxt_jni_Context.h
Normal file
23
src/java/nxt_jni_Context.h
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_CONTEXT_H_INCLUDED_
|
||||
#define _NXT_JAVA_CONTEXT_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
|
||||
int nxt_java_initContext(JNIEnv *env, jobject cl);
|
||||
|
||||
jobject nxt_java_startContext(JNIEnv *env, const char *webapp,
|
||||
jobject classpaths);
|
||||
|
||||
void nxt_java_service(JNIEnv *env, jobject ctx, jobject jreq, jobject jresp);
|
||||
|
||||
void nxt_java_stopContext(JNIEnv *env, jobject ctx);
|
||||
|
||||
#endif /* _NXT_JAVA_CONTEXT_H_INCLUDED_ */
|
||||
|
||||
153
src/java/nxt_jni_HeaderNamesEnumeration.c
Normal file
153
src/java/nxt_jni_HeaderNamesEnumeration.c
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_auto_config.h>
|
||||
|
||||
#include <nxt_unit.h>
|
||||
#include <nxt_unit_request.h>
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nxt_jni.h"
|
||||
#include "nxt_jni_URLClassLoader.h"
|
||||
#include "nxt_jni_HeaderNamesEnumeration.h"
|
||||
|
||||
|
||||
static jlong JNICALL nxt_java_HeaderNamesEnumeration_nextElementPos(JNIEnv *env,
|
||||
jclass cls, jlong headers_ptr, jlong size, jlong pos);
|
||||
static jstring JNICALL nxt_java_HeaderNamesEnumeration_nextElement(JNIEnv *env,
|
||||
jclass cls, jlong headers_ptr, jlong size, jlong pos);
|
||||
|
||||
|
||||
static jclass nxt_java_HeaderNamesEnumeration_class;
|
||||
static jmethodID nxt_java_HeaderNamesEnumeration_ctor;
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initHeaderNamesEnumeration(JNIEnv *env, jobject cl)
|
||||
{
|
||||
int res;
|
||||
jclass cls;
|
||||
|
||||
cls = nxt_java_loadClass(env, cl, "nginx.unit.HeaderNamesEnumeration");
|
||||
if (cls == NULL) {
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_HeaderNamesEnumeration_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
cls = nxt_java_HeaderNamesEnumeration_class;
|
||||
|
||||
nxt_java_HeaderNamesEnumeration_ctor = (*env)->GetMethodID(env, cls,
|
||||
"<init>", "(JJ)V");
|
||||
if (nxt_java_HeaderNamesEnumeration_ctor == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
JNINativeMethod hnenum_methods[] = {
|
||||
{ (char *) "nextElementPos",
|
||||
(char *) "(JJJ)J",
|
||||
nxt_java_HeaderNamesEnumeration_nextElementPos },
|
||||
|
||||
{ (char *) "nextElement",
|
||||
(char *) "(JJJ)Ljava/lang/String;",
|
||||
nxt_java_HeaderNamesEnumeration_nextElement },
|
||||
};
|
||||
|
||||
res = (*env)->RegisterNatives(env, nxt_java_HeaderNamesEnumeration_class,
|
||||
hnenum_methods,
|
||||
sizeof(hnenum_methods)
|
||||
/ sizeof(hnenum_methods[0]));
|
||||
|
||||
nxt_unit_debug(NULL, "registered HeaderNamesEnumeration methods: %d", res);
|
||||
|
||||
if (res != 0) {
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
}
|
||||
|
||||
|
||||
jobject
|
||||
nxt_java_newHeaderNamesEnumeration(JNIEnv *env, nxt_unit_field_t *f,
|
||||
uint32_t fields_count)
|
||||
{
|
||||
return (*env)->NewObject(env,
|
||||
nxt_java_HeaderNamesEnumeration_class,
|
||||
nxt_java_HeaderNamesEnumeration_ctor, nxt_ptr2jlong(f),
|
||||
(jlong) fields_count);
|
||||
}
|
||||
|
||||
|
||||
static jlong JNICALL
|
||||
nxt_java_HeaderNamesEnumeration_nextElementPos(JNIEnv *env, jclass cls,
|
||||
jlong headers_ptr, jlong size, jlong pos)
|
||||
{
|
||||
nxt_unit_field_t *f;
|
||||
|
||||
f = nxt_jlong2ptr(headers_ptr);
|
||||
|
||||
if (pos >= size) {
|
||||
return size;
|
||||
}
|
||||
|
||||
if (pos > 0) {
|
||||
while (pos < size
|
||||
&& f[pos].hash == f[pos - 1].hash
|
||||
&& f[pos].name_length == f[pos - 1].name_length)
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_HeaderNamesEnumeration_nextElement(JNIEnv *env, jclass cls,
|
||||
jlong headers_ptr, jlong size, jlong pos)
|
||||
{
|
||||
char *name, tmp;
|
||||
jstring res;
|
||||
nxt_unit_field_t *f;
|
||||
|
||||
f = nxt_jlong2ptr(headers_ptr);
|
||||
|
||||
if (pos > 0) {
|
||||
while (pos < size
|
||||
&& f[pos].hash == f[pos - 1].hash
|
||||
&& f[pos].name_length == f[pos - 1].name_length)
|
||||
{
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= size) {
|
||||
nxt_java_throw_NoSuchElementException(env, "pos >= size");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f += pos;
|
||||
|
||||
name = nxt_unit_sptr_get(&f->name);
|
||||
tmp = name[f->name_length];
|
||||
|
||||
if (tmp != '\0') {
|
||||
name[f->name_length] = '\0';
|
||||
}
|
||||
|
||||
res = (*env)->NewStringUTF(env, name);
|
||||
|
||||
if (tmp != '\0') {
|
||||
name[f->name_length] = tmp;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
19
src/java/nxt_jni_HeaderNamesEnumeration.h
Normal file
19
src/java/nxt_jni_HeaderNamesEnumeration.h
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_HEADERNAMESENUMERATION_H_INCLUDED_
|
||||
#define _NXT_JAVA_HEADERNAMESENUMERATION_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit_typedefs.h>
|
||||
|
||||
|
||||
int nxt_java_initHeaderNamesEnumeration(JNIEnv *env, jobject cl);
|
||||
|
||||
jobject nxt_java_newHeaderNamesEnumeration(JNIEnv *env, nxt_unit_field_t *f,
|
||||
uint32_t fields_count);
|
||||
|
||||
#endif /* _NXT_JAVA_HEADERNAMESENUMERATION_H_INCLUDED_ */
|
||||
148
src/java/nxt_jni_HeadersEnumeration.c
Normal file
148
src/java/nxt_jni_HeadersEnumeration.c
Normal file
@@ -0,0 +1,148 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_auto_config.h>
|
||||
|
||||
#include <nxt_unit.h>
|
||||
#include <nxt_unit_request.h>
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nxt_jni.h"
|
||||
#include "nxt_jni_URLClassLoader.h"
|
||||
#include "nxt_jni_HeadersEnumeration.h"
|
||||
|
||||
|
||||
static jclass nxt_java_HeadersEnumeration_class;
|
||||
static jmethodID nxt_java_HeadersEnumeration_ctor;
|
||||
|
||||
|
||||
static jlong JNICALL nxt_java_HeadersEnumeration_nextElementPos(JNIEnv *env,
|
||||
jclass cls, jlong headers_ptr, jlong size, jlong ipos, jlong pos);
|
||||
|
||||
static jstring JNICALL nxt_java_HeadersEnumeration_nextElement(JNIEnv *env,
|
||||
jclass cls, jlong headers_ptr, jlong size, jlong ipos, jlong pos);
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initHeadersEnumeration(JNIEnv *env, jobject cl)
|
||||
{
|
||||
int res;
|
||||
jclass cls;
|
||||
|
||||
cls = nxt_java_loadClass(env, cl, "nginx.unit.HeadersEnumeration");
|
||||
if (cls == NULL) {
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_HeadersEnumeration_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
cls = nxt_java_HeadersEnumeration_class;
|
||||
|
||||
nxt_java_HeadersEnumeration_ctor = (*env)->GetMethodID(env, cls,
|
||||
"<init>", "(JJJ)V");
|
||||
if (nxt_java_HeadersEnumeration_ctor == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
JNINativeMethod methods[] = {
|
||||
{ (char *) "nextElementPos",
|
||||
(char *) "(JJJJ)J",
|
||||
nxt_java_HeadersEnumeration_nextElementPos },
|
||||
|
||||
{ (char *) "nextElement",
|
||||
(char *) "(JJJJ)Ljava/lang/String;",
|
||||
nxt_java_HeadersEnumeration_nextElement },
|
||||
};
|
||||
|
||||
res = (*env)->RegisterNatives(env, nxt_java_HeadersEnumeration_class,
|
||||
methods,
|
||||
sizeof(methods) / sizeof(methods[0]));
|
||||
|
||||
nxt_unit_debug(NULL, "registered HeadersEnumeration methods: %d", res);
|
||||
|
||||
if (res != 0) {
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
}
|
||||
|
||||
|
||||
jobject
|
||||
nxt_java_newHeadersEnumeration(JNIEnv *env, nxt_unit_field_t *f,
|
||||
uint32_t fields_count, uint32_t pos)
|
||||
{
|
||||
return (*env)->NewObject(env,
|
||||
nxt_java_HeadersEnumeration_class,
|
||||
nxt_java_HeadersEnumeration_ctor, nxt_ptr2jlong(f),
|
||||
(jlong) fields_count, (jlong) pos);
|
||||
}
|
||||
|
||||
|
||||
static jlong JNICALL
|
||||
nxt_java_HeadersEnumeration_nextElementPos(JNIEnv *env, jclass cls,
|
||||
jlong headers_ptr, jlong size, jlong ipos, jlong pos)
|
||||
{
|
||||
nxt_unit_field_t *f, *init_field;
|
||||
|
||||
f = nxt_jlong2ptr(headers_ptr);
|
||||
|
||||
init_field = f + ipos;
|
||||
|
||||
if (pos >= size) {
|
||||
return size;
|
||||
}
|
||||
|
||||
f += pos;
|
||||
|
||||
if (f->hash != init_field->hash
|
||||
|| f->name_length != init_field->name_length)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
if (!nxt_java_strcaseeq(nxt_unit_sptr_get(&f->name),
|
||||
nxt_unit_sptr_get(&init_field->name),
|
||||
init_field->name_length))
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_HeadersEnumeration_nextElement(JNIEnv *env, jclass cls,
|
||||
jlong headers_ptr, jlong size, jlong ipos, jlong pos)
|
||||
{
|
||||
nxt_unit_field_t *f, *init_field;
|
||||
|
||||
f = nxt_jlong2ptr(headers_ptr);
|
||||
|
||||
init_field = f + ipos;
|
||||
|
||||
if (pos >= size) {
|
||||
nxt_java_throw_IOException(env, "pos >= size");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f += pos;
|
||||
|
||||
if (f->hash != init_field->hash
|
||||
|| f->name_length != init_field->name_length)
|
||||
{
|
||||
nxt_java_throw_IOException(env, "f->hash != hash");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nxt_java_newString(env, nxt_unit_sptr_get(&f->value),
|
||||
f->value_length);
|
||||
}
|
||||
19
src/java/nxt_jni_HeadersEnumeration.h
Normal file
19
src/java/nxt_jni_HeadersEnumeration.h
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_HEADERSENUMERATION_H_INCLUDED_
|
||||
#define _NXT_JAVA_HEADERSENUMERATION_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit_typedefs.h>
|
||||
|
||||
|
||||
int nxt_java_initHeadersEnumeration(JNIEnv *env, jobject cl);
|
||||
|
||||
jobject nxt_java_newHeadersEnumeration(JNIEnv *env, nxt_unit_field_t *f,
|
||||
uint32_t fields_count, uint32_t pos);
|
||||
|
||||
#endif /* _NXT_JAVA_HEADERSENUMERATION_H_INCLUDED_ */
|
||||
230
src/java/nxt_jni_InputStream.c
Normal file
230
src/java/nxt_jni_InputStream.c
Normal file
@@ -0,0 +1,230 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_auto_config.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nxt_jni.h"
|
||||
#include "nxt_jni_InputStream.h"
|
||||
#include "nxt_jni_URLClassLoader.h"
|
||||
|
||||
|
||||
static jint JNICALL nxt_java_InputStream_readLine(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jarray b, jint off, jint len);
|
||||
static jboolean JNICALL nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr);
|
||||
static jint JNICALL nxt_java_InputStream_readByte(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr);
|
||||
static jint JNICALL nxt_java_InputStream_read(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jarray b, jint off, jint len);
|
||||
static jlong JNICALL nxt_java_InputStream_skip(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jlong n);
|
||||
static jint JNICALL nxt_java_InputStream_available(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr);
|
||||
|
||||
|
||||
static jclass nxt_java_InputStream_class;
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initInputStream(JNIEnv *env, jobject cl)
|
||||
{
|
||||
int res;
|
||||
jclass cls;
|
||||
|
||||
cls = nxt_java_loadClass(env, cl, "nginx.unit.InputStream");
|
||||
if (cls == NULL) {
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_InputStream_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
|
||||
JNINativeMethod is_methods[] = {
|
||||
{ (char *) "readLine",
|
||||
(char *) "(J[BII)I",
|
||||
nxt_java_InputStream_readLine },
|
||||
|
||||
{ (char *) "isFinished",
|
||||
(char *) "(J)Z",
|
||||
nxt_java_InputStream_isFinished },
|
||||
|
||||
{ (char *) "read",
|
||||
(char *) "(J)I",
|
||||
nxt_java_InputStream_readByte },
|
||||
|
||||
{ (char *) "read",
|
||||
(char *) "(J[BII)I",
|
||||
nxt_java_InputStream_read },
|
||||
|
||||
{ (char *) "skip",
|
||||
(char *) "(JJ)J",
|
||||
nxt_java_InputStream_skip },
|
||||
|
||||
{ (char *) "available",
|
||||
(char *) "(J)I",
|
||||
nxt_java_InputStream_available },
|
||||
};
|
||||
|
||||
res = (*env)->RegisterNatives(env, nxt_java_InputStream_class,
|
||||
is_methods,
|
||||
sizeof(is_methods) / sizeof(is_methods[0]));
|
||||
|
||||
nxt_unit_debug(NULL, "registered InputStream methods: %d", res);
|
||||
|
||||
if (res != 0) {
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_InputStream_readLine(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jarray out, jint off, jint len)
|
||||
{
|
||||
char *p;
|
||||
jint size, b_size;
|
||||
uint8_t *data;
|
||||
ssize_t res;
|
||||
nxt_unit_buf_t *b;
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
size = 0;
|
||||
|
||||
for (b = req->content_buf; b; b = nxt_unit_buf_next(b)) {
|
||||
b_size = b->end - b->free;
|
||||
p = memchr(b->free, '\n', b_size);
|
||||
|
||||
if (p != NULL) {
|
||||
p++;
|
||||
size += p - b->free;
|
||||
break;
|
||||
}
|
||||
|
||||
size += b_size;
|
||||
|
||||
if (size >= len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len = len < size ? len : size;
|
||||
|
||||
data = (*env)->GetPrimitiveArrayCritical(env, out, NULL);
|
||||
|
||||
res = nxt_unit_request_read(req, data + off, len);
|
||||
|
||||
nxt_unit_req_debug(req, "readLine '%.*s'", res, (char *) data + off);
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, out, data, 0);
|
||||
|
||||
return res > 0 ? res : -1;
|
||||
}
|
||||
|
||||
|
||||
static jboolean JNICALL
|
||||
nxt_java_InputStream_isFinished(JNIEnv *env, jclass cls, jlong req_info_ptr)
|
||||
{
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
return req->content_length == 0;
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_InputStream_readByte(JNIEnv *env, jclass cls, jlong req_info_ptr)
|
||||
{
|
||||
uint8_t b;
|
||||
ssize_t size;
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
size = nxt_unit_request_read(req, &b, 1);
|
||||
|
||||
return size == 1 ? b : -1;
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_InputStream_read(JNIEnv *env, jclass cls, jlong req_info_ptr,
|
||||
jarray b, jint off, jint len)
|
||||
{
|
||||
uint8_t *data;
|
||||
ssize_t res;
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
data = (*env)->GetPrimitiveArrayCritical(env, b, NULL);
|
||||
|
||||
res = nxt_unit_request_read(req, data + off, len);
|
||||
|
||||
nxt_unit_req_debug(req, "read '%.*s'", res, (char *) data + off);
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, b, data, 0);
|
||||
|
||||
return res > 0 ? res : -1;
|
||||
}
|
||||
|
||||
|
||||
static jlong JNICALL
|
||||
nxt_java_InputStream_skip(JNIEnv *env, jclass cls, jlong req_info_ptr, jlong n)
|
||||
{
|
||||
size_t rest, b_size;
|
||||
nxt_unit_buf_t *buf;
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
rest = n;
|
||||
|
||||
buf = req->content_buf;
|
||||
|
||||
while (buf != NULL) {
|
||||
b_size = buf->end - buf->free;
|
||||
b_size = rest < b_size ? rest : b_size;
|
||||
|
||||
buf->free += b_size;
|
||||
rest -= b_size;
|
||||
|
||||
if (rest == 0) {
|
||||
if (buf->end == buf->free) {
|
||||
buf = nxt_unit_buf_next(buf);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
buf = nxt_unit_buf_next(buf);
|
||||
}
|
||||
|
||||
n = n < (jlong) req->content_length ? n : (jlong) req->content_length;
|
||||
|
||||
req->content_length -= n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_InputStream_available(JNIEnv *env, jclass cls, jlong req_info_ptr)
|
||||
{
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
return req->content_length;
|
||||
}
|
||||
15
src/java/nxt_jni_InputStream.h
Normal file
15
src/java/nxt_jni_InputStream.h
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_INPUTSTREAM_H_INCLUDED_
|
||||
#define _NXT_JAVA_INPUTSTREAM_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
|
||||
int nxt_java_initInputStream(JNIEnv *env, jobject cl);
|
||||
|
||||
#endif /* _NXT_JAVA_INPUTSTREAM_H_INCLUDED_ */
|
||||
236
src/java/nxt_jni_OutputStream.c
Normal file
236
src/java/nxt_jni_OutputStream.c
Normal file
@@ -0,0 +1,236 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_auto_config.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit.h>
|
||||
|
||||
#include "nxt_jni.h"
|
||||
#include "nxt_jni_OutputStream.h"
|
||||
#include "nxt_jni_URLClassLoader.h"
|
||||
|
||||
|
||||
static void JNICALL nxt_java_OutputStream_writeByte(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jint b);
|
||||
static nxt_unit_buf_t *nxt_java_OutputStream_req_buf(JNIEnv *env,
|
||||
nxt_unit_request_info_t *req);
|
||||
static void JNICALL nxt_java_OutputStream_write(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jarray b, jint off, jint len);
|
||||
static void JNICALL nxt_java_OutputStream_flush(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr);
|
||||
static void JNICALL nxt_java_OutputStream_close(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr);
|
||||
|
||||
|
||||
static jclass nxt_java_OutputStream_class;
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initOutputStream(JNIEnv *env, jobject cl)
|
||||
{
|
||||
int res;
|
||||
jclass cls;
|
||||
|
||||
cls = nxt_java_loadClass(env, cl, "nginx.unit.OutputStream");
|
||||
if (cls == NULL) {
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_OutputStream_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
|
||||
cls = nxt_java_OutputStream_class;
|
||||
|
||||
JNINativeMethod os_methods[] = {
|
||||
{ (char *) "write",
|
||||
(char *) "(JI)V",
|
||||
nxt_java_OutputStream_writeByte },
|
||||
|
||||
{ (char *) "write",
|
||||
(char *) "(J[BII)V",
|
||||
nxt_java_OutputStream_write },
|
||||
|
||||
{ (char *) "flush",
|
||||
(char *) "(J)V",
|
||||
nxt_java_OutputStream_flush },
|
||||
|
||||
{ (char *) "close",
|
||||
(char *) "(J)V",
|
||||
nxt_java_OutputStream_close },
|
||||
};
|
||||
|
||||
res = (*env)->RegisterNatives(env, nxt_java_OutputStream_class,
|
||||
os_methods,
|
||||
sizeof(os_methods) / sizeof(os_methods[0]));
|
||||
|
||||
nxt_unit_debug(NULL, "registered OutputStream methods: %d", res);
|
||||
|
||||
if (res != 0) {
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_OutputStream_writeByte(JNIEnv *env, jclass cls, jlong req_info_ptr,
|
||||
jint b)
|
||||
{
|
||||
nxt_unit_buf_t *buf;
|
||||
nxt_unit_request_info_t *req;
|
||||
nxt_java_request_data_t *data;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
data = req->data;
|
||||
|
||||
buf = nxt_java_OutputStream_req_buf(env, req);
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
*buf->free++ = b;
|
||||
|
||||
if ((uint32_t) (buf->free - buf->start) >= data->buf_size) {
|
||||
nxt_java_OutputStream_flush_buf(env, req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nxt_java_OutputStream_flush_buf(JNIEnv *env, nxt_unit_request_info_t *req)
|
||||
{
|
||||
int rc;
|
||||
nxt_java_request_data_t *data;
|
||||
|
||||
data = req->data;
|
||||
|
||||
if (!nxt_unit_response_is_init(req)) {
|
||||
rc = nxt_unit_response_init(req, 200, 0, 0);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_java_throw_IOException(env, "Failed to allocate response");
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nxt_unit_response_is_sent(req)) {
|
||||
rc = nxt_unit_response_send(req);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_java_throw_IOException(env, "Failed to send response headers");
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->buf != NULL) {
|
||||
rc = nxt_unit_buf_send(data->buf);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_java_throw_IOException(env, "Failed to send buffer");
|
||||
|
||||
} else {
|
||||
data->buf = NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
rc = NXT_UNIT_OK;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static nxt_unit_buf_t *
|
||||
nxt_java_OutputStream_req_buf(JNIEnv *env, nxt_unit_request_info_t *req)
|
||||
{
|
||||
uint32_t size;
|
||||
nxt_unit_buf_t *buf;
|
||||
nxt_java_request_data_t *data;
|
||||
|
||||
data = req->data;
|
||||
buf = data->buf;
|
||||
|
||||
if (buf == NULL || buf->free >= buf->end) {
|
||||
size = data->buf_size == 0 ? nxt_unit_buf_min() : data->buf_size;
|
||||
|
||||
buf = nxt_unit_response_buf_alloc(req, size);
|
||||
if (buf == NULL) {
|
||||
nxt_java_throw_IOException(env, "Failed to allocate buffer");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->buf = buf;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_OutputStream_write(JNIEnv *env, jclass cls, jlong req_info_ptr,
|
||||
jarray b, jint off, jint len)
|
||||
{
|
||||
int rc;
|
||||
jint copy;
|
||||
uint8_t *ptr;
|
||||
nxt_unit_buf_t *buf;
|
||||
nxt_unit_request_info_t *req;
|
||||
nxt_java_request_data_t *data;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
data = req->data;
|
||||
|
||||
ptr = (*env)->GetPrimitiveArrayCritical(env, b, NULL);
|
||||
|
||||
while (len > 0) {
|
||||
buf = nxt_java_OutputStream_req_buf(env, req);
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
copy = buf->end - buf->free;
|
||||
copy = copy < len ? copy : len;
|
||||
|
||||
memcpy(buf->free, ptr + off, copy);
|
||||
buf->free += copy;
|
||||
|
||||
len -= copy;
|
||||
off += copy;
|
||||
|
||||
if ((uint32_t) (buf->free - buf->start) >= data->buf_size) {
|
||||
rc = nxt_java_OutputStream_flush_buf(env, req);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, b, ptr, 0);
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_OutputStream_flush(JNIEnv *env, jclass cls, jlong req_info_ptr)
|
||||
{
|
||||
nxt_unit_request_info_t *req;
|
||||
nxt_java_request_data_t *data;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
data = req->data;
|
||||
|
||||
if (data->buf != NULL && data->buf->free > data->buf->start) {
|
||||
nxt_java_OutputStream_flush_buf(env, req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_OutputStream_close(JNIEnv *env, jclass cls, jlong req_info_ptr)
|
||||
{
|
||||
nxt_java_OutputStream_flush_buf(env, nxt_jlong2ptr(req_info_ptr));
|
||||
}
|
||||
17
src/java/nxt_jni_OutputStream.h
Normal file
17
src/java/nxt_jni_OutputStream.h
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_OUTPUTSTREAM_H_INCLUDED_
|
||||
#define _NXT_JAVA_OUTPUTSTREAM_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
|
||||
int nxt_java_initOutputStream(JNIEnv *env, jobject cl);
|
||||
|
||||
int nxt_java_OutputStream_flush_buf(JNIEnv *env, nxt_unit_request_info_t *req);
|
||||
|
||||
#endif /* _NXT_JAVA_OUTPUTSTREAM_H_INCLUDED_ */
|
||||
658
src/java/nxt_jni_Request.c
Normal file
658
src/java/nxt_jni_Request.c
Normal file
@@ -0,0 +1,658 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_auto_config.h>
|
||||
|
||||
#include <nxt_unit.h>
|
||||
#include <nxt_unit_request.h>
|
||||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nxt_jni.h"
|
||||
#include "nxt_jni_Request.h"
|
||||
#include "nxt_jni_URLClassLoader.h"
|
||||
#include "nxt_jni_HeadersEnumeration.h"
|
||||
#include "nxt_jni_HeaderNamesEnumeration.h"
|
||||
|
||||
|
||||
static jstring JNICALL nxt_java_Request_getHeader(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr, jstring name, jint name_len);
|
||||
static jobject JNICALL nxt_java_Request_getHeaderNames(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jobject JNICALL nxt_java_Request_getHeaders(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr, jstring name, jint name_len);
|
||||
static jint JNICALL nxt_java_Request_getIntHeader(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr, jstring name, jint name_len);
|
||||
static jstring JNICALL nxt_java_Request_getMethod(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getQueryString(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getRequestURI(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jlong JNICALL nxt_java_Request_getContentLength(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getContentType(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getLocalName(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jint JNICALL nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getProtocol(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getRemoteAddr(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getRemoteHost(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jint JNICALL nxt_java_Request_getRemotePort(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getScheme(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jstring JNICALL nxt_java_Request_getServerName(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static jint JNICALL nxt_java_Request_getServerPort(JNIEnv *env, jclass cls,
|
||||
jlong req_ptr);
|
||||
static void JNICALL nxt_java_Request_log(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jstring msg, jint msg_len);
|
||||
static void JNICALL nxt_java_Request_trace(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr, jstring msg, jint msg_len);
|
||||
static jobject JNICALL nxt_java_Request_getResponse(JNIEnv *env, jclass cls,
|
||||
jlong req_info_ptr);
|
||||
|
||||
|
||||
static jclass nxt_java_Request_class;
|
||||
static jmethodID nxt_java_Request_ctor;
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initRequest(JNIEnv *env, jobject cl)
|
||||
{
|
||||
int res;
|
||||
jclass cls;
|
||||
|
||||
cls = nxt_java_loadClass(env, cl, "nginx.unit.Request");
|
||||
if (cls == NULL) {
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_Request_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
cls = nxt_java_Request_class;
|
||||
|
||||
nxt_java_Request_ctor = (*env)->GetMethodID(env, cls, "<init>", "(Lnginx/unit/Context;JJ)V");
|
||||
if (nxt_java_Request_ctor == NULL) {
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
JNINativeMethod request_methods[] = {
|
||||
{ (char *) "getHeader",
|
||||
(char *) "(JLjava/lang/String;I)Ljava/lang/String;",
|
||||
nxt_java_Request_getHeader },
|
||||
|
||||
{ (char *) "getHeaderNames",
|
||||
(char *) "(J)Ljava/util/Enumeration;",
|
||||
nxt_java_Request_getHeaderNames },
|
||||
|
||||
{ (char *) "getHeaders",
|
||||
(char *) "(JLjava/lang/String;I)Ljava/util/Enumeration;",
|
||||
nxt_java_Request_getHeaders },
|
||||
|
||||
{ (char *) "getIntHeader",
|
||||
(char *) "(JLjava/lang/String;I)I",
|
||||
nxt_java_Request_getIntHeader },
|
||||
|
||||
{ (char *) "getMethod",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getMethod },
|
||||
|
||||
{ (char *) "getQueryString",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getQueryString },
|
||||
|
||||
{ (char *) "getRequestURI",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getRequestURI },
|
||||
|
||||
{ (char *) "getContentLength",
|
||||
(char *) "(J)J",
|
||||
nxt_java_Request_getContentLength },
|
||||
|
||||
{ (char *) "getContentType",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getContentType },
|
||||
|
||||
{ (char *) "getLocalAddr",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getLocalAddr },
|
||||
|
||||
{ (char *) "getLocalName",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getLocalName },
|
||||
|
||||
{ (char *) "getLocalPort",
|
||||
(char *) "(J)I",
|
||||
nxt_java_Request_getLocalPort },
|
||||
|
||||
{ (char *) "getProtocol",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getProtocol },
|
||||
|
||||
{ (char *) "getRemoteAddr",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getRemoteAddr },
|
||||
|
||||
{ (char *) "getRemoteHost",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getRemoteHost },
|
||||
|
||||
{ (char *) "getRemotePort",
|
||||
(char *) "(J)I",
|
||||
nxt_java_Request_getRemotePort },
|
||||
|
||||
{ (char *) "getScheme",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getScheme },
|
||||
|
||||
{ (char *) "getServerName",
|
||||
(char *) "(J)Ljava/lang/String;",
|
||||
nxt_java_Request_getServerName },
|
||||
|
||||
{ (char *) "getServerPort",
|
||||
(char *) "(J)I",
|
||||
nxt_java_Request_getServerPort },
|
||||
|
||||
{ (char *) "log",
|
||||
(char *) "(JLjava/lang/String;I)V",
|
||||
nxt_java_Request_log },
|
||||
|
||||
{ (char *) "trace",
|
||||
(char *) "(JLjava/lang/String;I)V",
|
||||
nxt_java_Request_trace },
|
||||
|
||||
{ (char *) "getResponse",
|
||||
(char *) "(J)Lnginx/unit/Response;",
|
||||
nxt_java_Request_getResponse },
|
||||
|
||||
};
|
||||
|
||||
res = (*env)->RegisterNatives(env, nxt_java_Request_class,
|
||||
request_methods,
|
||||
sizeof(request_methods) / sizeof(request_methods[0]));
|
||||
|
||||
nxt_unit_debug(NULL, "registered Request methods: %d", res);
|
||||
|
||||
if (res != 0) {
|
||||
nxt_unit_warn(NULL, "registering natives for Request failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
res = nxt_java_initHeadersEnumeration(env, cl);
|
||||
if (res != NXT_UNIT_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
res = nxt_java_initHeaderNamesEnumeration(env, cl);
|
||||
if (res != NXT_UNIT_OK) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
|
||||
failed:
|
||||
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
jobject
|
||||
nxt_java_newRequest(JNIEnv *env, jobject ctx, nxt_unit_request_info_t *req)
|
||||
{
|
||||
return (*env)->NewObject(env, nxt_java_Request_class,
|
||||
nxt_java_Request_ctor, ctx, nxt_ptr2jlong(req),
|
||||
nxt_ptr2jlong(req->request));
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getHeader(JNIEnv *env, jclass cls, jlong req_ptr,
|
||||
jstring name, jint name_len)
|
||||
{
|
||||
const char *name_str;
|
||||
nxt_unit_field_t *f;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
name_str = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
if (name_str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
f = nxt_java_findHeader(r->fields, r->fields + r->fields_count,
|
||||
name_str, name_len);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, name, name_str);
|
||||
|
||||
if (f == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value));
|
||||
}
|
||||
|
||||
|
||||
static jobject JNICALL
|
||||
nxt_java_Request_getHeaderNames(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
return nxt_java_newHeaderNamesEnumeration(env, r->fields, r->fields_count);
|
||||
}
|
||||
|
||||
|
||||
static jobject JNICALL
|
||||
nxt_java_Request_getHeaders(JNIEnv *env, jclass cls, jlong req_ptr,
|
||||
jstring name, jint name_len)
|
||||
{
|
||||
const char *name_str;
|
||||
nxt_unit_field_t *f;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
name_str = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
if (name_str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
f = nxt_java_findHeader(r->fields, r->fields + r->fields_count,
|
||||
name_str, name_len);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, name, name_str);
|
||||
|
||||
if (f == NULL) {
|
||||
f = r->fields + r->fields_count;
|
||||
}
|
||||
|
||||
return nxt_java_newHeadersEnumeration(env, r->fields, r->fields_count,
|
||||
f - r->fields);
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_Request_getIntHeader(JNIEnv *env, jclass cls, jlong req_ptr,
|
||||
jstring name, jint name_len)
|
||||
{
|
||||
jint res;
|
||||
char *value, *end;
|
||||
const char *name_str;
|
||||
nxt_unit_field_t *f;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
res = -1;
|
||||
|
||||
name_str = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
if (name_str == NULL) {
|
||||
return res;
|
||||
}
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
f = nxt_java_findHeader(r->fields, r->fields + r->fields_count,
|
||||
name_str, name_len);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, name, name_str);
|
||||
|
||||
if (f == NULL) {
|
||||
return res;
|
||||
}
|
||||
|
||||
value = nxt_unit_sptr_get(&f->value);
|
||||
end = value + f->value_length;
|
||||
|
||||
res = strtol(value, &end, 10);
|
||||
|
||||
if (end < value + f->value_length) {
|
||||
// TODO throw NumberFormatException.forInputString(value)
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getMethod(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->method));
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getQueryString(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
char *query;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
if (r->query.offset != 0) {
|
||||
query = nxt_unit_sptr_get(&r->query);
|
||||
return (*env)->NewStringUTF(env, query);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getRequestURI(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
char *target, *query;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
target = nxt_unit_sptr_get(&r->target);
|
||||
|
||||
if (r->query.offset != 0) {
|
||||
query = nxt_unit_sptr_get(&r->query);
|
||||
return nxt_java_newString(env, target, query - target - 1);
|
||||
}
|
||||
|
||||
return (*env)->NewStringUTF(env, target);
|
||||
}
|
||||
|
||||
|
||||
static jlong JNICALL
|
||||
nxt_java_Request_getContentLength(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
return r->content_length;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getContentType(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
nxt_unit_field_t *f;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
if (r->content_type_field != NXT_UNIT_NONE_FIELD) {
|
||||
f = r->fields + r->content_type_field;
|
||||
|
||||
return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&f->value));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getLocalAddr(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
return nxt_java_newString(env, nxt_unit_sptr_get(&r->local),
|
||||
r->local_length);
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getLocalName(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
char *local, *colon;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
local = nxt_unit_sptr_get(&r->local);
|
||||
colon = memchr(local, ':', r->local_length);
|
||||
|
||||
if (colon == NULL) {
|
||||
colon = local + r->local_length;
|
||||
}
|
||||
|
||||
return nxt_java_newString(env, local, colon - local);
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_Request_getLocalPort(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
jint res;
|
||||
char *local, *colon, tmp;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
local = nxt_unit_sptr_get(&r->local);
|
||||
colon = memchr(local, ':', r->local_length);
|
||||
|
||||
if (colon == NULL) {
|
||||
return 80;
|
||||
}
|
||||
|
||||
tmp = local[r->local_length];
|
||||
|
||||
local[r->local_length] = '\0';
|
||||
|
||||
res = strtol(colon + 1, NULL, 10);
|
||||
|
||||
local[r->local_length] = tmp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getProtocol(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
return (*env)->NewStringUTF(env, nxt_unit_sptr_get(&r->version));
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getRemoteAddr(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
return nxt_java_newString(env, nxt_unit_sptr_get(&r->remote),
|
||||
r->remote_length);
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getRemoteHost(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
char *remote, *colon;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
remote = nxt_unit_sptr_get(&r->remote);
|
||||
colon = memchr(remote, ':', r->remote_length);
|
||||
|
||||
if (colon == NULL) {
|
||||
colon = remote + r->remote_length;
|
||||
}
|
||||
|
||||
return nxt_java_newString(env, remote, colon - remote);
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_Request_getRemotePort(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
jint res;
|
||||
char *remote, *colon, tmp;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
remote = nxt_unit_sptr_get(&r->remote);
|
||||
colon = memchr(remote, ':', r->remote_length);
|
||||
|
||||
if (colon == NULL) {
|
||||
return 80;
|
||||
}
|
||||
|
||||
tmp = remote[r->remote_length];
|
||||
|
||||
remote[r->remote_length] = '\0';
|
||||
|
||||
res = strtol(colon + 1, NULL, 10);
|
||||
|
||||
remote[r->remote_length] = tmp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getScheme(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
return (*env)->NewStringUTF(env, "http");
|
||||
}
|
||||
|
||||
|
||||
static jstring JNICALL
|
||||
nxt_java_Request_getServerName(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
char *host, *colon;
|
||||
nxt_unit_field_t *f;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
f = nxt_java_findHeader(r->fields, r->fields + r->fields_count,
|
||||
"Host", 4);
|
||||
if (f != NULL) {
|
||||
host = nxt_unit_sptr_get(&f->value);
|
||||
|
||||
colon = memchr(host, ':', f->value_length);
|
||||
|
||||
if (colon == NULL) {
|
||||
colon = host + f->value_length;
|
||||
}
|
||||
|
||||
return nxt_java_newString(env, host, colon - host);
|
||||
}
|
||||
|
||||
return nxt_java_Request_getLocalName(env, cls, req_ptr);
|
||||
}
|
||||
|
||||
|
||||
static jint JNICALL
|
||||
nxt_java_Request_getServerPort(JNIEnv *env, jclass cls, jlong req_ptr)
|
||||
{
|
||||
jint res;
|
||||
char *host, *colon, tmp;
|
||||
nxt_unit_field_t *f;
|
||||
nxt_unit_request_t *r;
|
||||
|
||||
r = nxt_jlong2ptr(req_ptr);
|
||||
|
||||
f = nxt_java_findHeader(r->fields, r->fields + r->fields_count,
|
||||
"Host", 4);
|
||||
if (f != NULL) {
|
||||
host = nxt_unit_sptr_get(&f->value);
|
||||
|
||||
colon = memchr(host, ':', f->value_length);
|
||||
|
||||
if (colon == NULL) {
|
||||
return 80;
|
||||
}
|
||||
|
||||
tmp = host[f->value_length];
|
||||
|
||||
host[f->value_length] = '\0';
|
||||
|
||||
res = strtol(colon + 1, NULL, 10);
|
||||
|
||||
host[f->value_length] = tmp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return nxt_java_Request_getLocalPort(env, cls, req_ptr);
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_Request_log(JNIEnv *env, jclass cls, jlong req_info_ptr, jstring msg,
|
||||
jint msg_len)
|
||||
{
|
||||
const char *msg_str;
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
msg_str = (*env)->GetStringUTFChars(env, msg, NULL);
|
||||
if (msg_str == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
nxt_unit_req_log(req, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, msg, msg_str);
|
||||
}
|
||||
|
||||
|
||||
static void JNICALL
|
||||
nxt_java_Request_trace(JNIEnv *env, jclass cls, jlong req_info_ptr, jstring msg,
|
||||
jint msg_len)
|
||||
{
|
||||
#if (NXT_DEBUG)
|
||||
const char *msg_str;
|
||||
nxt_unit_request_info_t *req;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
|
||||
msg_str = (*env)->GetStringUTFChars(env, msg, NULL);
|
||||
if (msg_str == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
nxt_unit_req_debug(req, "%.*s", msg_len, msg_str);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, msg, msg_str);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static jobject JNICALL
|
||||
nxt_java_Request_getResponse(JNIEnv *env, jclass cls, jlong req_info_ptr)
|
||||
{
|
||||
nxt_unit_request_info_t *req;
|
||||
nxt_java_request_data_t *data;
|
||||
|
||||
req = nxt_jlong2ptr(req_info_ptr);
|
||||
data = req->data;
|
||||
|
||||
return data->jresp;
|
||||
}
|
||||
18
src/java/nxt_jni_Request.h
Normal file
18
src/java/nxt_jni_Request.h
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_REQUEST_H_INCLUDED_
|
||||
#define _NXT_JAVA_REQUEST_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit_typedefs.h>
|
||||
|
||||
|
||||
int nxt_java_initRequest(JNIEnv *env, jobject cl);
|
||||
|
||||
jobject nxt_java_newRequest(JNIEnv *env, jobject ctx, nxt_unit_request_info_t *req);
|
||||
|
||||
#endif /* _NXT_JAVA_REQUEST_H_INCLUDED_ */
|
||||
1105
src/java/nxt_jni_Response.c
Normal file
1105
src/java/nxt_jni_Response.c
Normal file
File diff suppressed because it is too large
Load Diff
18
src/java/nxt_jni_Response.h
Normal file
18
src/java/nxt_jni_Response.h
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_RESPONSE_H_INCLUDED_
|
||||
#define _NXT_JAVA_RESPONSE_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
#include <nxt_unit_typedefs.h>
|
||||
|
||||
|
||||
int nxt_java_initResponse(JNIEnv *env, jobject cl);
|
||||
|
||||
jobject nxt_java_newResponse(JNIEnv *env, nxt_unit_request_info_t *req);
|
||||
|
||||
#endif /* _NXT_JAVA_RESPONSE_H_INCLUDED_ */
|
||||
94
src/java/nxt_jni_Thread.c
Normal file
94
src/java/nxt_jni_Thread.c
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_unit.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include "nxt_jni_Thread.h"
|
||||
|
||||
|
||||
static jclass nxt_java_Thread_class;
|
||||
static jmethodID nxt_java_Thread_currentThread;
|
||||
static jmethodID nxt_java_Thread_getContextClassLoader;
|
||||
static jmethodID nxt_java_Thread_setContextClassLoader;
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initThread(JNIEnv *env)
|
||||
{
|
||||
jclass cls;
|
||||
|
||||
cls = (*env)->FindClass(env, "java/lang/Thread");
|
||||
if (cls == NULL) {
|
||||
nxt_unit_warn(NULL, "java.lang.Thread not found");
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_Thread_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
cls = nxt_java_Thread_class;
|
||||
|
||||
nxt_java_Thread_currentThread = (*env)->GetStaticMethodID(env, cls,
|
||||
"currentThread", "()Ljava/lang/Thread;");
|
||||
if (nxt_java_Thread_currentThread == NULL) {
|
||||
nxt_unit_warn(NULL, "java.lang.Thread.currentThread() not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nxt_java_Thread_getContextClassLoader = (*env)->GetMethodID(env, cls,
|
||||
"getContextClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
if (nxt_java_Thread_getContextClassLoader == NULL) {
|
||||
nxt_unit_warn(NULL, "java.lang.Thread.getContextClassLoader() "
|
||||
"not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nxt_java_Thread_setContextClassLoader = (*env)->GetMethodID(env, cls,
|
||||
"setContextClassLoader", "(Ljava/lang/ClassLoader;)V");
|
||||
if (nxt_java_Thread_setContextClassLoader == NULL) {
|
||||
nxt_unit_warn(NULL, "java.lang.Thread.setContextClassLoader() "
|
||||
"not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
|
||||
failed:
|
||||
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
nxt_java_setContextClassLoader(JNIEnv *env, jobject cl)
|
||||
{
|
||||
jobject thread;
|
||||
|
||||
thread = (*env)->CallStaticObjectMethod(env, nxt_java_Thread_class,
|
||||
nxt_java_Thread_currentThread);
|
||||
|
||||
if (thread == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*env)->CallVoidMethod(env, thread, nxt_java_Thread_setContextClassLoader,
|
||||
cl);
|
||||
}
|
||||
|
||||
jobject
|
||||
nxt_java_getContextClassLoader(JNIEnv *env)
|
||||
{
|
||||
jobject thread;
|
||||
|
||||
thread = (*env)->CallStaticObjectMethod(env, nxt_java_Thread_class,
|
||||
nxt_java_Thread_currentThread);
|
||||
|
||||
if (thread == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (*env)->CallObjectMethod(env, thread,
|
||||
nxt_java_Thread_getContextClassLoader);
|
||||
}
|
||||
20
src/java/nxt_jni_Thread.h
Normal file
20
src/java/nxt_jni_Thread.h
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_THREAD_H_INCLUDED_
|
||||
#define _NXT_JAVA_THREAD_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
|
||||
int nxt_java_initThread(JNIEnv *env);
|
||||
|
||||
void nxt_java_setContextClassLoader(JNIEnv *env, jobject cl);
|
||||
|
||||
jobject nxt_java_getContextClassLoader(JNIEnv *env);
|
||||
|
||||
#endif /* _NXT_JAVA_THREAD_H_INCLUDED_ */
|
||||
|
||||
187
src/java/nxt_jni_URLClassLoader.c
Normal file
187
src/java/nxt_jni_URLClassLoader.c
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_unit.h>
|
||||
#include <jni.h>
|
||||
|
||||
#include "nxt_jni_URLClassLoader.h"
|
||||
|
||||
|
||||
static jclass nxt_java_URLClassLoader_class;
|
||||
static jmethodID nxt_java_URLClassLoader_ctor;
|
||||
static jmethodID nxt_java_URLClassLoader_parent_ctor;
|
||||
static jmethodID nxt_java_URLClassLoader_loadClass;
|
||||
static jmethodID nxt_java_URLClassLoader_addURL;
|
||||
|
||||
static jclass nxt_java_URL_class;
|
||||
static jmethodID nxt_java_URL_ctor;
|
||||
|
||||
|
||||
int
|
||||
nxt_java_initURLClassLoader(JNIEnv *env)
|
||||
{
|
||||
jclass cls;
|
||||
|
||||
cls = (*env)->FindClass(env, "java/net/URLClassLoader");
|
||||
if (cls == NULL) {
|
||||
nxt_unit_warn(NULL, "java.net.URLClassLoader not found");
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_URLClassLoader_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
cls = nxt_java_URLClassLoader_class;
|
||||
|
||||
nxt_java_URLClassLoader_ctor = (*env)->GetMethodID(env, cls,
|
||||
"<init>", "([Ljava/net/URL;)V");
|
||||
if (nxt_java_URLClassLoader_ctor == NULL) {
|
||||
nxt_unit_warn(NULL, "java.net.URLClassLoader constructor not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nxt_java_URLClassLoader_parent_ctor = (*env)->GetMethodID(env, cls,
|
||||
"<init>", "([Ljava/net/URL;Ljava/lang/ClassLoader;)V");
|
||||
if (nxt_java_URLClassLoader_ctor == NULL) {
|
||||
nxt_unit_warn(NULL, "java.net.URLClassLoader constructor not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nxt_java_URLClassLoader_loadClass = (*env)->GetMethodID(env, cls,
|
||||
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
if (nxt_java_URLClassLoader_loadClass == NULL) {
|
||||
nxt_unit_warn(NULL, "java.net.URLClassLoader.loadClass not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nxt_java_URLClassLoader_addURL = (*env)->GetMethodID(env, cls,
|
||||
"addURL", "(Ljava/net/URL;)V");
|
||||
if (nxt_java_URLClassLoader_addURL == NULL) {
|
||||
nxt_unit_warn(NULL, "java.net.URLClassLoader.addURL not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env, "java/net/URL");
|
||||
if (cls == NULL) {
|
||||
nxt_unit_warn(NULL, "java.net.URL not found");
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
nxt_java_URL_class = (*env)->NewGlobalRef(env, cls);
|
||||
(*env)->DeleteLocalRef(env, cls);
|
||||
cls = nxt_java_URL_class;
|
||||
|
||||
nxt_java_URL_ctor = (*env)->GetMethodID(env, cls,
|
||||
"<init>", "(Ljava/lang/String;)V");
|
||||
if (nxt_java_URL_ctor == NULL) {
|
||||
nxt_unit_warn(NULL, "java.net.URL constructor not found");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return NXT_UNIT_OK;
|
||||
|
||||
failed:
|
||||
|
||||
(*env)->DeleteGlobalRef(env, cls);
|
||||
return NXT_UNIT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
jobject
|
||||
nxt_java_newURLClassLoader(JNIEnv *env, int url_count, char **urls)
|
||||
{
|
||||
jobjectArray jurls;
|
||||
|
||||
jurls = nxt_java_newURLs(env, url_count, urls);
|
||||
if (jurls == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (*env)->NewObject(env, nxt_java_URLClassLoader_class,
|
||||
nxt_java_URLClassLoader_ctor, jurls);
|
||||
}
|
||||
|
||||
|
||||
jobject
|
||||
nxt_java_newURLClassLoader_parent(JNIEnv *env, int url_count, char **urls,
|
||||
jobject parent)
|
||||
{
|
||||
jobjectArray jurls;
|
||||
|
||||
jurls = nxt_java_newURLs(env, url_count, urls);
|
||||
if (jurls == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (*env)->NewObject(env, nxt_java_URLClassLoader_class,
|
||||
nxt_java_URLClassLoader_parent_ctor, jurls,
|
||||
parent);
|
||||
}
|
||||
|
||||
|
||||
jobjectArray
|
||||
nxt_java_newURLs(JNIEnv *env, int url_count, char **urls)
|
||||
{
|
||||
int i;
|
||||
jstring surl;
|
||||
jobject jurl;
|
||||
jobjectArray jurls;
|
||||
|
||||
jurls = (*env)->NewObjectArray(env, url_count, nxt_java_URL_class, NULL);
|
||||
if (jurls == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < url_count; i++) {
|
||||
surl = (*env)->NewStringUTF(env, urls[i]);
|
||||
if (surl == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jurl = (*env)->NewObject(env, nxt_java_URL_class, nxt_java_URL_ctor,
|
||||
surl);
|
||||
if (jurl == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*env)->SetObjectArrayElement(env, jurls, i, jurl);
|
||||
}
|
||||
|
||||
return jurls;
|
||||
}
|
||||
|
||||
|
||||
jclass
|
||||
nxt_java_loadClass(JNIEnv *env, jobject cl, const char *name)
|
||||
{
|
||||
jstring jname;
|
||||
|
||||
jname = (*env)->NewStringUTF(env, name);
|
||||
if (jname == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (*env)->CallObjectMethod(env, cl, nxt_java_URLClassLoader_loadClass,
|
||||
jname);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_java_addURL(JNIEnv *env, jobject cl, const char *url)
|
||||
{
|
||||
jstring surl;
|
||||
jobject jurl;
|
||||
|
||||
surl = (*env)->NewStringUTF(env, url);
|
||||
if (surl == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
jurl = (*env)->NewObject(env, nxt_java_URL_class, nxt_java_URL_ctor, surl);
|
||||
if (jurl == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*env)->CallVoidMethod(env, cl, nxt_java_URLClassLoader_addURL, jurl);
|
||||
}
|
||||
27
src/java/nxt_jni_URLClassLoader.h
Normal file
27
src/java/nxt_jni_URLClassLoader.h
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _NXT_JAVA_URLCLASSLOADER_H_INCLUDED_
|
||||
#define _NXT_JAVA_URLCLASSLOADER_H_INCLUDED_
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
|
||||
int nxt_java_initURLClassLoader(JNIEnv *env);
|
||||
|
||||
jobject nxt_java_newURLClassLoader(JNIEnv *env, int url_count, char **urls);
|
||||
|
||||
jobject nxt_java_newURLClassLoader_parent(JNIEnv *env, int url_count,
|
||||
char **urls, jobject parent);
|
||||
|
||||
jobjectArray nxt_java_newURLs(JNIEnv *env, int url_count, char **urls);
|
||||
|
||||
jclass nxt_java_loadClass(JNIEnv *env, jobject cl, const char *name);
|
||||
|
||||
void nxt_java_addURL(JNIEnv *env, jobject cl, const char *url);
|
||||
|
||||
#endif /* _NXT_JAVA_URLCLASSLOADER_H_INCLUDED_ */
|
||||
|
||||
@@ -331,6 +331,17 @@ nxt_app_start(nxt_task_t *task, void *data)
|
||||
nxt_app = nxt_app_module_load(task, lang->file);
|
||||
}
|
||||
|
||||
if (nxt_app->pre_init != NULL) {
|
||||
ret = nxt_app->pre_init(task, data);
|
||||
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
nxt_debug(task, "application pre_init failed");
|
||||
|
||||
} else {
|
||||
nxt_debug(task, "application pre_init done");
|
||||
}
|
||||
}
|
||||
|
||||
if (app_conf->working_directory != NULL
|
||||
&& app_conf->working_directory[0] != 0)
|
||||
{
|
||||
@@ -521,6 +532,9 @@ nxt_app_parse_type(u_char *p, size_t length)
|
||||
|
||||
} else if (nxt_str_eq(&str, "ruby", 4)) {
|
||||
return NXT_APP_RUBY;
|
||||
|
||||
} else if (nxt_str_eq(&str, "java", 4)) {
|
||||
return NXT_APP_JAVA;
|
||||
}
|
||||
|
||||
return NXT_APP_UNKNOWN;
|
||||
|
||||
@@ -20,6 +20,7 @@ typedef enum {
|
||||
NXT_APP_PHP,
|
||||
NXT_APP_PERL,
|
||||
NXT_APP_RUBY,
|
||||
NXT_APP_JAVA,
|
||||
|
||||
NXT_APP_UNKNOWN,
|
||||
} nxt_app_type_t;
|
||||
@@ -70,6 +71,14 @@ typedef struct {
|
||||
} nxt_ruby_app_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
nxt_conf_value_t *classpath;
|
||||
char *webapp;
|
||||
nxt_conf_value_t *options;
|
||||
char *unit_jars;
|
||||
} nxt_java_app_conf_t;
|
||||
|
||||
|
||||
struct nxt_common_app_conf_s {
|
||||
nxt_str_t name;
|
||||
nxt_str_t type;
|
||||
@@ -85,6 +94,7 @@ struct nxt_common_app_conf_s {
|
||||
nxt_php_app_conf_t php;
|
||||
nxt_perl_app_conf_t perl;
|
||||
nxt_ruby_app_conf_t ruby;
|
||||
nxt_java_app_conf_t java;
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -152,6 +162,8 @@ struct nxt_app_module_s {
|
||||
nxt_str_t type;
|
||||
const char *version;
|
||||
|
||||
nxt_int_t (*pre_init)(nxt_task_t *task,
|
||||
nxt_common_app_conf_t *conf);
|
||||
nxt_int_t (*init)(nxt_task_t *task,
|
||||
nxt_common_app_conf_t *conf);
|
||||
};
|
||||
|
||||
@@ -125,7 +125,7 @@ void nxt_conf_set_element(nxt_conf_value_t *array, nxt_uint_t index,
|
||||
nxt_conf_value_t *value);
|
||||
nxt_int_t nxt_conf_set_element_string_dup(nxt_conf_value_t *array, nxt_mp_t *mp,
|
||||
nxt_uint_t index, nxt_str_t *value);
|
||||
nxt_uint_t nxt_conf_array_elements_count(nxt_conf_value_t *value);
|
||||
NXT_EXPORT nxt_uint_t nxt_conf_array_elements_count(nxt_conf_value_t *value);
|
||||
void nxt_conf_array_qsort(nxt_conf_value_t *value,
|
||||
int (*compare)(const void *, const void *));
|
||||
|
||||
|
||||
@@ -88,6 +88,10 @@ static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt,
|
||||
nxt_conf_value_t *value);
|
||||
static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt,
|
||||
nxt_str_t *name, nxt_conf_value_t *value);
|
||||
static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
|
||||
nxt_conf_value_t *value);
|
||||
static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt,
|
||||
nxt_conf_value_t *value);
|
||||
|
||||
|
||||
static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = {
|
||||
@@ -423,6 +427,31 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = {
|
||||
};
|
||||
|
||||
|
||||
static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = {
|
||||
{ nxt_string("classpath"),
|
||||
NXT_CONF_VLDT_ARRAY,
|
||||
&nxt_conf_vldt_array_iterator,
|
||||
(void *) &nxt_conf_vldt_java_classpath},
|
||||
|
||||
{ nxt_string("webapp"),
|
||||
NXT_CONF_VLDT_STRING,
|
||||
NULL,
|
||||
NULL },
|
||||
|
||||
{ nxt_string("options"),
|
||||
NXT_CONF_VLDT_ARRAY,
|
||||
&nxt_conf_vldt_array_iterator,
|
||||
(void *) &nxt_conf_vldt_java_option},
|
||||
|
||||
{ nxt_string("unit_jars"),
|
||||
NXT_CONF_VLDT_STRING,
|
||||
NULL,
|
||||
NULL },
|
||||
|
||||
NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
|
||||
};
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_conf_validate(nxt_conf_validation_t *vldt)
|
||||
{
|
||||
@@ -818,6 +847,7 @@ nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
||||
nxt_conf_vldt_php_members,
|
||||
nxt_conf_vldt_perl_members,
|
||||
nxt_conf_vldt_ruby_members,
|
||||
nxt_conf_vldt_java_members,
|
||||
};
|
||||
|
||||
ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
|
||||
@@ -1216,3 +1246,44 @@ nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name,
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
||||
{
|
||||
nxt_str_t str;
|
||||
|
||||
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
||||
return nxt_conf_vldt_error(vldt, "The \"classpath\" array "
|
||||
"must contain only string values.");
|
||||
}
|
||||
|
||||
nxt_conf_get_string(value, &str);
|
||||
|
||||
if (nxt_memchr(str.start, '\0', str.length) != NULL) {
|
||||
return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not "
|
||||
"contain strings with null character.");
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
static nxt_int_t
|
||||
nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
|
||||
{
|
||||
nxt_str_t str;
|
||||
|
||||
if (nxt_conf_type(value) != NXT_CONF_STRING) {
|
||||
return nxt_conf_vldt_error(vldt, "The \"options\" array "
|
||||
"must contain only string values.");
|
||||
}
|
||||
|
||||
nxt_conf_get_string(value, &str);
|
||||
|
||||
if (nxt_memchr(str.start, '\0', str.length) != NULL) {
|
||||
return nxt_conf_vldt_error(vldt, "The \"options\" array must not "
|
||||
"contain strings with null character.");
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ nxt_app_module_t nxt_external_module = {
|
||||
NULL,
|
||||
nxt_string("external"),
|
||||
"*",
|
||||
NULL,
|
||||
nxt_external_init,
|
||||
};
|
||||
|
||||
|
||||
462
src/nxt_java.c
Normal file
462
src/nxt_java.c
Normal file
@@ -0,0 +1,462 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <nxt_main.h>
|
||||
#include <nxt_runtime.h>
|
||||
#include <nxt_router.h>
|
||||
#include <nxt_unit.h>
|
||||
#include <nxt_unit_field.h>
|
||||
#include <nxt_unit_request.h>
|
||||
#include <nxt_unit_response.h>
|
||||
|
||||
#include <java/nxt_jni.h>
|
||||
|
||||
#include "java/nxt_jni_Thread.h"
|
||||
#include "java/nxt_jni_Context.h"
|
||||
#include "java/nxt_jni_Request.h"
|
||||
#include "java/nxt_jni_Response.h"
|
||||
#include "java/nxt_jni_InputStream.h"
|
||||
#include "java/nxt_jni_OutputStream.h"
|
||||
#include "java/nxt_jni_URLClassLoader.h"
|
||||
|
||||
#include "nxt_jars.h"
|
||||
|
||||
static nxt_int_t nxt_java_pre_init(nxt_task_t *task,
|
||||
nxt_common_app_conf_t *conf);
|
||||
static nxt_int_t nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
|
||||
static void nxt_java_request_handler(nxt_unit_request_info_t *req);
|
||||
|
||||
static uint32_t compat[] = {
|
||||
NXT_VERNUM, NXT_DEBUG,
|
||||
};
|
||||
|
||||
char *nxt_java_modules;
|
||||
|
||||
|
||||
#define NXT_STRING(x) _NXT_STRING(x)
|
||||
#define _NXT_STRING(x) #x
|
||||
|
||||
NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
||||
sizeof(compat),
|
||||
compat,
|
||||
nxt_string("java"),
|
||||
NXT_STRING(NXT_JAVA_VERSION),
|
||||
nxt_java_pre_init,
|
||||
nxt_java_init,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
JNIEnv *env;
|
||||
jobject ctx;
|
||||
} nxt_java_data_t;
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_java_pre_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
|
||||
{
|
||||
const char *unit_jars;
|
||||
|
||||
unit_jars = conf->u.java.unit_jars;
|
||||
if (unit_jars == NULL) {
|
||||
unit_jars = NXT_JARS;
|
||||
}
|
||||
|
||||
nxt_java_modules = realpath(unit_jars, NULL);
|
||||
if (nxt_java_modules == NULL) {
|
||||
nxt_alert(task, "realpath(%s) failed: %E", NXT_JARS, nxt_errno);
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
static char **
|
||||
nxt_java_module_jars(const char *jars[], int jar_count)
|
||||
{
|
||||
char **res, *jurl;
|
||||
nxt_int_t modules_len, jlen, i;
|
||||
const char **jar;
|
||||
|
||||
res = nxt_malloc(jar_count * sizeof(char*));
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
modules_len = nxt_strlen(nxt_java_modules);
|
||||
|
||||
for (i = 0, jar = jars; *jar != NULL; jar++) {
|
||||
jlen = nxt_length("file:") + modules_len + nxt_length("/")
|
||||
+ nxt_strlen(*jar) + 1;
|
||||
jurl = nxt_malloc(jlen);
|
||||
if (jurl == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res[i++] = jurl;
|
||||
|
||||
jurl = nxt_cpymem(jurl, "file:", nxt_length("file:"));
|
||||
jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len);
|
||||
*jurl++ = '/';
|
||||
jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar));
|
||||
*jurl++ = '\0';
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static nxt_int_t
|
||||
nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
|
||||
{
|
||||
jint rc;
|
||||
char *opt, *real_path;
|
||||
char **classpath_arr, **unit_jars, **system_jars;
|
||||
JavaVM *jvm;
|
||||
JNIEnv *env;
|
||||
jobject cl, classpath;
|
||||
nxt_str_t str;
|
||||
nxt_int_t opt_len, real_path_len;
|
||||
nxt_uint_t i, unit_jars_count, classpath_count, system_jars_count;
|
||||
JavaVMOption *jvm_opt;
|
||||
JavaVMInitArgs jvm_args;
|
||||
nxt_unit_ctx_t *ctx;
|
||||
nxt_unit_init_t java_init;
|
||||
nxt_java_data_t data;
|
||||
nxt_conf_value_t *value;
|
||||
nxt_java_app_conf_t *c;
|
||||
|
||||
//setenv("ASAN_OPTIONS", "handle_segv=0", 1);
|
||||
|
||||
jvm_args.version = JNI_VERSION_1_6;
|
||||
jvm_args.nOptions = 0;
|
||||
jvm_args.ignoreUnrecognized = 0;
|
||||
|
||||
c = &conf->u.java;
|
||||
|
||||
if (c->options != NULL) {
|
||||
jvm_args.nOptions += nxt_conf_array_elements_count(c->options);
|
||||
}
|
||||
|
||||
jvm_opt = nxt_malloc(jvm_args.nOptions * sizeof(JavaVMOption));
|
||||
if (jvm_opt == NULL) {
|
||||
nxt_alert(task, "failed to allocate jvm_opt");
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
jvm_args.options = jvm_opt;
|
||||
|
||||
unit_jars_count = nxt_nitems(nxt_java_unit_jars) - 1;
|
||||
|
||||
unit_jars = nxt_java_module_jars(nxt_java_unit_jars, unit_jars_count);
|
||||
if (unit_jars == NULL) {
|
||||
nxt_alert(task, "failed to allocate buffer for unit_jars array");
|
||||
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
system_jars_count = nxt_nitems(nxt_java_system_jars) - 1;
|
||||
|
||||
system_jars = nxt_java_module_jars(nxt_java_system_jars, system_jars_count);
|
||||
if (system_jars == NULL) {
|
||||
nxt_alert(task, "failed to allocate buffer for system_jars array");
|
||||
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
if (c->options != NULL) {
|
||||
|
||||
for (i = 0; /* void */ ; i++) {
|
||||
value = nxt_conf_get_array_element(c->options, i);
|
||||
if (value == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
nxt_conf_get_string(value, &str);
|
||||
|
||||
opt = nxt_malloc(str.length + 1);
|
||||
if (opt == NULL) {
|
||||
nxt_alert(task, "failed to allocate jvm_opt");
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
memcpy(opt, str.start, str.length);
|
||||
opt[str.length] = '\0';
|
||||
|
||||
jvm_opt[i].optionString = opt;
|
||||
}
|
||||
}
|
||||
|
||||
if (c->classpath != NULL) {
|
||||
classpath_count = nxt_conf_array_elements_count(c->classpath);
|
||||
classpath_arr = nxt_malloc(classpath_count * sizeof(char *));
|
||||
|
||||
for (i = 0; /* void */ ; i++) {
|
||||
value = nxt_conf_get_array_element(c->classpath, i);
|
||||
if (value == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
nxt_conf_get_string(value, &str);
|
||||
|
||||
opt_len = str.length + 1;
|
||||
|
||||
char *sc = memchr(str.start, ':', str.length);
|
||||
if (sc == NULL && str.start[0] == '/') {
|
||||
opt_len += nxt_length("file:");
|
||||
}
|
||||
|
||||
opt = nxt_malloc(opt_len);
|
||||
if (opt == NULL) {
|
||||
nxt_alert(task, "failed to allocate classpath");
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
if (sc == NULL && str.start[0] != '/') {
|
||||
nxt_memcpy(opt, str.start, str.length);
|
||||
opt[str.length] = '\0';
|
||||
|
||||
real_path = realpath(opt, NULL);
|
||||
if (real_path == NULL) {
|
||||
nxt_alert(task, "realpath(%s) failed: %E", opt, nxt_errno);
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
real_path_len = nxt_strlen(real_path);
|
||||
|
||||
free(opt);
|
||||
|
||||
opt_len = nxt_length("file:") + real_path_len + 1;
|
||||
|
||||
opt = nxt_malloc(opt_len);
|
||||
if (opt == NULL) {
|
||||
nxt_alert(task, "failed to allocate classpath");
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
real_path = (char *) str.start; /* I love this cast! */
|
||||
real_path_len = str.length;
|
||||
}
|
||||
|
||||
classpath_arr[i] = opt;
|
||||
|
||||
if (sc == NULL) {
|
||||
opt = nxt_cpymem(opt, "file:", nxt_length("file:"));
|
||||
}
|
||||
|
||||
opt = nxt_cpymem(opt, real_path, real_path_len);
|
||||
*opt = '\0';
|
||||
}
|
||||
|
||||
} else {
|
||||
classpath_count = 0;
|
||||
classpath_arr = NULL;
|
||||
}
|
||||
|
||||
rc = JNI_CreateJavaVM(&jvm, (void **) &env, &jvm_args);
|
||||
if (rc != JNI_OK) {
|
||||
nxt_alert(task, "failed to create Java VM: %d", (int) rc);
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
rc = nxt_java_initThread(env);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_initThread() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
rc = nxt_java_initURLClassLoader(env);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_initURLClassLoader() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
cl = nxt_java_newURLClassLoader(env, system_jars_count, system_jars);
|
||||
if (cl == NULL) {
|
||||
nxt_alert(task, "nxt_java_newURLClassLoader failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
nxt_java_setContextClassLoader(env, cl);
|
||||
|
||||
cl = nxt_java_newURLClassLoader_parent(env, unit_jars_count, unit_jars, cl);
|
||||
if (cl == NULL) {
|
||||
nxt_alert(task, "nxt_java_newURLClassLoader_parent failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
nxt_java_setContextClassLoader(env, cl);
|
||||
|
||||
rc = nxt_java_initContext(env, cl);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_initContext() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
rc = nxt_java_initRequest(env, cl);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_initRequest() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
rc = nxt_java_initResponse(env, cl);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_initResponse() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
rc = nxt_java_initInputStream(env, cl);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_initInputStream() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
rc = nxt_java_initOutputStream(env, cl);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_initOutputStream() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
nxt_java_jni_init(env);
|
||||
if (rc != NXT_UNIT_OK) {
|
||||
nxt_alert(task, "nxt_java_jni_init() failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
classpath = nxt_java_newURLs(env, classpath_count, classpath_arr);
|
||||
if (classpath == NULL) {
|
||||
nxt_alert(task, "nxt_java_newURLs failed");
|
||||
goto env_failed;
|
||||
}
|
||||
|
||||
data.env = env;
|
||||
data.ctx = nxt_java_startContext(env, c->webapp, classpath);
|
||||
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
nxt_alert(task, "Unhandled exception in application start");
|
||||
(*env)->ExceptionDescribe(env);
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
nxt_unit_default_init(task, &java_init);
|
||||
|
||||
java_init.callbacks.request_handler = nxt_java_request_handler;
|
||||
java_init.request_data_size = sizeof(nxt_java_request_data_t);
|
||||
java_init.data = &data;
|
||||
|
||||
ctx = nxt_unit_init(&java_init);
|
||||
if (nxt_slow_path(ctx == NULL)) {
|
||||
nxt_alert(task, "nxt_unit_init() failed");
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
rc = nxt_unit_run(ctx);
|
||||
if (nxt_slow_path(rc != NXT_UNIT_OK)) {
|
||||
/* TODO report error */
|
||||
}
|
||||
|
||||
nxt_unit_done(ctx);
|
||||
|
||||
nxt_java_stopContext(env, data.ctx);
|
||||
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
}
|
||||
|
||||
(*jvm)->DestroyJavaVM(jvm);
|
||||
|
||||
exit(0);
|
||||
|
||||
return NXT_OK;
|
||||
|
||||
env_failed:
|
||||
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
}
|
||||
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
nxt_java_request_handler(nxt_unit_request_info_t *req)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jobject jreq, jresp;
|
||||
nxt_java_data_t *java_data;
|
||||
nxt_java_request_data_t *data;
|
||||
|
||||
java_data = req->unit->data;
|
||||
env = java_data->env;
|
||||
data = req->data;
|
||||
|
||||
jreq = nxt_java_newRequest(env, java_data->ctx, req);
|
||||
if (jreq == NULL) {
|
||||
nxt_unit_req_alert(req, "failed to create Request instance");
|
||||
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
|
||||
nxt_unit_request_done(req, NXT_UNIT_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
jresp = nxt_java_newResponse(env, req);
|
||||
if (jresp == NULL) {
|
||||
nxt_unit_req_alert(req, "failed to create Response instance");
|
||||
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
|
||||
(*env)->DeleteLocalRef(env, jreq);
|
||||
|
||||
nxt_unit_request_done(req, NXT_UNIT_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
data->header_size = 10 * 1024;
|
||||
data->buf_size = 32 * 1024; /* from Jetty */
|
||||
data->jreq = jreq;
|
||||
data->jresp = jresp;
|
||||
data->buf = NULL;
|
||||
|
||||
nxt_unit_request_group_dup_fields(req);
|
||||
|
||||
nxt_java_service(env, java_data->ctx, jreq, jresp);
|
||||
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
|
||||
if (!nxt_unit_response_is_init(req)) {
|
||||
nxt_unit_response_init(req, 200, 0, 0);
|
||||
}
|
||||
|
||||
if (!nxt_unit_response_is_sent(req)) {
|
||||
nxt_unit_response_send(req);
|
||||
}
|
||||
|
||||
if (data->buf != NULL) {
|
||||
nxt_unit_buf_send(data->buf);
|
||||
|
||||
data->buf = NULL;
|
||||
}
|
||||
|
||||
(*env)->DeleteLocalRef(env, jresp);
|
||||
(*env)->DeleteLocalRef(env, jreq);
|
||||
|
||||
nxt_unit_request_done(req, NXT_UNIT_OK);
|
||||
}
|
||||
|
||||
@@ -219,12 +219,38 @@ static nxt_conf_map_t nxt_ruby_app_conf[] = {
|
||||
};
|
||||
|
||||
|
||||
static nxt_conf_map_t nxt_java_app_conf[] = {
|
||||
{
|
||||
nxt_string("classpath"),
|
||||
NXT_CONF_MAP_PTR,
|
||||
offsetof(nxt_common_app_conf_t, u.java.classpath),
|
||||
},
|
||||
{
|
||||
nxt_string("webapp"),
|
||||
NXT_CONF_MAP_CSTRZ,
|
||||
offsetof(nxt_common_app_conf_t, u.java.webapp),
|
||||
},
|
||||
{
|
||||
nxt_string("options"),
|
||||
NXT_CONF_MAP_PTR,
|
||||
offsetof(nxt_common_app_conf_t, u.java.options),
|
||||
},
|
||||
{
|
||||
nxt_string("unit_jars"),
|
||||
NXT_CONF_MAP_CSTRZ,
|
||||
offsetof(nxt_common_app_conf_t, u.java.unit_jars),
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
static nxt_conf_app_map_t nxt_app_maps[] = {
|
||||
{ nxt_nitems(nxt_external_app_conf), nxt_external_app_conf },
|
||||
{ nxt_nitems(nxt_python_app_conf), nxt_python_app_conf },
|
||||
{ nxt_nitems(nxt_php_app_conf), nxt_php_app_conf },
|
||||
{ nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf },
|
||||
{ nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf },
|
||||
{ nxt_nitems(nxt_java_app_conf), nxt_java_app_conf },
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
||||
compat,
|
||||
nxt_string("php"),
|
||||
PHP_VERSION,
|
||||
NULL,
|
||||
nxt_php_init,
|
||||
};
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
||||
compat,
|
||||
nxt_string("python"),
|
||||
PY_VERSION,
|
||||
NULL,
|
||||
nxt_python_init,
|
||||
};
|
||||
|
||||
|
||||
@@ -293,6 +293,7 @@ static const nxt_str_t *nxt_app_msg_prefix[] = {
|
||||
&http_prefix,
|
||||
&http_prefix,
|
||||
&http_prefix,
|
||||
&empty_prefix,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
||||
nxt_perl_psgi_compat,
|
||||
nxt_string("perl"),
|
||||
PERL_VERSION_STRING,
|
||||
NULL,
|
||||
nxt_perl_psgi_init,
|
||||
};
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
||||
compat,
|
||||
nxt_string("ruby"),
|
||||
ruby_version,
|
||||
NULL,
|
||||
nxt_ruby_init,
|
||||
};
|
||||
|
||||
|
||||
89
test/java/content_type/app.java
Normal file
89
test/java/content_type/app.java
Normal file
@@ -0,0 +1,89 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
if (request.getServletPath().equals("/1")) {
|
||||
response.setContentType("text/plain;charset=utf-8");
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getServletPath().equals("/2")) {
|
||||
response.setContentType("text/plain");
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getServletPath().equals("/3")) {
|
||||
response.setContentType("text/plain;charset=utf-8");
|
||||
response.setCharacterEncoding("windows-1251");
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getServletPath().equals("/4")) {
|
||||
response.setCharacterEncoding("windows-1251");
|
||||
response.setContentType("text/plain");
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getServletPath().equals("/5")) {
|
||||
response.setContentType("text/plain;charset=utf-8");
|
||||
response.setCharacterEncoding(null);
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getServletPath().equals("/6")) {
|
||||
response.setContentType("text/plain;charset=utf-8");
|
||||
response.setContentType(null);
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getServletPath().equals("/7")) {
|
||||
response.setContentType("text/plain;charset=utf-8");
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
|
||||
response.setCharacterEncoding("windows-1251");
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.getServletPath().equals("/8")) {
|
||||
response.setContentType("text/plain;charset=utf-8");
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
|
||||
response.setContentType("text/html;charset=windows-1251");
|
||||
response.setHeader("X-Character-Encoding", response.getCharacterEncoding());
|
||||
response.setHeader("X-Content-Type", response.getContentType());
|
||||
return;
|
||||
}
|
||||
|
||||
response.sendError(404);
|
||||
}
|
||||
}
|
||||
30
test/java/cookies/app.java
Normal file
30
test/java/cookies/app.java
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie c : cookies) {
|
||||
if (c.getName().equals("var1")) {
|
||||
response.addHeader("X-Cookie-1", c.getValue());
|
||||
}
|
||||
if (c.getName().equals("var2")) {
|
||||
response.addHeader("X-Cookie-2", c.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
test/java/empty/app.java
Normal file
18
test/java/empty/app.java
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{ }
|
||||
}
|
||||
54
test/java/filter/app.java
Normal file
54
test/java/filter/app.java
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@WebFilter(urlPatterns = "")
|
||||
public static class filter implements Filter
|
||||
{
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.getOutputStream().println("Extra Info");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
|
||||
((HttpServletResponse) response).addHeader("X-Filter-Before", "1");
|
||||
|
||||
chain.doFilter(request, response);
|
||||
|
||||
((HttpServletResponse) response).setHeader("X-Filter-After", "1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.getOutputStream().println("This is servlet response");
|
||||
response.setHeader("X-Filter-After", "0");
|
||||
}
|
||||
}
|
||||
138
test/java/forward/app.java
Normal file
138
test/java/forward/app.java
Normal file
@@ -0,0 +1,138 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
private String id;
|
||||
|
||||
private class RequestWrapper extends HttpServletRequestWrapper
|
||||
{
|
||||
public RequestWrapper(HttpServletRequest r)
|
||||
{
|
||||
super(r);
|
||||
}
|
||||
}
|
||||
|
||||
private class ResponseWrapper extends HttpServletResponseWrapper
|
||||
{
|
||||
public ResponseWrapper(HttpServletResponse r)
|
||||
{
|
||||
super(r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig sc)
|
||||
throws ServletException
|
||||
{
|
||||
id = sc.getInitParameter("id");
|
||||
}
|
||||
|
||||
private RequestDispatcher getRequestDispatcher(HttpServletRequest request, String str)
|
||||
{
|
||||
String disp = request.getParameter("disp");
|
||||
|
||||
if (disp != null && disp.equals("ctx")) {
|
||||
return request.getServletContext().getRequestDispatcher(str);
|
||||
}
|
||||
|
||||
if (disp != null && disp.equals("name")) {
|
||||
return request.getServletContext().getNamedDispatcher(str);
|
||||
}
|
||||
|
||||
if (disp == null || disp.equals("req")) {
|
||||
return request.getRequestDispatcher(str);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
String dtype = "" + request.getDispatcherType();
|
||||
|
||||
response.addHeader("X-" + dtype + "-Id", id);
|
||||
response.addHeader("X-" + dtype + "-Request-URI", "" + request.getRequestURI());
|
||||
response.addHeader("X-" + dtype + "-Servlet-Path", "" + request.getServletPath());
|
||||
response.addHeader("X-" + dtype + "-Path-Info", "" + request.getPathInfo());
|
||||
response.addHeader("X-" + dtype + "-Query-String", "" + request.getQueryString());
|
||||
response.addHeader("X-" + dtype + "-Dispatcher-Type", "" + request.getDispatcherType());
|
||||
|
||||
response.setContentType("text/plain; charset=utf-8");
|
||||
|
||||
Map<String, String[]> pmap = request.getParameterMap();
|
||||
|
||||
for (Map.Entry<String,String[]> p : pmap.entrySet()) {
|
||||
response.addHeader("X-" + dtype + "-Param-" + p.getKey(), "" + String.join(",", p.getValue()));
|
||||
}
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
|
||||
if (id.equals("fwd")) {
|
||||
String uri = request.getParameter("uri");
|
||||
|
||||
if (uri != null && request.getDispatcherType() != DispatcherType.FORWARD) {
|
||||
response.addHeader("X-Forward-To", "" + uri);
|
||||
|
||||
out.println("Before forwarding.");
|
||||
|
||||
RequestDispatcher d = getRequestDispatcher(request, uri);
|
||||
|
||||
if (d == null) {
|
||||
out.println("Dispatcher is null");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
d.forward(new RequestWrapper(request), new ResponseWrapper(response));
|
||||
} catch(Exception e) {
|
||||
response.addHeader("X-Exception", "" + e);
|
||||
}
|
||||
|
||||
response.addHeader("X-After-Forwarding", "you-should-not-see-this");
|
||||
|
||||
out.println("After forwarding.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (id.equals("data")) {
|
||||
response.addHeader("X-" + RequestDispatcher.FORWARD_REQUEST_URI, "" + request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI));
|
||||
response.addHeader("X-" + RequestDispatcher.FORWARD_CONTEXT_PATH, "" + request.getAttribute(RequestDispatcher.FORWARD_CONTEXT_PATH));
|
||||
response.addHeader("X-" + RequestDispatcher.FORWARD_SERVLET_PATH, "" + request.getAttribute(RequestDispatcher.FORWARD_SERVLET_PATH));
|
||||
response.addHeader("X-" + RequestDispatcher.FORWARD_PATH_INFO, "" + request.getAttribute(RequestDispatcher.FORWARD_PATH_INFO));
|
||||
response.addHeader("X-" + RequestDispatcher.FORWARD_QUERY_STRING, "" + request.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING));
|
||||
|
||||
out.println("app.doGet(): #" + this + ", " + id);
|
||||
out.println("RequestURI: " + request.getRequestURI());
|
||||
out.println("ServletPath: " + request.getServletPath());
|
||||
out.println("PathInfo: " + request.getPathInfo());
|
||||
out.println("DispType: " + request.getDispatcherType());
|
||||
out.println("QueryString: " + request.getQueryString());
|
||||
|
||||
for (Map.Entry<String,String[]> p : pmap.entrySet()) {
|
||||
out.println("- " + p.getKey() + "=" + String.join(",", p.getValue()));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
response.sendError(404);
|
||||
}
|
||||
}
|
||||
1
test/java/forward/index.html
Normal file
1
test/java/forward/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><body>This is index.html.</body></html>
|
||||
38
test/java/forward/web.xml
Normal file
38
test/java/forward/web.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="3.0">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>fwd</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>fwd</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>fwd</servlet-name>
|
||||
<url-pattern>/fwd/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<servlet>
|
||||
<servlet-name>data</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>data</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>data</servlet-name>
|
||||
<url-pattern>/data/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>data</servlet-name>
|
||||
<url-pattern>/WEB-INF/index.html</url-pattern>
|
||||
<url-pattern>/index.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
21
test/java/get_header/app.java
Normal file
21
test/java/get_header/app.java
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.addHeader("X-Reply", request.getHeader("X-Header"));
|
||||
}
|
||||
}
|
||||
27
test/java/get_header_names/app.java
Normal file
27
test/java/get_header_names/app.java
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
Enumeration<String> header_names = request.getHeaderNames();
|
||||
|
||||
for (int i = 0; header_names.hasMoreElements(); i++) {
|
||||
response.addHeader("X-Reply-" + Integer.toString(i),
|
||||
header_names.nextElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
27
test/java/get_headers/app.java
Normal file
27
test/java/get_headers/app.java
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
Enumeration<String> headers = request.getHeaders("X-Header");
|
||||
|
||||
for (int i = 0; headers.hasMoreElements(); i++) {
|
||||
response.addHeader("X-Reply-" + Integer.toString(i),
|
||||
headers.nextElement());
|
||||
}
|
||||
}
|
||||
}
|
||||
50
test/java/get_params/app.java
Normal file
50
test/java/get_params/app.java
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.addHeader("X-Var-1", request.getParameter("var1"));
|
||||
response.addHeader("X-Var-2", "" + (request.getParameter("var2") != null));
|
||||
response.addHeader("X-Var-3", "" + (request.getParameter("var3") != null));
|
||||
response.addHeader("X-Var-4", request.getParameter("var4"));
|
||||
|
||||
Enumeration<String> parameter_names = request.getParameterNames();
|
||||
|
||||
String names = "";
|
||||
for (int i = 0; parameter_names.hasMoreElements(); i++) {
|
||||
names = names.concat(parameter_names.nextElement() + " ");
|
||||
}
|
||||
response.addHeader("X-Param-Names", names);
|
||||
|
||||
String[] parameter_values = request.getParameterValues("var4");
|
||||
|
||||
String values = "";
|
||||
for (int i = 0; i < parameter_values.length; i++) {
|
||||
values = values.concat(parameter_values[i] + " ");
|
||||
}
|
||||
response.addHeader("X-Param-Values", values);
|
||||
|
||||
Map <String, String[]> parameter_map = request.getParameterMap();
|
||||
|
||||
String map = "";
|
||||
for (Map.Entry <String, String[]> p : parameter_map.entrySet()) {
|
||||
map = map.concat(p.getKey() + "=" + String.join(",", p.getValue()) + " ");
|
||||
}
|
||||
response.addHeader("X-Param-Map", map);
|
||||
}
|
||||
}
|
||||
34
test/java/header/app.java
Normal file
34
test/java/header/app.java
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.setHeader("X-Set-Utf8-Value", "тест");
|
||||
response.setHeader("X-Set-Utf8-Name-Имя", "x");
|
||||
|
||||
response.addHeader("X-Add-Utf8-Value", "тест");
|
||||
response.addHeader("X-Add-Utf8-Name-Имя", "y");
|
||||
|
||||
response.addHeader("X-Add-Test", "v1");
|
||||
response.addHeader("X-Add-Test", null);
|
||||
|
||||
response.setHeader("X-Set-Test1", "v1");
|
||||
response.setHeader("X-Set-Test1", null);
|
||||
|
||||
response.setHeader("X-Set-Test2", "v1");
|
||||
response.setHeader("X-Set-Test2", "");
|
||||
}
|
||||
}
|
||||
22
test/java/header_date/app.java
Normal file
22
test/java/header_date/app.java
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.setDateHeader("X-Set-Date", 1000);
|
||||
response.addDateHeader("X-Get-Date", request.getDateHeader("X-Header"));
|
||||
}
|
||||
}
|
||||
22
test/java/header_int/app.java
Normal file
22
test/java/header_int/app.java
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.setIntHeader("X-Set-Int", 1);
|
||||
response.addHeader("X-Get-Int", Integer.toString(request.getIntHeader("X-Header")));
|
||||
}
|
||||
}
|
||||
136
test/java/include/app.java
Normal file
136
test/java/include/app.java
Normal file
@@ -0,0 +1,136 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
private String id;
|
||||
|
||||
private class RequestWrapper extends HttpServletRequestWrapper
|
||||
{
|
||||
public RequestWrapper(HttpServletRequest r)
|
||||
{
|
||||
super(r);
|
||||
}
|
||||
}
|
||||
|
||||
private class ResponseWrapper extends HttpServletResponseWrapper
|
||||
{
|
||||
public ResponseWrapper(HttpServletResponse r)
|
||||
{
|
||||
super(r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig sc)
|
||||
throws ServletException
|
||||
{
|
||||
id = sc.getInitParameter("id");
|
||||
}
|
||||
|
||||
private RequestDispatcher getRequestDispatcher(HttpServletRequest request, String str)
|
||||
{
|
||||
String disp = request.getParameter("disp");
|
||||
|
||||
if (disp != null && disp.equals("ctx")) {
|
||||
return request.getServletContext().getRequestDispatcher(str);
|
||||
}
|
||||
|
||||
if (disp != null && disp.equals("name")) {
|
||||
return request.getServletContext().getNamedDispatcher(str);
|
||||
}
|
||||
|
||||
if (disp == null || disp.equals("req")) {
|
||||
return request.getRequestDispatcher(str);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
String dtype = "" + request.getDispatcherType();
|
||||
|
||||
response.addHeader("X-" + dtype + "-Id", id);
|
||||
response.addHeader("X-" + dtype + "-Request-URI", "" + request.getRequestURI());
|
||||
response.addHeader("X-" + dtype + "-Servlet-Path", "" + request.getServletPath());
|
||||
response.addHeader("X-" + dtype + "-Path-Info", "" + request.getPathInfo());
|
||||
response.addHeader("X-" + dtype + "-Query-String", "" + request.getQueryString());
|
||||
response.addHeader("X-" + dtype + "-Dispatcher-Type", "" + request.getDispatcherType());
|
||||
|
||||
response.setContentType("text/plain; charset=utf-8");
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
|
||||
if (id.equals("inc")) {
|
||||
String uri = request.getParameter("uri");
|
||||
|
||||
if (uri != null && request.getDispatcherType() != DispatcherType.INCLUDE) {
|
||||
response.addHeader("X-Include", "" + uri);
|
||||
|
||||
out.println("Before include.");
|
||||
|
||||
RequestDispatcher d = getRequestDispatcher(request, uri);
|
||||
|
||||
if (d == null) {
|
||||
out.println("Dispatcher is null");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
d.include(new RequestWrapper(request), new ResponseWrapper(response));
|
||||
} catch(Exception e) {
|
||||
response.addHeader("X-Exception", "" + e);
|
||||
out.println("Exception: " + e);
|
||||
}
|
||||
|
||||
response.addHeader("X-After-Include", "you-should-see-this");
|
||||
|
||||
out.println("After include.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (id.equals("data")) {
|
||||
out.println("app.doGet(): #" + this + ", " + id);
|
||||
out.println("RequestURI: " + request.getRequestURI());
|
||||
out.println("ServletPath: " + request.getServletPath());
|
||||
out.println("PathInfo: " + request.getPathInfo());
|
||||
out.println("DispType: " + request.getDispatcherType());
|
||||
out.println("QueryString: " + request.getQueryString());
|
||||
|
||||
Map<String, String[]> pmap = request.getParameterMap();
|
||||
|
||||
for (Map.Entry<String,String[]> p : pmap.entrySet()) {
|
||||
out.println("- " + p.getKey() + "=" + String.join(",", p.getValue()));
|
||||
}
|
||||
|
||||
out.println(RequestDispatcher.INCLUDE_REQUEST_URI + ": " + request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI));
|
||||
out.println(RequestDispatcher.INCLUDE_CONTEXT_PATH + ": " + request.getAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH));
|
||||
out.println(RequestDispatcher.INCLUDE_SERVLET_PATH + ": " + request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH));
|
||||
out.println(RequestDispatcher.INCLUDE_PATH_INFO + ": " + request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO));
|
||||
out.println(RequestDispatcher.INCLUDE_QUERY_STRING + ": " + request.getAttribute(RequestDispatcher.INCLUDE_QUERY_STRING));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
response.sendError(404);
|
||||
}
|
||||
}
|
||||
1
test/java/include/index.html
Normal file
1
test/java/include/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><body>This is index.html.</body></html>
|
||||
37
test/java/include/web.xml
Normal file
37
test/java/include/web.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="3.0">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>inc</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>inc</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>data</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>data</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>inc</servlet-name>
|
||||
<url-pattern>/inc/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>data</servlet-name>
|
||||
<url-pattern>/data/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>data</servlet-name>
|
||||
<url-pattern>/WEB-INF/index.html</url-pattern>
|
||||
<url-pattern>/index.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
2
test/java/jsp/index.jsp
Normal file
2
test/java/jsp/index.jsp
Normal file
@@ -0,0 +1,2 @@
|
||||
<%@ page contentType="text/plain"%>This is plain text response for "<%= request.getMethod() %> <%= request.getRequestURI() %>".
|
||||
<% response.addHeader("X-Unit-JSP", "ok"); %>
|
||||
37
test/java/mirror/app.java
Normal file
37
test/java/mirror/app.java
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
BufferedReader reader = request.getReader();
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
buffer.append(line);
|
||||
}
|
||||
|
||||
String data = buffer.toString();
|
||||
|
||||
String dataLength = Integer.toString(data.length());
|
||||
response.setHeader("Content-Length", dataLength);
|
||||
|
||||
response.setContentType("text/html");
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
out.print(data);
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
56
test/java/path_translation/app.java
Normal file
56
test/java/path_translation/app.java
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet( urlPatterns = { "/", "/pt/*" } )
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.addHeader("X-Request-URI", "" + request.getRequestURI());
|
||||
response.addHeader("X-Servlet-Path", "" + request.getServletPath());
|
||||
response.addHeader("X-Path-Info", "" + request.getPathInfo());
|
||||
response.addHeader("X-Query-String", "" + request.getQueryString());
|
||||
response.addHeader("X-Path-Translated", "" + request.getPathTranslated());
|
||||
|
||||
response.setContentType("text/plain; charset=utf-8");
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
ServletContext ctx = request.getServletContext();
|
||||
|
||||
String path = request.getParameter("path");
|
||||
|
||||
if (path != null) {
|
||||
response.addHeader("X-Real-Path", "" + ctx.getRealPath(path));
|
||||
response.addHeader("X-Resource", "" + ctx.getResource(path));
|
||||
|
||||
Set<String> paths = ctx.getResourcePaths(path);
|
||||
|
||||
response.addHeader("X-Resource-Paths", "" + paths);
|
||||
|
||||
InputStream is = ctx.getResourceAsStream(path);
|
||||
|
||||
response.addHeader("X-Resource-As-Stream", "" + is);
|
||||
|
||||
if (is != null) {
|
||||
final byte[] buf = new byte[1024];
|
||||
int r = is.read(buf);
|
||||
|
||||
out.println(new String(buf, 0, r, "utf-8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
test/java/path_translation/index.html
Normal file
1
test/java/path_translation/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><body>This is index.html.</body></html>
|
||||
22
test/java/post_params/app.java
Normal file
22
test/java/post_params/app.java
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.addHeader("X-Var-1", request.getParameter("var1"));
|
||||
response.addHeader("X-Var-2", "" + (request.getParameter("var2") != null));
|
||||
response.addHeader("X-Var-3", "" + (request.getParameter("var3") != null));
|
||||
}
|
||||
}
|
||||
20
test/java/query_string/app.java
Normal file
20
test/java/query_string/app.java
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet( urlPatterns = { "/" } )
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.addHeader("X-Query-String", "" + request.getQueryString());
|
||||
}
|
||||
}
|
||||
79
test/java/request_listeners/app.java
Normal file
79
test/java/request_listeners/app.java
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequestEvent;
|
||||
import javax.servlet.ServletRequestListener;
|
||||
import javax.servlet.ServletRequestAttributeEvent;
|
||||
import javax.servlet.ServletRequestAttributeListener;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.annotation.WebListener;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebListener
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet implements
|
||||
ServletRequestListener,
|
||||
ServletRequestAttributeListener
|
||||
{
|
||||
private static String request_initialized = "";
|
||||
private static String request_destroyed = "";
|
||||
private static String attribute_added = "";
|
||||
private static String attribute_removed = "";
|
||||
private static String attribute_replaced = "";
|
||||
|
||||
@Override
|
||||
public void requestInitialized(ServletRequestEvent sre)
|
||||
{
|
||||
HttpServletRequest r = (HttpServletRequest) sre.getServletRequest();
|
||||
|
||||
request_initialized = r.getRequestURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestDestroyed(ServletRequestEvent sre)
|
||||
{
|
||||
HttpServletRequest r = (HttpServletRequest) sre.getServletRequest();
|
||||
|
||||
request_destroyed = r.getRequestURI();
|
||||
|
||||
attribute_added = "";
|
||||
attribute_removed = "";
|
||||
attribute_replaced = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(ServletRequestAttributeEvent event)
|
||||
{
|
||||
attribute_added += event.getName() + "=" + event.getValue() + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(ServletRequestAttributeEvent event)
|
||||
{
|
||||
attribute_removed += event.getName() + "=" + event.getValue() + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(ServletRequestAttributeEvent event)
|
||||
{
|
||||
attribute_replaced += event.getName() + "=" + event.getValue() + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
request.setAttribute("var", request.getParameter("var1"));
|
||||
request.setAttribute("var", request.getParameter("var2"));
|
||||
request.setAttribute("var", request.getParameter("var3"));
|
||||
|
||||
response.addHeader("X-Request-Initialized", request_initialized);
|
||||
response.addHeader("X-Request-Destroyed", request_destroyed);
|
||||
response.addHeader("X-Attr-Added", attribute_added);
|
||||
response.addHeader("X-Attr-Removed", attribute_removed);
|
||||
response.addHeader("X-Attr-Replaced", attribute_replaced);
|
||||
}
|
||||
}
|
||||
30
test/java/session/app.java
Normal file
30
test/java/session/app.java
Normal file
@@ -0,0 +1,30 @@
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
HttpSession s = request.getSession();
|
||||
String old_var1 = (String) s.getAttribute("var1");
|
||||
s.setAttribute("var1", request.getParameter("var1"));
|
||||
|
||||
if (old_var1 == null) {
|
||||
response.addHeader("X-Var-1", "null");
|
||||
} else {
|
||||
response.addHeader("X-Var-1", old_var1);
|
||||
}
|
||||
|
||||
response.addHeader("X-Session-Id", s.getId());
|
||||
response.addHeader("X-Session-New", "" + s.isNew());
|
||||
}
|
||||
}
|
||||
27
test/java/session_inactive/app.java
Normal file
27
test/java/session_inactive/app.java
Normal file
@@ -0,0 +1,27 @@
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
HttpSession s = request.getSession();
|
||||
|
||||
if (s.isNew()) {
|
||||
s.setMaxInactiveInterval(2);
|
||||
}
|
||||
|
||||
response.addHeader("X-Session-Id", s.getId());
|
||||
response.addDateHeader("X-Session-Last-Access-Time", s.getLastAccessedTime());
|
||||
response.addIntHeader("X-Session-Interval", s.getMaxInactiveInterval());
|
||||
}
|
||||
}
|
||||
23
test/java/session_invalidate/app.java
Normal file
23
test/java/session_invalidate/app.java
Normal file
@@ -0,0 +1,23 @@
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
HttpSession s = request.getSession();
|
||||
|
||||
s.invalidate();
|
||||
|
||||
response.addHeader("X-Session-Id", s.getId());
|
||||
}
|
||||
}
|
||||
80
test/java/session_listeners/app.java
Normal file
80
test/java/session_listeners/app.java
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionAttributeListener;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionIdListener;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class app extends HttpServlet implements
|
||||
HttpSessionListener,
|
||||
HttpSessionIdListener,
|
||||
HttpSessionAttributeListener
|
||||
{
|
||||
private static String session_created = "";
|
||||
private static String session_destroyed = "";
|
||||
private static String session_id_changed = "";
|
||||
private static String attribute_added = "";
|
||||
private static String attribute_removed = "";
|
||||
private static String attribute_replaced = "";
|
||||
|
||||
@Override
|
||||
public void sessionCreated(HttpSessionEvent se)
|
||||
{
|
||||
session_created += se.getSession().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(HttpSessionEvent se)
|
||||
{
|
||||
session_destroyed += se.getSession().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionIdChanged(HttpSessionEvent event, String oldId)
|
||||
{
|
||||
session_id_changed += " " + oldId + "->" + event.getSession().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(HttpSessionBindingEvent event)
|
||||
{
|
||||
attribute_added += event.getName() + "=" + event.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(HttpSessionBindingEvent event)
|
||||
{
|
||||
attribute_removed += event.getName() + "=" + event.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(HttpSessionBindingEvent event)
|
||||
{
|
||||
attribute_replaced += event.getName() + "=" + event.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
HttpSession s = request.getSession();
|
||||
s.setAttribute("var1", request.getParameter("var1"));
|
||||
|
||||
response.addHeader("X-Session-Id", s.getId());
|
||||
response.addHeader("X-Session-Created", session_created);
|
||||
response.addHeader("X-Session-Destroyed", session_destroyed);
|
||||
response.addHeader("X-Attr-Added", attribute_added);
|
||||
response.addHeader("X-Attr-Removed", attribute_removed);
|
||||
response.addHeader("X-Attr-Replaced", attribute_replaced);
|
||||
}
|
||||
}
|
||||
14
test/java/session_listeners/web.xml
Normal file
14
test/java/session_listeners/web.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="3.0">
|
||||
<listener>
|
||||
<listener-class>app</listener-class>
|
||||
</listener>
|
||||
<listener>
|
||||
<listener-class>app</listener-class>
|
||||
</listener>
|
||||
</web-app>
|
||||
|
||||
39
test/java/url_pattern/app.java
Normal file
39
test/java/url_pattern/app.java
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
private String id;
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig sc)
|
||||
throws ServletException
|
||||
{
|
||||
id = sc.getInitParameter("id");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.addHeader("X-Id", id);
|
||||
response.addHeader("X-Request-URI", "" + request.getRequestURI());
|
||||
response.addHeader("X-Servlet-Path", "" + request.getServletPath());
|
||||
response.setHeader("X-Path-Info", "" + request.getPathInfo());
|
||||
|
||||
response.setContentType("text/plain; charset=utf-8");
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println("app.doGet(): #" + this + ", " + id);
|
||||
out.println("RequestURI: " + request.getRequestURI());
|
||||
out.println("ServletPath: " + request.getServletPath());
|
||||
out.println("PathInfo: " + request.getPathInfo());
|
||||
}
|
||||
}
|
||||
75
test/java/url_pattern/web.xml
Normal file
75
test/java/url_pattern/web.xml
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="3.0">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>servlet0</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>servlet0</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>servlet1</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>servlet1</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>servlet2</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>servlet2</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>servlet3</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>servlet3</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>servlet4</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>servlet4</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>default</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
<init-param><param-name>id</param-name><param-value>default</param-value></init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>servlet0</servlet-name>
|
||||
<url-pattern>/foo/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>servlet1</servlet-name>
|
||||
<url-pattern>/foo/bar/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>servlet2</servlet-name>
|
||||
<url-pattern>/baz/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>servlet3</servlet-name>
|
||||
<url-pattern>/catalog</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>servlet4</servlet-name>
|
||||
<url-pattern>*.bop</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>default</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
67
test/java/welcome_files/app.java
Normal file
67
test/java/welcome_files/app.java
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import javax.servlet.annotation.WebFilter;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
public class app extends HttpServlet
|
||||
{
|
||||
@WebFilter(urlPatterns = "*.jsp")
|
||||
public static class jsp_filter implements Filter
|
||||
{
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) { }
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
((HttpServletResponse) response).addHeader("X-JSP-Filter", "1");
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() { }
|
||||
}
|
||||
|
||||
@WebFilter(urlPatterns = "*.txt")
|
||||
public static class txt_filter implements Filter
|
||||
{
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) { }
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
((HttpServletResponse) response).addHeader("X-TXT-Filter", "1");
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() { }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.addHeader("X-App-Servlet", "1");
|
||||
response.setContentType("text/plain; charset=utf-8");
|
||||
|
||||
PrintWriter out = response.getWriter();
|
||||
out.println("App Servlet");
|
||||
}
|
||||
}
|
||||
1
test/java/welcome_files/dir1/index.txt
Normal file
1
test/java/welcome_files/dir1/index.txt
Normal file
@@ -0,0 +1 @@
|
||||
This is index.txt.
|
||||
3
test/java/welcome_files/dir2/default.jsp
Normal file
3
test/java/welcome_files/dir2/default.jsp
Normal file
@@ -0,0 +1,3 @@
|
||||
<%@ page contentType="text/html"%>
|
||||
<html><body><p>You should see this on <a href="/dir2/">/dir2/</a> URL.</p></body></html>
|
||||
<% response.addHeader("X-Unit-JSP", "ok"); %>
|
||||
1
test/java/welcome_files/dir2/index.html
Normal file
1
test/java/welcome_files/dir2/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><body><p>You should see this on <a href="/dir2/">/dir2/</a> URL.</p></body></html>
|
||||
1
test/java/welcome_files/dir3/index.txt
Normal file
1
test/java/welcome_files/dir3/index.txt
Normal file
@@ -0,0 +1 @@
|
||||
You should never see this.
|
||||
1
test/java/welcome_files/dir4/index.html
Normal file
1
test/java/welcome_files/dir4/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><body><p>You should see this for <a href="/dir4/index.html">/dir4/index.html</a> or <a href="/dir4/">/dir4/</a> url.</body></html>
|
||||
1
test/java/welcome_files/index.htm
Normal file
1
test/java/welcome_files/index.htm
Normal file
@@ -0,0 +1 @@
|
||||
<html><body><p>You should see this ONLY for <a href="/index.htm">/index.htm</a> url.</body></html>
|
||||
27
test/java/welcome_files/web.xml
Normal file
27
test/java/welcome_files/web.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
|
||||
version="3.0">
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.txt</welcome-file>
|
||||
<welcome-file>default.jsp</welcome-file>
|
||||
<welcome-file>index.html</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>app</servlet-name>
|
||||
<servlet-class>app</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>app</servlet-name>
|
||||
<url-pattern>/dir3/index.txt</url-pattern>
|
||||
<url-pattern>/dir4/index.txt</url-pattern>
|
||||
<url-pattern>/dir5/index.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
753
test/test_java_application.py
Normal file
753
test/test_java_application.py
Normal file
@@ -0,0 +1,753 @@
|
||||
import time
|
||||
import unittest
|
||||
import unit
|
||||
|
||||
class TestUnitJavaApplication(unit.TestUnitApplicationJava):
|
||||
|
||||
def setUpClass():
|
||||
unit.TestUnit().check_modules('java')
|
||||
|
||||
def test_java_application_cookies(self):
|
||||
self.load('cookies')
|
||||
|
||||
headers = self.get(headers={
|
||||
'Cookie': 'var1=val1; var2=val2',
|
||||
'Host': 'localhost',
|
||||
'Connection': 'close'
|
||||
})['headers']
|
||||
|
||||
self.assertEqual(headers['X-Cookie-1'], 'val1', 'cookie 1')
|
||||
self.assertEqual(headers['X-Cookie-2'], 'val2', 'cookie 2')
|
||||
|
||||
def test_java_application_filter(self):
|
||||
self.load('filter')
|
||||
|
||||
headers = self.get()['headers']
|
||||
|
||||
self.assertEqual(headers['X-Filter-Before'], '1', 'filter before')
|
||||
self.assertEqual(headers['X-Filter-After'], '1', 'filter after')
|
||||
|
||||
self.assertEqual(self.get(url='/test')['headers']['X-Filter-After'],
|
||||
'0', 'filter after 2')
|
||||
|
||||
def test_java_application_get_variables(self):
|
||||
self.load('get_params')
|
||||
|
||||
headers = self.get(url='/?var1=val1&var2=&var4=val4&var4=foo')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Var-1'], 'val1', 'GET variables')
|
||||
self.assertEqual(headers['X-Var-2'], 'true', 'GET variables 2')
|
||||
self.assertEqual(headers['X-Var-3'], 'false', 'GET variables 3')
|
||||
|
||||
self.assertEqual(headers['X-Param-Names'], 'var4 var2 var1 ',
|
||||
'getParameterNames')
|
||||
self.assertEqual(headers['X-Param-Values'], 'val4 foo ',
|
||||
'getParameterValues')
|
||||
self.assertEqual(headers['X-Param-Map'],
|
||||
'var2= var1=val1 var4=val4,foo ', 'getParameterMap')
|
||||
|
||||
def test_java_application_post_variables(self):
|
||||
self.load('post_params')
|
||||
|
||||
headers = self.post(headers={
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Host': 'localhost',
|
||||
'Connection': 'close'
|
||||
}, body='var1=val1&var2=')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Var-1'], 'val1', 'POST variables')
|
||||
self.assertEqual(headers['X-Var-2'], 'true', 'POST variables 2')
|
||||
self.assertEqual(headers['X-Var-3'], 'false', 'POST variables 3')
|
||||
|
||||
def test_java_application_session(self):
|
||||
self.load('session')
|
||||
|
||||
headers = self.get(url='/?var1=val1')['headers']
|
||||
session_id = headers['X-Session-Id']
|
||||
|
||||
self.assertEqual(headers['X-Var-1'], 'null', 'variable empty')
|
||||
self.assertEqual(headers['X-Session-New'], 'true', 'session create')
|
||||
|
||||
headers = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
}, url='/?var1=val2')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Var-1'], 'val1', 'variable')
|
||||
self.assertEqual(headers['X-Session-New'], 'false', 'session resume')
|
||||
self.assertEqual(session_id, headers['X-Session-Id'], 'session same id')
|
||||
|
||||
def test_java_application_session_active(self):
|
||||
self.load('session_inactive')
|
||||
|
||||
resp = self.get()
|
||||
session_id = resp['headers']['X-Session-Id']
|
||||
|
||||
self.assertEqual(resp['status'], 200, 'session init')
|
||||
self.assertEqual(resp['headers']['X-Session-Interval'], '2',
|
||||
'session interval')
|
||||
self.assertLess(abs(self.date_to_sec_epoch(
|
||||
resp['headers']['X-Session-Last-Access-Time']) - self.sec_epoch()),
|
||||
5, 'session last access time')
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
resp = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
})
|
||||
|
||||
self.assertEqual(resp['headers']['X-Session-Id'], session_id,
|
||||
'session active')
|
||||
|
||||
session_id = resp['headers']['X-Session-Id']
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
resp = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
})
|
||||
|
||||
self.assertEqual(resp['headers']['X-Session-Id'], session_id,
|
||||
'session active 2')
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
resp = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
})
|
||||
|
||||
self.assertEqual(resp['headers']['X-Session-Id'], session_id,
|
||||
'session active 3')
|
||||
|
||||
def test_java_application_session_inactive(self):
|
||||
self.load('session_inactive')
|
||||
|
||||
resp = self.get()
|
||||
session_id = resp['headers']['X-Session-Id']
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
resp = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
})
|
||||
|
||||
self.assertNotEqual(resp['headers']['X-Session-Id'], session_id,
|
||||
'session inactive')
|
||||
|
||||
def test_java_application_session_invalidate(self):
|
||||
self.load('session_invalidate')
|
||||
|
||||
resp = self.get()
|
||||
session_id = resp['headers']['X-Session-Id']
|
||||
|
||||
resp = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
})
|
||||
|
||||
self.assertNotEqual(resp['headers']['X-Session-Id'], session_id,
|
||||
'session invalidate')
|
||||
|
||||
def test_java_application_session_listeners(self):
|
||||
self.load('session_listeners')
|
||||
|
||||
headers = self.get(url='/test?var1=val1')['headers']
|
||||
session_id = headers['X-Session-Id']
|
||||
|
||||
self.assertEqual(headers['X-Session-Created'], session_id,
|
||||
'session create')
|
||||
self.assertEqual(headers['X-Attr-Added'], 'var1=val1',
|
||||
'attribute add')
|
||||
|
||||
headers = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
}, url='/?var1=val2')['headers']
|
||||
|
||||
self.assertEqual(session_id, headers['X-Session-Id'], 'session same id')
|
||||
self.assertEqual(headers['X-Attr-Replaced'], 'var1=val1',
|
||||
'attribute replace')
|
||||
|
||||
headers = self.get(headers={
|
||||
'Host': 'localhost',
|
||||
'Cookie': 'JSESSIONID=' + session_id,
|
||||
'Connection': 'close'
|
||||
}, url='/')['headers']
|
||||
|
||||
self.assertEqual(session_id, headers['X-Session-Id'], 'session same id')
|
||||
self.assertEqual(headers['X-Attr-Removed'], 'var1=val2',
|
||||
'attribute remove')
|
||||
|
||||
def test_java_application_jsp(self):
|
||||
self.load('jsp')
|
||||
|
||||
headers = self.get(url='/index.jsp')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Unit-JSP'], 'ok', 'JSP Ok header')
|
||||
|
||||
def test_java_application_url_pattern(self):
|
||||
self.load('url_pattern')
|
||||
|
||||
headers = self.get(url='/foo/bar/index.html')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet1', '#1 Servlet1 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/foo/bar/index.html', '#1 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/foo/bar', '#1 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], '/index.html', '#1 path info')
|
||||
|
||||
headers = self.get(url='/foo/bar/index.bop')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet1', '#2 Servlet1 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/foo/bar/index.bop', '#2 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/foo/bar', '#2 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], '/index.bop', '#2 path info')
|
||||
|
||||
headers = self.get(url='/baz')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet2', '#3 Servlet2 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/baz', '#3 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/baz', '#3 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null', '#3 path info')
|
||||
|
||||
headers = self.get(url='/baz/index.html')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet2', '#4 Servlet2 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/baz/index.html', '#4 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/baz', '#4 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], '/index.html', '#4 path info')
|
||||
|
||||
headers = self.get(url='/catalog')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet3', '#5 Servlet3 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/catalog', '#5 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/catalog', '#5 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null', '#5 path info')
|
||||
|
||||
headers = self.get(url='/catalog/index.html')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'default', '#6 default request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/catalog/index.html', '#6 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/catalog/index.html', '#6 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null', '#6 path info')
|
||||
|
||||
headers = self.get(url='/catalog/racecar.bop')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet4', '#7 servlet4 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/catalog/racecar.bop', '#7 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/catalog/racecar.bop', '#7 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null', '#7 path info')
|
||||
|
||||
headers = self.get( url='/index.bop')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet4', '#8 servlet4 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/index.bop', '#8 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/index.bop', '#8 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null', '#8 path info')
|
||||
|
||||
headers = self.get(url='/foo/baz')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'servlet0', '#9 servlet0 request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/foo/baz', '#9 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/foo', '#9 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], '/baz', '#9 path info')
|
||||
|
||||
headers = self.get()['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'default', '#10 default request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/', '#10 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/', '#10 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null', '#10 path info')
|
||||
|
||||
headers = self.get(url='/index.bop/')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Id'], 'default', '#11 default request')
|
||||
self.assertEqual(headers['X-Request-URI'], '/index.bop/', '#11 request URI')
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/index.bop/', '#11 servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null', '#11 path info')
|
||||
|
||||
def test_java_application_header(self):
|
||||
self.load('header')
|
||||
|
||||
headers = self.get()['headers']
|
||||
|
||||
self.assertEqual(headers['X-Set-Utf8-Value'], '????', 'set Utf8 header value')
|
||||
self.assertEqual(headers['X-Set-Utf8-Name-???'], 'x', 'set Utf8 header name')
|
||||
self.assertEqual(headers['X-Add-Utf8-Value'], '????', 'add Utf8 header value')
|
||||
self.assertEqual(headers['X-Add-Utf8-Name-???'], 'y', 'add Utf8 header name')
|
||||
self.assertEqual(headers['X-Add-Test'], 'v1', 'add null header')
|
||||
self.assertEqual('X-Set-Test1' in headers, False, 'set null header')
|
||||
self.assertEqual(headers['X-Set-Test2'], '', 'set empty header')
|
||||
|
||||
def test_java_application_content_type(self):
|
||||
self.load('content_type')
|
||||
|
||||
headers = self.get(url='/1')['headers']
|
||||
|
||||
self.assertEqual(headers['Content-Type'], 'text/plain;charset=utf-8', '#1 Content-Type header')
|
||||
self.assertEqual(headers['X-Content-Type'], 'text/plain;charset=utf-8', '#1 response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'utf-8', '#1 response charset')
|
||||
|
||||
headers = self.get(url='/2')['headers']
|
||||
|
||||
self.assertEqual(headers['Content-Type'], 'text/plain;charset=iso-8859-1', '#2 Content-Type header')
|
||||
self.assertEqual(headers['X-Content-Type'], 'text/plain;charset=iso-8859-1', '#2 response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'iso-8859-1', '#2 response charset')
|
||||
|
||||
headers = self.get(url='/3')['headers']
|
||||
|
||||
self.assertEqual(headers['Content-Type'], 'text/plain;charset=windows-1251', '#3 Content-Type header')
|
||||
self.assertEqual(headers['X-Content-Type'], 'text/plain;charset=windows-1251', '#3 response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'windows-1251', '#3 response charset')
|
||||
|
||||
headers = self.get(url='/4')['headers']
|
||||
|
||||
self.assertEqual(headers['Content-Type'], 'text/plain;charset=windows-1251', '#4 Content-Type header')
|
||||
self.assertEqual(headers['X-Content-Type'], 'text/plain;charset=windows-1251', '#4 response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'windows-1251', '#4 response charset')
|
||||
|
||||
headers = self.get(url='/5')['headers']
|
||||
|
||||
self.assertEqual(headers['Content-Type'], 'text/plain;charset=iso-8859-1', '#5 Content-Type header')
|
||||
self.assertEqual(headers['X-Content-Type'], 'text/plain;charset=iso-8859-1', '#5 response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'iso-8859-1', '#5 response charset')
|
||||
|
||||
headers = self.get(url='/6')['headers']
|
||||
|
||||
self.assertEqual('Content-Type' in headers, False, '#6 no Content-Type header')
|
||||
self.assertEqual('X-Content-Type' in headers, False, '#6 no response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'utf-8', '#6 response charset')
|
||||
|
||||
|
||||
headers = self.get(url='/7')['headers']
|
||||
|
||||
self.assertEqual(headers['Content-Type'], 'text/plain;charset=utf-8', '#7 Content-Type header')
|
||||
self.assertEqual(headers['X-Content-Type'], 'text/plain;charset=utf-8', '#7 response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'utf-8', '#7 response charset')
|
||||
|
||||
headers = self.get(url='/8')['headers']
|
||||
|
||||
self.assertEqual(headers['Content-Type'], 'text/html;charset=utf-8', '#8 Content-Type header')
|
||||
self.assertEqual(headers['X-Content-Type'], 'text/html;charset=utf-8', '#8 response Content-Type')
|
||||
self.assertEqual(headers['X-Character-Encoding'], 'utf-8', '#8 response charset')
|
||||
|
||||
def test_java_application_welcome_files(self):
|
||||
self.load('welcome_files')
|
||||
|
||||
headers = self.get()['headers']
|
||||
|
||||
resp = self.get(url='/dir1')
|
||||
|
||||
self.assertEqual(resp['status'], 302, 'dir redirect expected')
|
||||
|
||||
resp = self.get(url='/dir1/')
|
||||
|
||||
self.assertEqual('This is index.txt.' in resp['body'], True, 'dir1 index body')
|
||||
self.assertEqual(resp['headers']['X-TXT-Filter'], '1', 'TXT Filter header')
|
||||
|
||||
headers = self.get(url='/dir2/')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Unit-JSP'], 'ok', 'JSP Ok header')
|
||||
self.assertEqual(headers['X-JSP-Filter'], '1', 'JSP Filter header')
|
||||
|
||||
headers = self.get(url='/dir3/')['headers']
|
||||
|
||||
self.assertEqual(headers['X-App-Servlet'], '1', 'URL pattern overrides welcome file')
|
||||
|
||||
headers = self.get(url='/dir4/')['headers']
|
||||
|
||||
self.assertEqual('X-App-Servlet' in headers, False, 'Static welcome file served first')
|
||||
|
||||
headers = self.get(url='/dir5/')['headers']
|
||||
|
||||
self.assertEqual(headers['X-App-Servlet'], '1', 'Servlet for welcome file served when no static file found')
|
||||
|
||||
def test_java_application_request_listeners(self):
|
||||
self.load('request_listeners')
|
||||
|
||||
headers = self.get(url='/test1')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Request-Initialized'], '/test1',
|
||||
'request initialized event')
|
||||
self.assertEqual(headers['X-Request-Destroyed'], '',
|
||||
'request destroyed event')
|
||||
self.assertEqual(headers['X-Attr-Added'], '',
|
||||
'attribute added event')
|
||||
self.assertEqual(headers['X-Attr-Removed'], '',
|
||||
'attribute removed event')
|
||||
self.assertEqual(headers['X-Attr-Replaced'], '',
|
||||
'attribute replaced event')
|
||||
|
||||
headers = self.get(url='/test2?var1=1')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Request-Initialized'], '/test2',
|
||||
'request initialized event')
|
||||
self.assertEqual(headers['X-Request-Destroyed'], '/test1',
|
||||
'request destroyed event')
|
||||
self.assertEqual(headers['X-Attr-Added'], 'var=1;',
|
||||
'attribute added event')
|
||||
self.assertEqual(headers['X-Attr-Removed'], 'var=1;',
|
||||
'attribute removed event')
|
||||
self.assertEqual(headers['X-Attr-Replaced'], '',
|
||||
'attribute replaced event')
|
||||
|
||||
headers = self.get(url='/test3?var1=1&var2=2')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Request-Initialized'], '/test3',
|
||||
'request initialized event')
|
||||
self.assertEqual(headers['X-Request-Destroyed'], '/test2',
|
||||
'request destroyed event')
|
||||
self.assertEqual(headers['X-Attr-Added'], 'var=1;',
|
||||
'attribute added event')
|
||||
self.assertEqual(headers['X-Attr-Removed'], 'var=2;',
|
||||
'attribute removed event')
|
||||
self.assertEqual(headers['X-Attr-Replaced'], 'var=1;',
|
||||
'attribute replaced event')
|
||||
|
||||
headers = self.get(url='/test4?var1=1&var2=2&var3=3')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Request-Initialized'], '/test4',
|
||||
'request initialized event')
|
||||
self.assertEqual(headers['X-Request-Destroyed'], '/test3',
|
||||
'request destroyed event')
|
||||
self.assertEqual(headers['X-Attr-Added'], 'var=1;',
|
||||
'attribute added event')
|
||||
self.assertEqual(headers['X-Attr-Removed'], '',
|
||||
'attribute removed event')
|
||||
self.assertEqual(headers['X-Attr-Replaced'], 'var=1;var=2;',
|
||||
'attribute replaced event')
|
||||
|
||||
def test_java_application_request_uri_forward(self):
|
||||
self.load('forward')
|
||||
|
||||
resp = self.get(url='/fwd?uri=%2Fdata%2Ftest%3Furi%3Dnew_uri%26a%3D2%26b%3D3&a=1&c=4')
|
||||
headers = resp['headers']
|
||||
|
||||
self.assertEqual(headers['X-REQUEST-Id'], 'fwd',
|
||||
'initial request servlet mapping')
|
||||
self.assertEqual(headers['X-Forward-To'], '/data/test?uri=new_uri&a=2&b=3',
|
||||
'forwarding triggered')
|
||||
self.assertEqual(headers['X-REQUEST-Param-uri'], '/data/test?uri=new_uri&a=2&b=3',
|
||||
'original uri parameter')
|
||||
self.assertEqual(headers['X-REQUEST-Param-a'], '1',
|
||||
'original a parameter')
|
||||
self.assertEqual(headers['X-REQUEST-Param-c'], '4',
|
||||
'original c parameter')
|
||||
|
||||
self.assertEqual(headers['X-FORWARD-Id'], 'data',
|
||||
'forward request servlet mapping')
|
||||
self.assertEqual(headers['X-FORWARD-Request-URI'], '/data/test',
|
||||
'forward request uri')
|
||||
self.assertEqual(headers['X-FORWARD-Servlet-Path'], '/data',
|
||||
'forward request servlet path')
|
||||
self.assertEqual(headers['X-FORWARD-Path-Info'], '/test',
|
||||
'forward request path info')
|
||||
self.assertEqual(headers['X-FORWARD-Query-String'], 'uri=new_uri&a=2&b=3',
|
||||
'forward request query string')
|
||||
self.assertEqual(headers['X-FORWARD-Param-uri'], 'new_uri,/data/test?uri=new_uri&a=2&b=3',
|
||||
'forward uri parameter')
|
||||
self.assertEqual(headers['X-FORWARD-Param-a'], '2,1',
|
||||
'forward a parameter')
|
||||
self.assertEqual(headers['X-FORWARD-Param-b'], '3',
|
||||
'forward b parameter')
|
||||
self.assertEqual(headers['X-FORWARD-Param-c'], '4',
|
||||
'forward c parameter')
|
||||
|
||||
self.assertEqual(headers['X-javax.servlet.forward.request_uri'], '/fwd',
|
||||
'original request uri')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.context_path'], '',
|
||||
'original request context path')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.servlet_path'], '/fwd',
|
||||
'original request servlet path')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.path_info'], 'null',
|
||||
'original request path info')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.query_string'], 'uri=%2Fdata%2Ftest%3Furi%3Dnew_uri%26a%3D2%26b%3D3&a=1&c=4',
|
||||
'original request query')
|
||||
|
||||
self.assertEqual('Before forwarding' in resp['body'], False,
|
||||
'discarded data added before forward() call')
|
||||
self.assertEqual('X-After-Forwarding' in headers, False,
|
||||
'cannot add headers after forward() call')
|
||||
self.assertEqual('After forwarding' in resp['body'], False,
|
||||
'cannot add data after forward() call')
|
||||
|
||||
def test_java_application_named_dispatcher_forward(self):
|
||||
self.load('forward')
|
||||
|
||||
resp = self.get(url='/fwd?disp=name&uri=data')
|
||||
headers = resp['headers']
|
||||
|
||||
self.assertEqual(headers['X-REQUEST-Id'], 'fwd',
|
||||
'initial request servlet mapping')
|
||||
self.assertEqual(headers['X-Forward-To'], 'data',
|
||||
'forwarding triggered')
|
||||
|
||||
self.assertEqual(headers['X-FORWARD-Id'], 'data',
|
||||
'forward request servlet mapping')
|
||||
self.assertEqual(headers['X-FORWARD-Request-URI'], '/fwd',
|
||||
'forward request uri')
|
||||
self.assertEqual(headers['X-FORWARD-Servlet-Path'], '/fwd',
|
||||
'forward request servlet path')
|
||||
self.assertEqual(headers['X-FORWARD-Path-Info'], 'null',
|
||||
'forward request path info')
|
||||
self.assertEqual(headers['X-FORWARD-Query-String'], 'disp=name&uri=data',
|
||||
'forward request query string')
|
||||
|
||||
self.assertEqual(headers['X-javax.servlet.forward.request_uri'], 'null',
|
||||
'original request uri')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.context_path'], 'null',
|
||||
'original request context path')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.servlet_path'], 'null',
|
||||
'original request servlet path')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.path_info'], 'null',
|
||||
'original request path info')
|
||||
self.assertEqual(headers['X-javax.servlet.forward.query_string'], 'null',
|
||||
'original request query')
|
||||
|
||||
self.assertEqual('Before forwarding' in resp['body'], False,
|
||||
'discarded data added before forward() call')
|
||||
self.assertEqual('X-After-Forwarding' in headers, False,
|
||||
'cannot add headers after forward() call')
|
||||
self.assertEqual('After forwarding' in resp['body'], False,
|
||||
'cannot add data after forward() call')
|
||||
|
||||
def test_java_application_request_uri_include(self):
|
||||
self.load('include')
|
||||
|
||||
resp = self.get(url='/inc?uri=/data/test')
|
||||
headers = resp['headers']
|
||||
body = resp['body']
|
||||
|
||||
self.assertEqual(headers['X-REQUEST-Id'], 'inc',
|
||||
'initial request servlet mapping')
|
||||
self.assertEqual(headers['X-Include'], '/data/test',
|
||||
'including triggered')
|
||||
|
||||
self.assertEqual('X-INCLUDE-Id' in headers, False,
|
||||
'unable to add headers in include request')
|
||||
|
||||
self.assertEqual('javax.servlet.include.request_uri: /data/test' in body,
|
||||
True, 'include request uri')
|
||||
# self.assertEqual('javax.servlet.include.context_path: ' in body,
|
||||
# 'include request context path')
|
||||
self.assertEqual('javax.servlet.include.servlet_path: /data' in body,
|
||||
True, 'include request servlet path')
|
||||
self.assertEqual('javax.servlet.include.path_info: /test' in body,
|
||||
True, 'include request path info')
|
||||
self.assertEqual('javax.servlet.include.query_string: null' in body,
|
||||
True, 'include request query')
|
||||
|
||||
self.assertEqual('Before include' in body, True,
|
||||
'preserve data added before include() call')
|
||||
self.assertEqual(headers['X-After-Include'], 'you-should-see-this',
|
||||
'add headers after include() call')
|
||||
self.assertEqual('After include' in body, True,
|
||||
'add data after include() call')
|
||||
|
||||
def test_java_application_named_dispatcher_include(self):
|
||||
self.load('include')
|
||||
|
||||
resp = self.get(url='/inc?disp=name&uri=data')
|
||||
headers = resp['headers']
|
||||
body = resp['body']
|
||||
|
||||
self.assertEqual(headers['X-REQUEST-Id'], 'inc',
|
||||
'initial request servlet mapping')
|
||||
self.assertEqual(headers['X-Include'], 'data',
|
||||
'including triggered')
|
||||
|
||||
self.assertEqual('X-INCLUDE-Id' in headers, False,
|
||||
'unable to add headers in include request')
|
||||
|
||||
self.assertEqual('javax.servlet.include.request_uri: null' in body,
|
||||
True, 'include request uri')
|
||||
# self.assertEqual('javax.servlet.include.context_path: null' in body,
|
||||
# 'include request context path')
|
||||
self.assertEqual('javax.servlet.include.servlet_path: null' in body,
|
||||
True, 'include request servlet path')
|
||||
self.assertEqual('javax.servlet.include.path_info: null' in body,
|
||||
True, 'include request path info')
|
||||
self.assertEqual('javax.servlet.include.query_string: null' in body,
|
||||
True, 'include request query')
|
||||
|
||||
self.assertEqual('Before include' in body, True,
|
||||
'preserve data added before include() call')
|
||||
self.assertEqual(headers['X-After-Include'], 'you-should-see-this',
|
||||
'add headers after include() call')
|
||||
self.assertEqual('After include' in body, True,
|
||||
'add data after include() call')
|
||||
|
||||
def test_java_application_path_translation(self):
|
||||
self.load('path_translation')
|
||||
|
||||
headers = self.get(url='/pt/test?path=/')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/pt',
|
||||
'matched servlet path')
|
||||
self.assertEqual(headers['X-Path-Info'], '/test',
|
||||
'the rest of the path')
|
||||
self.assertEqual(headers['X-Path-Translated'],
|
||||
headers['X-Real-Path'] + headers['X-Path-Info'],
|
||||
'translated path is the app root + path info')
|
||||
self.assertEqual(
|
||||
headers['X-Resource-Paths'].endswith('/WEB-INF/, /index.html]'),
|
||||
True, 'app root directory content')
|
||||
self.assertEqual(headers['X-Resource-As-Stream'], 'null',
|
||||
'no resource stream for root path')
|
||||
|
||||
headers = self.get(url='/test?path=/none')['headers']
|
||||
|
||||
self.assertEqual(headers['X-Servlet-Path'], '/test',
|
||||
'matched whole path')
|
||||
self.assertEqual(headers['X-Path-Info'], 'null',
|
||||
'the rest of the path is null, whole path matched')
|
||||
self.assertEqual(headers['X-Path-Translated'], 'null',
|
||||
'translated path is null because path info is null')
|
||||
self.assertEqual(headers['X-Real-Path'].endswith('/none'), True,
|
||||
'read path is not null')
|
||||
self.assertEqual(headers['X-Resource-Paths'], 'null',
|
||||
'no resource found')
|
||||
self.assertEqual(headers['X-Resource-As-Stream'], 'null',
|
||||
'no resource stream')
|
||||
|
||||
def test_java_application_query_string(self):
|
||||
self.load('query_string')
|
||||
|
||||
self.assertEqual(self.get(url='/?a=b')['headers']['X-Query-String'],
|
||||
'a=b', 'query string')
|
||||
|
||||
def test_java_application_query_empty(self):
|
||||
self.load('query_string')
|
||||
|
||||
self.assertEqual(self.get(url='/?')['headers']['X-Query-String'], '',
|
||||
'query string empty')
|
||||
|
||||
def test_java_application_query_absent(self):
|
||||
self.load('query_string')
|
||||
|
||||
self.assertEqual(self.get()['headers']['X-Query-String'], 'null',
|
||||
'query string absent')
|
||||
|
||||
def test_java_application_empty(self):
|
||||
self.load('empty')
|
||||
|
||||
self.assertEqual(self.get()['status'], 200, 'empty')
|
||||
|
||||
def test_java_application_keepalive_body(self):
|
||||
self.load('mirror')
|
||||
|
||||
(resp, sock) = self.post(headers={
|
||||
'Connection': 'keep-alive',
|
||||
'Content-Type': 'text/html',
|
||||
'Host': 'localhost'
|
||||
}, start=True, body='0123456789' * 500)
|
||||
|
||||
self.assertEqual(resp['body'], '0123456789' * 500, 'keep-alive 1')
|
||||
|
||||
resp = self.post(headers={
|
||||
'Connection': 'close',
|
||||
'Content-Type': 'text/html',
|
||||
'Host': 'localhost'
|
||||
}, sock=sock, body='0123456789')
|
||||
|
||||
self.assertEqual(resp['body'], '0123456789', 'keep-alive 2')
|
||||
|
||||
def test_java_application_http_10(self):
|
||||
self.load('empty')
|
||||
|
||||
self.assertEqual(self.get(http_10=True)['status'], 200, 'HTTP 1.0')
|
||||
|
||||
def test_java_application_no_method(self):
|
||||
self.load('empty')
|
||||
|
||||
self.assertEqual(self.post()['status'], 405, 'no method')
|
||||
|
||||
def test_java_application_get_header(self):
|
||||
self.load('get_header')
|
||||
|
||||
self.assertEqual(self.get(headers={
|
||||
'X-Header': 'blah',
|
||||
'Content-Type': 'text/html',
|
||||
'Host': 'localhost'
|
||||
})['headers']['X-Reply'], 'blah', 'get header')
|
||||
|
||||
def test_java_application_get_header_empty(self):
|
||||
self.load('get_header')
|
||||
|
||||
self.assertNotIn('X-Reply', self.get()['headers'], 'get header empty')
|
||||
|
||||
def test_java_application_get_headers(self):
|
||||
self.load('get_headers')
|
||||
|
||||
headers = self.get(headers={
|
||||
'X-Header': ['blah', 'blah'],
|
||||
'Content-Type': 'text/html',
|
||||
'Host': 'localhost'
|
||||
})['headers']
|
||||
|
||||
self.assertEqual(headers['X-Reply-0'], 'blah', 'get headers')
|
||||
self.assertEqual(headers['X-Reply-1'], 'blah', 'get headers 2')
|
||||
|
||||
def test_java_application_get_headers_empty(self):
|
||||
self.load('get_headers')
|
||||
|
||||
self.assertNotIn('X-Reply-0', self.get()['headers'],
|
||||
'get headers empty')
|
||||
|
||||
def test_java_application_get_header_names(self):
|
||||
self.load('get_header_names')
|
||||
|
||||
headers = self.get()['headers']
|
||||
|
||||
self.assertRegex(headers['X-Reply-0'], r'(?:Host|Connection)',
|
||||
'get header names')
|
||||
self.assertRegex(headers['X-Reply-1'], r'(?:Host|Connection)',
|
||||
'get header names 2')
|
||||
self.assertNotEqual(headers['X-Reply-0'], headers['X-Reply-1'],
|
||||
'get header names not equal')
|
||||
|
||||
def test_java_application_get_header_names_empty(self):
|
||||
self.load('get_header_names')
|
||||
|
||||
self.assertNotIn('X-Reply-0', self.get(headers={})['headers'],
|
||||
'get header names empty')
|
||||
|
||||
def test_java_application_header_int(self):
|
||||
self.load('header_int')
|
||||
|
||||
headers = self.get(headers={
|
||||
'X-Header': '2',
|
||||
'Content-Type': 'text/html',
|
||||
'Host': 'localhost'
|
||||
})['headers']
|
||||
|
||||
self.assertEqual(headers['X-Set-Int'], '1', 'set int header')
|
||||
self.assertEqual(headers['X-Get-Int'], '2', 'get int header')
|
||||
|
||||
def test_java_application_header_date(self):
|
||||
self.load('header_date')
|
||||
|
||||
date = 'Fri, 15 Mar 2019 14:45:34 GMT'
|
||||
|
||||
headers = self.get(headers={
|
||||
'X-Header': date,
|
||||
'Content-Type': 'text/html',
|
||||
'Host': 'localhost'
|
||||
})['headers']
|
||||
|
||||
self.assertEqual(headers['X-Set-Date'], 'Thu, 01 Jan 1970 00:00:01 GMT',
|
||||
'set date header')
|
||||
self.assertEqual(headers['X-Get-Date'], date, 'get date header')
|
||||
|
||||
if __name__ == '__main__':
|
||||
TestUnitJavaApplication.main()
|
||||
66
test/unit.py
66
test/unit.py
@@ -600,6 +600,72 @@ class TestUnitApplicationNode(TestUnitApplicationProto):
|
||||
}
|
||||
})
|
||||
|
||||
class TestUnitApplicationJava(TestUnitApplicationProto):
|
||||
def load(self, script, name='app'):
|
||||
|
||||
app_path = self.testdir + '/java'
|
||||
web_inf_path = app_path + '/WEB-INF/'
|
||||
classes_path = web_inf_path + 'classes/'
|
||||
|
||||
script_path = self.current_dir + '/java/' + script + '/'
|
||||
|
||||
if not os.path.isdir(app_path):
|
||||
os.makedirs(app_path)
|
||||
|
||||
src = []
|
||||
|
||||
for f in os.listdir(script_path):
|
||||
if f.endswith('.java'):
|
||||
src.append(script_path + f)
|
||||
continue
|
||||
|
||||
if f.startswith('.') or f == 'Makefile':
|
||||
continue
|
||||
|
||||
if os.path.isdir(script_path + f):
|
||||
if f == 'WEB-INF':
|
||||
continue
|
||||
|
||||
shutil.copytree(script_path + f, app_path + '/' + f)
|
||||
continue
|
||||
|
||||
if f == 'web.xml':
|
||||
if not os.path.isdir(web_inf_path):
|
||||
os.makedirs(web_inf_path)
|
||||
|
||||
shutil.copy2(script_path + f, web_inf_path)
|
||||
else:
|
||||
shutil.copy2(script_path + f, app_path)
|
||||
|
||||
if src:
|
||||
if not os.path.isdir(classes_path):
|
||||
os.makedirs(classes_path)
|
||||
|
||||
javac = ['javac', '-encoding', 'utf-8', '-d', classes_path,
|
||||
'-classpath',
|
||||
self.pardir + '/build/tomcat-servlet-api-9.0.13.jar']
|
||||
javac.extend(src)
|
||||
|
||||
process = subprocess.Popen(javac)
|
||||
process.communicate()
|
||||
|
||||
self.conf({
|
||||
"listeners": {
|
||||
"*:7080": {
|
||||
"application": script
|
||||
}
|
||||
},
|
||||
"applications": {
|
||||
script: {
|
||||
"unit_jars": self.pardir + '/build',
|
||||
"type": "java",
|
||||
"processes": { "spare": 0 },
|
||||
"working_directory": script_path,
|
||||
"webapp": app_path
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class TestUnitApplicationPerl(TestUnitApplicationProto):
|
||||
def load(self, script, name='psgi.pl'):
|
||||
self.conf({
|
||||
|
||||
Reference in New Issue
Block a user