com.webfirmframework.wffweb.server.page.js.WffJsFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wffweb Show documentation
Show all versions of wffweb Show documentation
A java framework to develop web applications
/*
* Copyright 2014-2019 Web Firm Framework
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.webfirmframework.wffweb.server.page.js;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.webfirmframework.wffweb.server.page.Task;
import com.webfirmframework.wffweb.tag.html.attribute.core.AttributeRegistry;
import com.webfirmframework.wffweb.tag.html.core.TagRegistry;
import com.webfirmframework.wffweb.util.StringBuilderUtil;
import com.webfirmframework.wffweb.util.StringUtil;
/**
* @author WFF
*
*/
public enum WffJsFile {
// should be kept in the same order
JS_WORK_AROUND("jsWorkAround.js"),
WFF_GLOBAL("wffGlobal.js"),
WFF_BM_UTIL("wffBMUtil.js"),
WFF_TAG_UTIL("wffTagUtil.js"),
WFF_BM_CRUID_UTIL("wffBMCRUIDUtil.js"),
WFF_CLIENT_CRUD_UTIL("wffClientCRUDUtil.js"),
WFF_SERVER_METHODS("wffServerMethods.js"),
WFF_CLIENT_METHODS("wffClientMethods.js"),
WFF_CLASSES("WffClasses.js"),
WFF_ASYNC("wffAsync.js"),
WFF_BM_CLIENT_EVENTS("wffBMClientEvents.js"),
WFF_WS("wffWS.js"),
WFF_CLIENT_EVENTS("wffClientEvents.js");
private static final String AUTOREMOVE_PARENT_SCRIPT = "document.currentScript.parentNode.removeChild(document.currentScript);";
private static final Logger LOGGER = Logger
.getLogger(WffJsFile.class.getName());
// should be static final
public static final boolean PRODUCTION_MODE = true;
public static final boolean COMPRESSED_WFF_DATA = true;
private static String allOptimizedContent;
private String filename;
private String optimizedFileContent;
private static volatile Set functionNames;
private static Set variableNames;
private static int functionId = 0;
private static int variableId = 0;
private static String[][] minifiableParts = { { "else {", "else{" },
{ "} else", "}else" }, { "if (", "if(" }, { ") {", "){" } };
private static final String HEART_BEAT_JS = "setInterval(function(){try{wffWS.send([]);}catch(e){wffWS.closeSocket();}},\"${HEARTBEAT_INTERVAL}\");";
/**
* INDEXED_TAGS_ARRAY
*/
private static final String NDXD_TGS;
private static final String NDXD_ATRBS;
static {
final StringBuilder tagsArraySB = new StringBuilder();
final List tagNames = TagRegistry.getTagNames();
for (final String tagName : tagNames) {
tagsArraySB.append(",\"");
tagsArraySB.append(tagName);
tagsArraySB.append('"');
}
NDXD_TGS = "[" + tagsArraySB.substring(1) + "]";
final StringBuilder attrbsArraySB = new StringBuilder();
final List attrNames = AttributeRegistry.getAttributeNames();
for (final String attrName : attrNames) {
attrbsArraySB.append(",\"");
attrbsArraySB.append(attrName);
attrbsArraySB.append('"');
}
NDXD_ATRBS = "[" + attrbsArraySB.substring(1) + "]";
if (PRODUCTION_MODE) {
final Comparator descendingLehgth = (o1, o2) -> {
// to sort in descending order of the length of the names
if (o1.length() > o2.length()) {
return -1;
}
if (o1.length() < o2.length()) {
return 1;
}
return -1;
};
functionNames = new TreeSet<>(descendingLehgth);
variableNames = new TreeSet<>(descendingLehgth);
// should be in descending order of the value length
functionNames.add("getAttrNameValueFromCompressedBytes");
functionNames.add("createTagFromCompressedWffBMBytes");
functionNames.add("getLengthOfOptimizedBytesFromInt");
functionNames.add("concatArrayValuesFromPosition");
functionNames.add("getTagNameFromCompressedBytes");
functionNames.add("extractValuesFromValueBytes");
functionNames.add("getDoubleFromOptimizedBytes");
functionNames.add("parseWffBinaryMessageBytes");
functionNames.add("getAttrUpdatedWffBMBytes");
functionNames.add("getWffBinaryMessageBytes");
functionNames.add("getIntFromOptimizedBytes");
functionNames.add("getOptimizedBytesFromInt");
functionNames.add("isWffWindowEventSupported");
functionNames.add("getTagByTagNameAndWffId");
functionNames.add("getTagDeletedWffBMBytes");
functionNames.add("createTagFromWffBMBytes");
functionNames.add("getTagCreatedWffBMBytes");
functionNames.add("wffRemovePrevBPInstance");
functionNames.add("getChildByNthIndexBytes");
functionNames.add("getWffIdFromWffIdBytes");
functionNames.add("getWffIdFromWffIdBytes");
functionNames.add("extractEachValueBytes");
functionNames.add("getWffIdBytesFromTag");
functionNames.add("getWffIdBytesFromTag");
functionNames.add("appendHtmlAsChildren");
functionNames.add("wffRemoveBPInstance");
functionNames.add("getLastBytesFromInt");
functionNames.add("getAttributeUpdates");
functionNames.add("getStringFromBytes");
functionNames.add("splitAttrNameValue");
functionNames.add("getBytesFromDouble");
functionNames.add("getStringFromBytes");
functionNames.add("concatArrayValues");
functionNames.add("getTaskNameValue");
functionNames.add("getValueTypeByte");
functionNames.add("onWffWindowClose");
functionNames.add("getValueTypeByte");
functionNames.add("getIntFromBytes");
functionNames.add("getBytesFromInt");
functionNames.add("getTagByWffId");
functionNames.add("getTagByWffId");
functionNames.add("invokeTasks");
functionNames.add("recurChild");
functionNames.add("invokeTask");
variableNames.add("wffRemovePrevBPInstanceInvoked");
variableNames.add("maxBytesLengthFromTotalBytes");
variableNames.add("totalNoOfBytesForAllValues");
variableNames.add("maxBytesLengthForAllValues");
variableNames.add("totalNoOfBytesForAllValues");
variableNames.add("lengOfOptmzdBytsOfAttrNam");
variableNames.add("indexInWffBinaryMessage");
variableNames.add("lengOfOptmzdBytsOfTgNam");
variableNames.add("valueLengthBytesLength");
variableNames.add("nameLengthBytesLength");
variableNames.add("wffBinaryMessageBytes");
variableNames.add("maxNoValueLengthBytes");
variableNames.add("attrNameAndValueBytes");
variableNames.add("nameLengthBytesLength");
variableNames.add("extractEachValueBytes");
variableNames.add("nameLengthBytesLength");
variableNames.add("maxNoNameLengthBytes");
variableNames.add("nameValueCallbackFun");
variableNames.add("superParentNameValue");
variableNames.add("currentParentTagName");
variableNames.add("maxValuesBytesLength");
variableNames.add("maxNoNameLengthBytes");
variableNames.add("attrNamNdxOptmzdByts");
// child index optimized int bytes
variableNames.add("chldNdxOptmzdIntByts");
variableNames.add("parentOfExistingTag");
variableNames.add("maxNoOfValuesBytes");
variableNames.add("wffInstanceIdBytes");
variableNames.add("attrNameValueBytes");
variableNames.add("currentParentWffId");
variableNames.add("tgNamNdxOptmzdByts");
variableNames.add("tgNamNdxOptmzdByts");
variableNames.add("callbackFunctions");
variableNames.add("attrNameValueArry");
variableNames.add("superParentValues");
variableNames.add("wffOnWindowClosed");
variableNames.add("indexOfSeparator");
variableNames.add("argumentBMObject");
variableNames.add("currentParentTag");
variableNames.add("maxNoOfNameBytes");
variableNames.add("valueLengthBytes");
variableNames.add("methodNameBytes");
variableNames.add("valueLegthBytes");
variableNames.add("bmObjOrArrBytes");
variableNames.add("nameLengthBytes");
variableNames.add("valuesToAppend");
variableNames.add("parentDocIndex");
variableNames.add("beforeTagWffId");
variableNames.add("nameLegthBytes");
variableNames.add("nodeValueBytes");
variableNames.add("nameLegthBytes");
variableNames.add("callbackFunId");
variableNames.add("fromByteArray");
variableNames.add("applicableTag");
variableNames.add("beforeTagName");
variableNames.add("sOrCUtf8Bytes");
variableNames.add("appendToArray");
variableNames.add("lastNoOfBytes");
variableNames.add("parentTagName");
variableNames.add("nodeNameBytes");
variableNames.add("attrNameValue");
variableNames.add("messageIndex");
variableNames.add("childTagName");
variableNames.add("tagNameBytes");
variableNames.add("reqBytsLngth");
variableNames.add("reqBytsLngth");
variableNames.add("parentIndex");
variableNames.add("doubleValue");
variableNames.add("tagToRemove");
variableNames.add("tagDocIndex");
variableNames.add("zerothIndex");
variableNames.add("valueLength");
variableNames.add("secondIndex");
variableNames.add("attrValByts");
variableNames.add("attrNamByts");
variableNames.add("thirdIndex");
variableNames.add("valueLegth");
variableNames.add("childWffId");
variableNames.add("intIdBytes");
variableNames.add("wffIdBytes");
variableNames.add("nameValues");
variableNames.add("valueBytes");
variableNames.add("valuesFrom");
variableNames.add("wffBMBytes");
variableNames.add("firstIndex");
variableNames.add("methodName");
variableNames.add("attrNamNdx");
variableNames.add("attrValLen");
variableNames.add("nameValue");
variableNames.add("nameBytes");
variableNames.add("beforeTag");
variableNames.add("attrValue");
variableNames.add("attrBytes");
variableNames.add("htmlNodes");
variableNames.add("wffTagId");
variableNames.add("attrName");
variableNames.add("childTag");
variableNames.add("nameByte");
variableNames.add("argBytes");
variableNames.add("tgNamNdx");
variableNames.add("allTags");
variableNames.add("allTags");
variableNames.add("wffIds");
variableNames.add("wffId");
variableNames.add("intId");
variableNames.add("sOrC");
// should not replace, because there is webSocket's onmessage
// function
// VARIABLE_NAMES.add("message");
// these must be excluded
// should not be included even by mistake
variableNames.remove("wffSM");
variableNames.remove("iawpff");
variableNames.remove("iawpf");
variableNames.remove("iawff");
variableNames.remove("ia");
functionNames.remove("wffSM");
functionNames.remove("iawpff");
functionNames.remove("iawpf");
functionNames.remove("iawff");
functionNames.remove("ia");
}
}
private WffJsFile(final String filename) {
this.filename = filename;
init();
}
private void init() {
try {
// this might make java.nio.file.FileSystemNotFoundException in
// production server.
// final List allLines = Files.readAllLines(
// Paths.get(WffJsFile.class.getResource(filename).toURI()),
// StandardCharsets.UTF_8);
final InputStream in = WffJsFile.class
.getResourceAsStream(filename);
final BufferedReader reader = new BufferedReader(
new InputStreamReader(in, StandardCharsets.UTF_8));
// this will might java.nio.file.FileSystemNotFoundException in
// production server.
// final long fileLength = Files.size(
// Paths.get(WffJsFile.class.getResource(filename).toURI()));
final long fileLength = in.available() > 0 ? in.available() : 16;
final StringBuilder builder = new StringBuilder((int) fileLength);
String eachLine = null;
while ((eachLine = reader.readLine()) != null) {
// replacing double spaces with single space
// by .replaceAll(" +", " ")
// will not be file as there could e double space variable
// initialization.
String line = eachLine;
final int indexOfCommentSlashes = line.indexOf("//");
if (indexOfCommentSlashes != -1) {
if (indexOfCommentSlashes == 0) {
line = line.substring(0, indexOfCommentSlashes);
} else if (line
.indexOf("://") != (indexOfCommentSlashes - 1)) {
line = line.substring(0, indexOfCommentSlashes);
}
}
line = StringUtil.strip(line);
builder.append(line);
if (!line.isEmpty()) {
if (line.charAt(line.length() - 1) != ';') {
builder.append('\n');
} else if (!PRODUCTION_MODE) {
builder.append('\n');
}
}
}
if (PRODUCTION_MODE) {
boolean containsComment = false;
do {
containsComment = false;
final int indexOfSlashStarCommentStart = builder
.indexOf("/*");
if (indexOfSlashStarCommentStart != -1) {
final int indexOfStarCommentEnd = builder.indexOf("*/");
if (indexOfStarCommentEnd != -1
&& indexOfSlashStarCommentStart < indexOfStarCommentEnd) {
builder.replace(indexOfSlashStarCommentStart,
indexOfStarCommentEnd + 2, "");
containsComment = true;
}
}
} while (containsComment);
boolean containsLog = false;
do {
containsLog = false;
final int indexOfConsole = builder.indexOf("console");
if (indexOfConsole != -1) {
final int indexOfSemiColon = builder.indexOf(");",
indexOfConsole);
if (indexOfSemiColon > indexOfConsole) {
builder.replace(indexOfConsole,
indexOfSemiColon + 2, "");
containsLog = true;
}
}
} while (containsLog);
}
optimizedFileContent = StringBuilderUtil.getTrimmedString(builder)
.toString();
} catch (final Exception e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
}
/**
* NB :- This method is only for internal use.
*
* @param wsUrl
* @param instanceId
* @param removePrevBPOnInitTab
* @param removePrevBPOnClosetTab
* @param heartbeatInterval
* in milliseconds
* @return the js string for the client
* @author WFF
*/
public static String getAllOptimizedContent(final String wsUrl,
final String instanceId, final boolean removePrevBPOnInitTab,
final boolean removePrevBPOnClosetTab, final int heartbeatInterval,
final int wsReconnectInterval,
final boolean autoremoveParentScript) {
if (allOptimizedContent != null) {
if (heartbeatInterval > 0) {
if (autoremoveParentScript) {
return buildJsContentWithHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
heartbeatInterval, wsReconnectInterval)
.append(AUTOREMOVE_PARENT_SCRIPT)
.toString();
}
return buildJsContentWithHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
heartbeatInterval, wsReconnectInterval).toString();
}
if (autoremoveParentScript) {
return buildJsContentWithoutHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
wsReconnectInterval).append(AUTOREMOVE_PARENT_SCRIPT)
.toString();
}
return buildJsContentWithoutHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
wsReconnectInterval).toString();
}
try {
int totalContentLength = 0;
for (final WffJsFile wffJsFile : WffJsFile.values()) {
totalContentLength += wffJsFile.optimizedFileContent.length();
}
final StringBuilder builder = new StringBuilder(totalContentLength);
final WffJsFile[] wffJsFiles = WffJsFile.values();
for (int i = 2; i < wffJsFiles.length; i++) {
builder.append('\n').append(wffJsFiles[i].optimizedFileContent);
}
allOptimizedContent = StringBuilderUtil.getTrimmedString(builder)
.toString();
if (PRODUCTION_MODE && functionNames != null) {
synchronized (WffJsFile.class) {
if (functionNames != null) {
for (final String name : functionNames) {
allOptimizedContent = allOptimizedContent
.replace(name, "f" + (++functionId));
}
for (final String name : variableNames) {
allOptimizedContent = allOptimizedContent
.replace(name, "v" + (++variableId));
}
for (final String[] each : minifiableParts) {
allOptimizedContent = allOptimizedContent
.replace(each[0], each[1]);
}
// there is bug while enabling this, also enable in Task
// for (final Task task : Task.getSortedTasks()) {
// allOptimizedContent = allOptimizedContent
// .replace(task.name(), task.getShortName());
// }
functionNames = null;
variableNames = null;
minifiableParts = null;
}
}
}
if (heartbeatInterval > 0) {
if (autoremoveParentScript) {
return buildJsContentWithHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
heartbeatInterval, wsReconnectInterval)
.append(AUTOREMOVE_PARENT_SCRIPT)
.toString();
}
return buildJsContentWithHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
heartbeatInterval, wsReconnectInterval).toString();
}
if (autoremoveParentScript) {
return buildJsContentWithoutHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
wsReconnectInterval).append(AUTOREMOVE_PARENT_SCRIPT)
.toString();
}
return buildJsContentWithoutHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
wsReconnectInterval).toString();
} catch (final Exception e) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, e.getMessage(), e);
}
}
return "";
}
private static StringBuilder buildJsContentWithHeartbeat(final String wsUrl,
final String instanceId, final boolean removePrevBPOnInitTab,
final boolean removePrevBPOnClosetTab, final int heartbeatInterval,
final int wsReconnectInterval) {
return buildJsContentWithoutHeartbeat(wsUrl, instanceId,
removePrevBPOnInitTab, removePrevBPOnClosetTab,
wsReconnectInterval).append(
HEART_BEAT_JS.replace("\"${HEARTBEAT_INTERVAL}\"",
Integer.toString(heartbeatInterval)));
}
private static StringBuilder buildJsContentWithoutHeartbeat(
final String wsUrl, final String instanceId,
final boolean removePrevBPOnInitTab,
final boolean removePrevBPOnClosetTab,
final int wsReconnectInterval) {
return new StringBuilder(
"var wffLog = console.log;")
.append(JS_WORK_AROUND.optimizedFileContent).append(
WFF_GLOBAL.optimizedFileContent
.replace("\"${CPRSD_DATA}\"",
String.valueOf(
COMPRESSED_WFF_DATA))
.replace("\"${NDXD_TGS}\"", NDXD_TGS)
.replace("\"${NDXD_ATRBS}\"",
NDXD_ATRBS)
.replace("${WS_URL}",
wsUrl)
.replace("${INSTANCE_ID}", instanceId)
.replace(
"\"${REMOVE_PREV_BP_ON_TABCLOSE}\"",
String.valueOf(
removePrevBPOnClosetTab))
.replace(
"\"${REMOVE_PREV_BP_ON_INITTAB}\"",
String.valueOf(
removePrevBPOnInitTab))
.replace("\"${TASK_VALUES}\"",
Task.getJsObjectString())
.replace("\"${WS_RECON}\"", String
.valueOf(wsReconnectInterval))
).append(allOptimizedContent);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy