/*
* RHQ Management Platform
* Copyright (C) 2005-2014 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.core.system;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.sigar.DirUsage;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.NetConnection;
import org.hyperic.sigar.Swap;
import org.rhq.core.util.exec.ProcessExecutionOutputStream;
import org.rhq.core.util.exec.ProcessExecutor;
import org.rhq.core.util.exec.ProcessExecutorResults;
import org.rhq.core.util.exec.ProcessToStart;
/**
* This is the "non-native" fallback implementation of a {@link SystemInfo} used in the case when there is no native
* library available that can be used to obtain low-level system information. This implementation cannot provide all the
* types of information that a true {@link NativeSystemInfo} implementation can - in the cases where this implementation
* cannot provide the requested information, the {@link UnsupportedOperationException} exception will be thrown.
*
* @author John Mazzitelli
*/
public class JavaSystemInfo implements SystemInfo {
private final Log log = LogFactory.getLog(JavaSystemInfo.class);
private final ProcessExecutor javaExec;
/**
* Constructor for {@link JavaSystemInfo} with package scope so only the {@link SystemInfoFactory} can instantiate
* this object.
*
* @param threadPool executor thread pool used for managing sub processes
*/
JavaSystemInfo(ExecutorService threadPool) {
javaExec = new ProcessExecutor(threadPool);
}
/**
* Returns <code>false</code> - this implementation relies solely on the Java API to get all the system information
* it can.
*
* @see SystemInfo#isNative()
*/
public boolean isNative() {
return false;
}
/**
* Returns {@link OperatingSystemType#JAVA} unless the type can be determined via the Java "os.name" property. The
* caller can call {@link #getOperatingSystemName()} to try to determine the real operating system type if this
* method cannot.
*
* @see org.rhq.core.system.SystemInfo#getOperatingSystemType()
*/
public OperatingSystemType getOperatingSystemType() {
String osName = System.getProperty("os.name").toLowerCase(Locale.US);
if (osName.indexOf("windows") > -1) {
return OperatingSystemType.WINDOWS;
} else if (osName.indexOf("linux") > -1) {
return OperatingSystemType.LINUX;
} else if ((osName.indexOf("solaris") > -1) || (osName.indexOf("sunos") > -1)) {
return OperatingSystemType.SOLARIS;
} else if (osName.indexOf("bsd") > -1) {
return OperatingSystemType.BSD;
} else if (osName.indexOf("aix") > -1) {
return OperatingSystemType.AIX;
} else if (osName.indexOf("hp-ux") > -1) {
return OperatingSystemType.HPUX;
} else if (osName.indexOf("mac") > -1) // "Mac OS X"
{
return OperatingSystemType.OSX;
}
// TODO - find out the other os.name values for the other platforms
log.warn("Defaulting to Java OS. Did not recogize [" + osName + "], derived from ["
+ System.getProperty("os.name") + "]");
return OperatingSystemType.JAVA;
}
/**
* Returns the value of the Java system property <code>os.name</code>.
*
* @see SystemInfo#getOperatingSystemName()
*/
public String getOperatingSystemName() {
return System.getProperty("os.name");
}
/**
* Returns the value of the Java system property <code>os.version</code>.
*
* @see SystemInfo#getOperatingSystemVersion()
*/
public String getOperatingSystemVersion() {
return System.getProperty("os.version");
}
/**
* This returns the canonical hostname as it is known via the Java API <code>InetAddress.getLocalHost()</code>.
*
* @see SystemInfo#getHostname()
*/
public String getHostname() {
try {
return InetAddress.getLocalHost().getCanonicalHostName();
} catch (UnknownHostException e) {
throw getUnsupportedException(e);
}
}
/**
* Returns partially filled {@link NetworkAdapterInfo} objects - only the data available via the Java API
* (particularly the <code>NetworkInterface</code> class) will be available in the returned objects.
*
* @see SystemInfo#getAllServices()
*/
public List<NetworkAdapterInfo> getAllNetworkAdapters() throws SystemInfoException {
throw getUnsupportedException("Cannot get list of network adaptors without native support");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about installed
* services.
*
* @see SystemInfo#getAllServices()
*/
public List<ServiceInfo> getAllServices() throws UnsupportedOperationException {
throw getUnsupportedException("Cannot get list of installed services without native support");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about currently running
* processes.
*
* @see SystemInfo#getAllProcesses()
*/
public List<ProcessInfo> getAllProcesses() throws UnsupportedOperationException {
throw getUnsupportedException("Cannot get the process table information without native support");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about processes.
*
* @see SystemInfo#getProcesses(String)
*/
public List<ProcessInfo> getProcesses(String processInfoQuery) {
throw getUnsupportedException("Cannot get the process table information without native support");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about currently running
* processes.
*
* @see SystemInfo#getThisProcess()
*/
public ProcessInfo getThisProcess() {
throw getUnsupportedException("Cannot get information on this process without native support");
}
/**
* Spawns a new process using the Java Runtime API.
*
* @see SystemInfo#executeProcess(ProcessExecution)
*/
public ProcessExecutionResults executeProcess(ProcessExecution processExecution) {
ProcessToStart process = new ProcessToStart();
ProcessExecutionResults executionResults = new ProcessExecutionResults();
process.setProgramExecutable(processExecution.getExecutable());
process.setCheckExecutableExists(processExecution.isCheckExecutableExists());
process.setArguments(processExecution.getArgumentsAsArray());
process.setEnvironment(processExecution.getEnvironmentVariablesAsArray());
process.setWorkingDirectory(processExecution.getWorkingDirectory());
process.setWaitForExit(Long.valueOf(processExecution.getWaitForCompletion()));
process.setCaptureOutput(Boolean.valueOf(processExecution.getCaptureMode().isCapture()));
process.setKillOnTimeout(Boolean.valueOf(processExecution.isKillOnTimeout()));
ProcessExecutionOutputStream outputStream = processExecution.getCaptureMode().createOutputStream();
process.setOutputStream(outputStream);
executionResults.setCapturedOutputStream(outputStream);
ProcessExecutorResults javaExecResults = javaExec.execute(process);
executionResults.setExitCode(javaExecResults.getExitCode());
executionResults.setError(javaExecResults.getError());
executionResults.setProcess(javaExecResults.getProcess());
return executionResults;
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about the number of
* CPUs.
*
* @see SystemInfo#getNumberOfCpus()
*/
public int getNumberOfCpus() {
throw getUnsupportedException("Cannot get the number of CPUs without native support");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about low level memory
* details.
*
* @see SystemInfo#getMemoryInfo()
*/
public Mem getMemoryInfo() {
throw getUnsupportedException("Cannot get any information about memory without native support");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about low level swap
* details.
*
* @see SystemInfo#getSwapInfo()
*/
public Swap getSwapInfo() {
throw getUnsupportedException("Cannot get any information about swap without native support");
}
/**
* Reads from <code>System.in</code>.
*
* @see SystemInfo#readLineFromConsole(boolean)
*/
public String readLineFromConsole(boolean noEcho) throws IOException {
return new BufferedReader(new InputStreamReader(System.in)).readLine();
}
/**
* Writes to <code>System.out</code>.
*
* @see SystemInfo#writeLineToConsole(String)
*/
public void writeLineToConsole(String line) throws IOException {
System.out.print(line); // note: don't use println - let the caller append newline char to 'line' if needed
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about CPUs.
*
* @see SystemInfo#getCpu(int)
*/
public CpuInformation getCpu(int cpuIndex) {
throw getUnsupportedException("Cannot get CPU information without native support");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about file systems.
*
* @see SystemInfo#getFileSystems()
*/
public List<FileSystemInfo> getFileSystems() {
throw getUnsupportedException("Cannot get file systems information");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about file systems.
*
* @see SystemInfo#getFileSystemsDeferredUsageInfo()
*/
public List<FileSystemInfo> getFileSystemsDeferredUsageInfo() {
throw getUnsupportedException("Cannot get file systems information");
}
/**
* Throws {@link UnsupportedOperationException} since the Java API cannot obtain information about file systems.
*
* @see SystemInfo#getFileSystem(String)
*/
public FileSystemInfo getFileSystem(String directory) {
throw getUnsupportedException("Cannot get file system information");
}
@Override
public DirUsage getDirectoryUsage(String path) {
throw getUnsupportedException("Cannot get directory information yet");
}
public NetworkAdapterStats getNetworkAdapterStats(String interfaceName) {
throw getUnsupportedException("Cannot get network adapter stats");
}
public NetworkStats getNetworkStats(String addressName, int port) {
throw getUnsupportedException("Cannot get network stats");
}
public List<NetConnection> getNetworkConnections(String addressName, int port) {
throw getUnsupportedException("Cannot get network connections");
}
private UnsupportedOperationException getUnsupportedException(Exception e) {
return new UnsupportedOperationException("No native library available - " + e, e);
}
private UnsupportedOperationException getUnsupportedException(String err) {
return new UnsupportedOperationException("No native library available - " + err);
}
public String getSystemArchitecture() {
return System.getProperty("os.arch");
}
}