/*****************************************************************************
*
* Copyright (C) Zenoss, Inc. 2010, all rights reserved.
*
* This content is made available according to terms specified in
* License.zenoss under the directory where your Zenoss product is installed.
*
****************************************************************************/
package org.zenoss.zep.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zenoss.zep.UUIDGenerator;
import org.zenoss.zep.ZepInstance;
import org.zenoss.zep.ZepUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
public class ZepInstanceImpl implements ZepInstance {
private static final Logger logger = LoggerFactory
.getLogger(ZepInstanceImpl.class.getName());
private final String instanceId;
private final Map<String, String> config;
private final UUIDGenerator uuidGenerator;
public ZepInstanceImpl(Properties config, UUIDGenerator uuidGenerator) throws IOException {
this.uuidGenerator = uuidGenerator;
this.instanceId = loadInstanceId();
this.config = createConfig(config);
}
private Map<String, String> createConfig(Properties config) {
Map<String, String> cfg = new HashMap<String, String>(config.size());
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
Object key = entry.getKey();
Object val = entry.getValue();
if (key instanceof String && val instanceof String) {
String strKey = (String) key;
String strVal = (String) val;
cfg.put(strKey, strVal);
}
}
for (Map.Entry<Object, Object> entry : config.entrySet()) {
Object key = entry.getKey();
Object val = entry.getValue();
if (key instanceof String && val instanceof String) {
String strKey = (String) key;
String strVal = (String) val;
if (!cfg.containsKey(strKey)) {
cfg.put(strKey, strVal);
}
}
}
return cfg;
}
private String loadInstanceId() throws IOException {
String id;
String zenHome = System.getenv("ZENHOME");
if (zenHome == null) {
zenHome = System.getProperty("ZENHOME");
}
if (zenHome == null) {
logger.warn("ZENHOME not specified. Not persisting ZEP instance id.");
id = this.uuidGenerator.generate().toString();
} else {
File f = new File(zenHome, "etc/zeneventserver/instance.properties");
Properties props = loadProperties(f);
id = props.getProperty("id");
// Persist ID to disk
if (id == null || !isValidUuid(id)) {
id = this.uuidGenerator.generate().toString();
props.put("id", id);
saveProperties(props, f);
}
}
return id;
}
private static boolean isValidUuid(String uuid) {
boolean valid = false;
try {
UUID.fromString(uuid);
valid = true;
} catch (Exception e) {
logger.warn("Invalid UUID: {}", uuid);
}
return valid;
}
private Properties loadProperties(File f) throws IOException {
Properties props = new Properties();
if (f.isFile()) {
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(new FileInputStream(f));
props.load(bis);
return props;
} finally {
if (bis != null) {
ZepUtils.close(bis);
}
}
}
return props;
}
private void saveProperties(Properties properties, File f)
throws IOException {
BufferedOutputStream bos = null;
try {
if (!f.getParentFile().isDirectory() && !f.getParentFile().mkdirs()) {
throw new IOException("Failed to create parent directory: " +
f.getParentFile().getAbsolutePath());
}
bos = new BufferedOutputStream(new FileOutputStream(f));
properties.store(bos, "ZEP Instance ID. Do not modify");
} finally {
ZepUtils.close(bos);
}
}
@Override
public String getId() {
return this.instanceId;
}
@Override
public Map<String, String> getConfig() {
return Collections.unmodifiableMap(this.config);
}
@Override
public String toString() {
return String.format("ZepInstance[id=%s]", this.instanceId);
}
}