From d7edf3db4a421db9fa7427fc65a3306cecb22e91 Mon Sep 17 00:00:00 2001 From: Mark Milligan Date: Mon, 2 May 2022 18:20:03 -0500 Subject: [PATCH] Turns out we don't actually need 30MB of bloated jars to make a single HTTP post to get a Google SSO auth token. Don't need them for Firebase either. And not for Apple SSO. Shoot while we're at it, might as well get rid of pi4j too since making a JNI wrapper for PiGPio is easy enough. --- .../lantern-config-currentmonitor/pom.xml | 4 +- currentmonitor/lantern-currentmonitor/pom.xml | 15 +- .../currentmonitor/CurrentMonitor.java | 20 +- .../currentmonitor/MonitorApp.java | 1 - .../currentmonitor/adc/MCP3008.java | 13 +- .../src/main/resources/logback.xml | 6 - .../lantern-dataaccess-currentmonitor/pom.xml | 14 +- .../lantern-datamodel-currentmonitor/pom.xml | 14 +- .../lantern-service-currentmonitor/pom.xml | 33 +- .../currentmonitor/context/Globals.java | 4 +- .../currentmonitor/servlet/AuthServlet.java | 27 +- .../servlet/console/GsoServlet.java | 24 +- .../currentmonitor/util/GoogleAuthHelper.java | 42 - pigpio/lantern-pigpio/pom.xml | 68 ++ .../com/lanternsoftware/pigpio/PIGPIO.java | 54 ++ .../lanternsoftware/pigpio/PiGpioFactory.java | 51 ++ .../java/com/lanternsoftware/pigpio/Spi.java | 37 + .../lantern-pigpio/src/main/native/Makefile | 54 ++ .../com_lanternsoftware_pigpio_PIGPIO.c | 117 +++ .../com_lanternsoftware_pigpio_PIGPIO.h | 109 +++ .../resources/lib/aarch64/lantern-pigpio.so | Bin 0 -> 13520 bytes pigpio/pom.xml | 18 + pom.xml | 4 +- rules/lantern-dataaccess-rules/pom.xml | 14 +- rules/lantern-datamodel-rules/pom.xml | 14 +- rules/lantern-service-rules/pom.xml | 34 +- .../rules/actions/AbstractAlertAction.java | 37 +- .../com/lanternsoftware/TestSendAlert.java | 22 +- .../src/test/resources/logback.xml | 16 + util/lantern-util-cloudservices/pom.xml | 74 ++ .../util/cloudservices/apple/AppleSSO.java | 70 ++ .../google/FirebaseCredentials.java | 97 +++ .../cloudservices/google/FirebaseHelper.java | 109 +++ .../util/cloudservices/google/GoogleSSO.java | 57 ++ .../dao/FirebaseCredentialsSerializer.java | 58 ++ ...om.lanternsoftware.util.dao.IDaoSerializer | 1 + util/lantern-util-common/pom.xml | 2 +- .../com/lanternsoftware/util/NullUtils.java | 763 +++++++++--------- util/lantern-util-dao-ephemeral/pom.xml | 2 +- util/lantern-util-dao-mongo/pom.xml | 2 +- util/lantern-util-dao/pom.xml | 2 +- util/lantern-util-excel/pom.xml | 2 +- util/lantern-util-http/pom.xml | 2 +- .../util/http/HttpFactory.java | 18 + util/lantern-util-servlet/pom.xml | 2 +- util/pom.xml | 1 + zwave/lantern-datamodel-zwave/pom.xml | 14 +- zwave/lantern-service-thermometer/pom.xml | 4 +- zwave/lantern-service-zwave/pom.xml | 4 +- zwave/lantern-uirt/pom.xml | 14 +- zwave/lantern-zwave/pom.xml | 4 +- 51 files changed, 1495 insertions(+), 673 deletions(-) delete mode 100644 currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/util/GoogleAuthHelper.java create mode 100644 pigpio/lantern-pigpio/pom.xml create mode 100644 pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PIGPIO.java create mode 100644 pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PiGpioFactory.java create mode 100644 pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/Spi.java create mode 100644 pigpio/lantern-pigpio/src/main/native/Makefile create mode 100644 pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.c create mode 100644 pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.h create mode 100644 pigpio/lantern-pigpio/src/main/resources/lib/aarch64/lantern-pigpio.so create mode 100644 pigpio/pom.xml create mode 100644 rules/lantern-service-rules/src/test/resources/logback.xml create mode 100644 util/lantern-util-cloudservices/pom.xml create mode 100644 util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/apple/AppleSSO.java create mode 100644 util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseCredentials.java create mode 100644 util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseHelper.java create mode 100644 util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/GoogleSSO.java create mode 100644 util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/dao/FirebaseCredentialsSerializer.java create mode 100644 util/lantern-util-cloudservices/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer create mode 100644 util/lantern-util-http/src/main/java/com/lanternsoftware/util/http/HttpFactory.java diff --git a/currentmonitor/lantern-config-currentmonitor/pom.xml b/currentmonitor/lantern-config-currentmonitor/pom.xml index 81bd20f..d73f0d0 100644 --- a/currentmonitor/lantern-config-currentmonitor/pom.xml +++ b/currentmonitor/lantern-config-currentmonitor/pom.xml @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.3.0 false diff --git a/currentmonitor/lantern-currentmonitor/pom.xml b/currentmonitor/lantern-currentmonitor/pom.xml index 165c501..6e9c4a1 100644 --- a/currentmonitor/lantern-currentmonitor/pom.xml +++ b/currentmonitor/lantern-currentmonitor/pom.xml @@ -23,14 +23,9 @@ 1.2.3 - com.pi4j - pi4j-core - 2.2.0-SNAPSHOT - - - com.pi4j - pi4j-plugin-pigpio - 2.2.0-SNAPSHOT + com.lanternsoftware.pigpio + lantern-pigpio + ${pigpio.version} com.github.hypfvieh @@ -63,7 +58,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -83,7 +78,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.3.0 false diff --git a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java index 07c0c76..e6915c4 100644 --- a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java +++ b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/CurrentMonitor.java @@ -6,12 +6,9 @@ import com.lanternsoftware.datamodel.currentmonitor.Breaker; import com.lanternsoftware.datamodel.currentmonitor.BreakerHub; import com.lanternsoftware.datamodel.currentmonitor.BreakerPolarity; import com.lanternsoftware.datamodel.currentmonitor.BreakerPower; +import com.lanternsoftware.pigpio.PiGpioFactory; import com.lanternsoftware.util.CollectionUtils; import com.lanternsoftware.util.concurrency.ConcurrencyUtils; -import com.pi4j.Pi4J; -import com.pi4j.context.Context; -import com.pi4j.io.spi.Spi; -import com.pi4j.io.spi.SpiMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,26 +25,17 @@ public class CurrentMonitor { private static final Logger LOG = LoggerFactory.getLogger(CurrentMonitor.class); private static final int BATCH_CNT = 4; private final ExecutorService executor = Executors.newCachedThreadPool(); - private Context pi4j; private final Map chips = new HashMap<>(); private Sampler sampler; private PowerListener listener; private boolean debug = false; - public void start() { - pi4j = Pi4J.newAutoContext(); - } - public void stop() { stopMonitoring(); ConcurrencyUtils.sleep(1000); executor.shutdown(); ConcurrencyUtils.sleep(1000); - for (MCP3008 mcp : chips.values()) { - mcp.shutdown(pi4j); - } - ConcurrencyUtils.sleep(1000); - pi4j.shutdown(); + PiGpioFactory.shutdown(); chips.clear(); LOG.info("Power Monitor Service Stopped"); } @@ -139,9 +127,7 @@ public class CurrentMonitor { if (chip == null) { String id = "SPI" + _chip; LOG.info("Creating chip {}", id); - Spi spi = pi4j.create(Spi.newConfigBuilder(pi4j).mode(SpiMode.MODE_0).id(id).name("MCP3008_" + _chip).address(_chip).baud(810000).build()); - LOG.info("is open {}", spi.isOpen()); - chip = new MCP3008(spi); + chip = new MCP3008(PiGpioFactory.getSpiChannel(_chip, 810000, false)); chips.put(_chip, chip); } return chip; diff --git a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java index caa717e..da609ec 100644 --- a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java +++ b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/MonitorApp.java @@ -214,7 +214,6 @@ public class MonitorApp { if (NullUtils.isNotEmpty(config.getHost())) host = NullUtils.terminateWith(config.getHost(), "/"); monitor.setDebug(config.isDebug()); - monitor.start(); LEDFlasher.setLEDOn(false); if (NullUtils.isNotEmpty(config.getAuthCode())) authCode = config.getAuthCode(); diff --git a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/adc/MCP3008.java b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/adc/MCP3008.java index f42e33f..5e70dcd 100644 --- a/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/adc/MCP3008.java +++ b/currentmonitor/lantern-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/adc/MCP3008.java @@ -1,12 +1,11 @@ package com.lanternsoftware.currentmonitor.adc; -import com.pi4j.context.Context; -import com.pi4j.io.spi.Spi; +import com.lanternsoftware.pigpio.Spi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MCP3008 { - private static final Logger LOG = LoggerFactory.getLogger(MCP3008.class); + protected static final Logger LOG = LoggerFactory.getLogger(MCP3008.class); private static final byte[][] pins = new byte[8][]; private final Spi spi; @@ -22,15 +21,9 @@ public class MCP3008 { spi = _spi; } - public void shutdown(Context _pi4j) { - spi.close(); - spi.shutdown(_pi4j); - } - public int readPin(int _pin) { - if (spi.transfer(pins[_pin], resp) > 2) { + if (spi != null && spi.transfer(pins[_pin], resp) > 2) return ((resp[1] & 0x03) << 8) + (resp[2] & 0xFF); - } return 0; } } diff --git a/currentmonitor/lantern-currentmonitor/src/main/resources/logback.xml b/currentmonitor/lantern-currentmonitor/src/main/resources/logback.xml index b4a0684..2eb7d5d 100644 --- a/currentmonitor/lantern-currentmonitor/src/main/resources/logback.xml +++ b/currentmonitor/lantern-currentmonitor/src/main/resources/logback.xml @@ -2,12 +2,6 @@ - - - ${log.pattern} - - - /opt/currentmonitor/log/log.txt diff --git a/currentmonitor/lantern-dataaccess-currentmonitor/pom.xml b/currentmonitor/lantern-dataaccess-currentmonitor/pom.xml index db45edc..e334a31 100644 --- a/currentmonitor/lantern-dataaccess-currentmonitor/pom.xml +++ b/currentmonitor/lantern-dataaccess-currentmonitor/pom.xml @@ -43,7 +43,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 package @@ -73,16 +73,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 2.5 - - - true - - - diff --git a/currentmonitor/lantern-datamodel-currentmonitor/pom.xml b/currentmonitor/lantern-datamodel-currentmonitor/pom.xml index ebad97b..62db98b 100644 --- a/currentmonitor/lantern-datamodel-currentmonitor/pom.xml +++ b/currentmonitor/lantern-datamodel-currentmonitor/pom.xml @@ -28,7 +28,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -48,7 +48,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 package @@ -58,16 +58,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 2.5 - - - true - - - diff --git a/currentmonitor/lantern-service-currentmonitor/pom.xml b/currentmonitor/lantern-service-currentmonitor/pom.xml index 5661be9..d1e0058 100644 --- a/currentmonitor/lantern-service-currentmonitor/pom.xml +++ b/currentmonitor/lantern-service-currentmonitor/pom.xml @@ -11,44 +11,32 @@ 1.1.0 - - - - com.google.api-client - google-api-client-bom - 1.33.4 - pom - import - - - - com.lanternsoftware.currentmonitor lantern-dataaccess-currentmonitor - 1.0.0 + ${cm.version} com.lanternsoftware.util lantern-util-servlet ${util.version} + + com.lanternsoftware.util + lantern-util-cloudservices + ${util.version} + com.lanternsoftware.util lantern-util-http ${util.version} - test com.lanternsoftware.rules lantern-service-rules ${rules.version} - - com.google.api-client - google-api-client - javax javaee-api @@ -65,6 +53,11 @@ logback-classic 1.2.3 + + com.auth0 + java-jwt + 3.19.1 + com.mailjet mailjet-client @@ -81,7 +74,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -100,7 +93,7 @@ maven-war-plugin - 2.5 + 3.3.2 diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java index e2d041e..95d5b50 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/context/Globals.java @@ -6,8 +6,9 @@ import com.lanternsoftware.datamodel.currentmonitor.HubCommand; import com.lanternsoftware.datamodel.currentmonitor.HubCommands; import com.lanternsoftware.rules.RulesEngine; import com.lanternsoftware.util.DateUtils; -import com.lanternsoftware.util.external.LanternFiles; import com.lanternsoftware.util.dao.mongo.MongoConfig; +import com.lanternsoftware.util.external.LanternFiles; +import com.lanternsoftware.util.http.HttpFactory; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -32,6 +33,7 @@ public class Globals implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent sce) { dao.shutdown(); + HttpFactory.shutdown(); RulesEngine.shutdown(); } diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java index c943482..eafbef7 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/AuthServlet.java @@ -1,14 +1,15 @@ package com.lanternsoftware.currentmonitor.servlet; import com.lanternsoftware.currentmonitor.context.Globals; -import com.lanternsoftware.currentmonitor.util.GoogleAuthHelper; import com.lanternsoftware.util.DateUtils; import com.lanternsoftware.util.NullUtils; +import com.lanternsoftware.util.cloudservices.apple.AppleSSO; +import com.lanternsoftware.util.cloudservices.google.GoogleSSO; import com.lanternsoftware.util.dao.DaoEntity; +import com.lanternsoftware.util.dao.DaoSerializer; +import com.lanternsoftware.util.external.LanternFiles; import com.lanternsoftware.util.servlet.BasicAuth; import com.lanternsoftware.util.servlet.LanternServlet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; @@ -16,19 +17,27 @@ import javax.servlet.http.HttpServletResponse; @WebServlet("/auth/*") public class AuthServlet extends LanternServlet { - private static final Logger logger = LoggerFactory.getLogger(AuthServlet.class); + private static final GoogleSSO googleSSO = new GoogleSSO(LanternFiles.CONFIG_PATH + "google_sso.txt"); + private static final AppleSSO appleSSO = new AppleSSO(LanternFiles.CONFIG_PATH + "apple_sso.txt"); @Override protected void doGet(HttpServletRequest _req, HttpServletResponse _rep) { String authCode = _req.getHeader("auth_code"); - if (NullUtils.isEmpty(authCode)) { + String idToken = _req.getHeader("id_token"); + String email = null; + if (NullUtils.isNotEmpty(idToken)) + email = appleSSO.getEmailFromIdToken(idToken); + else if (NullUtils.isNotEmpty(authCode)) + authCode = Globals.dao.exchangeAuthCode(authCode, DaoSerializer.toInteger(_req.getHeader("override_account"))); + else { BasicAuth auth = new BasicAuth(_req); - if (NullUtils.isEqual(auth.getUsername(), "googlesso")) { - logger.info("Attempting google SSO"); - authCode = GoogleAuthHelper.signin(auth.getPassword(), DateUtils.fromTimeZoneId(_req.getHeader("timezone"))); - } else + if (NullUtils.isEqual(auth.getUsername(), "googlesso")) + email = googleSSO.signin(auth.getPassword()); + else authCode = Globals.dao.authenticateAccount(auth.getUsername(), auth.getPassword()); } + if (NullUtils.isNotEmpty(email)) + authCode = Globals.dao.getAuthCodeForEmail(email, DateUtils.fromTimeZoneId(_req.getHeader("timezone"))); DaoEntity rep = new DaoEntity("auth_code", authCode).and("timezone", Globals.dao.getTimeZoneForAccount(authCode)); if (isPath(_req, 0, "bin")) zipBsonResponse(_rep, rep); diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/console/GsoServlet.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/console/GsoServlet.java index 5195f32..eedd115 100644 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/console/GsoServlet.java +++ b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/servlet/console/GsoServlet.java @@ -1,7 +1,10 @@ package com.lanternsoftware.currentmonitor.servlet.console; -import com.lanternsoftware.currentmonitor.util.GoogleAuthHelper; +import com.lanternsoftware.currentmonitor.context.Globals; +import com.lanternsoftware.util.DateUtils; import com.lanternsoftware.util.NullUtils; +import com.lanternsoftware.util.cloudservices.google.GoogleSSO; +import com.lanternsoftware.util.external.LanternFiles; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; @@ -10,6 +13,8 @@ import javax.servlet.http.HttpServletResponse; @WebServlet("/gso") public class GsoServlet extends SecureConsoleServlet { + private static final GoogleSSO googleSSO = new GoogleSSO(LanternFiles.CONFIG_PATH + "google_sso.txt"); + @Override protected void get(HttpServletRequest _req, HttpServletResponse _rep) { render(_rep, "login.ftl", model(_req)); @@ -19,13 +24,16 @@ public class GsoServlet extends SecureConsoleServlet { protected void post(HttpServletRequest _req, HttpServletResponse _rep) { String code = getRequestPayloadAsString(_req); if (NullUtils.isNotEmpty(code)) { - String authCode = GoogleAuthHelper.signin(code, null); - if (NullUtils.isNotEmpty(authCode)) { - Cookie authCookie = new Cookie("auth_code", authCode); - authCookie.setMaxAge(157680000); - authCookie.setSecure(true); - _rep.addCookie(authCookie); - _req.getSession().setAttribute("auth_code", authCode); + String email = googleSSO.signin(code); + if (NullUtils.isNotEmpty(email)) { + String authCode = Globals.dao.getAuthCodeForEmail(email, DateUtils.fromTimeZoneId(_req.getHeader("timezone"))); + if (NullUtils.isNotEmpty(authCode)) { + Cookie authCookie = new Cookie("auth_code", authCode); + authCookie.setMaxAge(157680000); + authCookie.setSecure(true); + _rep.addCookie(authCookie); + _req.getSession().setAttribute("auth_code", authCode); + } } } } diff --git a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/util/GoogleAuthHelper.java b/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/util/GoogleAuthHelper.java deleted file mode 100644 index 39ca351..0000000 --- a/currentmonitor/lantern-service-currentmonitor/src/main/java/com/lanternsoftware/currentmonitor/util/GoogleAuthHelper.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lanternsoftware.currentmonitor.util; - -import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest; -import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; -import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.gson.GsonFactory; -import com.lanternsoftware.currentmonitor.context.Globals; -import com.lanternsoftware.util.ResourceLoader; -import com.lanternsoftware.util.dao.DaoEntity; -import com.lanternsoftware.util.dao.DaoSerializer; -import com.lanternsoftware.util.external.LanternFiles; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.TimeZone; - -public class GoogleAuthHelper { - private static final Logger logger = LoggerFactory.getLogger(GoogleAuthHelper.class); - private static final NetHttpTransport transport = new NetHttpTransport(); - private static final String googleClientId; - private static final String googleClientSecret; - static { - DaoEntity google = DaoSerializer.parse(ResourceLoader.loadFileAsString(LanternFiles.CONFIG_PATH + "google_sso.txt")); - googleClientId = DaoSerializer.getString(google, "id"); - googleClientSecret = DaoSerializer.getString(google, "secret"); - } - - public static String signin(String _code, TimeZone _tz) { - try { - GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(transport, new GsonFactory(), "https://oauth2.googleapis.com/token", googleClientId, googleClientSecret, _code, "https://lanternsoftware.com/console").execute(); - if (tokenResponse != null) { - GoogleIdToken idToken = tokenResponse.parseIdToken(); - if (idToken != null) - return Globals.dao.getAuthCodeForEmail(idToken.getPayload().getEmail(), _tz); - } - } catch (Exception _e) { - logger.error("Failed to validate google auth code", _e); - } - return null; - } -} diff --git a/pigpio/lantern-pigpio/pom.xml b/pigpio/lantern-pigpio/pom.xml new file mode 100644 index 0000000..86b4bfa --- /dev/null +++ b/pigpio/lantern-pigpio/pom.xml @@ -0,0 +1,68 @@ + + 4.0.0 + lantern-pigpio + jar + 1.0.0 + lantern-pigpio + + + com.lanternsoftware.pigpio + pigpio + 1.0.0 + + + + + com.lanternsoftware.util + lantern-util-common + ${util.version} + + + org.slf4j + slf4j-api + 1.7.29 + + + + + + src/main/resources + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + + + testCompile + + compile + + + + true + true + UTF-8 + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + package + + jar + + + + + + + diff --git a/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PIGPIO.java b/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PIGPIO.java new file mode 100644 index 0000000..c1bc3f6 --- /dev/null +++ b/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PIGPIO.java @@ -0,0 +1,54 @@ +package com.lanternsoftware.pigpio; + +import com.lanternsoftware.util.ResourceLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.Files; + +public class PIGPIO { + protected static final Logger LOG = LoggerFactory.getLogger(PIGPIO.class); + + private PIGPIO() { + } + + static { + try { + String osArch = System.getProperty("os.arch").toLowerCase(); + if (osArch.equals("arm")) + osArch = "armhf"; + String path = "/lib/" + osArch + "/lantern-pigpio.so"; + byte[] file = ResourceLoader.getByteArrayResource(PIGPIO.class, path); + String target = Files.createTempFile("lantern-pigpio", "so").toAbsolutePath().toString(); + ResourceLoader.writeFile(target, file); + System.load(target); + } catch (IOException _e) { + LOG.error("Failed to load lantern-pigpio.so from resource", _e); + } + } + + public static native int gpioInitialise(); + + public static native void gpioTerminate(); + + public static native int gpioSetMode(int gpio, int mode); + + public static native int gpioGetMode(int gpio); + + public static native int gpioSetPullUpDown(int gpio, int pud); + + public static native int gpioRead(int gpio); + + public static native int gpioWrite(int gpio, int level); + + public static native int spiOpen(int spiChan, int baud, int spiFlags); + + public static native int spiClose(int handle); + + public static native int spiRead(int handle, byte[] buf, int offset, int count); + + public static native int spiWrite(int handle, byte[] buf, int offset, int count); + + public static native int spiXfer(int handle, byte[] txBuf, int txOffset, byte[] rxBuf, int rxOffset, int count); +} diff --git a/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PiGpioFactory.java b/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PiGpioFactory.java new file mode 100644 index 0000000..1a3d67b --- /dev/null +++ b/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/PiGpioFactory.java @@ -0,0 +1,51 @@ +package com.lanternsoftware.pigpio; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public class PiGpioFactory { + private static final Logger LOG = LoggerFactory.getLogger(PIGPIO.class); + private static final Map spiHandles = new HashMap<>(); + private static boolean initialized = false; + + public static Spi getSpiChannel(int _channel, int _baud, boolean _auxiliary) { + ensureInitialized(); + int channelId = (0xff & _channel); + if (_auxiliary) + channelId |= 0x100; + Spi handle = spiHandles.get(channelId); + if (handle == null) { + int h = PIGPIO.spiOpen(_channel, _baud, _auxiliary ? 0x100 : 0); + if (h >= 0) { + handle = new Spi(h); + spiHandles.put(channelId, handle); + } + else { + LOG.error("Failed to get SPI handle"); + } + } + return handle; + } + + private static void ensureInitialized() { + if (initialized) + return; + int init = PIGPIO.gpioInitialise(); + LOG.info("GPIO init: {}", init); + if (init < 0) + LOG.error("Failed to initialize PiGpio"); + else + initialized = true; + } + + public static void shutdown() { + for (Spi handle : spiHandles.values()) { + PIGPIO.spiClose(handle.getHandle()); + } + spiHandles.clear(); + PIGPIO.gpioTerminate(); + } +} diff --git a/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/Spi.java b/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/Spi.java new file mode 100644 index 0000000..24c4444 --- /dev/null +++ b/pigpio/lantern-pigpio/src/main/java/com/lanternsoftware/pigpio/Spi.java @@ -0,0 +1,37 @@ +package com.lanternsoftware.pigpio; + +public class Spi { + private final int handle; + + public Spi(int _handle) { + handle = _handle; + } + + public int getHandle() { + return handle; + } + + public int read(byte[] buf) { + return read(buf, 0, buf.length); + } + + public int read(byte[] buf, int offset, int count) { + return PIGPIO.spiRead(handle, buf, offset, count); + } + + public int write(byte[] buf) { + return write(buf, 0, buf.length); + } + + public int write(byte[] buf, int offset, int count) { + return PIGPIO.spiWrite(handle, buf, offset, count); + } + + public int transfer(byte[] txBuf, byte[] rxBuf) { + return transfer(txBuf, 0, rxBuf, 0, rxBuf.length); + } + + public int transfer(byte[] txBuf, int txOffset, byte[] rxBuf, int rxOffset, int count) { + return PIGPIO.spiXfer(handle, txBuf, txOffset, rxBuf, rxOffset, count); + } +} diff --git a/pigpio/lantern-pigpio/src/main/native/Makefile b/pigpio/lantern-pigpio/src/main/native/Makefile new file mode 100644 index 0000000..cd253f2 --- /dev/null +++ b/pigpio/lantern-pigpio/src/main/native/Makefile @@ -0,0 +1,54 @@ +ARCH := armhf +DEBUG = -O3 +CC = $(CROSS_PREFIX)gcc +AR = $(CROSS_PREFIX)ar +RANLIB = $(CROSS_PREFIX)ranlib +SIZE = $(CROSS_PREFIX)size +STRIP = $(CROSS_PREFIX)strip +SHLIB = $(CC) -shared +STRIPLIB = $(STRIP) --strip-unneeded +INCLUDE = -I. -Ipigpio \ + -I/$(JAVA_HOME)/include \ + -I/$(JAVA_HOME)/include/linux \ + -I/usr/local/include -I/usr/local/include/linux + +CFLAGS := $(DEBUG) -Wall $(INCLUDE) -Winline -pipe $(CARGS) -fPIC +LIBS = -L lib/$(ARCH) -L pigpio -lpigpio -lrt + +TARGET=lantern-pigpio.so + +############################################################################### + +SRC = com_lanternsoftware_pigpio_PIGPIO.c + +OBJ = $(SRC:.c=.o) + +all: $(OBJ) + @echo [LINK with DYNAMICALLY linked libraries] + @$(CC) $(OBJ) -shared -o $(TARGET) $(INCLUDE) $(LIBS) + +.c.o: + @echo [COMPILE] $< + @$(CC) -c $(CFLAGS) $< -o $@ + +clean: + rm -f $(OBJ) $(TARGET) *~ core tags Makefile.bak + +tags: $(SRC) + @echo [ctags] + @ctags $(SRC) + +depend: + makedepend -Y $(SRC) + +install: $(TARGET) + @echo [install] + install -m 0755 -d /usr/local/lib + install -m 0755 -d /usr/local/include + install -m 0644 $(TARGET) /usr/local/lib + +uninstall: + @echo [uninstall] + rm -f /usr/local/lib/$(TARGET) + +com_lanternsoftware_pigpio_PIGPIO.o: com_lanternsoftware_pigpio_PIGPIO.h diff --git a/pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.c b/pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.c new file mode 100644 index 0000000..fdf1fad --- /dev/null +++ b/pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include "com_lanternsoftware_pigpio_PIGPIO.h" + + +JavaVM *callback_jvm; + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) +{ + JNIEnv *env; + if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2)) + { + return JNI_ERR; + } + callback_jvm = jvm; + return JNI_VERSION_1_2; +} + +JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved) +{ + return; +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioInitialise + (JNIEnv *env, jclass class) +{ + gpioCfgSetInternals (gpioCfgGetInternals () | PI_CFG_NOSIGHANDLER); + return gpioInitialise(); +} + +JNIEXPORT void JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioTerminate(JNIEnv *env, jclass class) +{ + return gpioTerminate(); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioSetMode + (JNIEnv *env, jclass class, jint gpio, jint mode) +{ + return gpioSetMode((unsigned)gpio, (unsigned)mode); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioGetMode + (JNIEnv *env, jclass class, jint gpio) +{ + return gpioGetMode((unsigned)gpio); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioSetPullUpDown + (JNIEnv *env, jclass class, jint gpio, jint pud) +{ + return gpioSetPullUpDown((unsigned)gpio, (unsigned)pud); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioRead + (JNIEnv *env, jclass class, jint gpio) +{ + return gpioRead((unsigned)gpio); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioWrite + (JNIEnv *env, jclass class, jint gpio, jint level) +{ + return gpioWrite((unsigned)gpio, (unsigned)level); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiOpen + (JNIEnv *env, jclass class, jint spiChan, jint baud, jint spiFlags) +{ + return spiOpen((unsigned)spiChan, (unsigned)baud, (unsigned)spiFlags); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiClose + (JNIEnv *env, jclass class, jint handle) +{ + return spiClose((unsigned)handle); +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiRead + (JNIEnv *env, jclass class, jint handle, jbyteArray data, jint offset, jint count) +{ + jbyte *buffer = (*env)->GetByteArrayElements(env, data, 0); + jsize max_length = (*env)->GetArrayLength(env, data) - offset; + int length = (count > max_length) ? max_length : count; + jbyte *offsetBuffer = buffer + offset; + jint result = spiRead((unsigned)handle, (char *)offsetBuffer, (unsigned)length); + (*env)->ReleaseByteArrayElements(env, data, buffer, 0); + return result; +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiWrite + (JNIEnv *env, jclass class, jint handle, jbyteArray data, jint offset, jint count) +{ + jbyte *buffer = (*env)->GetByteArrayElements(env, data, 0); + jsize max_length = (*env)->GetArrayLength(env, data) - offset; + int length = (count > max_length) ? max_length : count; + jbyte *offsetBuffer = buffer + offset; + jint result = spiWrite((unsigned)handle, (char *)offsetBuffer, (unsigned)length); + (*env)->ReleaseByteArrayElements(env, data, buffer, JNI_ABORT); + return result; +} + +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiXfer + (JNIEnv *env, jclass class, jint handle, jbyteArray writeData, jint writeOffset, jbyteArray readData, jint readOffset, jint count) +{ + jbyte *writeBuffer = (*env)->GetByteArrayElements(env, writeData, 0); + jbyte *readBuffer = (*env)->GetByteArrayElements(env, readData, 0); + jsize max_length = (*env)->GetArrayLength(env, writeData) - writeOffset; + int length = (count > max_length) ? max_length : count; + jbyte *offsetWriteBuffer = writeBuffer + writeOffset; + jbyte *offsetReadBuffer = readBuffer + readOffset; + jint result = spiXfer((unsigned)handle, (char *)offsetWriteBuffer, (char *)offsetReadBuffer, (unsigned)length); + (*env)->ReleaseByteArrayElements(env, writeData, writeBuffer, JNI_ABORT); + (*env)->ReleaseByteArrayElements(env, readData, readBuffer, 0); + return result; +} diff --git a/pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.h b/pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.h new file mode 100644 index 0000000..429b61d --- /dev/null +++ b/pigpio/lantern-pigpio/src/main/native/com_lanternsoftware_pigpio_PIGPIO.h @@ -0,0 +1,109 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_lanternsoftware_pigpio_PIGPIO */ + +#ifndef _Included_com_lanternsoftware_pigpio_PIGPIO +#define _Included_com_lanternsoftware_pigpio_PIGPIO +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: gpioInitialise + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioInitialise + (JNIEnv *, jclass); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: gpioTerminate + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioTerminate + (JNIEnv *, jclass); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: gpioSetMode + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioSetMode + (JNIEnv *, jclass, jint, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: gpioGetMode + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioGetMode + (JNIEnv *, jclass, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: gpioSetPullUpDown + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioSetPullUpDown + (JNIEnv *, jclass, jint, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: gpioRead + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioRead + (JNIEnv *, jclass, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: gpioWrite + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_gpioWrite + (JNIEnv *, jclass, jint, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: spiOpen + * Signature: (III)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiOpen + (JNIEnv *, jclass, jint, jint, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: spiClose + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiClose + (JNIEnv *, jclass, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: spiRead + * Signature: (I[BII)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiRead + (JNIEnv *, jclass, jint, jbyteArray, jint, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: spiWrite + * Signature: (I[BII)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiWrite + (JNIEnv *, jclass, jint, jbyteArray, jint, jint); + +/* + * Class: com_lanternsoftware_pigpio_PIGPIO + * Method: spiXfer + * Signature: (I[BI[BII)I + */ +JNIEXPORT jint JNICALL Java_com_lanternsoftware_pigpio_PIGPIO_spiXfer + (JNIEnv *, jclass, jint, jbyteArray, jint, jbyteArray, jint, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/pigpio/lantern-pigpio/src/main/resources/lib/aarch64/lantern-pigpio.so b/pigpio/lantern-pigpio/src/main/resources/lib/aarch64/lantern-pigpio.so new file mode 100644 index 0000000000000000000000000000000000000000..b89e987b6be142733b20d4c1622b384c0c5d0a48 GIT binary patch literal 13520 zcmeHOeQ;FO6~DVL34|{bK!{*rLE6R$OQ32|v1~R8Ni;wVVZ_nt%Vu|zY}xF_-HimW zH8M`il+g)-hzb-HD`A*1b+E;cwlQ@&Y5AiWQA({afoVI;)IUH(SRtmrbKgD5+qb(m zskNPPawl)kJHLC*x#ymD-+k}ick)PS<#M~tCb($gSAsa#1OsuYie9HW0da{XVhn!s z#B?c}IaHN&Ryf6gmE$aurtPXLOvf5# zLU@dq8JwLg7hOn&^_&mKHQzEJ(OI4F)|a8!vY8KOkkwq%O@ z{f>-PRF{W?!t3n$g3-wg^&1vL2)7W1Q+>xT)?P=`HPa}VG8h^Ue*r9Qds$DIOd_x-h@4!x~I6R*Q zKbFSM$7$MyxJc#aL@A#w#3Try@VK5R?PrU_6AfHVFQOJ~u9za))ph6l)urUSlsw}f zD*T+q&U32WcT~Ikjb_ABh36=o?KGi&vd9*XDLZ`M9#!(q*BAyaD?4kHe4&!BQTPdk zcUtTOl^uu0pF_(3J|)loY*cpI6@I<4A64?b3g@^9U2kX#hxBO76N%}%&?{j?(yJl=Ks z4<2e#_?l3VYVPtpAWHohy`Fe z>KDWo*Ef{;V--@%6O1yp+Ki3BdW}EQ1kYped-yJ)u@zz8h*aS7NLA2ERZB3qrnw}% zJ~R^ds{JF2@V$}1@cSQa4y-`ZC4AdDT%^3|l z7pdC>?-96BP&9QTJJkK+u;9Jw2IA)o%QN3K+puGU9lkfoZjT8cM}R85CR{ZsYfhN( z=`0M|XTs@uJy_KIXGgpAjOH@dg!3FlbvY*7{Qi|^!p-j=4iiq#eJ=SX+}z(n6OP$@ zuq-j*=0~{8gb&V9&?-0KYATers!X_=Y9+qbg!8k5Dr!x5u9P%>8cn$QdDm>h)hnn} zXf@&H`1f!6ZAZT*wp9wTqkq%e2f8%$^Ln)q?x-6nn#_&O6m8T@7wKMni~CVmF^ZWBKX{23EJ7rfmz)c&`? z&o%J{;N2$P3BJz6F9yHa#NP`31rvWe_-+&bJ@97?z74Sv=gQ(PAr8j}2BuToI5tF4 z-zyyUZI6P^0bM4puFpg>$n*D60ph@*3_K60#R!lPT~TrJxE zHsm)$*ZsG$c%9U>59(5T{hNLxuj7UBBEB7M*3Na`=CX-fV7F8BmBm31%QjrD_)7x= zPoKcy5N*}9bM3cX81IVrZ|auUp8N12`o!mk{a<&uAwO5_i_mz{ge!jfMX}AB=ZaIC z7c_CORxCS?VRj4k(FIutWaoTT7XOYwy=>!mYJ9a#zG{gXkHd}dONeQUcYxA(+^PKV zf%a+kg43E-@I!U}6IDn4ab2Clh~Ju`{vlI6**c?T6x;`lTqwI)}|ip)21ABA97=y zEIV!&)9=>Bv~|ySe|M|9cjt^gEw5lX`ssu08SUDGB(EWEpJ<|h^d1w%xNggi_i0lL zF03x+XI;W%j38l}57@pUB~S8k&F>G$dy8S^X8 zt+tuk9kgbqIs5FDfq}!IdAJ#RK-YqP2zmfi*n~I&ng=?ee_&uKXdY-4=n~Lo(50Y{ zftG{r0$mGA@7ax@U7)R??}2UsrFHWz(5s*aKrwHN%FhP|N0S?>V%P*rSyLU|S_N*P5B~NAS)Z9g1nKynp=Id(*bXaq(hFdBi;2#iKxGy&T!Fao@P%KN4CnoZ?1wLaqY0)NNj zz0XGVl7F2cKDaMCQ}Mi3n4x&ypOtGCU|fIk^MNploKp?+9_JBt!h4%*l|Q^Eo2@oa zd2f=|YgBko^{m=|RcfM5*{Agw72X@=J=-m6^ONx&;BpHRy7HnvAA&YqQXUsXu*)RBS!KwLFcIu@3`2p+wwNB!b zlkSW43g`Kf>{6k9PkV}dnx6s}B6)t;BjuCF`HRy2`2p*FZH(vS`RaAZQ~pGkiZeeC zJ$SIvp02fgq~xu6A!qS`OeNopP0CdGlr;8drok6Vd}ut>D93JBc&G9o&B+o5?oj7u z@*^d0&0nGSjZ}XALdl;~_W5=_qi}0pNG|N8YWF5-KU?%!;(Witt@$o5N&9Bcjq|Na zzFpbj_pQwmPnLgM$y@Vg&I3>7=ZQ4!_Q~s>Y=5G>zRCGFGZb#kzo}4ouO*(FC7x`5 zC-78xMX#pmZ*>~HD2@FWfv1XtSlAMcEJTjN!UnH*p~n;PHr{&kf?y!j(z>7_)Ut3< z;XoL?WIIx<3?)Y!LMkPm^Ew zwKO$tfQpIJAsI^${kMrk@K@KDR~M}))k{~FP^MGKeJhJrR1^b7mJ@@zFB;YxJs}_E zJ5ejBMjoVITCSAKOR9zRROn@utK3DE`l{v2SC`i4HAU{qQhm5dE|kYK!h|4ByGfM- zWy-i3W|j?E8OnUpEeTv-X(H4}({*GvkW5TVnS3^a4u6$-MHJAAp+vP|dNr6F^+kzy z#?>8J-W&|eG^b(uLEa~3o2g-zkX4tE&1cCR6wc^|rkJM=G!`*vBcFxBF~1Yjmb0!U z5cDkw_=MydJ<&$t^lb=1)1a}4a7O$=4}t2eIT#a8c_%t!{#KmRG$EY+Ml~Tc`k=#{ zA!*DEh9sZEpriZJ_IY9+;jD{Bg%eXq6Xu=dXTX1g&^`sN_3=29h1Ziz z=P8^C9s>!*3GP#@{aK&aolF~*G#)py@OzVDky%e~ZA0zz`jly{Qlxh2l=XSv!KH9+ zpVzTWd4B|Avf%NYP|CrPZPw@YF4Hb0ZS|kquU7hQCCBSxrfsT0(x+E$tN#xGBN5); z;r%71ypDs2EY|qn3)HO7>+C^l>9A#)Ch9EuynbYwZ)wn~-)Pb2bvsk5yv3XdDSeK= z_5TibquyMs`VXU$y2$#x4=_l%LK)%sv&|plgubow_2s-u{(l6kJo8MSgf8Xtu|DrB zIMn}ZupC5WVV>z;pmgn7pVvqH{~qn?`fbV-Euc|CJvHb9g@gAD$%KGQ>} zG3)bw##yDmYf#fTVLhg=S@e0m*5*i*H@Knk&-|M>AzSP}?~iP87!ur1gG<)$LIwG6 z?I-Jhn-vu$St@2~86vX2(;>W6`-+cemJ}CQcXc)g$HyZR+zHq9N+htjr T6H@8hX<|kBgFyy=t@{509aS;o literal 0 HcmV?d00001 diff --git a/pigpio/pom.xml b/pigpio/pom.xml new file mode 100644 index 0000000..7d37d2e --- /dev/null +++ b/pigpio/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + pom + com.lanternsoftware.pigpio + pigpio + pigpio + 1.0.0 + + + com.lanternsoftware + LanternPowerMonitor + 1.0.0 + + + + lantern-pigpio + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index e413959..00aa574 100644 --- a/pom.xml +++ b/pom.xml @@ -11,14 +11,16 @@ 11 UTF-8 1.1.0 - 1.0.0 + 1.0.0 1.0.0 + 1.0.0 1.0.0 currentmonitor util + pigpio rules zwave diff --git a/rules/lantern-dataaccess-rules/pom.xml b/rules/lantern-dataaccess-rules/pom.xml index 012beb5..0f4b049 100644 --- a/rules/lantern-dataaccess-rules/pom.xml +++ b/rules/lantern-dataaccess-rules/pom.xml @@ -33,7 +33,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -53,7 +53,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 package @@ -63,16 +63,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 2.5 - - - true - - - diff --git a/rules/lantern-datamodel-rules/pom.xml b/rules/lantern-datamodel-rules/pom.xml index 63349d8..05f99f1 100644 --- a/rules/lantern-datamodel-rules/pom.xml +++ b/rules/lantern-datamodel-rules/pom.xml @@ -28,7 +28,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -48,7 +48,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 package @@ -58,16 +58,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 2.5 - - - true - - - diff --git a/rules/lantern-service-rules/pom.xml b/rules/lantern-service-rules/pom.xml index a64c55a..1c27f8e 100644 --- a/rules/lantern-service-rules/pom.xml +++ b/rules/lantern-service-rules/pom.xml @@ -12,28 +12,7 @@ 1.0.0 - - - - com.google.api-client - google-api-client-bom - 1.32.1 - pom - import - - - - - - com.google.api-client - google-api-client - - - com.google.firebase - firebase-admin - 8.0.0 - com.lanternsoftware.rules lantern-dataaccess-rules @@ -49,6 +28,11 @@ lantern-util-servlet ${util.version} + + com.lanternsoftware.util + lantern-util-cloudservices + ${util.version} + javax javaee-api @@ -60,6 +44,12 @@ slf4j-api 1.7.29 + + ch.qos.logback + logback-classic + 1.2.3 + test + @@ -71,7 +61,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/AbstractAlertAction.java b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/AbstractAlertAction.java index 60c6315..3247b46 100644 --- a/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/AbstractAlertAction.java +++ b/rules/lantern-service-rules/src/main/java/com/lanternsoftware/rules/actions/AbstractAlertAction.java @@ -1,55 +1,28 @@ package com.lanternsoftware.rules.actions; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.firebase.FirebaseApp; -import com.google.firebase.FirebaseOptions; -import com.google.firebase.messaging.AndroidConfig; -import com.google.firebase.messaging.FirebaseMessaging; -import com.google.firebase.messaging.Message; import com.lanternsoftware.datamodel.rules.Alert; import com.lanternsoftware.datamodel.rules.FcmDevice; import com.lanternsoftware.datamodel.rules.Rule; import com.lanternsoftware.rules.RulesEngine; -import com.lanternsoftware.util.external.LanternFiles; +import com.lanternsoftware.util.dao.DaoEntity; import com.lanternsoftware.util.dao.DaoSerializer; -import org.apache.commons.io.IOUtils; +import com.lanternsoftware.util.external.LanternFiles; +import com.lanternsoftware.util.cloudservices.google.FirebaseHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.FileInputStream; import java.util.List; public abstract class AbstractAlertAction implements ActionImpl { protected static final Logger logger = LoggerFactory.getLogger(AbstractAlertAction.class); - protected static final FirebaseMessaging messaging; - static { - FirebaseMessaging m = null; - try { - FileInputStream is = new FileInputStream(LanternFiles.CONFIG_PATH + "google_account_key.json"); - FirebaseOptions options = FirebaseOptions.builder().setCredentials(GoogleCredentials.fromStream(is)).build(); - m = FirebaseMessaging.getInstance(FirebaseApp.initializeApp(options)); - IOUtils.closeQuietly(is); - } - catch (Exception _e) { - logger.error("Failed to load google credentials", _e); - } - messaging = m; - } + protected static final FirebaseHelper firebaseHelper = new FirebaseHelper(LanternFiles.CONFIG_PATH + "google_account_key.json"); protected void sendAlert(Rule _rule, Alert _alert) { List devices = RulesEngine.instance().dao().getFcmDevicesForAccount(_rule.getAccountId()); if (devices.isEmpty()) return; for (FcmDevice device : devices) { - Message msg = Message.builder().setToken(device.getToken()).putData("payload", DaoSerializer.toBase64ZipBson(_alert)).putData("payloadClass", Alert.class.getCanonicalName()).setAndroidConfig(AndroidConfig.builder().setPriority(AndroidConfig.Priority.HIGH).setDirectBootOk(true).build()).build(); - try { - messaging.send(msg); - } catch (Exception _e) { - if (_e.getMessage().contains("not found")) { - RulesEngine.instance().dao().removeFcmDevice(device.getId()); - } - logger.error("Failed to send message to account {}, device {}", _rule.getAccountId(), device.getName(), _e); - } + firebaseHelper.sendMessage(device.getToken(), new DaoEntity("payload", DaoSerializer.toBase64ZipBson(_alert)).and("payloadClass", Alert.class.getCanonicalName())); } } } diff --git a/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestSendAlert.java b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestSendAlert.java index 29154b2..bd19f1b 100644 --- a/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestSendAlert.java +++ b/rules/lantern-service-rules/src/test/java/com/lanternsoftware/TestSendAlert.java @@ -1,20 +1,14 @@ package com.lanternsoftware; -import com.google.auth.oauth2.GoogleCredentials; -import com.google.firebase.FirebaseApp; -import com.google.firebase.FirebaseOptions; -import com.google.firebase.messaging.FirebaseMessaging; -import com.google.firebase.messaging.Message; import com.lanternsoftware.dataaccess.rules.MongoRulesDataAccess; import com.lanternsoftware.dataaccess.rules.RulesDataAccess; import com.lanternsoftware.datamodel.rules.Alert; import com.lanternsoftware.datamodel.rules.FcmDevice; -import com.lanternsoftware.util.external.LanternFiles; +import com.lanternsoftware.util.cloudservices.google.FirebaseHelper; +import com.lanternsoftware.util.dao.DaoEntity; import com.lanternsoftware.util.dao.DaoSerializer; import com.lanternsoftware.util.dao.mongo.MongoConfig; -import org.apache.commons.io.IOUtils; - -import java.io.FileInputStream; +import com.lanternsoftware.util.external.LanternFiles; public class TestSendAlert { public static void main(String[] args) { @@ -24,15 +18,7 @@ public class TestSendAlert { continue; Alert alert = new Alert(); alert.setMessage("Garage Door 1 is still open"); - Message msg = Message.builder().setToken(d.getToken()).putData("payload", DaoSerializer.toBase64ZipBson(alert)).putData("payloadClass", Alert.class.getCanonicalName()).build(); - try { - FileInputStream is = new FileInputStream("d:\\zwave\\firebase\\account_key.json"); - FirebaseOptions options = FirebaseOptions.builder().setCredentials(GoogleCredentials.fromStream(is)).build(); - FirebaseMessaging.getInstance(FirebaseApp.initializeApp(options)).send(msg); - IOUtils.closeQuietly(is); - } catch (Exception _e) { - _e.printStackTrace(); - } + new FirebaseHelper(LanternFiles.CONFIG_PATH + "google_sso.json").sendMessage(d.getToken(), new DaoEntity("payload", DaoSerializer.toBase64ZipBson(alert)).and("payloadClass", Alert.class.getCanonicalName())); } } } diff --git a/rules/lantern-service-rules/src/test/resources/logback.xml b/rules/lantern-service-rules/src/test/resources/logback.xml new file mode 100644 index 0000000..bfde39c --- /dev/null +++ b/rules/lantern-service-rules/src/test/resources/logback.xml @@ -0,0 +1,16 @@ + + + + + + + ${log.pattern} + + + + + + + + + \ No newline at end of file diff --git a/util/lantern-util-cloudservices/pom.xml b/util/lantern-util-cloudservices/pom.xml new file mode 100644 index 0000000..e91be51 --- /dev/null +++ b/util/lantern-util-cloudservices/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + lantern-util-cloudservices + lantern-util-cloudservices + 1.0.0 + jar + + + com.lanternsoftware.util + util + 1.0.0 + + + + + ${project.groupId} + lantern-util-common + ${project.version} + + + ${project.groupId} + lantern-util-dao + ${project.version} + + + ${project.groupId} + lantern-util-http + ${project.version} + + + com.auth0 + java-jwt + 3.19.1 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + + + testCompile + + compile + + + + true + true + UTF-8 + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + package + + jar + + + + + + + diff --git a/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/apple/AppleSSO.java b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/apple/AppleSSO.java new file mode 100644 index 0000000..069cf36 --- /dev/null +++ b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/apple/AppleSSO.java @@ -0,0 +1,70 @@ +package com.lanternsoftware.util.cloudservices.apple; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.lanternsoftware.util.NullUtils; +import com.lanternsoftware.util.ResourceLoader; +import com.lanternsoftware.util.dao.DaoEntity; +import com.lanternsoftware.util.dao.DaoSerializer; +import com.lanternsoftware.util.http.HttpFactory; +import org.apache.commons.codec.binary.Base64; +import org.apache.http.client.methods.HttpGet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.RSAPublicKeySpec; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +public class AppleSSO { + private static final Logger LOG = LoggerFactory.getLogger(AppleSSO.class); + private final Map publicKeys = new HashMap<>(); + private final String audience; + + public AppleSSO(String _credentialsPath) { + audience = ResourceLoader.loadFileAsString(_credentialsPath).trim(); + } + + public String getEmailFromIdToken(String _idToken) { + if (validatePublicKey()) { + try { + DecodedJWT jwt = JWT.decode(NullUtils.base64ToString(_idToken)); + String kid = jwt.getHeaderClaim("kid").asString(); + RSAPublicKey key = publicKeys.get(kid); + if (key != null) { + Algorithm algorithm = Algorithm.RSA256(key, null); + JWTVerifier verifier = JWT.require(algorithm).withIssuer("https://appleid.apple.com").withAudience(audience).build(); + return verifier.verify(jwt).getClaim("email").asString().toLowerCase(Locale.ROOT); + } + } catch (Exception _e){ + LOG.error("Failed to verify Apple JWT token", _e); + } + } + return null; + } + + private synchronized boolean validatePublicKey() { + if (!publicKeys.isEmpty()) + return true; + DaoEntity resp = DaoSerializer.parse(HttpFactory.pool().executeToString(new HttpGet("https://appleid.apple.com/auth/keys"))); + for (DaoEntity key : DaoSerializer.getDaoEntityList(resp, "keys")) { + try { + KeyFactory fact = KeyFactory.getInstance("RSA"); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec(new BigInteger(1, Base64.decodeBase64(DaoSerializer.getString(key, "n"))), new BigInteger(1, Base64.decodeBase64(DaoSerializer.getString(key, "e")))); + RSAPublicKey publicKey = (RSAPublicKey)fact.generatePublic(keySpec); + if (publicKey != null) + publicKeys.put(DaoSerializer.getString(key, "kid"), publicKey); + } catch (Exception _e) { + LOG.error("Failed to generate RSA public key", _e); + } + } + return !publicKeys.isEmpty(); + } + +} diff --git a/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseCredentials.java b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseCredentials.java new file mode 100644 index 0000000..e753c3d --- /dev/null +++ b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseCredentials.java @@ -0,0 +1,97 @@ +package com.lanternsoftware.util.cloudservices.google; + +import com.lanternsoftware.util.dao.annotations.DBSerializable; + +@DBSerializable +public class FirebaseCredentials { + private String type; + private String projectId; + private String privateKeyId; + private String privateKey; + private String clientEmail; + private String clientId; + private String authUri; + private String tokenUri; + private String authProviderX509CertUrl; + private String clientX509CertUrl; + + public String getType() { + return type; + } + + public void setType(String _type) { + type = _type; + } + + public String getProjectId() { + return projectId; + } + + public void setProjectId(String _projectId) { + projectId = _projectId; + } + + public String getPrivateKeyId() { + return privateKeyId; + } + + public void setPrivateKeyId(String _privateKeyId) { + privateKeyId = _privateKeyId; + } + + public String getPrivateKey() { + return privateKey; + } + + public void setPrivateKey(String _privateKey) { + privateKey = _privateKey; + } + + public String getClientEmail() { + return clientEmail; + } + + public void setClientEmail(String _clientEmail) { + clientEmail = _clientEmail; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String _clientId) { + clientId = _clientId; + } + + public String getAuthUri() { + return authUri; + } + + public void setAuthUri(String _authUri) { + authUri = _authUri; + } + + public String getTokenUri() { + return tokenUri; + } + + public void setTokenUri(String _tokenUri) { + tokenUri = _tokenUri; + } + + public String getAuthProviderX509CertUrl() { + return authProviderX509CertUrl; + } + + public void setAuthProviderX509CertUrl(String _authProviderX509CertUrl) { + authProviderX509CertUrl = _authProviderX509CertUrl; + } + + public String getClientX509CertUrl() { + return clientX509CertUrl; + } + + public void setClientX509CertUrl(String _clientX509CertUrl) { + clientX509CertUrl = _clientX509CertUrl; + } +} diff --git a/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseHelper.java b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseHelper.java new file mode 100644 index 0000000..02d0909 --- /dev/null +++ b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/FirebaseHelper.java @@ -0,0 +1,109 @@ +package com.lanternsoftware.util.cloudservices.google; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.lanternsoftware.util.CollectionUtils; +import com.lanternsoftware.util.DateUtils; +import com.lanternsoftware.util.NullUtils; +import com.lanternsoftware.util.ResourceLoader; +import com.lanternsoftware.util.dao.DaoEntity; +import com.lanternsoftware.util.dao.DaoSerializer; +import com.lanternsoftware.util.http.HttpFactory; +import org.apache.commons.codec.binary.Base64; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicNameValuePair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.security.KeyFactory; +import java.security.interfaces.RSAPrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class FirebaseHelper { + private static final Logger LOG = LoggerFactory.getLogger(FirebaseHelper.class); + private static final String FCM_SEND_URL = "https://fcm.googleapis.com/v1/projects/%s/messages:send"; + private static final List SCOPES = List.of("https://www.googleapis.com/auth/firebase.database", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/identitytoolkit", "https://www.googleapis.com/auth/devstorage.full_control", "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/datastore"); + + private final FirebaseCredentials credentials; + private final RSAPrivateKey privateKey; + private final String fcmSendUrl; + private String accessToken; + private Date validUntil; + + public FirebaseHelper(String _credentialsPath) { + this(DaoSerializer.parse(ResourceLoader.loadFileAsString(_credentialsPath), FirebaseCredentials.class)); + } + + public FirebaseHelper(FirebaseCredentials _credentials) { + credentials = _credentials; + if (credentials != null) { + privateKey = fromPEM(credentials.getPrivateKey()); + fcmSendUrl = String.format(FCM_SEND_URL, credentials.getProjectId()); + } + else { + LOG.error("Failed to load FCM credentials"); + privateKey = null; + fcmSendUrl = null; + } + } + + private RSAPrivateKey fromPEM(String _pem) { + try { + String pem = _pem.replaceAll("(-+BEGIN PRIVATE KEY-+|-+END PRIVATE KEY-+|\\r|\\n)", ""); + byte[] encoded = Base64.decodeBase64(pem); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); + return (RSAPrivateKey)keyFactory.generatePrivate(keySpec); + } + catch (Exception _e) { + LOG.error("Failed to generate RSA private key", _e); + return null; + } + } + + private boolean validateAccessToken() { + if (isTokenValid()) + return true; + Date now = new Date(); + String assertion = JWT.create().withKeyId(credentials.getPrivateKeyId()).withIssuer(credentials.getClientEmail()).withIssuedAt(new Date()).withExpiresAt(DateUtils.addHours(now, 1)).withClaim("scope", CollectionUtils.delimit(SCOPES, " ")).withAudience(credentials.getTokenUri()).sign(Algorithm.RSA256(null, privateKey)); + + HttpPost post = new HttpPost(credentials.getTokenUri()); + List payload = new ArrayList<>(); + payload.add(new BasicNameValuePair("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer")); + payload.add(new BasicNameValuePair("assertion", assertion)); + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(payload, StandardCharsets.UTF_8); + entity.setContentType("application/x-www-form-urlencoded"); + post.setEntity(entity); + DaoEntity rep = DaoSerializer.parse(HttpFactory.pool().executeToString(post)); + if (rep == null) + return false; + accessToken = DaoSerializer.getString(rep, "access_token"); + validUntil = DateUtils.secondsFromNow(DaoSerializer.getInteger(rep, "expires_in")-10); + return isTokenValid(); + } + + private boolean isTokenValid() { + return NullUtils.isNotEmpty(accessToken) && (validUntil != null) && new Date().before(validUntil); + } + + public boolean sendMessage(String _deviceToken, DaoEntity _payload) { + if (!validateAccessToken()) { + LOG.error("Failed to get a valid access token for Firebase, not sending message"); + return false; + } + DaoEntity msg = new DaoEntity("message", new DaoEntity("token", _deviceToken).and("data", _payload).and("android", new DaoEntity("priority", "high").and("direct_boot_ok", true))); + HttpPost post = new HttpPost(fcmSendUrl); + post.addHeader("X-GOOG-API-FORMAT-VERSION", "2"); + post.addHeader("X-Firebase-Client", "fire-admin-java/8.0.0"); + post.addHeader("Authorization", "Bearer " + accessToken); + post.setEntity(new StringEntity(DaoSerializer.toJson(msg), StandardCharsets.UTF_8)); + return NullUtils.isNotEmpty(HttpFactory.pool().executeToString(post)); + } +} diff --git a/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/GoogleSSO.java b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/GoogleSSO.java new file mode 100644 index 0000000..58e7604 --- /dev/null +++ b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/GoogleSSO.java @@ -0,0 +1,57 @@ +package com.lanternsoftware.util.cloudservices.google; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.lanternsoftware.util.NullUtils; +import com.lanternsoftware.util.ResourceLoader; +import com.lanternsoftware.util.dao.DaoEntity; +import com.lanternsoftware.util.dao.DaoSerializer; +import com.lanternsoftware.util.http.HttpFactory; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.message.BasicNameValuePair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +public class GoogleSSO { + private static final Logger logger = LoggerFactory.getLogger(GoogleSSO.class); + private final String googleClientId; + private final String googleClientSecret; + + public GoogleSSO(String _credentialsPath) { + DaoEntity google = DaoSerializer.parse(ResourceLoader.loadFileAsString(_credentialsPath)); + googleClientId = DaoSerializer.getString(google, "id"); + googleClientSecret = DaoSerializer.getString(google, "secret"); + } + + public String signin(String _code) { + HttpPost post = new HttpPost("https://oauth2.googleapis.com/token"); + List payload = new ArrayList<>(); + payload.add(new BasicNameValuePair("grant_type", "authorization_code")); + payload.add(new BasicNameValuePair("code", _code)); + payload.add(new BasicNameValuePair("redirect_uri", "https://lanternsoftware.com/console")); + payload.add(new BasicNameValuePair("client_id", googleClientId)); + payload.add(new BasicNameValuePair("client_secret", googleClientSecret)); + UrlEncodedFormEntity entity = new UrlEncodedFormEntity(payload, StandardCharsets.UTF_8); + entity.setContentType("application/x-www-form-urlencoded"); + post.setEntity(entity); + post.setHeader("Content-Type", "application/x-www-form-urlencoded"); + String idToken = DaoSerializer.getString(DaoSerializer.parse(HttpFactory.pool().executeToString(post)), "id_token"); + if (NullUtils.isNotEmpty(idToken)) { + try { + DecodedJWT jwt = JWT.decode(idToken); + return DaoSerializer.getString(DaoSerializer.parse(NullUtils.base64ToString(jwt.getPayload())), "email"); + } catch (Exception _e) { + logger.error("Failed to validate google auth code", _e); + return null; + } + } + logger.error("Failed to validate google auth code"); + return null; + } +} diff --git a/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/dao/FirebaseCredentialsSerializer.java b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/dao/FirebaseCredentialsSerializer.java new file mode 100644 index 0000000..3eead09 --- /dev/null +++ b/util/lantern-util-cloudservices/src/main/java/com/lanternsoftware/util/cloudservices/google/dao/FirebaseCredentialsSerializer.java @@ -0,0 +1,58 @@ +package com.lanternsoftware.util.cloudservices.google.dao; + +import com.lanternsoftware.util.cloudservices.google.FirebaseCredentials; +import com.lanternsoftware.util.dao.AbstractDaoSerializer; +import com.lanternsoftware.util.dao.DaoEntity; +import com.lanternsoftware.util.dao.DaoProxyType; +import com.lanternsoftware.util.dao.DaoSerializer; + +import java.util.Collections; +import java.util.List; + +public class FirebaseCredentialsSerializer extends AbstractDaoSerializer +{ + @Override + public Class getSupportedClass() + { + return FirebaseCredentials.class; + } + + @Override + public List getSupportedProxies() { + return Collections.singletonList(DaoProxyType.MONGO); + } + + @Override + public DaoEntity toDaoEntity(FirebaseCredentials _o) + { + DaoEntity d = new DaoEntity(); + d.put("type", _o.getType()); + d.put("project_id", _o.getProjectId()); + d.put("private_key_id", _o.getPrivateKeyId()); + d.put("private_key", _o.getPrivateKey()); + d.put("client_email", _o.getClientEmail()); + d.put("client_id", _o.getClientId()); + d.put("auth_uri", _o.getAuthUri()); + d.put("token_uri", _o.getTokenUri()); + d.put("auth_provider_x509_cert_url", _o.getAuthProviderX509CertUrl()); + d.put("client_x509_cert_url", _o.getClientX509CertUrl()); + return d; + } + + @Override + public FirebaseCredentials fromDaoEntity(DaoEntity _d) + { + FirebaseCredentials o = new FirebaseCredentials(); + o.setType(DaoSerializer.getString(_d, "type")); + o.setProjectId(DaoSerializer.getString(_d, "project_id")); + o.setPrivateKeyId(DaoSerializer.getString(_d, "private_key_id")); + o.setPrivateKey(DaoSerializer.getString(_d, "private_key")); + o.setClientEmail(DaoSerializer.getString(_d, "client_email")); + o.setClientId(DaoSerializer.getString(_d, "client_id")); + o.setAuthUri(DaoSerializer.getString(_d, "auth_uri")); + o.setTokenUri(DaoSerializer.getString(_d, "token_uri")); + o.setAuthProviderX509CertUrl(DaoSerializer.getString(_d, "auth_provider_x509_cert_url")); + o.setClientX509CertUrl(DaoSerializer.getString(_d, "client_x509_cert_url")); + return o; + } +} \ No newline at end of file diff --git a/util/lantern-util-cloudservices/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer b/util/lantern-util-cloudservices/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer new file mode 100644 index 0000000..611064f --- /dev/null +++ b/util/lantern-util-cloudservices/src/main/resources/META-INF/services/com.lanternsoftware.util.dao.IDaoSerializer @@ -0,0 +1 @@ +com.lanternsoftware.util.cloudservices.google.dao.FirebaseCredentialsSerializer diff --git a/util/lantern-util-common/pom.xml b/util/lantern-util-common/pom.xml index c9ae072..06b02cf 100644 --- a/util/lantern-util-common/pom.xml +++ b/util/lantern-util-common/pom.xml @@ -34,7 +34,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java index 60701d3..c24ebe4 100644 --- a/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java +++ b/util/lantern-util-common/src/main/java/com/lanternsoftware/util/NullUtils.java @@ -1,5 +1,6 @@ package com.lanternsoftware.util; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import java.io.UnsupportedEncodingException; @@ -13,395 +14,379 @@ import java.util.Map; import java.util.Map.Entry; public class NullUtils { - public static boolean isNotEqual(Object a, Object b) { - return !isEqual(a, b); + public static boolean isNotEqual(Object a, Object b) { + return !isEqual(a, b); + } + + public static boolean isEqual(Object a, Object b) { + if (a != null) + return (b != null) && a.equals(b); + return (b == null); + } + + public static > boolean isNotIdentical(T a, T b) { + return !isIdentical(a, b); + } + + public static > boolean isIdentical(T a, T b) { + if (a != null) + return (b != null) && a.isIdentical(b); + return (b == null); + } + + public static boolean isNotEqual(T a, T b, IEquals _equals) { + return !isEqual(a, b, _equals); + } + + public static boolean isEqual(T a, T b, IEquals _equals) { + if (a != null) + return (b != null) && _equals.equals(a, b); + return (b == null); + } + + public static boolean equalsIgnoreCase(String a, String b) { + if (a != null) + return a.equalsIgnoreCase(b); + return (b == null); + } + + public static int length(String _val) { + if (_val == null) + return 0; + return _val.length(); + } + + public static boolean isEmpty(String _sVal) { + return (_sVal == null) || (_sVal.length() == 0); + } + + public static boolean isAnyEmpty(String... _vals) { + if (_vals == null) + return true; + for (String val : _vals) { + if (isEmpty(val)) + return true; + } + return false; + } + + public static boolean isNotEmpty(String _sVal) { + return !isEmpty(_sVal); + } + + public static boolean isAnyNotEmpty(String... _vals) { + if (_vals == null) + return false; + for (String val : _vals) { + if (isNotEmpty(val)) + return true; + } + return false; + } + + public static boolean isAnyNull(Object... _o) { + if ((_o == null) || (_o.length == 0)) + return false; + for (Object o : _o) { + if (o == null) + return true; + } + return false; + } + + public static boolean isOneOf(Object _o, Object... _values) { + if ((_o == null) || (_values == null) || (_values.length == 0)) + return false; + for (Object o : _values) { + if (_o.equals(o)) + return true; + } + return false; + } + + public static String trim(String _val) { + if (_val == null) + return null; + return _val.trim(); + } + + public static String toString(byte[] _arrBytes) { + if (_arrBytes == null) + return null; + try { + return new String(_arrBytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + return null; + } + } + + public static byte[] toByteArray(String _value) { + if (_value == null) + return null; + try { + return _value.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + return null; + } + } + + public static int toInteger(String _value) { + try { + return Integer.valueOf(makeNotNull(_value)); + } catch (NumberFormatException _e) { + return 0; + } + } + + public static long toLong(String _value) { + try { + return Long.valueOf(makeNotNull(_value)); + } catch (NumberFormatException _e) { + return 0; + } + } + + public static double toDouble(String _value) { + try { + return Double.valueOf(makeNotNull(_value)); + } catch (NumberFormatException _e) { + return 0.0; + } + } + + public static float toFloat(String _value) { + try { + return Float.valueOf(makeNotNull(_value)); + } catch (NumberFormatException _e) { + return 0f; + } + } + + public static String urlEncode(String _url) { + try { + return URLEncoder.encode(makeNotNull(_url), "UTF-8"); + } catch (UnsupportedEncodingException e) { + return _url; + } + } + + public static String urlDecode(String _url) { + try { + return URLDecoder.decode(makeNotNull(_url), "UTF-8"); + } catch (UnsupportedEncodingException e) { + return _url; + } + } + + public static String makeNotNull(String _value) { + if (_value != null) + return _value; + return ""; + } + + public static String after(String _value, String _search) { + if (_value == null) + return ""; + int iPos = _value.lastIndexOf(_search); + if (iPos < 0) + return ""; + return iPos < _value.length() - _search.length() ? _value.substring(iPos + _search.length()) : ""; + } + + public static > T toEnum(Class _enumType, String _sValue) { + return toEnum(_enumType, _sValue, null); + } + + public static > T toEnum(Class _enumType, String _sValue, T _default) { + T e = null; + try { + e = Enum.valueOf(_enumType, _sValue); + } catch (Throwable t) { + return _default; + } + return e; + } + + public static > List toEnums(Class _enumType, Collection _values) { + List listEnums = new ArrayList(); + for (String value : CollectionUtils.makeNotNull(_values)) { + T e = toEnum(_enumType, value, null); + if (e != null) + listEnums.add(e); + } + return listEnums; + } + + public static > int compare(T a, T b) { + return compare(a, b, true); + } + + public static > int compare(T a, T b, boolean _bNullsFirst) { + if (a != null) { + if (b != null) + return a.compareTo(b); + else + return _bNullsFirst ? 1 : -1; + } + if (b != null) + return _bNullsFirst ? -1 : 1; + return 0; + } + + public static int min(int... values) { + int iMin = Integer.MAX_VALUE; + for (int value : values) { + if (value < iMin) + iMin = value; + } + return iMin; + } + + public static String[] cleanSplit(String _sValue, String _sRegex) { + if (_sValue == null) + return new String[0]; + return removeEmpties(_sValue.split(_sRegex)); + } + + public static String[] removeEmpties(String[] _arr) { + if (_arr == null) + return new String[0]; + int valid = 0; + for (String s : _arr) { + if (NullUtils.isNotEmpty(s)) + valid++; + } + if (valid == _arr.length) + return _arr; + String[] ret = new String[valid]; + valid = 0; + for (String s : _arr) { + if (NullUtils.isNotEmpty(s)) + ret[valid++] = s; + } + return ret; + } + + public static String wrap(String _input, int _lineLength) { + return wrap(_input, _lineLength, false); + } + + public static String wrap(String _input, int _lineLength, boolean carriageReturn) { + if (_input == null) + return null; + StringBuilder output = new StringBuilder(); + int i = 0; + while (i < _input.length()) { + if ((i + _lineLength) > _input.length()) + output.append(_input.substring(i, _input.length())); + else { + output.append(_input.substring(i, i + _lineLength)); + if (carriageReturn) + output.append("\r"); + output.append("\n"); + } + i += _lineLength; + } + return output.toString(); + } + + public static Class getClass(String _className, Class _superClass) { + try { + return Class.forName(_className).asSubclass(_superClass); + } catch (ClassNotFoundException _e) { + return null; + } + } + + public static String terminateWith(String _value, String _suffix) { + if (_value == null) + return _suffix; + if (_value.endsWith(_suffix)) + return _value; + return _value + _suffix; + } + + public static String toUpperCase(String _value) { + if (_value == null) + return null; + return _value.toUpperCase(); + } + + public static String toLowerCase(String _value) { + if (_value == null) + return null; + return _value.toLowerCase(); + } + + public static Map> parseQueryParams(String _queryString) { + Map> queryParameters = new HashMap<>(); + if (isEmpty(_queryString)) { + return queryParameters; + } + String[] parameters = _queryString.split("&"); + for (String parameter : parameters) { + String[] keyValuePair = parameter.split("="); + if (keyValuePair.length > 1) + CollectionUtils.addToMultiMap(keyValuePair[0], keyValuePair[1], queryParameters); + } + return queryParameters; + } + + public static String toQueryString(Map> _queryParameters) { + StringBuilder queryString = null; + for (Entry> entry : CollectionUtils.makeNotNull(_queryParameters).entrySet()) { + for (String param : CollectionUtils.makeNotNull(entry.getValue())) { + if (NullUtils.isEmpty(param)) + continue; + if (queryString == null) + queryString = new StringBuilder(); + else + queryString.append("&"); + queryString.append(entry.getKey()); + queryString.append("="); + queryString.append(param); + } + } + return queryString == null ? "" : queryString.toString(); + } + + public static String toHex(String _sValue) { + return toHex(toByteArray(_sValue)); + } + + public static String toHexBytes(byte[] _btData) { + List bytes = new ArrayList<>(_btData.length); + for (byte b : _btData) { + bytes.add(String.format("%02X ", b)); + } + return CollectionUtils.delimit(bytes, " "); + } + + public static String toHex(byte[] _btData) { + try { + return new String(Hex.encodeHex(_btData)); + } catch (Exception e) { + return ""; + } + } + + public static byte[] fromHex(String _sValue) { + try { + return Hex.decodeHex(makeNotNull(_sValue).toCharArray()); + } catch (Exception e) { + return null; + } + } + + public static String base64ToString(String _base64) { + return toString(Base64.decodeBase64(_base64)); } - public static boolean isEqual(Object a, Object b) { - if (a != null) - return (b != null) && a.equals(b); - return (b == null); - } - - public static > boolean isNotIdentical(T a, T b) { - return !isIdentical(a, b); - } - - public static > boolean isIdentical(T a, T b) { - if (a != null) - return (b != null) && a.isIdentical(b); - return (b == null); - } - - public static boolean isNotEqual(T a, T b, IEquals _equals) { - return !isEqual(a, b, _equals); - } - - public static boolean isEqual(T a, T b, IEquals _equals) { - if (a != null) - return (b != null) && _equals.equals(a, b); - return (b == null); - } - - public static boolean equalsIgnoreCase(String a, String b) { - if (a != null) - return a.equalsIgnoreCase(b); - return (b == null); - } - - public static int length(String _val) { - if (_val == null) - return 0; - return _val.length(); - } - - public static boolean isEmpty(String _sVal) { - return (_sVal == null) || (_sVal.length() == 0); - } - - public static boolean isAnyEmpty(String... _vals) { - if (_vals == null) - return true; - for (String val : _vals) { - if (isEmpty(val)) - return true; - } - return false; - } - - public static boolean isNotEmpty(String _sVal) { - return !isEmpty(_sVal); - } - - public static boolean isAnyNotEmpty(String... _vals) { - if (_vals == null) - return false; - for (String val : _vals) { - if (isNotEmpty(val)) - return true; - } - return false; - } - - public static boolean isAnyNull(Object... _o) { - if ((_o == null) || (_o.length == 0)) - return false; - for (Object o : _o) { - if (o == null) - return true; - } - return false; - } - - public static boolean isOneOf(Object _o, Object... _values) { - if ((_o == null) || (_values == null) || (_values.length == 0)) - return false; - for (Object o : _values) { - if (_o.equals(o)) - return true; - } - return false; - } - - public static String trim(String _val) { - if (_val == null) - return null; - return _val.trim(); - } - - public static String toString(byte[] _arrBytes) { - if (_arrBytes == null) - return null; - try { - return new String(_arrBytes, "UTF-8"); - } - catch (UnsupportedEncodingException e) { - return null; - } - } - - public static byte[] toByteArray(String _value) { - if (_value == null) - return null; - try { - return _value.getBytes("UTF-8"); - } - catch (UnsupportedEncodingException e) { - return null; - } - } - - public static int toInteger(String _value) { - try { - return Integer.valueOf(makeNotNull(_value)); - } - catch (NumberFormatException _e) { - return 0; - } - } - - public static long toLong(String _value) { - try { - return Long.valueOf(makeNotNull(_value)); - } - catch (NumberFormatException _e) { - return 0; - } - } - - public static double toDouble(String _value) { - try { - return Double.valueOf(makeNotNull(_value)); - } - catch (NumberFormatException _e) { - return 0.0; - } - } - - public static float toFloat(String _value) { - try { - return Float.valueOf(makeNotNull(_value)); - } - catch (NumberFormatException _e) { - return 0f; - } - } - - public static String urlEncode(String _url) { - try { - return URLEncoder.encode(makeNotNull(_url), "UTF-8"); - } - catch (UnsupportedEncodingException e) { - return _url; - } - } - - public static String urlDecode(String _url) { - try { - return URLDecoder.decode(makeNotNull(_url), "UTF-8"); - } - catch (UnsupportedEncodingException e) { - return _url; - } - } - - public static String makeNotNull(String _value) { - if (_value != null) - return _value; - return ""; - } - - public static String after(String _value, String _search) { - if (_value == null) - return ""; - int iPos = _value.lastIndexOf(_search); - if (iPos < 0) - return ""; - return iPos < _value.length() - _search.length() ? _value.substring(iPos + _search.length()) : ""; - } - - public static > T toEnum(Class _enumType, String _sValue) { - return toEnum(_enumType, _sValue, null); - } - - public static > T toEnum(Class _enumType, String _sValue, T _default) { - T e = null; - try { - e = Enum.valueOf(_enumType, _sValue); - } - catch (Throwable t) { - return _default; - } - return e; - } - - public static > List toEnums(Class _enumType, Collection _values) { - List listEnums = new ArrayList(); - for (String value : CollectionUtils.makeNotNull(_values)) { - T e = toEnum(_enumType, value, null); - if (e != null) - listEnums.add(e); - } - return listEnums; - } - - public static > int compare(T a, T b) { - return compare(a, b, true); - } - - public static > int compare(T a, T b, boolean _bNullsFirst) { - if (a != null) { - if (b != null) - return a.compareTo(b); - else - return _bNullsFirst ? 1 : -1; - } - if (b != null) - return _bNullsFirst ? -1 : 1; - return 0; - } - - public static int min(int... values) { - int iMin = Integer.MAX_VALUE; - for (int value : values) { - if (value < iMin) - iMin = value; - } - return iMin; - } - - public static String[] cleanSplit(String _sValue, String _sRegex) { - if (_sValue == null) - return new String[0]; - return removeEmpties(_sValue.split(_sRegex)); - } - - public static String[] removeEmpties(String[] _arr) { - if (_arr == null) - return new String[0]; - int valid = 0; - for (String s : _arr) { - if (NullUtils.isNotEmpty(s)) - valid++; - } - if (valid == _arr.length) - return _arr; - String[] ret = new String[valid]; - valid = 0; - for (String s : _arr) { - if (NullUtils.isNotEmpty(s)) - ret[valid++] = s; - } - return ret; - } - - public static String wrap(String _input, int _lineLength) { - return wrap(_input, _lineLength, false); - } - - public static String wrap(String _input, int _lineLength, boolean carriageReturn) { - if (_input == null) - return null; - StringBuilder output = new StringBuilder(); - int i = 0; - while (i < _input.length()) { - if ((i + _lineLength) > _input.length()) - output.append(_input.substring(i, _input.length())); - else { - output.append(_input.substring(i, i + _lineLength)); - if (carriageReturn) - output.append("\r"); - output.append("\n"); - } - i += _lineLength; - } - return output.toString(); - } - - public static Class getClass(String _className, Class _superClass) { - try { - return Class.forName(_className).asSubclass(_superClass); - } - catch (ClassNotFoundException _e) { - return null; - } - } - - public static String terminateWith(String _value, String _suffix) { - if (_value == null) - return _suffix; - if (_value.endsWith(_suffix)) - return _value; - return _value + _suffix; - } - - public static String toUpperCase(String _value) { - if (_value == null) - return null; - return _value.toUpperCase(); - } - - public static String toLowerCase(String _value) { - if (_value == null) - return null; - return _value.toLowerCase(); - } - - public static Map> parseQueryParams(String _queryString) { - Map> queryParameters = new HashMap<>(); - if (isEmpty(_queryString)) { - return queryParameters; - } - String[] parameters = _queryString.split("&"); - for (String parameter : parameters) { - String[] keyValuePair = parameter.split("="); - if (keyValuePair.length > 1) - CollectionUtils.addToMultiMap(keyValuePair[0], keyValuePair[1], queryParameters); - } - return queryParameters; - } - - public static String toQueryString(Map> _queryParameters) { - StringBuilder queryString = null; - for (Entry> entry : CollectionUtils.makeNotNull(_queryParameters).entrySet()) { - for (String param : CollectionUtils.makeNotNull(entry.getValue())) { - if (NullUtils.isEmpty(param)) - continue; - if (queryString == null) - queryString = new StringBuilder(); - else - queryString.append("&"); - queryString.append(entry.getKey()); - queryString.append("="); - queryString.append(param); - } - } - return queryString == null?"":queryString.toString(); - } - - public static String toHex(String _sValue) - { - return toHex(toByteArray(_sValue)); - } - - public static String toHexBytes(byte[] _btData) - { - List bytes = new ArrayList<>(_btData.length); - for (byte b : _btData) { - bytes.add(String.format("%02X ", b)); - } - return CollectionUtils.delimit(bytes, " "); - } - - public static String toHex(byte[] _btData) - { - try - { - return new String(Hex.encodeHex(_btData)); - } - catch (Exception e) - { - return ""; - } - } - - public static byte[] fromHex(String _sValue) - { - try - { - return Hex.decodeHex(makeNotNull(_sValue).toCharArray()); - } - catch (Exception e) - { - return null; - } - } - - public static int bound(int _value, int _min, int _max) { - if (_value < _min) - return _min; - if (_value > _max) - return _max; - return _value; - } + public static int bound(int _value, int _min, int _max) { + if (_value < _min) + return _min; + if (_value > _max) + return _max; + return _value; + } } diff --git a/util/lantern-util-dao-ephemeral/pom.xml b/util/lantern-util-dao-ephemeral/pom.xml index 29e7a91..4672cd2 100644 --- a/util/lantern-util-dao-ephemeral/pom.xml +++ b/util/lantern-util-dao-ephemeral/pom.xml @@ -29,7 +29,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/util/lantern-util-dao-mongo/pom.xml b/util/lantern-util-dao-mongo/pom.xml index 205eb1f..a9944ee 100644 --- a/util/lantern-util-dao-mongo/pom.xml +++ b/util/lantern-util-dao-mongo/pom.xml @@ -34,7 +34,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/util/lantern-util-dao/pom.xml b/util/lantern-util-dao/pom.xml index bb86f7c..63beacc 100644 --- a/util/lantern-util-dao/pom.xml +++ b/util/lantern-util-dao/pom.xml @@ -29,7 +29,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/util/lantern-util-excel/pom.xml b/util/lantern-util-excel/pom.xml index c7a33fe..b3d866f 100644 --- a/util/lantern-util-excel/pom.xml +++ b/util/lantern-util-excel/pom.xml @@ -30,7 +30,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/util/lantern-util-http/pom.xml b/util/lantern-util-http/pom.xml index 32171b9..7072b82 100644 --- a/util/lantern-util-http/pom.xml +++ b/util/lantern-util-http/pom.xml @@ -39,7 +39,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/util/lantern-util-http/src/main/java/com/lanternsoftware/util/http/HttpFactory.java b/util/lantern-util-http/src/main/java/com/lanternsoftware/util/http/HttpFactory.java new file mode 100644 index 0000000..3c71bb4 --- /dev/null +++ b/util/lantern-util-http/src/main/java/com/lanternsoftware/util/http/HttpFactory.java @@ -0,0 +1,18 @@ +package com.lanternsoftware.util.http; + +public class HttpFactory { + private static final int CONNECTIONS = 10; + private static HttpPool pool; + public static synchronized HttpPool pool() { + if (pool == null) + pool = new HttpPool(CONNECTIONS, CONNECTIONS); + return pool; + } + + public static synchronized void shutdown() { + if (pool != null) { + pool.shutdown(); + pool = null; + } + } +} diff --git a/util/lantern-util-servlet/pom.xml b/util/lantern-util-servlet/pom.xml index 95aee0e..ecbbc96 100644 --- a/util/lantern-util-servlet/pom.xml +++ b/util/lantern-util-servlet/pom.xml @@ -35,7 +35,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 diff --git a/util/pom.xml b/util/pom.xml index a185dbb..9663785 100644 --- a/util/pom.xml +++ b/util/pom.xml @@ -14,6 +14,7 @@ + lantern-util-cloudservices lantern-util-common lantern-util-dao lantern-util-dao-ephemeral diff --git a/zwave/lantern-datamodel-zwave/pom.xml b/zwave/lantern-datamodel-zwave/pom.xml index baf03b0..ce0d14f 100644 --- a/zwave/lantern-datamodel-zwave/pom.xml +++ b/zwave/lantern-datamodel-zwave/pom.xml @@ -28,7 +28,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -48,7 +48,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 package @@ -58,16 +58,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 2.5 - - - true - - - diff --git a/zwave/lantern-service-thermometer/pom.xml b/zwave/lantern-service-thermometer/pom.xml index ee52513..83ea739 100644 --- a/zwave/lantern-service-thermometer/pom.xml +++ b/zwave/lantern-service-thermometer/pom.xml @@ -56,7 +56,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -75,7 +75,7 @@ maven-war-plugin - 2.5 + 3.3.2 diff --git a/zwave/lantern-service-zwave/pom.xml b/zwave/lantern-service-zwave/pom.xml index cf8b537..3e0d7ee 100644 --- a/zwave/lantern-service-zwave/pom.xml +++ b/zwave/lantern-service-zwave/pom.xml @@ -70,7 +70,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -89,7 +89,7 @@ maven-war-plugin - 2.5 + 3.3.2 diff --git a/zwave/lantern-uirt/pom.xml b/zwave/lantern-uirt/pom.xml index 3e4aa2f..71c2612 100644 --- a/zwave/lantern-uirt/pom.xml +++ b/zwave/lantern-uirt/pom.xml @@ -33,7 +33,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -53,7 +53,7 @@ org.apache.maven.plugins maven-source-plugin - 2.4 + 3.2.1 package @@ -63,16 +63,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 2.5 - - - true - - - diff --git a/zwave/lantern-zwave/pom.xml b/zwave/lantern-zwave/pom.xml index a6c5b3e..9d40cb5 100644 --- a/zwave/lantern-zwave/pom.xml +++ b/zwave/lantern-zwave/pom.xml @@ -44,7 +44,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.2 + 3.10.1 @@ -64,7 +64,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.1 + 3.3.0 false