Skip to content

Commit 2903d61

Browse files
committed
v0.4.0 update
created front-end page to view log messages created front-end page to edit database tables added button to test the SFTP connection added button to reset server ID and database connection added debug setting for more verbose log messages patched minor empty/null string bugs created PostgreSQL trigger to automatically hash raw passwords on row insert or update empty password are now ignored when connection settings are saved added documentation link at bottom of each front-end page minor refactoring
1 parent 00ab59d commit 2903d61

20 files changed

+1375
-64
lines changed

root/info.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<extension version="1">
22
<name>PostgreSQL_Connect</name>
33
<description>Periodically synchronizes data to an external PostgreSQL database.</description>
4-
<version>0.3.2</version>
4+
<version>0.4.0</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: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@
1919
<url-pattern>/index</url-pattern>
2020
</servlet-mapping>
2121

22+
<servlet>
23+
<servlet-name>TableEditorPage</servlet-name>
24+
<servlet-class>aces.webctrl.postgresql.web.TableEditorPage</servlet-class>
25+
</servlet>
26+
<servlet-mapping>
27+
<servlet-name>TableEditorPage</servlet-name>
28+
<url-pattern>/TableEditor</url-pattern>
29+
</servlet-mapping>
30+
2231
<servlet>
2332
<servlet-name>SaveOperator</servlet-name>
2433
<servlet-class>aces.webctrl.postgresql.web.SaveOperator</servlet-class>
@@ -28,6 +37,24 @@
2837
<url-pattern>/SaveOperator</url-pattern>
2938
</servlet-mapping>
3039

40+
<servlet>
41+
<servlet-name>LogViewerPage</servlet-name>
42+
<servlet-class>aces.webctrl.postgresql.web.LogViewerPage</servlet-class>
43+
</servlet>
44+
<servlet-mapping>
45+
<servlet-name>LogViewerPage</servlet-name>
46+
<url-pattern>/LogViewer</url-pattern>
47+
</servlet-mapping>
48+
49+
<servlet>
50+
<servlet-name>LocalOperatorsPage</servlet-name>
51+
<servlet-class>aces.webctrl.postgresql.web.LocalOperatorsPage</servlet-class>
52+
</servlet>
53+
<servlet-mapping>
54+
<servlet-name>LocalOperatorsPage</servlet-name>
55+
<url-pattern>/LocalOperators</url-pattern>
56+
</servlet-mapping>
57+
3158
<security-constraint>
3259
<web-resource-collection>
3360
<web-resource-name>WEB</web-resource-name>

