Skip to content

Commit 352f811

Browse files
committed
initial commit
0 parents  commit 352f811

File tree

10 files changed

+358
-0
lines changed

10 files changed

+358
-0
lines changed

LICENSE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
BSD 3-Clause License
2+
3+
Copyright (c) 2022, Automatic Controls Equipment Systems, Inc.
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
1. Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
3. Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# AddonDevRefresher

config/BUILD_DETAILS

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
JDK Version:
2+
openjdk 18.0.2.1 2022-08-18
3+
OpenJDK Runtime Environment (build 18.0.2.1+1-1)
4+
OpenJDK 64-Bit Server VM (build 18.0.2.1+1-1, mixed mode, sharing)
5+
6+
Compilation Flags:
7+
--release 8
8+
9+
Runtime Dependencies:
10+
addonsupport-api-addon-1.7.0
11+
alarmmanager-api-addon-1.7.0
12+
bacnet-api-addon-1.8.007-20220318.0837r
13+
directaccess-api-addon-1.7.0
14+
tomcat-embed-core-9.0.37
15+
webaccess-api-addon-1.7.0
16+
xdatabase-api-addon-1.7.0
17+
extensionsupport-api-8.0.002
18+
webaccess-api-8.0.002
19+
webserver-api-8.0.002
20+
21+
Packaged Dependencies:

config/COMPILE_FLAGS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--release 8

config/RUNTIME_DEPS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
file:extensionsupport-api:modules\extensionsupport
2+
file:webaccess-api:modules\webaccess
3+
file:webserver-api:modules\webserver

deploy.bat

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
@echo off
2+
if "%WebCTRL%" EQU "" goto :bad
3+
if "%addonFile%" EQU "" goto :bad
4+
if "%certFile%" EQU "" goto :bad
5+
if /i "%*" EQU "--help" (
6+
echo DEPLOY Copies the .addon archive and certificate file to the bound WebCTRL installation.
7+
exit /b 0
8+
)
9+
if "%*" NEQ "" (
10+
echo Unexpected parameter.
11+
exit /b 1
12+
)
13+
if not exist "%addonFile%" (
14+
echo Cannot deploy because !name!.addon does not exist.
15+
exit /b 1
16+
)
17+
echo Deploying...
18+
if "!name!" EQU "AddonDevRefresher" (
19+
echo Cannot be used to self-deploy.
20+
echo Deployment unsuccessful.
21+
exit /b 1
22+
)
23+
if not exist "%WebCTRL%\addons" mkdir "%WebCTRL%\addons" >nul 2>nul
24+
copy /y "%certFile%" "%WebCTRL%\addons\%certFileName%" >nul
25+
copy /y "%addonFile%" "%WebCTRL%\addons\!name!.update" >nul
26+
if %ErrorLevel% NEQ 0 (
27+
echo Deployment unsuccessful.
28+
exit /b 1
29+
)
30+
set /a count=0
31+
:waitUpdate
32+
timeout 1 /nobreak >nul
33+
set /a count+=1
34+
if exist "%WebCTRL%\addons\!name!.update" (
35+
if "%count%" EQU "60" (
36+
echo Timeout occurred.
37+
echo Deployment unsuccessful.
38+
exit /b 1
39+
) else (
40+
goto :waitUpdate
41+
)
42+
)
43+
if exist "%WebCTRL%\addons\!name!.addon" (
44+
echo Deployment successful.
45+
exit /b 0
46+
) else (
47+
echo Deployment unsuccessful.
48+
exit /b 1
49+
)
50+
51+
:bad
52+
echo This script should not be invoked as a stand-alone application.
53+
echo You must use this file as an extension to addon-dev-script.
54+
echo https://github.com/automatic-controls/addon-dev-script
55+
echo Press any key to exit.
56+
pause >nul
57+
exit /b 1

root/info.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<extension version="1">
2+
<name>AddonDevRefresher</name>
3+
<description>Streamlines add-on development by automatically removing and adding add-ons from a local WebCTRL server as they are developed.</description>
4+
<version>1.0.0</version>
5+
<vendor>Automatic Controls Equipment Systems, Inc.</vendor>
6+
</extension>

