Skip to content

Commit e0e4fe4

Browse files
committed
v0.5.4 update
various bug fixes updated PostgreSQL dependency to 42.7.3 updated JSch dependency to 0.2.17 added random offset to stagger database queries improved PostgreSQL authentication scheme - client certificates improved SFTP authentication scheme - private keys added partial two-way operator syncing from server to database added descriptive hovertext to tables in the UI added WebCTRL servers page to the UI added function to save and retrieve license files from any server added function to see all applied cumulative updates on any server added notes column to add extra information to each WebCTRL server added operator blacklist exceptions table to the UI added optional add-on feature add log expiration feature
1 parent 9e21c24 commit e0e4fe4

30 files changed

+982
-234
lines changed

config/BUILD_DETAILS

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,34 @@
11
JDK Version:
2-
openjdk 19.0.1 2022-10-18
3-
OpenJDK Runtime Environment (build 19.0.1+10-21)
4-
OpenJDK 64-Bit Server VM (build 19.0.1+10-21, mixed mode, sharing)
2+
openjdk 21.0.2 2024-01-16
3+
OpenJDK Runtime Environment (build 21.0.2+13-58)
4+
OpenJDK 64-Bit Server VM (build 21.0.2+13-58, mixed mode, sharing)
55

66
Compilation Flags:
7-
--release 8
7+
--release 11
88

99
Runtime Dependencies:
10-
addonsupport-api-addon-1.9.0
11-
alarmmanager-api-addon-1.9.0
12-
bacnet-api-core-1.10.002-20230209.1438r
13-
directaccess-api-addon-1.9.0
14-
tomcat-embed-core-9.0.68
15-
webaccess-api-addon-1.9.0
16-
xdatabase-api-addon-1.9.0
17-
common-8.5.002
18-
commonbaseutils-2.0.3
19-
commonexceptions-8.5.002
20-
core-8.5.002
21-
datatable-8.5.002
22-
directaccess-8.5.002
23-
directaccess-api-8.5.002
24-
extensionsupport-api-8.5.002
25-
jsch-0.2.11-sources
26-
postgresql-42.6.0-sources
27-
spring-context-5.2.22.RELEASE
28-
webserver-api-8.5.002
10+
addonsupport-api-addon-1.10.0
11+
alarmmanager-api-addon-1.10.0
12+
bacnet-api-core-1.10.007-20240227.1003r
13+
directaccess-api-addon-1.10.0
14+
tomcat-embed-core-9.0.87
15+
webaccess-api-addon-1.10.0
16+
xdatabase-api-addon-1.10.0
17+
cjupdate-1.2.4
18+
common-9.0.002
19+
commonbaseutils-2.0.5
20+
commonexceptions-9.0.002
21+
core-9.0.002
22+
datatable-9.0.002
23+
directaccess-9.0.002
24+
directaccess-api-9.0.002
25+
extensionsupport-api-9.0.002
26+
jsch-0.2.17-sources
27+
postgresql-42.7.3-sources
28+
spring-context-5.3.33
29+
update-api-9.0.002
30+
webserver-api-9.0.002
2931

3032
Packaged Dependencies:
31-
jsch-0.2.11
32-
postgresql-42.6.0
33+
jsch-0.2.17
34+
postgresql-42.7.3

config/COMPILE_FLAGS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
--release 8
1+
--release 11

config/EXTERNAL_DEPS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
url:postgresql:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.6.0/postgresql-42.6.0.jar
2-
url:jsch:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.11/jsch-0.2.11.jar
1+
url:postgresql:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.3/postgresql-42.7.3.jar
2+
url:jsch:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.17/jsch-0.2.17.jar

config/RUNTIME_DEPS

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@ file:commonexceptions:modules\commonexceptions
88
file:commonbaseutils:bin\lib
99
file:directaccess:modules\directaccess
1010
file:directaccess-api:modules\directaccess
11-
url:postgresql:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.6.0/postgresql-42.6.0-sources.jar
12-
url:jsch:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.11/jsch-0.2.11-sources.jar
11+
file:cjupdate:bin\lib
12+
file:update-api:modules\update
13+
url:postgresql:https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.3/postgresql-42.7.3-sources.jar
14+
url:jsch:https://repo1.maven.org/maven2/com/github/mwiede/jsch/0.2.17/jsch-0.2.17-sources.jar

root/info.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<extension version="1">
22
<name>PostgreSQL_Connect</name>
3-
<description>Periodically synchronizes data to an external PostgreSQL database.</description>
4-
<version>0.4.5</version>
3+
<description>Periodically synchronizes operators, add-ons, and specified trends with an external PostgreSQL database.</description>
4+
<version>0.5.4</version>
55
<vendor>Automatic Controls Equipment Systems, Inc.</vendor>
66
<system-menu-provider>aces.webctrl.postgresql.web.SystemMenuEditor</system-menu-provider>
77
</extension>

