mirror of
https://github.com/zyphlar/LanternPowerMonitor.git
synced 2024-03-08 14:07:47 +00:00
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.
This commit is contained in:
parent
c8319d6369
commit
d7edf3db4a
|
@ -43,7 +43,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -63,7 +63,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
|
|
|
@ -23,14 +23,9 @@
|
|||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.pi4j</groupId>
|
||||
<artifactId>pi4j-core</artifactId>
|
||||
<version>2.2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.pi4j</groupId>
|
||||
<artifactId>pi4j-plugin-pigpio</artifactId>
|
||||
<version>2.2.0-SNAPSHOT</version>
|
||||
<groupId>com.lanternsoftware.pigpio</groupId>
|
||||
<artifactId>lantern-pigpio</artifactId>
|
||||
<version>${pigpio.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.hypfvieh</groupId>
|
||||
|
@ -63,7 +58,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -83,7 +78,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
|
|
|
@ -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<Integer, MCP3008> 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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,6 @@
|
|||
<configuration>
|
||||
<property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>/opt/currentmonitor/log/log.txt</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -63,7 +63,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -73,16 +73,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<index>true</index>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -58,16 +58,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<index>true</index>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -11,44 +11,32 @@
|
|||
<version>1.1.0</version>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client-bom</artifactId>
|
||||
<version>1.33.4</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.currentmonitor</groupId>
|
||||
<artifactId>lantern-dataaccess-currentmonitor</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<version>${cm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>lantern-util-servlet</artifactId>
|
||||
<version>${util.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>lantern-util-cloudservices</artifactId>
|
||||
<version>${util.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>lantern-util-http</artifactId>
|
||||
<version>${util.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.rules</groupId>
|
||||
<artifactId>lantern-service-rules</artifactId>
|
||||
<version>${rules.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax</groupId>
|
||||
<artifactId>javaee-api</artifactId>
|
||||
|
@ -65,6 +53,11 @@
|
|||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.19.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mailjet</groupId>
|
||||
<artifactId>mailjet-client</artifactId>
|
||||
|
@ -81,7 +74,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -100,7 +93,7 @@
|
|||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>3.3.2</version>
|
||||
<configuration>
|
||||
<webResources>
|
||||
<resource>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
68
pigpio/lantern-pigpio/pom.xml
Normal file
68
pigpio/lantern-pigpio/pom.xml
Normal file
|
@ -0,0 +1,68 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>lantern-pigpio</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0.0</version>
|
||||
<name>lantern-pigpio</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lanternsoftware.pigpio</groupId>
|
||||
<artifactId>pigpio</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>lantern-util-common</artifactId>
|
||||
<version>${util.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.29</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<phase>compile</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<optimize>true</optimize>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -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);
|
||||
}
|
|
@ -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<Integer, Spi> 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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
54
pigpio/lantern-pigpio/src/main/native/Makefile
Normal file
54
pigpio/lantern-pigpio/src/main/native/Makefile
Normal file
|
@ -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
|
|
@ -0,0 +1,117 @@
|
|||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pigpio.h>
|
||||
#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;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* 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
|
Binary file not shown.
18
pigpio/pom.xml
Normal file
18
pigpio/pom.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>pom</packaging>
|
||||
<groupId>com.lanternsoftware.pigpio</groupId>
|
||||
<artifactId>pigpio</artifactId>
|
||||
<name>pigpio</name>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lanternsoftware</groupId>
|
||||
<artifactId>LanternPowerMonitor</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>lantern-pigpio</module>
|
||||
</modules>
|
||||
</project>
|
4
pom.xml
4
pom.xml
|
@ -11,14 +11,16 @@
|
|||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<cm.version>1.1.0</cm.version>
|
||||
<util.version>1.0.0</util.version>
|
||||
<pigpio.version>1.0.0</pigpio.version>
|
||||
<rules.version>1.0.0</rules.version>
|
||||
<util.version>1.0.0</util.version>
|
||||
<zw.version>1.0.0</zw.version>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>currentmonitor</module>
|
||||
<module>util</module>
|
||||
<module>pigpio</module>
|
||||
<module>rules</module>
|
||||
<module>zwave</module>
|
||||
</modules>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -63,16 +63,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<index>true</index>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -58,16 +58,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<index>true</index>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -12,28 +12,7 @@
|
|||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client-bom</artifactId>
|
||||
<version>1.32.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.api-client</groupId>
|
||||
<artifactId>google-api-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.firebase</groupId>
|
||||
<artifactId>firebase-admin</artifactId>
|
||||
<version>8.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.rules</groupId>
|
||||
<artifactId>lantern-dataaccess-rules</artifactId>
|
||||
|
@ -49,6 +28,11 @@
|
|||
<artifactId>lantern-util-servlet</artifactId>
|
||||
<version>${util.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>lantern-util-cloudservices</artifactId>
|
||||
<version>${util.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax</groupId>
|
||||
<artifactId>javaee-api</artifactId>
|
||||
|
@ -60,6 +44,12 @@
|
|||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.29</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
|
@ -71,7 +61,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -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<FcmDevice> 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
16
rules/lantern-service-rules/src/test/resources/logback.xml
Normal file
16
rules/lantern-service-rules/src/test/resources/logback.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<property name="log.pattern" value="%date %-5level %logger{0} - %message%n"/>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="com.lanternsoftware" level="DEBUG"/>
|
||||
|
||||
<root level="OFF">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
</configuration>
|
74
util/lantern-util-cloudservices/pom.xml
Normal file
74
util/lantern-util-cloudservices/pom.xml
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>lantern-util-cloudservices</artifactId>
|
||||
<name>lantern-util-cloudservices</name>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.lanternsoftware.util</groupId>
|
||||
<artifactId>util</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>lantern-util-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>lantern-util-dao</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>lantern-util-http</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.19.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>testCompile</goal>
|
||||
</goals>
|
||||
<phase>compile</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<optimize>true</optimize>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -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<String, RSAPublicKey> 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<String> 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<NameValuePair> 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));
|
||||
}
|
||||
}
|
|
@ -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<NameValuePair> 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;
|
||||
}
|
||||
}
|
|
@ -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<FirebaseCredentials>
|
||||
{
|
||||
@Override
|
||||
public Class<FirebaseCredentials> getSupportedClass()
|
||||
{
|
||||
return FirebaseCredentials.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DaoProxyType> 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
com.lanternsoftware.util.cloudservices.google.dao.FirebaseCredentialsSerializer
|
|
@ -34,7 +34,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -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 <T extends IIdentical<T>> boolean isNotIdentical(T a, T b) {
|
||||
return !isIdentical(a, b);
|
||||
}
|
||||
|
||||
public static <T extends IIdentical<T>> boolean isIdentical(T a, T b) {
|
||||
if (a != null)
|
||||
return (b != null) && a.isIdentical(b);
|
||||
return (b == null);
|
||||
}
|
||||
|
||||
public static <T> boolean isNotEqual(T a, T b, IEquals<T> _equals) {
|
||||
return !isEqual(a, b, _equals);
|
||||
}
|
||||
|
||||
public static <T> boolean isEqual(T a, T b, IEquals<T> _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 extends Enum<T>> T toEnum(Class<T> _enumType, String _sValue) {
|
||||
return toEnum(_enumType, _sValue, null);
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> T toEnum(Class<T> _enumType, String _sValue, T _default) {
|
||||
T e = null;
|
||||
try {
|
||||
e = Enum.valueOf(_enumType, _sValue);
|
||||
} catch (Throwable t) {
|
||||
return _default;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> List<T> toEnums(Class<T> _enumType, Collection<String> _values) {
|
||||
List<T> listEnums = new ArrayList<T>();
|
||||
for (String value : CollectionUtils.makeNotNull(_values)) {
|
||||
T e = toEnum(_enumType, value, null);
|
||||
if (e != null)
|
||||
listEnums.add(e);
|
||||
}
|
||||
return listEnums;
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compare(T a, T b) {
|
||||
return compare(a, b, true);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> 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 <T> Class<? extends T> getClass(String _className, Class<T> _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<String, List<String>> parseQueryParams(String _queryString) {
|
||||
Map<String, List<String>> 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<String, List<String>> _queryParameters) {
|
||||
StringBuilder queryString = null;
|
||||
for (Entry<String, List<String>> 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<String> 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 <T extends IIdentical<T>> boolean isNotIdentical(T a, T b) {
|
||||
return !isIdentical(a, b);
|
||||
}
|
||||
|
||||
public static <T extends IIdentical<T>> boolean isIdentical(T a, T b) {
|
||||
if (a != null)
|
||||
return (b != null) && a.isIdentical(b);
|
||||
return (b == null);
|
||||
}
|
||||
|
||||
public static <T> boolean isNotEqual(T a, T b, IEquals<T> _equals) {
|
||||
return !isEqual(a, b, _equals);
|
||||
}
|
||||
|
||||
public static <T> boolean isEqual(T a, T b, IEquals<T> _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 extends Enum<T>> T toEnum(Class<T> _enumType, String _sValue) {
|
||||
return toEnum(_enumType, _sValue, null);
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> T toEnum(Class<T> _enumType, String _sValue, T _default) {
|
||||
T e = null;
|
||||
try {
|
||||
e = Enum.valueOf(_enumType, _sValue);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
return _default;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
public static <T extends Enum<T>> List<T> toEnums(Class<T> _enumType, Collection<String> _values) {
|
||||
List<T> listEnums = new ArrayList<T>();
|
||||
for (String value : CollectionUtils.makeNotNull(_values)) {
|
||||
T e = toEnum(_enumType, value, null);
|
||||
if (e != null)
|
||||
listEnums.add(e);
|
||||
}
|
||||
return listEnums;
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compare(T a, T b) {
|
||||
return compare(a, b, true);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> 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 <T> Class<? extends T> getClass(String _className, Class<T> _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<String, List<String>> parseQueryParams(String _queryString) {
|
||||
Map<String, List<String>> 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<String, List<String>> _queryParameters) {
|
||||
StringBuilder queryString = null;
|
||||
for (Entry<String, List<String>> 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<String> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,7 +35,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>lantern-util-cloudservices</module>
|
||||
<module>lantern-util-common</module>
|
||||
<module>lantern-util-dao</module>
|
||||
<module>lantern-util-dao-ephemeral</module>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -58,16 +58,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<index>true</index>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -75,7 +75,7 @@
|
|||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>3.3.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -89,7 +89,7 @@
|
|||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>3.3.2</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -63,16 +63,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<index>true</index>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.10.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
|
@ -64,7 +64,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
<version>3.3.0</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
|
|
Loading…
Reference in New Issue
Block a user