root/webapp/WEB-INF/web.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<web-app>
4+
5+
<listener>
6+
<listener-class>aces.webctrl.dev.Initializer</listener-class>
7+
</listener>
8+
9+
<security-constraint>
10+
<web-resource-collection>
11+
<web-resource-name>WEB</web-resource-name>
12+
<url-pattern>/*</url-pattern>
13+
</web-resource-collection>
14+
</security-constraint>
15+
16+
<filter>
17+
<filter-name>RoleFilterAJAX</filter-name>
18+
<filter-class>com.controlj.green.addonsupport.web.RoleFilter</filter-class>
19+
<init-param>
20+
<param-name>roles</param-name>
21+
<param-value>view_administrator_only</param-value>
22+
</init-param>
23+
</filter>
24+
<filter-mapping>
25+
<filter-name>RoleFilterAJAX</filter-name>
26+
<url-pattern>/*</url-pattern>
27+
</filter-mapping>
28+
29+
</web-app>

src/aces/webctrl/dev/HelperAPI.java

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
BSD 3-Clause License
3+
Copyright (c) 2022, Automatic Controls Equipment Systems, Inc.
4+
Contributors: Cameron Vogt (@cvogt729)
5+
*/
6+
package aces.webctrl.dev;
7+
import java.nio.file.*;
8+
import com.controlj.green.addonsupport.web.auth.AuthenticationManager;
9+
import com.controlj.green.extensionsupport.Extension;
10+
import com.controlj.green.webserver.*;
11+
/**
12+
* Namespace which contains methods to access small sections of a few internal WebCTRL APIs.
13+
*/
14+
public class HelperAPI {
15+
/**
16+
* Specifies whether methods of this API should log stack traces generated from errors.
17+
*/
18+
public static volatile boolean logErrors = true;
19+
/**
20+
* Disables an add-on with the given name.
21+
* @param name is used to identify the add-on.
22+
* @return {@code true} on success; {@code false} on failure.
23+
*/
24+
public static boolean disableAddon(String name){
25+
try{
26+
TomcatServer server = TomcatServerSingleton.get();
27+
if (server==null){
28+
return false;
29+
}
30+
AddOn addon = null;
31+
for (AddOn x:server.scanForAddOns()){
32+
if (x.getName().equals(name)){
33+
addon = x;
34+
break;
35+
}
36+
}
37+
if (addon==null){
38+
return true;
39+
}
40+
server.disableAddOn(addon);
41+
return true;
42+
}catch(Throwable t){
43+
if (logErrors){ t.printStackTrace(); }
44+
return false;
45+
}
46+
}
47+
/**
48+
* Enables an add-on with the given name.
49+
* @param name is used to identify the add-on.
50+
* @return {@code true} on success; {@code false} on failure.
51+
*/
52+
public static boolean enableAddon(String name){
53+
try{
54+
TomcatServer server = TomcatServerSingleton.get();
55+
if (server==null){
56+
return false;
57+
}
58+
AddOn addon = null;
59+
for (AddOn x:server.scanForAddOns()){
60+
if (x.getName().equals(name)){
61+
addon = x;
62+
break;
63+
}
64+
}
65+
if (addon==null){
66+
return false;
67+
}
68+
server.enableAddOn(addon);
69+
return true;
70+
}catch(Throwable t){
71+
if (logErrors){ t.printStackTrace(); }
72+
return false;
73+
}
74+
}
75+
/**
76+
* Removes an add-on with the given name.
77+
* @param name is used to identify the add-on.
78+
* @param removeData specifies whether to remove data associated to the add-on.
79+
* @return {@code true} on success; {@code false} on failure.
80+
*/
81+
public static boolean removeAddon(String name, boolean removeData){
82+
try{
83+
TomcatServer server = TomcatServerSingleton.get();
84+
if (server==null){
85+
return false;
86+
}
87+
AddOn addon = null;
88+
for (AddOn x:server.scanForAddOns()){
89+
if (x.getName().equals(name)){
90+
addon = x;
91+
break;
92+
}
93+
}
94+
if (addon==null){
95+
return false;
96+
}
97+
server.removeAddOn(addon, removeData);
98+
return true;
99+
}catch(Throwable t){
100+
if (logErrors){ t.printStackTrace(); }
101+
return false;
102+
}
103+
}
104+
/**
105+
* Activates the specified {@code WebOperatorProvider}.
106+
* @param addonFile specifies the location of the .addon file to activate.
107+
* @return an {@code Extension} object matching the given {@code addonFile}, or {@code null} if the addon cannot be found or if any error occurs.
108+
*/
109+
public static Extension activateWebOperatorProvider(Path addonFile){
110+
try{
111+
AuthenticationManager auth = new AuthenticationManager();
112+
for (Extension e:auth.findWebOperatorProviders()){
113+
if (Files.isSameFile(e.getSourceFile().toPath(), addonFile)){
114+
auth.activateProvider(e);
115+
return e;
116+
}
117+
}
118+
}catch(Throwable t){
119+
if (logErrors){ t.printStackTrace(); }
120+
}
121+
return null;
122+
}
123+
/**
124+
* Activates the default {@code WebOperatorProvider}.
125+
* @return whether this method executed successfully.
126+
*/
127+
public static boolean activateDefaultWebOperatorProvider(){
128+
try{
129+
new AuthenticationManager().activateProvider(null);
130+
return true;
131+
}catch(Throwable t){
132+
if (logErrors){ t.printStackTrace(); }
133+
return false;
134+
}
135+
}
136+
}