root/webapp/WEB-INF/web.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@
2828
<url-pattern>/TableEditor</url-pattern>
2929
</servlet-mapping>
3030

31+
<servlet>
32+
<servlet-name>InstallAddonPage</servlet-name>
33+
<servlet-class>aces.webctrl.postgresql.web.InstallAddonPage</servlet-class>
34+
</servlet>
35+
<servlet-mapping>
36+
<servlet-name>InstallAddonPage</servlet-name>
37+
<url-pattern>/InstallAddon</url-pattern>
38+
</servlet-mapping>
39+
40+
<servlet>
41+
<servlet-name>DownloadLicensePage</servlet-name>
42+
<servlet-class>aces.webctrl.postgresql.web.DownloadLicensePage</servlet-class>
43+
</servlet>
44+
<servlet-mapping>
45+
<servlet-name>DownloadLicensePage</servlet-name>
46+
<url-pattern>/DownloadLicense</url-pattern>
47+
</servlet-mapping>
48+
3149
<servlet>
3250
<servlet-name>SaveOperator</servlet-name>
3351
<servlet-class>aces.webctrl.postgresql.web.SaveOperator</servlet-class>
Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
package aces.webctrl.postgresql.core;
22
import java.nio.file.*;
33
import com.controlj.green.webserver.AddOn;
4+
import java.util.regex.*;
45
public class AddonDownload {
5-
public String name;
6+
public String displayName;
67
public String version;
78
public String path;
89
public boolean removeData;
910
public boolean keepNewer;
11+
public boolean optional;
1012
public Path file = null;
1113
public AddOn addon = null;
14+
private String refname = null;
15+
private final static Pattern filenameParser = Pattern.compile("[/\\\\]([^/\\\\]+)\\.addon$");
16+
public String getReferenceName(){
17+
if (refname!=null){
18+
return refname;
19+
}
20+
final Matcher m = filenameParser.matcher(path);
21+
if (m.find()){
22+
refname = m.group(1);
23+
}
24+
if (refname==null){
25+
if (displayName==null){
26+
refname = "addon";
27+
}else{
28+
refname = displayName;
29+
}
30+
}
31+
return refname;
32+
}
1233
}

