/**
* JBoss, Home of Professional Open Source Copyright Red Hat, Inc., and individual contributors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
package org.jboss.aerogear.simplepush.server.netty.standalone;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jboss.aerogear.io.netty.handler.codec.sockjs.SockJsConfig;
import org.jboss.aerogear.simplepush.server.DefaultSimplePushConfig;
import org.jboss.aerogear.simplepush.server.DefaultSimplePushConfig.Builder;
import org.jboss.aerogear.simplepush.server.SimplePushServerConfig;
import org.jboss.aerogear.simplepush.server.datastore.CouchDBDataStore;
import org.jboss.aerogear.simplepush.server.datastore.DataStore;
import org.jboss.aerogear.simplepush.server.datastore.InMemoryDataStore;
import org.jboss.aerogear.simplepush.server.datastore.JpaDataStore;
import org.jboss.aerogear.simplepush.server.datastore.RedisDataStore;
/**
* Utility to read a JSON config files.
*/
public class ConfigReader {
private static final ObjectMapper OM = new ObjectMapper();
private ConfigReader() {
}
/**
* Will parse the passed in file, which can either be a file on the file system
* or a file on the classpath into a {@link StandaloneConfig} instance.
*
* @param fileName the name of a file on the file system or on the classpath.
* @return {@link StandaloneConfig} populated with the values in the JSON configuration file.
* @throws Exception
*/
public static StandaloneConfig parse(final String fileName) throws Exception {
final File configFile = new File(fileName);
InputStream in = null;
try {
in = configFile.exists() ? new FileInputStream(configFile) : ConfigReader.class.getResourceAsStream(fileName);
return parse(in);
} finally {
if (in != null) {
in.close();
}
}
}
/**
* Will parse the passed InputStream into a {@link StandaloneConfig} instance.
*
* @param in the input stream to parse. Should be from a JSON source representing a SimplePush configuration.
* @return {@link StandaloneConfig} populated with the values in the JSON input stream.
*/
public static StandaloneConfig parse(final InputStream in) {
try {
final JsonNode json = OM.readTree(in);
return new StandaloneConfig(parseSimplePushProperties(json),
parseSockJsProperties(json),
createDataStore(json));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static DataStore createDataStore(final JsonNode json) {
final JsonNode dataStore = json.get("datastore");
if (dataStore == null) {
throw new IllegalArgumentException("datastore element must be specified");
}
final JsonNode inMemory = dataStore.get("in-memory");
if (inMemory != null) {
return new InMemoryDataStore();
}
final JsonNode redis = dataStore.get("redis");
if (redis != null) {
return new RedisDataStore(redis.get("host").asText(), redis.get("port").asInt());
}
final JsonNode couchdb = dataStore.get("couchdb");
if (couchdb != null) {
return new CouchDBDataStore(couchdb.get("url").asText(), couchdb.get("dbName").asText());
}
final JsonNode jpa = dataStore.get("jpa");
if (jpa != null) {
return new JpaDataStore(jpa.get("persistenceUnit").asText());
}
throw new IllegalStateException("datastore must be specified");
}
private static SockJsConfig parseSockJsProperties(final JsonNode json) {
final JsonNode prefixNode = json.get("sockjs-prefix");
final String prefix = prefixNode != null ? prefixNode.asText() : "/simplepush";
final org.jboss.aerogear.io.netty.handler.codec.sockjs.SockJsConfig.Builder builder = SockJsConfig.withPrefix(prefix);
final JsonNode cookiesNeeded = json.get("sockjs-cookies-needed");
if (cookiesNeeded != null && cookiesNeeded.asBoolean()) {
builder.cookiesNeeded();
}
final JsonNode sockjsUrl = json.get("sockjs-url");
if (sockjsUrl != null) {
builder.sockJsUrl(sockjsUrl.asText());
}
final JsonNode sessionTimeout = json.get("sockjs-session-timeout");
if (sessionTimeout != null) {
builder.sessionTimeout(sessionTimeout.asLong());
}
final JsonNode heartbeatInterval = json.get("sockjs-heartbeat-interval");
if (heartbeatInterval != null) {
builder.heartbeatInterval(heartbeatInterval.asLong());
}
final JsonNode maxStreamingBytesSize = json.get("sockjs-max-streaming-bytes-size");
if (maxStreamingBytesSize != null) {
builder.maxStreamingBytesSize(maxStreamingBytesSize.asInt());
}
final JsonNode keystore = json.get("sockjs-keystore");
if (keystore != null) {
builder.keyStore(keystore.asText());
}
final JsonNode keystorePassword = json.get("sockjs-keystore-password");
if (keystorePassword != null) {
builder.keyStorePassword(keystorePassword.asText());
}
final JsonNode tls = json.get("sockjs-tls");
if (tls != null) {
builder.tls(tls.asBoolean());
}
final JsonNode websocketEnable = json.get("sockjs-websocket-enable");
if (websocketEnable != null && !websocketEnable.asBoolean()) {
builder.disableWebSocket();
}
final JsonNode websocketHeartbeatInterval = json.get("sockjs-websocket-heartbeat-interval");
if (websocketHeartbeatInterval != null) {
builder.webSocketHeartbeatInterval(websocketHeartbeatInterval.asLong());
}
final JsonNode websocketProtocols = json.get("sockjs-websocket-protocols");
if (websocketProtocols != null) {
builder.webSocketProtocols(websocketProtocols.asText().split(","));
}
return builder.build();
}
private static SimplePushServerConfig parseSimplePushProperties(final JsonNode json) {
final JsonNode host = json.get("host");
final JsonNode port = json.get("port");
final Builder builder = DefaultSimplePushConfig.create(host.asText(), port.asInt());
final JsonNode password = json.get("password");
if (password != null) {
builder.password(password.asText());
}
final JsonNode useragentReaperTimeout = json.get("useragent-reaper-timeout");
if (useragentReaperTimeout != null) {
builder.userAgentReaperTimeout(useragentReaperTimeout.asLong());
}
final JsonNode endpointHost = json.get("endpoint-host");
if (endpointHost != null) {
builder.endpointHost(endpointHost.asText());
}
final JsonNode endpointPort = json.get("endpoint-port");
if (endpointPort != null) {
builder.endpointPort(endpointPort.asInt());
}
final JsonNode endpointTls = json.get("endpoint-tls");
if (endpointTls != null) {
builder.endpointTls(endpointTls.asBoolean());
}
final JsonNode endpointPrefix = json.get("endpoint-prefix");
if (endpointPrefix != null) {
builder.endpointPrefix(endpointPrefix.asText());
}
final JsonNode ackInterval = json.get("ack-interval");
if (ackInterval != null) {
builder.ackInterval(ackInterval.asLong());
}
final JsonNode notifierMaxThreads = json.get("notifier-max-threads");
if (notifierMaxThreads != null) {
builder.notifierMaxThreads(notifierMaxThreads.asInt());
}
return builder.build();
}
}