Initial commit
This commit is contained in:
commit
880e39de2e
511 files changed
+38363
No files matched your search
@@ -0,0 +1,4 @@
|
||||
Portal Common
|
||||
==
|
||||
|
||||
The portal_common module contains classes that are shared between the other modules. Any reusable code that is used in multiple places is placed here.
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<FindBugsFilter xmlns="https://github.com/spotbugs/filter/3.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0_RC6/spotbugs/etc/findbugsfilter.xsd">
|
||||
<Match>
|
||||
<Package name="~.*\.request" />
|
||||
</Match>
|
||||
</FindBugsFilter>
|
||||
@@ -0,0 +1,86 @@
|
||||
<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>
|
||||
|
||||
<parent>
|
||||
<groupId>net.locusworks</groupId>
|
||||
<artifactId>portal</artifactId>
|
||||
<version>1.0.0-RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>portal_common</artifactId>
|
||||
<name>Portal Common Files</name>
|
||||
<description>The common files are used throughout the patch repository project. Code that is used in multiple places are placed in this library for reusability</description>
|
||||
|
||||
<properties>
|
||||
<main.basedir>${project.parent.basedir}</main.basedir>
|
||||
<jackson.version>2.9.4</jackson.version>
|
||||
<leak-preventor.version>2.5.0</leak-preventor.version>
|
||||
<log4j.version>2.9.1</log4j.version>
|
||||
</properties>
|
||||
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>findbugs-maven-plugin</artifactId>
|
||||
<version>${findbugs.version}</version>
|
||||
<configuration>
|
||||
<xmlOutput>true</xmlOutput>
|
||||
<xmlOutputDirectory>target/site/${project.artifactId}</xmlOutputDirectory>
|
||||
<excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<!-- Apache http client -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpmime</artifactId>
|
||||
<version>4.5.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- Database connection pools -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-dbcp2</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.5.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Apache http client -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpmime</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.locusworks</groupId>
|
||||
<artifactId>portal_json</artifactId>
|
||||
<version>${current.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,252 @@
|
||||
package net.locusworks.portal.common;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.dbcp2.ConnectionFactory;
|
||||
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
|
||||
import org.apache.commons.dbcp2.PoolableConnection;
|
||||
import org.apache.commons.dbcp2.PoolableConnectionFactory;
|
||||
import org.apache.commons.dbcp2.PoolingDataSource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.pool2.impl.AbandonedConfig;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import net.locusworks.common.logger.ApplicationLogger;
|
||||
import net.locusworks.common.logger.ApplicationLoggerFactory;
|
||||
import net.locusworks.portal.common.services.ConfigurationService;
|
||||
|
||||
/***
|
||||
* Defines the Portals's database connections
|
||||
* @author Isaac Parenteau
|
||||
*
|
||||
*/
|
||||
@Primary
|
||||
@Component
|
||||
public class PortalDataSource {
|
||||
|
||||
private static ApplicationLogger logger = ApplicationLoggerFactory.getLogger(PortalDataSource.class);
|
||||
|
||||
private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
|
||||
private static final String JNDI_STRING = "jdbc:mysql://%s:%d%s";
|
||||
|
||||
private static Map<String, String> mysqlProperties;
|
||||
static {
|
||||
mysqlProperties = new LinkedHashMap<>();
|
||||
mysqlProperties.put("rewriteBatchedStatements", "true");
|
||||
mysqlProperties.put("zeroDateTimeBehavior", "CONVERT_TO_NULL");
|
||||
mysqlProperties.put("useSSL", "false");
|
||||
mysqlProperties.put("serverTimezone", TimeZone.getDefault().getDisplayName(false, TimeZone.SHORT));
|
||||
}
|
||||
|
||||
private Map<Jndi, DataSource> dataSources = new HashMap<>();
|
||||
|
||||
protected static enum Jndi {
|
||||
PORTAL_USER,
|
||||
PORTAL_ROOT
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public PortalDataSource() {
|
||||
dataSources = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the data source bean
|
||||
* @return the data source bean
|
||||
*/
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return getPortalDataSource();
|
||||
}
|
||||
|
||||
/***
|
||||
* Creates a database connection
|
||||
* This will create a connection and store it in the data pool
|
||||
* which will allow reuse of connections instead of creating new connections every time
|
||||
* @param url URL to the database
|
||||
* @param userName The username for the database
|
||||
* @param password the password for the database
|
||||
* @return A Datasource representing the connection
|
||||
* @throws Exception
|
||||
*/
|
||||
private static DataSource createDataSource(String url, String userName, String password) throws Exception {
|
||||
Class.forName(DRIVER).newInstance();
|
||||
|
||||
Properties props = new Properties();
|
||||
props.setProperty("user", userName);
|
||||
props.setProperty("password", password);
|
||||
|
||||
List<String> params = mysqlProperties
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(prop -> String.format("%s=%s", prop.getKey(), prop.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
url = String.format("%s?%s", url, StringUtils.join(params, "&"));
|
||||
|
||||
//Create a connection factory that the pool will use to create connections
|
||||
ConnectionFactory cf = new DriverManagerConnectionFactory(url, props);
|
||||
//Create the poolable connection factory
|
||||
PoolableConnectionFactory pcf = new PoolableConnectionFactory(cf, null);
|
||||
pcf.setValidationQuery("SELECT 1");
|
||||
pcf.setDefaultAutoCommit(true);
|
||||
|
||||
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
|
||||
poolConfig.setMinIdle(10);
|
||||
poolConfig.setMaxTotal(100);
|
||||
|
||||
AbandonedConfig abandonConfig = new AbandonedConfig();
|
||||
abandonConfig.setRemoveAbandonedTimeout(60);
|
||||
abandonConfig.setLogAbandoned(false);
|
||||
abandonConfig.setRemoveAbandonedOnBorrow(true);
|
||||
abandonConfig.setRemoveAbandonedOnMaintenance(true);
|
||||
|
||||
//Create the pool of connections
|
||||
GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(pcf, poolConfig);
|
||||
connectionPool.setTestOnBorrow(true);
|
||||
connectionPool.setTestWhileIdle(true);
|
||||
connectionPool.setTimeBetweenEvictionRunsMillis(10000);
|
||||
connectionPool.setMinEvictableIdleTimeMillis(1000);
|
||||
connectionPool.setAbandonedConfig(abandonConfig);
|
||||
pcf.setPool(connectionPool);
|
||||
|
||||
//Pooling data source itself
|
||||
PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a datasouce from the JNDI type
|
||||
* @param jndi Root or User JNDI
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private DataSource createDataSource(Jndi jndi) throws Exception {
|
||||
|
||||
if (dataSources.containsKey(jndi)) {
|
||||
return dataSources.get(jndi);
|
||||
}
|
||||
|
||||
String tail = null;
|
||||
boolean isRoot = false;
|
||||
switch (jndi) {
|
||||
case PORTAL_ROOT:
|
||||
tail = "";
|
||||
isRoot = true;
|
||||
break;
|
||||
case PORTAL_USER:
|
||||
tail = "/portal";
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Unknown data source specifier: " + jndi);
|
||||
}
|
||||
|
||||
String userName = isRoot ? configurationService.getDatabaseRootUsername() : configurationService.getDatabaseUsername();
|
||||
String passwd = isRoot? configurationService.getDatabaseRootPassword() : configurationService.getDatabasePassword();
|
||||
|
||||
String url = String.format(JNDI_STRING, configurationService.getDatabaseHost(), configurationService.getDatabasePort(), tail);
|
||||
|
||||
dataSources.put(jndi, createDataSource(url, userName, passwd));
|
||||
|
||||
return dataSources.get(jndi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the datasource
|
||||
* @param jndiName name of the data source to retrieve
|
||||
* @return
|
||||
*/
|
||||
private DataSource getDataSource(Jndi jndiName) {
|
||||
// locate the DataSource
|
||||
DataSource ds = null;
|
||||
try {
|
||||
ds = dataSources.get(jndiName);
|
||||
if (ds == null) {
|
||||
logger.info("JNDI %s not found. Creating it", jndiName.toString());
|
||||
// Get the data source from initial context or by building our own pooling data source
|
||||
ds = createDataSource(jndiName);
|
||||
dataSources.put(jndiName, ds);
|
||||
} else {
|
||||
logger.info("Loading JNDI %s", jndiName.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to get datasource", e);
|
||||
}
|
||||
return ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the normal data source that is used for the portal application
|
||||
* @return the user data source
|
||||
*/
|
||||
public DataSource getPortalDataSource() {
|
||||
return getDataSource(PortalDataSource.Jndi.PORTAL_USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database root data source.
|
||||
* This data source is only used to do the migrations then closed
|
||||
* @return the root data source
|
||||
*/
|
||||
public DataSource getPortalRootDataSource() {
|
||||
return getDataSource(PortalDataSource.Jndi.PORTAL_ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the root data source once it is no longer necessary.
|
||||
*/
|
||||
public void closeRootDataSource() {
|
||||
DataSource ds = dataSources.get(PortalDataSource.Jndi.PORTAL_ROOT);
|
||||
try {
|
||||
if (ds != null) {
|
||||
if (ds instanceof PoolingDataSource<?>) {
|
||||
((PoolingDataSource<?>)ds).close();
|
||||
} else {
|
||||
ds.getConnection().close();
|
||||
}
|
||||
dataSources.remove(PortalDataSource.Jndi.PORTAL_ROOT);
|
||||
}
|
||||
} catch (Exception e) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the data source connections when the server shots down
|
||||
*/
|
||||
public void closeDataSources() {
|
||||
for (Iterator<Map.Entry<Jndi, DataSource>> it = dataSources.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<Jndi, DataSource> ds = it.next();
|
||||
try {
|
||||
logger.info("Closing datasource " + ds.getKey());
|
||||
DataSource dataSource = ds.getValue();
|
||||
if (dataSource instanceof PoolingDataSource<?>) {
|
||||
((PoolingDataSource<?>)dataSource).close();
|
||||
} else {
|
||||
dataSource.getConnection().close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.error("Unable to close datasource %s -> %s", ds.getKey(), ex.getMessage());
|
||||
} finally {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package net.locusworks.portal.common.enums;
|
||||
|
||||
/**
|
||||
* Enumeration specifying the allowed configuration values
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum Configuration {
|
||||
DB_ROOT_USER("dbRootUser"),
|
||||
DB_ROOT_PASSWORD("dbRootPassword"),
|
||||
DB_USER("dbUsername"),
|
||||
DB_PASSWORD("dbPassword"),
|
||||
DB_HOST("dbHost"),
|
||||
DB_PORT("dbPort"),
|
||||
USER_EXPIRATION_DAYS("userExpirationDays"),
|
||||
CA_CERT_FILE("caCertFile"),
|
||||
CA_CERT_PASSWORD("caCertPassword"),
|
||||
AES_SEED_FILE("aesSeedFile"),
|
||||
LOG_LEVEL("logLevel");
|
||||
|
||||
private String value;
|
||||
|
||||
private Configuration(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value of the enumeration
|
||||
* @return value
|
||||
*/
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the configuration is of a certain value
|
||||
* @param confTypes types to check against
|
||||
* @return true if the current configuration is of a certain enumeration, false otherwise
|
||||
*/
|
||||
public boolean is(Configuration... confTypes) {
|
||||
for (Configuration confType : confTypes) {
|
||||
if (this == confType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the configuration is not of a certain value
|
||||
* @param confTypes Types to check against
|
||||
* @return true if the current configuration is not of a certain enuermation, false otherwise
|
||||
*/
|
||||
public boolean isNot(Configuration... confTypes) {
|
||||
return !is(confTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a specific enumeration
|
||||
* @param value Value to find
|
||||
* @return the found enumeration or null if nothing is found
|
||||
*/
|
||||
public static Configuration findEnum(String value) {
|
||||
for (Configuration conf: values()) {
|
||||
if (conf.getValue().equalsIgnoreCase(value)) {
|
||||
return conf;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a specific value is in a set of configuration types
|
||||
* @param value Value to look for
|
||||
* @param confTypes types to compare against
|
||||
* @return true if the string value is in a certain set of configuration enumerations, false otherwise
|
||||
*/
|
||||
public static boolean in(String value, Configuration... confTypes) {
|
||||
Configuration ft = findEnum(value);
|
||||
if (ft == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Configuration confType : confTypes) {
|
||||
if (ft == confType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a specific value is not in a set of configuration types
|
||||
* @param value Value to look for
|
||||
* @param confTypes types to compare against
|
||||
* @return true if the string value is not in a certain set of configuration enumerations, false otherwise
|
||||
*/
|
||||
public static boolean notIn(String value, Configuration... confTypes) {
|
||||
return !in(value, confTypes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package net.locusworks.portal.common.enums;
|
||||
|
||||
/**
|
||||
* Enumeration specifying the allowed credential types
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum CredentialType {
|
||||
SSH,
|
||||
PASSWD;
|
||||
|
||||
/**
|
||||
* Checks to see if the credential type is of a certain value
|
||||
* @param credentialTypes types to check against
|
||||
* @return true if the current credential type is of a certain enumeration, false otherwise
|
||||
*/
|
||||
public boolean is(CredentialType... credentialTypes) {
|
||||
for (CredentialType credType : credentialTypes) {
|
||||
if (this == credType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the credential type based off the string value
|
||||
* @param value value to check
|
||||
* @return the credential type if one is found or null
|
||||
*/
|
||||
public static CredentialType getEnum(String value) {
|
||||
for (CredentialType type : values()) {
|
||||
if (type.toString().equalsIgnoreCase(value)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a specific value is in a set of credential types
|
||||
* @param value Value to look for
|
||||
* @param credentialTypes types to compare against
|
||||
* @return true if the string value is in a certain set of credential types enumerations, false otherwise
|
||||
*/
|
||||
public static boolean in(String value, CredentialType... credentialTypes) {
|
||||
CredentialType ft = getEnum(value);
|
||||
if (ft == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (CredentialType freqType : credentialTypes) {
|
||||
if (ft == freqType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a specific value is not in a set of credential types
|
||||
* @param value Value to look for
|
||||
* @param credentialTypes types to compare against
|
||||
* @return true if the string value is not in a certain set of credential types enumerations, false otherwise
|
||||
*/
|
||||
public static boolean notIn(String value, CredentialType... credentialTypes) {
|
||||
return !in(value, credentialTypes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package net.locusworks.portal.common.enums;
|
||||
|
||||
/**
|
||||
* Enumeration specifying the different types of allowed events
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum EventType {
|
||||
LOGIN,
|
||||
LOGOUT,
|
||||
USER_ADDED,
|
||||
USER_EDITED,
|
||||
USER_DELETED,
|
||||
CREDENTIALS_ADDED,
|
||||
CREDENTIALS_REMOVED,
|
||||
REPOSITORY_ADDED,
|
||||
REPOSITORY_PULL,
|
||||
REPOSITORY_DELETED,
|
||||
SCRIPT_ADDED,
|
||||
SCRIPT_EDITED,
|
||||
SCRIPT_DELETED,
|
||||
SCRIPT_SCHEDULE_DELETED,
|
||||
ENVVAR_ADDED,
|
||||
ENVVAR_EDITED,
|
||||
ENVVAR_DELETED,
|
||||
SCRIPT_RUN,
|
||||
SCRIPT_END,
|
||||
SCRIPT_ERROR,
|
||||
SSH_RUN,
|
||||
SSH_END,
|
||||
SSH_ERROR,
|
||||
SCP_RUN,
|
||||
SCP_END,
|
||||
SCP_ERROR,
|
||||
LOGS_PURGED,
|
||||
HASH_TYPE_UPDATED,
|
||||
CONFIGURATION_UPDATED,
|
||||
PERMISSIONS_CHANGED,
|
||||
PERMISSIONS_DELETED,
|
||||
DIRECTORY_PERMISSIONS_CHANGED,
|
||||
DIRECTORY_PERMISSIONS_REMOVED,
|
||||
FILE_DOWNLOADED,
|
||||
FILE_DELETED,
|
||||
EMAIL_TEMPLATED_ADDED,
|
||||
EMAIL_TEMPLATED_EDITED,
|
||||
EMAIL_TEMPLATED_DELETED,
|
||||
SMTP_CONFIG_CHANGED,
|
||||
MESSAGE,
|
||||
EXCEPTION;
|
||||
|
||||
public String getValue() {
|
||||
//Returns the enum type with the underscores replaced with spaces
|
||||
return this.toString().replace("_", " ").trim().toUpperCase();
|
||||
}
|
||||
|
||||
public static EventType getEnum(String value) {
|
||||
for (EventType type : values()) {
|
||||
if (type.getValue().equalsIgnoreCase(value)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No EventType found for value of: " + value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package net.locusworks.portal.common.enums;
|
||||
|
||||
/**
|
||||
* Enumeration containing the frequency types allowed for scheduling events
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum FrequencyType {
|
||||
NOW,
|
||||
HOURLY,
|
||||
DAILY,
|
||||
WEEKLY,
|
||||
MONTHLY,
|
||||
YEARLY,
|
||||
SPECIFIC,
|
||||
TRIGGERED;
|
||||
|
||||
/**
|
||||
* Get a frequency type by string value
|
||||
* @param value frequency type to check for
|
||||
* @return frequencyType if found; null otherwise
|
||||
*/
|
||||
public static FrequencyType getEnum(String value) {
|
||||
for (FrequencyType type : values()) {
|
||||
if (type.toString().equalsIgnoreCase(value)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks to see if a string value is in a certain set of frequency types
|
||||
* @param value Value to check
|
||||
* @param frequencyTypes frequency types to check against
|
||||
* @return true if found within the set, false otherwise
|
||||
*/
|
||||
public static boolean in(String value, FrequencyType... frequencyTypes) {
|
||||
FrequencyType ft = getEnum(value);
|
||||
if (ft == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (FrequencyType freqType : frequencyTypes) {
|
||||
if (ft == freqType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks to see if a string value is not in a certain set of frequency types
|
||||
* @param value Value to check
|
||||
* @param frequencyTypes frequency types to check against
|
||||
* @return false if found within the set, true otherwise
|
||||
*/
|
||||
public static boolean notIn(String value, FrequencyType... frequencyTypes) {
|
||||
return !in(value, frequencyTypes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.locusworks.portal.common.enums;
|
||||
|
||||
/**
|
||||
* Enumeration specifying the allowed permissions
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public enum PermissionType {
|
||||
VIEW_SCRIPT_TAB,
|
||||
VIEW_GIT_TAB,
|
||||
VIEW_USER_TAB,
|
||||
VIEW_CREDS_TAB,
|
||||
VIEW_LOG_TAB,
|
||||
VIEW_PERMISSION_TAB,
|
||||
VIEW_EMAIL_TAB,
|
||||
VIEW_ENV_VARS_TAB,
|
||||
VIEW_CONFIG,
|
||||
CHANGE_CONFIG,
|
||||
VIEW_SMTP_CONFIG,
|
||||
EDIT_SMTP_CONFIG,
|
||||
VIEW_HASH_TYPES,
|
||||
CHANGE_HASH_TYPES,
|
||||
ADD_USERS,
|
||||
DELETE_USERS,
|
||||
PURGE_LOGS,
|
||||
ADD_PERMS,
|
||||
DELETE_PERMS,
|
||||
ADD_CREDENTIALS,
|
||||
DELETE_CREDENTIALS,
|
||||
ADD_GIT_REPO,
|
||||
PULL_GIT_REPO,
|
||||
DELETE_GIT_REPO,
|
||||
ADD_EMAIL,
|
||||
DELETE_EMAIL,
|
||||
RUN_SCRIPT,
|
||||
ADD_SCRIPT,
|
||||
DELETE_SCRIPT,
|
||||
VIEW_SCRIPT_SCHED_STATUS,
|
||||
DELETE_SCRIPT_SCHED_STATUS,
|
||||
ADD_ENV_VARS,
|
||||
DELETE_ENV_VARS,
|
||||
VIEW_ENV_VARS,
|
||||
VIEW_LOG_LEVELS,
|
||||
CHANGE_LOG_LEVELS,
|
||||
DELETE_FILE,
|
||||
UPDATE_SEED_VALUE
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.locusworks.portal.common.enums;
|
||||
|
||||
/**
|
||||
* Enumeration for the allowed script types when creating a task
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum ScriptType {
|
||||
LOCAL,
|
||||
REMOTE,
|
||||
SCP,
|
||||
NULL;
|
||||
|
||||
/**
|
||||
* Get a script type based off from string value
|
||||
* @param value value to check
|
||||
* @return script type if the value is found. False otherwise
|
||||
*/
|
||||
public static ScriptType getEnum(String value) {
|
||||
for (ScriptType type : values()) {
|
||||
if (type.toString().equalsIgnoreCase(value)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return ScriptType.NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.locusworks.portal.common.enums;
|
||||
|
||||
/**
|
||||
* Enumeration specifying the allowed trigger types
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*
|
||||
*/
|
||||
public enum TriggerType {
|
||||
APP_LOGS_UPDATED,
|
||||
APP_LOGS_PURGED,
|
||||
SCRIPT_COMPLETED,
|
||||
SCRIPT_DELETED,
|
||||
SCRIPT_ADDED,
|
||||
SCRIPT_UPDATED,
|
||||
SCRIPT_SCHEDULE_DELETED,
|
||||
USER_ADDED,
|
||||
USER_DELETED,
|
||||
HASH_TYPES_CHANGED,
|
||||
PERMISSIONS_DELETED,
|
||||
PERMISSIONS_CHANGED,
|
||||
PERMISSIONS_UPDATED,
|
||||
PERMISSIONS_ADDED,
|
||||
FILE_DELETED,
|
||||
ENV_VARS_ADDED,
|
||||
ENV_VARS_DELETED,
|
||||
EMAIL_TEMPLATE_UPDATED,
|
||||
EMAIL_TEMPLATE_DELETED,
|
||||
SMTP_CONFIG_UPDATED,
|
||||
SEED_UPDATED
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package net.locusworks.portal.common.exceptions;
|
||||
|
||||
import net.locusworks.common.exceptions.ApplicationException;
|
||||
|
||||
/***
|
||||
* Custom exception class for the portal program
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public class PortalException extends ApplicationException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Exception is thrown when there is no file found with a given file name
|
||||
* @param fileName The file name of the file trying to be located
|
||||
* @return no such file error message
|
||||
*/
|
||||
public static PortalException noSuchFile(String fileName) {
|
||||
return new PortalException(9010, String.format("No such file found for %s", fileName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when a file is unable to be deleted
|
||||
* @param filename Name of the file that couldn't be deleted
|
||||
* @return unable to delete file error message
|
||||
*/
|
||||
public static PortalException unableToDeleteFile(String filename) {
|
||||
return new PortalException(9010, String.format("Unable to delete file %s. Please check permissions", filename));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the PortalException
|
||||
* @param code error code
|
||||
* @param message error message
|
||||
*/
|
||||
private PortalException(int code, Exception ex) {
|
||||
super(code, ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the PortalException
|
||||
* @param code error code
|
||||
* @param message error message
|
||||
*/
|
||||
private PortalException(int code, String message) {
|
||||
super(code, message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package net.locusworks.portal.common.http;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import net.locusworks.common.logger.ApplicationLogger;
|
||||
import net.locusworks.common.logger.ApplicationLoggerFactory;
|
||||
|
||||
/**
|
||||
* Class to handle http(s) connections
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public class HttpClientHelper {
|
||||
|
||||
private static ApplicationLogger logger = ApplicationLoggerFactory.getLogger(HttpClientHelper.class);
|
||||
|
||||
public enum HttpSchema {
|
||||
HTTP,
|
||||
HTTPS;
|
||||
|
||||
public static HttpSchema findEnum(String value) {
|
||||
for (HttpSchema schema : values()) {
|
||||
if (value.equalsIgnoreCase(schema.toString())) {
|
||||
return schema;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String[] TLS = new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"};
|
||||
|
||||
private HttpClient client;
|
||||
private String baseUrl;
|
||||
|
||||
/**
|
||||
* Constructor to handle http connection
|
||||
* @param protocol protocol to use (http or https)
|
||||
* @param host the host url
|
||||
* @param port the host port
|
||||
* @throws Exception exception
|
||||
*/
|
||||
public HttpClientHelper(String protocol, String host, String port) throws Exception {
|
||||
HttpSchema schema = HttpSchema.findEnum(protocol);
|
||||
if (schema == null) {
|
||||
throw new Exception("Unable to find http schema of " + protocol);
|
||||
}
|
||||
this.baseUrl = String.format("%s://%s:%s", schema.toString().toLowerCase(), host, port);
|
||||
this.client = createClient(schema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a http client
|
||||
* @param schema Schema to connect via (HTTP or HTTPS)
|
||||
* @return newly created http client
|
||||
* @throws Exception thrown when the client can't be created
|
||||
*/
|
||||
private HttpClient createClient(HttpSchema schema) throws Exception {
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
|
||||
if (schema == HttpSchema.HTTP) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
//Trust all ssl certificates
|
||||
TrustManager[] trustAllCerts = new TrustManager[] {
|
||||
new X509TrustManager() {
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() { return null; }
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { }
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { }
|
||||
}
|
||||
};
|
||||
|
||||
//Setup the ssl instance using tls
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, trustAllCerts, new SecureRandom());
|
||||
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, TLS, null, new HostnameVerifier() {
|
||||
@Override
|
||||
public boolean verify(String hostname, SSLSession session) { return true; }
|
||||
});
|
||||
|
||||
builder = builder.setSSLSocketFactory(sslsf);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the http GET response code
|
||||
* @param endpoint endpoint to get the response from
|
||||
* @return responseCode
|
||||
* @throws Exception general exception
|
||||
*/
|
||||
public Integer getGetResponseCode(String endpoint) throws Exception {
|
||||
String url = this.baseUrl + endpoint;
|
||||
|
||||
HttpResponse response = this.client.execute(new HttpGet(url));
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
|
||||
String responseString = EntityUtils.toString(entity);
|
||||
|
||||
logger.info("Response from stomp: " + responseString);
|
||||
|
||||
Integer responseCode = response.getStatusLine().getStatusCode();
|
||||
|
||||
EntityUtils.consume(entity);
|
||||
|
||||
return responseCode;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package net.locusworks.portal.common.services;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import net.locusworks.common.crypto.AES;
|
||||
import net.locusworks.common.utils.Utils;
|
||||
import net.locusworks.portal.common.triggers.SeedTrigger;
|
||||
|
||||
import static net.locusworks.common.Charsets.UTF_8;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Service to handle AES encryption
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
@Service
|
||||
public class AESService implements ApplicationListener<SeedTrigger>{
|
||||
|
||||
private static final String PORTAL_AES_SEED = "PORTAL_AES_SEED";
|
||||
|
||||
private static final String DEFAULT_SEED = "portal.tomcat";
|
||||
|
||||
private String seedLoc;
|
||||
|
||||
private AES aes;
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService confService;
|
||||
|
||||
/**
|
||||
* Initialize the aes engine by loading the seed file.
|
||||
* This file is needed to decrypt the aes.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
try {
|
||||
confService.init(); //initialize our conf file to pick up the latest changes if any
|
||||
//Check to see if the environment variable is set first
|
||||
seedLoc = System.getProperty(PORTAL_AES_SEED) == null ? System.getenv(PORTAL_AES_SEED) : System.getProperty(PORTAL_AES_SEED);
|
||||
if (seedLoc == null) {
|
||||
//If it can't find it in the environment variable load it from the properties file
|
||||
seedLoc = confService.getAesSeedFile();
|
||||
}
|
||||
if (seedLoc == null) {
|
||||
throw new RuntimeException("Seed location is not set... unable to continue");
|
||||
}
|
||||
File seedFile = new File(seedLoc);
|
||||
if (!seedFile.exists()) {
|
||||
try(BufferedReader br = getReader()) {
|
||||
StringBuilder seeder = new StringBuilder();
|
||||
while(br.ready()) {
|
||||
seeder.append(br.readLine());
|
||||
}
|
||||
saveSeed(seeder.toString());
|
||||
}
|
||||
seedFile = new File(seedLoc);
|
||||
if (!seedFile.canRead()) {
|
||||
throw new IOException("Unable to read file");
|
||||
}
|
||||
}
|
||||
|
||||
String seed = IOUtils.toString(new FileInputStream(seedFile), UTF_8).trim();
|
||||
aes = AES.createInstance(seed);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to read file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedReader getReader() throws IOException {
|
||||
InputStream is = this.getClass().getResourceAsStream(DEFAULT_SEED);
|
||||
if (is == null) {
|
||||
is = this.getClass().getClassLoader().getResourceAsStream(DEFAULT_SEED);
|
||||
}
|
||||
if (is == null) {
|
||||
throw new IOException("Unable to read default seed file from resources");
|
||||
}
|
||||
return new BufferedReader(new InputStreamReader(is, UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a string
|
||||
* @param plainText string to encrypt
|
||||
* @return encrypted string
|
||||
*/
|
||||
public String encrypt(String plainText) {
|
||||
return aes.encrypt(plainText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a byte array
|
||||
* @param plainText the byte array to encrypt
|
||||
* @return encrypted string
|
||||
*/
|
||||
public byte[] encrypt(byte[] plainText) {
|
||||
return encrypt(new String(plainText, UTF_8)).getBytes(UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt an ecnrypted byte array
|
||||
* @param cypherBytes byte array to decrypt
|
||||
* @return decrypted string
|
||||
*/
|
||||
public String decrypt(byte[] cypherBytes) {
|
||||
return decrypt(new String(cypherBytes, UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt an encrypted string
|
||||
* @param cypherText the encrypted string to decrypt
|
||||
* @return decrypted string
|
||||
*/
|
||||
public String decrypt(String cypherText) {
|
||||
return aes.decrypt(cypherText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the encryption value
|
||||
* @param oldEncryptedValue the old encryption value
|
||||
* @param newSeed the new seed to set the value too
|
||||
* @return new encryption value
|
||||
*/
|
||||
public String changeEncryptionValue(String oldEncryptedValue, String newSeed) {
|
||||
String oldValue = decrypt(oldEncryptedValue);
|
||||
String newValue = AES.createInstance(newSeed).encrypt(oldValue);
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public String changeEncryptionValue(byte[] oldValue, String newSeed) {
|
||||
return changeEncryptionValue(new String(oldValue, UTF_8), newSeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the seed file with the new seed. <br/>
|
||||
* <b>Warning:</b> once the seed has changed all encrypted values that
|
||||
* were encrypted with the previous seed will no longer decrypt.
|
||||
* Make sure to write a service that will decrypt all the previous values
|
||||
* then encrypt with new seed
|
||||
* @param newSeed the new seed to use
|
||||
* @throws IOException occurs when the seed can't be written
|
||||
*/
|
||||
public void saveSeed(String newSeed) throws IOException {
|
||||
File seedFile = new File(seedLoc);
|
||||
if (seedFile.exists() && (!seedFile.isFile() || !seedFile.canRead())) {
|
||||
throw new IOException("Unable to read or locate file");
|
||||
}
|
||||
try(FileWriter fw = new FileWriter(seedFile, false)) {
|
||||
fw.write(newSeed);
|
||||
fw.flush();
|
||||
}
|
||||
|
||||
try {
|
||||
//Set the file permission will throw UnsupportedOperationException if on windows machine
|
||||
//Can ignore the exception
|
||||
Set<PosixFilePermission> perms = Utils.toSet(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE);
|
||||
Files.setPosixFilePermissions(seedFile.toPath(), perms);
|
||||
} catch (UnsupportedOperationException ex) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(SeedTrigger event) {
|
||||
String seed = event.getSeed();
|
||||
this.aes.setSeed(seed);
|
||||
}
|
||||
}
|
||||
+420
@@ -0,0 +1,420 @@
|
||||
package net.locusworks.portal.common.services;
|
||||
|
||||
import static net.locusworks.portal.common.utils.Constants.PROPERTIES_FILE;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import net.locusworks.common.configuration.PropertiesManager;
|
||||
import net.locusworks.common.logger.ApplicationLogger;
|
||||
import net.locusworks.common.logger.ApplicationLoggerFactory;
|
||||
import net.locusworks.portal.common.enums.Configuration;
|
||||
import net.locusworks.portal.common.exceptions.PortalException;
|
||||
import net.locusworks.portal.json.ConfigurationRequest;
|
||||
|
||||
/**
|
||||
* Configuration Service class that reads the conf file
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
@Service
|
||||
public final class ConfigurationService {
|
||||
|
||||
private Properties configuration;
|
||||
private Properties defaults = null;
|
||||
private File portalConf = null;
|
||||
private String keyDir = null;
|
||||
private long lastModified = 0;
|
||||
|
||||
private static final String DB_ROOT_USER_PROPERTY = "DB_ROOT_USER";
|
||||
private static final String DB_ROOT_PASSWD_ENV = "DB_ROOT_PASSWD";
|
||||
|
||||
private static ApplicationLogger logger = ApplicationLoggerFactory.getLogger(ConfigurationService.class);
|
||||
|
||||
@Autowired
|
||||
private AESService aesService;
|
||||
|
||||
/**
|
||||
* Initialize the configuration service
|
||||
* This happens during server start up
|
||||
* @throws IOException If the file cannot be read
|
||||
* @throws Exception any other exception thrown
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() throws IOException, Exception {
|
||||
|
||||
// load defaults when the webapp loads
|
||||
try {
|
||||
defaults = PropertiesManager.loadConfiguration(this.getClass(), PROPERTIES_FILE);
|
||||
} catch (IOException ex) {
|
||||
logger.error(String.format("Failed to load default %s: %s", PROPERTIES_FILE, ex.getMessage()));
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// create portalConf File object
|
||||
portalConf = new File(String.format("%s/conf/%s", System.getProperty("catalina.base"), PROPERTIES_FILE));
|
||||
|
||||
//Create a temporary key directory
|
||||
keyDir = String.format("%s/keys", System.getProperty("catalina.base"));
|
||||
File keyDirFile = new File(keyDir);
|
||||
if (!keyDirFile.exists()) {
|
||||
try {
|
||||
keyDirFile.mkdirs();
|
||||
} catch (Exception ex) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
// initial config load
|
||||
loadConf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the configuration file
|
||||
*/
|
||||
private void loadConf() {
|
||||
|
||||
// load the active config file
|
||||
// ignore read error, we can continue with an empty configuration map
|
||||
// and all default items will be added below and the file created
|
||||
logger.info("Loading config file: " + portalConf);
|
||||
try {
|
||||
configuration = PropertiesManager.loadConfiguration(portalConf);
|
||||
} catch (Exception e) {
|
||||
logger.info("Config file: " + portalConf + " will be created from template");
|
||||
configuration = new Properties();
|
||||
}
|
||||
|
||||
Map<String, String> results = PropertiesManager.addConfiguration(configuration, defaults);
|
||||
boolean changed = !results.isEmpty();
|
||||
if (!results.isEmpty()) {
|
||||
logger.info(results, new StringBuilder("Added new configuration items:%n"));
|
||||
}
|
||||
|
||||
results = PropertiesManager.removeConfiguration(configuration, defaults);
|
||||
changed |= !results.isEmpty();
|
||||
if (!results.isEmpty()) {
|
||||
logger.info(results, new StringBuilder("Removed unused configuration items:%n"));
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
PropertiesManager.saveConfiguration(configuration, portalConf, "Patch Repository properties file");
|
||||
}
|
||||
|
||||
lastModified = portalConf.lastModified();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the configuration values to file
|
||||
* @param confs Configuration property values to save
|
||||
* @throws Exception general exception
|
||||
*/
|
||||
public void saveToConf(Properties confs) throws Exception {
|
||||
PropertiesManager.saveConfiguration(confs, portalConf, "Patch Repository properties file");
|
||||
logger.info("Saved config file: " + portalConf + ", " + confs.size() + " entries");
|
||||
loadConf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database root user name.
|
||||
* It first checks the catalina.properties file for the root user
|
||||
* then checks the patchrepo.properties file
|
||||
* @return root database username
|
||||
*/
|
||||
public String getDatabaseRootUsername() {
|
||||
String rootUser = System.getProperty(DB_ROOT_USER_PROPERTY);
|
||||
return rootUser != null ? rootUser : configuration.getProperty(Configuration.DB_ROOT_USER.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database root user password
|
||||
* It first checks the catalina.properties file for the password
|
||||
* then checks the patchrepo.properties file.
|
||||
* The password must be encrypted in both locations
|
||||
* @return root database password
|
||||
*/
|
||||
public String getDatabaseRootPassword() {
|
||||
String rootPassword = System.getProperty(DB_ROOT_PASSWD_ENV);
|
||||
String dbPasswd = rootPassword == null ? configuration.getProperty(Configuration.DB_ROOT_PASSWORD.getValue()) : rootPassword;
|
||||
try {
|
||||
return aesService.decrypt(dbPasswd);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Unable to get db root password " + ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the standard database user name
|
||||
* @return portal database username
|
||||
*/
|
||||
public String getDatabaseUsername() {
|
||||
return configuration.getProperty(Configuration.DB_USER.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the standard database password.
|
||||
* The password is encrypted in the properties file
|
||||
* @return patchrepo database password
|
||||
*/
|
||||
public String getDatabasePassword() {
|
||||
String dbPasswd = configuration.getProperty(Configuration.DB_PASSWORD.getValue());
|
||||
try {
|
||||
return aesService.decrypt(dbPasswd);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Unable to get db password " + ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database host url
|
||||
* @return database host url
|
||||
*/
|
||||
public String getDatabaseHost() {
|
||||
return configuration.getProperty(Configuration.DB_HOST.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database host port
|
||||
* @return the database port
|
||||
*/
|
||||
public Integer getDatabasePort() {
|
||||
return Integer.parseInt(configuration.getProperty(Configuration.DB_PORT.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default number of days until a new user expires
|
||||
* @return number of days after creation the user will expire by default
|
||||
*/
|
||||
public Integer getUserExpirationDays() {
|
||||
return Integer.parseInt(configuration.getProperty(Configuration.USER_EXPIRATION_DAYS.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Directory to store temporary private keys
|
||||
* @return directory location
|
||||
*/
|
||||
public String getKeyDirectory() {
|
||||
return keyDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CA cert file
|
||||
* @return the ca cert file
|
||||
*/
|
||||
public String getCaCertFile() {
|
||||
String caCertFile = configuration.getProperty(Configuration.CA_CERT_FILE.toString(), "");
|
||||
caCertFile = replaceProperties(caCertFile);
|
||||
return caCertFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the ca cert password
|
||||
* the password is encrypted
|
||||
* @return the ca cert file password
|
||||
*/
|
||||
public String getCaCertPassword() {
|
||||
String caCertPasswd = configuration.getProperty(Configuration.CA_CERT_PASSWORD.getValue());
|
||||
try {
|
||||
return aesService.decrypt(caCertPasswd);
|
||||
} catch (Exception ex) {
|
||||
logger.error("Unable to get db password " + ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the aes seed file for aes encryption
|
||||
* @return seed file location
|
||||
*/
|
||||
public String getAesSeedFile() {
|
||||
String aesSeed = configuration.getProperty(Configuration.AES_SEED_FILE.getValue(), "");
|
||||
aesSeed = replaceProperties(aesSeed);
|
||||
return aesSeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration value
|
||||
* @param key key for the value to find
|
||||
* @return the configuration value
|
||||
*/
|
||||
public ConfigurationRequest getConfiguration(String key) {
|
||||
Configuration type = Configuration.findEnum(key);
|
||||
return getConfiguration(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration value
|
||||
* @param typse the configuration types to get
|
||||
* @return the configuration value
|
||||
*/
|
||||
public ConfigurationRequest getConfigurations(Configuration... types) {
|
||||
ConfigurationRequest cr = new ConfigurationRequest();
|
||||
for (Configuration type : types) {
|
||||
String key = type.getValue();
|
||||
String value = this.configuration.getProperty(key);
|
||||
switch(type) {
|
||||
case CA_CERT_FILE:
|
||||
cr.setCaCertFile(value);
|
||||
break;
|
||||
case CA_CERT_PASSWORD:
|
||||
cr.setCaCertPassword(value);
|
||||
break;
|
||||
case DB_HOST:
|
||||
cr.setDbHost(value);
|
||||
break;
|
||||
case DB_PASSWORD:
|
||||
cr.setDbPassword(value);
|
||||
break;
|
||||
case DB_PORT:
|
||||
cr.setDbPort(Integer.parseInt(value));
|
||||
break;
|
||||
case DB_ROOT_PASSWORD:
|
||||
cr.setDbRootPassword(value);
|
||||
break;
|
||||
case DB_ROOT_USER:
|
||||
cr.setDbRootUser(value);
|
||||
break;
|
||||
case DB_USER:
|
||||
cr.setDbUsername(value);
|
||||
break;
|
||||
case USER_EXPIRATION_DAYS:
|
||||
cr.setUserExpirationDays(Integer.parseInt(value));
|
||||
break;
|
||||
case AES_SEED_FILE:
|
||||
cr.setAesSeedFile(value);
|
||||
break;
|
||||
case LOG_LEVEL:
|
||||
cr.setLogLevel(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration value
|
||||
* @param type the configuration type to get
|
||||
* @return the configuration value
|
||||
*/
|
||||
public ConfigurationRequest getConfiguration(Configuration type) {
|
||||
return getConfigurations(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current configuration
|
||||
* @return configuration
|
||||
*/
|
||||
public Properties getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last time the configuration file was modified
|
||||
* @return last modified
|
||||
*/
|
||||
public long getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
public void updateEncryption(String newSeed) throws Exception {
|
||||
String newDBRootPassword = aesService.changeEncryptionValue(configuration.getProperty(Configuration.DB_ROOT_PASSWORD.getValue()), newSeed);
|
||||
String newDBPassword = aesService.changeEncryptionValue(configuration.getProperty(Configuration.DB_PASSWORD.getValue()), newSeed);
|
||||
String newCACertPassword = aesService.changeEncryptionValue(configuration.getProperty(Configuration.CA_CERT_PASSWORD.getValue()), newSeed);
|
||||
|
||||
ConfigurationRequest cr = getConfigurations(Configuration.values());
|
||||
cr.setCaCertPassword(newCACertPassword);
|
||||
cr.setDbRootPassword(newDBRootPassword);
|
||||
cr.setDbPassword(newDBPassword);
|
||||
|
||||
saveConfiguration(cr, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current configuration
|
||||
* @param request Request with configuration values
|
||||
* @throws PortalException actionNotPermitted
|
||||
*/
|
||||
public void saveConfiguration(ConfigurationRequest request) throws Exception {
|
||||
saveConfiguration(request, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current configuration
|
||||
* @param request request with the configuration values
|
||||
* @param encryptCreds set to true to encrypt credentials false if the credentials are already encrypted
|
||||
* @throws Exception PortalException actionNotPermitted
|
||||
*/
|
||||
public void saveConfiguration(ConfigurationRequest request, boolean encryptCreds) throws Exception {
|
||||
try {
|
||||
Properties props = new Properties();
|
||||
|
||||
//copy what is current in the configuration settings into the new properties file
|
||||
Enumeration<?> confEnumeration = configuration.propertyNames();
|
||||
while(confEnumeration.hasMoreElements()) {
|
||||
String key = (String)confEnumeration.nextElement();
|
||||
String value = configuration.getProperty(key).toString();
|
||||
props.setProperty(key, value);
|
||||
}
|
||||
boolean changed = false;
|
||||
for (Field f : request.getClass().getDeclaredFields()) {
|
||||
f.setAccessible(true);
|
||||
String fieldName = f.getName();
|
||||
|
||||
//Ensures we are only saving values that are already configured
|
||||
Configuration conf = Configuration.findEnum(fieldName);
|
||||
if (conf == null) continue;
|
||||
|
||||
Object value = f.get(request);
|
||||
if (value == null) continue;
|
||||
|
||||
String fieldValue = String.valueOf(value);
|
||||
//Check to see if the old value changed
|
||||
String oldValue = props.getProperty(conf.getValue());
|
||||
if (StringUtils.isAllBlank(oldValue, fieldValue) || oldValue.equals(fieldValue)) { continue; }
|
||||
|
||||
changed = true;
|
||||
|
||||
fieldValue = encryptCreds && conf.is(Configuration.DB_ROOT_PASSWORD, Configuration.DB_PASSWORD, Configuration.CA_CERT_PASSWORD) ? aesService.encrypt(fieldValue) : fieldValue;
|
||||
|
||||
props.setProperty(fieldName, fieldValue);
|
||||
}
|
||||
if (changed) {
|
||||
saveToConf(props);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw PortalException.actionNotPermitted(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through the system properties and replace
|
||||
* the property value with the system property
|
||||
* @param value value to check
|
||||
* @return fromatted string
|
||||
*/
|
||||
private String replaceProperties(String value) {
|
||||
String tmp = new String(value);
|
||||
|
||||
Enumeration<?> sysPropEnum = System.getProperties().propertyNames();
|
||||
while (sysPropEnum.hasMoreElements()) {
|
||||
String key = (String) sysPropEnum.nextElement();
|
||||
String variableKey = String.format("${%s}", key);
|
||||
tmp = tmp.replace(variableKey, System.getProperty(key));
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.locusworks.portal.common.triggers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.locusworks.common.utils.Utils;
|
||||
import net.locusworks.portal.common.enums.TriggerType;
|
||||
|
||||
/**
|
||||
* Account trigger class to send stomp triggers across the system and to the client
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public class AccountTrigger extends Trigger {
|
||||
|
||||
private static final long serialVersionUID = 2139401946845273241L;
|
||||
|
||||
private Integer userId;
|
||||
|
||||
public AccountTrigger() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AccountTrigger(TriggerType type, Object... resources) {
|
||||
this();
|
||||
setType(type);
|
||||
setResources(Utils.toList(resources));
|
||||
}
|
||||
|
||||
private List<Object> resources = new ArrayList<>();
|
||||
|
||||
public Integer getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Integer userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public List<Object> getResources() {
|
||||
return resources;
|
||||
}
|
||||
|
||||
public void setResources(List<Object> resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package net.locusworks.portal.common.triggers;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
public class SeedTrigger extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 8676727530092345425L;
|
||||
|
||||
private String seed;
|
||||
|
||||
public SeedTrigger() {
|
||||
super(new Object());
|
||||
}
|
||||
|
||||
public SeedTrigger(String seed) {
|
||||
this();
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the seed
|
||||
*/
|
||||
public String getSeed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param seed the seed to set
|
||||
*/
|
||||
public void setSeed(String seed) {
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package net.locusworks.portal.common.triggers;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import net.locusworks.portal.common.enums.TriggerType;
|
||||
|
||||
/**
|
||||
* Abstract class to send stomp events across the system
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class Trigger extends ApplicationEvent {
|
||||
|
||||
private static final long serialVersionUID = 3123109911284540118L;
|
||||
|
||||
private long timestampCreation;
|
||||
private TriggerType type;
|
||||
|
||||
public Trigger() {
|
||||
this(new Object());
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
* @param source trigger payload
|
||||
*/
|
||||
public Trigger(Object source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the timestamp at which the trigger was created
|
||||
* @return timestampCreation
|
||||
*/
|
||||
public long getTimestampCreation() {
|
||||
return timestampCreation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timestamp the trigger was created
|
||||
* @param timestampCreation timestamp
|
||||
*/
|
||||
public void setTimestampCreation(long timestampCreation) {
|
||||
this.timestampCreation = timestampCreation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the trigger type
|
||||
* @return triggerType
|
||||
*/
|
||||
public TriggerType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the trigger type
|
||||
* @param type Trigger type to set
|
||||
*/
|
||||
public void setType(TriggerType type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.locusworks.portal.common.utils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
/**
|
||||
* Class to hold final static constant values used across the system
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final String SEPARATOR = FilenameUtils.separatorsToUnix(File.separator);
|
||||
|
||||
public static final String SCHEDULER_GROUP_NAME = "scriptScheduler";
|
||||
|
||||
|
||||
public static final String KEY_STORE_PATH = "javax.net.ssl.keyStore";
|
||||
public static final String KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword";
|
||||
|
||||
public static final String TRUST_STORE_PATH = "javax.net.ssl.trustStore";
|
||||
public static final String TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword";
|
||||
|
||||
public static final String PROPERTIES_FILE = "portal.properties";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package net.locusworks.portal.common.utils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import net.locusworks.portal.common.services.ConfigurationService;
|
||||
|
||||
/**
|
||||
* Component class to help convert dates to human readable format
|
||||
* @author Isaac Parenteau
|
||||
* @since 1.0.0-RELEASE
|
||||
* @version 1.0
|
||||
*/
|
||||
@Component
|
||||
public class DateService {
|
||||
private static final String DEFAULT = "MM/dd/yyyy";
|
||||
private static final String EXPANDED = "MM/dd/yyyy HH:mm:ss z";
|
||||
private static final String PRETTY_EXPANDED = "MMM d, yyyy HH:mm:ss z";
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService confService;
|
||||
|
||||
/**
|
||||
* Get the date in which a new user would expire
|
||||
* @return Returns the user expiration date
|
||||
*/
|
||||
public Date getUserExpirationDate() {
|
||||
return createDate(Calendar.DATE, confService.getUserExpirationDays());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new date
|
||||
* @return new Date with todays date
|
||||
*/
|
||||
public Date createDate() {
|
||||
return createDate(Calendar.DATE, 0);
|
||||
}
|
||||
|
||||
/***
|
||||
* Create a date
|
||||
* @param calField Field in the calendar class to add time to
|
||||
* @param numToAdd Number to add corresponding to the field can be negative
|
||||
* @return new date with the offset applied
|
||||
*/
|
||||
public Date createDate(Integer calField, Integer numToAdd) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
|
||||
Date date = new Date();
|
||||
cal.setTime(date);
|
||||
cal.add(calField, numToAdd);
|
||||
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a date to the default format of "MM/dd/yyyy"
|
||||
* @param date Date to format
|
||||
* @return formatted String
|
||||
*/
|
||||
public static String defaultFormat(Date date) {
|
||||
return format(date, DEFAULT);
|
||||
}
|
||||
|
||||
public static Date defaultFormatToDate(String date) {
|
||||
return formatToDate(DEFAULT, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a date to the expanded format of "MM/dd/yyyy HH:mm:ss z"
|
||||
* @param date Date to format
|
||||
* @return formatted date string
|
||||
*/
|
||||
public static String expandedFormat(Date date) {
|
||||
return format(date, EXPANDED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a string from a give date with the format of "MMM d, yyyy HH:mm:ss z"
|
||||
* @param date The date to format to a string
|
||||
* @return formatted string
|
||||
*/
|
||||
public static String prettyFormat(Date date) {
|
||||
return format(date, PRETTY_EXPANDED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a date
|
||||
* @param date Date to format
|
||||
* @param format Format in which to convert the date to
|
||||
* @return formatted date
|
||||
*/
|
||||
public static String format(Date date, String format) {
|
||||
return new SimpleDateFormat(format).format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string value to a date object
|
||||
* @param format The format to use in reference to the source
|
||||
* @param source the source to convert
|
||||
* @return Date object if the conversion was success; null otherwise
|
||||
*/
|
||||
public static Date formatToDate(String format, String source) {
|
||||
try {
|
||||
return new SimpleDateFormat(format).parse(source);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a date is within a range with date being now
|
||||
* Will return false if the provided date or start is null
|
||||
* end date can be null. Date will only compare against start if this is the case
|
||||
* @param start starting date
|
||||
* @param end ending date
|
||||
* @return true if its between the dates false otherwise
|
||||
*/
|
||||
public static boolean inRange(Date start, Date end) {
|
||||
return inRange(new Date(), start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a date is within a specified date range
|
||||
* Will return false if the provided date or start is null
|
||||
* end date can be null. Date will only compare against start if this is the case
|
||||
* @param date Date to check
|
||||
* @param start starting date
|
||||
* @param end ending date
|
||||
* @return true if its between the dates false otherwise
|
||||
*/
|
||||
public static boolean inRange(Date date, Date start, Date end) {
|
||||
if (date == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (start == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (end == null && start.getTime() <= date.getTime()) {
|
||||
return true;
|
||||
}
|
||||
return start.getTime() <= date.getTime() && date.getTime() <= end.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date to midnight
|
||||
* @param date date to set
|
||||
* @return Date that is set to midnight
|
||||
*/
|
||||
public static Date toMidnight(Date date) {
|
||||
return toMidnight(date, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date to midnight
|
||||
* @param date Date to set
|
||||
* @param addDays Number of days to add (can be negative) to the date when setting it to midnight
|
||||
* @return date set to midnight for a given date
|
||||
*/
|
||||
public static Date toMidnight(Date date, Integer addDays) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(date);
|
||||
cal.add(Calendar.DATE, addDays);
|
||||
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||
cal.set(Calendar.MINUTE, 0);
|
||||
cal.set(Calendar.SECOND, 0);
|
||||
cal.set(Calendar.MILLISECOND, 0);
|
||||
return cal.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a date with specified minutes ahead
|
||||
* @param minutesToAdd number of minutes to add to the date (can be negative)
|
||||
* @return date
|
||||
*/
|
||||
public static Date getDate(Integer minutesToAdd) {
|
||||
return getDate(Calendar.MINUTE, minutesToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a date with specified value added
|
||||
* @param field Calendar field to add value too
|
||||
* @param valueToAdd the amount to increase field by (can be negative)
|
||||
* @return date
|
||||
*/
|
||||
public static Date getDate(Integer field, Integer valueToAdd) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTime(new Date());
|
||||
if (valueToAdd != null) {
|
||||
cal.add(field, valueToAdd);
|
||||
}
|
||||
return cal.getTime();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user