feat: add components
This commit is contained in:
82
components/component-args.js
Normal file
82
components/component-args.js
Normal file
@@ -0,0 +1,82 @@
|
||||
var parseARGS = (kvKeys) => {
|
||||
return exports.parse($ARGS, kvKeys);
|
||||
};
|
||||
|
||||
var parse = (args, kvKeys) => {
|
||||
var newArgs = [];
|
||||
var keyValueMap = {};
|
||||
var keyFlagMap = {};
|
||||
|
||||
keyValueMap.vals = () => {
|
||||
var ret = [];
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var v = keyValueMap[arguments[i]];
|
||||
if (v) { v.forEach((x) => { ret.push(x) } ); }
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
keyValueMap.val = () => {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var v = keyValueMap[arguments[i]] && keyValueMap[arguments[i]][0];
|
||||
if (v) { return v; }
|
||||
}
|
||||
return null;
|
||||
};
|
||||
keyFlagMap.flg = () => {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var v = keyFlagMap[arguments[i]];
|
||||
if (v) { return true; }
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var kvKeyMap = {}; (kvKeys || []).forEach((k) => { kvKeyMap[k] = 1; });
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
var key = null;
|
||||
if (arg.startsWith('--')) {
|
||||
key = arg.substring(2);
|
||||
} else if (arg.startsWith('-')) {
|
||||
key = arg.substring(1);
|
||||
if (key.length > 1) {
|
||||
for (var x = 0; x < key.length; x++) {
|
||||
var k = key.substring(x, 1);
|
||||
kvKeyMap[k] = 1;
|
||||
keyFlagMap[k] = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((key != null) && ((i + 1) < args.length) || kvKeyMap[key]) {
|
||||
if (kvKeyMap[key]) {
|
||||
keyFlagMap[key] = 1;
|
||||
} else {
|
||||
keyValueMap[key] = keyValueMap[key] || [];
|
||||
keyValueMap[key].push(args[++i]);
|
||||
}
|
||||
} else {
|
||||
newArgs.push(arg);
|
||||
}
|
||||
}
|
||||
return {
|
||||
args: newArgs,
|
||||
flags: keyFlagMap,
|
||||
values: keyValueMap
|
||||
};
|
||||
};
|
||||
|
||||
var parseDefARGs = (kvKeys) => {
|
||||
var args = parseARGS(kvKeys);
|
||||
var newArgs = args.args;
|
||||
newArgs.flg = args.flags.flg;
|
||||
newArgs.val = args.values.val;
|
||||
newArgs.vals = args.values.vals;
|
||||
return newArgs;
|
||||
};
|
||||
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.parse = parse;
|
||||
exports.parseARGS = parseARGS;
|
||||
exports.parseDefARGs = parseDefARGs;
|
||||
}
|
||||
17
components/component-bytes.js
Normal file
17
components/component-bytes.js
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
var UNITS = ['bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
var UNITS_BYTES = [0, Math.pow(1024, 1), Math.pow(1024, 2), Math.pow(1024, 3), Math.pow(1024, 4)];
|
||||
|
||||
exports.showBytes = (bytes) => {
|
||||
for (var i = 0; i < (UNITS.length - 1); i++) {
|
||||
if ((bytes >= UNITS_BYTES[i]) && bytes < UNITS_BYTES[i + 1]) {
|
||||
if (i == 0) {
|
||||
return bytes + ((bytes <= 1) ? ' byte' : ' bytes');
|
||||
} else {
|
||||
return (parseInt(bytes * 100 / UNITS_BYTES[i]) / 100) + ' ' + UNITS[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (parseInt(bytes * 100 / UNITS_BYTES[i]) / 100) + ' ' + UNITS[i]; // i == UNITS.length - 1
|
||||
};
|
||||
41
components/component-colorprint-ex.js
Normal file
41
components/component-colorprint-ex.js
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
var HEADER = '\033[95m';
|
||||
var OKBLUE = '\033[94m';
|
||||
var OKGREEN = '\033[92m';
|
||||
var WARNING = '\033[93m';
|
||||
var FAIL = '\033[91m';
|
||||
var BOLD = '\033[1m';
|
||||
var UNDERLINE = '\033[4m';
|
||||
var ENDC = '\033[0m';
|
||||
|
||||
var colorMapping = {
|
||||
"header": HEADER,
|
||||
"okblue": OKBLUE,
|
||||
"okgreen": OKGREEN,
|
||||
"warning": WARNING,
|
||||
"fail": FAIL,
|
||||
"bold": BOLD,
|
||||
"underline": UNDERLINE,
|
||||
"none": null // nothing special
|
||||
};
|
||||
|
||||
var colorPrint = exports;
|
||||
|
||||
for (var k in colorMapping) {
|
||||
colorPrint[k] = {};
|
||||
colorPrint[k].render = ((k) => {
|
||||
return (x) => {
|
||||
return colorMapping[k] ? (colorMapping[k] + x + ENDC) : x;
|
||||
};
|
||||
})(k);
|
||||
colorPrint[k].print = ((k) => {
|
||||
return (x) => {
|
||||
print(colorPrint[k].render(x));
|
||||
};
|
||||
})(k);
|
||||
colorPrint[k].println = ((k) => {
|
||||
return (x) => {
|
||||
println(colorPrint[k].render(x));
|
||||
};
|
||||
})(k);
|
||||
}
|
||||
3
components/component-colorprint.js
Normal file
3
components/component-colorprint.js
Normal file
@@ -0,0 +1,3 @@
|
||||
(() => {
|
||||
colorPrint = require('component-colorprint-ex.js');
|
||||
})();
|
||||
61
components/component-console.js
Normal file
61
components/component-console.js
Normal file
@@ -0,0 +1,61 @@
|
||||
var System = java.lang.System;
|
||||
|
||||
var readLineEx = (prompt) => {
|
||||
var ret = null;
|
||||
while ((ret == null) || $STR(ret).trim() == '') {
|
||||
ret = readLine(prompt);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
var readLine = (prompt) => {
|
||||
print(prompt);
|
||||
return System.console().readLine();
|
||||
};
|
||||
|
||||
var readYNEx = (prompt) => {
|
||||
var ret = null;
|
||||
while (ret == null) {
|
||||
ret = readYN(prompt);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
var readYN = (prompt) => {
|
||||
print(prompt);
|
||||
var read = readLine();
|
||||
if ($STR(read).toLowerCase() == 'y') {
|
||||
return true;
|
||||
}
|
||||
if ($STR(read).toLowerCase() == 'n') {
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var readListToMark = (prompt, mark) => {
|
||||
if (!(mark)) { throw 'Mark cannot be null or empty.'; }
|
||||
print(prompt);
|
||||
var list = [];
|
||||
while (true) {
|
||||
var ln = System.console().readLine();
|
||||
if ($STR(ln) == $STR(mark)) {
|
||||
return list;
|
||||
}
|
||||
list.push(ln);
|
||||
}
|
||||
};
|
||||
|
||||
var readListToCustomMark = (prompt) => {
|
||||
var mark = readLineEx(prompt);
|
||||
return readListToMark('', mark);
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.readYN = readYN;
|
||||
exports.readYNEx = readYNEx;
|
||||
exports.readLine = readLine;
|
||||
exports.readLineEx = readLineEx;
|
||||
exports.readListToMark = readListToMark;
|
||||
exports.readListToCustomMark = readListToCustomMark;
|
||||
}
|
||||
137
components/component-coordtransform.js
Normal file
137
components/component-coordtransform.js
Normal file
@@ -0,0 +1,137 @@
|
||||
// https://github.com/wandergis/coordtransform/blob/master/index.js
|
||||
(() => {
|
||||
/**
|
||||
* Created by Wandergis on 2015/7/8.
|
||||
* 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
|
||||
*/
|
||||
//定义一些常量
|
||||
var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
|
||||
var PI = 3.1415926535897932384626;
|
||||
var a = 6378245.0;
|
||||
var ee = 0.00669342162296594323;
|
||||
/**
|
||||
* 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
|
||||
* 即 百度 转 谷歌、高德
|
||||
* @param bd_lon
|
||||
* @param bd_lat
|
||||
* @returns {*[]}
|
||||
*/
|
||||
var bd09togcj02 = function bd09togcj02(bd_lon, bd_lat) {
|
||||
var bd_lon = +bd_lon;
|
||||
var bd_lat = +bd_lat;
|
||||
var x = bd_lon - 0.0065;
|
||||
var y = bd_lat - 0.006;
|
||||
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
|
||||
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
|
||||
var gg_lng = z * Math.cos(theta);
|
||||
var gg_lat = z * Math.sin(theta);
|
||||
return [gg_lng, gg_lat]
|
||||
};
|
||||
|
||||
/**
|
||||
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
|
||||
* 即谷歌、高德 转 百度
|
||||
* @param lng
|
||||
* @param lat
|
||||
* @returns {*[]}
|
||||
*/
|
||||
var gcj02tobd09 = function gcj02tobd09(lng, lat) {
|
||||
var lat = +lat;
|
||||
var lng = +lng;
|
||||
var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
|
||||
var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
|
||||
var bd_lng = z * Math.cos(theta) + 0.0065;
|
||||
var bd_lat = z * Math.sin(theta) + 0.006;
|
||||
return [bd_lng, bd_lat]
|
||||
};
|
||||
|
||||
/**
|
||||
* WGS84转GCj02
|
||||
* @param lng
|
||||
* @param lat
|
||||
* @returns {*[]}
|
||||
*/
|
||||
var wgs84togcj02 = function wgs84togcj02(lng, lat) {
|
||||
var lat = +lat;
|
||||
var lng = +lng;
|
||||
if (out_of_china(lng, lat)) {
|
||||
return [lng, lat]
|
||||
} else {
|
||||
var dlat = transformlat(lng - 105.0, lat - 35.0);
|
||||
var dlng = transformlng(lng - 105.0, lat - 35.0);
|
||||
var radlat = lat / 180.0 * PI;
|
||||
var magic = Math.sin(radlat);
|
||||
magic = 1 - ee * magic * magic;
|
||||
var sqrtmagic = Math.sqrt(magic);
|
||||
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
|
||||
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
|
||||
var mglat = lat + dlat;
|
||||
var mglng = lng + dlng;
|
||||
return [mglng, mglat]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* GCJ02 转换为 WGS84
|
||||
* @param lng
|
||||
* @param lat
|
||||
* @returns {*[]}
|
||||
*/
|
||||
var gcj02towgs84 = function gcj02towgs84(lng, lat) {
|
||||
var lat = +lat;
|
||||
var lng = +lng;
|
||||
if (out_of_china(lng, lat)) {
|
||||
return [lng, lat]
|
||||
} else {
|
||||
var dlat = transformlat(lng - 105.0, lat - 35.0);
|
||||
var dlng = transformlng(lng - 105.0, lat - 35.0);
|
||||
var radlat = lat / 180.0 * PI;
|
||||
var magic = Math.sin(radlat);
|
||||
magic = 1 - ee * magic * magic;
|
||||
var sqrtmagic = Math.sqrt(magic);
|
||||
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
|
||||
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
|
||||
var mglat = lat + dlat;
|
||||
var mglng = lng + dlng;
|
||||
return [lng * 2 - mglng, lat * 2 - mglat]
|
||||
}
|
||||
};
|
||||
|
||||
var transformlat = function transformlat(lng, lat) {
|
||||
var lat = +lat;
|
||||
var lng = +lng;
|
||||
var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
|
||||
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
||||
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
|
||||
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
|
||||
return ret
|
||||
};
|
||||
|
||||
var transformlng = function transformlng(lng, lat) {
|
||||
var lat = +lat;
|
||||
var lng = +lng;
|
||||
var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
|
||||
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
|
||||
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
|
||||
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
|
||||
return ret
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断是否在国内,不在国内则不做偏移
|
||||
* @param lng
|
||||
* @param lat
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var out_of_china = function out_of_china(lng, lat) {
|
||||
var lat = +lat;
|
||||
var lng = +lng;
|
||||
// 纬度3.86~53.55,经度73.66~135.05
|
||||
return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
|
||||
};
|
||||
|
||||
exports.bd09togcj02 = bd09togcj02;
|
||||
exports.gcj02tobd09 = gcj02tobd09;
|
||||
exports.wgs84togcj02 = wgs84togcj02;
|
||||
exports.gcj02towgs84 = gcj02towgs84;
|
||||
})();
|
||||
68
components/component-cos.js
Normal file
68
components/component-cos.js
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
var counter = require('component-counter.js');
|
||||
|
||||
var requireJARs = () => {
|
||||
$ONCE('component-cos-requireJARS').run(() => {
|
||||
requireJAR('cos_api-5.2.2.jar');
|
||||
requireJAR('httpcore-4.4.6.jar');
|
||||
requireJAR('commons-codec-1.10.jar');
|
||||
requireJAR('commons-logging-1.2.jar');
|
||||
requireJAR('httpclient-4.5.3.jar');
|
||||
requireJAR('httpmime-4.5.2.jar');
|
||||
requireJAR('slf4j-api-1.7.21.jar');
|
||||
requireJAR('log4j-1.2.17.jar');
|
||||
requireJAR('slf4j-log4j12-1.7.21.jar');
|
||||
requireJAR('joda-time-2.9.6.jar');
|
||||
requireJAR('jackson-core-2.8.5.jar');
|
||||
requireJAR('jackson-annotations-2.8.0.jar');
|
||||
requireJAR('jackson-databind-2.8.5.jar');
|
||||
});
|
||||
};
|
||||
|
||||
var createCounterIS = (file) => {
|
||||
var CounterInputStream = Packages.me.hatter.tools.commons.io.CounterInputStream;
|
||||
var uploadFile = (file instanceof java.io.File) ? file : new java.io.File(file);
|
||||
var uploadIS = new java.io.FileInputStream(uploadFile);
|
||||
var counterIS = new CounterInputStream(uploadIS, counter.getCounterBar(uploadFile.length()));
|
||||
return counterIS;
|
||||
};
|
||||
|
||||
var putObject = (client, bucket, key, file) => {
|
||||
var f = $$.file(file);
|
||||
var objectMetadata = new Packages.com.qcloud.cos.model.ObjectMetadata();
|
||||
objectMetadata.setContentLength(f.length());
|
||||
var result = client.putObject(bucket, key, createCounterIS(f), objectMetadata);
|
||||
return result;
|
||||
};
|
||||
|
||||
// client -> https://cloud.tencent.com/document/product/436/10199
|
||||
// region -> https://cloud.tencent.com/document/product/436/6224
|
||||
var newClient = (region, appId, accessKey, secretKey) => {
|
||||
requireJARs();
|
||||
|
||||
var COSClient = Packages.com.qcloud.cos.COSClient;
|
||||
var Region = Packages.com.qcloud.cos.region.Region;
|
||||
var ClientConfig = Packages.com.qcloud.cos.ClientConfig;
|
||||
var BasicCOSCredentials = Packages.com.qcloud.cos.auth.BasicCOSCredentials;
|
||||
var cred = new BasicCOSCredentials(appId, accessKey, secretKey);
|
||||
var clientConfig = new ClientConfig(new Region(region));
|
||||
var client = new COSClient(cred, clientConfig);
|
||||
return {
|
||||
runWith: (runFunc) => {
|
||||
try {
|
||||
runFunc(client);
|
||||
} catch (e) {
|
||||
println('COS Error: ' + e);
|
||||
} finally {
|
||||
client.shutdown();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.requireJARs = requireJARs;
|
||||
exports.createCounterIS = createCounterIS;
|
||||
exports.putObject = putObject;
|
||||
exports.newClient = newClient;
|
||||
}
|
||||
77
components/component-counter.js
Normal file
77
components/component-counter.js
Normal file
@@ -0,0 +1,77 @@
|
||||
var bytesjs = require('component-bytes.js');
|
||||
|
||||
exports.getCounter = (fileLength, dotStep) => {
|
||||
var total = 0;
|
||||
var step = dotStep || (1024 * 64);
|
||||
var percentPrintFlag = {};
|
||||
var percentN = (fileLength > (60 * 1024 * 1024)) ? 100 : 10;
|
||||
return (len) => {
|
||||
var t = total;
|
||||
total += len;
|
||||
var n = parseInt(total / step) - parseInt(t / step);
|
||||
if (n > 0) { n.times(() => { print('.') }); }
|
||||
if (fileLength) {
|
||||
var updatePercentN = parseInt((total * percentN) / fileLength);
|
||||
if (updatePercentN && (!(percentPrintFlag[updatePercentN]))) {
|
||||
percentPrintFlag[updatePercentN] = 1;
|
||||
print('[' + parseInt((total * 100) / fileLength) + '%]');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.getCounter2 = (dotStep) => {
|
||||
var total = 0;
|
||||
var step = dotStep || (1024 * 64);
|
||||
var percentPrintFlag = {};
|
||||
return (len, fileLength) => {
|
||||
var t = total;
|
||||
total += len;
|
||||
var n = parseInt(total / step) - parseInt(t / step);
|
||||
if (n > 0) { n.times(() => { print('.') }); }
|
||||
if (fileLength > 0) {
|
||||
var updatePercent10 = parseInt((total * 10) / fileLength);
|
||||
if (updatePercent10 && (!(percentPrintFlag[updatePercent10]))) {
|
||||
percentPrintFlag[updatePercent10] = 1;
|
||||
print('[' + parseInt((total * 100) / fileLength) + '%]');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.getCounter2Bar = (dotStep) => {
|
||||
Packages.me.hatter.tools.jssp.main.StandaloneMainInteractive.initJLine(); // require jline
|
||||
var total = 0;
|
||||
var start = $$.date().millis();
|
||||
var step = dotStep || (1024 * 64);
|
||||
var percentPrintFlag = {};
|
||||
return (len, fileLength) => {
|
||||
var t = total; total += len;
|
||||
var diff = $$.date().millis() - start;
|
||||
var download = bytesjs.showBytes(total);
|
||||
var speed = 'unknown';
|
||||
if (diff > 0) {
|
||||
speed = bytesjs.showBytes(parseInt(total * 1000 / diff)) + '/s';
|
||||
}
|
||||
if (fileLength > 0) {
|
||||
var width = Packages.jline.TerminalFactory.get().getWidth();
|
||||
var per = ' ' + $$.num(total).mul(100).divr(fileLength, 2, null) + '% [' + download + ' - ' + speed + ']';
|
||||
var w = $$.num(total).divr((fileLength), 10, null).mul(width - 2 - per.length).floor().aint();
|
||||
reprint(repeat('>', w) + per);
|
||||
} else {
|
||||
reprint('Downloaded: ' + download + ', speed: ' + speed);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.getCounterBar = (fileLength) => {
|
||||
Packages.me.hatter.tools.jssp.main.StandaloneMainInteractive.initJLine(); // require jline
|
||||
var total = 0;
|
||||
return (len) => {
|
||||
var width = Packages.jline.TerminalFactory.get().getWidth();
|
||||
total += len;
|
||||
var per = ' ' + $$.num(total).mul(100).divr(fileLength, 2, null) + '%';
|
||||
var w = $$.num(total).divr((fileLength), 10, null).mul(width - 1 - per.length).floor().aint();
|
||||
print('\r' + repeat('>', w) + per + '\033[K');
|
||||
};
|
||||
};
|
||||
26
components/component-dataaccessentity.js
Normal file
26
components/component-dataaccessentity.js
Normal file
@@ -0,0 +1,26 @@
|
||||
requireJAR('dataaccess-1.0.jar');
|
||||
|
||||
var InMemoryCompiler = Packages.me.hatter.tools.commons.classloader.compile.InMemoryCompiler;
|
||||
var EntityJavaSourceCodeGenerateTool = Packages.me.hatter.tools.dataaccess.entity.EntityJavaSourceCodeGenerateTool;
|
||||
|
||||
var systemInMemoryCompiler = InMemoryCompiler.systemInstance().updateClassPath();
|
||||
var allCompiledEntityClassMap = {};
|
||||
|
||||
var generateClass = (json) => {
|
||||
var sourceCode = EntityJavaSourceCodeGenerateTool.instance().config(json).generate();
|
||||
var clazz = systemInMemoryCompiler.compile(sourceCode);
|
||||
return clazz;
|
||||
};
|
||||
|
||||
var getClass = (json) => {
|
||||
var jsonSha256Hex = $$.digests().sha256().digest(json.getBytes('UTF-8')).asHex();
|
||||
if (allCompiledEntityClassMap[jsonSha256Hex]) {
|
||||
return allCompiledEntityClassMap[jsonSha256Hex];
|
||||
}
|
||||
var clazz = generateClass(json);
|
||||
allCompiledEntityClassMap[jsonSha256Hex] = clazz;
|
||||
return clazz;
|
||||
};
|
||||
|
||||
exports.getClass = getClass;
|
||||
exports.generateClass = generateClass;
|
||||
38
components/component-diffutil-ex.js
Normal file
38
components/component-diffutil-ex.js
Normal file
@@ -0,0 +1,38 @@
|
||||
requireJAR('diffutils-1.3.0.jar');
|
||||
|
||||
var DiffUtils = Packages.difflib.DiffUtils;
|
||||
var DeleteDelta = Packages.difflib.DeleteDelta;
|
||||
var ChangeDelta = Packages.difflib.ChangeDelta;
|
||||
var InsertDelta = Packages.difflib.InsertDelta;
|
||||
|
||||
exports.diff2List = (left, right) => {
|
||||
var patch = DiffUtils.diff(left, right);
|
||||
var result = [];
|
||||
$EACH(patch.getDeltas(), (delta) => {
|
||||
if (delta instanceof DeleteDelta) {
|
||||
result.push("@@deleted @" + delta.getOriginal().getPosition()
|
||||
+ " #" + delta.getOriginal().getLines().size());
|
||||
$EACH(delta.getOriginal().getLines(), (line) => {
|
||||
result.push("-- " + line);
|
||||
})
|
||||
}
|
||||
if (delta instanceof ChangeDelta) {
|
||||
result.push("@@modified @" + delta.getOriginal().getPosition()
|
||||
+ " #" + delta.getOriginal().getLines().size() + '-' + delta.getRevised().getLines().size());
|
||||
$EACH(delta.getOriginal().getLines(), (line) => {
|
||||
result.push("-- " + line);
|
||||
});
|
||||
$EACH(delta.getRevised().getLines(), (line) => {
|
||||
result.push("++ " + line);
|
||||
});
|
||||
}
|
||||
if (delta instanceof InsertDelta) {
|
||||
result.push("@@inserted @" + delta.getOriginal().getPosition()
|
||||
+ " #" + delta.getRevised().getLines().size());
|
||||
$EACH(delta.getRevised().getLines(), (line) => {
|
||||
result.push("++ " + line);
|
||||
});
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
9
components/component-diffutil.js
Normal file
9
components/component-diffutil.js
Normal file
@@ -0,0 +1,9 @@
|
||||
requireJAR('diffutils-1.3.0.jar');
|
||||
|
||||
(() => {
|
||||
var diff = require('component-diffutil-ex.js');
|
||||
|
||||
diff2List = (left, right) => {
|
||||
return diff.diff2List(left, right);
|
||||
};
|
||||
})();
|
||||
24
components/component-dingtalkrobot-ex.js
Normal file
24
components/component-dingtalkrobot-ex.js
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
exports.sendText = (token, message) => {
|
||||
var dingTalkRobotURL = 'https://oapi.dingtalk.com/robot/send?access_token=' + token;
|
||||
var postResult = $$.httpRequest()
|
||||
.url(dingTalkRobotURL)
|
||||
.addHeader('Content-Type', 'application/json')
|
||||
.post(JSON.stringify({
|
||||
"msgtype": "text",
|
||||
"text": {
|
||||
"content": $STR(message)
|
||||
}
|
||||
}));
|
||||
return postResult;
|
||||
};
|
||||
|
||||
exports.sendTextDefault = (message) => {
|
||||
var tokenFile = $$.file($$.prop('user.home'), '.component-dingtalkrobot.js.token');
|
||||
if (!tokenFile.exists()) {
|
||||
println('DingTalk token file not exists: ' + tokenFile);
|
||||
return;
|
||||
}
|
||||
var token = $$.rFile(tokenFile).string().trim();
|
||||
sendDingTalkRobotTextMessage(token, message);
|
||||
};
|
||||
11
components/component-dingtalkrobot.js
Normal file
11
components/component-dingtalkrobot.js
Normal file
@@ -0,0 +1,11 @@
|
||||
(() => {
|
||||
var dingtalkrobot = require('component-dingtalkrobot-ex.js');
|
||||
|
||||
sendDingTalkRobotTextMessage = (token, message) => {
|
||||
return dingtalkrobot.sendText(token, message);
|
||||
};
|
||||
|
||||
sendDingTalkRobotTextMessageDefault = (message) => {
|
||||
return dingtalkrobot.sendTextDefault(message);
|
||||
};
|
||||
})();
|
||||
26
components/component-filechooser-ex.js
Normal file
26
components/component-filechooser-ex.js
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
var Proxy = java.lang.reflect.Proxy;
|
||||
var Toolkit = java.awt.Toolkit;
|
||||
var FileFilter = javax.swing.filechooser.FileFilter;
|
||||
var JFileChooser = javax.swing.JFileChooser;
|
||||
|
||||
exports.showDialog = (filter, filterName) => {
|
||||
var fileFilter = new FileFilter({
|
||||
"getDescription": () => {
|
||||
return filterName || 'Default Filter';
|
||||
},
|
||||
"accept": (f) => {
|
||||
return filter(f);
|
||||
}
|
||||
});
|
||||
var chooser = new JFileChooser();
|
||||
if (filter != null) {
|
||||
chooser.setFileFilter(fileFilter);
|
||||
}
|
||||
var ret = chooser.showOpenDialog(null);
|
||||
|
||||
if (ret == JFileChooser.APPROVE_OPTION) {
|
||||
return chooser.getSelectedFile();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
7
components/component-filechooser.js
Normal file
7
components/component-filechooser.js
Normal file
@@ -0,0 +1,7 @@
|
||||
(() => {
|
||||
var filechooser = require('component-filechooser-ex.js');
|
||||
|
||||
showFileOpenDialog = (filter, filterName) => {
|
||||
return filechooser.showDialog(filter, filterName);
|
||||
};
|
||||
})();
|
||||
14
components/component-filesystem.js
Normal file
14
components/component-filesystem.js
Normal file
@@ -0,0 +1,14 @@
|
||||
var Files = java.nio.file.Files;
|
||||
var PosixFilePermission = java.nio.file.attribute.PosixFilePermission;
|
||||
|
||||
var chmodAddExec = (file) => {
|
||||
file = $$.file(file);
|
||||
var perms = $$.set();
|
||||
perms.addAll(Files.getPosixFilePermissions(file.toPath()));
|
||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
Files.setPosixFilePermissions(file.toPath(), perms);
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.chmodAddExec = chmodAddExec;
|
||||
}
|
||||
243
components/component-geohash.js
Normal file
243
components/component-geohash.js
Normal file
@@ -0,0 +1,243 @@
|
||||
// https://github.com/chrisveness/latlon-geohash/blob/master/latlon-geohash.js
|
||||
(() => {
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
/* Geohash encoding/decoding and associated functions (c) Chris Veness 2014-2016 / MIT Licence */
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
/**
|
||||
* Geohash encode, decode, bounds, neighbours.
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var Geohash = {};
|
||||
|
||||
/* (Geohash-specific) Base32 map */
|
||||
Geohash.base32 = '0123456789bcdefghjkmnpqrstuvwxyz';
|
||||
|
||||
/**
|
||||
* Encodes latitude/longitude to geohash, either to specified precision or to automatically
|
||||
* evaluated precision.
|
||||
*
|
||||
* @param {number} lat - Latitude in degrees.
|
||||
* @param {number} lon - Longitude in degrees.
|
||||
* @param {number} [precision] - Number of characters in resulting geohash.
|
||||
* @returns {string} Geohash of supplied latitude/longitude.
|
||||
* @throws Invalid geohash.
|
||||
*
|
||||
* @example
|
||||
* var geohash = Geohash.encode(52.205, 0.119, 7); // geohash: 'u120fxw'
|
||||
*/
|
||||
exports.encode = Geohash.encode = function (lat, lon, precision) {
|
||||
// infer precision?
|
||||
if (typeof precision == 'undefined') {
|
||||
// refine geohash until it matches precision of supplied lat/lon
|
||||
for (var p = 1; p <= 12; p++) {
|
||||
var hash = Geohash.encode(lat, lon, p);
|
||||
var posn = Geohash.decode(hash);
|
||||
if (posn.lat == lat && posn.lon == lon) return hash;
|
||||
}
|
||||
precision = 12; // set to maximum
|
||||
}
|
||||
|
||||
lat = Number(lat);
|
||||
lon = Number(lon);
|
||||
precision = Number(precision);
|
||||
|
||||
if (isNaN(lat) || isNaN(lon) || isNaN(precision)) throw new Error('Invalid geohash');
|
||||
|
||||
var idx = 0; // index into base32 map
|
||||
var bit = 0; // each char holds 5 bits
|
||||
var evenBit = true;
|
||||
var geohash = '';
|
||||
|
||||
var latMin = -90, latMax = 90;
|
||||
var lonMin = -180, lonMax = 180;
|
||||
|
||||
while (geohash.length < precision) {
|
||||
if (evenBit) {
|
||||
// bisect E-W longitude
|
||||
var lonMid = (lonMin + lonMax) / 2;
|
||||
if (lon >= lonMid) {
|
||||
idx = idx * 2 + 1;
|
||||
lonMin = lonMid;
|
||||
} else {
|
||||
idx = idx * 2;
|
||||
lonMax = lonMid;
|
||||
}
|
||||
} else {
|
||||
// bisect N-S latitude
|
||||
var latMid = (latMin + latMax) / 2;
|
||||
if (lat >= latMid) {
|
||||
idx = idx * 2 + 1;
|
||||
latMin = latMid;
|
||||
} else {
|
||||
idx = idx * 2;
|
||||
latMax = latMid;
|
||||
}
|
||||
}
|
||||
evenBit = !evenBit;
|
||||
|
||||
if (++bit == 5) {
|
||||
// 5 bits gives us a character: append it and start over
|
||||
geohash += Geohash.base32.charAt(idx);
|
||||
bit = 0;
|
||||
idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return geohash;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Decode geohash to latitude/longitude (location is approximate centre of geohash cell,
|
||||
* to reasonable precision).
|
||||
*
|
||||
* @param {string} geohash - Geohash string to be converted to latitude/longitude.
|
||||
* @returns {{lat:number, lon:number}} (Center of) geohashed location.
|
||||
* @throws Invalid geohash.
|
||||
*
|
||||
* @example
|
||||
* var latlon = Geohash.decode('u120fxw'); // latlon: { lat: 52.205, lon: 0.1188 }
|
||||
*/
|
||||
exports.decode = Geohash.decode = function (geohash) {
|
||||
|
||||
var bounds = Geohash.bounds(geohash); // <-- the hard work
|
||||
// now just determine the centre of the cell...
|
||||
|
||||
var latMin = bounds.sw.lat, lonMin = bounds.sw.lon;
|
||||
var latMax = bounds.ne.lat, lonMax = bounds.ne.lon;
|
||||
|
||||
// cell centre
|
||||
var lat = (latMin + latMax) / 2;
|
||||
var lon = (lonMin + lonMax) / 2;
|
||||
|
||||
// round to close to centre without excessive precision: ⌊2-log10(Δ°)⌋ decimal places
|
||||
lat = lat.toFixed(Math.floor(2 - Math.log(latMax - latMin) / Math.LN10));
|
||||
lon = lon.toFixed(Math.floor(2 - Math.log(lonMax - lonMin) / Math.LN10));
|
||||
|
||||
return { lat: Number(lat), lon: Number(lon) };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns SW/NE latitude/longitude bounds of specified geohash.
|
||||
*
|
||||
* @param {string} geohash - Cell that bounds are required of.
|
||||
* @returns {{sw: {lat: number, lon: number}, ne: {lat: number, lon: number}}}
|
||||
* @throws Invalid geohash.
|
||||
*/
|
||||
exports.bounds = Geohash.bounds = function (geohash) {
|
||||
if (geohash.length === 0) throw new Error('Invalid geohash');
|
||||
|
||||
geohash = geohash.toLowerCase();
|
||||
|
||||
var evenBit = true;
|
||||
var latMin = -90, latMax = 90;
|
||||
var lonMin = -180, lonMax = 180;
|
||||
|
||||
for (var i = 0; i < geohash.length; i++) {
|
||||
var chr = geohash.charAt(i);
|
||||
var idx = Geohash.base32.indexOf(chr);
|
||||
if (idx == -1) throw new Error('Invalid geohash');
|
||||
|
||||
for (var n = 4; n >= 0; n--) {
|
||||
var bitN = idx >> n & 1;
|
||||
if (evenBit) {
|
||||
// longitude
|
||||
var lonMid = (lonMin + lonMax) / 2;
|
||||
if (bitN == 1) {
|
||||
lonMin = lonMid;
|
||||
} else {
|
||||
lonMax = lonMid;
|
||||
}
|
||||
} else {
|
||||
// latitude
|
||||
var latMid = (latMin + latMax) / 2;
|
||||
if (bitN == 1) {
|
||||
latMin = latMid;
|
||||
} else {
|
||||
latMax = latMid;
|
||||
}
|
||||
}
|
||||
evenBit = !evenBit;
|
||||
}
|
||||
}
|
||||
|
||||
var bounds = {
|
||||
sw: { lat: latMin, lon: lonMin },
|
||||
ne: { lat: latMax, lon: lonMax },
|
||||
};
|
||||
|
||||
return bounds;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines adjacent cell in given direction.
|
||||
*
|
||||
* @param geohash - Cell to which adjacent cell is required.
|
||||
* @param direction - Direction from geohash (N/S/E/W).
|
||||
* @returns {string} Geocode of adjacent cell.
|
||||
* @throws Invalid geohash.
|
||||
*/
|
||||
exports.adjacent = Geohash.adjacent = function (geohash, direction) {
|
||||
// based on github.com/davetroy/geohash-js
|
||||
|
||||
geohash = geohash.toLowerCase();
|
||||
direction = direction.toLowerCase();
|
||||
|
||||
if (geohash.length === 0) throw new Error('Invalid geohash');
|
||||
if ('nsew'.indexOf(direction) == -1) throw new Error('Invalid direction');
|
||||
|
||||
var neighbour = {
|
||||
n: ['p0r21436x8zb9dcf5h7kjnmqesgutwvy', 'bc01fg45238967deuvhjyznpkmstqrwx'],
|
||||
s: ['14365h7k9dcfesgujnmqp0r2twvyx8zb', '238967debc01fg45kmstqrwxuvhjyznp'],
|
||||
e: ['bc01fg45238967deuvhjyznpkmstqrwx', 'p0r21436x8zb9dcf5h7kjnmqesgutwvy'],
|
||||
w: ['238967debc01fg45kmstqrwxuvhjyznp', '14365h7k9dcfesgujnmqp0r2twvyx8zb'],
|
||||
};
|
||||
var border = {
|
||||
n: ['prxz', 'bcfguvyz'],
|
||||
s: ['028b', '0145hjnp'],
|
||||
e: ['bcfguvyz', 'prxz'],
|
||||
w: ['0145hjnp', '028b'],
|
||||
};
|
||||
|
||||
var lastCh = geohash.slice(-1); // last character of hash
|
||||
var parent = geohash.slice(0, -1); // hash without last character
|
||||
|
||||
var type = geohash.length % 2;
|
||||
|
||||
// check for edge-cases which don't share common prefix
|
||||
if (border[direction][type].indexOf(lastCh) != -1 && parent !== '') {
|
||||
parent = Geohash.adjacent(parent, direction);
|
||||
}
|
||||
|
||||
// append letter for direction to parent
|
||||
return parent + Geohash.base32.charAt(neighbour[direction][type].indexOf(lastCh));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns all 8 adjacent cells to specified geohash.
|
||||
*
|
||||
* @param {string} geohash - Geohash neighbours are required of.
|
||||
* @returns {{n,ne,e,se,s,sw,w,nw: string}}
|
||||
* @throws Invalid geohash.
|
||||
*/
|
||||
exports.neighbours = Geohash.neighbours = function (geohash) {
|
||||
return {
|
||||
'n': Geohash.adjacent(geohash, 'n'),
|
||||
'ne': Geohash.adjacent(Geohash.adjacent(geohash, 'n'), 'e'),
|
||||
'e': Geohash.adjacent(geohash, 'e'),
|
||||
'se': Geohash.adjacent(Geohash.adjacent(geohash, 's'), 'e'),
|
||||
's': Geohash.adjacent(geohash, 's'),
|
||||
'sw': Geohash.adjacent(Geohash.adjacent(geohash, 's'), 'w'),
|
||||
'w': Geohash.adjacent(geohash, 'w'),
|
||||
'nw': Geohash.adjacent(Geohash.adjacent(geohash, 'n'), 'w'),
|
||||
};
|
||||
};
|
||||
})();
|
||||
9
components/component-git.js
Normal file
9
components/component-git.js
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
exports.isGitUptodate = () => {
|
||||
var r = $STR($$.shell().commands('git', 'fetch', '--dry-run').mergeError().start()[0]);
|
||||
if (r.trim().length > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
32
components/component-gpg-ex.js
Normal file
32
components/component-gpg-ex.js
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
exports.encrypt = (keyId, srcFile, destFile) => {
|
||||
$$.shell().commands('sh', '-c', 'gpg -r ' + keyId + ' -e -o "' + destFile + '" ' + srcFile).start();
|
||||
};
|
||||
|
||||
exports.encryptArmor = (keyId, srcFile, destFile) => {
|
||||
$$.shell().commands('sh', '-c', 'gpg -r ' + keyId + ' -e -a --no-comment --comment "https://hatter.in/key" -o "' + destFile + '" ' + srcFile).start();
|
||||
};
|
||||
|
||||
exports.decryptArmor = (gpgArmor) => {
|
||||
var gpgArmorB64 = __.bytes.from(gpgArmor).asBase64();
|
||||
var result = $$.shell().commands('sh', '-c', "echo '" + gpgArmorB64 + "' | base64 -D | gpg").start();
|
||||
return __decrypt(result);
|
||||
};
|
||||
|
||||
exports.decrypt = (gpgFile) => {
|
||||
var result = $$.shell().commands('sh', '-c', 'cat ' + gpgFile + ' | gpg').start();
|
||||
__decrypt(result);
|
||||
};
|
||||
|
||||
var __decrypt = (result) => {
|
||||
var out = result[0].string();
|
||||
var err = result[1].string();
|
||||
if (err.contains('public key decryption failed')) {
|
||||
println('+ Decrypt file FAILED: ' + gpgFile);
|
||||
if (!Packages.me.hatter.tools.jssp.main.StandaloneMain.JSSP_MAIN_MUTE) {
|
||||
println("ERROR detail:\n" + err);
|
||||
}
|
||||
throw 'decrypt file failed: ' + gpgFile;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
15
components/component-gpg.js
Normal file
15
components/component-gpg.js
Normal file
@@ -0,0 +1,15 @@
|
||||
(() => {
|
||||
var gpg = require('component-gpg-ex.js');
|
||||
|
||||
gpgEncrypt = (keyId, srcFile, destFile) => {
|
||||
return gpg.encrypt(keyId, srcFile, destFile);
|
||||
};
|
||||
|
||||
gpgEncryptArmor = (keyId, srcFile, destFile) => {
|
||||
return gpg.encryptArmor(keyId, srcFile, destFile);
|
||||
};
|
||||
|
||||
gpgDecrypt = (gpgFile) => {
|
||||
return gpg.decrypt(gpgFile);
|
||||
};
|
||||
})();
|
||||
48
components/component-hashjs.js
Normal file
48
components/component-hashjs.js
Normal file
@@ -0,0 +1,48 @@
|
||||
var COMMENT_HASH_TAG = '//HASH:';
|
||||
|
||||
var CollectionUtil = Packages.me.hatter.tools.commons.collection.CollectionUtil;
|
||||
|
||||
var __containsCommentHashTag = (list) => {
|
||||
for (var i = (list.size() - 1); i >= 0; i--) {
|
||||
var l = list.get(i);
|
||||
if ($STR(l.trim()) != '') {
|
||||
return l.startsWith(COMMENT_HASH_TAG);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var __getDigestJSON = (list) => {
|
||||
var digestJSON = null;
|
||||
if (__containsCommentHashTag(list)) {
|
||||
var last = CollectionUtil.last(list);
|
||||
while ((list.size() > 0) && ($STR(last.trim()) == '')) { CollectionUtil.removeLast(list); last = CollectionUtil.last(list); }
|
||||
if (last.startsWith(COMMENT_HASH_TAG)) {
|
||||
CollectionUtil.removeLast(list);
|
||||
digestJSON = JSON.parse(last.substring(COMMENT_HASH_TAG.length));
|
||||
}
|
||||
}
|
||||
return digestJSON;
|
||||
};
|
||||
|
||||
var __calcSHA256Hex = (list) => {
|
||||
return $STR($$.digests().sha256().digest($$.bytes($ARR(list).join('\n'))).asHex());
|
||||
};
|
||||
|
||||
var __checkSHA256 = (list) => {
|
||||
var digestJSON = __getDigestJSON(list);
|
||||
return digestJSON && (digestJSON.SHA256 == __calcSHA256Hex(list));
|
||||
};
|
||||
|
||||
var checkBytesSHA256 = (bytes) => {
|
||||
return __checkSHA256(bytes.list());
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.__containsCommentHashTag = __containsCommentHashTag;
|
||||
exports.__getDigestJSON = __getDigestJSON;
|
||||
exports.__calcSHA256Hex = __calcSHA256Hex;
|
||||
exports.__checkSHA256 = __checkSHA256;
|
||||
exports.COMMENT_HASH_TAG = COMMENT_HASH_TAG;
|
||||
exports.checkBytesSHA256 = checkBytesSHA256;
|
||||
}
|
||||
6
components/component-helloworld.js
Normal file
6
components/component-helloworld.js
Normal file
@@ -0,0 +1,6 @@
|
||||
(() => {
|
||||
helloworld = () => {
|
||||
return 'Hello World!!!';
|
||||
};
|
||||
})();
|
||||
|
||||
5
components/component-helloworld2.js
Normal file
5
components/component-helloworld2.js
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
exports.sayhello = () => {
|
||||
return 'Say Hello World!';
|
||||
};
|
||||
|
||||
415
components/component-httpserver-ex.js
Normal file
415
components/component-httpserver-ex.js
Normal file
@@ -0,0 +1,415 @@
|
||||
|
||||
var bytes = require('component-bytes.js');
|
||||
|
||||
var Runtime = java.lang.Runtime;
|
||||
var InetSocketAddress = java.net.InetSocketAddress;
|
||||
var Executors = java.util.concurrent.Executors;
|
||||
var Bytes = Packages.me.hatter.tools.commons.bytes.Bytes;
|
||||
var IOUtil = Packages.me.hatter.tools.commons.io.IOUtil;
|
||||
var HttpServer = Packages.com.sun.net.httpserver.HttpServer;
|
||||
|
||||
// {
|
||||
// "status": 200,
|
||||
// "headers": [[key, value],[key2, value2]],
|
||||
// "responseJSON": ...,
|
||||
// "responseBytes": ...,
|
||||
// "responseText": ...,
|
||||
// }
|
||||
var writeResponse = (httpExchange, response) => {
|
||||
response.status = (response.status == null) ? 200 : response.status;
|
||||
var resBs;
|
||||
var resStream = null;
|
||||
if (response.responseJSON != null) {
|
||||
resBs = Bytes.from(JSON.stringify(response.responseJSON)).getBytes();
|
||||
} else if (response.responseText != null) {
|
||||
resBs = Bytes.from(response.responseText).getBytes();
|
||||
} else if (response.responseStream != null) {
|
||||
resBs = null;
|
||||
resStream = response.responseStream;
|
||||
} else {
|
||||
resBs = response.responseBytes;
|
||||
}
|
||||
var responseHeaders = httpExchange.getResponseHeaders();
|
||||
if ((response.headers != null) && (response.headers.length > 0)) {
|
||||
for (var i = 0; i < response.headers.length; i++) {
|
||||
var keyValue = response.headers[i];
|
||||
responseHeaders.set(keyValue[0], keyValue[1]);
|
||||
}
|
||||
} else {
|
||||
responseHeaders.set('Content-Type', 'text/plain;charset=UTF-8');
|
||||
}
|
||||
httpExchange.sendResponseHeaders(response.status, (resBs != null) ? resBs.length : 0);
|
||||
var resBody = httpExchange.getResponseBody();
|
||||
if (resBs != null) {
|
||||
resBody.write(resBs);
|
||||
} else {
|
||||
IOUtil.copy(response.responseStream, resBody);
|
||||
IOUtil.closeQuietly(response.responseStream);
|
||||
}
|
||||
resBody.close();
|
||||
};
|
||||
|
||||
exports.parseQuery = exports.parseQueryParameterMap = (httpExchange) => {
|
||||
var queryParameterMap = {};
|
||||
var rawQuery = $STR(httpExchange.getRequestURI().getRawQuery());
|
||||
if (rawQuery != null) {
|
||||
rawQuery.split('&').forEach((kv) => {
|
||||
var indexOfE = kv.indexOf('=');
|
||||
var key = '';
|
||||
var value = '';
|
||||
if (indexOfE >= 0) {
|
||||
key = kv.substring(0, indexOfE);
|
||||
value = kv.substring(indexOfE + 1);
|
||||
} else {
|
||||
key = kv;
|
||||
}
|
||||
queryParameterMap[key] = queryParameterMap[key] || [];
|
||||
queryParameterMap[key].push(value);
|
||||
});
|
||||
}
|
||||
return queryParameterMap;
|
||||
};
|
||||
|
||||
var handleDir = (httpExchange, dir, opts) => {
|
||||
var sb = [];
|
||||
if (opts.handleDir) {
|
||||
if (!httpExchange.getRequestURI().getPath().endsWith('/')) {
|
||||
return {
|
||||
status: 302,
|
||||
"headers": [
|
||||
["Location", httpExchange.getRequestURI().getPath() + '/'],
|
||||
["Content-Type", 'text/html;charset=UTF-8'],
|
||||
],
|
||||
bytes: new java.lang.String('<html>\n'
|
||||
+ '<head>\n'
|
||||
+ '<title>Redirecting ...</title>\n'
|
||||
+ '<meta http-equiv="refresh" content="0; URL=' + httpExchange.getRequestURI().getPath() + '/' + '" />\n'
|
||||
+ '</head>\n'
|
||||
+ '<body>\n'
|
||||
+ 'Redirect to new location: ' + httpExchange.getRequestURI().getPath() + '/' + '\n'
|
||||
+ '</body>\n'
|
||||
+ '</html>').getBytes('UTF-8')
|
||||
};
|
||||
}
|
||||
|
||||
var files = dir.getAbsoluteFile().listFiles();
|
||||
sb.push('<h1>Directory Listing</h1>\n');
|
||||
sb.push('<br>\n');
|
||||
$EACH(files, (f) => {
|
||||
var isDir = f.isDirectory();
|
||||
if (isDir) {
|
||||
sb.push('<a href="' + f.getName() + '/">[' + f.getName() + ']</a>'
|
||||
+ ' <span style="font-size:12px;"><i>' + new Date(f.lastModified()) + '</i></span>'
|
||||
+ '<br>\n');
|
||||
} else {
|
||||
sb.push('<a href="' + f.getName() + '">' + f.getName() + '</a>'
|
||||
+ ' <span style="font-size:12px;">'
|
||||
+ bytes.showBytes(f.length())
|
||||
+ ' <i>' + new Date(f.lastModified()) + '</i>'
|
||||
+ '</span>'
|
||||
+ '<br>\n');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
sb.push('Directory listing is forbidden.');
|
||||
}
|
||||
return { html: sb.join('') };
|
||||
};
|
||||
|
||||
// https://www.freeformatter.com/mime-types-list.html
|
||||
var mimeTypeList = [
|
||||
[['txt', 'text'], 'text/plain;charset=UTF-8'],
|
||||
[['jpg', 'jpeg'], 'image/jpeg'],
|
||||
[['png'], 'image/png'],
|
||||
[['swf'], 'application/x-shockwave-flash'],
|
||||
[['js'], 'text/javascript;charset=UTF-8'],
|
||||
[['htm', 'html'], 'text/html;charset=UTF-8'],
|
||||
[['css'], 'text/css;charset=UTF-8'],
|
||||
[['geojson'], 'application/vnd.geo+json'],
|
||||
[['svg'], 'image/svg+xml'],
|
||||
[['7z'], 'application/x-7z-compressed'],
|
||||
[['ace'], 'application/x-ace-compressed'],
|
||||
[['acc'], 'application/vnd.americandynamics.acc'],
|
||||
[['pdf'], 'application/pdf'],
|
||||
[['aac'], 'audio/x-aac'],
|
||||
[['apk'], 'application/vnd.android.package-archive'],
|
||||
[['dmg'], 'application/x-apple-diskimage'],
|
||||
[['mpkg'], 'application/vnd.apple.installer+xml'],
|
||||
[['s'], 'text/x-asm'],
|
||||
[['avi'], 'video/x-msvideo'],
|
||||
[['bin'], 'application/octet-stream'],
|
||||
[['bmp'], 'image/bmp'],
|
||||
[['torrent'], 'application/x-bittorrent'],
|
||||
[['sh'], 'application/x-sh'],
|
||||
[['bz'], 'application/x-bzip'],
|
||||
[['bz2'], 'application/x-bzip2'],
|
||||
[['csh'], 'application/x-csh'],
|
||||
[['c'], 'text/x-c'],
|
||||
[['csv'], ' text/csv'],
|
||||
[['deb'], 'application/x-debian-package'],
|
||||
[['dtd'], 'application/xml-dtd'],
|
||||
[['dwg'], 'image/vnd.dwg'],
|
||||
[['es'], 'application/ecmascript'],
|
||||
[['epub'], 'application/epub+zip'],
|
||||
[['eml'], 'message/rfc822'],
|
||||
[['f4v'], 'video/x-f4v'],
|
||||
[['flv'], 'video/x-flv'],
|
||||
[['gif'], 'image/gif'],
|
||||
[['h261'], 'video/h261'],
|
||||
[['h263'], 'video/h263'],
|
||||
[['h264'], 'video/h264'],
|
||||
[['ico'], 'image/x-icon'],
|
||||
[['cer'], 'application/pkix-cert'],
|
||||
[['pki'], 'application/pkixcmp'],
|
||||
[['crl'], 'application/pkix-crl'],
|
||||
[['jad'], 'text/vnd.sun.j2me.app-descriptor'],
|
||||
[['jar'], 'application/java-archive'],
|
||||
[['class'], 'application/java-vm'],
|
||||
[['jnlp'], 'application/x-java-jnlp-file'],
|
||||
[['ser'], 'application/java-serialized-object'],
|
||||
[['java'], 'text/x-java-source,java'],
|
||||
[['json'], 'application/json'],
|
||||
[['m3u', 'm3u8'], 'audio/x-mpegurl'],
|
||||
[['mathml'], 'application/mathml+xml'],
|
||||
[['exe'], 'application/x-msdownload'],
|
||||
[['cab'], 'application/vnd.ms-cab-compressed'],
|
||||
[['eot'], 'application/vnd.ms-fontobject'],
|
||||
[['xls'], 'application/vnd.ms-excel'],
|
||||
[['ppt'], 'application/vnd.ms-powerpoint'],
|
||||
[['doc'], 'application/msword'],
|
||||
[['vsd'], 'application/vnd.visio'],
|
||||
[['chm'], 'application/vnd.ms-htmlhelp'],
|
||||
[['pptx'], 'application/vnd.openxmlformats-officedocument.presentationml.presentation'],
|
||||
[['ppsx'], 'application/vnd.openxmlformats-officedocument.presentationml.slideshow'],
|
||||
[['xlsx'], 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
|
||||
[['docx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
|
||||
[['dotx'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.template'],
|
||||
[['vsdx'], 'application/vnd.visio2013'],
|
||||
[['mpeg'], 'video/mpeg'],
|
||||
[['mp4a'], 'audio/mp4'],
|
||||
[['mp4'], 'video/mp4'],
|
||||
[['psd'], 'image/vnd.adobe.photoshop'],
|
||||
[['p10'], 'application/pkcs10'],
|
||||
[['p12'], 'application/x-pkcs12'],
|
||||
[['p7m'], 'application/pkcs7-mime'],
|
||||
[['p7s'], 'application/pkcs7-signature'],
|
||||
[['p7r'], 'application/x-pkcs7-certreqresp'],
|
||||
[['p7b'], 'application/x-pkcs7-certificates'],
|
||||
[['p8'], 'application/pkcs8'],
|
||||
[['pgp'], 'application/pgp-encrypted'],
|
||||
[['rar'], 'application/x-rar-compressed'],
|
||||
[['rm'], 'application/vnd.rn-realmedia'],
|
||||
[['rtf'], 'application/rtf'],
|
||||
[['movie'], 'video/x-sgi-movie'],
|
||||
[['tiff'], 'image/tiff'],
|
||||
[['tar'], 'application/x-tar'],
|
||||
[['tex'], 'application/x-tex'],
|
||||
[['ttf'], 'application/x-font-ttf'],
|
||||
[['vcs'], 'text/x-vcalendar'],
|
||||
[['vcf'], 'text/x-vcard'],
|
||||
[['wav'], 'audio/x-wav'],
|
||||
[['woff'], 'application/x-font-woff'],
|
||||
[['webp'], 'image/webp'],
|
||||
[['der'], 'application/x-x509-ca-cert'],
|
||||
[['xml'], 'application/xml'],
|
||||
[['zip'], 'application/zip']
|
||||
];
|
||||
|
||||
var mimeTypeMap = {};
|
||||
mimeTypeList.forEach((m) => {
|
||||
m[0].forEach((t) => {
|
||||
mimeTypeMap[t] = m[1];
|
||||
});
|
||||
});
|
||||
|
||||
var getMimeTypeByExt = (ext) => {
|
||||
return mimeTypeMap[ext] || 'application/octet-stream';
|
||||
};
|
||||
|
||||
var fileCacheSize = 0;
|
||||
var fileCacheCount = 0;
|
||||
var fileCacheMap = {};
|
||||
var handleFile = (httpExchange, file, opts) => {
|
||||
var fileAbsPath = file.getAbsolutePath();
|
||||
if (opts.enableFileCache) {
|
||||
println('[INFO] ' + getDateYmd() + ' ' + 'File cache hit: ' + fileAbsPath);
|
||||
var cachedFileContent = fileCacheMap[fileAbsPath];
|
||||
if (cachedFileContent) { return cachedFileContent; } // cache hit
|
||||
}
|
||||
if (file.exists()) {
|
||||
var path = $STR(httpExchange.getRequestURI().getPath()).toLowerCase();
|
||||
var lastIndexOfDot = path.lastIndexOf('.');
|
||||
var ext = '';
|
||||
if (lastIndexOfDot >= 0) {
|
||||
ext = path.substring(lastIndexOfDot + 1);
|
||||
}
|
||||
var contentType = null;
|
||||
if (opts.getContentType) {
|
||||
contentType = opts.getContentType(httpExchange, file, ext);
|
||||
}
|
||||
contentType = contentType || getMimeTypeByExt(ext);
|
||||
|
||||
if (opts.enableFileCache && (file.length() < (opts.cacheFileLength || (1024 * 1024 * 5)))) { // default cache file length 5MB
|
||||
if (fileCacheCount < (opts.cacheCount || 1000)) { // default cache size 1000
|
||||
var fileContent = {
|
||||
headers: [
|
||||
['Content-Type', contentType],
|
||||
['Content-Length', file.length()]
|
||||
],
|
||||
bytes: $$.rFile(file).rStream().bytesAndClose()
|
||||
};
|
||||
fileCacheCount++;
|
||||
fileCacheSize += file.length();
|
||||
println('[INFO] ' + getDateYmd() + ' ' + 'File cached: ' + fileAbsPath + ', size: ' + bytes.showBytes(file.length()) + ', cached count: ' + fileCacheCount + ', cached size: ' + bytes.showBytes(fileCacheSize));
|
||||
fileCacheMap[fileAbsPath] = fileContent;
|
||||
return fileContent;
|
||||
}
|
||||
}
|
||||
return {
|
||||
headers: [
|
||||
['Content-Type', contentType],
|
||||
['Content-Length', file.length()]
|
||||
],
|
||||
stream: $$.rFile(file).rStream().stream()
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
var getDateYmd = () => {
|
||||
return new java.text.SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(new java.util.Date());
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {*} httpExchange
|
||||
* @param {*} options
|
||||
* basePath - base path
|
||||
* getContentType (httpExchange, file, ext) - get content type
|
||||
* handleDir - enable dir listing
|
||||
*/
|
||||
exports.handleFile = (httpExchange, options) => {
|
||||
var opts = options || {};
|
||||
var path = $STR(httpExchange.getRequestURI().getPath());
|
||||
if (path == '/') {
|
||||
return handleDir(httpExchange, opts.basePath ? $$.file(opts.basePath) : $$.file(''), opts);
|
||||
}
|
||||
var f = path.substring(1);
|
||||
var file = opts.basePath ? $$.file(opts.basePath, f) : $$.file(f);
|
||||
if (file.exists()) {
|
||||
if (file.isDirectory()) {
|
||||
return handleDir(httpExchange, file, opts);
|
||||
} else {
|
||||
return handleFile(httpExchange, file, opts);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} port port number
|
||||
* @param {*} handler process handle
|
||||
* return {
|
||||
* text: 'text'
|
||||
* }
|
||||
* return {
|
||||
* html: 'html'
|
||||
* }
|
||||
* ...
|
||||
* @param {*} options
|
||||
* processors - processor count
|
||||
* printErrors - print exception detail
|
||||
*/
|
||||
exports.serveHTTP = (port, handler, options) => {
|
||||
var opts = options || {};
|
||||
var addr = new InetSocketAddress(port);
|
||||
var httpServer = HttpServer.create(addr, 0);
|
||||
if (opts.processors) {
|
||||
httpServer.setExecutor(Executors.newFixedThreadPool(opts.processors));
|
||||
} else {
|
||||
httpServer.setExecutor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2));
|
||||
}
|
||||
httpServer.createContext("/", (httpExchange) => {
|
||||
try {
|
||||
println('[INFO] ' + getDateYmd() + ' ' + httpExchange.getRequestURI());
|
||||
var response = handler(httpExchange);
|
||||
if (response != null) {
|
||||
if (response.text != null) {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": [
|
||||
["Content-Type", "text/plain;charset=UTF-8"],
|
||||
],
|
||||
"responseText": response.text
|
||||
};
|
||||
} else if (response.html != null) {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": [
|
||||
["Content-Type", "text/html;charset=UTF-8"],
|
||||
],
|
||||
"responseText": response.html
|
||||
};
|
||||
} else if (response.css != null) {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": [
|
||||
["Content-Type", "text/css;charset=UTF-8"],
|
||||
],
|
||||
"responseText": response.css
|
||||
};
|
||||
} else if (response.js != null) {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": [
|
||||
["Content-Type", "text/javascript;charset=UTF-8"],
|
||||
],
|
||||
"responseText": response.js
|
||||
};
|
||||
} else if (response.json != null) {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": [
|
||||
["Content-Type", "application/json;charset=UTF-8"],
|
||||
],
|
||||
"responseJSON": response.json
|
||||
};
|
||||
} else if (response.bytes != null) {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": response.headers,
|
||||
"responseBytes": response.bytes
|
||||
};
|
||||
} else if (response.stream != null) {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": response.headers,
|
||||
"responseStream": response.stream
|
||||
};
|
||||
} else {
|
||||
responseResult = {
|
||||
"status": response.status || 200,
|
||||
"headers": [
|
||||
["Content-Type", "text/plain;charset=UTF-8"],
|
||||
],
|
||||
"responseText": $STR(response)
|
||||
};
|
||||
}
|
||||
writeResponse(httpExchange, responseResult);
|
||||
}
|
||||
} catch (e) {
|
||||
var errMsg = '[ERROR] Request: ' + httpExchange.getRequestURI() + ', exception: ' + e;
|
||||
println('[ERROR] ' + getDateYmd() + ' ' + errMsg);
|
||||
if (e.printStackTrace) { e.printStackTrace(); }
|
||||
|
||||
writeResponse(httpExchange, {
|
||||
"status": 500,
|
||||
"responseText": opts.printErrors ? errMsg : '500 - Server Error'
|
||||
});
|
||||
}
|
||||
});
|
||||
println('[INFO] ' + getDateYmd() + ' ' + "Start listen at: " + port + ' ...');
|
||||
httpServer.start();
|
||||
};
|
||||
|
||||
12
components/component-httpserver.js
Normal file
12
components/component-httpserver.js
Normal file
@@ -0,0 +1,12 @@
|
||||
(() => {
|
||||
var httpserver = require('component-httpserver-ex.js');
|
||||
|
||||
parseQueryParameterMap = (httpExchange) => {
|
||||
return httpserver.parseQueryParameterMap(httpExchange);
|
||||
};
|
||||
|
||||
serveHTTP = (port, handler) => {
|
||||
return httpserver.serveHTTP(port, handler);
|
||||
};
|
||||
})();
|
||||
|
||||
67
components/component-javahome.js
Normal file
67
components/component-javahome.js
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
var OSUtil = Packages.me.hatter.tools.commons.os.OSUtil;
|
||||
|
||||
var getJavaHomeFromJdks = (version) => {
|
||||
var jdksPath = $$.file('~/.jssp/jdks');
|
||||
if (!(jdksPath.exists() && jdksPath.isDirectory())) {
|
||||
return null;
|
||||
}
|
||||
var jdkVersions = $ARRAY(jdksPath.listFiles()).filter((p) => {
|
||||
return p.isDirectory();
|
||||
}).map((p) => {
|
||||
var jdkVersion = p.getName();
|
||||
if (jdkVersion.startsWith('jdk-')) {
|
||||
jdkVersion = jdkVersion.substring('jdk-'.length);
|
||||
} else if (jdkVersion.startsWith('jdk')) {
|
||||
jdkVersion = jdkVersion.substring('jdk'.length);
|
||||
}
|
||||
return [jdkVersion, p.getAbsolutePath()];
|
||||
}).sort((a, b) => {
|
||||
return b[0] - a[0];
|
||||
});
|
||||
for (var i = 0; i < jdkVersions.length; i++) {
|
||||
if (jdkVersions[i][0].startsWith(version)) {
|
||||
return jdkVersions[i][1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var getJavaHomeFromBuildConfig = (version) => {
|
||||
var buildConfigRFile = __.rfile.from('~/.jssp/config/buildconfig.json');
|
||||
if (buildConfigRFile.notExists()) {
|
||||
return null;
|
||||
}
|
||||
var buildConfigJSON = JSON.parse(buildConfigRFile.string());
|
||||
if (buildConfigJSON['java'] && buildConfigJSON['java']['versions']) {
|
||||
var versions = buildConfigJSON['java']['versions'];
|
||||
for (var i = 0; i < versions.length; i++) {
|
||||
if (versions[i].startsWith(version)) {
|
||||
return buildConfigJSON['java'][versions[i]]['home'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
var getJavaHome = (version) => {
|
||||
if ((version == null) || ($STR(version) == '')) { return null; }
|
||||
if (OSUtil.isMacOS()) {
|
||||
var jversions = $$.shell().commands('/usr/libexec/java_home', '-version', version).start();
|
||||
if (jversions[1] && $STR(jversions[1].toString()).contains('Unable to find any JVMs matching version')) {
|
||||
return null;
|
||||
}
|
||||
return jversions[0].toString().trim();
|
||||
} else {
|
||||
var javaHomeFromJdks = getJavaHomeFromJdks(version);
|
||||
if (javaHomeFromJdks != null) {
|
||||
return javaHomeFromJdks;
|
||||
}
|
||||
var javaHomeFromBuildConfig = getJavaHomeFromBuildConfig(version);
|
||||
return javaHomeFromBuildConfig;
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.getJavaHome = getJavaHome;
|
||||
}
|
||||
51
components/component-jose.js
Normal file
51
components/component-jose.js
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
$ONCE('component-jose-requireJARS').run(() => {
|
||||
requireJAR('jose4j-0.5.5.jar');
|
||||
requireJAR('slf4j-api-1.7.21.jar');
|
||||
});
|
||||
|
||||
var JsonWebKey = Packages.org.jose4j.jwk.JsonWebKey;
|
||||
var JsonWebEncryption = Packages.org.jose4j.jwe.JsonWebEncryption;
|
||||
var AlgorithmConstraints = Packages.org.jose4j.jwa.AlgorithmConstraints;
|
||||
var ConstraintType = Packages.org.jose4j.jwa.AlgorithmConstraints.ConstraintType;
|
||||
var KeyManagementAlgorithmIdentifiers = Packages.org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;
|
||||
var ContentEncryptionAlgorithmIdentifiers = Packages.org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
|
||||
|
||||
var jwkLoad = (jwkJSONString) => {
|
||||
return JsonWebKey.Factory.newJwk(jwkJSONString);
|
||||
}
|
||||
|
||||
var jweEnc = (jwk, txt) => {
|
||||
var jwe = new JsonWebEncryption();
|
||||
jwe.setPlaintext(txt);
|
||||
jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.DIRECT);
|
||||
jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_GCM);
|
||||
jwe.setKey(jwk.getKey());
|
||||
return jwe.getCompactSerialization();
|
||||
};
|
||||
|
||||
var jweDec = (jwk, compactSerialization) => {
|
||||
var jwe = new JsonWebEncryption();
|
||||
var algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST, KeyManagementAlgorithmIdentifiers.DIRECT);
|
||||
jwe.setAlgorithmConstraints(algConstraints);
|
||||
var encConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST, ContentEncryptionAlgorithmIdentifiers.AES_128_GCM);
|
||||
jwe.setContentEncryptionAlgorithmConstraints(encConstraints);
|
||||
jwe.setCompactSerialization(compactSerialization);
|
||||
jwe.setKey(jwk.getKey());
|
||||
return receiverJwe.getPlaintextString();
|
||||
};
|
||||
|
||||
var jwk = {
|
||||
"load": jwkLoad
|
||||
};
|
||||
var jwe = {
|
||||
"enc": jweEnc,
|
||||
"dec": jweDec
|
||||
};
|
||||
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.jwk = jwk;
|
||||
exports.jwe = jwe;
|
||||
}
|
||||
|
||||
13
components/component-json-ex.js
Normal file
13
components/component-json-ex.js
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
var FastJSON = Packages.com.alibaba.fastjson.JSON;
|
||||
var FastJSONSerializerFeature = Packages.com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
|
||||
exports.prettyJSON = (obj) => {
|
||||
return FastJSON.toJSONString(FastJSON.parse(JSON.stringify(obj)), FastJSONSerializerFeature.PrettyFormat);
|
||||
};
|
||||
|
||||
exports.prettyJavaJSON = (obj) => {
|
||||
return FastJSON.toJSONString(obj, FastJSONSerializerFeature.PrettyFormat);
|
||||
};
|
||||
|
||||
|
||||
7
components/component-json.js
Normal file
7
components/component-json.js
Normal file
@@ -0,0 +1,7 @@
|
||||
(() => {
|
||||
var json = require('component-json-ex.js');
|
||||
|
||||
prettyJSON = (obj) => {
|
||||
return json.prettyJSON(obj);
|
||||
};
|
||||
})();
|
||||
8
components/component-mysqldataaccess-ex.js
Normal file
8
components/component-mysqldataaccess-ex.js
Normal file
@@ -0,0 +1,8 @@
|
||||
requireJAR('mysql-connector-java-5.1.44.jar');
|
||||
requireJAR('dataaccess-1.0.jar');
|
||||
|
||||
var DataAccessObjectUtil = Packages.me.hatter.tools.dataaccess.util.DataAccessObjectUtil;
|
||||
|
||||
exports.createDAO = (host, sid, userName, password) => {
|
||||
return DataAccessObjectUtil.createMySQLObject(host, sid, userName, password);
|
||||
};
|
||||
16
components/component-os.js
Normal file
16
components/component-os.js
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
// https://stackoverflow.com/questions/246007/how-to-determine-whether-a-given-linux-is-32-bit-or-64-bit
|
||||
// https://stackoverflow.com/questions/106387/is-it-possible-to-detect-32-bit-vs-64-bit-in-a-bash-script
|
||||
var getOS = () => {
|
||||
var osName = $STR($$.shell().commands('uname').start()[0]).trim();
|
||||
var arch = $STR($$.shell().commands('uname', '-m').start()[0]).trim(); // OR getconf LONG_BIT
|
||||
|
||||
return {
|
||||
'name': osName,
|
||||
'arch': arch
|
||||
};
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.getOS = getOS;
|
||||
}
|
||||
78
components/component-oss.js
Normal file
78
components/component-oss.js
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
var URLEncoder = java.net.URLEncoder;
|
||||
var Bytes = Packages.me.hatter.tools.commons.bytes.Bytes;
|
||||
var HMacs = Packages.me.hatter.tools.commons.security.hmac.HMacs;
|
||||
|
||||
var counter = require('component-counter.js');
|
||||
|
||||
var requireJARs = () => {
|
||||
$ONCE('component-oss-requireJARS').run(() => {
|
||||
requireJAR('aliyun-sdk-oss-2.4.1-SNAPSHOT.jar');
|
||||
requireJAR('commons-beanutils-1.8.0.jar');
|
||||
requireJAR('commons-codec-1.9.jar');
|
||||
requireJAR('commons-collections-3.2.1.jar');
|
||||
requireJAR('commons-lang-2.5.jar');
|
||||
requireJAR('commons-logging-1.2.jar');
|
||||
requireJAR('ezmorph-1.0.6.jar');
|
||||
requireJAR('hamcrest-core-1.1.jar');
|
||||
requireJAR('httpclient-4.4.1.jar');
|
||||
requireJAR('httpcore-4.4.1.jar');
|
||||
requireJAR('jdom-1.1.jar');
|
||||
requireJAR('json-lib-2.4-jdk15.jar');
|
||||
});
|
||||
};
|
||||
|
||||
var generateSignedURL = (endpoint, accessKeyId, accessKeySecret, bucketName, key, expiresInSeconds, isHTTP) => {
|
||||
var sb = [];
|
||||
sb.push(isHTTP ? 'http://' : 'https://'); // default HTTPS
|
||||
sb.push(bucketName);
|
||||
sb.push('.' + endpoint);
|
||||
sb.push('/' + key);
|
||||
var expires = parseInt($$.date().millis() / 1000) + expiresInSeconds;
|
||||
sb.push('?Expires=' + expires);
|
||||
sb.push('&OSSAccessKeyId=' + URLEncoder.encode(accessKeyId, 'UTF-8'));
|
||||
sb.push('&Signature=' + URLEncoder.encode(sign(accessKeySecret, expires, bucketName, key), 'UTF-8'));
|
||||
return sb.join('');
|
||||
};
|
||||
|
||||
var sign = (accessKeySecret, expires, bucketName, key) => {
|
||||
return HMacs.sha1(Bytes.from(accessKeySecret).getBytes())
|
||||
.sign(Bytes.from('GET\n\n\n' + expires + '\n/' + bucketName + '/' + key).getBytes())
|
||||
.asBase64();
|
||||
};
|
||||
|
||||
var createCounterIS = (file) => {
|
||||
var CounterInputStream = Packages.me.hatter.tools.commons.io.CounterInputStream;
|
||||
var uploadFile = (file instanceof java.io.File) ? file : new java.io.File(file);
|
||||
var uploadIS = new java.io.FileInputStream(uploadFile);
|
||||
var counterIS = new CounterInputStream(uploadIS, counter.getCounter(uploadFile.length()));
|
||||
return counterIS;
|
||||
};
|
||||
|
||||
var newClient = (endpoint, accessKey, secretKey) => {
|
||||
requireJARs();
|
||||
|
||||
var OSSClient = Packages.com.aliyun.oss.OSSClient;
|
||||
var client = new OSSClient(endpoint, accessKey, secretKey);
|
||||
return {
|
||||
runWith: (runFunc) => {
|
||||
try {
|
||||
runFunc(client);
|
||||
} catch (e) {
|
||||
println('OSS Error: ' + e);
|
||||
} finally {
|
||||
client.shutdown();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.requireJARs = requireJARs;
|
||||
exports.sign = sign;
|
||||
exports.generateSignedURL = generateSignedURL;
|
||||
exports.createCounterIS = createCounterIS;
|
||||
exports.newClient = newClient;
|
||||
}
|
||||
|
||||
55
components/component-package.js
Normal file
55
components/component-package.js
Normal file
@@ -0,0 +1,55 @@
|
||||
var counter = require('component-counter.js');
|
||||
|
||||
var getLocalPackage = (packageInfo, skipCertCheck) => {
|
||||
var basePath = $$.file(packageInfo.basePath);
|
||||
var bin = $$.file(basePath, packageInfo.subPath, packageInfo.bin);
|
||||
if (!(bin.exists())) {
|
||||
var packageFn = packageInfo.package.substring(packageInfo.package.lastIndexOf('/') + 1);
|
||||
xprintln('[INFO] Package bin not exists, downloading...');
|
||||
var packageFile = $$.file(basePath, packageFn);
|
||||
packageFile.getAbsoluteFile().getParentFile().mkdirs();
|
||||
var fos = new java.io.FileOutputStream(packageFile);
|
||||
$$.httpRequest()
|
||||
.url(packageInfo.package)
|
||||
.addHeader('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36')
|
||||
.skipCertCheck(!! skipCertCheck)
|
||||
.get(fos, counter.getCounter2());
|
||||
fos.close();
|
||||
println();
|
||||
|
||||
var sha256 = $$.rFile(packageFile).digest($$.digests().sha256()).asHex();
|
||||
if ($STR(sha256) == packageInfo.sha256) {
|
||||
xprintln('[SUCCESS] Check SHA256 success: ' + packageFn);
|
||||
} else {
|
||||
xprintln('[ERROR] Check SHA256 failed, actual is: ' + sha256 + ',expected: ' + packageInfo.sha256 + ': ' + packageFn);
|
||||
f.renameTo($$.file(basePath, packageFn + '.invalid.' + $$.date().millis()));
|
||||
return null;
|
||||
}
|
||||
|
||||
var installBuilderScripts = [];
|
||||
installBuilderScripts.push('cd ' + packageInfo.basePath);
|
||||
if (/.*\.tar\.gz$/.test(packageInfo.package) || /.*\.tgz$/.test(packageInfo.package)) {
|
||||
installBuilderScripts.push('tar xzvf ' + packageFn);
|
||||
} else if (/.*\.zip$/.test(packageInfo.package)) {
|
||||
installBuilderScripts.push('unzip ' + packageFn);
|
||||
} else {
|
||||
xprintln('[ERROR] Extract package failed: ' + packageFn);
|
||||
return;
|
||||
}
|
||||
installBuilderScripts.push('');
|
||||
|
||||
var builderIntall = $$.file('.builder_install.sh');
|
||||
$$.rFile(builderIntall).write(installBuilderScripts.join('\n'));
|
||||
$$.shell().inheritIO().commands('sh', builderIntall.getName()).run();
|
||||
builderIntall.delete();
|
||||
}
|
||||
return {
|
||||
'packageInfo': packageInfo,
|
||||
'packageHome': $STR($$.file(packageInfo.basePath, packageInfo.subPath).getAbsolutePath()),
|
||||
'binFile': bin
|
||||
};
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.getLocalPackage = getLocalPackage;
|
||||
}
|
||||
149
components/component-pki.js
Normal file
149
components/component-pki.js
Normal file
@@ -0,0 +1,149 @@
|
||||
var gpg = require('component-gpg-ex.js');
|
||||
|
||||
var File = java.io.File;
|
||||
var ECSignatureTool = Packages.me.hatter.tools.commons.security.sign.SignatureTool;
|
||||
|
||||
var DEFAULT_SIGN_FILE_EXT = '.sig.txt';
|
||||
var DEFAULT_PGP_KEY_ID = '6FAFC0E0170985AA71545483C794B1646A886CD6';
|
||||
var DEFAULT_EC_PRIVATE_KEY_PGP_ENC = '-----BEGIN PGP MESSAGE-----\n' +
|
||||
'Comment: GPGTools - https://gpgtools.org\n' +
|
||||
'\n' +
|
||||
'hQIMA8N6kJ6vG/sAAQ//ef8seBe4daxW1tQg12G6tE2VhA1Y0W/Y3GKCtAxM8PwC\n' +
|
||||
'j/VjanTqozVwVQp7Qb3hHoBkEJBAEjrNtIhUE7dJBSbrGkK5i8mkQpkc8MFgtx1A\n' +
|
||||
'LVkhdNkTWenk07l6d56v0+iVjlWJsl9wlpP9eY3GkqkWydCXPEn0rICrB3mBf2BA\n' +
|
||||
'SRPqucnzSpIjH+KXhUcyVFjU86ZHyzoRP5RwG2MVVSWhwt7Oyd9A6p1hAKHKIjwH\n' +
|
||||
'K1W4PhxwrjnelcVWC2uwSLWXqgdXQ0EZXMzH5fv3R2EdZopyaC7AF6/jtauEs5RO\n' +
|
||||
'X4l64jjfajqswSZKW0fGKqJgPVzb3p2fBGBeBFx2sYGU/Xk7QTQlfKOvADzLdEIE\n' +
|
||||
'hw/i1Huo/xSg4CYiyjlVw82x6cA10UP2d7KRA21NPqWQUKv9p6aWpjkXoM1UE+5D\n' +
|
||||
'TdyHSnT0Fu+VaBsGZ+3/x+oRlM6PHjk22n8CUEsZecYzGnyXyAEJuCaYOVtfSMTW\n' +
|
||||
'gdy13gJInaxMawHHyRVFqJClZsXc4LEsSsY4fdTus6mEkD+S5S2gkoFffB6uLWYL\n' +
|
||||
'pq59IIJ+tp2Y3wxCqUXhu0PYer5No7lU/A53+dtcj7xQYLoOUlB/DkHWfmqAsJi7\n' +
|
||||
'Zt+SXoy0ksCtXciBZRhuJESbISALjKqOfQIV/8J9GrN/zQl/dzEmrfgqE00hY1bS\n' +
|
||||
'kQFX26y+2iY7k2xoLg+fNB6LNKmtM4U6115CL+rcX3p02P1f4E6O4gGEg9l/3fe2\n' +
|
||||
'rz7+2a3WK/MNE1Ak7ImFf6ufU3PHUCQqyEqk7wGeNmRRG3SPJUyBQbpa6I+4xTZ8\n' +
|
||||
'R6RqgeigqUMDFyyIwYULEwP+dqnHfRBeckh3MKGfrHQUmgrGDOYawxb1G+h2iaVC\n' +
|
||||
'VtA=\n' +
|
||||
'=QCYC\n' +
|
||||
'-----END PGP MESSAGE-----';
|
||||
var DEFAULT_EC_PUBLIC_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESZWG1x7tlv02YF+UZzuZdLquR6Oi3H7QRmaRWzDoupG66dWeKruRUQVj2ozliDKaRQ+5b91u/z9BApIaFs6quw==';
|
||||
|
||||
var generateECsecp256r1KeyPair = () => {
|
||||
var ecSignTool = ECSignatureTool.secp256r1();
|
||||
ecSignTool.generateKeyPair();
|
||||
return {
|
||||
'privKey': ecSignTool.encodePriKey(),
|
||||
'pubKey': ecSignTool.encodePubKey()
|
||||
};
|
||||
};
|
||||
|
||||
var __defaultEcPrivateKeyBytes = null;
|
||||
var getDefaultEcPrivateKeyBytes = () => {
|
||||
if (__defaultEcPrivateKeyBytes != null) { return __defaultEcPrivateKeyBytes; }
|
||||
|
||||
var __defaultEcPrivateKeyLocalFile = $$.file('~/.jssp/config/.defaultecprivatekey.json');
|
||||
if (__defaultEcPrivateKeyLocalFile.exists()) {
|
||||
return __.bytes.fromBase64(JSON.parse($$.rFile(__defaultEcPrivateKeyLocalFile).string()).base64Key);
|
||||
}
|
||||
|
||||
var tempPrivKeyFile = File.createTempFile('component-pki', '.temp_key');
|
||||
$$.rFile(tempPrivKeyFile).write(DEFAULT_EC_PRIVATE_KEY_PGP_ENC);
|
||||
tempPrivKeyFile.deleteOnExit();
|
||||
var privKey = gpg.decrypt(tempPrivKeyFile.getAbsolutePath());
|
||||
__defaultEcPrivateKeyBytes = __.bytes.fromBase64(privKey.trim());
|
||||
|
||||
__defaultEcPrivateKeyLocalFile.getParentFile().mkdirs();
|
||||
$$.rFile(__defaultEcPrivateKeyLocalFile).write(JSON.stringify({
|
||||
'date': $$.date().fmt('yyyy-MM-dd HH:mm:ss Z').format($$.date().today()),
|
||||
'base64Key': __defaultEcPrivateKeyBytes.asBase64()
|
||||
}));
|
||||
|
||||
return __defaultEcPrivateKeyBytes;
|
||||
};
|
||||
|
||||
var getDefaultEcPublicKeyBytes = () => {
|
||||
return __.bytes.fromBase64(DEFAULT_EC_PUBLIC_KEY);
|
||||
};
|
||||
|
||||
var getDefaultEcSignSignature = () => {
|
||||
return ECSignatureTool.secp256r1().decodePriKey(getDefaultEcPrivateKeyBytes()).signSHA256ECDSA();
|
||||
};
|
||||
|
||||
var getDefaultEcVerifySignature = () => {
|
||||
return ECSignatureTool.secp256r1().decodePubKey(getDefaultEcPublicKeyBytes()).verifySHA256ECDSA();
|
||||
};
|
||||
|
||||
var defaultSignFile = (file) => {
|
||||
file = $$.file(file);
|
||||
if (file.getName().endsWith(DEFAULT_SIGN_FILE_EXT) || !(file.exists()) || !(file.isFile())) {
|
||||
return false;
|
||||
}
|
||||
var signFile = $$.file(file.getAbsoluteFile().getParentFile(), file.getName() + DEFAULT_SIGN_FILE_EXT);
|
||||
var sigHex = $$.rFile(file).sign(getDefaultEcSignSignature()).asHex();
|
||||
$$.rFile(signFile).write(JSON.stringify({
|
||||
'length': $$.str(file.length()),
|
||||
'lastModified': $$.str(file.lastModified()),
|
||||
'signature': sigHex
|
||||
}));
|
||||
return true;
|
||||
};
|
||||
|
||||
var defaultSignFileV2 = (file) => {
|
||||
file = $$.file(file);
|
||||
if (file.getName().endsWith(DEFAULT_SIGN_FILE_EXT) || !(file.exists()) || !(file.isFile())) {
|
||||
return false;
|
||||
}
|
||||
var signFile = $$.file(file.getAbsoluteFile().getParentFile(), file.getName() + DEFAULT_SIGN_FILE_EXT);
|
||||
var sha256 = $$.rFile(file).digest(__.digests.sha256()).asHex();
|
||||
var sigHex = __.bytes.fromHex(sha256).sign(getDefaultEcSignSignature()).asHex();
|
||||
$$.rFile(signFile).write(JSON.stringify({
|
||||
'version': 2,
|
||||
'length': $$.str(file.length()),
|
||||
'lastModified': $$.str(file.lastModified()),
|
||||
'SHA256': sha256,
|
||||
'signature': sigHex
|
||||
}));
|
||||
return true;
|
||||
};
|
||||
|
||||
var defaultQuickVerifyFile = (file) => {
|
||||
file = $$.file(file);
|
||||
if (file.getName().endsWith(DEFAULT_SIGN_FILE_EXT) || !(file.exists()) || !(file.isFile())) {
|
||||
return null;
|
||||
}
|
||||
var signFile = $$.file(file.getAbsoluteFile().getParentFile(), file.getName() + DEFAULT_SIGN_FILE_EXT);
|
||||
if (!(signFile.exists())) {
|
||||
return null;
|
||||
}
|
||||
var signatureJSON = JSON.parse($$.rFile(signFile).string().trim());
|
||||
return $$.strEquals(file.length(), signatureJSON.length) && $$.strEquals(file.lastModified(), signatureJSON.lastModified);
|
||||
};
|
||||
|
||||
var defaultVerifyFile = (file) => {
|
||||
file = $$.file(file);
|
||||
if (file.getName().endsWith(DEFAULT_SIGN_FILE_EXT) || !(file.exists()) || !(file.isFile())) {
|
||||
return null;
|
||||
}
|
||||
var signFile = $$.file(file.getAbsoluteFile().getParentFile(), file.getName() + DEFAULT_SIGN_FILE_EXT);
|
||||
if (!(signFile.exists())) {
|
||||
return null;
|
||||
}
|
||||
var signatureJSON = JSON.parse($$.rFile(signFile).string().trim());
|
||||
if (signatureJSON.version) {
|
||||
var sha256 = $$.rFile(file).digest(__.digests.sha256());
|
||||
return $$.strEquals(sha256.asHex(), signatureJSON.SHA256) && sha256.verify(getDefaultEcVerifySignature(), __.bytes.fromHex(signatureJSON.signature));
|
||||
} else {
|
||||
return $$.rFile(file).verify(getDefaultEcVerifySignature(), __.bytes.fromHex(signatureJSON.signature));
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.generateECsecp256r1KeyPair = generateECsecp256r1KeyPair;
|
||||
exports.getDefaultEcPrivateKeyBytes = getDefaultEcPrivateKeyBytes;
|
||||
exports.getDefaultEcPublicKeyBytes = getDefaultEcPublicKeyBytes;
|
||||
exports.getDefaultEcSignSignature = getDefaultEcSignSignature;
|
||||
exports.getDefaultEcVerifySignature = getDefaultEcVerifySignature;
|
||||
exports.defaultSignFile = defaultSignFile;
|
||||
exports.defaultVerifyFile = defaultVerifyFile;
|
||||
exports.defaultSignFileV2 = defaultSignFileV2;
|
||||
exports.defaultQuickVerifyFile = defaultQuickVerifyFile;
|
||||
}
|
||||
33
components/component-shannonentropy-ex.js
Normal file
33
components/component-shannonentropy-ex.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// http://blog.dkbza.org/2007/05/scanning-data-for-entropy-anomalies.html
|
||||
// https://github.com/dxa4481/truffleHog/blob/master/truffleHog.py
|
||||
|
||||
var Math_log2 = Math.log2 || (x) => {
|
||||
return Math.log(x) * Math.LOG2E;
|
||||
};
|
||||
|
||||
exports.SHANNON_ENTROPY_BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||
exports.SHANNON_ENTROPY_HEX = "1234567890abcdefABCDEF";
|
||||
|
||||
exports.shannonEntropy = (data, charRange) => {
|
||||
if (!data) {
|
||||
return 0;
|
||||
}
|
||||
var lenOfData = data.length;
|
||||
var charCodeCountMap = {};
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var charCode = data.charCodeAt(i);
|
||||
charCodeCountMap[charCode] = charCodeCountMap[charCode] || 0;
|
||||
charCodeCountMap[charCode] += 1;
|
||||
}
|
||||
var entropy = 0;
|
||||
for (var i = 0; i < charRange.length; i++) {
|
||||
var charCode = charRange.charCodeAt(i);
|
||||
var charCodeCount = charCodeCountMap[charCode];
|
||||
if (charCodeCount != null) {
|
||||
var pCharCode = charCodeCount / lenOfData;
|
||||
entropy += - pCharCode * Math_log2(pCharCode);
|
||||
}
|
||||
}
|
||||
return entropy;
|
||||
};
|
||||
|
||||
10
components/component-shannonentropy.js
Normal file
10
components/component-shannonentropy.js
Normal file
@@ -0,0 +1,10 @@
|
||||
(() => {
|
||||
var shannonentropy = require('component-shannonentropy-ex.js');
|
||||
|
||||
SHANNON_ENTROPY_BASE64 = shannonentropy.SHANNON_ENTROPY_BASE64;
|
||||
SHANNON_ENTROPY_HEX = shannonentropy.SHANNON_ENTROPY_HEX;
|
||||
|
||||
shannonEntropy = (data, charRange) => {
|
||||
return shannonentropy.shannonEntropy(data, charRange);
|
||||
};
|
||||
})();
|
||||
8
components/component-sqlitedataaccess-ex.js
Normal file
8
components/component-sqlitedataaccess-ex.js
Normal file
@@ -0,0 +1,8 @@
|
||||
requireJAR('jdbc.sqlite-3.6.7.jar');
|
||||
requireJAR('dataaccess-1.0.jar');
|
||||
|
||||
var DataAccessObjectUtil = Packages.me.hatter.tools.dataaccess.util.DataAccessObjectUtil;
|
||||
|
||||
exports.createDAO = (dbFile) => {
|
||||
return DataAccessObjectUtil.createSqliteObject(dbFile);
|
||||
};
|
||||
7
components/component-sqlitedataaccess.js
Normal file
7
components/component-sqlitedataaccess.js
Normal file
@@ -0,0 +1,7 @@
|
||||
(() => {
|
||||
var sqlitedao = require('component-sqlitedataaccess-ex.js');
|
||||
|
||||
createSqliteDataAccessObject = (dbFile) => {
|
||||
return sqlitedao.createDAO(dbFile);
|
||||
};
|
||||
})();
|
||||
94
components/component-swing.js
Normal file
94
components/component-swing.js
Normal file
@@ -0,0 +1,94 @@
|
||||
(() => {
|
||||
var JFrame = javax.swing.JFrame;
|
||||
var JLabel = javax.swing.JLabel;
|
||||
var JPanel = javax.swing.JPanel;
|
||||
var JButton = javax.swing.JButton;
|
||||
var JTextArea = javax.swing.JTextArea;
|
||||
var JScrollPane = javax.swing.JScrollPane;
|
||||
var Frame = java.awt.Frame;
|
||||
var Toolkit = java.awt.Toolkit;
|
||||
var BorderLayout = java.awt.BorderLayout;
|
||||
var WindowListener = java.awt.event.WindowListener;
|
||||
var Proxy = java.lang.reflect.Proxy;
|
||||
var CountDownLatch = java.util.concurrent.CountDownLatch;
|
||||
|
||||
try {
|
||||
//javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getCrossPlatformLookAndFeelClassName());
|
||||
} catch (e) { /* IGNORE */ }
|
||||
|
||||
function FutureResult() {
|
||||
this.result = null;
|
||||
this.countDown = new CountDownLatch(1);
|
||||
}
|
||||
|
||||
FutureResult.prototype.set = (result) => {
|
||||
this.result = result;
|
||||
this.countDown.countDown();
|
||||
};
|
||||
|
||||
FutureResult.prototype.get = () => {
|
||||
this.countDown.await();
|
||||
return this.result;
|
||||
};
|
||||
|
||||
showWindow = (title, text, message, editable) => { // GLOBAL
|
||||
var result = new FutureResult();
|
||||
var f = new JFrame(title || "Hatter's Frame");
|
||||
f.addWindowListener(Proxy.newProxyInstance(
|
||||
Proxy.class.getClassLoader(),
|
||||
[WindowListener.class],
|
||||
(proxy, method, args) => {
|
||||
if (method && method.name == "windowClosing") {
|
||||
f.setVisible(false);
|
||||
f.dispose();
|
||||
result.set(null);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
var text = new JTextArea(text || "", 30, 80);
|
||||
text.setWrapStyleWord(true);
|
||||
text.setLineWrap(true);
|
||||
text.setEditable(!!editable);
|
||||
|
||||
var textScrollPane = new JScrollPane(text);
|
||||
|
||||
var label = new JLabel(message || "This is default message!");
|
||||
|
||||
var btnOK = null;
|
||||
if (editable) {
|
||||
btnOK = new JButton("OK!");
|
||||
btnOK.addActionListener(() => {
|
||||
var t = text.getText();
|
||||
f.setVisible(false);
|
||||
f.dispose();
|
||||
result.set(t);
|
||||
});
|
||||
}
|
||||
var btnCancel = new JButton("Cancel");
|
||||
btnCancel.addActionListener(() => {
|
||||
f.setVisible(false);
|
||||
f.dispose();
|
||||
result.set(null);
|
||||
});
|
||||
|
||||
var pane = new JPanel();
|
||||
if (btnOK != null) {
|
||||
pane.add(btnOK);
|
||||
}
|
||||
pane.add(btnCancel);
|
||||
|
||||
f.getContentPane().add(label, BorderLayout.NORTH);
|
||||
f.getContentPane().add(pane, BorderLayout.SOUTH);
|
||||
f.getContentPane().add(textScrollPane, BorderLayout.CENTER);
|
||||
|
||||
f.pack();
|
||||
|
||||
var dim = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
f.setLocation((dim.width / 2) - (f.getSize().width / 2), (dim.height / 2) - (f.getSize().height / 2));
|
||||
|
||||
f.setVisible(true);
|
||||
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
66
components/component-time.js
Normal file
66
components/component-time.js
Normal file
@@ -0,0 +1,66 @@
|
||||
var getMillis = (date) => {
|
||||
if (date == null) { return 0; }
|
||||
if (date instanceof java.util.Date) {
|
||||
return date.getTime();
|
||||
}
|
||||
return date;
|
||||
};
|
||||
|
||||
var formatDuration = (date) => {
|
||||
var millis = getMillis(date);
|
||||
var diffMillis = $$.date().millis() - millis;
|
||||
if (diffMillis < 3000) {
|
||||
return 'just now';
|
||||
}
|
||||
var secs = $$.num(diffMillis).divr(1000, 0, null).along();
|
||||
if (secs < 60) {
|
||||
return secs + 's';
|
||||
}
|
||||
var mins = $$.num(secs).divr(60, 0, null).along();
|
||||
if (mins < 60) {
|
||||
return mins + 'm';
|
||||
}
|
||||
var hours = $$.num(mins).divr(60, 0, null).along();
|
||||
if (hours < 24) {
|
||||
return hours + 'h';
|
||||
}
|
||||
var days = $$.num(hours).divr(24, 0, null).along();
|
||||
if (days < 31) {
|
||||
return days + 'd';
|
||||
}
|
||||
return $$.date().fmt('yyyy-MM-dd').format(new java.util.Date(millis));
|
||||
};
|
||||
|
||||
|
||||
var formatDueInDays = (date) => {
|
||||
var millis = getMillis(date);
|
||||
var diffMillis = millis - $$.date().millis();
|
||||
var isMinus = diffMillis < 0;
|
||||
if (isMinus) {
|
||||
diffMillis = -diffMillis;
|
||||
}
|
||||
var prefix = isMinus ? '-' : '';
|
||||
var secs = $$.num(diffMillis).divr(1000, 0, null).along();
|
||||
if (secs < 60) {
|
||||
return 'in ' + prefix + secs + 's';
|
||||
}
|
||||
var mins = $$.num(secs).divr(60, 0, null).along();
|
||||
if (mins < 60) {
|
||||
return 'in ' + prefix + secs + 'm';
|
||||
}
|
||||
var hours = $$.num(mins).divr(60, 0, null).along();
|
||||
if (hours < 24) {
|
||||
return 'in ' + prefix + hours + 'h';
|
||||
}
|
||||
var days = $$.num(hours).divr(24, 0, null).along();
|
||||
if (days < 31) {
|
||||
return 'in ' + prefix + days + 'd';
|
||||
}
|
||||
return $$.date().fmt('yyyy-MM-dd').format(new java.util.Date(millis));
|
||||
};
|
||||
|
||||
if (typeof exports == 'object') {
|
||||
exports.getMillis = getMillis;
|
||||
exports.formatDuration = formatDuration;
|
||||
exports.formatDueInDays = formatDueInDays;
|
||||
}
|
||||
Reference in New Issue
Block a user