/*
* Copyright (C) NGINX, Inc.
*/
#include <nxt_auto_config.h>
#include <nxt_unit.h>
#include <nxt_unit_response.h>
#include <jni.h>
#include <stdio.h>
#include "nxt_jni.h"
#include "nxt_jni_Response.h"
#include "nxt_jni_HeadersEnumeration.h"
#include "nxt_jni_HeaderNamesEnumeration.h"
#include "nxt_jni_OutputStream.h"
#include "nxt_jni_URLClassLoader.h"
static jclass nxt_java_Response_class;
static jmethodID nxt_java_Response_ctor;
static void JNICALL nxt_java_Response_addHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name, jarray value);
static nxt_unit_request_info_t *nxt_java_get_response_info(
jlong req_info_ptr, uint32_t extra_fields, uint32_t extra_data);
static void JNICALL nxt_java_Response_addIntHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name, jint value);
static void nxt_java_add_int_header(nxt_unit_request_info_t *req,
const char *name, uint8_t name_len, int value);
static jboolean JNICALL nxt_java_Response_containsHeader(JNIEnv *env,
jclass cls, jlong req_info_ptr, jarray name);
static jstring JNICALL nxt_java_Response_getHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name);
static jobject JNICALL nxt_java_Response_getHeaderNames(JNIEnv *env,
jclass cls, jlong req_info_ptr);
static jobject JNICALL nxt_java_Response_getHeaders(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name);
static jint JNICALL nxt_java_Response_getStatus(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static jobject JNICALL nxt_java_Response_getRequest(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static void JNICALL nxt_java_Response_commit(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static void JNICALL nxt_java_Response_sendRedirect(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray loc);
static int nxt_java_response_set_header(jlong req_info_ptr,
const char *name, jint name_len, const char *value, jint value_len);
static void JNICALL nxt_java_Response_setHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name, jarray value);
static void JNICALL nxt_java_Response_removeHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name);
static int nxt_java_response_remove_header(jlong req_info_ptr,
const char *name, jint name_len);
static void JNICALL nxt_java_Response_setIntHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name, jint value);
static void JNICALL nxt_java_Response_setStatus(JNIEnv *env, jclass cls,
jlong req_info_ptr, jint sc);
static jstring JNICALL nxt_java_Response_getContentType(JNIEnv *env,
jclass cls, jlong req_info_ptr);
static jboolean JNICALL nxt_java_Response_isCommitted(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static void JNICALL nxt_java_Response_reset(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static void JNICALL nxt_java_Response_resetBuffer(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static void JNICALL nxt_java_Response_setBufferSize(JNIEnv *env, jclass cls,
jlong req_info_ptr, jint size);
static jint JNICALL nxt_java_Response_getBufferSize(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static void JNICALL nxt_java_Response_setContentLength(JNIEnv *env, jclass cls,
jlong req_info_ptr, jlong len);
static void JNICALL nxt_java_Response_setContentType(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray type);
static void JNICALL nxt_java_Response_removeContentType(JNIEnv *env, jclass cls,
jlong req_info_ptr);
static void JNICALL nxt_java_Response_log(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray msg);
static void JNICALL nxt_java_Response_trace(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray msg);
int
nxt_java_initResponse(JNIEnv *env, jobject cl)
{
int res;
jclass cls;
cls = nxt_java_loadClass(env, cl, "nginx.unit.Response");
if (cls == NULL) {
return NXT_UNIT_ERROR;
}
nxt_java_Response_class = (*env)->NewGlobalRef(env, cls);
(*env)->DeleteLocalRef(env, cls);
cls = nxt_java_Response_class;
nxt_java_Response_ctor = (*env)->GetMethodID(env, cls, "<init>", "(J)V");
if (nxt_java_Response_ctor == NULL) {
(*env)->DeleteGlobalRef(env, cls);
return NXT_UNIT_ERROR;
}
JNINativeMethod resp_methods[] = {
{ (char *) "addHeader",
(char *) "(J[B[B)V",
nxt_java_Response_addHeader },
{ (char *) "addIntHeader",
(char *) "(J[BI)V",
nxt_java_Response_addIntHeader },
{ (char *) "containsHeader",
(char *) "(J[B)Z",
nxt_java_Response_containsHeader },
{ (char *) "getHeader",
(char *) "(J[B)Ljava/lang/String;",
nxt_java_Response_getHeader },
{ (char *) "getHeaderNames",
(char *) "(J)Ljava/util/Enumeration;",
nxt_java_Response_getHeaderNames },
{ (char *) "getHeaders",
(char *) "(J[B)Ljava/util/Enumeration;",
nxt_java_Response_getHeaders },
{ (char *) "getStatus",
(char *) "(J)I",
nxt_java_Response_getStatus },
{ (char *) "getRequest",
(char *) "(J)Lnginx/unit/Request;",
nxt_java_Response_getRequest },
{ (char *) "commit",
(char *) "(J)V",
nxt_java_Response_commit },
{ (char *) "sendRedirect",
(char *) "(J[B)V",
nxt_java_Response_sendRedirect },
{ (char *) "setHeader",
(char *) "(J[B[B)V",
nxt_java_Response_setHeader },
{ (char *) "removeHeader",
(char *) "(J[B)V",
nxt_java_Response_removeHeader },
{ (char *) "setIntHeader",
(char *) "(J[BI)V",
nxt_java_Response_setIntHeader },
{ (char *) "setStatus",
(char *) "(JI)V",
nxt_java_Response_setStatus },
{ (char *) "getContentType",
(char *) "(J)Ljava/lang/String;",
nxt_java_Response_getContentType },
{ (char *) "isCommitted",
(char *) "(J)Z",
nxt_java_Response_isCommitted },
{ (char *) "reset",
(char *) "(J)V",
nxt_java_Response_reset },
{ (char *) "resetBuffer",
(char *) "(J)V",
nxt_java_Response_resetBuffer },
{ (char *) "setBufferSize",
(char *) "(JI)V",
nxt_java_Response_setBufferSize },
{ (char *) "getBufferSize",
(char *) "(J)I",
nxt_java_Response_getBufferSize },
{ (char *) "setContentLength",
(char *) "(JJ)V",
nxt_java_Response_setContentLength },
{ (char *) "setContentType",
(char *) "(J[B)V",
nxt_java_Response_setContentType },
{ (char *) "removeContentType",
(char *) "(J)V",
nxt_java_Response_removeContentType },
{ (char *) "log",
(char *) "(J[B)V",
nxt_java_Response_log },
{ (char *) "trace",
(char *) "(J[B)V",
nxt_java_Response_trace },
};
res = (*env)->RegisterNatives(env, nxt_java_Response_class,
resp_methods,
sizeof(resp_methods)
/ sizeof(resp_methods[0]));
nxt_unit_debug(NULL, "registered Response methods: %d", res);
if (res != 0) {
(*env)->DeleteGlobalRef(env, cls);
return NXT_UNIT_ERROR;
}
return NXT_UNIT_OK;
}
jobject
nxt_java_newResponse(JNIEnv *env, nxt_unit_request_info_t *req)
{
return (*env)->NewObject(env, nxt_java_Response_class,
nxt_java_Response_ctor, nxt_ptr2jlong(req));
}
static void JNICALL
nxt_java_Response_addHeader(JNIEnv *env, jclass cls, jlong req_info_ptr,
jarray name, jarray value)
{
int rc;
char *name_str, *value_str;
jsize name_len, value_len;
nxt_unit_request_info_t *req;
name_len = (*env)->GetArrayLength(env, name);
value_len = (*env)->GetArrayLength(env, value);
req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2);
if (req == NULL) {
return;
}
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
nxt_unit_req_warn(req, "addHeader: failed to get name content");
return;
}
value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL);
if (value_str == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
nxt_unit_req_warn(req, "addHeader: failed to get value content");
return;
}
rc = nxt_unit_response_add_field(req, name_str, name_len,
value_str, value_len);
if (rc != NXT_UNIT_OK) {
// throw
}
(*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0);
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
}
static nxt_unit_request_info_t *
nxt_java_get_response_info(jlong req_info_ptr, uint32_t extra_fields,
uint32_t extra_data)
{
int rc;
char *p;
uint32_t max_size;
nxt_unit_buf_t *buf;
nxt_unit_request_info_t *req;
nxt_java_request_data_t *data;
req = nxt_jlong2ptr(req_info_ptr);
if (nxt_unit_response_is_sent(req)) {
return NULL;
}
data = req->data;
if (!nxt_unit_response_is_init(req)) {
max_size = nxt_unit_buf_max();
max_size = max_size < data->header_size ? max_size : data->header_size;
rc = nxt_unit_response_init(req, 200, 16, max_size);
if (rc != NXT_UNIT_OK) {
return NULL;
}
}
buf = req->response_buf;
if (extra_fields > req->response_max_fields
- req->response->fields_count
|| extra_data > (uint32_t) (buf->end - buf->free))
{
p = buf->start + sizeof(nxt_unit_response_t)
+ req->response_max_fields * sizeof(nxt_unit_field_t);
max_size = 2 * (buf->end - p);
if (max_size > nxt_unit_buf_max()) {
nxt_unit_req_warn(req, "required max_size is too big: %"PRIu32,
max_size);
return NULL;
}
rc = nxt_unit_response_realloc(req, 2 * req->response_max_fields,
max_size);
if (rc != NXT_UNIT_OK) {
nxt_unit_req_warn(req, "reallocation failed: %"PRIu32", %"PRIu32,
2 * req->response_max_fields, max_size);
return NULL;
}
}
return req;
}
static void JNICALL
nxt_java_Response_addIntHeader(JNIEnv *env, jclass cls, jlong req_info_ptr,
jarray name, jint value)
{
char *name_str;
jsize name_len;
nxt_unit_request_info_t *req;
name_len = (*env)->GetArrayLength(env, name);
req = nxt_java_get_response_info(req_info_ptr, 1, name_len + 40);
if (req == NULL) {
return;
}
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
nxt_unit_req_warn(req, "addIntHeader: failed to get name content");
return;
}
nxt_java_add_int_header(req, name_str, name_len, value);
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
}
static void
nxt_java_add_int_header(nxt_unit_request_info_t *req, const char *name,
uint8_t name_len, int value)
{
char *p;
nxt_unit_field_t *f;
nxt_unit_response_t *resp;
resp = req->response;
f = resp->fields + resp->fields_count;
p = req->response_buf->free;
f->hash = nxt_unit_field_hash(name, name_len);
f->skip = 0;
f->name_length = name_len;
nxt_unit_sptr_set(&f->name, p);
memcpy(p, name, name_len);
p += name_len;
nxt_unit_sptr_set(&f->value, p);
f->value_length = snprintf(p, 40, "%d", (int) value);
p += f->value_length + 1;
resp->fields_count++;
req->response_buf->free = p;
}
static jboolean JNICALL
nxt_java_Response_containsHeader(JNIEnv *env,
jclass cls, jlong req_info_ptr, jarray name)
{
jboolean res;
char *name_str;
jsize name_len;
nxt_unit_response_t *resp;
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
if (!nxt_unit_response_is_init(req)) {
nxt_unit_req_debug(req, "containsHeader: response is not initialized");
return 0;
}
if (nxt_unit_response_is_sent(req)) {
nxt_unit_req_debug(req, "containsHeader: response already sent");
return 0;
}
name_len = (*env)->GetArrayLength(env, name);
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
nxt_unit_req_warn(req, "containsHeader: failed to get name content");
return 0;
}
resp = req->response;
res = nxt_java_findHeader(resp->fields,
resp->fields + resp->fields_count,
name_str, name_len) != NULL;
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
return res;
}
static jstring JNICALL
nxt_java_Response_getHeader(JNIEnv *env, jclass cls, jlong req_info_ptr,
jarray name)
{
char *name_str;
jsize name_len;
nxt_unit_field_t *f;
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
if (!nxt_unit_response_is_init(req)) {
nxt_unit_req_debug(req, "getHeader: response is not initialized");
return NULL;
}
if (nxt_unit_response_is_sent(req)) {
nxt_unit_req_debug(req, "getHeader: response already sent");
return NULL;
}
name_len = (*env)->GetArrayLength(env, name);
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
nxt_unit_req_warn(req, "getHeader: failed to get name content");
return NULL;
}
f = nxt_java_findHeader(req->response->fields,
req->response->fields + req->response->fields_count,
name_str, name_len);
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
if (f == NULL) {
return NULL;
}
return nxt_java_newString(env, nxt_unit_sptr_get(&f->value),
f->value_length);
}
static jobject JNICALL
nxt_java_Response_getHeaderNames(JNIEnv *env, jclass cls, jlong req_info_ptr)
{
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
if (!nxt_unit_response_is_init(req)) {
nxt_unit_req_debug(req, "getHeaderNames: response is not initialized");
return NULL;
}
if (nxt_unit_response_is_sent(req)) {
nxt_unit_req_debug(req, "getHeaderNames: response already sent");
return NULL;
}
return nxt_java_newHeaderNamesEnumeration(env, req->response->fields,
req->response->fields_count);
}
static jobject JNICALL
nxt_java_Response_getHeaders(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name)
{
char *name_str;
jsize name_len;
nxt_unit_field_t *f;
nxt_unit_response_t *resp;
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
if (!nxt_unit_response_is_init(req)) {
nxt_unit_req_debug(req, "getHeaders: response is not initialized");
return NULL;
}
if (nxt_unit_response_is_sent(req)) {
nxt_unit_req_debug(req, "getHeaders: response already sent");
return NULL;
}
resp = req->response;
name_len = (*env)->GetArrayLength(env, name);
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
nxt_unit_req_warn(req, "getHeaders: failed to get name content");
return NULL;
}
f = nxt_java_findHeader(resp->fields, resp->fields + resp->fields_count,
name_str, name_len);
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
if (f == NULL) {
f = resp->fields + resp->fields_count;
}
return nxt_java_newHeadersEnumeration(env, resp->fields, resp->fields_count,
f - resp->fields);
}
static jint JNICALL
nxt_java_Response_getStatus(JNIEnv *env, jclass cls, jlong req_info_ptr)
{
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
if (!nxt_unit_response_is_init(req)) {
nxt_unit_req_debug(req, "getStatus: response is not initialized");
return 200;
}
if (nxt_unit_response_is_sent(req)) {
nxt_unit_req_debug(req, "getStatus: response already sent");
return 200;
}
return req->response->status;
}
static jobject JNICALL
nxt_java_Response_getRequest(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->jreq;
}
static void JNICALL
nxt_java_Response_commit(JNIEnv *env, jclass cls, jlong req_info_ptr)
{
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
nxt_java_OutputStream_flush_buf(env, req);
}
static void JNICALL
nxt_java_Response_sendRedirect(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray loc)
{
int rc;
char *loc_str;
jsize loc_len;
nxt_unit_request_info_t *req;
static const char location[] = "Location";
static const uint32_t location_len = sizeof(location) - 1;
req = nxt_jlong2ptr(req_info_ptr);
if (nxt_unit_response_is_sent(req)) {
nxt_java_throw_IllegalStateException(env, "Response already sent");
return;
}
loc_len = (*env)->GetArrayLength(env, loc);
req = nxt_java_get_response_info(req_info_ptr, 1,
location_len + loc_len + 2);
if (req == NULL) {
return;
}
loc_str = (*env)->GetPrimitiveArrayCritical(env, loc, NULL);
if (loc_str == NULL) {
nxt_unit_req_warn(req, "sendRedirect: failed to get loc content");
return;
}
req->response->status = 302;
rc = nxt_java_response_set_header(req_info_ptr, location, location_len,
loc_str, loc_len);
if (rc != NXT_UNIT_OK) {
// throw
}
(*env)->ReleasePrimitiveArrayCritical(env, loc, loc_str, 0);
nxt_unit_response_send(req);
}
static int
nxt_java_response_set_header(jlong req_info_ptr,
const char *name, jint name_len, const char *value, jint value_len)
{
int add_field;
char *dst;
nxt_unit_field_t *f, *e;
nxt_unit_response_t *resp;
nxt_unit_request_info_t *req;
req = nxt_java_get_response_info(req_info_ptr, 0, 0);
if (req == NULL) {
return NXT_UNIT_ERROR;
}
resp = req->response;
f = resp->fields;
e = f + resp->fields_count;
add_field = 1;
for ( ;; ) {
f = nxt_java_findHeader(f, e, name, name_len);
if (f == NULL) {
break;
}
if (add_field && f->value_length >= (uint32_t) value_len) {
dst = nxt_unit_sptr_get(&f->value);
memcpy(dst, value, value_len);
dst[value_len] = '\0';
f->value_length = value_len;
add_field = 0;
f->skip = 0;
} else {
f->skip = 1;
}
++f;
}
if (!add_field) {
return NXT_UNIT_OK;
}
req = nxt_java_get_response_info(req_info_ptr, 1, name_len + value_len + 2);
if (req == NULL) {
return NXT_UNIT_ERROR;
}
return nxt_unit_response_add_field(req, name, name_len, value, value_len);
}
static void JNICALL
nxt_java_Response_setHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name, jarray value)
{
int rc;
char *name_str, *value_str;
jsize name_len, value_len;
nxt_unit_request_info_t *req;
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
req = nxt_jlong2ptr(req_info_ptr);
nxt_unit_req_warn(req, "setHeader: failed to get name content");
return;
}
value_str = (*env)->GetPrimitiveArrayCritical(env, value, NULL);
if (value_str == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
req = nxt_jlong2ptr(req_info_ptr);
nxt_unit_req_warn(req, "setHeader: failed to get value content");
return;
}
name_len = (*env)->GetArrayLength(env, name);
value_len = (*env)->GetArrayLength(env, value);
rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len,
value_str, value_len);
if (rc != NXT_UNIT_OK) {
// throw
}
(*env)->ReleasePrimitiveArrayCritical(env, value, value_str, 0);
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
}
static void JNICALL
nxt_java_Response_removeHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name)
{
int rc;
char *name_str;
jsize name_len;
nxt_unit_request_info_t *req;
name_len = (*env)->GetArrayLength(env, name);
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
req = nxt_jlong2ptr(req_info_ptr);
nxt_unit_req_warn(req, "setHeader: failed to get name content");
return;
}
rc = nxt_java_response_remove_header(req_info_ptr, name_str, name_len);
if (rc != NXT_UNIT_OK) {
// throw
}
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
}
static int
nxt_java_response_remove_header(jlong req_info_ptr,
const char *name, jint name_len)
{
nxt_unit_field_t *f, *e;
nxt_unit_response_t *resp;
nxt_unit_request_info_t *req;
req = nxt_java_get_response_info(req_info_ptr, 0, 0);
if (req == NULL) {
return NXT_UNIT_ERROR;
}
resp = req->response;
f = resp->fields;
e = f + resp->fields_count;
for ( ;; ) {
f = nxt_java_findHeader(f, e, name, name_len);
if (f == NULL) {
break;
}
f->skip = 1;
++f;
}
return NXT_UNIT_OK;
}
static void JNICALL
nxt_java_Response_setIntHeader(JNIEnv *env, jclass cls,
jlong req_info_ptr, jarray name, jint value)
{
int value_len, rc;
char value_str[40];
char *name_str;
jsize name_len;
value_len = snprintf(value_str, sizeof(value_str), "%d", (int) value);
name_len = (*env)->GetArrayLength(env, name);
name_str = (*env)->GetPrimitiveArrayCritical(env, name, NULL);
if (name_str == NULL) {
nxt_unit_req_warn(nxt_jlong2ptr(req_info_ptr),
"setIntHeader: failed to get name content");
return;
}
rc = nxt_java_response_set_header(req_info_ptr, name_str, name_len,
value_str, value_len);
if (rc != NXT_UNIT_OK) {
// throw
}
(*env)->ReleasePrimitiveArrayCritical(env, name, name_str, 0);
}
static void JNICALL
nxt_java_Response_setStatus(JNIEnv *env, jclass cls, jlong req_info_ptr,
jint sc)
{
nxt_unit_request_info_t *req;
req = nxt_java_get_response_info(req_info_ptr, 0, 0);
if (req == NULL) {
return;
}
req->response->status = sc;
}
static jstring JNICALL
nxt_java_Response_getContentType(JNIEnv *env, jclass cls, jlong req_info_ptr)
{
nxt_unit_field_t *f;
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
if (!nxt_unit_response_is_init(req)) {
nxt_unit_req_debug(req, "getContentType: response is not initialized");
return NULL;
}
if (nxt_unit_response_is_sent(req)) {
nxt_unit_req_debug(req, "getContentType: response already sent");
return NULL;
}
f = nxt_java_findHeader(req->response->fields,
req->response->fields + req->response->fields_count,
"Content-Type", sizeof("Content-Type") - 1);
if (f == NULL) {
return NULL;
}
return nxt_java_newString(env, nxt_unit_sptr_get(&f->value),
f->value_length);
}
static jboolean JNICALL
nxt_java_Response_isCommitted(JNIEnv *env, jclass cls, jlong req_info_ptr)
{
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
if (nxt_unit_response_is_sent(req)) {
return 1;
}
return 0;
}
static void JNICALL
nxt_java_Response_reset(JNIEnv *env, jclass cls, jlong req_info_ptr)
{
nxt_unit_buf_t *buf;
nxt_unit_request_info_t *req;
nxt_java_request_data_t *data;
req = nxt_jlong2ptr(req_info_ptr);
if (nxt_unit_response_is_sent(req)) {
nxt_java_throw_IllegalStateException(env, "Response already sent");
return;
}
data = req->data;
if (data->buf != NULL && data->buf->free > data->buf->start) {
data->buf->free = data->buf->start;
}
if (nxt_unit_response_is_init(req)) {
req->response->status = 200;
req->response->fields_count = 0;
buf = req->response_buf;
buf->free = buf->start + sizeof(nxt_unit_response_t)
+ req->response_max_fields * sizeof(nxt_unit_field_t);
}
}
static void JNICALL
nxt_java_Response_resetBuffer(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) {
data->buf->free = data->buf->start;
}
}
static void JNICALL
nxt_java_Response_setBufferSize(JNIEnv *env, jclass cls, jlong req_info_ptr,
jint size)
{
nxt_unit_request_info_t *req;
nxt_java_request_data_t *data;
req = nxt_jlong2ptr(req_info_ptr);
data = req->data;
if (data->buf_size == (uint32_t) size) {
return;
}
if (data->buf != NULL && data->buf->free > data->buf->start) {
nxt_java_throw_IllegalStateException(env, "Buffer is not empty");
return;
}
data->buf_size = size;
if (data->buf_size > nxt_unit_buf_max()) {
data->buf_size = nxt_unit_buf_max();
}
if (data->buf != NULL
&& (uint32_t) (data->buf->end - data->buf->start) < data->buf_size)
{
nxt_unit_buf_free(data->buf);
data->buf = NULL;
}
}
static jint JNICALL
nxt_java_Response_getBufferSize(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->buf_size;
}
static void JNICALL
nxt_java_Response_setContentLength(JNIEnv *env, jclass cls, jlong req_info_ptr,
jlong len)
{
nxt_unit_request_info_t *req;
req = nxt_java_get_response_info(req_info_ptr, 0, 0);
if (req == NULL) {
return;
}
req->response->content_length = len;
}
static void JNICALL
nxt_java_Response_setContentType(JNIEnv *env, jclass cls, jlong req_info_ptr,
jarray type)
{
int rc;
char *type_str;
jsize type_len;
static const char content_type[] = "Content-Type";
static const uint32_t content_type_len = sizeof(content_type) - 1;
type_len = (*env)->GetArrayLength(env, type);
type_str = (*env)->GetPrimitiveArrayCritical(env, type, NULL);
if (type_str == NULL) {
return;
}
rc = nxt_java_response_set_header(req_info_ptr,
content_type, content_type_len,
type_str, type_len);
if (rc != NXT_UNIT_OK) {
// throw
}
(*env)->ReleasePrimitiveArrayCritical(env, type, type_str, 0);
}
static void JNICALL
nxt_java_Response_removeContentType(JNIEnv *env, jclass cls, jlong req_info_ptr)
{
nxt_java_response_remove_header(req_info_ptr, "Content-Type",
sizeof("Content-Type") - 1);
}
static void JNICALL
nxt_java_Response_log(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray msg)
{
char *msg_str;
jsize msg_len;
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
msg_len = (*env)->GetArrayLength(env, msg);
msg_str = (*env)->GetPrimitiveArrayCritical(env, msg, NULL);
if (msg_str == NULL) {
nxt_unit_req_warn(req, "log: failed to get msg content");
return;
}
nxt_unit_req_log(req, NXT_UNIT_LOG_INFO, "%.*s", msg_len, msg_str);
(*env)->ReleasePrimitiveArrayCritical(env, msg, msg_str, 0);
}
static void JNICALL
nxt_java_Response_trace(JNIEnv *env, jclass cls, jlong req_info_ptr, jarray msg)
{
#if (NXT_DEBUG)
char *msg_str;
jsize msg_len;
nxt_unit_request_info_t *req;
req = nxt_jlong2ptr(req_info_ptr);
msg_len = (*env)->GetArrayLength(env, msg);
msg_str = (*env)->GetPrimitiveArrayCritical(env, msg, NULL);
if (msg_str == NULL) {
nxt_unit_req_warn(req, "trace: failed to get msg content");
return;
}
nxt_unit_req_debug(req, "%.*s", msg_len, msg_str);
(*env)->ReleasePrimitiveArrayCritical(env, msg, msg_str, 0);
#endif
}