Initial revision
This commit is contained in:
parent
1a7957fb1e
commit
dffe0da855
|
@ -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
|
|
@ -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>
|
|
@ -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("");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -0,0 +1,3 @@
|
|||
sigar-bin
|
||||
build
|
||||
testresults
|
|
@ -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>
|
|
@ -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 © 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.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package net.hyperic.sigar;
|
||||
|
||||
class SigarCacheObject {
|
||||
|
||||
int expire = SigarProxyCache.EXPIRE_DEFAULT;
|
||||
long timestamp = 0;
|
||||
Object value = null;
|
||||
}
|
|
@ -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); }
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package net.hyperic.sigar;
|
||||
|
||||
public class SigarFileNotFoundException extends SigarException {
|
||||
|
||||
public SigarFileNotFoundException(String s) { super(s); }
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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); }
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package net.hyperic.sigar.pager;
|
||||
|
||||
public class PageFetchException extends Exception {
|
||||
public PageFetchException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PageFetchException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 + "'");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package net.hyperic.sigar.shell;
|
||||
|
||||
public interface SIGINT {
|
||||
|
||||
public void handleSIGINT();
|
||||
}
|
|
@ -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]);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.hyperic.sigar.shell;
|
||||
|
||||
public class ShellCommandExecException extends Exception {
|
||||
|
||||
public ShellCommandExecException() {}
|
||||
|
||||
public ShellCommandExecException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.hyperic.sigar.shell;
|
||||
|
||||
public class ShellCommandInitException extends Exception {
|
||||
|
||||
public ShellCommandInitException() {}
|
||||
|
||||
public ShellCommandInitException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue