Initial revision

This commit is contained in:
Doug MacEachern 2004-06-21 22:37:04 +00:00
parent 1a7957fb1e
commit dffe0da855
207 changed files with 34390 additions and 0 deletions

50
README Normal file
View File

@ -0,0 +1,50 @@
sigar - System Info Gather And Reporter
goal of this api is provide a portable interface for gathering system
information such as:
- system memory (total, used, etc.)
- system cpu (total, sys, idle, etc.)
- system swap (total, free, etc.)
- process memory usage (size, vsize, etc.)
- process cpu usage (user, sys, etc.)
- process credentials (uid, gid, ppid, etc.)
- process times (start time, user cpu, system cpu, etc.)
- process state (name, state, etc.)
- process list (list of active process pids)
- process arguments
- process environment
- filesystem list (list of mounted filesystems: fs type, fs name, etc.)
- filesystem usage (total blocks, blocks free, files, etc.)
- load average
- uptime
- netload (packets in, packets out, bytes in, bytes out, etc.)
the api used by applications will be the same for all platforms,
underneath the platform vendor api(s) are used to fill in the portable
sigar structures:
- linux => /proc filesystem, native system calls
- solaris => kstat api + /proc filesystem
- hpux => pstat api
- win32 => registry performance "api", sdk calls
- aix => /dev/kmem, native system calls

View File

@ -0,0 +1,48 @@
<?xml version="1.0"?>
<!-- NAnt build file: http://sourceforge.net/projects/nant/ -->
<project name="SigarSharp" default="build">
<property name="debug" value="true"/>
<target name="clean" description="clean build files">
<delete dir="build"/>
</target>
<target name="build" description="Build C# Sigar bindings">
<mkdir dir="build"/>
<csc target="library" output="build/SigarSharp.dll" debug="${debug}">
<sources>
<includes name="src/Sigar.cs"/>
</sources>
</csc>
<csc target="exe" output="build/Free.exe" debug="${debug}">
<sources>
<includes name="examples/Free.cs"/>
</sources>
<references>
<includes name="build/SigarSharp.dll"/>
</references>
</csc>
<csc target="exe" output="build/CpuInfo.exe" debug="${debug}">
<sources>
<includes name="examples/CpuInfo.cs"/>
</sources>
<references>
<includes name="build/SigarSharp.dll"/>
</references>
</csc>
<csc target="exe" output="build/Df.exe" debug="${debug}">
<sources>
<includes name="examples/Df.cs"/>
</sources>
<references>
<includes name="build/SigarSharp.dll"/>
</references>
</csc>
</target>
</project>

View File

@ -0,0 +1,21 @@
using System;
using Hyperic.Sigar;
public class CpuInfo {
public static void Main() {
Sigar sigar = new Sigar();
Hyperic.Sigar.CpuInfo[] infos =
sigar.CpuInfos();
System.Console.WriteLine(infos.Length + " total CPUs..");
foreach (Hyperic.Sigar.CpuInfo info in infos) {
System.Console.WriteLine("Vendor........" + info.Vendor);
System.Console.WriteLine("Model........." + info.Model);
System.Console.WriteLine("Mhz..........." + info.Mhz);
System.Console.WriteLine("");
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using Hyperic.Sigar;
public class Df {
public static void Main() {
Sigar sigar = new Sigar();
foreach (FileSystem fs in sigar.FileSystemList()) {
FileSystemUsage usage;
ulong used, avail, total, pct;
try {
usage = sigar.FileSystemUsage(fs.DirName);
used = usage.Total - usage.Free;
avail = usage.Avail;
total = usage.Total;
pct = (ulong)(usage.UsePercent * 100);
} catch (ApplicationException) {
used = avail = total = pct = 0;
continue;
}
string usePct;
if (pct == 0) {
usePct = "-";
}
else {
usePct = pct + "%";
}
System.Console.WriteLine(fs.DevName + "\t" +
total + "\t" +
used + "\t" +
avail + "\t" +
usePct + "\t" +
fs.DirName + "\t" +
fs.SysTypeName + "/" + fs.TypeName);
}
}
}

View File

@ -0,0 +1,26 @@
using System;
using Hyperic.Sigar;
public class Free {
public static void Main() {
Sigar sigar = new Sigar();
Mem mem = sigar.Mem();
Swap swap = sigar.Swap();
System.Console.WriteLine("\tTotal\tUsed\tFree");
System.Console.WriteLine("Mem:\t" +
mem.Total / 1024 + "\t" +
mem.Used / 1024 + "\t" +
mem.Free / 1024);
System.Console.WriteLine("Swap:\t" +
swap.Total / 1024 + "\t" +
swap.Used / 1024 + "\t" +
swap.Free / 1024);
System.Console.WriteLine("RAM:\t" + mem.Ram + "MB");
}
}

View File

@ -0,0 +1,271 @@
using System;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;
namespace Hyperic.Sigar {
public class Sigar {
public const int OK = 0;
internal const int FS_NAME_LEN = 64;
internal const string LIBSIGAR = "sigar-x86-winnt.dll";
internal HandleRef sigar;
[DllImport(LIBSIGAR)]
private static extern IntPtr sigar_new();
[DllImport(LIBSIGAR)]
private static extern int sigar_close(IntPtr sigar);
public Sigar() {
IntPtr handle = sigar_new();
this.sigar = new HandleRef(this, handle);
}
public Mem Mem() {
return Hyperic.Sigar.Mem.NativeGet(this);
}
public Swap Swap() {
return Hyperic.Sigar.Swap.NativeGet(this);
}
public CpuInfo[] CpuInfos() {
return Hyperic.Sigar.CpuInfos.NativeGet(this);
}
public FileSystem[] FileSystemList() {
return Hyperic.Sigar.FileSystemList.NativeGet(this);
}
public FileSystemUsage FileSystemUsage(string dirname) {
return Hyperic.Sigar.FileSystemUsage.NativeGet(this, dirname);
}
~Sigar() {
sigar_close(this.sigar.Handle);
}
internal static IntPtr incrementIntPtr(IntPtr ptr, int size) {
Int32 x = (Int32)ptr;
x += size;
return (IntPtr)x;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Mem {
public readonly ulong Ram;
public readonly ulong Total;
public readonly ulong Used;
public readonly ulong Free;
public readonly ulong Shared;
private readonly ulong NA_buffer;
private readonly ulong NA_cached;
private readonly ulong NA_user;
[DllImport(Sigar.LIBSIGAR)]
private static extern int sigar_mem_get(IntPtr sigar, IntPtr mem);
internal static Mem NativeGet(Sigar sigar) {
Type type = typeof(Mem);
//sigar_mem_t *ptr = malloc(sizeof(*ptr))
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(type));
int status = sigar_mem_get(sigar.sigar.Handle, ptr);
if (status != Sigar.OK) {
Marshal.FreeHGlobal(ptr);
throw new ApplicationException("mem_get");
}
//memcpy(ptr, this, sizeof(this))
Mem mem = (Mem)Marshal.PtrToStructure(ptr, type);
Marshal.FreeHGlobal(ptr);
return mem;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Swap {
public readonly ulong Total;
public readonly ulong Used;
public readonly ulong Free;
[DllImport(Sigar.LIBSIGAR)]
private static extern int sigar_swap_get(IntPtr sigar, IntPtr swap);
internal static Swap NativeGet(Sigar sigar) {
Type type = typeof(Swap);
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(type));
int status = sigar_swap_get(sigar.sigar.Handle, ptr);
if (status != Sigar.OK) {
Marshal.FreeHGlobal(ptr);
throw new ApplicationException("swap_get");
}
Swap swap = (Swap)Marshal.PtrToStructure(ptr, type);
Marshal.FreeHGlobal(ptr);
return swap;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct CpuInfo {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public readonly string Vendor; //char[128]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
public readonly string Model; //char[128]
public readonly int Mhz;
private readonly ulong CacheSize; //XXX not implemented
}
[StructLayout(LayoutKind.Sequential)]
internal struct CpuInfos {
private readonly uint Number; //sizeof(unsigned long) == 4
private readonly uint size;
private readonly IntPtr data;
[DllImport(Sigar.LIBSIGAR)]
private static extern int sigar_cpu_infos_get(IntPtr sigar,
IntPtr cpu_infos);
[DllImport(Sigar.LIBSIGAR)]
private static extern int sigar_cpu_infos_destroy(IntPtr sigar,
IntPtr cpu_infos);
internal static CpuInfo[] NativeGet(Sigar sigar) {
Type type = typeof(CpuInfos);
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(type));
int status = sigar_cpu_infos_get(sigar.sigar.Handle, ptr);
if (status != Sigar.OK) {
Marshal.FreeHGlobal(ptr);
throw new ApplicationException("cpu_infos_get");
}
CpuInfos infosPtr = (CpuInfos)Marshal.PtrToStructure(ptr, type);
CpuInfo[] infos = new CpuInfo[infosPtr.Number];
IntPtr eptr = infosPtr.data;
int size = Marshal.SizeOf(infos[0]);
for (int i=0; i<infosPtr.Number; i++) {
infos[i] = (CpuInfo)Marshal.PtrToStructure(eptr, typeof(CpuInfo));
//eptr += sizeof(sigar_cpu_info_t);
eptr = Sigar.incrementIntPtr(eptr, size);
}
sigar_cpu_infos_destroy(sigar.sigar.Handle, ptr);
Marshal.FreeHGlobal(ptr);
return infos;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct FileSystem {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=Sigar.FS_NAME_LEN)]
public readonly string DirName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=Sigar.FS_NAME_LEN)]
public readonly string DevName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=Sigar.FS_NAME_LEN)]
public readonly string TypeName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=Sigar.FS_NAME_LEN)]
public readonly string SysTypeName;
public readonly int Type;
public readonly uint Flags;
}
[StructLayout(LayoutKind.Sequential)]
internal struct FileSystemList {
private readonly uint Number;
private readonly uint size;
private readonly IntPtr data;
[DllImport(Sigar.LIBSIGAR)]
private static extern int sigar_file_system_list_get(IntPtr sigar,
IntPtr fslist);
[DllImport(Sigar.LIBSIGAR)]
private static extern int sigar_file_system_list_destroy(IntPtr sigar,
IntPtr fslist);
internal static FileSystem[] NativeGet(Sigar sigar) {
Type type = typeof(FileSystemList);
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(type));
int status = sigar_file_system_list_get(sigar.sigar.Handle, ptr);
if (status != Sigar.OK) {
Marshal.FreeHGlobal(ptr);
throw new ApplicationException("sigar_file_system_list_get");
}
FileSystemList fsPtr =
(FileSystemList)Marshal.PtrToStructure(ptr, type);
FileSystem[] fs = new FileSystem[fsPtr.Number];
IntPtr fptr = fsPtr.data;
int size = Marshal.SizeOf(fs[0]);
for (int i=0; i<fsPtr.Number; i++) {
fs[i] = (FileSystem)Marshal.PtrToStructure(fptr, typeof(FileSystem));
//fptr += sizeof(sigar_fs_t);
fptr = Sigar.incrementIntPtr(fptr, size);
}
sigar_file_system_list_destroy(sigar.sigar.Handle, ptr);
Marshal.FreeHGlobal(ptr);
return fs;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct FileSystemUsage {
public readonly ulong Total;
public readonly ulong Free;
public readonly ulong Avail;
private readonly ulong NA_Files; //XXX not implemented
private readonly ulong NA_FreeFiles;
public readonly double UsePercent;
[DllImport(Sigar.LIBSIGAR)]
private static extern int sigar_file_system_usage_get(IntPtr sigar,
string dirname,
IntPtr fsusage);
internal static FileSystemUsage NativeGet(Sigar sigar, string dirname) {
Type type = typeof(FileSystemUsage);
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(type));
int status = sigar_file_system_usage_get(sigar.sigar.Handle,
dirname, ptr);
if (status != Sigar.OK) {
Marshal.FreeHGlobal(ptr);
throw new ApplicationException("file_system_usage_get");
}
FileSystemUsage fsusage =
(FileSystemUsage)Marshal.PtrToStructure(ptr, type);
Marshal.FreeHGlobal(ptr);
return fsusage;
}
}
}

11
bindings/java/.classpath Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="build/src"/>
<classpathentry kind="src" path="hyperic_jni/src"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="lib" path="lib/bcel-5.1.jar" sourcepath="/usr/src/jakarta/bcel-5.1/src/java/"/>
<classpathentry kind="lib" path="lib/junit.jar"/>
<classpathentry kind="lib" path="hyperic_jni/lib/cpptasks.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="build/classes"/>
</classpath>

3
bindings/java/.cvsignore Normal file
View File

@ -0,0 +1,3 @@
sigar-bin
build
testresults

17
bindings/java/.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>sigar</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

205
bindings/java/build.xml Normal file
View File

@ -0,0 +1,205 @@
<!DOCTYPE project [
<!ENTITY jni-build SYSTEM "hyperic_jni/jni-build.xml">
]>
<project name="Sigar" default="build" basedir=".">
<property file="${user.home}/.sigar-build.properties"/>
<property name="project.name" value="sigar"/>
<property name="jni.define.name" value="SIGAR"/>
<property name="sigar-bin" location="sigar-bin"/>
<property name="jni.bin" location="${sigar-bin}"/>
<property name="jni.source.dir" location="../.."/>
<property name="jni.src.java" value="hyperic_jni/src"/>
<property name="jni.libprefix" value=""/> <!-- drop "java" prefix -->
<property name="jni.werror" value="true"/>
<property name="cpptasks.jar"
location="hyperic_jni/lib/cpptasks.jar"/>
&jni-build;
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="build.javadocs" value="${build}/javadocs"/>
<property name="dist.name" value="hyperic-sigar"/>
<property name="dist" location="${build}/${dist.name}"/>
<property name="perl" value="perl"/>
<!-- trick TestFQDN into passing with: ant test -Dsigar.fdqn=foo.bar -->
<property name="sigar.fqdn" value=""/>
<path id="libjars">
<fileset dir="lib" includes="*.jar"/>
</path>
<path id="alljars">
<path refid="libjars"/>
<fileset dir="${sigar-bin}/lib" includes="sigar.jar"/>
</path>
<target name="javadoc_check">
<uptodate property="javadoc.notrequired"
targetfile="${build.javadocs}/packages.html" >
<srcfiles dir="src" includes="**/*.java"/>
</uptodate>
</target>
<path id="javadocs.path">
<pathelement path="src"/>
<pathelement path="${build}/src"/>
</path>
<target name="javadocs" depends="javadoc_check">
<mkdir dir="${build.javadocs}"/>
<javadoc packagenames="net.hyperic.sigar.*"
excludepackagenames="net.hyperic.sigar.test.*,net.hyperic.jni.*"
useexternalfile="yes"
sourcepathref="javadocs.path"
destdir="${build.javadocs}"
author="false"
version="false"
windowtitle="Sigar API"
doctitle="Sigar">
<group title="Sigar" packages="net.hyperic.sigar" />
<classpath refid="libjars"/>
<classpath><path path="${env.ANT_HOME}/lib/ant.jar"/></classpath>
<bottom>Copyright &#169; 2004 Hyperic, LLC. All Rights Reserved.</bottom>
</javadoc>
</target>
<target name="compile">
<mkdir dir="${build}/classes"/>
<javac destdir="${build}/classes"
debug="true"
classpathref="libjars">
<src path="${src}"/>
<src path="${build}/src"/>
<src path="${jni.src.java}"/>
<include name="**/*.java"/>
</javac>
</target>
<target name="prepare-src">
<mkdir dir="${build}/src"/>
<exec executable="${perl}" dir=".">
<arg value="src/jni/generate.pl"/>
<arg value="${build}/src"/>
</exec>
<!-- include sigar *.c files rather than link against libsigar -->
<patternset id="jni.source.files">
<include name="src/*.c"/>
<include name="src/os/${jni.src}/*.c"/>
<include name="bindings/java/src/jni/javasigar.c"/>
</patternset>
<path id="jni.include.dirs">
<path location="../../include"/>
<path location="../../src/os/${jni.src}"/>
<path location="${build}/src"/>
</path>
<condition property="jni.libset.dir" value="/usr/lib">
<isset property="solaris"/>
</condition>
<condition property="jni.libset.libs" value="kstat">
<isset property="solaris"/>
</condition>
</target>
<target name="copy-includes">
<mkdir dir="${sigar-bin}/include"/>
<copy toDir="${sigar-bin}/include" overwrite="true">
<fileset dir="../../include">
<include name="sigar.h"/>
<include name="sigar_fileinfo.h"/>
</fileset>
</copy>
</target>
<target name="build-jni"
depends="jni-init,prepare-src,jni-compile,jni-lib-copy,copy-includes"
if="jni.libarch"/>
<target name="pack-jar">
<jar jarfile="${sigar-bin}/lib/sigar.jar"
basedir="${build}/classes">
<manifest>
<attribute name="Main-Class"
value="net.hyperic.sigar.cmd.Runner"/>
</manifest>
</jar>
</target>
<target name="build" depends="build-jni,compile,pack-jar"/>
<target name="clean">
<delete dir="${build}"/>
<delete dir="${sigar-bin}"/>
<delete dir="testresults"/>
</target>
<target name="xtest">
<mkdir dir="testresults"/>
<junit printsummary="yes" fork="yes"
haltonfailure="yes" showoutput="true">
<jvmarg value="-Dsigar.fqdn=${sigar.fqdn}"/>
<classpath refid="alljars"/>
<formatter type="plain"/>
<batchtest fork="yes" todir="testresults">
<fileset dir="${src}">
<include name="**/Test*.java"/>
<!-- slow; run by hand with bin/run_tests.sh Threads -->
<exclude name="**/TestThreads*.java"/>
</fileset>
</batchtest>
</junit>
</target>
<target name="test" depends="build,xtest"/>
<target name="dist">
<mkdir dir="${dist}/sigar-bin"/>
<copy toDir="${dist}/sigar-bin" overwrite="true">
<fileset dir="${sigar-bin}">
<include name="lib/*.jar"/>
<include name="lib/*.dll"/>
<include name="lib/*.sl"/>
<include name="lib/*.so"/>
<include name="lib/*.dylib"/>
</fileset>
</copy>
<zip destfile="${dist}.zip"
basedir="${build}"
includes="${dist.name}/**/*"/>
<!-- Stupid ant tar task, doesn't preserve file permissions
without making you jump through some hoops -->
<tar tarfile="${dist}.tgz"
longfile="gnu"
compression="gzip">
<tarfileset dir="${dist}/.." mode="755">
<include name="${dist.name}/**/bin/*"/>
<include name="${dist.name}/**/*.sh"/>
<include name="${dist.name}/**/*.bat"/>
<include name="${dist.name}/**/*.cmd"/>
<include name="${dist.name}/**/*.sl"/>
</tarfileset>
<tarfileset dir="${dist}/..">
<exclude name="${dist.name}/**/bin/*"/>
<exclude name="${dist.name}/**/*.sh"/>
<exclude name="${dist.name}/**/*.bat"/>
<exclude name="${dist.name}/**/*.cmd"/>
<exclude name="${dist.name}/**/*.sl"/>
<include name="${dist.name}/**"/>
</tarfileset>
</tar>
</target>
</project>

Binary file not shown.

BIN
bindings/java/lib/junit.jar Normal file

Binary file not shown.