src/aces/webctrl/postgresql/core/Config.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@
33
import java.nio.file.*;
44
import java.nio.channels.*;
55
public class Config {
6-
private volatile static Path file = null;
6+
public volatile static Path file = null;
77
public volatile static String connectionURL = null;
88
public volatile static String username = null;
99
public volatile static String password = null;
10+
public volatile static String keystorePassword = null;
1011
public volatile static int ID;
1112
public final static CronExpression cron = new CronExpression();
13+
public volatile static long maxRandomOffset;
1214
static { revertDefaults(); }
1315
private static void revertDefaults(){
1416
ID = -1;
1517
connectionURL = "";
1618
username = "";
1719
password = "";
20+
keystorePassword = "";
21+
maxRandomOffset = 0L;
1822
cron.set("0 0 * * * *");
1923
}
2024
private Config(){}
@@ -29,9 +33,8 @@ public static void reset(){
2933
Sync.started = false;
3034
}
3135
}
32-
public static boolean init(Path file){
36+
public static void init(Path file){
3337
Config.file = file;
34-
return load();
3538
}
3639
public static boolean load(){
3740
if (file==null){
@@ -46,11 +49,14 @@ public static boolean load(){
4649
try{
4750
final SerializationStream s = new SerializationStream(arr);
4851
ID = s.readInt();
49-
/*final String version =*/ s.readString();
52+
//final String version =
53+
s.readString();
5054
connectionURL = s.readString();
5155
username = s.readString();
5256
password = s.readString();
57+
maxRandomOffset = s.readLong();
5358
cron.set(s.readString());
59+
keystorePassword = s.readString();
5460
if (!s.end()){
5561
Initializer.log("Configuration file corrupted. Parameters reverted to defaults.",true);
5662
revertDefaults();
@@ -80,6 +86,7 @@ public static boolean save(){
8086
l+=username.length();
8187
l+=password.length();
8288
l+=cronExpr.length();
89+
l+=keystorePassword.length();
8390
l<<=1;
8491
l+=4;
8592
final SerializationStream s = new SerializationStream(l, true);
@@ -88,7 +95,9 @@ public static boolean save(){
8895
s.write(connectionURL);
8996
s.write(username);
9097
s.write(password);
98+
s.write(maxRandomOffset);
9199
s.write(cronExpr);
100+
s.write(keystorePassword);
92101
final ByteBuffer buf = s.getBuffer();
93102
synchronized(Config.class){
94103
try(

src/aces/webctrl/postgresql/core/ConnectSFTP.java

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package aces.webctrl.postgresql.core;
22
import java.io.*;
3+
import java.nio.*;
4+
import java.nio.channels.*;
35
import java.nio.file.*;
46
import com.jcraft.jsch.*;
57
public class ConnectSFTP implements AutoCloseable {
@@ -9,33 +11,44 @@ public ConnectSFTP(){
911
final String host = Sync.settings.get("ftp_host");
1012
final String port = Sync.settings.get("ftp_port");
1113
final String username = Sync.settings.get("ftp_username");
12-
final String password = Sync.settings.get("ftp_password");
13-
if (host==null || port==null || username==null || password==null){
14+
final String key = Sync.settings.get("ftp_key");
15+
if (host==null || port==null || username==null || key==null){
1416
Initializer.log("Failed to connect to SFTP server because connection settings were not provided.",true);
1517
return;
1618
}
1719
try{
18-
connect(host, Integer.parseInt(port), username, password);
19-
}catch(NumberFormatException e){
20+
final ByteBuffer buf = ByteBuffer.wrap(key.getBytes(java.nio.charset.StandardCharsets.UTF_8));
21+
synchronized(ConnectSFTP.class){
22+
try(
23+
FileChannel out = FileChannel.open(Initializer.sftpkey, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
24+
){
25+
while (buf.hasRemaining()){
26+
out.write(buf);
27+
}
28+
}
29+
}
30+
connect(host, Integer.parseInt(port), username);
31+
}catch(Throwable e){
2032
Initializer.log(e);
2133
return;
2234
}
2335
}
24-
public ConnectSFTP(String host, int port, String username, String password){
25-
connect(host, port, username, password);
36+
public ConnectSFTP(String host, int port, String username){
37+
connect(host, port, username);
2638
}
27-
private void connect(String host, int port, String username, String password){
39+
private void connect(String host, int port, String username){
2840
try{
2941
final JSch jsch = new JSch();
3042
{
3143
final String knownHosts = Sync.settings.get("ftp_known_hosts");
3244
if (knownHosts==null){
45+
Initializer.log("Failed to connect to SFTP server because ftp_known_hosts is undefined.",true);
3346
return;
3447
}
3548
jsch.setKnownHosts(new ByteArrayInputStream(knownHosts.getBytes(java.nio.charset.StandardCharsets.UTF_8)));
3649
}
50+
jsch.addIdentity(Initializer.sftpkey.toString());
3751
jschSession = jsch.getSession(username, host, port);
38-
jschSession.setPassword(password);
3952
jschSession.setTimeout(10000);
4053
jschSession.setConfig("StrictHostKeyChecking", "yes");
4154
jschSession.connect(10000);
@@ -47,6 +60,42 @@ private void connect(String host, int port, String username, String password){
4760
return;
4861
}
4962
}
63+
public boolean overwriteFile(InputStream src, String dst){
64+
if (jschChannel==null){
65+
return false;
66+
}
67+
try{
68+
jschChannel.put(src, dst, new SftpProgressMonitor(){
69+
@Override public void init(int op, String src, String dest, long max){}
70+
@Override public boolean count(long count){
71+
return !Initializer.stop;
72+
}
73+
@Override public void end(){}
74+
}, ChannelSftp.OVERWRITE);
75+
return !Initializer.stop;
76+
}catch(Throwable t){
77+
Initializer.log(t);
78+
return false;
79+
}
80+
}
81+
public boolean uploadFile(Path src, String dst){
82+
if (jschChannel==null){
83+
return false;
84+
}
85+
try{
86+
try(
87+
BufferedInputStream s = new BufferedInputStream(Files.newInputStream(src));
88+
){
89+
if (overwriteFile(s, dst)){
90+
return true;
91+
}
92+
}
93+
return false;
94+
}catch(Throwable t){
95+
Initializer.log(t);
96+
return false;
97+
}
98+
}
5099
public boolean retrieveFile(String path, OutputStream out){
51100
if (jschChannel==null){
52101
return false;
@@ -76,7 +125,6 @@ public boolean downloadFile(String path, Path out){
76125
if (retrieveFile(path,s)){
77126
return true;
78127
}
79-
s.close();
80128
}
81129
Files.deleteIfExists(out);
82130
return false;

src/aces/webctrl/postgresql/core/CronExpression.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public boolean set(String expr){
3030
}
3131
}
3232
}
33+
/**
34+
* Explicity sets the next scheduled instant.
35+
*/
36+
public void setNext(long next){
37+
this.next = next;
38+
}
3339
/**
3440
* Recomputes the next scheduled instant for this Cron expression.
3541
*/
@@ -39,7 +45,12 @@ public void reset(){
3945
next = -1;
4046
}else{
4147
try{
42-
next = gen.next(new Date()).getTime();
48+
final long offset = Config.maxRandomOffset;
49+
if (offset>0){
50+
next = gen.next(new Date()).getTime()+(long)(offset*Math.random());
51+
}else{
52+
next = gen.next(new Date()).getTime();
53+
}
4354
}catch(Throwable t){
4455
next = -1;
4556
}

0 commit comments

Comments
 (0)