root/webapp/main.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,13 @@ a {
7676
a:link,a:visited {
7777
color: lightgreen;
7878
}
79-
a:hover {
79+
a.nav:link,a.nav:visited {
80+
color: violet;
81+
}
82+
a:hover,a.nav:hover {
8083
color:darkgoldenrod;
8184
}
82-
a:active {
85+
a:active,a.nav:active {
8386
color:teal;
8487
}
8588
td, th {

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ private static void revertDefaults(){
1919
}
2020
private Config(){}
2121
/**
22-
* Invoke this whenever {@code connectionURL} is changed.
22+
* Resets the link ID for the database tables
2323
*/
2424
public static void reset(){
25-
ID = -1;
26-
Sync.versionCompatible = false;
27-
Sync.started = false;
25+
synchronized (Sync.class){
26+
new Sync(Event.SHUTDOWN);
27+
ID = -1;
28+
Sync.versionCompatible = false;
29+
Sync.started = false;
30+
}
2831
}
2932
public static boolean init(Path file){
3033
Config.file = file;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22
public enum Event {
33
GENERAL,
44
SHUTDOWN,
5-
SAVE_OPERATOR
5+
SAVE_OPERATOR,
6+
SELECT_TABLE,
7+
UPDATE_TABLE
68
}

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
package aces.webctrl.postgresql.core;
22
import java.time.*;
3-
import java.io.*;
43
public class LogMessage {
54
private volatile String message;
6-
private final OffsetDateTime stamp = OffsetDateTime.now();
5+
private volatile OffsetDateTime stamp;
76
private volatile boolean err;
87
public LogMessage(String message){
8+
stamp = OffsetDateTime.now();
99
this.message = message;
1010
err = false;
1111
}
1212
public LogMessage(Throwable t){
13-
StringWriter w = new StringWriter(64);
14-
t.printStackTrace(new PrintWriter(w));
15-
message = w.toString();
13+
stamp = OffsetDateTime.now();
14+
message = Utility.getStackTrace(t);
1615
err = true;
1716
}
17+
public LogMessage(OffsetDateTime stamp, boolean err, String message){
18+
this.stamp = stamp;
19+
this.err = err;
20+
this.message = message;
21+
}
1822
public String getMessage(){
1923
return message;
2024
}

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

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public Sync(Event event, String... args){
3030
synchronized (Sync.class){
3131
if (Initializer.stop && event!=Event.SHUTDOWN){ return; }
3232
try{
33+
final boolean debug = "true".equalsIgnoreCase(settings.get("debug"));
3334
final String url = "jdbc:postgresql://"+Config.connectionURL;
3435
final String username = Config.username;
3536
final String password = Config.password;
@@ -59,6 +60,49 @@ public Sync(Event event, String... args){
5960
}
6061
break;
6162
}
63+
case SELECT_TABLE:{
64+
if (ID==-1 || !started || args.length!=1){
65+
return;
66+
}
67+
args[0] = args[0].replace("$ID", String.valueOf(ID));
68+
try(
69+
Connection con = DriverManager.getConnection(url, connectionParams);
70+
){
71+
syncLog(con,ID);
72+
try(
73+
Statement s = con.createStatement();
74+
){
75+
fillCache(args[0],s);
76+
}
77+
}
78+
break;
79+
}
80+
case UPDATE_TABLE:{
81+
if (ID==-1 || !started || args.length<=1){
82+
return;
83+
}
84+
try(
85+
Connection con = DriverManager.getConnection(url, connectionParams);
86+
){
87+
con.setAutoCommit(false);
88+
syncLog(con,ID);
89+
try(
90+
Statement s = con.createStatement();
91+
){
92+
for (int i=1;i<args.length;++i){
93+
if (Initializer.stop){ return; }
94+
if (debug){
95+
Initializer.log(args[i]);
96+
}
97+
s.executeUpdate(args[i]);
98+
}
99+
con.commit();
100+
fillCache(args[0],s);
101+
}
102+
con.commit();
103+
}
104+
break;
105+
}
62106
case SAVE_OPERATOR:{
63107
if (ID==-1 || args.length!=2 || !versionCompatible){
64108
return;
@@ -160,7 +204,7 @@ public void execute(SystemAccess sys){
160204
while (r.next()){
161205
k = r.getString(1);
162206
v = r.getString(2);
163-
if (k!=null && v!=null){
207+
if (k!=null && v!=null && !k.isEmpty() && !v.isEmpty()){
164208
map.put(k,v);
165209
}
166210
}
@@ -226,7 +270,6 @@ public void execute(SystemAccess sys){
226270
}
227271
// Update webctrl.log
228272
syncLog(con,ID);
229-
con.commit();
230273
if (Initializer.stop){ return; }
231274
// Delete operators in webctrl.operator_blacklist
232275
// Create operators in webctrl.operator_whitelist
@@ -254,7 +297,7 @@ public void execute(SystemAccess sys){
254297
data.password = r.getString(3);
255298
data.lvl5_auto_logout = r.getInt(4);
256299
data.lvl5_auto_collapse = r.getBoolean(5);
257-
if (data.password.isEmpty()){
300+
if (data.password==null || data.password.isEmpty()){
258301
data.password = defaultPassword;
259302
}
260303
whitelist.put(data.username,data);
@@ -331,7 +374,7 @@ public void execute(SystemAccess sys){
331374
while (r.next()){
332375
min = r.getString(2);
333376
max = r.getString(3);
334-
if ((min==null || Utility.compareVersions(Initializer.simpleVersion,min)>=0) && (max==null || Utility.compareVersions(Initializer.simpleVersion,max)<=0)){
377+
if ((min==null || min.isEmpty() || Utility.compareVersions(Initializer.simpleVersion,min)>=0) && (max==null || max.isEmpty() || Utility.compareVersions(Initializer.simpleVersion,max)<=0)){
335378
addon = r.getString(1);
336379
if (addon!=null && !Initializer.getName().equalsIgnoreCase(addon)){
337380
blacklist.add(addon.toLowerCase());
@@ -356,7 +399,7 @@ public void execute(SystemAccess sys){
356399
while (r.next()){
357400
min = r.getString(5);
358401
max = r.getString(6);
359-
if ((min==null || Utility.compareVersions(Initializer.simpleVersion,min)>=0) && (max==null || Utility.compareVersions(Initializer.simpleVersion,max)<=0)){
402+
if ((min==null || min.isEmpty() || Utility.compareVersions(Initializer.simpleVersion,min)>=0) && (max==null || max.isEmpty() || Utility.compareVersions(Initializer.simpleVersion,max)<=0)){
360403
addon = r.getString(1);
361404
if (addon!=null && !Initializer.getName().equalsIgnoreCase(addon)){
362405
d = new AddonDownload();
@@ -418,7 +461,6 @@ public void execute(SystemAccess sys){
418461
s.executeUpdate("INSERT INTO webctrl.events VALUES("+ID+",'SYNCED',CURRENT_TIMESTAMP);");
419462
}
420463
syncLog(con,ID);
421-
con.commit();
422464
}finally{
423465
con.rollback();
424466
}
@@ -431,8 +473,9 @@ public void execute(SystemAccess sys){
431473
success = true;
432474
}catch(Throwable t){
433475
if (!(t instanceof InterruptedException)){
434-
Initializer.status = "Sync Error";
435-
Initializer.log("Sync error.");
476+
final String s = "Sync error during: "+event.name();
477+
Initializer.status = s;
478+
Initializer.log(s);
436479
Initializer.log(t);
437480
}
438481
}finally{
@@ -485,10 +528,47 @@ private void syncLog(Connection con, int ID) throws Throwable {
485528
s.addBatch();
486529
}
487530
s.executeBatch();
531+
if (!con.getAutoCommit()){
532+
con.commit();
533+
}
488534
}catch(Throwable t){
489535
Initializer.logCache.addAll(cache);
490536
throw t;
491537
}
492538
}
493539
}
540+
private void fillCache(String query, Statement s) throws Throwable {
541+
try(
542+
ResultSet r = s.executeQuery(query);
543+
){
544+
final TableCache cache = new TableCache();
545+
final ResultSetMetaData meta = r.getMetaData();
546+
cache.columns = meta.getColumnCount();
547+
final int[] types = new int[cache.columns];
548+
int i;
549+
for (i=0;i<types.length;++i){
550+
types[i] = meta.getColumnType(i+1);
551+
}
552+
cache.data = new ArrayList<String>(cache.columns<<6);
553+
cache.rows = 0;
554+
String ss;
555+
while (r.next()){
556+
if (Initializer.stop){ return; }
557+
for (i=0;i<types.length;++i){
558+
switch (types[i]){
559+
case java.sql.Types.BOOLEAN: case java.sql.Types.BIT: {
560+
ss = String.valueOf(r.getBoolean(i+1));
561+
break;
562+
}
563+
default:{
564+
ss = r.getString(i+1);
565+
}
566+
}
567+
cache.data.add(ss);
568+
}
569+
++cache.rows;
570+
}
571+
TableCache.instance = cache;
572+
}
573+
}
494574
}

0 commit comments

Comments
 (0)