Introducing Java Servlet Container beta.
This commit is contained in:
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_ */
|
||||
|
||||
Reference in New Issue
Block a user