src/aces/webctrl/dev/Initializer.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package aces.webctrl.dev;
2+
import com.controlj.green.addonsupport.*;
3+
import javax.servlet.*;
4+
import java.nio.file.*;
5+
public class Initializer implements ServletContextListener {
6+
public volatile AddOnInfo info;
7+
private volatile String name;
8+
private volatile Path addons;
9+
private volatile Thread thread;
10+
private volatile boolean go = true;
11+
@Override public void contextInitialized(ServletContextEvent sce){
12+
try{
13+
info = AddOnInfo.getAddOnInfo();
14+
name = info.getName();
15+
addons = info.getPrivateDir().toPath().getParent().getParent().getParent().getParent().getParent().resolve("addons").normalize();
16+
thread = new Thread(){
17+
@Override public void run(){
18+
try{
19+
String addonName;
20+
Path addon;
21+
while (go){
22+
try{
23+
try(
24+
DirectoryStream<Path> stream = Files.newDirectoryStream(addons);
25+
){
26+
for (Path p:stream){
27+
try{
28+
addonName = p.getFileName().toString();
29+
if (addonName.endsWith(".update")){
30+
addonName = addonName.substring(0,addonName.length()-7);
31+
if (!addonName.equals(name)){
32+
addon = addons.resolve(addonName+".addon");
33+
if (!Files.exists(addon) || HelperAPI.disableAddon(addonName)){
34+
try{
35+
Files.move(p,addon,StandardCopyOption.REPLACE_EXISTING);
36+
}catch(Throwable t){
37+
continue;
38+
}
39+
if (Files.exists(addon)){
40+
HelperAPI.enableAddon(addonName);
41+
HelperAPI.activateWebOperatorProvider(addon);
42+
}
43+
}
44+
}
45+
}
46+
}catch(Throwable t){
47+
t.printStackTrace();
48+
}
49+
}
50+
}
51+
}catch(Throwable t){
52+
t.printStackTrace();
53+
}
54+
Thread.sleep(3000);
55+
}
56+
}catch(InterruptedException e){}catch(Throwable t){
57+
t.printStackTrace();
58+
}
59+
}
60+
};
61+
thread.start();
62+
}catch(Throwable t){
63+
t.printStackTrace();
64+
}
65+
}
66+
@Override public void contextDestroyed(ServletContextEvent sce){
67+
try{
68+
go = false;
69+
thread.interrupt();
70+
thread.join();
71+
}catch(Throwable t){
72+
t.printStackTrace();
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)