BIN
bindings/java/lib/log4j.jar Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,974 @@
#include <jni.h>
#include "sigar.h"
#include "sigar_fileinfo.h"
#include "sigar_log.h"
#include <string.h>
#ifdef WIN32
#include <winsock.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <stdlib.h>
#endif
#include "javasigar_generated.h"
#define JENV (*env)
#define SIGAR_PACKAGE "net/hyperic/sigar/"
#define SIGAR_JNI(m) JNICALL Java_net_hyperic_sigar_##m
#define SIGAR_FIND_CLASS(name) \
JENV->FindClass(env, SIGAR_PACKAGE name)
typedef struct {
jclass classref;
jfieldID *ids;
} jsigar_field_cache_t;
typedef struct {
JNIEnv *env;
jobject logger;
sigar_t *sigar;
jsigar_field_cache_t *fields[JSIGAR_FIELDS_MAX];
int open_status;
} jni_sigar_t;
#define dSIGAR_GET \
jni_sigar_t *jsigar = sigar_get_pointer(env, sigar_obj); \
sigar_t *sigar
#define dSIGAR_VOID \
dSIGAR_GET; \
if (!jsigar) return; \
sigar = jsigar->sigar
#define dSIGAR(val) \
dSIGAR_GET; \
if (!jsigar) return val; \
sigar = jsigar->sigar
static void sigar_throw_exception(JNIEnv *env, char *msg)
{
jclass errorClass = SIGAR_FIND_CLASS("SigarException");
JENV->ThrowNew(env, errorClass, msg);
}
static void sigar_throw_notimpl(JNIEnv *env, char *msg)
{
jclass errorClass = SIGAR_FIND_CLASS("SigarNotImplementedException");
JENV->ThrowNew(env, errorClass, msg);
}
static void sigar_throw_error(JNIEnv *env, sigar_t *sigar, int err)
{
jclass errorClass;
switch (err) {
#ifndef WIN32
case ENOENT:
errorClass = SIGAR_FIND_CLASS("SigarFileNotFoundException");
break;
#else
/*XXX*/
#endif
case SIGAR_ENOTIMPL:
errorClass = SIGAR_FIND_CLASS("SigarNotImplementedException");
break;
default:
errorClass = SIGAR_FIND_CLASS("SigarException");
break;
}
JENV->ThrowNew(env, errorClass,
sigar_strerror(sigar, err));
}
static jni_sigar_t *sigar_get_pointer(JNIEnv *env, jobject obj) {
jfieldID pointer_field;
jni_sigar_t *jsigar;
jclass cls;
cls = JENV->GetObjectClass(env, obj);
pointer_field = JENV->GetFieldID(env, cls, "sigarWrapper", "I");
jsigar = (jni_sigar_t *) JENV->GetIntField(env, obj, pointer_field);
if (!jsigar) {
sigar_throw_exception(env, "sigar has been closed");
return NULL;
}
if (jsigar->open_status != SIGAR_OK) {
sigar_throw_error(env, jsigar->sigar,
jsigar->open_status);
return NULL;
}
return jsigar;
}
static void sigar_set_pointer(JNIEnv *env, jobject obj, const void *ptr) {
jfieldID pointer_field;
int pointer_int;
jclass cls;
cls = JENV->GetObjectClass(env, obj);
pointer_field = JENV->GetFieldID(env, cls, "sigarWrapper", "I");
pointer_int = (int)ptr;
JENV->SetIntField(env, obj, pointer_field, pointer_int);
}
JNIEXPORT jstring SIGAR_JNI(Sigar_formatSize)
(JNIEnv *env, jclass cls, jlong size)
{
char buf[56];
sigar_format_size(size, buf);
return JENV->NewStringUTF(env, buf);
}
JNIEXPORT void SIGAR_JNI(Sigar_open)
(JNIEnv *env, jobject obj)
{
jni_sigar_t *jsigar = malloc(sizeof(*jsigar));
memset(jsigar, '\0', sizeof(*jsigar));
sigar_set_pointer(env, obj, jsigar);
/* this method is called by the constructor.
* if != SIGAR_OK save status and throw exception
* when methods are invoked (see sigar_get_pointer).
*/
if ((jsigar->open_status = sigar_open(&jsigar->sigar)) != SIGAR_OK) {
sigar_throw_error(env, jsigar->sigar, jsigar->open_status);
return;
}
}
JNIEXPORT jint SIGAR_JNI(Sigar_nativeClose)
(JNIEnv *env, jobject sigar_obj)
{
jint status;
int i;
dSIGAR(0);
/* only place it is possible this would be something other than
* SIGAR_OK is on win32 if RegCloseKey fails, which i don't think
* is possible either.
*/
status = sigar_close(sigar);
if (jsigar->logger != NULL) {
JENV->DeleteGlobalRef(env, jsigar->logger);
}
for (i=0; i<JSIGAR_FIELDS_MAX; i++) {
if (jsigar->fields[i]) {
JENV->DeleteGlobalRef(env,
jsigar->fields[i]->classref);
free(jsigar->fields[i]->ids);
free(jsigar->fields[i]);
}
}
free(jsigar);
sigar_set_pointer(env, sigar_obj, NULL);
return status;
}
JNIEXPORT jlong SIGAR_JNI(Sigar_getPid)
(JNIEnv *env, jobject sigar_obj)
{
dSIGAR(0);
return sigar_pid_get(sigar);
}
JNIEXPORT void SIGAR_JNI(Sigar_kill)
(JNIEnv *env, jobject sigar_obj, jlong pid, jint signum)
{
int status;
dSIGAR_VOID;
if ((status = sigar_proc_kill(pid, signum)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
}
}
#define SetStringField(env, obj, fieldID, val) \
SetObjectField(env, obj, fieldID, JENV->NewStringUTF(env, val))
static jstring jinet_ntoa(JNIEnv *env, sigar_t *sigar, sigar_uint64_t val) {
char addr_str[SIGAR_INET_ADDR_LEN];
sigar_inet_ntoa(sigar, val, addr_str);
return JENV->NewStringUTF(env, addr_str);
}
#define SetNetAddrField(env, obj, fieldID, val) \
SetObjectField(env, obj, fieldID, jinet_ntoa(env, sigar, val))
#include "javasigar_generated.c"
#define SIGAR_CLASS_SIG(name) \
"L" SIGAR_PACKAGE name ";"
#define SIGAR_ALLOC_OBJECT(name) \
JENV->AllocObject(env, SIGAR_FIND_CLASS(name))
enum {
FS_FIELD_DIRNAME,
FS_FIELD_DEVNAME,
FS_FIELD_SYS_TYPENAME,
FS_FIELD_TYPE,
FS_FIELD_TYPENAME,
FS_FIELD_MAX
};
#define STRING_SIG "Ljava/lang/String;"
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getFileSystemList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_file_system_list_t fslist;
jobjectArray fsarray;
jfieldID ids[FS_FIELD_MAX];
jclass cls = SIGAR_FIND_CLASS("FileSystem");
dSIGAR(NULL);
if ((status = sigar_file_system_list_get(sigar, &fslist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
ids[FS_FIELD_DIRNAME] =
JENV->GetFieldID(env, cls, "dirName", STRING_SIG);
ids[FS_FIELD_DEVNAME] =
JENV->GetFieldID(env, cls, "devName", STRING_SIG);
ids[FS_FIELD_TYPENAME] =
JENV->GetFieldID(env, cls, "typeName", STRING_SIG);
ids[FS_FIELD_SYS_TYPENAME] =
JENV->GetFieldID(env, cls, "sysTypeName", STRING_SIG);
ids[FS_FIELD_TYPE] =
JENV->GetFieldID(env, cls, "type", "I");
fsarray = JENV->NewObjectArray(env, fslist.number, cls, 0);
for (i=0; i<fslist.number; i++) {
sigar_file_system_t *fs = &(fslist.data)[i];
jobject fsobj = JENV->AllocObject(env, cls);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_DIRNAME],
fs->dir_name);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_DEVNAME],
fs->dev_name);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_SYS_TYPENAME],
fs->sys_type_name);
JENV->SetStringField(env, fsobj,
ids[FS_FIELD_TYPENAME],
fs->type_name);
JENV->SetIntField(env, fsobj,
ids[FS_FIELD_TYPE],
fs->type);
JENV->SetObjectArrayElement(env, fsarray, i, fsobj);
}
sigar_file_system_list_destroy(sigar, &fslist);
return fsarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getCpuInfoList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_cpu_infos_t cpu_infos;
jobjectArray cpuarray;
jclass cls = SIGAR_FIND_CLASS("CpuInfo");
dSIGAR(NULL);
if ((status = sigar_cpu_infos_get(sigar, &cpu_infos)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_CPUINFO(cls);
cpuarray = JENV->NewObjectArray(env, cpu_infos.number, cls, 0);
for (i=0; i<cpu_infos.number; i++) {
jobject info_obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_CPUINFO(cls, info_obj,
cpu_infos.data[i]);
JENV->SetObjectArrayElement(env, cpuarray, i, info_obj);
}
sigar_cpu_infos_destroy(sigar, &cpu_infos);
return cpuarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getCpuListNative)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_cpu_list_t cpulist;
jobjectArray cpuarray;
jclass cls = SIGAR_FIND_CLASS("Cpu");
dSIGAR(NULL);
if ((status = sigar_cpu_list_get(sigar, &cpulist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_CPU(cls);
cpuarray = JENV->NewObjectArray(env, cpulist.number, cls, 0);
for (i=0; i<cpulist.number; i++) {
jobject info_obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_CPU(cls, info_obj,
cpulist.data[i]);
JENV->SetObjectArrayElement(env, cpuarray, i, info_obj);
}
sigar_cpu_list_destroy(sigar, &cpulist);
return cpuarray;
}
JNIEXPORT jlongArray SIGAR_JNI(Sigar_getProcList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
jlongArray procarray;
sigar_proc_list_t proclist;
jlong *pids = NULL;
dSIGAR(NULL);
if ((status = sigar_proc_list_get(sigar, &proclist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
procarray = JENV->NewLongArray(env, proclist.number);
if (sizeof(jlong) == sizeof(sigar_pid_t)) {
pids = (jlong *)proclist.data;
}
else {
unsigned int i;
pids = (jlong *)malloc(sizeof(jlong) * proclist.number);
for (i=0; i<proclist.number; i++) {
pids[i] = proclist.data[i];
}
}
JENV->SetLongArrayRegion(env, procarray, 0,
proclist.number, pids);
if (pids != (jlong *)proclist.data) {
free(pids);
}
sigar_proc_list_destroy(sigar, &proclist);
return procarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getProcArgs)
(JNIEnv *env, jobject sigar_obj, jlong pid)
{
int status;
unsigned int i;
sigar_proc_args_t procargs;
jobjectArray argsarray;
jclass stringclass = JENV->FindClass(env, "java/lang/String");
dSIGAR(NULL);
if ((status = sigar_proc_args_get(sigar, pid, &procargs)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
argsarray = JENV->NewObjectArray(env, procargs.number, stringclass, 0);
for (i=0; i<procargs.number; i++) {
jstring s = JENV->NewStringUTF(env, procargs.data[i]);
JENV->SetObjectArrayElement(env, argsarray, i, s);
}
sigar_proc_args_destroy(sigar, &procargs);
return argsarray;
}
typedef struct {
JNIEnv *env;
jobject map;
jmethodID id;
} jni_env_put_t;
static int jni_env_getall(void *data,
const char *key, int klen,
char *val, int vlen)
{
jni_env_put_t *put = (jni_env_put_t *)data;
JNIEnv *env = put->env;
JENV->CallObjectMethod(env, put->map, put->id,
JENV->NewStringUTF(env, key),
JENV->NewStringUTF(env, val));
return SIGAR_OK;
}
JNIEXPORT jobject SIGAR_JNI(ProcEnv_getAll)
(JNIEnv *env, jobject cls, jobject sigar_obj, jlong pid)
{
int status;
sigar_proc_env_t procenv;
jobject hashmap;
jni_env_put_t put;
jclass mapclass =
JENV->FindClass(env, "java/util/HashMap");
jmethodID mapid =
JENV->GetMethodID(env, mapclass, "<init>", "()V");
jmethodID putid =
JENV->GetMethodID(env, mapclass, "put",
"(Ljava/lang/Object;Ljava/lang/Object;)"
"Ljava/lang/Object;");
dSIGAR(NULL);
hashmap = JENV->NewObject(env, mapclass, mapid);
put.env = env;
put.id = putid;
put.map = hashmap;
procenv.type = SIGAR_PROC_ENV_ALL;
procenv.env_getter = jni_env_getall;
procenv.data = &put;
if ((status = sigar_proc_env_get(sigar, pid, &procenv)) != SIGAR_OK) {
JENV->DeleteLocalRef(env, hashmap);
sigar_throw_error(env, sigar, status);
return NULL;
}
return hashmap;
}
typedef struct {
JNIEnv *env;
const char *key;
int klen;
jstring val;
} jni_env_get_t;
static int jni_env_getvalue(void *data,
const char *key, int klen,
char *val, int vlen)
{
jni_env_get_t *get = (jni_env_get_t *)data;
JNIEnv *env = get->env;
if ((get->klen == klen) &&
(strcmp(get->key, key) == 0))
{
get->val = JENV->NewStringUTF(env, val);
return !SIGAR_OK; /* foundit; stop iterating */
}
return SIGAR_OK;
}
JNIEXPORT jstring SIGAR_JNI(ProcEnv_getValue)
(JNIEnv *env, jobject cls, jobject sigar_obj, jlong pid, jstring key)
{
int status;
sigar_proc_env_t procenv;
jni_env_get_t get;
dSIGAR(NULL);
get.env = env;
get.key = JENV->GetStringUTFChars(env, key, 0);
get.klen = JENV->GetStringUTFLength(env, key);
get.val = NULL;
procenv.type = SIGAR_PROC_ENV_KEY;
procenv.key = get.key;
procenv.klen = get.klen;
procenv.env_getter = jni_env_getvalue;
procenv.data = &get;
if ((status = sigar_proc_env_get(sigar, pid, &procenv)) != SIGAR_OK) {
JENV->ReleaseStringUTFChars(env, key, get.key);
sigar_throw_error(env, sigar, status);
return NULL;
}
JENV->ReleaseStringUTFChars(env, key, get.key);
return get.val;
}
JNIEXPORT jdoubleArray SIGAR_JNI(Sigar_getLoadAverage)
(JNIEnv *env, jobject sigar_obj)
{
int status;
jlongArray avgarray;
sigar_loadavg_t loadavg;
dSIGAR(NULL);
if ((status = sigar_loadavg_get(sigar, &loadavg)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
avgarray = JENV->NewDoubleArray(env, 3);
JENV->SetDoubleArrayRegion(env, avgarray, 0,
3, loadavg.loadavg);
return avgarray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getNetRouteList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
jarray routearray;
jclass cls = SIGAR_FIND_CLASS("NetRoute");
sigar_net_route_list_t routelist;
dSIGAR(NULL);
if ((status = sigar_net_route_list_get(sigar, &routelist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_NETROUTE(cls);
routearray = JENV->NewObjectArray(env, routelist.number, cls, 0);
for (i=0; i<routelist.number; i++) {
jobject obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_NETROUTE(cls, obj, routelist.data[i]);
JENV->SetObjectArrayElement(env, routearray, i, obj);
}
sigar_net_route_list_destroy(sigar, &routelist);
return routearray;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getNetConnectionList)
(JNIEnv *env, jobject sigar_obj, jint flags)
{
int status;
unsigned int i;
jarray connarray;
jclass cls = SIGAR_FIND_CLASS("NetConnection");
sigar_net_connection_list_t connlist;
dSIGAR(NULL);
status = sigar_net_connection_list_get(sigar, &connlist, flags);
if (status != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
JAVA_SIGAR_INIT_FIELDS_NETCONNECTION(cls);
connarray = JENV->NewObjectArray(env, connlist.number, cls, 0);
for (i=0; i<connlist.number; i++) {
jobject obj = JENV->AllocObject(env, cls);
JAVA_SIGAR_SET_FIELDS_NETCONNECTION(cls, obj, connlist.data[i]);
JENV->SetObjectArrayElement(env, connarray, i, obj);
}
sigar_net_connection_list_destroy(sigar, &connlist);
return connarray;
}
JNIEXPORT jstring SIGAR_JNI(NetConnection_getTypeString)
(JNIEnv *env, jobject obj)
{
jclass cls = JENV->GetObjectClass(env, obj);
jfieldID field = JENV->GetFieldID(env, cls, "type", "I");
jint type = JENV->GetIntField(env, obj, field);
return JENV->NewStringUTF(env,
sigar_net_connection_type_get(type));
}
/* XXX perhaps it would be better to duplicate these strings
* in java land as static final so we dont create a new String
* everytime.
*/
JNIEXPORT jstring SIGAR_JNI(FileInfo_getTypeString)
(JNIEnv *env, jclass cls, jint type)
{
return JENV->NewStringUTF(env,
sigar_file_attrs_type_string_get(type));
}
JNIEXPORT jstring SIGAR_JNI(FileInfo_getPermissionsString)
(JNIEnv *env, jclass cls, jlong perms)
{
char str[24];
return JENV->NewStringUTF(env,
sigar_file_attrs_permissions_string_get(perms,
str));
}
JNIEXPORT jint SIGAR_JNI(FileInfo_getMode)
(JNIEnv *env, jclass cls, jlong perms)
{
return sigar_file_attrs_mode_get(perms);
}
/*
* copy of the generated FileAttrs_nativeGet function
* but we call the lstat wrapper instead.
*/
JNIEXPORT void SIGAR_JNI(FileInfo_nativeGetLink)
(JNIEnv *env, jobject obj, jobject sigar_obj, jstring name)
{
sigar_file_attrs_t s;
int status;
jclass cls = JENV->GetObjectClass(env, obj);
const char *utf;
dSIGAR_VOID;
utf = JENV->GetStringUTFChars(env, name, 0);
status = sigar_link_attrs_get(sigar, utf, &s);
JENV->ReleaseStringUTFChars(env, name, utf);
if (status != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return;
}
JAVA_SIGAR_INIT_FIELDS_FILEATTRS(cls);
JAVA_SIGAR_SET_FIELDS_FILEATTRS(cls, obj, s);
}
JNIEXPORT jlong SIGAR_JNI(Sigar_getProcPort)
(JNIEnv *env, jobject sigar_obj, jlong port)
{
int status;
sigar_pid_t pid;
dSIGAR(0);
#if defined(__linux__) || defined(WIN32)
/* just thinking about implementing this on other platforms hurts */
if ((status = sigar_proc_port_get(sigar, (unsigned long)port, &pid)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
}
#else
status = SIGAR_ENOTIMPL;
pid = -1;
sigar_throw_error(env, sigar, status);
#endif
return pid;
}
JNIEXPORT jobjectArray SIGAR_JNI(Sigar_getNetInterfaceList)
(JNIEnv *env, jobject sigar_obj)
{
int status;
unsigned int i;
sigar_net_interface_list_t iflist;
jobjectArray ifarray;
jclass stringclass = JENV->FindClass(env, "java/lang/String");
dSIGAR(NULL);
if ((status = sigar_net_interface_list_get(sigar, &iflist)) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
ifarray = JENV->NewObjectArray(env, iflist.number, stringclass, 0);
for (i=0; i<iflist.number; i++) {
jstring s = JENV->NewStringUTF(env, iflist.data[i]);
JENV->SetObjectArrayElement(env, ifarray, i, s);
}
sigar_net_interface_list_destroy(sigar, &iflist);
return ifarray;
}
JNIEXPORT jstring SIGAR_JNI(Sigar_getPasswordNative)
(JNIEnv *env, jclass classinstance, jstring prompt)
{
const char *prompt_str;
char *password;
if (getenv("NO_NATIVE_GETPASS")) {
sigar_throw_notimpl(env, "disabled with $NO_NATIVE_GETPASS");
return NULL;
}
prompt_str = JENV->GetStringUTFChars(env, prompt, 0);
password = sigar_password_get(prompt_str);
JENV->ReleaseStringUTFChars(env, prompt, prompt_str);
return JENV->NewStringUTF(env, password);
}
JNIEXPORT jstring SIGAR_JNI(Sigar_getFQDN)
(JNIEnv *env, jobject sigar_obj)
{
char fqdn[SIGAR_FQDN_LEN];
int status;
dSIGAR(NULL);
if ((status = sigar_fqdn_get(sigar, fqdn, sizeof(fqdn))) != SIGAR_OK) {
sigar_throw_error(env, sigar, status);
return NULL;
}
return JENV->NewStringUTF(env, fqdn);
}
#include "sigar_getline.h"
JNIEXPORT jstring SIGAR_JNI(util_Getline_getline)
(JNIEnv *env, jobject sigar_obj, jstring prompt)
{
const char *prompt_str;
char *line;
jboolean is_copy;
prompt_str = JENV->GetStringUTFChars(env, prompt, &is_copy);
line = sigar_getline((char *)prompt_str);
if (is_copy) {
JENV->ReleaseStringUTFChars(env, prompt, prompt_str);
}
if ((line == NULL) ||
sigar_getline_eof())
{
jclass eof_ex = JENV->FindClass(env, "java/io/EOFException");
JENV->ThrowNew(env, eof_ex, "");
return NULL;
}
return JENV->NewStringUTF(env, line);
}
JNIEXPORT void SIGAR_JNI(util_Getline_histadd)
(JNIEnv *env, jobject sigar_obj, jstring hist)
{
const char *hist_str;
jboolean is_copy;
hist_str = JENV->GetStringUTFChars(env, hist, &is_copy);
sigar_getline_histadd((char *)hist_str);
if (is_copy) {
JENV->ReleaseStringUTFChars(env, hist, hist_str);
}
}
JNIEXPORT void SIGAR_JNI(util_Getline_histinit)
(JNIEnv *env, jobject sigar_obj, jstring hist)
{
const char *hist_str;
jboolean is_copy;
hist_str = JENV->GetStringUTFChars(env, hist, &is_copy);
sigar_getline_histinit((char *)hist_str);
if (is_copy) {
JENV->ReleaseStringUTFChars(env, hist, hist_str);
}
}
static struct {
JNIEnv *env;
jobject obj;
jmethodID id;
jclass clazz;
} jsigar_completer;
static int jsigar_getline_completer(char *buffer, int offset, int *pos)
{
JNIEnv *env = jsigar_completer.env;
jstring jbuffer;
jstring completion;
const char *line;
int len, cur;
jboolean is_copy;
jbuffer = JENV->NewStringUTF(env, buffer);
completion =
JENV->CallObjectMethod(env, jsigar_completer.obj,
jsigar_completer.id, jbuffer);
if (JENV->ExceptionOccurred(env)) {
JENV->ExceptionDescribe(env);
return 0;
}
if (!completion) {
return 0;
}
line = JENV->GetStringUTFChars(env, completion, &is_copy);
len = JENV->GetStringUTFLength(env, completion);
cur = *pos;
if (len != cur) {
strcpy(buffer, line);
*pos = len;
}
if (is_copy) {
JENV->ReleaseStringUTFChars(env, completion, line);
}
return cur;
}
JNIEXPORT void SIGAR_JNI(util_Getline_setCompleter)
(JNIEnv *env, jclass classinstance, jobject completer)
{
if (completer == NULL) {
sigar_getline_completer_set(NULL);
return;
}
jsigar_completer.env = env;
jsigar_completer.obj = completer;
jsigar_completer.clazz = JENV->GetObjectClass(env, completer);
jsigar_completer.id =
JENV->GetMethodID(env, jsigar_completer.clazz,
"complete",
"(Ljava/lang/String;)Ljava/lang/String;");
sigar_getline_completer_set(jsigar_getline_completer);
}
JNIEXPORT void SIGAR_JNI(util_Getline_redraw)
(JNIEnv *env, jobject obj)
{
sigar_getline_redraw();
}
JNIEXPORT void SIGAR_JNI(util_Getline_reset)
(JNIEnv *env, jobject obj)
{
sigar_getline_reset();
}
static const char *log_methods[] = {
"fatal", /* SIGAR_LOG_FATAL */
"error", /* SIGAR_LOG_ERROR */
"warn", /* SIGAR_LOG_WARN */
"info", /* SIGAR_LOG_INFO */
"debug", /* SIGAR_LOG_DEBUG */
/* XXX trace is only in commons-logging??? */
"debug", /* SIGAR_LOG_TRACE */
};
static void jsigar_log_impl(sigar_t *sigar, void *data,
int level, char *message)
{
jni_sigar_t *jsigar = (jni_sigar_t *)data;
JNIEnv *env = jsigar->env;
jobject logger = jsigar->logger;
jobject message_obj;
/* XXX should cache method id lookups */
jmethodID id =
JENV->GetMethodID(env, JENV->GetObjectClass(env, logger),
log_methods[level],
"(Ljava/lang/Object;)V");
if (JENV->ExceptionOccurred(env)) {
JENV->ExceptionDescribe(env);
return;
}
message_obj = (jobject)JENV->NewStringUTF(env, message);
JENV->CallObjectMethod(env, logger, id, message_obj);
}
JNIEXPORT void SIGAR_JNI(SigarLog_setLogger)
(JNIEnv *env, jclass classinstance, jobject sigar_obj, jobject logger)
{
dSIGAR_VOID;
jsigar->env = env;
if (jsigar->logger != NULL) {
JENV->DeleteGlobalRef(env, jsigar->logger);
jsigar->logger = NULL;
}
if (logger) {
jsigar->logger = JENV->NewGlobalRef(env, logger);
sigar_log_impl_set(sigar, jsigar, jsigar_log_impl);
}
else {
sigar_log_impl_set(sigar, NULL, NULL);
}
}
JNIEXPORT void SIGAR_JNI(SigarLog_setLevel)
(JNIEnv *env, jclass classinstance, jobject sigar_obj, jint level)
{
dSIGAR_VOID;
sigar_log_level_set(sigar, level);
}

View File

@ -0,0 +1,89 @@
package net.hyperic.sigar;
/**
* CPU percentage usage
*/
public class CpuPerc {
private double user;
private double sys;
private double nice;
private double idle;
CpuPerc(){ }
static CpuPerc calculate(Cpu oldCpu, Cpu curCpu) {
double diffUser, diffSys, diffNice, diffIdle, diffTotal;
diffUser = curCpu.getUser() - oldCpu.getUser();
diffSys = curCpu.getSys() - oldCpu.getSys();
diffNice = curCpu.getNice() - oldCpu.getNice();
diffIdle = curCpu.getIdle() - oldCpu.getIdle();
// Sanity check -- sometimes these values waiver in between
// whole numbers when Cpu is checked very rapidly
diffUser = diffUser < 0 ? 0 : diffUser;
diffSys = diffSys < 0 ? 0 : diffSys;
diffNice = diffNice < 0 ? 0 : diffNice;
diffIdle = diffIdle < 0 ? 0 : diffIdle;
diffTotal = diffUser + diffSys + diffNice + diffIdle;
CpuPerc perc = new CpuPerc();
perc.setUser(diffUser / diffTotal);
perc.setSys(diffSys / diffTotal);
perc.setNice(diffNice / diffTotal);
perc.setIdle(diffIdle / diffTotal);
return perc;
}
public double getUser(){
return this.user;
}
void setUser(double user){
this.user = user;
}
public double getSys(){
return this.sys;
}
void setSys(double sys){
this.sys = sys;
}
public double getNice(){
return this.nice;
}
void setNice(double nice){
this.nice = nice;
}
public double getIdle(){
return this.idle;
}
void setIdle(double idle){
this.idle = idle;
}
public static String format(double val) {
String p = String.valueOf(val * 100.0);
//cant wait for sprintf.
int ix = p.indexOf(".") + 1;
String percent =
p.substring(0, ix) +
p.substring(ix, ix+1);
return percent + "%";
}
public String toString() {
return
"CPU states: " +
format(this.user) + " user, " +
format(this.sys) + " system, " +
format(this.nice) + " nice, " +
format(this.idle) + " idle";
}
}

View File

@ -0,0 +1,73 @@
package net.hyperic.sigar;
public class CurrentProcessSummary {
private int total=0, sleeping=0, running=0, zombie=0, stopped=0;
private CurrentProcessSummary() { }
public static CurrentProcessSummary get(SigarProxy sigar)
throws SigarException {
long[] pids = sigar.getProcList();
CurrentProcessSummary summary =
new CurrentProcessSummary();
for (int i=0; i<pids.length; i++) {
ProcState state;
try {
state = sigar.getProcState(pids[i]);
} catch (SigarException e) {
continue; //e.g. stale pid
}
summary.total++;
switch (state.getState()) {
case ProcState.RUN:
summary.running++;
break;
case ProcState.STOP:
summary.stopped++;
break;
case ProcState.SLEEP:
summary.sleeping++;
break;
case ProcState.ZOMBIE:
summary.zombie++;
break;
}
}
return summary;
}
public int getTotal() {
return this.total;
}
public int getSleeping() {
return this.sleeping;
}
public int getRunning() {
return this.running;
}
public int getZombie() {
return this.zombie;
}
public int getStopped() {
return this.stopped;
}
public String toString() {
return
this.total + " processes: " +
this.sleeping + " sleeping, " +
this.running + " running, " +
this.zombie + " zombie, " +
this.stopped + " stopped";
}
}

View File

@ -0,0 +1,429 @@
package net.hyperic.sigar;
import java.io.File;
import java.util.Date;
public class FileInfo extends FileAttrs {
String name;
private Sigar sigar;
private boolean dirStatEnabled = false;
private DirStat stat = null;
private boolean lstat;
private FileInfo oldInfo = null;
private static char DIFF_SEP = '|';
/**
* No file type determined.
*/
public static final int TYPE_NOFILE = 0;
/**
* A regular file.
*/
public static final int TYPE_REG = 1;
/**
* A directory.
*/
public static final int TYPE_DIR = 2;
/**
* A character device.
*/
public static final int TYPE_CHR = 3;
/**
* A block device.
*/
public static final int TYPE_BLK = 4;
/**
* A FIFO / pipe.
*/
public static final int TYPE_PIPE = 5;
/**
* A symbolic link.
*/
public static final int TYPE_LNK = 6;
/**
* A [unix domain] socket.
*/
public static final int TYPE_SOCK = 7;
/**
* A file of unknown type.
*/
public static final int TYPE_UNKFILE = 8;
/**
* Readable by user.
*/
public static final int MODE_UREAD = 0x0400;
/**
* Writable by user.
*/
public static final int MODE_UWRITE = 0x0200;
/**
* Executable by user.
*/
public static final int MODE_UEXECUTE = 0x0100;
/**
* Readable by group.
*/
public static final int MODE_GREAD = 0x0040;
/**
* Writable by group.
*/
public static final int MODE_GWRITE = 0x0020;
/**
* Executable by group.
*/
public static final int MODE_GEXECUTE = 0x0010;
/**
* Readable by others.
*/
public static final int MODE_WREAD = 0x0004;
/**
* Writable by others.
*/
public static final int MODE_WWRITE = 0x0002;
/**
* Executable by others.
*/
public static final int MODE_WEXECUTE = 0x0001;
private static native String getTypeString(int type);
native void nativeGetLink(Sigar sigar, String name)
throws SigarException;
public String getTypeString() {
return FileInfo.getTypeString(this.type);
}
public char getTypeChar() {
switch (this.type) {
case TYPE_DIR:
return 'd';
case TYPE_CHR:
return 'c';
case TYPE_BLK:
return 'b';
case TYPE_PIPE:
return 'p';
case TYPE_LNK:
return 'l';
case TYPE_SOCK:
return 's';
default:
return '-';
}
}
public String getName() {
return this.name;
}
public int hashCode() {
return this.name.hashCode();
}
public boolean equals(Object o) {
return o.equals(this.name);
}
private static native String getPermissionsString(long type);
public String getPermissionsString() {
return FileInfo.getPermissionsString(this.permissions);
}
private static native int getMode(long permissions);
/**
* Convert permissions bit mask to human readable number.
* Example:
* <code>MODE_UREAD|MODE_UWRITE|MODE_GREAD|MODE_WREAD</code>
* converts to <code>644</code>.
* @return The file permissions mode.
*/
public int getMode() {
return FileInfo.getMode(this.permissions);
}
public void enableDirStat(boolean value) {
this.dirStatEnabled = value;
if (value) {
if (this.type != TYPE_DIR) {
throw new IllegalArgumentException(this.name + " is not a directory");
}
try {
if (this.stat == null) {
this.stat = this.sigar.getDirStat(this.name);
}
else {
this.stat.nativeGet(this.sigar, this.name);
}
} catch (SigarException e) {
//ok for now
}
}
}
public String diff() {
if (this.oldInfo == null) {
return "";
}
return diff(this.oldInfo);
}
public String diff(DirStat stat) {
DirStat thisStat = this.stat;
StringBuffer sb = new StringBuffer();
if (thisStat.files != stat.files) {
sb.append("Files........").
append(stat.files).
append(DIFF_SEP).
append(thisStat.files).
append("\n");
}
if (thisStat.subdirs != stat.subdirs) {
sb.append("Subdirs......").
append(stat.subdirs).
append(DIFF_SEP).
append(thisStat.subdirs).
append("\n");
}
if (thisStat.symlinks != stat.symlinks) {
sb.append("Symlinks.....").
append(stat.symlinks).
append(DIFF_SEP).
append(thisStat.symlinks).
append("\n");
}
if (thisStat.chrdevs != stat.chrdevs) {
sb.append("Chrdevs......").
append(stat.chrdevs).
append(DIFF_SEP).
append(thisStat.chrdevs).
append("\n");
}
if (thisStat.blkdevs != stat.blkdevs) {
sb.append("Blkdevs......").
append(stat.blkdevs).
append(DIFF_SEP).
append(thisStat.blkdevs).
append("\n");
}
if (thisStat.sockets != stat.sockets) {
sb.append("Sockets......").
append(stat.sockets).
append(DIFF_SEP).
append(thisStat.sockets).
append("\n");
}
if (thisStat.total != stat.total) {
sb.append("Total........").
append(stat.total).
append(DIFF_SEP).
append(thisStat.total).
append("\n");
}
return sb.toString();
}
public String diff(FileInfo info) {
StringBuffer sb = new StringBuffer();
boolean changed = false;
if (this.ctime != info.ctime) {
sb.append("Ctime........").
append(new Date(info.ctime)).
append(DIFF_SEP).
append(new Date(info.ctime)).
append("\n");
changed = true;
}
if (this.mtime != info.mtime) {
sb.append("Mtime........").
append(new Date(info.mtime)).
append(DIFF_SEP).
append(new Date(this.mtime)).
append("\n");
}
else if (!changed) {
//no point in checking the rest if all times are the same.
//or should we include atime in the diff?
return "";
}
if (this.atime != info.atime) {
sb.append("Atime........").
append(new Date(info.atime)).
append(DIFF_SEP).
append(new Date(this.atime)).
append("\n");
}
if (this.permissions != info.permissions) {
sb.append("Permissions..").
append(getPermissionsString(info.permissions)).
append(DIFF_SEP).
append(getPermissionsString(this.permissions)).
append("\n");
}
if (this.type != info.type) {
sb.append("Type.........").
append(getTypeString(info.type)).
append(DIFF_SEP).
append(getTypeString(this.type)).
append("\n");
}
if (this.uid != info.uid) {
sb.append("Uid..........").
append(info.uid).
append(DIFF_SEP).
append(this.uid).
append("\n");
}
if (this.gid != info.gid) {
sb.append("Gid..........").
append(info.gid).
append(DIFF_SEP).
append(this.gid).
append("\n");
}
if (this.inode != info.inode) {
sb.append("Inode........").
append(info.inode).
append(DIFF_SEP).
append(this.inode).
append("\n");
}
if (this.device != info.device) {
sb.append("Device.......").
append(info.device).
append(DIFF_SEP).
append(this.device).
append("\n");
}
if (this.nlink != info.nlink) {
sb.append("Nlink........").
append(info.nlink).
append(DIFF_SEP).
append(this.nlink).
append("\n");
}
if (this.size != info.size) {
sb.append("Size.........").
append(info.size).
append(DIFF_SEP).
append(this.size).
append("\n");
}
if (this.dirStatEnabled) {
sb.append(diff(info.stat));
}
return sb.toString();
}
public FileInfo getPreviousInfo() {
return this.oldInfo;
}
public boolean modified()
throws SigarException,
SigarFileNotFoundException {
if (this.oldInfo == null) {
this.oldInfo = new FileInfo();
if (this.dirStatEnabled) {
this.oldInfo.stat = new DirStat();
}
}
copyTo(this.oldInfo);
if (this.dirStatEnabled) {
this.stat.copyTo(this.oldInfo.stat);
}
stat();
return this.mtime != oldInfo.mtime;
}
public boolean changed()
throws SigarException,
SigarFileNotFoundException {
return modified() || (this.ctime != oldInfo.ctime);
}
public void stat()
throws SigarException,
SigarFileNotFoundException {
long mtime = this.mtime;
if (this.lstat) {
this.nativeGetLink(this.sigar, this.name);
}
else {
this.nativeGet(this.sigar, this.name);
}
if (this.dirStatEnabled &&
(mtime != this.mtime)) //no need to fetch stat if unmodified.
{
this.stat.nativeGet(this.sigar, this.name);
}
}
private static FileInfo fetchInfo(Sigar sigar, String name,
boolean followSymlinks)
throws SigarException {
FileInfo info = new FileInfo();
if (followSymlinks) {
info.nativeGet(sigar, name);
info.lstat = false;
}
else {
info.nativeGetLink(sigar, name);
info.lstat = true;
}
info.sigar = sigar;
info.name = name;
return info;
}
static FileInfo fetchFileInfo(Sigar sigar, String name)
throws SigarException {
return fetchInfo(sigar, name, true);
}
static FileInfo fetchLinkInfo(Sigar sigar, String name)
throws SigarException {
return fetchInfo(sigar, name, false);
}
}

View File

@ -0,0 +1,76 @@
package net.hyperic.sigar;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import java.io.File;
/**
* Helper class to build a map of mounted file systems.
*/
public class FileSystemMap extends HashMap {
/**
* FileSystemMap is read-only, this method is unsupported.
* @see #init
*/
public Object put(Object key, Object value) {
throw new UnsupportedOperationException();
}
/**
* Populate the map. FileSystem.getDirName is used as the map key.
*/
public void init(FileSystem[] fslist) {
super.clear();
for (int i=0; i<fslist.length; i++) {
super.put(fslist[i].getDirName(), fslist[i]);
}
}
public FileSystem getFileSystem(String name) {
return (FileSystem)get(name);
}
public boolean isMounted(String name) {
return (get(name) != null);
}
/**
* Find the file system the given file or directory is within.
* @return FileSystem or null if file or directory name does not exist.
*/
public FileSystem getMountPoint(String name) {
FileSystem fs = getFileSystem(name);
if (fs != null) {
return fs;
}
File dir = new File(name);
if (!dir.exists()) {
return null;
}
try {
dir = dir.getCanonicalFile();
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
if (!dir.isDirectory()) {
dir = dir.getParentFile();
}
do {
fs = getFileSystem(dir.toString());
if (fs != null) {
return fs;
}
dir = dir.getParentFile();
} while (dir != null);
return null;
}
}

View File

@ -0,0 +1,63 @@
package net.hyperic.sigar;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
public abstract class FileTail extends FileWatcher {
private HashMap offsets = new HashMap();
public abstract void tail(FileInfo info, Reader reader);
public FileTail(Sigar sigar) {
super(sigar);
}
public void onChange(FileInfo info) {
long len = info.size;
Reader reader = null;
try {
reader = new FileReader(info.getName());
reader.skip(getOffset(info));
tail(info, reader);
setOffset(info);
} catch (IOException e) {
//XXX
e.printStackTrace();
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException e) { }
}
}
}
public FileInfo add(String file)
throws SigarException {
FileInfo info = super.add(file);
setOffset(info);
return info;
}
protected boolean changed(FileInfo info)
throws SigarException,
SigarFileNotFoundException {
return info.modified();
}
private long getOffset(FileInfo info) {
Long offset = (Long)this.offsets.get(info);
return offset.longValue();
}
private void setOffset(FileInfo info) {
this.offsets.put(info, new Long(info.size));
}
}

View File

@ -0,0 +1,120 @@
package net.hyperic.sigar;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public abstract class FileWatcher {
private Sigar sigar;
private long interval = 0;
private long lastTime = 0;
private Set files =
Collections.synchronizedSet(new HashSet());
public abstract void onChange(FileInfo info);
public void onNotFound(FileInfo info) {
}
public void onException(FileInfo info, SigarException e) {
}
public FileWatcher(Sigar sigar) {
this.sigar = sigar;
}
public void setInterval(long interval) {
this.interval = interval;
}
public long getInterval() {
return this.interval;
}
public FileInfo add(File file)
throws SigarException {
return add(file.getAbsolutePath());
}
public FileInfo add(String file)
throws SigarException {
FileInfo info = this.sigar.getFileInfo(file);
this.files.add(info);
return info;
}
public void add(File[] files)
throws SigarException {
for (int i=0; i<files.length; i++) {
add(files[i]);
}
}
public void add(String[] files)
throws SigarException {
for (int i=0; i<files.length; i++) {
add(files[i]);
}
}
public void remove(File file) {
remove(file.getAbsolutePath());
}
public void remove(String file) {
FileInfo info = new FileInfo();
info.name = file;
this.files.remove(info);
}
public void clear() {
this.files.clear();
}
public Set getFiles() {
return this.files;
}
protected boolean changed(FileInfo info)
throws SigarException,
SigarFileNotFoundException {
return info.changed();
}
public void check() {
if (this.interval != 0) {
long timeNow = System.currentTimeMillis();
long timeDiff = timeNow - this.lastTime;
if (timeDiff < this.interval) {
return;
}
this.lastTime = timeNow;
}
synchronized (this.files) {
for (Iterator it = this.files.iterator();
it.hasNext();)
{
FileInfo info = (FileInfo)it.next();
try {
if (changed(info)) {
this.onChange(info);
}
} catch (SigarFileNotFoundException e) {
this.onNotFound(info);
} catch (SigarException e) {
this.onException(info, e);
}
}
}
}
}

View File

@ -0,0 +1,89 @@
package net.hyperic.sigar;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class FileWatcherThread implements Runnable {
public static final int DEFAULT_INTERVAL = 60 * 5 * 1000;
private Thread thread = null;
private static FileWatcherThread instance = null;
private boolean shouldDie = false;
private long interval = DEFAULT_INTERVAL;
private Set watchers =
Collections.synchronizedSet(new HashSet());
public static synchronized FileWatcherThread getInstance() {
if (instance == null) {
instance = new FileWatcherThread();
}
return instance;
}
public synchronized void doStart() {
if (this.thread != null) {
return;
}
this.thread = new Thread(this, "FileWatcherThread");
this.thread.setDaemon(true);
this.thread.start();
}
public synchronized void doStop() {
if (this.thread == null) {
return;
}
die();
this.thread.interrupt();
this.thread = null;
}
public void setInterval(long interval) {
this.interval = interval;
}
public long getInterval() {
return this.interval;
}
public void add(FileWatcher watcher) {
this.watchers.add(watcher);
}
public void remove(FileWatcher watcher) {
this.watchers.remove(watcher);
}
public void run() {
while (!shouldDie) {
check();
try {
Thread.sleep(this.interval);
} catch (InterruptedException e) {
}
}
}
public void die() {
this.shouldDie = true;
}
public void check() {
synchronized (this.watchers) {
for (Iterator it = this.watchers.iterator();
it.hasNext();)
{
FileWatcher watcher = (FileWatcher)it.next();
watcher.check();
}
}
}
}

View File

@ -0,0 +1,117 @@
package net.hyperic.sigar;
/**
* Flag constants for network related ops.
*/
public class NetFlags {
private NetFlags () { }
/**
* value of unknown or non-existent hardware address
*/
public final static String NULL_HWADDR = "00:00:00:00:00:00";
/**
* interface is up
*/
public final static int IFF_UP = 0x1;
/**
* broadcast address valid
*/
public final static int IFF_BROADCAST = 0x2;
/**
* debugging is on
*/
public final static int IFF_DEBUG = 0x4;
/**
* is a loopback net
*/
public final static int IFF_LOOPBACK = 0x8;
/**
* interface has a point-to-point link
*/
public final static int IFF_POINTOPOINT = 0x10;
/**
* avoid use of trailers
*/
public final static int IFF_NOTRAILERS = 0x20;
/**
* interface is running
*/
public final static int IFF_RUNNING = 0x40;
/**
* no ARP protocol
*/
public final static int IFF_NOARP = 0x80;
/**
* receive all packets
*/
public final static int IFF_PROMISC = 0x100;
/**
* receive all multicast packets
*/
public final static int IFF_ALLMULTI = 0x200;
/**
* supports multicast
*/
public final static int IFF_MULTICAST = 0x800;
public final static int CONN_CLIENT = 0x01;
public final static int CONN_SERVER = 0x02;
public final static int CONN_TCP = 0x10;
public final static int CONN_UDP = 0x20;
public final static int CONN_RAW = 0x40;
public final static int CONN_UNIX = 0x80;
public final static int CONN_PROTOCOLS =
NetFlags.CONN_TCP | NetFlags.CONN_UDP |
NetFlags.CONN_RAW | NetFlags.CONN_UNIX;
/**
* @param flags network inteface flags.
* @return String representation of network inteface flags.
* @see net.hyperic.sigar.NetIfconfig#getFlags
*/
public static String getIfFlagsString(long flags) {
String retval = "";
if (flags == 0)
retval += "[NO FLAGS] ";
if ((flags & IFF_UP) > 0)
retval += "UP ";
if ((flags & IFF_BROADCAST) > 0)
retval += "BROADCAST ";
if ((flags & IFF_DEBUG) > 0)
retval += "DEBUG ";
if ((flags & IFF_LOOPBACK) > 0)
retval += "LOOPBACK ";
if ((flags & IFF_POINTOPOINT) > 0)
retval += "POINTOPOINT ";
if ((flags & IFF_NOTRAILERS) > 0)
retval += "NOTRAILERS ";
if ((flags & IFF_RUNNING) > 0)
retval += "RUNNING ";
if ((flags & IFF_NOARP) > 0)
retval += "NOARP ";
if ((flags & IFF_PROMISC) > 0)
retval += "PROMISC ";
if ((flags & IFF_ALLMULTI) > 0)
retval += "ALLMULTI ";
if ((flags & IFF_MULTICAST) > 0)
retval += "MULTICAST ";
return retval;
}
}

View File

@ -0,0 +1,92 @@
package net.hyperic.sigar;
import java.util.HashMap;
import java.util.Map;
/**
* Extend ProcTime to provide process cpu percentage metric.
*/
public class ProcCpu extends ProcTime {
private static ProcCpu key = new ProcCpu();
private static Map ptable = new HashMap();
private long lastTime = 0;
private long pid;
private long time = 0;
private double percent = 0.0;
private void getValues(Sigar sigar, long pid)
throws SigarException {
this.nativeGet(sigar, pid);
this.time = this.utime + this.stime;
}
static synchronized ProcCpu get(Sigar sigar, long pid)
throws SigarException {
ProcCpu cpu;
key.pid = pid;
cpu = (ProcCpu)ptable.get(key);
if (cpu == null) {
cpu = new ProcCpu();
cpu.pid = pid;
ptable.put(cpu, cpu);
}
long timeNow = System.currentTimeMillis() / 1000; //seconds
double diff = timeNow - cpu.lastTime;
if (diff == 0) {
return cpu; //we were just called within < 1 second ago.
}
cpu.lastTime = timeNow;
long otime = cpu.time;
cpu.getValues(sigar, pid);
if (otime == 0) {
//XXX could/should pause first time called.
return cpu;
}
cpu.percent = ((cpu.time - otime) / diff);
if (cpu.percent >= 1.0) {
cpu.percent = 0.99;
}
return cpu;
}
/**
* @return Process CPU usage percentage.
*/
public double getPercent() {
return this.percent;
}
/**
* @return Sum of Utime and Stime.
*/
public long getTotal() {
return this.time;
}
/**
* @return Pid of the process.
*/
public int hashCode() {
return (int)this.pid;
}
public boolean equals(Object cpu) {
if (!(cpu instanceof ProcCpu)) {
return false;
}
return ((ProcCpu)cpu).pid == this.pid;
}
}

View File

@ -0,0 +1,32 @@
package net.hyperic.sigar;
import java.util.Map;
/**
* Lookup environment for a process.
*/
class ProcEnv {
private ProcEnv () { }
/**
* @param sigar The Sigar object.
* @param pid Process id.
* @return Map of environment.
* @exception SigarException on failure.
* @see net.hyperic.sigar.Sigar#getProcEnv
*/
public static native Map getAll(Sigar sigar, long pid)
throws SigarException;
/**
* @param sigar The Sigar object.
* @param pid Process id.
* @param key Environment variable name.
* @return Environment variable value.
* @exception SigarException on failure.
* @see net.hyperic.sigar.Sigar#getProcEnv
*/
public static native String getValue(Sigar sigar, long pid, String key)
throws SigarException;
}

View File

@ -0,0 +1,565 @@
package net.hyperic.sigar;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import net.hyperic.jni.ArchLoaderException;
import net.hyperic.jni.ArchNotSupportedException;
/**
* Entry point for the Sigar - System Information GAtheRer
*/
public class Sigar implements SigarProxy {
public static final String VERSION = "1.1.0";
private static SigarLoader loader = new SigarLoader(Sigar.class);
private FileSystemMap mounts = null;
int sigarWrapper = 0; //holds the sigar_t *
// lastCpu is used to calculate the cpuPerc;
private Cpu lastCpu;
private Cpu[] lastCpuList;
private static SigarProxy instance = null;
static {
try {
load();
} catch (SigarException e) {
//will find out later when invoking methods.
}
}
private static void load() throws SigarException {
try {
loader.load();
} catch (ArchNotSupportedException e) {
throw new SigarException(e.getMessage());
} catch (ArchLoaderException e) {
throw new SigarException(e.getMessage());
} catch (UnsatisfiedLinkError e) {
throw new SigarException(e.getMessage());
}
}
/**
* Format size in bytes to a human readable string.
*
* @param size The size to format.
* @return The formatted string.
*/
public static native String formatSize(long size);
/**
* Constructor
*/
public Sigar() {
try {
open();
} catch (SigarException e) {
//XXX log?
} catch (UnsatisfiedLinkError e) {
//XXX log?
}
}
/**
* Convenience method to keep a sigar instance alive.
* This instance is not thread safe.
*/
//XXX we could make it thread safe by returning a SigarProxy
//impl which synchronizes all method calls.
public static synchronized SigarProxy getInstance() {
if (instance == null) {
instance = new Sigar();
}
return instance;
}
protected void finalize() {
close();
}
private native void open() throws SigarException;
/**
* Release any native resources associated with this sigar instance.
* The sigar object is no longer usable after it has been closed.
*/
public void close() {
if (this.sigarWrapper != 0) {
nativeClose();
}
}
private native int nativeClose();
/**
* Get pid of the current process.
* @exception SigarException on failure.
*/
public native long getPid();
/**
* Send signal to a process.
*
* @param pid The process id.
* @param signum The signal number.
* @exception SigarException on failure.
*/
public native void kill(long pid, int signum) throws SigarException;
/**
* Get system memory info.
* @exception SigarException on failure.
*/
public Mem getMem() throws SigarException {
return Mem.fetch(this);
}
/**
* Get system swap info.
* @exception SigarException on failure.
*/
public Swap getSwap() throws SigarException {
return Swap.fetch(this);
}
/**
* Get system cpu info.
* @exception SigarException on failure.
*/
public Cpu getCpu() throws SigarException {
return (this.lastCpu = Cpu.fetch(this));
}
private static void pause(int millis) {
try {
Thread.sleep(millis);
} catch(InterruptedException e) { }
}
private static void pause() {
pause(500);
}
/**
* Get system CPU info in percentage format. (i.e. fraction of 1)
* @exception SigarException on failure.
*/
public CpuPerc getCpuPerc() throws SigarException {
Cpu oldCpu, curCpu;
if (this.lastCpu == null){
oldCpu = this.getCpu();
pause();
}
else {
oldCpu = this.lastCpu;
}
curCpu = this.getCpu();
return CpuPerc.calculate(oldCpu, curCpu);
}
/**
* Get system per-CPU info in percentage format. (i.e. fraction of 1)
* @exception SigarException on failure.
*/
public CpuPerc[] getCpuPercList() throws SigarException {
Cpu[] oldCpuList, curCpuList;
if (this.lastCpuList == null){
oldCpuList = getCpuList();
pause();
}
else {
oldCpuList = this.lastCpuList;
}
curCpuList = getCpuList();
int curLen = curCpuList.length, oldLen = oldCpuList.length;
CpuPerc[] perc = new CpuPerc[curLen < oldLen ? curLen : oldLen];
for (int i=0; i<curCpuList.length; i++) {
Cpu curCpu = curCpuList[i], oldCpu;
oldCpu = oldCpuList[i];
perc[i] = CpuPerc.calculate(oldCpu, curCpu);
}
return perc;
}
/**
* Get system uptime info.
* @exception SigarException on failure.
*/
public Uptime getUptime() throws SigarException {
return Uptime.fetch(this);
}
/**
* Get system load average.
* @exception SigarException on failure.
* @return The system load averages for the past 1, 5, and 15 minutes.
*/
public native double[] getLoadAverage() throws SigarException;
/**
* Get system process list.
* @exception SigarException on failure.
* @return Array of process ids.
*/
public native long[] getProcList() throws SigarException;
/**
* Get system process stats.
* @exception SigarException on failure.
*/
public ProcStat getProcStat() throws SigarException {
return ProcStat.fetch(this);
}
private long convertPid(String pid) throws SigarException {
if (pid.equals("$$")) {
return getPid();
}
return Long.parseLong(pid);
}
/**
* Get process memory info.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcMem getProcMem(long pid) throws SigarException {
return ProcMem.fetch(this, pid);
}
public ProcMem getProcMem(String pid) throws SigarException {
return getProcMem(convertPid(pid));
}
/**
* Get process state info.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcState getProcState(long pid) throws SigarException {
return ProcState.fetch(this, pid);
}
public ProcState getProcState(String pid) throws SigarException {
return getProcState(convertPid(pid));
}
/**
* Get process time info.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcTime getProcTime(long pid) throws SigarException {
return ProcTime.fetch(this, pid);
}
public ProcTime getProcTime(String pid) throws SigarException {
return getProcTime(convertPid(pid));
}
/**
* Get process cpu info.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcCpu getProcCpu(long pid) throws SigarException {
return ProcCpu.get(this, pid);
}
public ProcCpu getProcCpu(String pid) throws SigarException {
return getProcCpu(convertPid(pid));
}
/**
* Get process credential info.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcCred getProcCred(long pid) throws SigarException {
return ProcCred.fetch(this, pid);
}
public ProcCred getProcCred(String pid) throws SigarException {
return getProcCred(convertPid(pid));
}
/**
* Get process credential names.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcCredName getProcCredName(long pid) throws SigarException {
return ProcCredName.fetch(this, pid);
}
public ProcCredName getProcCredName(String pid) throws SigarException {
return getProcCredName(convertPid(pid));
}
/**
* Get process file descriptor info.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcFd getProcFd(long pid) throws SigarException {
return ProcFd.fetch(this, pid);
}
public ProcFd getProcFd(String pid) throws SigarException {
return getProcFd(convertPid(pid));
}
/**
* Get process current working directory.
* @param pid The process id.
* @exception SigarException on failure.
*/
public ProcExe getProcExe(long pid) throws SigarException {
return ProcExe.fetch(this, pid);
}
public ProcExe getProcExe(String pid) throws SigarException {
return getProcExe(convertPid(pid));
}
/**
* Get process arguments.
* @param pid The process id.
* @return Array of argument strings.
* @exception SigarException on failure.
*/
public native String[] getProcArgs(long pid) throws SigarException;
public String[] getProcArgs(String pid) throws SigarException {
return getProcArgs(convertPid(pid));
}
/**
* Get process environment.
* @param pid The process id.
* @return Map of environment strings.
* @exception SigarException on failure.
*/
public Map getProcEnv(long pid) throws SigarException {
return ProcEnv.getAll(this, pid);
}
public Map getProcEnv(String pid) throws SigarException {
return getProcEnv(convertPid(pid));
}
/**
* Get process environment variable value.
* This method is intended to avoid the overhead
* of creating a Map with all variables if only
* a single variable is needed.
* @param pid The process id.
* @param key Environment variable name.
* @return Environment variable value.
* @exception SigarException on failure.
*/
public String getProcEnv(long pid, String key) throws SigarException {
return ProcEnv.getValue(this, pid, key);
}
public String getProcEnv(String pid, String key) throws SigarException {
return getProcEnv(convertPid(pid), key);
}
public native long getProcPort(long port) throws SigarException;
public long getProcPort(String port) throws SigarException {
return getProcPort(Integer.parseInt(port));
}
/**
* Get list of file systems.
* @exception SigarException on failure.
*/
public native FileSystem[] getFileSystemList() throws SigarException;
/**
* Get file system usage.
* @param name Name of the directory on which filesystem is mounted.
* @exception SigarException on failure.
*/
public FileSystemUsage getFileSystemUsage(String name)
throws SigarException {
if (name == null) {
throw new SigarException("name cannot be null");
}
return FileSystemUsage.fetch(this, name);
}
/**
* Get file system usage of a mounted directory.
* This method checks that the given directory is mounted.
* Unlike getFileSystemUsage() which only requires that the
* directory exists within a mounted file system.
* @param name Name of the directory on which filesystem is mounted.
* @exception SigarException If given directory is not mounted.
* @see net.hyperic.sigar.Sigar#getFileSystemUsage
*/
public FileSystemUsage getMountedFileSystemUsage(String name)
throws SigarException {
if (!getFileSystemMap().isMounted(name)) {
throw new SigarException(name + " is not a mounted filesystem");
}
return FileSystemUsage.fetch(this, name);
}
public FileSystemMap getFileSystemMap()
throws SigarException {
if (this.mounts == null) {
this.mounts = new FileSystemMap();
}
this.mounts.init(getFileSystemList());
return this.mounts;
}
public FileInfo getFileInfo(String name)
throws SigarException {
return FileInfo.fetchFileInfo(this, name);
}
public FileInfo getLinkInfo(String name)
throws SigarException {
return FileInfo.fetchLinkInfo(this, name);
}
public DirStat getDirStat(String name)
throws SigarException {
return DirStat.fetch(this, name);
}
/**
* Get list of cpu infomation.
* @exception SigarException on failure.
*/
public native CpuInfo[] getCpuInfoList() throws SigarException;
private native Cpu[] getCpuListNative() throws SigarException;
/**
* Get list of per-cpu metrics.
* @exception SigarException on failure.
*/
public Cpu[] getCpuList() throws SigarException {
return (this.lastCpuList = getCpuListNative());
}
/**
* Get list of network routes.
* @exception SigarException on failure.
*/
public native NetRoute[] getNetRouteList() throws SigarException;
/**
* Get list of network connections.
* @exception SigarException on failure.
*/
public native NetConnection[] getNetConnectionList(int flags)
throws SigarException;
/**
* Get network interface configuration info.
* @exception SigarException on failure.
*/
public NetInterfaceConfig getNetInterfaceConfig(String name)
throws SigarException {
return NetInterfaceConfig.fetch(this, name);
}
/**
* Get network interface stats.
* @exception SigarException on failure.
*/
public NetInterfaceStat getNetInterfaceStat(String name)
throws SigarException {
return NetInterfaceStat.fetch(this, name);
}
/**
* Get the list of configured network interface names.
* @exception SigarException on failure.
*/
public native String[] getNetInterfaceList() throws SigarException;
/**
* Prompt for a password, disabling terminal echo
* during user input.
* @param prompt Text printed before disabling echo
* @return Text entered by the user.
* @throws IOException If input could not be read.
* @throws SigarNotImplementedException If the native method
* is not implemented on the current platform.
*/
native static String getPasswordNative(String prompt)
throws IOException, SigarNotImplementedException;
/**
* Prompt for a password, disabling terminal echo
* during user input if possible.
* @param prompt Text printed before disabling echo
* @return Text entered by the user.
* @throws IOException If input could not be read.
*/
public static String getPassword(String prompt)
throws IOException
{
try {
return getPasswordNative(prompt);
} catch (IOException e) {
throw e;
} catch (SigarNotImplementedException e) {
//fallthrough
}
//fallback if native .so was not loaded or not supported
System.out.print(prompt);
return (new BufferedReader(new InputStreamReader(System.in))).
readLine();
}
/**
* Reliably retrieve the FQDN for a machine
*
* @return The fully qualified domain name of the machine.
* @exception SigarException on failure.
*/
public native String getFQDN() throws SigarException;
public void enableLogging(boolean value) {
if (value) {
SigarLog.enable(this);
}
else {
SigarLog.disable(this);
}
}
}

View File

@ -0,0 +1,8 @@
package net.hyperic.sigar;
class SigarCacheObject {
int expire = SigarProxyCache.EXPIRE_DEFAULT;
long timestamp = 0;
Object value = null;
}

View File

@ -0,0 +1,11 @@
package net.hyperic.sigar;
/**
* Sigar base exception class.
*/
public class SigarException extends Exception {
public SigarException () { super(); }
public SigarException (String s) { super(s); }
}

View File

@ -0,0 +1,6 @@
package net.hyperic.sigar;
public class SigarFileNotFoundException extends SigarException {
public SigarFileNotFoundException(String s) { super(s); }
}

View File

@ -0,0 +1,291 @@
package net.hyperic.sigar;
import java.util.Arrays;
import java.util.HashMap;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
/**
* This class provides a string-ish interface to sigar.
* It is intended for use via JMX and Covalent CAM measurement
* plugins. Method lookups are cached and the like for better
* performance.
*/
public class SigarInvoker {
private static HashMap attrCache = new HashMap();
private static HashMap compatTypes = new HashMap();
static {
//XXX backwards compat for HQ because metric template
//updating does not work.
compatTypes.put("NetIfconfig", "NetInterfaceConfig");
compatTypes.put("NetIfstat", "NetInterfaceStat");
compatTypes.put("DirStats", "DirStat");
}
//avoid object creation as much as possible
private static final Class[] VOID_SIGNATURE = new Class[0];
private Class[] ARG_SIGNATURE = new Class[] { String.class };
private Class[] ARG2_SIGNATURE = new Class[] {
String.class, String.class
};
private static final Object[] VOID_ARGS = new Object[0];
private Object[] ARG_ARGS = new Object[1];
private String type = null;
private boolean typeIsArray = false;
private int arrayIdx = -1;
private boolean hasArrayIdx = false;
private int typeArrayType;
private static final int ARRAY_TYPE_OBJECT = 1;
private static final int ARRAY_TYPE_DOUBLE = 2;
private static final int ARRAY_TYPE_LONG = 3;
private Method typeMethod;
private SigarProxy sigarProxy;
private SigarProxyCache handler;
protected SigarInvoker() {
}
/**
* @param proxy SigarProxy implementation such as SigarProxyCache
* @param type The sigar type. Valid name is any of the SigarProxy
* interface methods (minus the 'get' prefix).
*/
public SigarInvoker(SigarProxy proxy, String type) {
setProxy(proxy);
setType(type);
}
protected void setProxy(SigarProxy proxy) {
try {
this.handler =
(SigarProxyCache)Proxy.getInvocationHandler(proxy);
} catch (IllegalArgumentException e) {
e.printStackTrace();
//XXX we can still deal w/o this.handler
}
this.sigarProxy = proxy;
}
protected void setType(String val) {
String alias = (String)compatTypes.get(val);
if (alias != null) {
val = alias;
}
this.type = val;
}
/**
* The type of this instance, as passed to the constructor.
*/
public String getType() {
return this.type;
}
private int getAttributeIndex(String attr) {
try {
return Integer.valueOf(attr).intValue();
} catch (NumberFormatException e) {
return -1;
}
}
private Method getTypeMethod(Object[] args)
throws SigarException {
if (this.typeMethod == null) {
Class[] sig = VOID_SIGNATURE;
boolean argIsArrayIdx = false;
int argLength = 0;
String getter = "get" + getType();
if (args != null) {
argLength = args.length;
switch (argLength) {
case 1:
sig = ARG_SIGNATURE;
break;
case 2:
sig = ARG2_SIGNATURE;
break;
default:
throw new IllegalArgumentException();
}
}
try {
this.typeMethod = Sigar.class.getMethod(getter, sig);
} catch (Exception e) {
try {
this.typeMethod =
Sigar.class.getMethod(getter, VOID_SIGNATURE);
if (argLength == 1) {
argIsArrayIdx = true;
}
} catch (Exception e2) {
String msg = "Unable to determine getter for " + type;
throw new SigarException(msg);
}
}
Class typeClass = this.typeMethod.getReturnType();
if (typeClass.isArray()) {
this.typeIsArray = true;
if (argIsArrayIdx) {
this.arrayIdx = Integer.parseInt((String)args[0]);
this.hasArrayIdx = true;
}
Class componentClass = typeClass.getComponentType();
if (componentClass.isPrimitive()) {
//e.g. getLoadAverage
if (componentClass == Double.TYPE) {
this.typeArrayType = ARRAY_TYPE_DOUBLE;
}
//e.g. getProcList
else if (componentClass == Long.TYPE) {
this.typeArrayType = ARRAY_TYPE_LONG;
}
else {
//won't happen.
throw new SigarException("unsupported array type: " +
componentClass.getName());
}
}
else {
this.typeArrayType = ARRAY_TYPE_OBJECT;
}
}
else {
this.typeIsArray = false;
}
}
return this.typeMethod;
}
public Object invoke(Object arg, String attr)
throws SigarException {
Object[] args = null;
if (arg != null) {
args = ARG_ARGS;
args[0] = arg;
}
return invoke(args, attr);
}
public Object invoke(Object[] args, String attr)
throws SigarException {
Method typeGetter, attrGetter;
Object typeObject, attrObject;
typeGetter = getTypeMethod(args);
if (this.hasArrayIdx) {
args = null;
}
try {
typeObject = this.handler.invoke(this.sigarProxy,
typeGetter,
args);
} catch (Throwable t) {
String msg = "Failed to invoke " +
typeGetter.getName() + Arrays.asList(args) +
": " + t.getMessage();
throw new SigarException(msg);
}
if (attr == null) {
return typeObject;
}
/*
* if the return type is an array and we've been given
* an attr, the attr is an index into the array, e.g.
* for getLoadAverage which returns a double[].
* working with primitive arrays here kinda sucks.
*/
if (this.typeIsArray) {
if (this.hasArrayIdx) {
typeObject = ((Object[])typeObject)[this.arrayIdx];
}
else {
int idx = getAttributeIndex(attr);
if (idx < 0) {
throw new SigarException("Invalid array index: " + attr);
}
switch (this.typeArrayType) {
case ARRAY_TYPE_DOUBLE:
return new Double(((double[])typeObject)[idx]);
case ARRAY_TYPE_LONG:
return new Long(((long[])typeObject)[idx]);
case ARRAY_TYPE_OBJECT:
return ((Object[])typeObject)[idx];
}
}
}
attrGetter = getAttributeMethod(attr);
try {
return attrGetter.invoke(typeObject, VOID_ARGS);
} catch (Throwable t) {
throw new SigarException(t.getMessage());
}
}
private Method getAttributeMethod(String attr)
throws SigarException {
Method attrMethod;
Class type = getTypeMethod(null).getReturnType();
HashMap attrs;
if (this.hasArrayIdx) {
type = type.getComponentType();
}
//Class.getMethod can be expensive so cache the lookups
synchronized (attrCache) {
attrs = (HashMap)attrCache.get(type);
if (attrs == null) {
attrs = new HashMap();
attrCache.put(type, attrs);
}
else {
if ((attrMethod = (Method)attrs.get(attr)) != null) {
return attrMethod;
}
}
}
try {
attrMethod = type.getMethod("get" + attr,
VOID_SIGNATURE);
} catch (Exception e) {
String msg = "Failed to invoke get" + attr + ": " +
e.getMessage();
throw new SigarException(msg);
}
synchronized (attrs) {
attrs.put(attr, attrMethod);
}
return attrMethod;
}
}

View File

@ -0,0 +1,37 @@
package net.hyperic.sigar;
import net.hyperic.jni.ArchLoader;
import net.hyperic.jni.ArchName;
import net.hyperic.jni.ArchNotSupportedException;
public class SigarLoader extends ArchLoader {
public SigarLoader(Class loaderClass) {
super(loaderClass);
}
//XXX same as super.getArchLibName()
//but db2monitor.jar gets loaded first in jboss
//results in NoSuchMethodError
public String getArchLibName()
throws ArchNotSupportedException {
return getName() + "-" + ArchName.getName();
}
public String getDefaultLibName()
throws ArchNotSupportedException {
return getArchLibName(); //drop "java" prefix
}
//override these methods to ensure our ClassLoader
//loads the native library.
protected void systemLoadLibrary(String name) {
System.loadLibrary(name);
}
protected void systemLoad(String name) {
System.load(name);
}
}

View File

@ -0,0 +1,57 @@
package net.hyperic.sigar;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
public class SigarLog {
//from sigar_log.h
private static final int LOG_FATAL = 0;
private static final int LOG_ERROR = 1;
private static final int LOG_WARN = 2;
private static final int LOG_INFO = 3;
private static final int LOG_DEBUG = 4;
private static final int LOG_TRACE = 5;
private static native void setLogger(Sigar sigar, Logger log);
public static native void setLevel(Sigar sigar, int level);
//XXX want to make this automatic, but also dont always
//want to turn on logging, since most sigar logging will be DEBUG
public static void enable(Sigar sigar) {
Logger log = Logger.getLogger("Sigar");
Level level = log.getLevel();
if (level == null) {
level = Logger.getRootLogger().getLevel();
if (level == null) {
return;
}
}
switch (level.toInt()) {
case Level.FATAL_INT:
setLevel(sigar, LOG_FATAL);
break;
case Level.ERROR_INT:
setLevel(sigar, LOG_ERROR);
break;
case Level.WARN_INT:
setLevel(sigar, LOG_WARN);
break;
case Level.INFO_INT:
setLevel(sigar, LOG_INFO);
break;
case Level.DEBUG_INT:
setLevel(sigar, LOG_DEBUG);
break;
}
setLogger(sigar, log);
}
public static void disable(Sigar sigar) {
setLogger(sigar, null);
}
}

View File

@ -0,0 +1,12 @@
package net.hyperic.sigar;
/**
* Sigar exception class, thrown for methods which are not implemented
* on a given platform.
*/
public class SigarNotImplementedException extends SigarException {
public SigarNotImplementedException () { super(); }
public SigarNotImplementedException (String s) { super(s); }
}

View File

@ -0,0 +1,112 @@
package net.hyperic.sigar;
import java.util.Map;
/**
* The proxyable interface for caching via SigarProxyCache.
* This interface includes all methods which leave java land and
* gather info from the system. All other accessors, such as the objects
* returned by these methods do not leave java land.
*/
public interface SigarProxy {
public long getPid();
public Mem getMem() throws SigarException;
public Swap getSwap() throws SigarException;
public Cpu getCpu() throws SigarException;
public CpuPerc getCpuPerc() throws SigarException;
public Uptime getUptime() throws SigarException;
public double[] getLoadAverage() throws SigarException;
public long[] getProcList() throws SigarException;
public ProcStat getProcStat() throws SigarException;
public ProcMem getProcMem(long pid) throws SigarException;
public ProcMem getProcMem(String pid) throws SigarException;
public ProcState getProcState(long pid) throws SigarException;
public ProcState getProcState(String pid) throws SigarException;
public ProcTime getProcTime(long pid) throws SigarException;
public ProcTime getProcTime(String pid) throws SigarException;
public ProcCpu getProcCpu(long pid) throws SigarException;
public ProcCpu getProcCpu(String pid) throws SigarException;
public ProcCred getProcCred(long pid) throws SigarException;
public ProcCred getProcCred(String pid) throws SigarException;
public ProcCredName getProcCredName(long pid) throws SigarException;
public ProcCredName getProcCredName(String pid) throws SigarException;
public ProcFd getProcFd(long pid) throws SigarException;
public ProcFd getProcFd(String pid) throws SigarException;
public ProcExe getProcExe(long pid) throws SigarException;
public ProcExe getProcExe(String pid) throws SigarException;
public String[] getProcArgs(long pid) throws SigarException;
public String[] getProcArgs(String pid) throws SigarException;
public Map getProcEnv(long pid) throws SigarException;
public Map getProcEnv(String pid) throws SigarException;
public String getProcEnv(long pid, String key) throws SigarException;
public String getProcEnv(String pid, String key) throws SigarException;
public long getProcPort(long port) throws SigarException;
public long getProcPort(String port) throws SigarException;
public FileSystem[] getFileSystemList() throws SigarException;
public FileSystemMap getFileSystemMap() throws SigarException;
public FileSystemUsage getMountedFileSystemUsage(String name)
throws SigarException;
public FileSystemUsage getFileSystemUsage(String name)
throws SigarException;
public FileInfo getFileInfo(String name) throws SigarException;
public FileInfo getLinkInfo(String name) throws SigarException;
public DirStat getDirStat(String name) throws SigarException;
public CpuInfo[] getCpuInfoList() throws SigarException;
public Cpu[] getCpuList() throws SigarException;
public CpuPerc[] getCpuPercList() throws SigarException;
public NetRoute[] getNetRouteList() throws SigarException;
public NetInterfaceConfig getNetInterfaceConfig(String name)
throws SigarException;
public NetInterfaceStat getNetInterfaceStat(String name)
throws SigarException;
public String[] getNetInterfaceList() throws SigarException;
public String getFQDN() throws SigarException;
}

View File

@ -0,0 +1,230 @@
package net.hyperic.sigar;
import java.util.Map;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import net.hyperic.sigar.util.ReferenceMap;
public class SigarProxyCache
implements InvocationHandler {
private Sigar sigar;
private Map cache = ReferenceMap.newInstance();
public static final int EXPIRE_DEFAULT = 30 * 1000; //30 seconds
private int expire;
private static final boolean debugEnabled =
"debug".equals(System.getProperty("sigar.log"));
public SigarProxyCache(Sigar sigar, int expire) {
this.sigar = sigar;
this.expire = expire;
}
public static SigarProxy newInstance() {
return newInstance(new Sigar());
}
public static SigarProxy newInstance(Sigar sigar) {
return newInstance(sigar, EXPIRE_DEFAULT);
}
public static SigarProxy newInstance(Sigar sigar, int expire) {
SigarProxyCache handler = new SigarProxyCache(sigar, expire);
SigarProxy proxy;
proxy = (SigarProxy)
Proxy.newProxyInstance(SigarProxy.class.getClassLoader(),
new Class[] { SigarProxy.class },
handler);
return proxy;
}
//poor mans logging
private void debug(String msg) {
System.out.println("[DEBUG] SigarProxyCache - " + msg);
}
private static final Class[] VOID_SIGNATURE = new Class[0];
public static void setExpire(SigarProxy proxy,
String type,
int expire)
throws SigarException {
SigarProxyCache handler =
(SigarProxyCache)Proxy.getInvocationHandler(proxy);
Method method;
try {
method = Sigar.class.getMethod("get" + type, VOID_SIGNATURE);
} catch (Exception e) {
throw new SigarException("invalid type " + type);
}
SigarCacheObject cacheVal =
(SigarCacheObject)handler.cache.get(method);
if (cacheVal == null) {
cacheVal = new SigarCacheObject();
}
cacheVal.expire = expire;
handler.cache.put(method, cacheVal);
}
public static void clear(Object proxy) {
SigarProxyCache handler =
(SigarProxyCache)Proxy.getInvocationHandler(proxy);
handler.cache.clear();
}
private String getDebugArgs(Object[] args, Object argKey) {
if (args.length == 0) {
return null;
}
StringBuffer dargs =
new StringBuffer(args[0].toString());
for (int i=1; i<args.length; i++) {
dargs.append(',').append(args[i].toString());
}
if (!dargs.toString().equals(argKey.toString())) {
dargs.append('/').append(argKey);
}
return dargs.toString();
}
/**
* The java.lang.reflect.InvocationHandler used by the Proxy.
* This method handles caching of all Sigar type objects.
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws SigarException, SigarNotImplementedException {
SigarCacheObject cacheVal = null;
Object retval;
Object argKey = null;
Map argMap = null;
long timeNow = System.currentTimeMillis();
if (args != null) {
if (args.length == 1) {
argKey = args[0];
}
else {
int hashCode = 0;
for (int i=0; i<args.length; i++) {
hashCode ^= args[i].hashCode();
}
argKey = new Integer(hashCode);
}
argMap = (Map)this.cache.get(method);
if (argMap == null) {
argMap = ReferenceMap.newInstance();
}
else {
//XXX what todo when pids are stale?
cacheVal = (SigarCacheObject)argMap.get(argKey);
}
}
else {
cacheVal = (SigarCacheObject)this.cache.get(method);
}
if (cacheVal == null) {
cacheVal = new SigarCacheObject();
cacheVal.expire = this.expire;
}
if (cacheVal.value != null) {
String argDebug = "";
if (this.debugEnabled) {
if ((args != null) && (args.length != 0)) {
argDebug = " with args=" +
getDebugArgs(args, argKey);
}
debug("found " + method.getName() +
" in cache" + argDebug);
}
if ((timeNow - cacheVal.timestamp) > cacheVal.expire) {
if (this.debugEnabled) {
debug("expiring " + method.getName() +
" from cache" + argDebug);
}
cacheVal.value = null;
}
}
if (cacheVal.value == null) {
try {
retval = method.invoke(this.sigar, args);
} catch (InvocationTargetException e) {
Throwable t =
((InvocationTargetException)e).
getTargetException();
String msg;
if (t instanceof SigarException) {
msg = "";
}
else {
msg = t.getClass().getName() + ": ";
}
msg += t.getMessage();
if (argKey != null) {
msg += ": " + getDebugArgs(args, argKey);
}
if (t instanceof SigarNotImplementedException) {
throw new SigarNotImplementedException(msg);
}
throw new SigarException(msg);
} catch (Exception e) {
String msg =
e.getClass().getName() + ": " +
e.getMessage();
if (argKey != null) {
msg += ": " + getDebugArgs(args, argKey);
}
throw new SigarException(msg);
}
cacheVal.value = retval;
cacheVal.timestamp = timeNow;
if (args == null) {
this.cache.put(method, cacheVal);
}
else {
argMap.put(argKey, cacheVal);
this.cache.put(method, argMap);
}
}
else {
retval = cacheVal.value;
}
return retval;
}
}

View File

@ -0,0 +1,33 @@
package net.hyperic.sigar;
import java.lang.reflect.Method;
public class SynchronizedSigarProxyCache
extends SigarProxyCache {
private static Object lock = new Object();
private static SigarProxy instance = null;
public static SigarProxy getInstance(Sigar sigar)
throws SigarException {
synchronized (lock) {
if (instance == null) {
instance = SigarProxyCache.newInstance(sigar);
}
}
return instance;
}
public SynchronizedSigarProxyCache(Sigar sigar, int expire) {
super(sigar, expire);
}
//all Objects returned are read-only.
public synchronized Object invoke(Object proxy, Method method, Object[] args)
throws SigarException, SigarNotImplementedException {
return super.invoke(proxy, method, args);
}
}

View File

@ -0,0 +1,45 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.CpuPerc;
import net.hyperic.sigar.SigarException;
public class CpuInfo extends SigarCommandBase {
public CpuInfo(Shell shell) {
super(shell);
}
public CpuInfo() {
super();
}
public String getUsageShort() {
return "Display cpu information";
}
public void output(String[] args) throws SigarException {
net.hyperic.sigar.CpuInfo[] infos =
this.sigar.getCpuInfoList();
CpuPerc[] cpus = this.sigar.getCpuPercList();
this.out.println(infos.length + " total CPUs..");
for (int i=0; i<infos.length; i++) {
net.hyperic.sigar.CpuInfo info = infos[i];
CpuPerc cpu = cpus[i];
this.out.println("Vendor........" + info.getVendor());
this.out.println("Model........." + info.getModel());
this.out.println("Mhz..........." + info.getMhz());
this.out.println("Cache size...." + info.getCacheSize());
this.out.println("User Time....." + CpuPerc.format(cpu.getUser()));
this.out.println("Sys Time......" + CpuPerc.format(cpu.getSys()));
this.out.println("Idle Time....." + CpuPerc.format(cpu.getIdle()));
this.out.println();
}
}
public static void main(String[] args) throws Exception {
new CpuInfo().processCommand(args);
}
}

View File

@ -0,0 +1,133 @@
package net.hyperic.sigar.cmd;
import java.util.ArrayList;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.FileSystem;
import net.hyperic.sigar.FileSystemMap;
import net.hyperic.sigar.FileSystemUsage;
import net.hyperic.sigar.shell.FileCompleter;
import net.hyperic.sigar.util.GetlineCompleter;
public class Df extends SigarCommandBase {
private static final String OUTPUT_FORMAT =
"%-10s %4s %4s %5s %4s %-10s %s";
//like df -h -a
private static final String[] HEADER = new String[] {
"Filesystem",
"Size",
"Used",
"Avail",
"Use%",
"Mounted on",
"Type"
};
private GetlineCompleter completer;
public Df(Shell shell) {
super(shell);
setOutputFormat(OUTPUT_FORMAT);
this.completer = new FileCompleter(shell);
}
public Df() {
super();
setOutputFormat(OUTPUT_FORMAT);
}
public GetlineCompleter getCompleter() {
return this.completer;
}
protected boolean validateArgs(String[] args) {
return args.length <= 1;
}
public String getSyntaxArgs() {
return "[filesystem]";
}
public String getUsageShort() {
return "Report filesystem disk space usage";
}
public void printHeader() {
printf(HEADER);
}
public void output(String[] args) throws SigarException {
if (args.length == 1) {
FileSystemMap mounts = this.proxy.getFileSystemMap();
String name = FileCompleter.expand(args[0]);
FileSystem fs = mounts.getMountPoint(name);
if (fs != null) {
printHeader();
output(fs);
return;
}
throw new SigarException(args[0] +
" No such file or directory");
}
else {
FileSystem[] fslist = this.proxy.getFileSystemList();
printHeader();
for (int i=0; i<fslist.length; i++) {
output(fslist[i]);
}
}
}
public void output(FileSystem fs) throws SigarException {
long used, avail, total, pct;
try {
FileSystemUsage usage =
this.sigar.getFileSystemUsage(fs.getDirName());
used = usage.getTotal() - usage.getFree();
avail = usage.getAvail();
total = usage.getTotal();
pct = (long)(usage.getUsePercent() * 100);
} catch (SigarException e) {
//e.g. on win32 D:\ fails with "Device not ready"
//if there is no cd in the drive.
used = avail = total = pct = 0;
}
String usePct;
if (pct == 0) {
usePct = "-";
}
else {
usePct = pct + "%";
}
ArrayList items = new ArrayList();
items.add(fs.getDevName());
items.add(formatSize(total));
items.add(formatSize(used));
items.add(formatSize(avail));
items.add(usePct);
items.add(fs.getDirName());
items.add(fs.getSysTypeName() + "/" + fs.getTypeName());
printf(items);
}
private static String formatSize(long size) {
return Sigar.formatSize(size * 1024);
}
public static void main(String[] args) throws Exception {
new Df().processCommand(args);
}
}

View File

@ -0,0 +1,43 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.Mem;
import net.hyperic.sigar.Swap;
import net.hyperic.sigar.SigarException;
public class Free extends SigarCommandBase {
public Free(Shell shell) {
super(shell);
}
public Free() {
super();
}
public String getUsageShort() {
return "Display information about free and used memory";
}
public void output(String[] args) throws SigarException {
Mem mem = this.sigar.getMem();
Swap swap = this.sigar.getSwap();
this.out.println("\tTotal\tUsed\tFree");
this.out.println("Mem: " +
mem.getTotal() / 1024 + "\t" +
mem.getUsed() / 1024 + "\t" +
mem.getFree() / 1024);
this.out.println("Swap: " +
swap.getTotal() / 1024 + "\t" +
swap.getUsed() / 1024 + "\t" +
swap.getFree() / 1024);
this.out.println("RAM: " + mem.getRam() + "MB");
}
public static void main(String[] args) throws Exception {
new Free().processCommand(args);
}
}

View File

@ -0,0 +1,137 @@
package net.hyperic.sigar.cmd;
import java.util.Arrays;
import java.util.Collection;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.NetInterfaceConfig;
import net.hyperic.sigar.NetInterfaceStat;
import net.hyperic.sigar.NetFlags;
public class Ifconfig extends SigarCommandBase {
public Ifconfig(Shell shell) {
super(shell);
}
public Ifconfig() {
super();
}
protected boolean validateArgs(String[] args) {
return args.length <= 1;
}
public String getSyntaxArgs() {
return "[interface]";
}
public String getUsageShort() {
return "Network interface information";
}
public Collection getCompletions() {
String[] ifNames;
try {
ifNames = this.proxy.getNetInterfaceList();
} catch (SigarException e) {
return super.getCompletions();
}
return Arrays.asList(ifNames);
}
public void output(String[] args) throws SigarException {
String[] ifNames;
if (args.length == 1) {
ifNames = args;
}
else {
ifNames = this.proxy.getNetInterfaceList();
}
for (int i=0; i<ifNames.length; i++) {
output(ifNames[i]);
}
}
public void output(String name) throws SigarException {
NetInterfaceConfig ifconfig =
this.sigar.getNetInterfaceConfig(name);
long flags = ifconfig.getFlags();
//XXX cannot assume ethernet
String encap = (flags & NetFlags.IFF_LOOPBACK) > 0 ?
"Local Loopback" : "Ethernet";
String hwaddr = "";
if (!NetFlags.NULL_HWADDR.equals(ifconfig.getHwaddr())) {
hwaddr = " HWaddr " + ifconfig.getHwaddr();
}
println(ifconfig.getName() + "\t" +
"Link encap:" + encap +
hwaddr);
String ptp = "";
if ((flags & NetFlags.IFF_POINTOPOINT) > 0) {
ptp = " P-t-P:" + ifconfig.getDestination();
}
String bcast = "";
if ((flags & NetFlags.IFF_BROADCAST) > 0) {
bcast = " Bcast:" + ifconfig.getBroadcast();
}
println("\t" +
"inet addr:" + ifconfig.getAddress() +
ptp + //unlikely
bcast +
" Mask:" + ifconfig.getNetmask());
println("\t" +
NetFlags.getIfFlagsString(flags) +
" MTU:" + ifconfig.getMtu() +
" Metric:" + ifconfig.getMetric());
try {
NetInterfaceStat ifstat =
this.sigar.getNetInterfaceStat(name);
println("\t" +
"RX packets:" + ifstat.getRxPackets() +
" errors:" + ifstat.getRxErrors() +
" dropped:" + ifstat.getRxDropped() +
" overruns:" + ifstat.getRxOverruns() +
" frame:" + ifstat.getRxFrame());
println("\t" +
"TX packets:" + ifstat.getTxPackets() +
" errors:" + ifstat.getTxErrors() +
" dropped:" + ifstat.getTxDropped() +
" overruns:" + ifstat.getTxOverruns() +
" carrier:" + ifstat.getTxCarrier());
println("\t" + "collisions:" +
ifstat.getTxCollisions());
long rxBytes = ifstat.getRxBytes();
long txBytes = ifstat.getTxBytes();
println("\t" +
"RX bytes:" + rxBytes +
" (" + Sigar.formatSize(rxBytes) + ")" +
" " +
"TX bytes:" + txBytes +
" (" + Sigar.formatSize(txBytes) + ")");
} catch (SigarException e) {
}
println("");
}
public static void main(String[] args) throws Exception {
new Ifconfig().processCommand(args);
}
}

View File

@ -0,0 +1,60 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.SigarException;
public class Kill extends SigarCommandBase {
public Kill(Shell shell) {
super(shell);
}
public Kill() {
super();
}
protected boolean validateArgs(String[] args) {
return args.length == 1 || args.length == 2;
}
public String getSyntaxArgs() {
return "[signal] <query|pid>";
}
public String getUsageShort() {
return "Send signal to a process";
}
public boolean isPidCompleter() {
return true;
}
public void output(String[] args) throws SigarException {
int signum = 15; //SIGTERM
long[] pids;
String query;
if (args.length == 2) {
query = args[1];
try {
signum = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
//XXX convert SIGFOO to number
throw new SigarException(e.getMessage());
}
}
else {
query = args[0];
}
pids = this.shell.findPids(new String[] { query });
for (int i=0; i<pids.length; i++) {
println("kill " + signum + " " + pids[i]);
this.sigar.kill(pids[i], signum);
}
}
public static void main(String[] args) throws Exception {
new Kill().processCommand(args);
}
}

View File

@ -0,0 +1,84 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.ProcMem;
/**
* Watch for changes in program memory usage.
*/
public class MemWatch {
static final int SLEEP_TIME = 1000 * 10;
public static void main(String[] args) throws Exception {
Sigar sigar = new Sigar();
if (args.length != 1) {
throw new Exception("Usage: MemWatch pid");
}
long pid = Long.parseLong(args[0]);
long lastTime = System.currentTimeMillis();
ProcMem last = sigar.getProcMem(pid);
while (true) {
ProcMem cur = sigar.getProcMem(pid);
StringBuffer diff = diff(last, cur);
if (diff.length() == 0) {
System.out.println("no change " +
"(size=" +
Sigar.formatSize(cur.getSize()) +
")");
}
else {
long curTime = System.currentTimeMillis();
long timeDiff = curTime - lastTime;
lastTime = curTime;
diff.append(" after " + timeDiff + "ms");
System.out.println(diff);
}
last = cur;
Thread.sleep(SLEEP_TIME);
}
}
private static StringBuffer diff(ProcMem last, ProcMem cur) {
StringBuffer buf = new StringBuffer();
long diff;
diff = cur.getSize() - last.getSize();
if (diff != 0) {
buf.append("size=" + diff);
}
diff = cur.getVsize() - last.getVsize();
if (diff != 0) {
buf.append(", vsize=" + diff);
}
diff = cur.getRss() - last.getRss();
if (diff != 0) {
buf.append(", rss=" + diff);
}
diff = cur.getResident() - last.getResident();
if (diff != 0) {
buf.append(", resident=" + diff);
}
diff = cur.getShare() - last.getShare();
if (diff != 0) {
buf.append(", share=" + diff);
}
return buf;
}
}

View File

@ -0,0 +1,99 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.NetConnection;
import net.hyperic.sigar.NetFlags;
public class Netstat extends SigarCommandBase {
public Netstat(Shell shell) {
super(shell);
}
public Netstat() {
super();
}
protected boolean validateArgs(String[] args) {
return true;
}
public String getUsageShort() {
return "Show network connections";
}
//poor mans getopt.
public static int getFlags(String[] args, int flags) {
int proto_flags = 0;
for (int i=0; i<args.length; i++) {
String arg = args[i];
int j = 0;
while (j<arg.length()) {
switch (arg.charAt(j++)) {
case '-':
continue;
case 'l':
flags &= ~NetFlags.CONN_CLIENT;
flags |= NetFlags.CONN_SERVER;
break;
case 'a':
flags |= NetFlags.CONN_SERVER | NetFlags.CONN_CLIENT;
break;
case 't':
proto_flags |= NetFlags.CONN_TCP;
break;
case 'u':
proto_flags |= NetFlags.CONN_UDP;
break;
case 'w':
proto_flags |= NetFlags.CONN_RAW;
break;
case 'x':
proto_flags |= NetFlags.CONN_UNIX;
break;
default:
System.err.println("unknown option");
}
}
}
if (proto_flags != 0) {
flags &= ~NetFlags.CONN_PROTOCOLS;
flags |= proto_flags;
}
return flags;
}
//XXX currently weak sauce. should end up like netstat command.
public void output(String[] args) throws SigarException {
//default
int flags = NetFlags.CONN_CLIENT | NetFlags.CONN_PROTOCOLS;
if (args.length > 0) {
flags = getFlags(args, flags);
}
NetConnection[] connections = this.sigar.getNetConnectionList(flags);
println("Proto\tLocal Address\tForeign Address");
for (int i=0; i<connections.length; i++) {
NetConnection conn = connections[i];
println(conn.getTypeString() +
"\t" +
conn.getLocalAddress() + ":" +
conn.getLocalPort() +
"\t" +
conn.getRemoteAddress() + ":" +
conn.getRemotePort());
}
}
public static void main(String[] args) throws Exception {
new Netstat().processCommand(args);
}
}

View File

@ -0,0 +1,181 @@
package net.hyperic.sigar.cmd;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.lang.reflect.Method;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.util.GetlineCompleter;
import net.hyperic.sigar.ptql.ProcessQueryBuilder;
import net.hyperic.sigar.shell.CollectionCompleter;
import net.hyperic.sigar.shell.MultiwordShellCommand;
import net.hyperic.sigar.shell.ShellBase;
import net.hyperic.sigar.shell.ShellCommandExecException;
import net.hyperic.sigar.shell.ShellCommandInitException;
import net.hyperic.sigar.shell.ShellCommandHandler;
import net.hyperic.sigar.shell.ShellCommandUsageException;
public class PTQL
extends MultiwordShellCommand
implements GetlineCompleter {
private Shell shell;
private PrintStream out = System.out;
private Sigar sigar;
private SigarProxy proxy;
private long[] foundPids = null;
private Ps ps;
private GetlineCompleter m_completer;
private Map methods;
private PTQL() { }
public PTQL(Shell shell) {
this.shell = shell;
this.out = shell.getOutStream();
this.sigar = shell.getSigar();
this.proxy = shell.getSigarProxy();
this.ps = new Ps(this.shell);
this.methods = ProcessQueryBuilder.getMethods();
this.m_completer =
new CollectionCompleter(shell, methods.keySet());
}
public String complete(String line) {
int ix = line.indexOf(".");
if (ix == -1) {
line = this.m_completer.complete(line);
if (!line.endsWith(".")) {
if (this.methods.get(line) != null) {
return line + ".";
}
}
return line;
}
String attrClass = line.substring(0, ix);
String attr = line.substring(ix+1, line.length());
Method method = (Method)this.methods.get(attrClass);
Class subtype = method.getReturnType();
if (method == null) {
return line;
}
boolean isSigarClass = ProcessQueryBuilder.isSigarClass(subtype);
int ix2 = attr.indexOf(".");
if (ix2 != -1) {
method = null;
String op = attr.substring(ix2+1, attr.length());
attr = attr.substring(0, ix2);
if (isSigarClass) {
try {
method =
subtype.getMethod("get" + attr,
ProcessQueryBuilder.NOPARAM);
} catch (NoSuchMethodException e) { }
}
final Method m = method;
GetlineCompleter completer =
new CollectionCompleter(this.shell,
ProcessQueryBuilder.
getMethodOpNames(m));
String partial = completer.complete(op);
String result = attrClass + "." + attr + "." + partial;
if (partial.length() == 2) {
result += "=";
}
return result;
}
if (isSigarClass) {
final ArrayList possible = new ArrayList();
Method[] submethods = subtype.getDeclaredMethods();
for (int i=0; i<submethods.length; i++) {
Method m = submethods[i];
if (m.getName().startsWith("get")) {
possible.add(m.getName().substring(3));
}
}
GetlineCompleter completer =
new CollectionCompleter(this.shell, possible);
String partial = completer.complete(attr);
String result = attrClass + "." + partial;
if (possible.contains(partial)) {
result += ".";
}
return result;
}
return line;
}
public void init(String commandName, ShellBase shell)
throws ShellCommandInitException
{
ShellCommandHandler handler;
super.init(commandName, shell);
handler = new ProcessQueryGenerate(this.shell);
registerSubHandler("generate", handler);
}
public String getSyntaxArgs() {
return "<query>";
}
public String getUsageShort() {
return "Run process table query";
}
public void processCommand(String[] args)
throws ShellCommandUsageException, ShellCommandExecException
{
if (args.length > 0) {
if (getSubHandler(args[0]) != null) {
super.processCommand(args);
return;
}
}
if (args.length != 1) {
throw new ShellCommandUsageException(getSyntax());
}
long[] pids;
try {
pids = this.shell.findPids(args);
} catch (NumberFormatException e) {
throw new ShellCommandUsageException(getSyntax());
} catch (SigarException e) {
throw new ShellCommandExecException(e.getMessage());
}
for (int i=0; i<pids.length; i++) {
try {
this.ps.output(pids[i]);
} catch (SigarException e) {
throw new ShellCommandExecException(e.getMessage());
}
}
this.ps.flush();
}
}

View File

@ -0,0 +1,49 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.ptql.ProcessFinder;
class PidFinder {
public static long[] getPids(SigarProxy sigar, String[] args)
throws SigarException {
long[] pids;
switch (args.length) {
case 0:
pids = new long[] { sigar.getPid() };
break;
case 1:
if (args[0].indexOf("=") > 0) {
pids = ProcessFinder.find(sigar, args[0]);
}
else if (args[0].equals("$$")) {
pids = new long[] { sigar.getPid() };
}
else {
pids = new long[] {
Long.parseLong(args[0])
};
}
break;
default:
throw new IllegalArgumentException("Usage: cmd [pid|query]");
}
return pids;
}
public static long getPid(SigarProxy sigar, String[] args)
throws SigarException {
long[] pids = getPids(sigar, args);
if (pids.length != 1) {
throw new IllegalArgumentException("Query matches more than 1 process");
}
return pids[0];
}
}

View File

@ -0,0 +1,63 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.ProcFd;
import net.hyperic.sigar.ProcExe;
public class ProcFileInfo extends SigarCommandBase {
public ProcFileInfo(Shell shell) {
super(shell);
}
public ProcFileInfo() {
super();
}
protected boolean validateArgs(String[] args) {
return true;
}
public String getUsageShort() {
return "Display process file info";
}
public boolean isPidCompleter() {
return true;
}
public void output(String[] args) throws SigarException {
long[] pids = this.shell.findPids(args);
for (int i=0; i<pids.length; i++) {
try {
output(pids[i]);
} catch (SigarException e) {
println("(" + e.getMessage() + ")");
}
println("\n------------------------\n");
}
}
public void output(long pid) throws SigarException {
ProcFd fd = sigar.getProcFd(pid);
println("pid=" + pid);
println("open file descriptors=" + fd.getTotal());
ProcExe exe = sigar.getProcExe(pid);
String name = exe.getName();
if (name.length() == 0) {
name = "unknown";
}
println("name=" + name);
println("cwd=" + exe.getCwd());
}
public static void main(String[] args) throws Exception {
new ProcFileInfo().processCommand(args);
}
}

View File

@ -0,0 +1,55 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.ptql.ProcessQueryGenerator;
public class ProcessQueryGenerate extends SigarCommandBase {
public ProcessQueryGenerate(Shell shell) {
super(shell);
}
public ProcessQueryGenerate() {
super();
}
public boolean validateArgs(String[] args) {
return true;
}
public void output(String[] args) throws SigarException {
ProcessQueryGenerator generator =
new ProcessQueryGenerator(this.proxy);
long[] pids;
if (args.length > 0) {
pids = this.shell.findPids(args);
}
else {
pids = this.proxy.getProcList();
}
for (int i=0; i<pids.length; i++) {
long pid = pids[i];
String query = generator.generate(pid);
if (query != null) {
println(query);
}
else {
this.err.println("failed to narrow query for " + pid +
" (" +
this.proxy.getProcState(pid).getName() +
")");
}
}
flush();
}
public static void main(String[] args) throws Exception {
new ProcessQueryGenerate().processCommand(args);
}
}

View File

@ -0,0 +1,183 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.ProcCredName;
import net.hyperic.sigar.ProcMem;
import net.hyperic.sigar.ProcTime;
import net.hyperic.sigar.ProcState;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Ps extends SigarCommandBase {
public Ps(Shell shell) {
super(shell);
}
public Ps() {
super();
}
protected boolean validateArgs(String[] args) {
return true;
}
public String getSyntaxArgs() {
return "[pid|query]";
}
public String getUsageShort() {
return "Show process status";
}
public boolean isPidCompleter() {
return true;
}
public void output(String[] args) throws SigarException {
long[] pids;
if (args.length == 0) {
pids = this.proxy.getProcList();
}
else {
pids = this.shell.findPids(args);
}
for (int i=0; i<pids.length; i++) {
long pid = pids[i];
try {
output(pid);
} catch (SigarException e) {
this.err.println("Exception getting process info for " +
pid + ": ");
e.printStackTrace();
}
}
}
public static String join(List info) {
StringBuffer buf = new StringBuffer();
Iterator i = info.iterator();
boolean hasNext = i.hasNext();
while (hasNext) {
buf.append((String)i.next());
hasNext = i.hasNext();
if (hasNext)
buf.append("\t");
}
return buf.toString();
}
private static boolean isClassName(String name) {
int len = name.length();
for (int i=0; i<len; i++) {
char c = name.charAt(i);
if (!((c == '.') || Character.isLetter(c))) {
return false;
}
}
return true;
}
public static List getInfo(SigarProxy sigar, long pid)
throws SigarException {
ProcState state = sigar.getProcState(pid);
ProcTime time = null;
String unknown = "???";
List info = new ArrayList();
info.add(String.valueOf(pid));
try {
ProcCredName cred = sigar.getProcCredName(pid);
info.add(cred.getUser());
} catch (SigarException e) {
info.add(unknown);
}
try {
time = sigar.getProcTime(pid);
info.add(getStartTime(time.getStartTime()));
} catch (SigarException e) {
info.add(unknown);
}
try {
ProcMem mem = sigar.getProcMem(pid);
info.add(Sigar.formatSize(mem.getSize()));
info.add(Sigar.formatSize(mem.getRss()));
info.add(Sigar.formatSize(mem.getShare()));
} catch (SigarException e) {
info.add(unknown);
}
info.add(String.valueOf(state.getState()));
if (time != null) {
info.add(getCpuTime(time));
}
else {
info.add(unknown);
}
String name = state.getName();
if (name.equals("java")) {
//try to guess classname for java programs
try {
String[] args = sigar.getProcArgs(pid);
for (int i=1; i<args.length; i++) {
String arg = args[i];
if (!isClassName(arg)) {
continue;
}
//example: "java:weblogic.Server"
name += ":" + arg;
break;
}
} catch (SigarException e) {}
}
info.add(name);
return info;
}
public void output(long pid) throws SigarException {
println(join(getInfo(this.proxy, pid)));
}
private static String getCpuTime(ProcTime time) {
long t = (time.getUtime() + time.getStime());
return t/60 + ":" + t%60;
}
private static String getStartTime(long time) {
if (time == 0) {
return "00:00";
}
long timeNow = System.currentTimeMillis();
String fmt = "MMMd";
if ((timeNow - time) < ((60*60*24) * 1000)) {
fmt = "HH:mm";
}
return new SimpleDateFormat(fmt).format(new Date(time));
}
public static void main(String[] args) throws Exception {
new Ps().processCommand(args);
}
}

View File

@ -0,0 +1,30 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.NetRoute;
public class Route {
//netstat -r
public static void main(String[] args) throws Exception {
Sigar sigar = new Sigar();
NetRoute[] routes = sigar.getNetRouteList();
System.out.println("Destination\tGateway\tGenmask" +
"\tFlags\tMSS\tWindow\tirtt\tIface");
for (int i=0; i<routes.length; i++) {
NetRoute route = routes[i];
System.out.println(route.getDestination() + "\t" +
route.getGateway() + "\t" +
route.getMask() + "\t" +
route.getFlags() + "\t" +
route.getMtu() + "\t" +
route.getWindow() + "\t" +
route.getIrtt() + "\t" +
route.getIfname());
}
}
}

View File

@ -0,0 +1,185 @@
package net.hyperic.sigar.cmd;
import java.io.File;
import java.io.FileFilter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.net.URLClassLoader;
import java.net.URL;
public class Runner {
private static HashMap wantedJars = new HashMap();
static {
wantedJars.put("bcel-5.1.jar", Boolean.FALSE);
wantedJars.put("junit.jar", Boolean.FALSE);
wantedJars.put("log4j.jar", Boolean.FALSE);
}
private static void printMissingJars() {
for (Iterator it = wantedJars.entrySet().iterator();
it.hasNext();)
{
Map.Entry entry = (Map.Entry)it.next();
String jar = (String)entry.getKey();
if (wantedJars.get(jar) == Boolean.FALSE) {
System.out.println("Unable to locate: " + jar);
}
}
}
private static boolean missingJars() {
for (Iterator it = wantedJars.entrySet().iterator();
it.hasNext();)
{
Map.Entry entry = (Map.Entry)it.next();
String jar = (String)entry.getKey();
if (wantedJars.get(jar) == Boolean.FALSE) {
return true;
}
}
return false;
}
public static URL[] getLibJars(String dir) throws Exception {
File[] jars = new File(dir).listFiles(new FileFilter() {
public boolean accept(File file) {
return wantedJars.get(file.getName()) != null;
}
});
if (jars == null) {
return new URL[0];
}
URL[] urls = new URL[jars.length];
for (int i=0; i<jars.length; i++) {
wantedJars.put(jars[i].getName(),
Boolean.TRUE);
URL url =
new URL("jar", null,
"file:" + jars[i].getAbsolutePath() + "!/");
urls[i] = url;
}
return urls;
}
private static void addURLs(URL[] jars) throws Exception {
URLClassLoader loader =
(URLClassLoader)Thread.currentThread().getContextClassLoader();
//bypass protected access.
Method addURL =
URLClassLoader.class.getDeclaredMethod("addURL",
new Class[] {
URL.class
});
addURL.setAccessible(true); //pound sand.
for (int i=0; i<jars.length; i++) {
addURL.invoke(loader, new Object[] { jars[i] });
}
}
private static boolean addJarDir(String dir) throws Exception {
URL[] jars = getLibJars(dir);
addURLs(jars);
return !missingJars();
}
public static void main(String[] args) throws Exception {
if (args.length < 1) {
args = new String[] { "Shell" };
}
else {
//e.g. convert
// "ifconfig", "eth0"
// to:
// "Shell", "ifconfig", "eth0"
if (Character.isLowerCase(args[0].charAt(0))) {
String[] nargs = new String[args.length + 1];
System.arraycopy(args, 0, nargs, 1, args.length);
nargs[0] = "Shell";
args = nargs;
}
}
String name = args[0];
String[] pargs = new String[args.length - 1];
System.arraycopy(args, 1, pargs, 0, args.length-1);
String[] dirs = { "lib", "." };
for (int i=0; i<dirs.length; i++) {
if (addJarDir(dirs[i])) {
break;
}
}
if (missingJars()) {
File[] subdirs = new File(".").listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
});
for (int i=0; i<subdirs.length; i++) {
File lib = new File(subdirs[i], "lib");
if (lib.exists()) {
if (addJarDir(lib.getAbsolutePath())) {
break;
}
}
}
}
Class cmd = null;
String[] packages = {
"net.hyperic.sigar.cmd.",
"net.hyperic.sigar.test."
};
for (int i=0; i<packages.length; i++) {
try {
cmd = Class.forName(packages[i] + name);
break;
} catch (ClassNotFoundException e) {}
}
if (cmd == null) {
System.out.println("Unknown command: " + args[0]);
return;
}
Method main = cmd.getMethod("main",
new Class[] {
String[].class
});
try {
main.invoke(null, new Object[] { pargs });
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof NoClassDefFoundError) {
System.out.println("Class Not Found: " +
t.getMessage());
printMissingJars();
}
else {
t.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,147 @@
package net.hyperic.sigar.cmd;
import java.io.IOException;
import java.io.File;
import java.util.ArrayList;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.SigarProxyCache;
import net.hyperic.sigar.ptql.ProcessFinder;
import net.hyperic.sigar.shell.ShellBase;
import net.hyperic.sigar.shell.ShellCommandExecException;
import net.hyperic.sigar.shell.ShellCommandHandler;
import net.hyperic.sigar.shell.ShellCommandInitException;
import net.hyperic.sigar.shell.ShellCommandUsageException;
import net.hyperic.sigar.test.SigarTestRunner;
public class Shell extends ShellBase {
private Sigar sigar = new Sigar();
private SigarProxy proxy = SigarProxyCache.newInstance(this.sigar);
private ProcessFinder finder = new ProcessFinder(this.proxy);
private long[] foundPids = new long[0];
private ArrayList completions = new ArrayList();
private boolean isInteractive = false;
public Shell() {
}
public SigarProxy getSigarProxy() {
return this.proxy;
}
public Sigar getSigar() {
return this.sigar;
}
public boolean isInteractive() {
return this.isInteractive;
}
public void registerCommands() throws ShellCommandInitException {
registerCommandHandler("df", new Df(this));
registerCommandHandler("free", new Free(this));
registerCommandHandler("pargs", new ShowArgs(this));
registerCommandHandler("penv", new ShowEnv(this));
registerCommandHandler("pfile", new ProcFileInfo(this));
registerCommandHandler("ptql", new PTQL(this));
registerCommandHandler("cpuinfo", new CpuInfo(this));
registerCommandHandler("ifconfig", new Ifconfig(this));
registerCommandHandler("uptime", new Uptime(this));
registerCommandHandler("ps", new Ps(this));
registerCommandHandler("kill", new Kill(this));
registerCommandHandler("netstat", new Netstat(this));
registerCommandHandler("version", new Version(this));
registerCommandHandler("test", new SigarTestRunner(this));
}
public void processCommand(ShellCommandHandler handler, String args[])
throws ShellCommandUsageException, ShellCommandExecException
{
try {
super.processCommand(handler, args);
if (handler instanceof SigarCommandBase) {
((SigarCommandBase)handler).flush();
}
} finally {
SigarProxyCache.clear(this.proxy);
}
}
public static long[] getPids(SigarProxy sigar, String[] args)
throws SigarException {
long[] pids;
switch (args.length) {
case 0:
pids = new long[] { sigar.getPid() };
break;
case 1:
if (args[0].indexOf("=") > 0) {
pids = ProcessFinder.find(sigar, args[0]);
}
else if (args[0].equals("$$")) {
pids = new long[] { sigar.getPid() };
}
else {
pids = new long[] {
Long.parseLong(args[0])
};
}
break;
default:
pids = new long[args.length];
for (int i=0; i<args.length; i++) {
pids[i] = Long.parseLong(args[i]);
}
break;
}
return pids;
}
public long[] findPids(String[] args) throws SigarException {
if ((args.length == 1) && args[0].equals("-")) {
return this.foundPids;
}
this.foundPids = getPids(this.proxy, args);
return this.foundPids;
}
public static void main(String[] args) {
Shell shell = new Shell();
try {
shell.init("sigar", System.out, System.err);
shell.registerCommands();
String home = System.getProperty("user.home");
try {
shell.readRCFile(new File(home, ".sigar"), false);
} catch (IOException e) { }
if (args.length == 0) {
shell.isInteractive = true;
shell.initHistory();
shell.gl.setCompleter(shell);
shell.run();
}
else {
shell.handleCommand(null, args);
}
} catch (Exception e) {
System.err.println("Unexpected exception: " + e);
} finally {
shell.shutdown();
}
}
}

View File

@ -0,0 +1,67 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarNotImplementedException;
public class ShowArgs extends SigarCommandBase {
public ShowArgs(Shell shell) {
super(shell);
}
public ShowArgs() {
super();
}
protected boolean validateArgs(String[] args) {
return true;
}
public String getUsageShort() {
return "Show process command line arguments";
}
public boolean isPidCompleter() {
return true;
}
public void output(String[] args) throws SigarException {
long[] pids = this.shell.findPids(args);
for (int i=0; i<pids.length; i++) {
output(pids[i]);
println("\n------------------------\n");
}
}
public void output(long pid) throws SigarException {
String[] argv = this.proxy.getProcArgs(pid);
println("pid=" + pid);
try {
String exe = this.proxy.getProcExe(pid).getName();
println("exe=" + exe);
} catch (SigarNotImplementedException e) {
} catch (SigarException e) {
println("exe=???");
}
try {
String cwd = this.proxy.getProcExe(pid).getCwd();
println("cwd=" + cwd);
} catch (SigarNotImplementedException e) {
} catch (SigarException e) {
println("cwd=???");
}
for (int i=0; i<argv.length; i++) {
println(" " + i + "=" + argv[i]);
}
}
public static void main(String[] args) throws Exception {
new ShowArgs().processCommand(args);
}
}

View File

@ -0,0 +1,59 @@
package net.hyperic.sigar.cmd;
import java.util.Map;
import java.util.Iterator;
import net.hyperic.sigar.SigarException;
public class ShowEnv extends SigarCommandBase {
public ShowEnv(Shell shell) {
super(shell);
}
public ShowEnv() {
super();
}
protected boolean validateArgs(String[] args) {
return true;
}
public String getUsageShort() {
return "Show process environment";
}
public boolean isPidCompleter() {
return true;
}
public void output(String[] args) throws SigarException {
long[] pids = this.shell.findPids(args);
for (int i=0; i<pids.length; i++) {
try {
println("pid=" + pids[i]);
output(pids[i]);
} catch (SigarException e) {
println(e.getMessage());
}
println("\n------------------------\n");
}
}
public void output(long pid) throws SigarException {
Map env = this.proxy.getProcEnv(pid);
for (Iterator it = env.entrySet().iterator();
it.hasNext();)
{
Map.Entry ent = (Map.Entry)it.next();
println(ent.getKey() + "=" + ent.getValue());
}
}
public static void main(String[] args) throws Exception {
new ShowEnv().processCommand(args);
}
}

View File

@ -0,0 +1,147 @@
package net.hyperic.sigar.cmd;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.pager.PageControl;
import net.hyperic.sigar.pager.PageFetchException;
import net.hyperic.sigar.pager.StaticPageFetcher;
import net.hyperic.sigar.util.GetlineCompleter;
import net.hyperic.sigar.util.PrintfFormat;
import net.hyperic.sigar.shell.CollectionCompleter;
import net.hyperic.sigar.shell.ShellCommandBase;
import net.hyperic.sigar.shell.ShellCommandExecException;
import net.hyperic.sigar.shell.ShellCommandUsageException;
public abstract class SigarCommandBase
extends ShellCommandBase
implements GetlineCompleter {
protected Shell shell;
protected PrintStream out = System.out;
protected PrintStream err = System.err;
protected Sigar sigar;
protected SigarProxy proxy;
protected List output = new ArrayList();
private CollectionCompleter completer;
private Collection completions = new ArrayList();
private PrintfFormat formatter;
public SigarCommandBase(Shell shell) {
this.shell = shell;
this.out = shell.getOutStream();
this.err = shell.getErrStream();
this.sigar = shell.getSigar();
this.proxy = shell.getSigarProxy();
//provide simple way for handlers to implement tab completion
this.completer = new CollectionCompleter(shell);
}
public SigarCommandBase() {
this(new Shell());
this.shell.setPageSize(PageControl.SIZE_UNLIMITED);
}
public void setOutputFormat(String format) {
this.formatter = new PrintfFormat(format);
}
public PrintfFormat getFormatter() {
return this.formatter;
}
public void printf(Object[] items) {
println(getFormatter().sprintf(items));
}
public void printf(List items) {
printf((Object[])items.toArray(new Object[0]));
}
public void println(String line) {
if (this.shell.isInteractive()) {
this.output.add(line);
}
else {
this.out.println(line);
}
}
public void flush() {
try {
this.shell.performPaging(new StaticPageFetcher(this.output));
} catch(PageFetchException e) {
this.err.println("Error paging: " + e.getMessage());
} finally {
this.output.clear();
}
}
public abstract void output(String[] args)
throws SigarException;
protected boolean validateArgs(String[] args) {
return args.length == 0;
}
public void processCommand(String[] args)
throws ShellCommandUsageException, ShellCommandExecException
{
if (!validateArgs(args)) {
throw new ShellCommandUsageException(getSyntax());
}
try {
output(args);
} catch (SigarException e) {
throw new ShellCommandExecException(e.getMessage());
}
}
public Collection getCompletions() {
return this.completions;
}
public GetlineCompleter getCompleter() {
return null;
}
public boolean isPidCompleter() {
return false;
}
public String completePid(String line) {
if ((line.length() >= 1) &&
Character.isDigit(line.charAt(0)))
{
return line;
}
return
((GetlineCompleter)this.shell.getHandler("ptql")).complete(line);
}
public String complete(String line) {
if (isPidCompleter()) {
return completePid(line);
}
GetlineCompleter c = getCompleter();
if (c != null) {
return c.complete(line);
}
this.completer.setCollection(getCompletions());
return this.completer.complete(line);
}
}

View File

@ -0,0 +1,62 @@
package net.hyperic.sigar.cmd;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.Reader;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.FileInfo;
import net.hyperic.sigar.FileTail;
import net.hyperic.sigar.FileWatcherThread;
public class Tail {
public static void main(String[] args) throws SigarException {
final String pattern;
Sigar sigar = new Sigar();
FileWatcherThread watcherThread =
FileWatcherThread.getInstance();
watcherThread.doStart();
watcherThread.setInterval(1000);
FileTail watcher =
new FileTail(sigar) {
public void tail(FileInfo info, Reader reader) {
String line;
BufferedReader buffer =
new BufferedReader(reader);
if (getFiles().size() > 1) {
System.out.println("==> " +
info.getName() +
" <==");
}
try {
while ((line = buffer.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println(e);
}
}
};
for (int i=0; i<args.length; i++) {
watcher.add(args[i]);
}
watcherThread.add(watcher);
try {
System.in.read();
} catch (IOException e) { }
watcherThread.doStop();
}
}

View File

@ -0,0 +1,65 @@
package net.hyperic.sigar.cmd;
import java.util.List;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.CpuPerc;
import net.hyperic.sigar.SigarProxyCache;
import net.hyperic.sigar.ProcCpu;
import net.hyperic.sigar.CurrentProcessSummary;
/**
* Example:<br>
* <code>% java -jar sigar-bin/lib/sigar.jar Top State.Name.eq=java</code>
*/
public class Top {
private static final int SLEEP_TIME = 1000 * 5;
private static final String HEADER =
"PID\tUSER\tSTIME\tSIZE\tRSS\tSHARE\tSTATE\tTIME\t%CPU\tCOMMAND";
private static final String CLEAR_SCREEN = "\033[2J";
public static void main(String[] args) throws Exception {
Sigar sigarImpl = new Sigar();
SigarProxy sigar =
SigarProxyCache.newInstance(sigarImpl, SLEEP_TIME);
while (true) {
System.out.print(CLEAR_SCREEN);
System.out.println(Uptime.getInfo(sigar));
System.out.println(CurrentProcessSummary.get(sigar));
System.out.println(sigar.getCpuPerc());
System.out.println(sigar.getMem());
System.out.println(sigar.getSwap());
System.out.println();
System.out.println(HEADER);
long[] pids = Shell.getPids(sigar, args);
for (int i=0; i<pids.length; i++) {
long pid = pids[i];
ProcCpu cpu = sigar.getProcCpu(pid);
List info = Ps.getInfo(sigar, pid);
info.add(info.size()-1,
CpuPerc.format(cpu.getPercent()));
System.out.println(Ps.join(info));
}
Thread.sleep(SLEEP_TIME);
SigarProxyCache.clear(sigar);
}
}
}

View File

@ -0,0 +1,80 @@
package net.hyperic.sigar.cmd;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarNotImplementedException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Uptime extends SigarCommandBase {
public Uptime(Shell shell) {
super(shell);
}
public Uptime() {
super();
}
public String getUsageShort() {
return "Show how long the system has been running";
}
public void output(String[] args) throws SigarException {
System.out.println(getInfo(this.sigar));
}
public static String getInfo(SigarProxy sigar) throws SigarException {
double uptime = sigar.getUptime().getUptime();
String loadAverage;
try {
double[] avg = sigar.getLoadAverage();
loadAverage = "load average: " +
avg[0] + ", " + avg[1] + ", " + avg[2];
} catch (SigarNotImplementedException e) {
loadAverage = "(load average unknown)";
}
return
" " + getCurrentTime() +
" up " + formatUptime(uptime) +
", " + loadAverage;
}
private static String formatUptime(double uptime) {
String retval = "";
int days = (int)uptime / (60*60*24);
int minutes, hours;
if (days != 0) {
retval += days + " " + ((days > 1) ? "days" : "day") + ", ";
}
minutes = (int)uptime / 60;
hours = minutes / 60;
hours %= 24;
minutes %= 60;
if (hours != 0) {
retval += hours + ":" + minutes;
}
else {
retval += minutes + " min";
}
return retval;
}
private static String getCurrentTime() {
return new SimpleDateFormat("h:mm a").format(new Date());
}
//pretty close to uptime command, but we don't output number of users yet
public static void main(String[] args) throws Exception {
new Uptime().processCommand(args);
}
}

View File

@ -0,0 +1,49 @@
package net.hyperic.sigar.cmd;
import java.io.PrintStream;
import net.hyperic.sigar.Sigar;
public class Version extends SigarCommandBase {
private static String[] SYS_PROPS = {
"os.name",
"os.version",
"os.arch",
"java.vm.version",
"java.vm.vendor",
"sun.arch.data.model",
"sun.cpu.endian",
"sun.os.patch.level",
};
public Version(Shell shell) {
super(shell);
}
public Version() {
super();
}
public String getUsageShort() {
return "Display sigar version";
}
public static void printInfo(PrintStream os) {
os.println("Sigar version=" + Sigar.VERSION);
os.println("");
for (int i=0; i<SYS_PROPS.length; i++) {
String prop = SYS_PROPS[i];
os.println(prop + "=" +
System.getProperty(prop));
}
}
public void output(String[] args) {
printInfo(this.out);
}
public static void main(String[] args) throws Exception {
new Version().processCommand(args);
}
}

View File

@ -0,0 +1,127 @@
package net.hyperic.sigar.cmd;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Date;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.DirStat;
import net.hyperic.sigar.FileInfo;
import net.hyperic.sigar.FileWatcher;
import net.hyperic.sigar.FileWatcherThread;
public class Watch {
private static void printHeader(Sigar sigar, FileInfo info)
throws SigarException {
String file = info.getName();
FileInfo link = sigar.getLinkInfo(file);
if (link.getType() == FileInfo.TYPE_LNK) {
try {
System.out.println(file + " -> " +
new File(file).getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(link.getTypeChar() +
info.getPermissionsString() + "\t" +
info.getUid() + "\t" + info.getGid() + "\t" +
info.getSize() + "\t" +
new Date(info.getMtime()) + "\t" +
file);
if (info.getType() == FileInfo.TYPE_DIR) {
info.enableDirStat(true);
DirStat stats = sigar.getDirStat(file);
System.out.println(" Files......." + stats.getFiles());
System.out.println(" Subdirs....." + stats.getSubdirs());
System.out.println(" Symlinks...." + stats.getSymlinks());
System.out.println(" Chrdevs....." + stats.getChrdevs());
System.out.println(" Blkdevs....." + stats.getBlkdevs());
System.out.println(" Sockets....." + stats.getSockets());
System.out.println(" Total......." + stats.getTotal());
}
}
private static void add(Sigar sigar,
FileWatcher watcher,
String file,
boolean recurse)
throws SigarException {
FileInfo info = watcher.add(file);
printHeader(sigar, info);
if (!recurse) {
return;
}
if (info.getType() == FileInfo.TYPE_DIR) {
File[] dirs =
new File(info.getName()).listFiles(new FileFilter() {
public boolean accept(File file) {
return file.isDirectory() && file.canRead();
}
});
for (int i=0; i<dirs.length; i++) {
add(sigar, watcher, dirs[i].getAbsolutePath(), recurse);
}
}
}
public static void main(String[] args) throws SigarException {
boolean recurse = false;
Sigar sigar = new Sigar();
FileWatcherThread watcherThread =
FileWatcherThread.getInstance();
watcherThread.doStart();
watcherThread.setInterval(1000);
FileWatcher watcher =
new FileWatcher(sigar) {
public void onChange(FileInfo info) {
System.out.println(info.getName() +
" Changed:\n" + info.diff());
}
public void onNotFound(FileInfo info) {
System.out.println(info.getName() + " no longer exists");
remove(info.getName());
}
public void onException(FileInfo info, SigarException e) {
System.out.println("Error checking " + info.getName() + ":");
e.printStackTrace();
}
};
watcher.setInterval(watcherThread.getInterval());
for (int i=0; i<args.length; i++) {
if (args[i].equals("-r")) {
recurse = true;
continue;
}
add(sigar, watcher, args[i], recurse);
}
watcherThread.add(watcher);
System.out.println("Press any key to stop");
try {
System.in.read();
} catch (IOException e) { }
watcherThread.doStop();
}
}

View File

@ -0,0 +1,178 @@
package net.hyperic.sigar.jmx;
import java.util.Map;
import java.util.StringTokenizer;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarInvoker;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.util.ReferenceMap;
/**
* Extension of SigarInvoker to provide JMX style ObjectName
* interface to sigar.
*/
public class SigarInvokerJMX extends SigarInvoker {
public static final String DOMAIN_NAME = "sigar";
public static final String PROP_TYPE = "Type";
public static final String PROP_ARG = "Arg";
private String arg = null;
private static Map cache =
ReferenceMap.synchronizedMap();
/**
* Get an invoker instance for the given object name.
* A cache is maintained so only 1 invoker object per
* unique object name will be constructed. The object name
* is in the format of:
* domainName:prop=val,prop2=val2
* Only two properties are currently recognized:
* Type == The SigarProxy name, required. (e.g. Cpu, Mem)
* Arg == Argument (if any) for the given type, optional. (e.g. Arg=eth0)
* @param proxy The SigarProxy object (e.g. SigarProxyCache)
* @param name The object Name (e.g. sigar:Type=NetIfStat,Arg=eth0)
*/
public static SigarInvokerJMX getInstance(SigarProxy proxy,
String name) {
SigarInvokerJMX invoker;
if ((invoker = (SigarInvokerJMX)cache.get(name)) != null) {
return invoker;
}
invoker = new SigarInvokerJMX();
invoker.setProxy(proxy);
int ix = name.indexOf(":");
if (ix > 0) {
//skip domain name
name = name.substring(ix + 1);
}
StringTokenizer st = new StringTokenizer(name, ",");
while (st.hasMoreTokens()) {
String attr = st.nextToken();
ix = attr.indexOf('=');
String key = attr.substring(0, ix);
String val = attr.substring(key.length()+1);
if (key.equals(PROP_TYPE)) {
invoker.setType(val);
}
else if (key.equals(PROP_ARG)) {
//need to decode value, e.g. Arg=C%3D\ => Arg=C:\
invoker.setArg(decode(val));
}
}
cache.put(name, invoker);
return invoker;
}
//like URLDecoder but we only look for escaped ObjectName
//delimiters ':', '=' and ','
public static String decode(String val) {
StringBuffer buf = new StringBuffer(val.length());
boolean changed = false;
int len = val.length();
int i = 0;
while (i < len) {
char c = val.charAt(i);
if (c == '%') {
char d;
if (i+2 > len) {
break;
}
String s = val.substring(i+1, i+3);
if (s.equals("3A")) {
d = ':';
}
else if (s.equals("3D")) {
d = '=';
}
else if (s.equals("2C")) {
d = ',';
}
else {
buf.append(c);
i++;
continue;
}
changed = true;
buf.append(d);
i += 3;
}
else {
buf.append(c);
i++;
}
}
return changed ? buf.toString() : val;
}
private void setArg(String val) {
this.arg = val;
}
/**
* The value of the parsed Arg property.
*/
public String getArg() {
return this.arg;
}
/**
* Returns a JMX style object name with given property values.
*/
public static String getObjectName(String type, String arg) {
String s = DOMAIN_NAME + ":";
s += PROP_TYPE + "=" + type;
if (arg != null) {
s += "," + PROP_ARG + "=" + arg;
}
return s;
}
/**
* Returns a JMX style object that represents this instance.
*/
public String getObjectName() {
return getObjectName(getType(), getArg());
}
public String toString() {
return getObjectName();
}
/**
* Invoke an attribute method for the given object.
* Example:
* SigarInvokerJMX invoker = new SigarInvokerJMX(proxy, "Type=Mem");
* Object val = invoker.invoke("Free");
*
* @param attr The attribute name (e.g. Total)
* @exception SigarException If invocation fails.
*/
public Object invoke(String attr)
throws SigarException {
return super.invoke(getArg(), attr);
}
}

View File

@ -0,0 +1,71 @@
package net.hyperic.sigar.jmx;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.SigarProxyCache;
/**
* Implement the SigarProcessMBean to provide current process info
* via JMX.
*/
public class SigarProcess implements SigarProcessMBean {
private Sigar sigar;
private SigarProxy sigarProxy;
private static final String procMemName =
SigarInvokerJMX.getObjectName("ProcMem", "$$");
private static final String procTimeName =
SigarInvokerJMX.getObjectName("ProcTime", "$$");
private SigarInvokerJMX procMem, procTime;
public SigarProcess() {
this(null);
}
public SigarProcess(String path) {
sigar = new Sigar();
sigarProxy = SigarProxyCache.newInstance(sigar);
procMem = SigarInvokerJMX.getInstance(sigarProxy,
procMemName);
procTime = SigarInvokerJMX.getInstance(sigarProxy,
procTimeName);
}
public void close() {
}
private Long getLongValue(SigarInvokerJMX invoker, String attr) {
try {
return (Long)invoker.invoke(attr);
} catch (SigarException e) {
return new Long(-1);
}
}
public Long getMemSize() {
return getLongValue(procMem, "Size");
}
public Long getMemVsize() {
return getLongValue(procMem, "Vsize");
}
public Long getMemShare() {
return getLongValue(procMem, "Share");
}
public Long getTimeUser() {
return getLongValue(procTime, "Utime");
}
public Long getTimeSys() {
return getLongValue(procTime, "Stime");
}
}

View File

@ -0,0 +1,19 @@
package net.hyperic.sigar.jmx;
/*
* yeah, yeah, we could generate this class via xdoclet,
* whoopdi-friggin-do... by hand is much less pain.
*/
public interface SigarProcessMBean {
public Long getMemSize();
public Long getMemVsize();
public Long getMemShare();
public Long getTimeUser();
public Long getTimeSys();
}

View File

@ -0,0 +1,22 @@
package net.hyperic.sigar.pager;
/**
* The default page processor does not process any elements
* that you're paging. This is useful if you're only looking
* to page through an existing collection, and you don't need
* to perform any transformations on the elements that are
* found to belong in the resultant page.
*/
public class DefaultPagerProcessor implements PagerProcessor {
/**
* Default processor does not process anything, it just
* returns what was passed in.
* @param o The object to process.
* @return The same (completely unmodified) object that was passed in.
* @see PagerProcessor#processElement
*/
public Object processElement(Object o) {
return o;
}
}

View File

@ -0,0 +1,108 @@
package net.hyperic.sigar.pager;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
/**
* A PageFetcher which works with a pre-fetched list as the
* data backing the fetcher.
*/
public class ListPageFetcher extends PageFetcher {
private List data;
private int sortOrder;
public ListPageFetcher(List data) {
super();
this.data = data;
this.sortOrder = PageControl.SORT_UNSORTED;
}
public PageList getPage(PageControl control) {
PageList res = new PageList();
int startIdx, curIdx, endIdx;
if (this.data.size() == 0) {
return new PageList();
}
this.ensureSortOrder(control);
res.setTotalSize(this.data.size());
startIdx = clamp(control.getPageEntityIndex(), 0,
this.data.size() - 1);
curIdx = startIdx;
if (control.getPagesize() == PageControl.SIZE_UNLIMITED) {
endIdx = this.data.size();
}
else {
endIdx = clamp(startIdx + control.getPagesize(), startIdx,
this.data.size());
}
for (ListIterator i=this.data.listIterator(startIdx);
i.hasNext() && curIdx < endIdx;
curIdx++)
{
res.add(i.next());
}
return res;
}
private class DescSorter implements Comparator {
public int compare(Object o1, Object o2){
return -((Comparable)o1).compareTo((Comparable)o2);
}
public boolean equals(Object other){
return false;
}
}
private void ensureSortOrder(PageControl control) {
if (control.getSortorder() == this.sortOrder) {
return;
}
this.sortOrder = control.getSortorder();
if (this.sortOrder == PageControl.SORT_UNSORTED) {
return;
}
else if(this.sortOrder == PageControl.SORT_ASC) {
Collections.sort(data);
}
else if(this.sortOrder == PageControl.SORT_DESC) {
Collections.sort(data, new DescSorter());
}
else {
throw new IllegalStateException("Unknown control sorting type: " +
this.sortOrder);
}
}
/**
* Clamp a value to a range. If the passed value is
* less than the minimum, return the minimum. If it
* is greater than the maximum, assign the maximum.
* else return the passed value.
*/
private static int clamp(int val, int min, int max) {
return (int)clamp((long)val, (long)min, (long)max);
}
private static long clamp(long val, long min, long max) {
if (val < min) {
return min;
}
if (val > max) {
return max;
}
return val;
}
}

View File

@ -0,0 +1,165 @@
package net.hyperic.sigar.pager;
import java.io.Serializable;
/**
* A utility class to wrap up all the paging/sorting options that
* are frequently used with finders and other methods that return
* lists of things.
*/
public class PageControl implements Serializable, Cloneable {
public static final int SIZE_UNLIMITED = -1;
public static final int SORT_UNSORTED = 0;
public static final int SORT_ASC = 1;
public static final int SORT_DESC = 2;
private int pagenum = 0;
private int pagesize = SIZE_UNLIMITED;
private int sortorder = SORT_UNSORTED;
private int sortattribute = SortAttribute.DEFAULT;
private Serializable metaData; // Meta-data that PageLists have returned
public PageControl() {}
public PageControl(int pagenum, int pagesize) {
this.pagenum = pagenum;
this.pagesize = pagesize;
}
public PageControl(int pagenum, int pagesize,
int sortorder, int sortattribute) {
this.pagenum = pagenum;
this.pagesize = pagesize;
this.sortorder = sortorder;
this.sortattribute = sortattribute;
}
public boolean isAscending() {
return this.sortorder == SORT_ASC;
}
public boolean isDescending() {
return this.sortorder == SORT_DESC;
}
/**
* sets the initial defaults for the PageControl. Sort attribute specifies
* which attribute to sort on.
*
* @param pc
* @param defaultSortAttr specifies the attribute to sort on.
* @return PageControl
*/
public static PageControl initDefaults(PageControl pc,
int defaultSortAttr) {
if (pc == null) {
pc = new PageControl();
}
else {
pc = (PageControl) pc.clone();
}
if (pc.getSortattribute() == SortAttribute.DEFAULT) {
pc.setSortattribute(defaultSortAttr);
}
if (pc.getSortorder() == SORT_UNSORTED) {
pc.setSortorder(SORT_ASC);
}
return pc;
}
/** @return The current page number (0-based) */
public int getPagenum() {
return this.pagenum;
}
/** @param pagenum Set the current page number to <code>pagenum</code> */
public void setPagenum(int pagenum) {
this.pagenum = pagenum;
}
/** @return The current page size */
public int getPagesize() {
return this.pagesize;
}
/** @param pagesize Set the current page size to this value */
public void setPagesize(int pagesize) {
this.pagesize = pagesize;
}
/** @return The sort order used. This is one of the SORT_XXX constants. */
public int getSortorder() {
return this.sortorder;
}
/** @param sortorder Sort order to use, one of the SORT_XXX constants. */
public void setSortorder(int sortorder) {
this.sortorder = sortorder;
}
/** @return The attribute that the sort is based on. */
public int getSortattribute() {
return this.sortattribute;
}
/** @param attr Set the attribute that the sort is based on. */
public void setSortattribute(int attr) {
this.sortattribute = attr;
}
public Serializable getMetaData() {
return this.metaData;
}
public void getMetaData(Serializable metaData) {
this.metaData = metaData;
}
/**
* Get the index of the first item on the page as dictated by the
* page size and page number.
*/
public int getPageEntityIndex() {
return this.pagenum * this.pagesize;
}
public String toString() {
StringBuffer s = new StringBuffer("{");
s.append("pn=" + this.pagenum + " ");
s.append("ps=" + this.pagesize + " ");
s.append("so=");
switch(this.sortorder) {
case SORT_ASC:
s.append("asc ");
break;
case SORT_DESC:
s.append("desc");
break;
case SORT_UNSORTED:
s.append("unsorted ");
break;
default:
s.append(' ');
}
s.append("sa=" + this.sortattribute + " ");
s.append("}");
return s.toString();
}
public Object clone() {
PageControl res =
new PageControl(this.pagenum, this.pagesize,
this.sortorder, this.sortattribute);
res.metaData = metaData;
return res;
}
}

View File

@ -0,0 +1,11 @@
package net.hyperic.sigar.pager;
public class PageFetchException extends Exception {
public PageFetchException() {
super();
}
public PageFetchException(String s) {
super(s);
}
}

View File

@ -0,0 +1,14 @@
package net.hyperic.sigar.pager;
/**
* A class which abstracts the fetching of the data for the pages
* so callers can deal directly with a single object.
*/
public abstract class PageFetcher {
/**
* Get a page of data, as specified by the control.
*/
public abstract PageList getPage(PageControl control)
throws PageFetchException;
}

View File

@ -0,0 +1,76 @@
package net.hyperic.sigar.pager;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
/**
* A utility class that contains all a "page" of data that is viewable
* <br>
* this list may or may not conain the entire list of information.
* generally this list conains a subset of data.
* <br>
* ex. say we have a list of 5000 users. the entire list does not need to be
* returned to only display the first 15 items, the user is only going to see
* the first 15 both the user and the application the user will want to know
* that there are 5000 users in the system.
* <br>
*
*/
public class PageList extends ArrayList implements Serializable {
private int totalSize = 0;
private boolean isUnbounded; // Is the total size of the list known?
private Serializable metaData;
public PageList() {
super();
this.isUnbounded = false;
}
public PageList(Collection c, int totalSize) {
super(c);
this.totalSize = totalSize;
this.isUnbounded = false;
}
public String toString() {
StringBuffer s = new StringBuffer("{");
s.append("totalSize=" + totalSize + " ");
s.append("}");
return super.toString() + s.toString();
}
/** returns the total size of the "masterlist" that this page is a
* subset of.
* @return Value of property listSize.
*/
public int getTotalSize() {
return Math.max(this.size(), this.totalSize);
}
/** Sets the total size of the "masterlist" that this page is a subset of.
* @param totalSize New value of property listSize.
*
*/
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public void setMetaData(Serializable metaData){
this.metaData = metaData;
}
public Serializable getMetaData(){
return this.metaData;
}
public boolean isUnbounded(){
return this.isUnbounded;
}
public void setUnbounded(boolean isUnbounded){
this.isUnbounded = isUnbounded;
}
}

View File

@ -0,0 +1,313 @@
package net.hyperic.sigar.pager;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Implements a generic pager. What is a pager? Let's say you
* have a large collection of objects, perhaps a long list of
* EJB Local Interfaces. You're interested in breaking the
* mammoth list out into a number pages, each with 25 items on it.
* You're interested in returning page #17 of such a collection.
* Why bother implementing the "skip past a bunch of things, then
* return pagesize items in the resultant colleciton" over and over
* again.
*
* You can also have the elements go through a processor that you
* supply as they move from the source collection to the
* destination collection.
*/
public class Pager {
public static final String DEFAULT_PROCESSOR_CLASSNAME
= "net.hyperic.sigar.pager.DefaultPagerProcessor";
private static Map PagerProcessorMap =
Collections.synchronizedMap(new HashMap());
private PagerProcessor processor = null;
private boolean skipNulls = false;
private PagerEventHandler eventHandler = null;
private Pager ( PagerProcessor processor ) {
this.processor = processor;
this.skipNulls = false;
this.eventHandler = null;
if ( this.processor instanceof PagerProcessorExt ) {
this.skipNulls = ((PagerProcessorExt) this.processor).skipNulls();
this.eventHandler
= ((PagerProcessorExt) this.processor).getEventHandler();
}
}
public static Pager getDefaultPager () {
try {
return getPager(DEFAULT_PROCESSOR_CLASSNAME);
} catch ( Exception e ) {
throw new IllegalStateException("This should never happen: " + e);
}
}
/**
* Get a pager based on the PagerProcessor supplied.
*/
public static Pager getPager (String pageProcessorClassName)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException
{
Pager p = null;
p = (Pager) PagerProcessorMap.get(pageProcessorClassName);
if ( p == null ) {
PagerProcessor processor = (PagerProcessor)
Class.forName(pageProcessorClassName).newInstance();
p = new Pager(processor);
PagerProcessorMap.put(pageProcessorClassName, p);
}
return p;
}
/**
* Seek to the specified pagenum in the source collection and
* return pagsize numberof of elements in the List.
* If pagenum or pagesize is -1, then everything in the
* source collection will be returned.
*
* @param source The source collection to seek through.
* @param pagenum The page number to seek to. If there not
* enough pages in the collection, then an empty list will be returned.
* @param pagesize The size of each page.
* @return PageList containing results of seek.
*/
public PageList seek ( Collection source, int pagenum, int pagesize ) {
return seek(source,pagenum,pagesize,null);
}
/**
* Seek to the specified pagenum in the source collection and return pagsize
* numberof of elements in the List, as specified the PageControl object.
* If pagenum or pagesize is -1, then everything in the
* source collection will be returned.
*
* @param source The source collection to seek through.
* @param pc The page control used for page size and page number to seek to. If there not
* enough pages in the collection, then an empty list will be returned.
* @return PageList containing results of seek.
*/
public PageList seek ( Collection source, PageControl pc ) {
if (pc == null)
pc = new PageControl();
return seek(source, pc.getPagenum(), pc.getPagesize(), null);
}
/**
* Seek to the specified pagenum in the source collection and
* return pagsize numberof of elements in the List.
* If pagenum or pagesize is -1, then everything in the
* source collection will be returned.
*
* @param source The source collection to seek through.
* @param pagenum The page number to seek to. If there not
* enough pages in the collection, then an empty list will be returned.
* @param pagesize The size of each page.
* @param procData - any data object required by the processor.
* @return PageList containing results of seek.
*/
public PageList seek ( Collection source, int pagenum, int pagesize,
Object procData ) {
PageList dest = new PageList();
seek(source, dest, pagenum, pagesize, procData);
dest.setTotalSize(source.size());
return dest;
}
/**
* Seek to the specified pagenum in the source collection and place
* pagesize number of elements into the dest collection.
* If pagenum or pagesize is -1, then everything in the
* source collection will be placed in the dest collection.
*
* @param source The source collection to seek through.
* @param dest The collection to place results into.
* @param pagenum The page number to seek to. If there not
* enough pages in the collection, then an empty list will be returned.
* @param pagesize The size of each page.
*/
public void seek ( Collection source, Collection dest, int pagenum,
int pagesize ) {
seek(source,dest,pagenum,pagesize,null);
}
/**
* Seek to the specified pagenum in the source collection and place
* pagesize number of elements into the dest collection.
* If pagenum or pagesize is -1, then everything in the
* source collection will be placed in the dest collection.
*
* @param source The source collection to seek through.
* @param dest The collection to place results into.
* @param pagenum The page number to seek to. If there not
* enough pages in the collection, then an empty list will be returned.
* @param pagesize The size of each page.
* @param procData any object required to process the item.
*/
public void seek ( Collection source, Collection dest, int pagenum,
int pagesize, Object procData) {
Iterator iter = source.iterator();
int i, currentPage;
if ( pagesize == -1 || pagenum == -1 ) {
pagenum = 0;
pagesize = Integer.MAX_VALUE;
}
for ( i=0, currentPage=0;
iter.hasNext() && currentPage < pagenum;
i++, currentPage += (i % pagesize == 0) ? 1:0 ) {
iter.next();
}
if ( this.eventHandler != null ) this.eventHandler.init();
if ( this.skipNulls ) {
Object elt;
while ( iter.hasNext() && dest.size() < pagesize ) {
if (this.processor instanceof PagerProcessorExt)
elt = ((PagerProcessorExt)this.processor)
.processElement(iter.next(), procData);
else
elt = this.processor.processElement(iter.next());
if ( elt == null )
continue;
dest.add(elt);
}
} else {
while ( iter.hasNext() && dest.size() < pagesize ) {
dest.add(this.processor.processElement(iter.next()));
}
}
if ( this.eventHandler != null ) this.eventHandler.cleanup();
}
/**
* Seek to the specified pagenum in the source collection and place
* pagesize number of elements into the dest collection. Unlike,
* seek(), all items are passed to the Processor or ProcessorExt
* regardless whether they are placed in dest collection. If pagenum
* or pagesize is -1, then everything in the source collection will
* be placed in the dest collection.
*
* @param source The source collection to seek through.
* @param pagenum The page number to seek to. If there not
* enough pages in the collection, then an empty list will be returned.
* @param pagesize The size of each page.
* @param procData any object required to process the item.
*/
public PageList seekAll ( Collection source, int pagenum, int pagesize,
Object procData ) {
PageList dest = new PageList();
seekAll(source, dest, pagenum, pagesize, procData);
dest.setTotalSize(source.size());
return dest;
}
/**
* Seek to the specified pagenum in the source collection and place
* pagesize number of elements into the dest collection. Unlike,
* seek(), all items are passed to the Processor or ProcessorExt
* regardless whether they are placed in dest collection. If pagenum
* or pagesize is -1, then everything in the source collection will
* be placed in the dest collection.
*
* @param source The source collection to seek through.
* @param dest The collection to place results into.
* @param pagenum The page number to seek to. If there not
* enough pages in the collection, then an empty list will be returned.
* @param pagesize The size of each page.
* @param procData any object required to process the item.
*/
public void seekAll ( Collection source, Collection dest, int pagenum,
int pagesize, Object procData) {
Iterator iter = source.iterator();
int i, currentPage;
if ( pagesize == -1 || pagenum == -1 ) {
pagenum = 0;
pagesize = Integer.MAX_VALUE;
}
// PR:8434 : Multi-part paging fixes.
// 1.) Invoke the pager processor external which in many cases may
// be keeping track of element [in|ex]clusion.
// 2.) The counter 'i' is used with modulus arithmetic to determine
// which page we should be on. Don't increment it if the proc-ext
// indicated that the element should not be paged.
// 3.) 'i' begins it's existance at 0. Zero modulus anything yields
// zero. So the ternary expression needs to check for this initial
// condition and not increment the page number.
for ( i=0, currentPage=0;
iter.hasNext() && currentPage < pagenum;
currentPage += (i != 0 && i % pagesize == 0) ? 1:0 ) {
if (this.processor instanceof PagerProcessorExt) {
Object ret = ((PagerProcessorExt)this.processor)
.processElement(iter.next(), procData);
if (ret != null) {
i++;
}
} else {
this.processor.processElement(iter.next());
i++;
}
}
if ( this.eventHandler != null ) this.eventHandler.init();
if ( this.skipNulls ) {
Object elt;
while ( iter.hasNext() ) {
if (this.processor instanceof PagerProcessorExt)
elt = ((PagerProcessorExt)this.processor)
.processElement(iter.next(), procData);
else
elt = this.processor.processElement(iter.next());
if ( elt == null )
continue;
if (dest.size() < pagesize)
dest.add(elt);
}
} else {
while ( iter.hasNext() ) {
Object elt = this.processor.processElement(iter.next());
if (dest.size() < pagesize)
dest.add(elt);
}
}
if ( this.eventHandler != null ) this.eventHandler.cleanup();
}
/** Process all objects in the source page list and return the destination
* page list with the same total size
*/
public PageList processAll(PageList source) {
PageList dest = new PageList();
for (Iterator it = source.iterator(); it.hasNext(); ) {
Object elt = this.processor.processElement(it.next());
if ( elt == null )
continue;
dest.add(elt);
}
dest.setTotalSize(source.getTotalSize());
return dest;
}
}

View File

@ -0,0 +1,15 @@
package net.hyperic.sigar.pager;
/**
* This class is useful for classes that implement PagerProcessorExt and
* need to do some initialization before paging begins and some cleanup
* after paging has ended.
*/
public interface PagerEventHandler {
/** Called before paging begins. */
public void init();
/** Called after paging ends. */
public void cleanup();
}

View File

@ -0,0 +1,19 @@
package net.hyperic.sigar.pager;
/**
* Provides a point of extensibility in the paging behavior.
* If you supply a PagerProcessor when you get a Pager,
* then that processor will be called to process each element
* as the pager moves it from the source collection to the
* destination collection.
*/
public interface PagerProcessor {
/**
* Process an element as the pager moves it from the source
* collection to the destination collection.
* @param o The object to process.
* @return The processed object.
*/
public Object processElement(Object o);
}

View File

@ -0,0 +1,37 @@
package net.hyperic.sigar.pager;
/**
* Provides a point of extensibility in the paging behavior.
* If you supply a PagerProcessor when you get a Pager,
* then that processor will be called to process each element
* as the pager moves it from the source collection to the
* destination collection.
*/
public interface PagerProcessorExt extends PagerProcessor {
/**
* Get the event handler for this pager. May return null to indicate
* that no event handler should be used.
*/
public PagerEventHandler getEventHandler();
/**
* Determines if null values are included in the Pager's results.
* @return If this method returns true, then when the processElement
* method returns null, that element will not be included in the results.
* If this methods returns false, then nulls may be added to the result
* page.
*/
public boolean skipNulls();
/**
* Process an element as the pager moves it from the source
* collection to the destination collection. This version
* allows an additional argument to be passed along.
* @param o1 The object to process.
* @param o2 Additional data required to processElement.
* @return The processed object.
*/
public Object processElement(Object o1, Object o2);
}

View File

@ -0,0 +1,52 @@
package net.hyperic.sigar.pager;
import java.io.Serializable;
public class SortAttribute implements Serializable {
private SortAttribute () {}
public static final int DEFAULT = 0;
// Generic attributes
public static final int NAME = 1;
public static final int CTIME = 2;
// Authz sort attributes - specifieds which column to store on
// for example, for 'subject_name', sort on column #3
public static final int ROLE_NAME = 1;
public static final int RESGROUP_NAME = 2;
public static final int RESTYPE_NAME = 4;
public static final int RESOURCE_NAME = 5;
public static final int OPERATION_NAME = 6;
public static final int ROLE_MEMBER_CNT= 17;
public static final int SUBJECT_NAME = 3;
public static final int FIRST_NAME = 7;
public static final int LAST_NAME = 8;
// Event sort attributes
public static final int EVENT_LOG_CTIME = 1;
// Control sort attributes
public static final int CONTROL_ACTION = 9;
public static final int CONTROL_STATUS = 10;
public static final int CONTROL_STARTED = 11;
public static final int CONTROL_ELAPSED = 12;
public static final int CONTROL_DATESCHEDULED = 13;
public static final int CONTROL_DESCRIPTION = 14;
public static final int CONTROL_NEXTFIRE = 15;
public static final int CONTROL_ENTITYNAME = 16;
public static final int OWNER_NAME = 21;
public static final int SERVICE_NAME = 22;
public static final int SERVICE_TYPE = 23;
public static final int RT_NAME = 24;
public static final int RT_LOW = 25;
public static final int RT_AVG = 26;
public static final int RT_PEAK = 27;
}

View File

@ -0,0 +1,53 @@
package net.hyperic.sigar.pager;
import java.util.Arrays;
import java.util.List;
/**
* A fetcher which uses a static array of strings to page
* through.
*/
public class StaticPageFetcher extends PageFetcher {
private List data;
public StaticPageFetcher(String[] data) {
this.data = Arrays.asList(data);
}
public StaticPageFetcher(List data) {
this.data = data;
}
public PageList getPage(PageControl control)
throws PageFetchException
{
PageList res = new PageList();
int startIdx, endIdx;
res.setTotalSize(this.data.size());
if (control.getPagesize() == PageControl.SIZE_UNLIMITED ||
control.getPagenum() == -1)
{
res.addAll(this.data);
return res;
}
startIdx = control.getPageEntityIndex();
endIdx = startIdx + control.getPagesize();
if (startIdx >= this.data.size()) {
return res;
}
if (endIdx > this.data.size()) {
endIdx = this.data.size();
}
res.addAll(this.data.subList(startIdx, endIdx));
return res;
}
}

View File

@ -0,0 +1,15 @@
package net.hyperic.sigar.ptql;
/**
* Exception for malformed process queries which cannot
* be parsed.
*/
public class MalformedQueryException extends Exception {
public MalformedQueryException() {
}
public MalformedQueryException(String message) {
super(message);
}
}

View File

@ -0,0 +1,54 @@
package net.hyperic.sigar.ptql;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import net.hyperic.sigar.SigarException;
public class PidFileQuery extends PidQuery {
File file;
long modified = -1;
public PidFileQuery(String file) {
this.file = new File(file);
}
public long getPid()
throws SigarException {
if (!file.exists()) {
throw new SigarException(this.file + " does not exist");
}
long lastMod = file.lastModified();
if (lastMod == this.modified) {
return this.pid;
}
this.modified = lastMod;
String line;
try {
BufferedReader in =
new BufferedReader(new FileReader(this.file));
line = in.readLine();
} catch (FileNotFoundException e) {
throw new SigarException(e.getMessage());
} catch (IOException e) {
throw new SigarException(e.getMessage());
}
try {
this.pid = Long.parseLong(line);
} catch (NumberFormatException e) {
throw new SigarException("Not a number: " + line);
}
return this.pid;
}
}

View File

@ -0,0 +1,30 @@
package net.hyperic.sigar.ptql;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
public class PidQuery implements ProcessQuery {
protected long pid;
protected PidQuery() { }
public PidQuery(long pid) {
this.pid = pid;
}
public PidQuery(String pid) {
this.pid = Long.parseLong(pid);
}
public long getPid()
throws SigarException {
return this.pid;
}
public boolean match(SigarProxy sigar, long pid)
throws SigarException {
return pid == getPid();
}
}

View File

@ -0,0 +1,152 @@
package net.hyperic.sigar.ptql;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarNotImplementedException;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.SigarProxyCache;
public class ProcessFinder {
private SigarProxy proxy;
public ProcessFinder(SigarProxy proxy) {
this.proxy = proxy;
//getpid() cache to optimize queries on this process.
this.proxy.getPid();
}
public long findSingleProcess(ProcessQuery query)
throws SigarException, SigarNotImplementedException,
MalformedQueryException {
if (query instanceof PidQuery) {
return ((PidQuery)query).getPid();
}
int i, matches = 0;
long[] pids = this.proxy.getProcList();
long pid=-1;
for (i=0; i<pids.length; i++) {
try {
if (query.match(this.proxy, pids[i])) {
matches++;
pid = pids[i];
}
} catch (SigarNotImplementedException e) {
throw e; //let caller know query is invalid.
} catch (SigarException e) {
//ok, e.g. permission denied.
}
}
if (matches == 1) {
return pid;
}
String msg;
if (matches == 0) {
msg = "Query did not match any processes";
}
else {
msg = "Query matched multiple processes" +
" (" + matches + ")";
}
throw new MalformedQueryException(msg);
}
public static long[] find(Sigar sigar, String query)
throws SigarException {
SigarProxy proxy =
SigarProxyCache.newInstance(sigar);
return find(proxy, query);
}
public static long[] find(SigarProxy sigar, String query)
throws SigarException {
ProcessFinder finder = new ProcessFinder(sigar);
try {
return finder.find(ProcessQueryFactory.getInstance(query, sigar));
} catch (QueryLoadException e) {
throw new SigarException(e.getMessage());
} catch (MalformedQueryException e) {
throw new SigarException(e.getMessage());
}
}
public long[] find(StringBuffer query)
throws SigarException, SigarNotImplementedException {
return find(query.toString());
}
public long[] find(String query)
throws SigarException, SigarNotImplementedException {
try {
return find(ProcessQueryFactory.getInstance(query));
} catch (QueryLoadException e) {
throw new SigarException(e.getMessage());
} catch (MalformedQueryException e) {
throw new SigarException(e.getMessage());
}
}
public long[] find(ProcessQuery query)
throws SigarException, SigarNotImplementedException {
int matches=0, lastMatch=-1;
//because we modify the array below. XXX this sucks.
long[] pids = (long[])this.proxy.getProcList().clone();
for (int i=0; i<pids.length; i++) {
long pid = pids[i];
boolean add = false;
try {
add = query.match(this.proxy, pid);
} catch (SigarNotImplementedException e) {
throw e; //let caller know query is invalid.
} catch (SigarException e) {
//ok, e.g. permission denied.
}
if (add) {
++matches;
lastMatch = i;
}
else {
pids[i] = -1;
continue;
}
}
long[] matched = new long[matches];
if (matches == 1) {
/* avoid loop below */
matched[0] = pids[lastMatch];
return matched;
}
//XXX this is clunky
for (int i=0, j=0; i<=lastMatch; i++) {
if (pids[i] == -1) {
continue;
}
matched[j++] = pids[i];
}
return matched;
}
}

View File

@ -0,0 +1,10 @@
package net.hyperic.sigar.ptql;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
public interface ProcessQuery {
public boolean match(SigarProxy sigar, long pid)
throws SigarException;
}

View File

@ -0,0 +1,812 @@
package net.hyperic.sigar.ptql;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import net.hyperic.sigar.SigarProxy;
import org.apache.bcel.Constants;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.Type;
public class ProcessQueryBuilder {
//set true during development to dump generated
//.class files to disk.
private static final boolean dumpClasses = false;
private static int generation = 0;
private static final String SIGAR_PACKAGE =
"net.hyperic.sigar.";
private static final String PROC_PREFIX =
SIGAR_PACKAGE + "Proc";
private static final String PROXY_CLASS =
SIGAR_PACKAGE + "SigarProxy";
private static final String PROXY_HELPER =
SIGAR_PACKAGE + "ptql.ProcessQueryHelper";
private static final String GENERATION_PACKAGE =
SIGAR_PACKAGE + "ptql.GENERATED.";
private static final String[] GENERATION_IMPL =
new String[] { ProcessQuery.class.getName() };
public static final Class[] NOPARAM =
new Class[] {};
static final char MOD_CLONE = 'C';
static final char MOD_PARENT = 'P';
static final char MOD_VALUE = 'V';
private static final HashMap INUMOPS;
private static final HashMap LNUMOPS;
private static final HashMap STROPS;
private static final HashMap IFMETHODS;
private InstructionFactory factory;
private ConstantPoolGen pool;
private ClassGen generator;
private String className;
//ProcessQuery.match method impl
private MethodGen query;
//query instructions (match method body)
private InstructionList qi = new InstructionList();
//branches of query method
private ArrayList branches = new ArrayList();
public static final boolean COMPAT_1_4;
static {
//long
HashMap lnops = new HashMap();
lnops.put("eq", new Short(Constants.IFNE));
lnops.put("ne", new Short(Constants.IFEQ));
lnops.put("gt", new Short(Constants.IFGE));
lnops.put("ge", new Short(Constants.IFGT));
lnops.put("lt", new Short(Constants.IFLE));
lnops.put("le", new Short(Constants.IFLT));
LNUMOPS = lnops;
//int
HashMap inops = new HashMap();
inops.put("eq", new Short(Constants.IF_ICMPNE));
inops.put("ne", new Short(Constants.IF_ICMPEQ));
inops.put("gt", new Short(Constants.IF_ICMPGE));
inops.put("ge", new Short(Constants.IF_ICMPGT));
inops.put("lt", new Short(Constants.IF_ICMPLE));
inops.put("le", new Short(Constants.IF_ICMPLT));
INUMOPS = inops;
HashMap sops = new HashMap();
sops.put("ew", new StringOp("endsWith", Constants.IFEQ));
sops.put("sw", new StringOp("startsWith", Constants.IFEQ));
sops.put("eq", new StringOp("equals", Constants.IFEQ));
sops.put("ne", new StringOp("equals", Constants.IFNE));
sops.put("re", new StringOp("matches", Constants.IFEQ));
sops.put("ct", new StringOp("indexOf", Constants.IF_ICMPEQ));
STROPS = sops;
HashMap iftab = new HashMap();
Method[] methods = SigarProxy.class.getMethods();
for (int i=0; i<methods.length; i++) {
String name = methods[i].getName();
if (!name.startsWith("getProc")) {
continue;
}
Class[] params = methods[i].getParameterTypes();
//getProcFoo(long pid)
if (!((params.length == 1) &&
(params[0] == Long.TYPE)))
{
continue;
}
iftab.put(name.substring(7), methods[i]);
}
IFMETHODS = iftab;
boolean isCompat;
try {
Class.forName("java.net.SocketAddress");
isCompat = true;
} catch (ClassNotFoundException e) {
isCompat = false;
}
COMPAT_1_4 = isCompat;
}
public ProcessQueryBuilder() {
init();
}
public static Map getMethods() {
return IFMETHODS;
}
public static Set getMethodOpNames(Method method) {
if (method == null) {
return STROPS.keySet();
}
Class rtype = method.getReturnType();
if ((rtype == Character.TYPE) ||
(rtype == Double.TYPE) ||
(rtype == Integer.TYPE) ||
(rtype == Long.TYPE))
{
return LNUMOPS.keySet();
}
return STROPS.keySet();
}
public static boolean isSigarClass(Class type) {
return type.getName().startsWith(SIGAR_PACKAGE);
}
class QueryOp {
String op;
int flags;
boolean isParent = false;
boolean isClone = false;
boolean isValue = false;
public QueryOp(String val)
throws MalformedQueryException {
int i=0;
char c;
while (Character.isUpperCase((c = val.charAt(i)))) {
switch (c) {
case MOD_CLONE:
this.isClone = true;
break;
case MOD_PARENT:
this.isParent = true;
break;
case MOD_VALUE:
this.isValue = true;
break;
default:
String msg = "Unsupported modifier: " + c;
throw new MalformedQueryException(msg);
}
i++;
}
this.op = val.substring(i);
}
}
private void init() {
String name = genClassName();
this.className = GENERATION_PACKAGE + name;
this.generator =
new ClassGen(this.className,
"java.lang.Object",
className + ".java",
Constants.ACC_PUBLIC|Constants.ACC_SUPER,
GENERATION_IMPL);
this.pool = this.generator.getConstantPool();
this.factory = new InstructionFactory(this.generator,
this.pool);
createConstructor();
this.query =
new MethodGen(Constants.ACC_PUBLIC,
Type.BOOLEAN,
new Type[] { new ObjectType(PROXY_CLASS), Type.LONG },
new String[] { "sigar", "pid" }, "match", getClassName(),
this.qi, this.pool);
}
//arg 1 passed to ProcessQuery.match
private void loadSigarArg() {
this.qi.append(InstructionFactory.createLoad(Type.OBJECT, 1));
}
//arg 2 passed to ProcessQuery.match
private void loadPidArg() {
this.qi.append(InstructionFactory.createLoad(Type.LONG, 2));
}
private static synchronized String genClassName() {
return "PTQL" + generation++;
}
public String getClassName() {
return this.className;
}
private void createConstructor() {
InstructionList il = new InstructionList();
MethodGen method =
new MethodGen(Constants.ACC_PUBLIC,
Type.VOID, Type.NO_ARGS,
new String[] {}, "<init>",
getClassName(),
il, this.pool);
il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
il.append(this.factory.createInvoke("java.lang.Object",
"<init>",
Type.VOID, Type.NO_ARGS,
Constants.INVOKESPECIAL));
il.append(InstructionFactory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
this.generator.addMethod(method.getMethod());
il.dispose();
}
private void loadStandardArgs(QueryOp qop) {
if (qop.isParent) {
loadSigarArg();
}
loadSigarArg();
loadPidArg();
if (!qop.isParent) {
return;
}
//e.g. sigar.getProcState(pid).getName() is converted to:
// sigar.getProcState(sigar.getProcState(pid).getPpid()).getName()
final String procState = SIGAR_PACKAGE + "ProcState";
this.qi.append(this.factory.createInvoke(PROXY_CLASS,
"getProcState",
new ObjectType(procState),
new Type[] { Type.LONG },
Constants.INVOKEINTERFACE));
this.qi.append(this.factory.createInvoke(procState,
"getPpid",
Type.LONG, Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
}
//e.g. sigar.getProcState(pid).getName()
//attrClass == "State"
//attr == "Name"
//type == Type.STRING (return type)
private void createStandardInvoker(String attrClass, String attr, Type type) {
this.qi.append(this.factory.createInvoke(PROXY_CLASS,
"getProc" + attrClass,
new ObjectType(PROC_PREFIX + attrClass),
new Type[] { Type.LONG },
Constants.INVOKEINTERFACE));
this.qi.append(this.factory.createInvoke(PROC_PREFIX + attrClass,
"get" + attr,
type, Type.NO_ARGS,
Constants.INVOKEVIRTUAL));
}
private MalformedQueryException unsupportedOp(String name) {
return new MalformedQueryException("Unsupported operator: " +
name);
}
private MalformedQueryException unsupportedMethod(String name) {
return new MalformedQueryException("Unsupported method: " +
name);
}
private MalformedQueryException unsupportedAttribute(String name) {
return new MalformedQueryException("Unsupported attribute: " +
name);
}
private StringOp getStringOp(String op)
throws QueryLoadException,
MalformedQueryException {
StringOp sop = (StringOp)STROPS.get(op);
if (sop == null) {
throw unsupportedOp(op);
}
if (!COMPAT_1_4) {
if (op.equals("re")) {
throw new QueryLoadException(op + " requires jdk 1.4+");
}
}
return sop;
}
private void createStringInvoker(String op)
throws QueryLoadException,
MalformedQueryException {
StringOp sop = getStringOp(op);
this.qi.append(this.factory.createInvoke("java.lang.String", sop.name,
sop.returnType, new Type[] { sop.type },
Constants.INVOKEVIRTUAL));
if (op.equals("ct")) {
this.qi.append(new PUSH(this.pool, -1));
}
BranchInstruction branch =
InstructionFactory.createBranchInstruction(sop.opcode, null);
this.qi.append(branch);
this.branches.add(branch);
}
//special case
public void appendProcPortOp(String flags, String op, long val)
throws MalformedQueryException {
//XXX flags current unused; could be used to narrow search scope.
QueryOp qop = new QueryOp(op);
loadSigarArg();
this.qi.append(new PUSH(this.pool, val)); //port
this.qi.append(this.factory.createInvoke(PROXY_CLASS,
"getProcPort",
Type.LONG,
new Type[] { Type.LONG },
Constants.INVOKEINTERFACE));
loadPidArg();
this.qi.append(InstructionConstants.LCMP);
Short sop = (Short)LNUMOPS.get(qop.op);
if (sop == null) {
throw unsupportedOp(qop.op);
}
BranchInstruction branch =
InstructionFactory.createBranchInstruction(sop.shortValue(), null);
this.qi.append(branch);
this.branches.add(branch);
}
//special case
public void appendEnvOp(String key, String op, String val)
throws QueryLoadException,
MalformedQueryException {
QueryOp qop = new QueryOp(op);
loadStandardArgs(qop);
this.qi.append(new PUSH(this.pool, key));
this.qi.append(this.factory.createInvoke(PROXY_HELPER,
"getProcEnv", Type.STRING,
new Type[] {
new ObjectType(PROXY_CLASS),
Type.LONG, Type.STRING
},
Constants.INVOKESTATIC));
this.qi.append(new PUSH(this.pool, val));
createStringInvoker(qop.op);
}
//special case
public void appendArgsOp(int idx, String op, String val)
throws QueryLoadException,
MalformedQueryException {
QueryOp qop = new QueryOp(op);
loadStandardArgs(qop);
this.qi.append(new PUSH(this.pool, idx));
this.qi.append(this.factory.createInvoke(PROXY_HELPER,
"getProcArg", Type.STRING,
new Type[] {
new ObjectType(PROXY_CLASS),
Type.LONG, Type.INT
},
Constants.INVOKESTATIC));
this.qi.append(new PUSH(this.pool, val));
createStringInvoker(qop.op);
}
public void appendArgsMatch(String op, String val)
throws QueryLoadException,
MalformedQueryException {
QueryOp qop = new QueryOp(op);
getStringOp(qop.op); //validate
loadStandardArgs(qop);
this.qi.append(new PUSH(this.pool, val));
this.qi.append(new PUSH(this.pool, qop.op));
this.qi.append(this.factory.createInvoke(PROXY_HELPER,
"argsMatch", Type.BOOLEAN,
new Type[] {
new ObjectType(PROXY_CLASS),
Type.LONG,
Type.STRING,
Type.STRING
},
Constants.INVOKESTATIC));
BranchInstruction branch =
InstructionFactory.createBranchInstruction(Constants.IFEQ, null);
this.qi.append(branch);
this.branches.add(branch);
}
public void appendStringOp(String attrClass, String attr,
String op, String val)
throws QueryLoadException,
MalformedQueryException {
QueryOp qop = new QueryOp(op);
loadStandardArgs(qop);
createStandardInvoker(attrClass, attr, Type.STRING);
if (qop.isValue) {
return;
}
if (qop.isClone) {
append(val, null);
}
else {
this.qi.append(new PUSH(this.pool, val));
}
createStringInvoker(qop.op);
}
public void appendNumberOp(String attrClass, String attr,
String op, int val)
throws MalformedQueryException {
appendNumberOp(attrClass, attr, op, Type.INT,
0, 0.0, val);
}
public void appendNumberOp(String attrClass, String attr,
String op, long val)
throws MalformedQueryException {
appendNumberOp(attrClass, attr, op, Type.LONG,
val, 0.0, 0);
}
public void appendNumberOp(String attrClass, String attr,
String op, double val)
throws MalformedQueryException {
appendNumberOp(attrClass, attr, op, Type.DOUBLE,
0, val, 0);
}
private void appendNumberOp(String attrClass, String attr,
String op, Type type,
long val, double dval, int ival)
throws MalformedQueryException {
short opcode;
HashMap nops;
if ((type == Type.INT) ||
(type == Type.CHAR))
{
nops = INUMOPS;
this.qi.append(new PUSH(this.pool, ival));
}
else if (type == Type.DOUBLE) {
nops = LNUMOPS;
this.qi.append(new PUSH(this.pool, dval));
}
else {
nops = LNUMOPS;
this.qi.append(new PUSH(this.pool, val));
}
QueryOp qop = new QueryOp(op);
loadStandardArgs(qop);
createStandardInvoker(attrClass, attr, type);
Short sop = (Short)nops.get(qop.op);
if (sop == null) {
throw unsupportedOp(qop.op);
}
if (type == Type.LONG) {
this.qi.append(InstructionConstants.LCMP);
}
else if (type == Type.DOUBLE) {
this.qi.append(InstructionConstants.DCMPL);
}
BranchInstruction branch =
InstructionFactory.createBranchInstruction(sop.shortValue(), null);
this.qi.append(branch);
this.branches.add(branch);
}
private void appendPidOp(String op, String val)
throws MalformedQueryException {
long longVal;
short opcode;
HashMap nops = LNUMOPS;
if (val.equals("$$")) {
loadSigarArg();
this.qi.append(this.factory.createInvoke(PROXY_CLASS,
"getPid",
Type.LONG, Type.NO_ARGS,
Constants.INVOKEINTERFACE));
}
else {
try {
longVal = Long.parseLong(val);
} catch (NumberFormatException e) {
String msg = "Pid value '" + val + "' is not a number";
throw new MalformedQueryException(msg);
}
this.qi.append(new PUSH(this.pool, longVal));
}
loadPidArg();
QueryOp qop = new QueryOp(op);
Short sop = (Short)nops.get(qop.op);
if (sop == null) {
throw unsupportedOp(qop.op);
}
this.qi.append(InstructionConstants.LCMP);
BranchInstruction branch =
InstructionFactory.createBranchInstruction(sop.shortValue(), null);
this.qi.append(branch);
this.branches.add(branch);
}
public void append(String branch, String val)
throws QueryLoadException,
MalformedQueryException {
QueryBranch qb = new QueryBranch(branch);
String attrClass=qb.attrClass, attr=qb.attr, op=qb.op;
if (attrClass.equals("Env")) {
appendEnvOp(attr, op, val);
}
else if (attrClass.equals("Args")) {
if (attr.equals("*")) {
//run op against all args
appendArgsMatch(op, val);
}
else {
int idx;
try {
idx = Integer.parseInt(attr);
} catch (NumberFormatException e) {
String msg = "Array index '" + attr + "' is not a number";
throw new MalformedQueryException(msg);
}
appendArgsOp(idx, op, val);
}
}
else if (attrClass.equals("Port")) {
long port;
try {
port = Long.parseLong(val);
} catch (NumberFormatException e) {
String msg = "Port value '" + val + "' is not a number";
throw new MalformedQueryException(msg);
}
appendProcPortOp(attr, op, port);
}
else if (attrClass.equals("Pid")) {
appendPidOp(op, val);
}
else {
Method method = (Method)IFMETHODS.get(attrClass);
if (method == null) {
throw unsupportedMethod(attrClass);
}
Class subtype = method.getReturnType();
boolean isStringType = false;
if (isSigarClass(subtype)) {
try {
method = subtype.getMethod("get" + attr,
NOPARAM);
} catch (NoSuchMethodException e) {
throw unsupportedAttribute(attr);
}
if (method.getReturnType() == String.class) {
isStringType = true;
}
else if (method.getReturnType() == Character.TYPE) {
if (val.length() != 1) {
String msg = val + " is not a char";
throw new MalformedQueryException(msg);
}
int c = (int)val.charAt(0);
appendNumberOp(attrClass, attr, op, Type.CHAR,
0, 0.0, c);
return;
}
else if (method.getReturnType() == Double.TYPE) {
try {
double doubleVal = Double.parseDouble(val);
appendNumberOp(attrClass, attr, op, doubleVal);
return;
} catch (NumberFormatException e) {
String msg = val + " is not a double";
throw new MalformedQueryException(msg);
}
}
}
else {
isStringType = true;
}
if (!isStringType && Character.isDigit(val.charAt(0))) {
try {
long longVal = Long.parseLong(val);
appendNumberOp(attrClass, attr, op, longVal);
return;
} catch (NumberFormatException e) {
}
}
appendStringOp(attrClass, attr, op, val);
}
}
String addModifier(String key, char modifier)
throws MalformedQueryException {
int ix;
if ((ix = key.lastIndexOf(".")) < 0) {
throw new MalformedQueryException();
}
return key.substring(0, ix+1) + modifier +
key.substring(ix+1, key.length());
}
public void finish() {
this.qi.append(new PUSH(this.pool, 1));
BranchInstruction gotoBranch =
InstructionFactory.createBranchInstruction(Constants.GOTO, null);
this.qi.append(gotoBranch);
InstructionHandle target =
this.qi.append(new PUSH(this.pool, 0));
InstructionHandle retval =
this.qi.append(InstructionFactory.createReturn(Type.INT));
for (int i=0; i<this.branches.size(); i++) {
BranchInstruction branch =
(BranchInstruction)this.branches.get(i);
branch.setTarget(target);
}
gotoBranch.setTarget(retval);
this.query.setMaxStack();
this.query.setMaxLocals();
this.generator.addMethod(this.query.getMethod());
this.qi.dispose();
}
public ProcessQuery load()
throws QueryLoadException {
if (dumpClasses) {
try {
FileOutputStream os =
new FileOutputStream(getClassName() + ".class");
dump(os);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
byte[] bytecode = this.generator.getJavaClass().getBytes();
ClassLoader parent = ClassLoader.getSystemClassLoader();
ClassLoader cl = new ProcessQueryClassLoader(parent, bytecode);
Class genclass;
try {
genclass = cl.loadClass(getClassName());
} catch (ClassNotFoundException e) {
throw new QueryLoadException("ClassNotFoundException: " +
e.getMessage());
}
try {
return (ProcessQuery)genclass.newInstance();
} catch (InstantiationException e) {
throw new QueryLoadException("InstantiationException: " +
e.getMessage());
} catch (IllegalAccessException e) {
throw new QueryLoadException("IllegalAccessException: " +
e.getMessage());
}
}
public void dump(OutputStream os) throws IOException {
this.generator.getJavaClass().dump(os);
}
}

View File

@ -0,0 +1,18 @@
package net.hyperic.sigar.ptql;
class ProcessQueryClassLoader extends ClassLoader {
private byte[] bytecode;
ProcessQueryClassLoader(ClassLoader parent, byte[] bytecode) {
super(parent);
this.bytecode = bytecode;
}
public Class findClass(String name) throws ClassNotFoundException {
try {
return defineClass(name, this.bytecode, 0, this.bytecode.length);
} catch (ClassFormatError e) {
throw new ClassNotFoundException("Class Format Error", e);
}
}
}

View File

@ -0,0 +1,172 @@
package net.hyperic.sigar.ptql;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.StringTokenizer;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.util.ReferenceMap;
public class ProcessQueryFactory implements Comparator {
private static Map cache =
ReferenceMap.synchronizedMap();
private SigarProxy sigar = null;
public ProcessQueryFactory() {}
public ProcessQueryFactory(SigarProxy sigar) {
this.sigar = sigar;
}
//sort what will become instruction branches.
//so the cheapest are executed first.
private int getOrder(String s) {
if (s.startsWith("Port.")) {
return 11;
}
else if (s.startsWith("Env.")) {
return 10;
}
else if (s.startsWith("Args.")) {
return 9;
}
else if (s.startsWith("Exe.")) {
return 8;
}
else if (s.startsWith("State.")) {
return 7;
}
return 1;
}
public int compare(Object o1, Object o2) {
return getOrder((String)o1) -
getOrder((String)o2);
}
public ProcessQuery prepare(QueryBranchMap map)
throws MalformedQueryException,
QueryLoadException {
ProcessQueryBuilder builder = new ProcessQueryBuilder();
String[] keys =
(String[])map.keySet().toArray(new String[0]);
Arrays.sort(keys, this);
for (int i=0; i<keys.length; i++) {
String key = keys[i];
String val = (String)map.get(key);
if (val.charAt(0) == '$') {
String var = val.substring(1);
try {
int ix = Integer.parseInt(var);
//$1..n references
ix--;
if ((ix < 0) || (ix >= map.branches.size())) {
String msg = "Variable out of range " + var;
throw new MalformedQueryException(msg);
}
var = (String)map.branches.get(ix);
var = builder.addModifier(var,
ProcessQueryBuilder.MOD_VALUE);
key = builder.addModifier(key,
ProcessQueryBuilder.MOD_CLONE);
} catch (NumberFormatException e) {
var = System.getProperty(var, val);
}
val = var;
}
builder.append(key, val);
}
builder.finish();
return builder.load();
}
private static ProcessQuery getPidInstance(String query)
throws MalformedQueryException {
if (query.indexOf(",") > 0) {
throw new MalformedQueryException("Invalid Pid query");
}
String[] vals = QueryBranch.split(query);
QueryBranch branch = new QueryBranch(vals[0]);
String val = vals[1];
if (!branch.op.equals("eq")) {
throw new MalformedQueryException("Invalid Pid operator");
}
if (branch.attr.equals("PidFile")) {
return new PidFileQuery(val);
}
throw new MalformedQueryException("Unsupported method: " +
branch.attr);
}
public static ProcessQuery getInstance(String query)
throws MalformedQueryException,
QueryLoadException {
return getInstance(query, null);
}
public static ProcessQuery getInstance(String query, SigarProxy sigar)
throws MalformedQueryException,
QueryLoadException {
if (query == null) {
throw new MalformedQueryException("null query");
}
if (query.length() == 0) {
throw new MalformedQueryException("empty query");
}
ProcessQuery pQuery = (ProcessQuery)cache.get(query);
if (pQuery != null) {
return pQuery;
}
if (query.startsWith("Pid.PidFile.")) {
pQuery = getPidInstance(query);
cache.put(query, pQuery);
return pQuery;
}
QueryBranchMap queries = new QueryBranchMap();
StringTokenizer st = new StringTokenizer(query, ",");
while (st.hasMoreTokens()) {
String[] vals = QueryBranch.split(st.nextToken());
queries.put(vals[0], vals[1]);
}
ProcessQueryFactory factory = new ProcessQueryFactory(sigar);
pQuery = factory.prepare(queries);
cache.put(query, pQuery);
return pQuery;
}
}

View File

@ -0,0 +1,67 @@
package net.hyperic.sigar.ptql;
import net.hyperic.sigar.ProcCred;
import net.hyperic.sigar.ProcState;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarProxy;
import net.hyperic.sigar.SigarProxyCache;
public class ProcessQueryGenerator {
private ProcessFinder finder;
private SigarProxy sigar;
public ProcessQueryGenerator(SigarProxy sigar) {
this.sigar = sigar;
this.finder = new ProcessFinder(sigar);
}
public String generate(long pid)
throws SigarException {
StringBuffer query = new StringBuffer();
ProcState state = sigar.getProcState(pid);
query.append("State.Name.eq=" + state.getName());
if (this.finder.find(query).length == 1) {
return query.toString();
}
try {
ProcCred cred = sigar.getProcCred(pid);
query.append(",").append("Cred.Uid.eq=" + cred.getUid());
query.append(",").append("Cred.Gid.eq=" + cred.getGid());
if (this.finder.find(query).length == 1) {
return query.toString();
}
} catch (SigarException e) {
}
try {
String[] args = sigar.getProcArgs(pid);
for (int i=args.length-1; i>=0; i--) {
int j;
//common case for java apps, last arg is the classname
//use -1 for query since number of args may change,
//but last arg is always the classname.
if (i == args.length-1) {
j = -1;
}
else {
j = i;
}
query.append(",").append("Args." + j + ".eq=" + args[i]);
if (this.finder.find(query).length == 1) {
return query.toString();
}
}
} catch (SigarException e) {
}
return null;
}
}

View File

@ -0,0 +1,132 @@
package net.hyperic.sigar.ptql;
import java.util.Map;
import java.util.HashMap;
import net.hyperic.sigar.SigarException;
import net.hyperic.sigar.SigarNotImplementedException;
import net.hyperic.sigar.SigarProxy;
public class ProcessQueryHelper {
static HashMap stringMatchers = new HashMap();
static {
stringMatchers.put("eq", new StringEqMatcher());
stringMatchers.put("ne", new StringNeMatcher());
stringMatchers.put("sw", new StringSwMatcher());
stringMatchers.put("ew", new StringEwMatcher());
//stringMatchers.put("re", new StringReMatcher());
stringMatchers.put("ct", new StringCtMatcher());
}
//avoid NPE if key does not exist.
public static String getProcEnv(SigarProxy proxy, long pid, String key)
throws SigarException, SigarNotImplementedException {
Map vars;
try {
vars = proxy.getProcEnv(pid);
} catch (SigarNotImplementedException e) {
throw e;
} catch (SigarException e) {
return "";
}
String val = (String)vars.get(key);
if (val == null) {
return "";
}
return val;
}
//avoid ArrayOutOfBoundsException
public static String getProcArg(SigarProxy proxy, long pid, int num)
throws SigarException, SigarNotImplementedException {
String[] args;
try {
args = proxy.getProcArgs(pid);
} catch (SigarNotImplementedException e) {
throw e;
} catch (SigarException e) {
return "";
}
//e.g. find last element of args: Args.-1.eq=weblogic.Server
if (num < 0) {
num += args.length;
}
if ((num >= args.length) ||
(num < 0)) {
return "";
}
return args[num];
}
public interface StringMatcher {
public boolean match(String left, String right);
}
static class StringEqMatcher implements StringMatcher {
public boolean match(String left, String right) {
return left.equals(right);
}
}
static class StringNeMatcher implements StringMatcher {
public boolean match(String left, String right) {
return !left.equals(right);
}
}
static class StringEwMatcher implements StringMatcher {
public boolean match(String left, String right) {
return left.endsWith(right);
}
}
static class StringSwMatcher implements StringMatcher {
public boolean match(String left, String right) {
return left.startsWith(right);
}
}
static class StringCtMatcher implements StringMatcher {
public boolean match(String left, String right) {
return left.indexOf(right) != -1;
}
}
//XXX requires jdk 1.4+ to compile
/*
static class StringReMatcher implements StringMatcher {
public boolean match(String left, String right) {
return left.matches(right);
}
}
*/
public static boolean argsMatch(SigarProxy proxy, long pid,
String value, String op)
throws SigarException, SigarNotImplementedException {
String[] args = proxy.getProcArgs(pid);
StringMatcher matcher =
(StringMatcher)stringMatchers.get(op);
for (int i=0; i<args.length; i++) {
if (matcher.match(value, args[i])) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,51 @@
package net.hyperic.sigar.ptql;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
class QueryBranch {
String attrClass;
String attr;
String op;
QueryBranch(String query)
throws MalformedQueryException {
StringTokenizer st = new StringTokenizer(query, ".");
try {
this.attrClass = st.nextToken();
} catch (NoSuchElementException e) {
throw new MalformedQueryException("Empty query");
}
try {
this.attr = st.nextToken();
} catch (NoSuchElementException e) {
throw new MalformedQueryException("Missing attribute");
}
try {
this.op = st.nextToken();
} catch (NoSuchElementException e) {
throw new MalformedQueryException("Missing operator");
}
}
static String[] split(String query)
throws MalformedQueryException {
String[] vals = new String[2];
int ix = query.indexOf('=');
if (ix < 0) {
throw new MalformedQueryException("Missing '='");
}
vals[0] = query.substring(0, ix);
vals[1] = query.substring(ix+1, query.length());
return vals;
}
}

View File

@ -0,0 +1,14 @@
package net.hyperic.sigar.ptql;
import java.util.ArrayList;
import java.util.HashMap;
public class QueryBranchMap extends HashMap {
ArrayList branches = new ArrayList();
public Object put(Object key, Object value) {
branches.add(key);
return super.put(key, value);
}
}

View File

@ -0,0 +1,15 @@
package net.hyperic.sigar.ptql;
/**
* Exception for process queries which were
* parsed ok but whos class generation failed.
*/
public class QueryLoadException extends Exception {
public QueryLoadException() {
}
public QueryLoadException(String message) {
super(message);
}
}

View File

@ -0,0 +1,21 @@
package net.hyperic.sigar.ptql;
import org.apache.bcel.generic.Type;
class StringOp {
String name;
short opcode;
Type type = Type.STRING;
Type returnType = Type.BOOLEAN;
StringOp(String name, short opcode) {
this.name = name;
this.opcode = opcode;
if (name.equals("equals")) {
this.type = Type.OBJECT;
}
else if (name.equals("indexOf")) {
this.returnType = Type.INT;
}
}
}

View File

@ -0,0 +1,133 @@
package net.hyperic.sigar.shell;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import net.hyperic.sigar.util.GetlineCompleter;
/**
* GetlineCompleter implementation looks for possible completions
* using an Iterator.
*/
public class CollectionCompleter
implements GetlineCompleter {
private ArrayList completions = new ArrayList();
private ShellBase shell = null;
private PrintStream out = System.out;
private Collection collection;
public CollectionCompleter() { }
public CollectionCompleter(ShellBase shell) {
this.shell = shell;
this.out = shell.getOutStream();
}
public CollectionCompleter(ShellBase shell, Collection collection) {
this(shell);
setCollection(collection);
}
public Iterator getIterator() {
return getCollection().iterator();
}
public Collection getCollection() {
return this.collection;
}
public void setCollection(Collection collection) {
this.collection = collection;
}
private boolean startsWith(String substr, String[] possible) {
for (int i=0; i<possible.length; i++) {
if (!possible[i].startsWith(substr)) {
return false;
}
}
return true;
}
public String getPartialCompletion(String[] possible) {
if (possible.length == 0) {
return "";
}
String match = possible[0];
StringBuffer lcd = new StringBuffer();
for (int i=0; i<match.length(); i++) {
if (startsWith(match.substring(0, i + 1), possible)) {
lcd.append(match.charAt(i));
}
else {
break;
}
}
return lcd.toString();
}
public String displayPossible(List possible) {
return displayPossible((String[])possible.
toArray(new String[possible.size()]));
}
public String displayPossible(String[] possible) {
int size = possible.length;
//print possibilities
//XXX page possibilities
String partial = getPartialCompletion(possible);
for (int i=0; i<size; i++) {
String match = possible[i];
this.out.println();
this.out.print(match + " ");
}
if (this.shell != null) {
this.shell.getGetline().redraw();
}
if (partial.length() > 0) {
return partial;
}
return null;
}
public String complete(String line) {
this.completions.clear();
int len = line.length();
for (Iterator it = getIterator();
it.hasNext(); )
{
String name = (String)it.next();
if ((len == 0) || name.startsWith(line)) {
this.completions.add(name);
}
}
int size = this.completions.size();
switch (size) {
case 0:
return line;
case 1:
return (String)this.completions.get(0);
default:
String partial = displayPossible(this.completions);
if (partial != null) {
return partial;
}
return line;
}
}
}

View File

@ -0,0 +1,140 @@
package net.hyperic.sigar.shell;
import java.io.File;
import java.io.FilenameFilter;
import java.util.List;
import java.util.Iterator;
import net.hyperic.sigar.SigarLoader;
public class FileCompleter
extends CollectionCompleter
implements FilenameFilter {
private static final String HOME =
System.getProperty("user.home");
private String name;
public FileCompleter() {
super();
}
public FileCompleter(ShellBase shell) {
super(shell);
}
public static String expand(String name) {
if (name.startsWith("~")) {
return HOME + name.substring(1, name.length());
}
return name;
}
public boolean accept(File dir, String name) {
if (name.equals(".") || name.equals("..")) {
return false;
}
return name.startsWith(this.name);
}
public Iterator getIterator() {
return null; //unused
}
private String appendSep(String name) {
if (name.endsWith(File.separator)) {
return name;
}
return name + File.separator;
}
//e.g. we don't want "~/." treated as a directory
//but we do want "." to be.
private boolean isDotFile(File file) {
return
file.getName().equals(".") &&
(file.getParentFile() != null);
}
public String complete(String line) {
String fileName = line;
boolean isHome = false;
if (line.length() == 0) {
return appendSep(".");
}
else if (fileName.startsWith("~")) {
isHome = true;
fileName = expand(fileName);
}
File file = new File(fileName);
File dir;
if (file.exists() && !isDotFile(file)) {
if (file.isDirectory()) {
this.name = null;
dir = file;
if (!fileName.endsWith(File.separator)) {
return line + File.separator;
}
}
else {
return line;
}
}
else {
this.name = file.getName();
dir = file.getParentFile();
if (dir == null) {
if (SigarLoader.IS_WIN32 &&
(line.length() == 1) &&
Character.isLetter(line.charAt(0)))
{
//e.g. C:\
return line + ":\\";
}
return line;
}
if (!(dir.exists() && dir.isDirectory())) {
return line;
}
}
String[] list;
if (this.name == null) {
list = dir.list();
}
else {
list = dir.list(this);
}
if (list.length == 1) {
fileName = appendSep(dir.toString()) + list[0];
if (new File(fileName).isDirectory()) {
fileName = appendSep(fileName);
}
if (isHome) {
return "~" + fileName.substring(HOME.length(),
fileName.length());
}
return fileName;
}
String partial = displayPossible(list);
if (partial != null) {
return appendSep(dir.toString()) + partial;
}
return line;
}
public static void main(String[] args) throws Exception {
String line = new FileCompleter().complete(args[0]);
System.out.println("\nsigar> '" + line + "'");
}
}

View File

@ -0,0 +1,124 @@
package net.hyperic.sigar.shell;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.hyperic.sigar.util.PrintfFormat;
public class MultiwordShellCommand extends ShellCommandBase {
private Map itsSubHandlerMap = new HashMap();
public ShellCommandHandler getSubHandler(String subName) {
return (ShellCommandHandler)itsSubHandlerMap.get(subName);
}
public Set getHandlerNames() {
return this.itsSubHandlerMap.keySet();
}
public void registerSubHandler(String subName,
ShellCommandHandler handler)
throws ShellCommandInitException {
if (!itsSubHandlerMap.containsValue(handler)) {
// Only init the handler if it has not been added yet.
// We do this because a single handler could be
// registered for multiple subName's (as in the case
// of aliasing).
handler.init(getCommandName() + " " + subName, getShell());
}
itsSubHandlerMap.put(subName, handler);
}
public void processCommand(String[] args)
throws ShellCommandUsageException, ShellCommandExecException
{
String cmdName = getCommandName();
ShellCommandHandler handler;
String[] subArgs;
if (args.length < 1) {
throw new ShellCommandUsageException(cmdName + " command " +
"requires an argument.");
}
handler = (ShellCommandHandler)
itsSubHandlerMap.get(args[0].toLowerCase());
if (handler == null) {
throw new ShellCommandUsageException("don't know how to " +
cmdName + " " + args[0]);
}
subArgs = new String[args.length - 1];
System.arraycopy(args, 1, subArgs, 0, subArgs.length);
handler.processCommand(subArgs);
}
public String getSyntaxArgs() {
StringBuffer res = new StringBuffer();
res.append("<");
for (Iterator i=this.getHandlerNames().iterator(); i.hasNext();) {
res.append((String)i.next());
if (i.hasNext()) {
res.append(" | ");
}
}
res.append(">");
return res.toString();
}
public String getUsageHelp(String[] args) {
ShellCommandHandler handler;
String[] subArgs;
if (args.length == 0) {
StringBuffer res = new StringBuffer();
Object[] fArgs = new Object[2];
PrintfFormat fmt;
String fmtStr;
int maxLen;
res.append(" " + this.getUsageShort());
res.append(".\n For further help on each subcommand, ");
res.append("type 'help ");
res.append(this.getCommandName() + " <subcommand>'\n\n");
maxLen = 0;
for (Iterator i=this.getHandlerNames().iterator(); i.hasNext();) {
String cmdName = (String)i.next();
if (cmdName.length() > maxLen)
maxLen = cmdName.length();
}
fmtStr = " %-" + (maxLen + 1) + "s %s";
fmt = new PrintfFormat(fmtStr);
for (Iterator i=this.getHandlerNames().iterator(); i.hasNext();) {
String cmdName = (String)i.next();
ShellCommandHandler sub = this.getSubHandler(cmdName);
fArgs[0] = cmdName + ":";
fArgs[1] = sub.getUsageShort();
res.append(fmt.sprintf(fArgs));
if (i.hasNext())
res.append("\n");
}
return res.toString();
}
if ((handler = getSubHandler(args[0].toLowerCase())) == null) {
return null;
}
subArgs = new String[args.length - 1];
System.arraycopy(args, 1, subArgs, 0, subArgs.length);
return handler.getUsageHelp(subArgs);
}
}

View File

@ -0,0 +1,9 @@
package net.hyperic.sigar.shell;
/**
* This exception is thrown when a command wants to exit the
* shell completely. Typically this is only done for quit commands.
*/
public class NormalQuitCommandException extends RuntimeException {
}

View File

@ -0,0 +1,6 @@
package net.hyperic.sigar.shell;
public interface SIGINT {
public void handleSIGINT();
}

View File

@ -0,0 +1,716 @@
package net.hyperic.sigar.shell;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import net.hyperic.sigar.Sigar;
import net.hyperic.sigar.util.Getline;
import net.hyperic.sigar.util.GetlineCompleter;
import net.hyperic.sigar.util.IteratorIterator;
import net.hyperic.sigar.pager.PageControl;
import net.hyperic.sigar.pager.PageFetchException;
import net.hyperic.sigar.pager.PageFetcher;
import net.hyperic.sigar.pager.PageList;
public abstract class ShellBase
implements ShellCommandMapper, GetlineCompleter, SIGINT {
// Default size for pages when doing list commands
public static final String PROP_PAGE_SIZE = "page.size";
private static final int DEFAULT_PAGE_SIZE = 20;
private String name = null;
private String prompt = null;
private Map handlers = null;
private HashMap hiddenCommands;
protected Getline gl;
protected PrintStream out = System.out;
protected PrintStream err = System.err;
private boolean doHistoryAdd;
private int pageSize;
private boolean isRedirected;
private GetlineCompleter completer;
public void handleSIGINT() {
this.gl.reset();
}
public void initHistory() throws IOException {
String historyFileName =
"." + this.name + "_history";
initHistory(new File(System.getProperty("user.home"),
historyFileName));
}
public void initHistory(File file) throws IOException {
this.doHistoryAdd = true;
this.gl.initHistoryFile(file);
}
public void registerSigIntHandler() {
ShellIntHandler.register(this); //catch ctrl-c
}
public void init (String applicationName,
PrintStream out,
PrintStream err) {
this.name = applicationName;
this.prompt = applicationName;
this.gl = new Getline();
this.out = out;
this.err = err;
this.doHistoryAdd = false;
this.pageSize = Integer.getInteger(PROP_PAGE_SIZE,
DEFAULT_PAGE_SIZE).intValue();
if (this.pageSize != -1) {
this.pageSize -= 1;
if (this.pageSize < 1) {
this.pageSize = 1;
}
}
this.isRedirected = false;
// Create command handler registry
this.handlers = new HashMap();
hiddenCommands = new HashMap();
// Register help and quit commands
try {
ShellCommand_quit quitCommand = new ShellCommand_quit();
ShellCommand_source sourceCommand = new ShellCommand_source();
registerCommandHandler(".", sourceCommand);
registerCommandHandler("alias", new ShellCommand_alias());
registerCommandHandler("exit", quitCommand);
registerCommandHandler("get", new ShellCommand_get());
registerCommandHandler("help", new ShellCommand_help());
registerCommandHandler("q", quitCommand);
registerCommandHandler("quit", quitCommand);
registerCommandHandler("set", new ShellCommand_set());
registerCommandHandler("source", sourceCommand);
registerCommandHandler("sleep", new ShellCommand_sleep());
} catch (Exception e) {
err.println("ERROR: could not register standard commands: " + e);
e.printStackTrace(err);
}
//DWIM commands
setHandlerHidden(".", true);
setHandlerHidden("q", true);
setHandlerHidden("exit", true);
registerSigIntHandler();
this.completer = new CollectionCompleter(this) {
public Iterator getIterator() {
IteratorIterator it = new IteratorIterator();
it.add(getCommandNameIterator());
it.add(ShellCommand_alias.getAliases());
return it;
}
};
}
/**
* Read a .rc file into the shell, invoking everything in it (without
* saving the actions to history)
*
* @param rcFile File to read
*/
public void readRCFile(File rcFile, boolean echoCommands)
throws IOException
{
FileInputStream is = null;
boolean oldHistAdd = this.doHistoryAdd;
this.doHistoryAdd = false;
try {
BufferedReader in;
String line = null;
is = new FileInputStream(rcFile);
in = new BufferedReader(new InputStreamReader(is));
while ((line = in.readLine()) != null) {
line = line.trim();
if (line.startsWith("#") || (line.length() == 0)) {
continue;
}
if (echoCommands) {
this.err.println(line);
}
handleCommand(line);
}
} finally {
if (is != null) {
is.close();
}
this.doHistoryAdd = oldHistAdd;
}
}
/**
* Change the prompt
* @param prompt
*/
public void setPrompt(String prompt) {
this.prompt = prompt;
}
/**
* Register a new command handler.
* @param commandName The command that this handler will process.
* @param handler The handler to register.
*/
public void registerCommandHandler(String commandName,
ShellCommandHandler handler)
throws ShellCommandInitException {
this.handlers.put(commandName, handler);
handler.init(commandName, this);
}
/**
* If a command needs additional input via the console, they
* can get it this way.
* @param prompt The prompt to display.
* @return The data that the user typed in.
*/
public String getInput(String prompt) throws EOFException, IOException {
return this.gl.getLine(prompt);
}
/**
* If a command needs additional input via the console, they
* can get it this way.
* @param prompt The prompt to display.
* @param addToHistory If true, the input entered will be added to the
* history file.
* @return The data that the user typed in.
*/
public String getInput(String prompt, boolean addToHistory)
throws EOFException, IOException {
return this.gl.getLine(prompt, addToHistory);
}
/**
* If a command needs additional input via the console, they
* can get it this way. The characters that the user types
* are not echoed.
* @param prompt The prompt to display.
* @return The data that the user typed in.
*/
public String getHiddenInput(String prompt)
throws EOFException, IOException
{
return Sigar.getPassword(prompt);
}
/**
* Write a string to this shell's output stream.
* @param s The string to write to the output stream.
*/
public void sendToOutStream(String s) {
out.println(s);
}
/**
* Write a string to this shell's output stream.
* @param s The string to write to the output stream.
*/
public void sendToErrStream(String s) {
err.println(s);
}
public void run() {
String input = null;
ShellIntHandler.push(this);
while (true) {
try {
// We don't add it to the history until we know
// that it is not an illegal command
input = this.gl.getLine(this.prompt + "> ", false);
} catch (EOFException e) {
break;
} catch (Exception e) {
err.println("Fatal error reading input line: " + e);
e.printStackTrace(err);
return;
}
if (input == null || input.trim().length() == 0) {
continue;
}
try {
handleCommand(input);
} catch (NormalQuitCommandException nqce) {
break;
}
}
out.println("Goodbye.");
}
public void handleCommand(String line) {
String[] args;
try {
args = explodeQuoted(line);
} catch(IllegalArgumentException exc) {
this.out.println("Syntax error: Unbalanced quotes");
return;
}
if (args.length != 0) {
handleCommand(line, args);
}
}
public void handleCommand(String line, String[] args) {
ShellCommandHandler handler = null;
PrintStream oldSysOut = null, oldOut = null;
String command = args[0];
String[] subArgs;
int useArgs;
if (args.length == 0) {
return;
}
handler = getHandler(command);
if (handler == null) {
String[] aliasArgs = ShellCommand_alias.getAlias(command);
if (aliasArgs == null) {
err.println("unknown command: " + command);
return;
}
handleCommand(line, aliasArgs);
return;
}
useArgs = args.length;
if (args.length > 2 && args[args.length - 2].equals(">")) {
PrintStream newOut;
oldSysOut = System.out;
oldOut = this.out;
// Re-direction, baby
try {
FileOutputStream fOut;
fOut = new FileOutputStream(args[args.length -1]);
newOut = new PrintStream(fOut);
} catch(IOException exc) {
this.err.println("Failed to redirect to output file: " + exc);
return;
}
this.isRedirected = true;
this.out = newOut;
System.setOut(newOut);
useArgs = useArgs - 2;
}
subArgs = new String[useArgs - 1];
System.arraycopy(args, 1, subArgs, 0, subArgs.length);
try {
processCommand(handler, subArgs);
} catch (ShellCommandUsageException e) {
String msg = e.getMessage();
if (msg == null || msg.trim().length() == 0) {
msg = "an unknown error occurred";
}
err.println(command + ": " + msg);
} catch (ShellCommandExecException e) {
err.println(e.getMessage());
} catch (NormalQuitCommandException e) {
throw e;
} catch (Exception e) {
err.println("Unexpected exception processing "
+ "command '" + command + "': " + e);
e.printStackTrace(err);
} finally {
if (this.doHistoryAdd) {
this.gl.addToHistory(line);
}
if (oldSysOut != null) {
this.isRedirected = false;
System.setOut(oldSysOut);
this.out = oldOut;
}
}
}
public void processCommand(ShellCommandHandler handler, String args[])
throws ShellCommandUsageException, ShellCommandExecException
{
handler.processCommand(args);
}
public PrintStream getOutStream() {
return this.out;
}
public PrintStream getErrStream() {
return this.err;
}
public Getline getGetline() {
return this.gl;
}
public boolean hasCompleter(ShellCommandHandler handler) {
return GetlineCompleter.class.isAssignableFrom(handler.getClass());
}
public String complete(ShellCommandHandler handler, String line) {
if (hasCompleter(handler)) {
return ((GetlineCompleter)handler).complete(line);
}
return line;
}
public String complete(String line) {
if (line == null) {
return null;
}
int ix = line.indexOf(" ");
if (ix != -1) {
//if the command name has been completed
//hand off completion of the rest to the command handler
//if it implements GetlineHandler
String cmd = line.substring(0, ix);
String sub = line.substring(ix+1, line.length());
ShellCommandHandler handler = getHandler(cmd);
if (handler != null) {
String hline = complete(handler, sub);
return cmd + " " + hline;
}
return line;
}
line = this.completer.complete(line);
if (getHandler(line) != null) {
return line + " ";
}
return line;
}
/**
* @see ShellCommandMapper#getHandler
*/
public ShellCommandHandler getHandler(String command) {
if (command == null) {
return null;
}
return
(ShellCommandHandler)this.handlers.get(command.toLowerCase());
}
public void setHandlerHidden(String handlerName, boolean isHidden) {
if (getHandler(handlerName) == null) {
throw new IllegalArgumentException("Unknown handler: " +
handlerName);
}
this.hiddenCommands.put(handlerName,
isHidden ? Boolean.TRUE : Boolean.FALSE);
}
public boolean handlerIsHidden(String handlerName) {
return this.hiddenCommands.get(handlerName) != null;
}
/**
* @see ShellCommandMapper#getCommandNameIterator
*/
public Iterator getCommandNameIterator() {
ArrayList keyArray = new ArrayList();
String[] keys;
for (Iterator i = this.handlers.keySet().iterator();
i.hasNext();)
{
String keyName = (String)i.next();
if (!handlerIsHidden(keyName)) {
keyArray.add(keyName);
}
}
keys = (String[])keyArray.toArray(new String[0]);
Arrays.sort(keys);
return Arrays.asList(keys).iterator();
}
public void shutdown() {
}
/**
* Check to see if the currently running shell command is being
* redirected to a file.
*
* @return true if the shell is redirecting to a file, else false
*/
public boolean isRedirected() {
return this.isRedirected;
}
/**
* Set the page size for data paging.
*
* @param size Number of rows to include in a page of data -- if
* 0, then unlimited rows will be used.
*/
public void setPageSize(int size) {
if (size == 0 || size < -1) {
throw new IllegalArgumentException("Page size must be > 0 or -1");
}
this.pageSize = size;
}
/**
* Get the current page size used when paging data.
*
* @return the # of rows in the current page size.
*/
public int getPageSize() {
return this.pageSize;
}
/**
* Get the number of pages that the fetcher can fetch, given the
* settings as specified by the control and the # of total entites
* the fetcher can fetch
*
* @param control Control which dictates the page size
* @param list Last pageList queried via the control
*/
private int getNumPages(PageControl control, PageList list) {
int pageSize = control.getPagesize();
int totalElems;
totalElems = list.getTotalSize();
if (pageSize == PageControl.SIZE_UNLIMITED) {
return 1;
}
else if (pageSize == 0) {
return 0;
}
if ((totalElems % pageSize) == 0) {
return totalElems / pageSize;
}
return (totalElems / pageSize) + 1;
}
/**
* Print a page of data
*
* @param out Stream to print to
* @param data List containing the data to print
* @param lineNo Line number of the first element of data
* @param printLineNumbers If true, prefix lines with their numbers
*
* @return the number of lines printed
*/
private void printPage(PrintStream out, PageList data, int lineNo,
boolean printLineNumbers)
{
for (Iterator i=data.iterator(); i.hasNext(); ) {
if (printLineNumbers) {
out.print(lineNo++ + ": ");
}
out.println((String)i.next());
}
}
public PageControl getDefaultPageControl() {
PageControl res;
res = new PageControl(0, getPageSize() == -1 ?
PageControl.SIZE_UNLIMITED :
getPageSize());
return res;
}
public void performPaging(PageFetcher fetcher)
throws PageFetchException
{
performPaging(fetcher, getDefaultPageControl());
}
public void performPaging(PageFetcher fetcher, PageControl control)
throws PageFetchException
{
PrintStream out;
PageControl curPage;
PageList data;
boolean lineNumberMode;
// Don't know how to handle this case
if (control.getPagesize() == 0) {
return;
}
lineNumberMode = false;
out = getOutStream();
if (isRedirected()) {
control.setPagesize(PageControl.SIZE_UNLIMITED);
}
data = fetcher.getPage((PageControl)control.clone());
printPage(out, data, control.getPageEntityIndex() + 1,
lineNumberMode);
if (control.getPagesize() == PageControl.SIZE_UNLIMITED ||
data.size() < control.getPagesize())
{
return;
}
while (true) {
boolean printPage = false;
String cmd;
int totalPages;
totalPages = getNumPages(control, data);
try {
cmd = getInput("--More-- (Page " +
(control.getPagenum() + 1) + " of " +
totalPages + ")", false);
} catch(IOException exc) {
out.println();
break;
}
if (cmd == null || (cmd = cmd.trim()).length() == 0) {
printPage = true;
control.setPagenum(control.getPagenum() + 1);
}
else if (cmd.equals("q")) {
break;
}
else if (cmd.equals("b")) {
printPage = true;
if (control.getPagenum() > 0) {
control.setPagenum(control.getPagenum() - 1);
}
}
else if (cmd.equals("l")) {
lineNumberMode = !lineNumberMode;
printPage = true;
}
else if (cmd.equals("?")) {
out.println(" 'b' - Scroll back one page");
out.println(" 'l' - Toggle line number mode");
out.println(" 'q' - Quit paging");
out.println(" '<number>' - Jump to the specified page #");
out.println(" '<enter>' - Scroll forward one page");
}
else {
int newPageNo;
try {
newPageNo = Integer.parseInt(cmd);
} catch(NumberFormatException exc) {
out.println("Unknown command '" + cmd + "' " +
" type '?' for paging help");
continue;
}
if (newPageNo < 1 || newPageNo > totalPages) {
out.println(newPageNo + " out of range (must be " +
"1 to " + totalPages + ")");
}
else {
control.setPagenum(newPageNo - 1);
printPage = true;
}
}
if (printPage) {
data = fetcher.getPage((PageControl)control.clone());
printPage(out, data, control.getPageEntityIndex() + 1,
lineNumberMode);
// Check to see if we printed the last of the data
if (data.size() < control.getPagesize()) {
break;
}
}
}
}
private static String[] explodeQuoted(String arg) {
ArrayList res = new ArrayList();
StringTokenizer quoteTok;
boolean inQuote = false;
arg = arg.trim();
quoteTok = new StringTokenizer(arg, "\"", true);
while (quoteTok.hasMoreTokens()) {
String elem = (String)quoteTok.nextElement();
if (elem.equals("\"")) {
inQuote = !inQuote;
continue;
}
if (inQuote) {
res.add(elem);
}
else {
StringTokenizer spaceTok = new StringTokenizer(elem.trim());
while (spaceTok.hasMoreTokens()) {
res.add(spaceTok.nextToken());
}
}
}
if (inQuote) {
throw new IllegalArgumentException("Unbalanced quotation marks");
}
return (String[]) res.toArray(new String[0]);
}
}

View File

@ -0,0 +1,54 @@
package net.hyperic.sigar.shell;
import java.io.PrintStream;
public class ShellCommandBase implements ShellCommandHandler {
protected String itsCommandName = null;
protected ShellBase itsShell = null;
private PrintStream out = null;
public String getCommandName() { return itsCommandName; }
public ShellBase getShell() { return itsShell; }
public PrintStream getOutStream() {
return this.getShell().getOutStream();
}
public PrintStream getErrStream() {
return this.getShell().getErrStream();
}
public void init(String commandName, ShellBase shell)
throws ShellCommandInitException {
itsCommandName = commandName;
itsShell = shell;
}
public void processCommand(String[] args)
throws ShellCommandUsageException, ShellCommandExecException {
out.println("ShellCommandBase: not implemented: " + itsCommandName);
/*
if (args != null && args.trim().length() > 0) {
out.println("args were: " + args);
}
*/
}
public String getSyntax() {
return "Syntax: " + this.getCommandName() + " " + this.getSyntaxArgs();
}
public String getSyntaxArgs() {
return "";
}
public String getUsageShort() {
return "";
}
public String getUsageHelp(String[] args) {
return "Help not available for command " + itsCommandName;
}
}

View File

@ -0,0 +1,10 @@
package net.hyperic.sigar.shell;
public class ShellCommandExecException extends Exception {
public ShellCommandExecException() {}
public ShellCommandExecException(String s) {
super(s);
}
}

View File

@ -0,0 +1,44 @@
package net.hyperic.sigar.shell;
public interface ShellCommandHandler {
/**
* Initialize this command handler.
* @param commandName The name of the command.
* @param shell The shell. This is useful for command
* that need to be able to interpret other commands, like the "help"
* command, and for commands that need to get additional user input,
* for example a login command that presents a password prompt.
*/
public void init(String commandName, ShellBase shell)
throws ShellCommandInitException;
/**
* Handle a command.
* @param args The args to the command.
* @exception ShellCommandUsageException If the args are malformed.
* @exception ShellCommandExecException If an error occurred
* executing the command.
*/
public void processCommand(String[] args)
throws ShellCommandUsageException, ShellCommandExecException;
/**
* Get some info on how to invoke this command.
* @return Some usage information on how this command is
* expected to be invoked.
*/
public String getUsageHelp(String[] args);
/**
* Get a very brief (40 character) description of the command
* @return A description of the command.
*/
public String getUsageShort();
/**
* Get a description of the syntax for how a command should be invoked.
* @return A description of the syntax
*/
public String getSyntax();
}

View File

@ -0,0 +1,10 @@
package net.hyperic.sigar.shell;
public class ShellCommandInitException extends Exception {
public ShellCommandInitException() {}
public ShellCommandInitException(String s) {
super(s);
}
}

View File

@ -0,0 +1,16 @@
package net.hyperic.sigar.shell;
import java.util.Iterator;
public interface ShellCommandMapper {
/**
* Get the command handler for a command.
*/
public ShellCommandHandler getHandler(String command);
/**
* Get an iterator for the command names.
*/
public Iterator getCommandNameIterator();
}

View File

@ -0,0 +1,10 @@
package net.hyperic.sigar.shell;
public class ShellCommandUsageException extends Exception {
public ShellCommandUsageException() {}
public ShellCommandUsageException(String s) {
super(s);
}
}

Some files were not shown because too many files have changed in this diff Show More