
io.lightlink.output.JSONResponseStream Maven / Gradle / Ivy
package io.lightlink.output;
/*
* #%L
* lightlink-core
* %%
* Copyright (C) 2015 Vitaliy Shevchuk
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import io.lightlink.config.ConfigManager;
import io.lightlink.core.Hints;
import io.lightlink.core.RunnerContext;
import io.lightlink.facades.TypesFacade;
import io.lightlink.security.AntiXSS;
import io.lightlink.spring.LightLinkFilter;
import io.lightlink.types.DateConverter;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.objects.NativeArray;
import jdk.nashorn.internal.runtime.ScriptObject;
import org.apache.commons.beanutils.BeanMap;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class JSONResponseStream implements ResponseStream {
public static final String PROGRESSIVE_KEY_STR = "\n\t \t\n";
public static final byte[] PROGRESSIVE_KEY = PROGRESSIVE_KEY_STR.getBytes();
public static final Charset CHARSET = Charset.forName("UTF-8");
public static final byte[] TOKEN_ARR_START = "\":[".getBytes();
public static final byte[] TOKEN_OBJ_START = "\":{".getBytes();
public static final String STR_QUOT = "\\\"";
public static final String STR_BACKSLASH = "\\\\";
public static final String STR_B = "\\b";
public static final String STR_F = "\\f";
public static final String STR_N = "\\n";
public static final String STR_R = "\\r";
public static final String STR_T = "\\t";
public static final String STR_SLASH = "\\/";
public static final String STR_SLASH_U = "\\u";
boolean ended = false;
int ident = 0;
boolean debug = ConfigManager.isInDebugMode();
RunnerContext runnerContext;
private boolean commaNeeded;
private boolean started;
private int[] progressiveBlockSizes;
private int currentProgressiveBlock;
private int currentRowNum;
private int openBracesCount;
private boolean antiXSS;
private OutputStream outputStream;
private char rootTagOpen = '{';
private char rootTagClose = '}';
public JSONResponseStream(OutputStream outputStream) {
this.outputStream = outputStream;
commaNeeded = false;
ident = 0;
ended = false;
started = false;
initHints();
}
protected void initHints() {
if (LightLinkFilter.isThreadLocalStreamingDataSet()) {
Hints hints = LightLinkFilter.getThreadLocalStreamingData().getHints();
if (hints != null) {
progressiveBlockSizes = hints.getProgressiveBlockSizes();
antiXSS = hints.isAntiXSS();
}
}
}
protected OutputStream getOutputStream() {
return outputStream;
}
public RunnerContext getRunnerContext() {
return runnerContext;
}
public void setRunnerContext(RunnerContext runnerContext) {
this.runnerContext = runnerContext;
}
private void identIn() {
writeIdent();
ident++;
}
private void identOut() {
ident--;
writeIdent();
}
private void writeIdent() {
if (debug) {
write('\n');
for (int i = 0; i < ident; i++)
write('\t');
}
}
private void write(char c) {
try {
outputStream.write(c);
} catch (IOException e) {
throw new RuntimeException(e.toString(), e);
}
}
protected void write(byte[] byes, int size) {
try {
outputStream.write(byes, 0, size);
} catch (IOException e) {
throw new RuntimeException(e.toString(), e);
}
}
protected void write(byte[] byes) {
try {
outputStream.write(byes);
} catch (IOException e) {
throw new RuntimeException(e.toString(), e);
}
}
private void beginIfNeeded() {
if (!started) {
started = true;
write(rootTagOpen);
openBracesCount++;
ident++;
}
}
@Override
public synchronized void end() {
if (!ended) {
beginIfNeeded();
write(rootTagClose);
openBracesCount--;
ended = true;
}
}
@Override
public synchronized void writeProperty(String name, Object value) {
beginIfNeeded();
comma();
identIn();
write('"');
writeEscapedString(name);
write('"');
write(':');
commaNeeded = false;
writeFullObjectToArray(value);
ident--;
commaNeeded = true;
}
@Override
public synchronized void writeFullObjectToArray(Object value) {
beginIfNeeded();
comma();
if (value != null && value instanceof jdk.nashorn.internal.runtime.ScriptObject) {
ScriptObject so = (ScriptObject) value;
if (so.isArray()) {
writeArrayStart();
int length = ((Number) so.get("length")).intValue();
for (int i = 0; i < length; i++) {
writeFullObjectToArray(genericDateConvert(so.get(i)));
}
writeArrayEnd();
} else {
writeObjectStart();
for (Object key : so.keySet()) {
writeProperty("" + key, genericDateConvert(so.get(key)));
}
writeObjectEnd();
}
return;
} else if (value != null && value instanceof jdk.nashorn.api.scripting.JSObject) {
JSObject jsObject = (JSObject) value;
if (jsObject.isArray()) {
writeArrayStart();
int length = ((Number) jsObject.getMember("length")).intValue();
for (int i = 0; i < length; i++) {
writeFullObjectToArray(genericDateConvert(jsObject.getSlot(i)));
}
writeArrayEnd();
} else {
writeObjectStart();
for (String key : jsObject.keySet()) {
writeProperty(key, genericDateConvert(jsObject.getMember(key)));
}
writeObjectEnd();
}
return;
} else if (value != null && value instanceof jdk.nashorn.internal.objects.NativeArray) {
NativeArray array = (NativeArray) value;
value = array.asObjectArray();
}
List list = new ArrayList();
value = handlePrimitiveArrays(value, list);
if (value instanceof Map) {
writeObjectStart();
Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy