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