/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Lachlan Dowding
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package permafrost.tundra.server;
import com.wm.app.b2b.server.Build;
import com.wm.app.b2b.server.Resources;
import com.wm.app.b2b.server.Server;
import com.wm.app.b2b.server.ServiceException;
import com.wm.data.IData;
import permafrost.tundra.data.CaseInsensitiveIData;
import permafrost.tundra.data.Element;
import permafrost.tundra.data.ElementList;
import permafrost.tundra.data.IDataMap;
import permafrost.tundra.data.ImmutableIData;
import permafrost.tundra.data.KeyAliasElement;
import permafrost.tundra.data.MapIData;
import permafrost.tundra.flow.variable.GlobalVariableHelper;
import permafrost.tundra.io.FileHelper;
import permafrost.tundra.math.LongHelper;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
/**
* A collection of convenience methods for working with the webMethods Integration Server system.
*/
public final class SystemHelper {
/**
* The cached structure for system environment variables.
*/
private static volatile IData system;
/**
* Whether the operating system is Microsoft Windows based.
*/
private static volatile boolean OPERATING_SYSTEM_IS_WINDOWS = isWindows();
/**
* Disallow instantiation of this class.
*/
private SystemHelper() {}
/**
* Returns information about Integration Server such as the software version, environment settings, Java properties,
* well-known directory locations, and memory usage.
*
* @return Integration Server properties.
* @throws ServiceException If an error occurs.
*/
public static IData reflect() throws ServiceException {
return reflect(false);
}
/**
* Returns information about Integration Server such as the software version, environment settings, Java properties,
* well-known directory locations, and memory usage.
*
* @param refresh If true, the returned IData will be rebuilt from the system environment and properties
* to reflect any changes that have occurred.
* @return Integration Server properties.
* @throws ServiceException If an error occurs.
*/
public static IData reflect(boolean refresh) throws ServiceException {
if (refresh || system == null) {
ElementList<String, Object> output = new ElementList<String, Object>();
output.add(new Element<String, Object>("version", Build.getVersion()));
output.add(new Element<String, Object>("environment", getEnvironment()));
output.add(new KeyAliasElement<String, Object>("property", getProperties(), "properties"));
if (GlobalVariableHelper.isSupported()) output.add(new Element<String, Object>("global", GlobalVariableHelper.list()));
output.add(new KeyAliasElement<String, Object>("directory", getDirectories(), "directories"));
output.add(new Element<String, Object>("memory", getMemoryUsage()));
system = new ImmutableIData(output);
}
return system;
}
/**
* Returns true if the operating system is Microsoft Windows based.
*
* @return True if the operating system is Microsoft Windows based.
*/
private static boolean isWindows() {
boolean result = false;
String operatingSystemName = System.getProperty("os.name");
if (operatingSystemName != null) {
result = operatingSystemName.toLowerCase().contains("windows");
}
return result;
}
/**
* Returns the current system environment variables.
*
* @return The current system environment variables.
*/
private static IData getEnvironment() {
IData environment = new MapIData<String, String>(new TreeMap<String, String>(System.getenv()));
if (OPERATING_SYSTEM_IS_WINDOWS) environment = new CaseInsensitiveIData(environment);
return environment;
}
/**
* Returns the current system properties.
*
* @return The current system properties.
*/
private static IData getProperties() {
// sort keys in natural ascending order via a TreeMap
Map<String, String> properties = new TreeMap<String, String>();
Properties systemProperties = System.getProperties();
if (systemProperties != null) {
// protect against concurrent modification exceptions by cloning
systemProperties = (Properties)systemProperties.clone();
// remove empty strings from properties object
for (Map.Entry<Object ,Object> entry : systemProperties.entrySet()) {
Object key = entry.getKey();
Object value = entry.getValue();
if (key instanceof String) {
if (value instanceof String && !value.equals("")) {
properties.put(key.toString(), value.toString());
}
}
}
}
// default the mail.from property if not set
String mailFrom = properties.get("mail.from");
if (mailFrom == null || mailFrom.equals("")) {
properties.put("mail.from", getDefaultFromEmailAddress());
}
return new MapIData<String, String>(properties);
}
/**
* Returns the locations of well-known Integration Server directories.
*
* @return The locations of well-known Integration Server directories.
*/
private static IData getDirectories() {
Resources resources = Server.getResources();
IDataMap output = new IDataMap();
output.put("root", FileHelper.normalize(resources.getRootDir()));
output.put("config", FileHelper.normalize(resources.getConfigDir()));
output.put("datastore", FileHelper.normalize(resources.getDatastoreDir()));
output.put("jobs", FileHelper.normalize(resources.getJobsDir()));
output.put("lib", FileHelper.normalize(resources.getLibDir()));
output.put("logs", FileHelper.normalize(resources.getLogDir()));
output.put("packages", FileHelper.normalize(resources.getPackagesDir()));
output.put("recycle", FileHelper.normalize(resources.getRecycleDir()));
output.put("replicate", FileHelper.normalize(resources.getReplicateDir()));
output.put("replicate.inbound", FileHelper.normalize(resources.getReplicateInDir()));
output.put("replicate.outbound", FileHelper.normalize(resources.getReplicateOutDir()));
output.put("replicate.salvage", FileHelper.normalize(resources.getReplicateSaveDir()));
return output;
}
/**
* Returns the Java heap memory usage for the currently executing JVM process.
*
* @return The Java heap memory usage for the currently executing JVM process.
*/
private static IData getMemoryUsage() {
Runtime runtime = Runtime.getRuntime();
long freeMemory = runtime.freeMemory();
long totalMemory = runtime.totalMemory();
long usedMemory = totalMemory - freeMemory;
IDataMap output = new IDataMap();
output.put("used", LongHelper.emit(usedMemory));
output.put("free", LongHelper.emit(freeMemory));
output.put("total", LongHelper.emit(totalMemory));
return output;
}
/**
* Returns the default from email address of this Integration Server.
*
* @return the default from email address of this Integration Server.
*/
private static String getDefaultFromEmailAddress() {
String domain;
try {
domain = java.net.InetAddress.getLocalHost().getCanonicalHostName().toLowerCase();
} catch (java.net.UnknownHostException ex) {
domain = "unknown";
}
return "Integration-Server@" + domain;
}
}