use of org.structr.core.GraphObject in project structr by structr.
the class CsvServlet method doPost.
@Override
protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
final String fieldSeparatorHeader = request.getHeader(DEFAULT_FIELD_SEPARATOR_HEADER_NAME);
final char fieldSeparator = (fieldSeparatorHeader == null) ? DEFAULT_FIELD_SEPARATOR : fieldSeparatorHeader.charAt(0);
final String quoteCharacterHeader = request.getHeader(DEFAULT_QUOTE_CHARACTER_HEADER_NAME);
final char quoteCharacter = (quoteCharacterHeader == null) ? DEFAULT_QUOTE_CHARACTER : quoteCharacterHeader.charAt(0);
final String doPeridicCommitHeader = request.getHeader(DEFAULT_PERIODIC_COMMIT_HEADER_NAME);
final boolean doPeriodicCommit = (doPeridicCommitHeader == null) ? DEFAULT_PERIODIC_COMMIT : Boolean.parseBoolean(doPeridicCommitHeader);
final String periodicCommitIntervalHeader = request.getHeader(DEFAULT_PERIODIC_COMMIT_INTERVAL_HEADER_NAME);
final int periodicCommitInterval = (periodicCommitIntervalHeader == null) ? DEFAULT_PERIODIC_COMMIT_INTERVAL : Integer.parseInt(periodicCommitIntervalHeader);
final String rangeHeader = request.getHeader(DEFAULT_RANGE_HEADER_NAME);
final List<RestMethodResult> results = new LinkedList<>();
final Authenticator authenticator;
final Resource resource;
try {
// first thing to do!
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
// get reader before initalizing security context
final Reader input = request.getReader();
// isolate request authentication in a transaction
try (final Tx tx = StructrApp.getInstance().tx()) {
authenticator = config.getAuthenticator();
securityContext = authenticator.initializeAndExamineRequest(request, response);
tx.success();
}
final App app = StructrApp.getInstance(securityContext);
if (securityContext != null) {
// isolate resource authentication
try (final Tx tx = app.tx()) {
resource = ResourceHelper.applyViewTransformation(request, securityContext, ResourceHelper.optimizeNestedResourceChain(securityContext, request, resourceMap, propertyView), propertyView);
authenticator.checkResourceAccess(securityContext, request, resource.getResourceSignature(), propertyView.get(securityContext));
tx.success();
}
// do not send websocket notifications for created objects
securityContext.setDoTransactionNotifications(false);
securityContext.disableModificationOfAccessTime();
securityContext.ignoreResultCount(true);
securityContext.disableEnsureCardinality();
final String username = securityContext.getUser(false).getName();
final long startTime = System.currentTimeMillis();
final Map<String, Object> data = new LinkedHashMap();
data.put("type", "CSV_IMPORT_STATUS");
data.put("subtype", "BEGIN");
data.put("username", username);
TransactionCommand.simpleBroadcastGenericMessage(data);
// isolate doPost
boolean retry = true;
while (retry) {
retry = false;
final Iterable<JsonInput> csv = CsvHelper.cleanAndParseCSV(securityContext, input, resource.getEntityClass(), fieldSeparator, quoteCharacter, rangeHeader);
if (resource.createPostTransaction()) {
if (doPeriodicCommit) {
final List<JsonInput> list = new ArrayList<>();
csv.iterator().forEachRemaining(list::add);
final List<List<JsonInput>> chunkedCsv = ListUtils.partition(list, periodicCommitInterval);
final int totalChunkNo = chunkedCsv.size();
int currentChunkNo = 0;
for (final List<JsonInput> currentChunk : chunkedCsv) {
try (final Tx tx = app.tx()) {
currentChunkNo++;
for (final JsonInput propertySet : currentChunk) {
handleCsvPropertySet(results, resource, propertySet);
}
tx.success();
logger.info("CSV: Finished importing chunk " + currentChunkNo + " / " + totalChunkNo);
final Map<String, Object> chunkMsgData = new LinkedHashMap();
chunkMsgData.put("type", "CSV_IMPORT_STATUS");
chunkMsgData.put("subtype", "CHUNK");
chunkMsgData.put("currentChunkNo", currentChunkNo);
chunkMsgData.put("totalChunkNo", totalChunkNo);
chunkMsgData.put("username", username);
TransactionCommand.simpleBroadcastGenericMessage(chunkMsgData);
} catch (RetryException ddex) {
retry = true;
}
}
} else {
try (final Tx tx = app.tx()) {
for (final JsonInput propertySet : csv) {
handleCsvPropertySet(results, resource, propertySet);
}
tx.success();
} catch (RetryException ddex) {
retry = true;
}
}
} else {
if (doPeriodicCommit) {
logger.warn("Resource auto-creates POST transaction - can not commit periodically!");
}
try {
for (final JsonInput propertySet : csv) {
handleCsvPropertySet(results, resource, propertySet);
}
} catch (RetryException ddex) {
retry = true;
}
}
}
final long endTime = System.currentTimeMillis();
DecimalFormat decimalFormat = new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
final String duration = decimalFormat.format(((endTime - startTime) / 1000.0)) + "s";
logger.info("CSV: Finished importing CSV data (Time: {})", duration);
final Map<String, Object> endMsgData = new LinkedHashMap();
endMsgData.put("type", "CSV_IMPORT_STATUS");
endMsgData.put("subtype", "END");
endMsgData.put("duration", duration);
endMsgData.put("username", username);
TransactionCommand.simpleBroadcastGenericMessage(endMsgData);
// set default value for property view
propertyView.set(securityContext, config.getDefaultPropertyView());
// isolate write output
try (final Tx tx = app.tx()) {
if (!results.isEmpty()) {
final RestMethodResult result = results.get(0);
final int resultCount = results.size();
if (result != null) {
if (resultCount > 1) {
for (final RestMethodResult r : results) {
final GraphObject objectCreated = r.getContent().get(0);
if (!result.getContent().contains(objectCreated)) {
result.addContent(objectCreated);
}
}
// remove Location header if more than one object was
// written because it may only contain a single URL
result.addHeader("Location", null);
}
result.commitResponse(gson.get(), response);
}
}
tx.success();
}
} else {
// isolate write output
try (final Tx tx = app.tx()) {
new RestMethodResult(HttpServletResponse.SC_FORBIDDEN).commitResponse(gson.get(), response);
tx.success();
}
}
} catch (FrameworkException frameworkException) {
// set status & write JSON output
response.setStatus(frameworkException.getStatus());
gson.get().toJson(frameworkException, response.getWriter());
response.getWriter().println();
} catch (JsonSyntaxException jsex) {
logger.warn("POST: Invalid JSON syntax", jsex.getMessage());
int code = HttpServletResponse.SC_BAD_REQUEST;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + jsex.getMessage()));
} catch (JsonParseException jpex) {
logger.warn("Unable to parse JSON string", jpex.getMessage());
int code = HttpServletResponse.SC_BAD_REQUEST;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "JsonParseException in POST: " + jpex.getMessage()));
} catch (UnsupportedOperationException uoe) {
logger.warn("POST not supported");
int code = HttpServletResponse.SC_BAD_REQUEST;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "POST not supported: " + uoe.getMessage()));
} catch (Throwable t) {
logger.warn("Exception in POST", t);
int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + t.getMessage()));
} finally {
try {
// response.getWriter().flush();
response.getWriter().close();
} catch (Throwable t) {
logger.warn("Unable to flush and close response: {}", t.getMessage());
}
}
}
use of org.structr.core.GraphObject in project structr by structr.
the class CsvServlet method writeCsv.
/**
* Write list of objects to output
*
* @param result
* @param out
* @param propertyView
* @throws IOException
*/
public static void writeCsv(final Result result, final Writer out, final String propertyView) throws IOException {
final List<GraphObject> list = result.getResults();
final StringBuilder row = new StringBuilder();
boolean headerWritten = false;
for (final GraphObject obj : list) {
// Write column headers
if (!headerWritten) {
row.setLength(0);
for (PropertyKey key : obj.getPropertyKeys(propertyView)) {
row.append("\"").append(key.dbName()).append("\"").append(DEFAULT_FIELD_SEPARATOR);
}
// remove last ;
int pos = row.lastIndexOf("" + DEFAULT_FIELD_SEPARATOR);
if (pos >= 0) {
row.deleteCharAt(pos);
}
// append DOS-style line feed as defined in RFC 4180
out.append(row).append("\r\n");
// flush each line
out.flush();
headerWritten = true;
}
row.setLength(0);
for (PropertyKey key : obj.getPropertyKeys(propertyView)) {
Object value = obj.getProperty(key);
row.append("\"").append((value != null ? escapeForCsv(value) : "")).append("\"").append(DEFAULT_FIELD_SEPARATOR);
}
// remove last ;
row.deleteCharAt(row.lastIndexOf("" + DEFAULT_FIELD_SEPARATOR));
out.append(row).append("\r\n");
// flush each line
out.flush();
}
}
use of org.structr.core.GraphObject in project structr by structr.
the class JsonRestServlet method doPost.
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="POST">
@Override
protected void doPost(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final List<RestMethodResult> results = new LinkedList<>();
final SecurityContext securityContext;
final Authenticator authenticator;
final Resource resource;
try {
assertInitialized();
// first thing to do!
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
// get reader before initalizing security context
final String input = IOUtils.toString(request.getReader());
// isolate request authentication in a transaction
try (final Tx tx = StructrApp.getInstance().tx()) {
authenticator = config.getAuthenticator();
securityContext = authenticator.initializeAndExamineRequest(request, response);
tx.success();
}
final App app = StructrApp.getInstance(securityContext);
final IJsonInput jsonInput = cleanAndParseJsonString(app, input);
if (securityContext != null) {
// isolate resource authentication
try (final Tx tx = app.tx()) {
resource = ResourceHelper.applyViewTransformation(request, securityContext, ResourceHelper.optimizeNestedResourceChain(securityContext, request, resourceMap, propertyView), propertyView);
authenticator.checkResourceAccess(securityContext, request, resource.getResourceSignature(), propertyView.get(securityContext));
tx.success();
}
// isolate doPost
boolean retry = true;
while (retry) {
if (resource.createPostTransaction()) {
try (final Tx tx = app.tx()) {
for (JsonInput propertySet : jsonInput.getJsonInputs()) {
results.add(resource.doPost(convertPropertySetToMap(propertySet)));
}
tx.success();
retry = false;
} catch (RetryException ddex) {
retry = true;
}
} else {
try {
for (JsonInput propertySet : jsonInput.getJsonInputs()) {
results.add(resource.doPost(convertPropertySetToMap(propertySet)));
}
retry = false;
} catch (RetryException ddex) {
retry = true;
}
}
}
// set default value for property view
propertyView.set(securityContext, config.getDefaultPropertyView());
// isolate write output
try (final Tx tx = app.tx()) {
if (!results.isEmpty()) {
final RestMethodResult result = results.get(0);
final int resultCount = results.size();
if (result != null) {
if (resultCount > 1) {
for (final RestMethodResult r : results) {
final GraphObject objectCreated = r.getContent().get(0);
if (!result.getContent().contains(objectCreated)) {
result.addContent(objectCreated);
}
}
// remove Location header if more than one object was
// written because it may only contain a single URL
result.addHeader("Location", null);
}
result.commitResponse(gson.get(), response);
}
}
tx.success();
}
} else {
// isolate write output
try (final Tx tx = app.tx()) {
new RestMethodResult(HttpServletResponse.SC_FORBIDDEN).commitResponse(gson.get(), response);
tx.success();
}
}
} catch (FrameworkException frameworkException) {
// set status & write JSON output
response.setStatus(frameworkException.getStatus());
gson.get().toJson(frameworkException, response.getWriter());
response.getWriter().println();
} catch (JsonSyntaxException jsex) {
logger.warn("POST: Invalid JSON syntax", jsex.getMessage());
int code = HttpServletResponse.SC_BAD_REQUEST;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + jsex.getMessage()));
} catch (JsonParseException jpex) {
logger.warn("Unable to parse JSON string", jpex.getMessage());
int code = HttpServletResponse.SC_BAD_REQUEST;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "JsonParseException in POST: " + jpex.getMessage()));
} catch (UnsupportedOperationException uoe) {
logger.warn("POST not supported");
int code = HttpServletResponse.SC_BAD_REQUEST;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "POST not supported: " + uoe.getMessage()));
} catch (Throwable t) {
logger.warn("Exception in POST", t);
int code = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
response.setStatus(code);
response.getWriter().append(RestMethodResult.jsonError(code, "JsonSyntaxException in POST: " + t.getMessage()));
} finally {
try {
// response.getWriter().flush();
response.getWriter().close();
} catch (Throwable t) {
logger.warn("Unable to flush and close response: {}", t.getMessage());
}
}
}
use of org.structr.core.GraphObject in project structr by structr.
the class StreamingWriter method stream.
public void stream(final SecurityContext securityContext, final Writer output, final Result result, final String baseUrl) throws IOException {
long t0 = System.nanoTime();
RestWriter writer = getRestWriter(securityContext, output);
if (indent) {
writer.setIndent(" ");
}
// result fields in alphabetical order
List<? extends GraphObject> results = result.getResults();
Integer outputNestingDepth = result.getOutputNestingDepth();
Integer page = result.getPage();
Integer pageCount = result.getPageCount();
Integer pageSize = result.getPageSize();
String queryTime = result.getQueryTime();
Integer resultCount = result.getRawResultCount();
String searchString = result.getSearchString();
String sortKey = result.getSortKey();
String sortOrder = result.getSortOrder();
GraphObject metaData = result.getMetaData();
writer.beginDocument(baseUrl, propertyView.get(securityContext));
// open result set
writer.beginObject();
if (outputNestingDepth != null) {
writer.name("output_nesting_depth").value(outputNestingDepth);
}
if (page != null) {
writer.name("page").value(page);
}
if (pageCount != null) {
writer.name("page_count").value(pageCount);
}
if (pageSize != null) {
writer.name("page_size").value(pageSize);
}
if (queryTime != null) {
writer.name("query_time").value(queryTime);
}
if (resultCount != null && renderResultCount) {
writer.name("result_count").value(resultCount);
}
if (results != null) {
if (results.isEmpty() && result.isPrimitiveArray()) {
writer.name(resultKeyName).nullValue();
} else if (results.isEmpty() && !result.isPrimitiveArray()) {
writer.name(resultKeyName).beginArray().endArray();
} else if (result.isPrimitiveArray()) {
writer.name(resultKeyName);
if (results.size() > 1) {
writer.beginArray();
}
for (final Object object : results) {
if (object != null) {
if (object instanceof GraphObject) {
// keep track of serialization time
final long startTime = System.currentTimeMillis();
final String localPropertyView = propertyView.get(null);
final GraphObject obj = (GraphObject) object;
final Iterator<PropertyKey> keyIt = obj.getPropertyKeys(localPropertyView).iterator();
while (keyIt.hasNext()) {
PropertyKey k = keyIt.next();
Object value = obj.getProperty(k);
root.serializeProperty(writer, k, value, localPropertyView, 0);
}
// check for timeout
if (System.currentTimeMillis() > startTime + MAX_SERIALIZATION_TIME) {
logger.error("JSON serialization of {} with {} results took more than {} ms, aborted. Please review output view size or adjust timeout.", new Object[] { securityContext.getCompoundRequestURI(), results.size(), MAX_SERIALIZATION_TIME });
// TODO: create some output indicating that streaming was interrupted
break;
}
} else {
writer.value(object.toString());
}
}
}
if (results.size() > 1) {
writer.endArray();
}
} else {
// result is an attribute called via REST API
if (results.size() > 1 && !result.isCollection()) {
throw new IllegalStateException(result.getClass().getSimpleName() + " is not a collection resource, but result set has size " + results.size());
}
// keep track of serialization time
long startTime = System.currentTimeMillis();
String localPropertyView = propertyView.get(null);
if (result.isCollection()) {
writer.name(resultKeyName).beginArray();
// serialize list of results
for (GraphObject graphObject : results) {
root.serialize(writer, graphObject, localPropertyView, 0);
// check for timeout
if (System.currentTimeMillis() > startTime + MAX_SERIALIZATION_TIME) {
logger.error("JSON serialization of {} with {} results took more than {} ms, aborted. Please review output view size or adjust timeout.", new Object[] { securityContext.getRequest().getRequestURI().concat((securityContext.getRequest().getQueryString() == null) ? "" : "?".concat(securityContext.getRequest().getQueryString())), results.size(), MAX_SERIALIZATION_TIME });
// TODO: create some output indicating that streaming was interrupted
break;
}
}
writer.endArray();
} else {
writer.name(resultKeyName);
root.serialize(writer, results.get(0), localPropertyView, 0);
}
}
}
if (searchString != null) {
writer.name("search_string").value(searchString);
}
if (sortKey != null) {
writer.name("sort_key").value(sortKey);
}
if (sortOrder != null) {
writer.name("sort_order").value(sortOrder);
}
if (metaData != null) {
String localPropertyView = propertyView.get(null);
writer.name("meta_data");
root.serialize(writer, metaData, localPropertyView, 0);
}
if (renderSerializationTime) {
writer.name("serialization_time").value(decimalFormat.format((System.nanoTime() - t0) / 1000000000.0));
}
// finished
writer.endObject();
writer.endDocument();
}
use of org.structr.core.GraphObject in project structr by structr.
the class AbstractHintProvider method getAllHints.
protected List<Hint> getAllHints(final GraphObject currentNode, final String currentToken, final String previousToken, final String thirdToken) {
final boolean isDeclaration = isJavascript() && "var".equals(previousToken);
final boolean isAssignment = isJavascript() && "=".equals(previousToken);
final boolean isDotNotationRequest = ".".equals(currentToken);
final ConfigurationProvider config = StructrApp.getConfiguration();
final Map<String, DataKey> dataKeys = new TreeMap<>();
final List<Hint> hints = new LinkedList<>();
final List<Hint> local = new LinkedList<>();
Class currentObjectType = null;
// data key etc. hints
if (currentNode != null) {
recursivelyFindDataKeys(currentNode, dataKeys);
}
switch(previousToken) {
case "current":
currentObjectType = AbstractNode.class;
break;
case "this":
currentObjectType = DOMNode.class;
break;
case "me":
currentObjectType = User.class;
break;
case "page":
currentObjectType = Page.class;
break;
case "link":
currentObjectType = File.class;
break;
case "template":
currentObjectType = Template.class;
break;
case "parent":
currentObjectType = DOMElement.class;
break;
default:
DataKey key = dataKeys.get(previousToken);
if (key != null) {
currentObjectType = key.identifyType(config);
} else if (StringUtils.isNotBlank(thirdToken)) {
key = dataKeys.get(thirdToken);
if (key != null) {
currentObjectType = key.identifyType(config);
if (currentObjectType != null) {
final PropertyKey nestedKey = StructrApp.key(currentObjectType, previousToken);
if (nestedKey != null) {
currentObjectType = nestedKey.relatedType();
}
}
}
}
break;
}
if (!keywords.contains(previousToken) && !isDotNotationRequest && !dataKeys.containsKey(previousToken)) {
if (!isAssignment) {
for (final Function<Object, Object> func : Functions.getFunctions()) {
hints.add(func);
}
}
Collections.sort(hints, comparator);
// non-function hints
local.add(createHint("current", "", "Current data object", !isJavascript() ? null : "get('current')"));
local.add(createHint("request", "", "Current request object", !isJavascript() ? null : "get('request')"));
local.add(createHint("this", "", "Current object", !isJavascript() ? null : "get('this')"));
local.add(createHint("element", "", "Current object", !isJavascript() ? null : "get('element')"));
local.add(createHint("page", "", "Current page", !isJavascript() ? null : "get('page')"));
local.add(createHint("link", "", "Current link", !isJavascript() ? null : "get('link')"));
local.add(createHint("template", "", "Closest template node", !isJavascript() ? null : "get('template')"));
local.add(createHint("parent", "", "Parent node", !isJavascript() ? null : "get('parent')"));
local.add(createHint("children", "", "Collection of child nodes", !isJavascript() ? null : "get('children')"));
local.add(createHint("host", "", "Client's host name", !isJavascript() ? null : "get('host')"));
local.add(createHint("port", "", "Client's port", !isJavascript() ? null : "get('port')"));
local.add(createHint("path_info", "", "URL path", !isJavascript() ? null : "get('path_info')"));
local.add(createHint("now", "", "Current date", !isJavascript() ? null : "get('now')"));
local.add(createHint("me", "", "Current user", !isJavascript() ? null : "get('me)"));
local.add(createHint("locale", "", "Current locale", !isJavascript() ? null : "get('locale')"));
}
// add local hints to the beginning of the list
Collections.sort(local, comparator);
hints.addAll(0, local);
// prepend data keys
if (currentObjectType == null && !dataKeys.containsKey(previousToken) && !isDotNotationRequest || isAssignment) {
for (final DataKey dataKey : dataKeys.values()) {
final String replacement = isJavascript() && !isDeclaration ? "get('" + dataKey.getDataKey() + "')" : null;
final Hint dataKeyHint = createHint(dataKey.getDataKey(), "", dataKey.getDescription(), replacement);
// disable replacement with "Structr.get(...)" when in Javascript declaration
dataKeyHint.allowNameModification(!isDeclaration);
hints.add(0, dataKeyHint);
}
}
// prepend property keys of current object type
collectHintsForType(hints, config, currentObjectType);
return hints;
}
Aggregations