/** * ***************************************************************************** * * Copyright (c) 2011, Oracle Corporation. * * All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Winston Prakash * ****************************************************************************** */ package org.eclipse.hudson.jna; import hudson.model.Descriptor; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A Native Support Utility (singleton) that delegates the actions to available * Native Support Extensions * * @since 3.0.0 * @see NativeAccessSupport, ZfsSupport */ public class NativeUtils implements Serializable { private NativeZfsSupport nativeZfsSupport; private NativeUnixSupport nativeUnixSupport; private NativeWindowsSupport nativeWindowsSupport; private NativeMacSupport nativeMacSupport; private static Logger logger = LoggerFactory.getLogger(NativeUtils.class); public static NativeUtils INSTANCE; private NativeUtils() { try { List<NativeUnixSupport> nativeUnixSupports = getAvailableNativeUnixSupports(); if (nativeUnixSupports.size() > 0) { nativeUnixSupport = nativeUnixSupports.get(0); } List<NativeWindowsSupport> nativeWindowsSupports = getAvailableNativeWindowSupports(); if (nativeWindowsSupports.size() > 0) { nativeWindowsSupport = nativeWindowsSupports.get(0); } List<NativeMacSupport> nativeMacSupports = getAvailableNativeMacSupports(); if (nativeMacSupports.size() > 0) { nativeMacSupport = nativeMacSupports.get(0); } List<NativeZfsSupport> nativeZfsSupports = getAvailableNativeZfsSupports(); if (nativeZfsSupports.size() > 0) { nativeZfsSupport = nativeZfsSupports.get(0); } } catch (Exception exc) { logger.info("Error getting Native Support Extensions", exc); } } private List<NativeUnixSupport> getAvailableNativeUnixSupports() { List<NativeUnixSupport> nativeUnixSupports = new ArrayList<NativeUnixSupport>(); if (NativeUnixSupport.all() != null && !NativeUnixSupport.all().isEmpty()) { for (Descriptor<NativeUnixSupport> nativeUnixSupport : NativeUnixSupport.all()) { try { nativeUnixSupports.add(nativeUnixSupport.newInstance(null, null)); } catch (Throwable exc) { logger.info("Failed to instantiate Native Unix Support - " + nativeUnixSupport.getDisplayName()); } } } return nativeUnixSupports; } private List<NativeWindowsSupport> getAvailableNativeWindowSupports() { List<NativeWindowsSupport> nativeWindowsSupports = new ArrayList<NativeWindowsSupport>(); if (NativeWindowsSupport.all() != null && !NativeWindowsSupport.all().isEmpty()) { for (Descriptor<NativeWindowsSupport> nativeWindowsSupport : NativeWindowsSupport.all()) { try { nativeWindowsSupports.add(nativeWindowsSupport.newInstance(null, null)); } catch (Throwable exc) { logger.info("Failed to instantiate Native Window Support - " + nativeWindowsSupport.getDisplayName()); } } } return nativeWindowsSupports; } private List<NativeMacSupport> getAvailableNativeMacSupports() { List<NativeMacSupport> nativeMacSupports = new ArrayList<NativeMacSupport>(); if (NativeMacSupport.all() != null && !NativeMacSupport.all().isEmpty()) { for (Descriptor<NativeMacSupport> nativeMacSupport : NativeMacSupport.all()) { try { nativeMacSupports.add(nativeMacSupport.newInstance(null, null)); } catch (Throwable exc) { logger.info("Failed to instantiate Native Mac Support - " + nativeMacSupport.getDisplayName()); } } } return nativeMacSupports; } private List<NativeZfsSupport> getAvailableNativeZfsSupports() { List<NativeZfsSupport> nativeZfsSupports = new ArrayList<NativeZfsSupport>(); if (NativeZfsSupport.all() != null && !NativeZfsSupport.all().isEmpty()) { for (Descriptor<NativeZfsSupport> nativeZfsSupport : NativeZfsSupport.all()) { try { nativeZfsSupports.add(nativeZfsSupport.newInstance(null, null)); } catch (Throwable exc) { logger.info("Failed to instantiate Native Zfs Support - " + nativeZfsSupport.getDisplayName()); } } } return nativeZfsSupports; } /** * Delay the instance creation until needed, else slave ClassLoader deserialization will try to * instantiate the instance and will fail to load the extension points. * @return */ public static synchronized NativeUtils getInstance() { if (INSTANCE == null){ INSTANCE = new NativeUtils(); } return INSTANCE; } /** * Check if any Native Unix Support plugin is installed * @return */ public boolean hasUnixSupport() { return nativeUnixSupport != null; } /** * Check if any Native Windows Support plugin is installed * * @return */ public boolean hasWindowsSupport() { return nativeWindowsSupport != null; } /** * Check if any Native Mac Support plugin is installed * * @return */ public boolean hasMacSupport() { return nativeMacSupport != null; } /** * Check if any Native ZFS Support plugin is installed * * @return */ public boolean hasZfsSupport() { return nativeZfsSupport != null; } private void ensureUnixSupport(NativeFunction function) throws NativeAccessException { if (!hasUnixSupport()) { throw new NativeAccessException("Native Unix Support plugin not installed"); } if (!nativeUnixSupport.hasSupportFor(function)) { throw new NativeAccessException("Installed Native Unix Support plugin does not support " + function); } } private void ensureWindowsSupport(NativeFunction function) throws NativeAccessException { if (!hasWindowsSupport()) { throw new NativeAccessException("Native Windows Support plugin not installed"); } if (!nativeWindowsSupport.hasSupportFor(function)) { throw new NativeAccessException("Installed Native Windows Support plugin does not support " + function); } } private void ensureMacSupport(NativeFunction function) throws NativeAccessException { if (!hasMacSupport()) { throw new NativeAccessException("Native Mac Support plugin not installed"); } if (!nativeMacSupport.hasSupportFor(function)) { throw new NativeAccessException("Installed Native Mac Support plugin does not support " + function); } } private void ensureZfsSupport(NativeFunction function) throws NativeAccessException { if (!hasZfsSupport()) { throw new NativeAccessException("Native ZFS Support plugin not installed"); } if (!nativeZfsSupport.hasSupportFor(function)) { throw new NativeAccessException("Installed Native ZFS Support plugin does not support " + function); } } /** * Do the Unix style chmod (change file permission) on a File * * @param file * @param mask * @return true if the function executed successfully * @throws hudson.util.jna.Native.ExecutionError */ public boolean chmod(File file, int mask) throws NativeAccessException { ensureUnixSupport(NativeFunction.CHMOD); return nativeUnixSupport.chmod(file, mask); } /** * Do the Unix style chown (change Owner permission) on a File * * @param file * @param mask * @return true if the function executed successfully * @throws hudson.util.jna.Native.ExecutionError */ public boolean chown(File file, int uid, int gid) throws NativeAccessException { ensureUnixSupport(NativeFunction.CHOWN); return nativeUnixSupport.chown(file, uid, gid); } /** * Get the Unix style mode (file permission) of a file * * @param file * @return * @throws hudson.util.jna.Native.ExecutionError */ public int mode(File file) throws NativeAccessException { ensureUnixSupport(NativeFunction.MODE); return nativeUnixSupport.mode(file); } /** * Get the name of the user who started this Java process * * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public String getProcessUser() throws NativeAccessException { ensureUnixSupport(NativeFunction.UNIX_USER); return nativeUnixSupport.getProcessUser(); } /** * Make the file writable with native operation * * @param file * @return true if the operation is successful * @throws hudson.util.jna.Native.ExecutionError */ public boolean makeFileWritable(File file) throws NativeAccessException { ensureUnixSupport(NativeFunction.FILE_WRITABLE); return nativeUnixSupport.makeFileWritable(file); } /** * Create Unix style symlink * * @param targetPath * @param file * @return true if the operation is successful * @throws hudson.util.jna.Native.ExecutionError */ public boolean createSymlink(String targetPath, File file) throws NativeAccessException { ensureUnixSupport(NativeFunction.SYMLINK); return nativeUnixSupport.createSymlink(targetPath, file); } /** * Resolves symlink, if the given file is a symlink on a Unix System. * Otherwise return null. * * @param targetPath * @param file * @return String the resolved file path * @throws hudson.util.jna.Native.ExecutionError */ public String resolveSymlink(File file) throws NativeAccessException { ensureUnixSupport(NativeFunction.RESOLVE_LINK); return nativeUnixSupport.resolveSymlink(file); } /** * Get the information about the System Memory * * @return * @throws hudson.util.jna.Native.ExecutionError */ public NativeSystemMemory getSystemMemory() throws NativeAccessException { ensureUnixSupport(NativeFunction.SYSTEM_MEMORY); return nativeUnixSupport.getSystemMemory(); } /** * Get the effective User ID on a Unix System * * @return * @throws hudson.util.jna.Native.ExecutionError */ public int getEuid() throws NativeAccessException { ensureUnixSupport(NativeFunction.EUID); return nativeUnixSupport.getEuid(); } /** * Get the effective Group ID on a Unix System * * @return * @throws hudson.util.jna.Native.ExecutionError */ public int getEgid() throws NativeAccessException { ensureUnixSupport(NativeFunction.EGID); return nativeUnixSupport.getEgid(); } /** * Check if this Unix user exists on the machine where this program runs * * @param userName * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public boolean checkUnixUser(String userName) throws NativeAccessException { ensureUnixSupport(NativeFunction.UNIX_USER); return nativeUnixSupport.checkUnixUser(userName); } /** * Check if this Unix group exists on the machine where this program runs * * @param userName * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public boolean checkUnixGroup(String groupName) throws NativeAccessException { ensureUnixSupport(NativeFunction.UNIX_GROUP); return nativeUnixSupport.checkUnixGroup(groupName); } /** * Authenticate using Using Unix Pluggable Authentication Modules (PAM) * * @param userName * @param password * @return List<String> list of groups to which this user belongs * @throws hudson.util.jna.Native.NativeExecutionException */ public Set<String> pamAuthenticate(String serviceName, String userName, String password) throws NativeAccessException { ensureUnixSupport(NativeFunction.PAM); return nativeUnixSupport.pamAuthenticate(serviceName, userName, password); } /** * Check if PAM Authentication available in the machine where this program * runs * * @return Message corresponding to the availability of PAM * @throws hudson.util.jna.Native.NativeExecutionException */ public String checkPamAuthentication() throws NativeAccessException { ensureUnixSupport(NativeFunction.PAM); return nativeUnixSupport.checkPamAuthentication(); } /** * Restart current Java process (JVM in which this application is running) * * @throws hudson.util.jna.Native.NativeExecutionException */ public void restartJavaProcess(Map<String, String> properties, boolean asDaemon) throws NativeAccessException { ensureUnixSupport(NativeFunction.JAVA_RESTART); nativeUnixSupport.restartJavaProcess(properties, asDaemon); } /** * Check if this Java process can be restarted * * @throws hudson.util.jna.Native.NativeExecutionException */ public boolean canRestartJavaProcess() throws NativeAccessException { ensureUnixSupport(NativeFunction.JAVA_RESTART); return nativeUnixSupport.canRestartJavaProcess(); } /** * Get the error associated with the last Native Unix Operation * * @return String error message */ public String getLastUnixError() { if (!hasUnixSupport()) { return "Native Unix Support plugin not installed"; } return nativeUnixSupport.getLastError(); } /** * Check if .NET is installed on a the Windows machine * * @return true if .NET is installed. * @throws hudson.util.jna.Native.ExecutionError */ public boolean isDotNetInstalled(int major, int minor) throws NativeAccessException { ensureWindowsSupport(NativeFunction.DOTNET); return nativeWindowsSupport.isDotNetInstalled(major, minor); } /** * Get all the native processes on a Windows System * * @return List of Native Window Processes * @throws hudson.util.jna.Native.ExecutionError */ public List<NativeProcess> getWindowsProcesses() throws NativeAccessException { ensureWindowsSupport(NativeFunction.WINDOWS_PROCESS); return nativeWindowsSupport.getWindowsProcesses(); } /** * Find the Native Process Id of the given java.lang.process * * @param process (java.lang.process) * @return pid, the Native Process ID */ public int getWindowsProcessId(Process process) throws NativeAccessException { ensureWindowsSupport(NativeFunction.WINDOWS_PROCESS); return nativeWindowsSupport.getWindowsProcessId(process); } /** * Run the Windows program natively in an elevated privilege * * @param winExe, windows executable to run * @param args, arguments to pass * @param logFile, File where the logs of the process should go * @param pwd, Path of the working directory * @return int, process exit code * @throws hudson.util.jna.Native.NativeExecutionException */ public int windowsExec(File winExe, String args, String logFile, File pwd) throws NativeAccessException { ensureWindowsSupport(NativeFunction.WINDOWS_EXEC); return nativeWindowsSupport.windowsExec(winExe, args, logFile, pwd); } /** * Move a Windows File using native win32 library * * @param fromFile * @param toFile * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public void windowsMoveFile(File fromFile, File toFile) throws NativeAccessException { ensureWindowsSupport(NativeFunction.WINDOWS_FILE_MOVE); nativeWindowsSupport.windowsMoveFile(fromFile, toFile); } /** * Get the error associated with the last Native Unix Operation * * @return String error message */ public String getLastWindowsError() { if (!hasUnixSupport()) { return "Native Windows Support plugin not installed"; } return nativeWindowsSupport.getLastError(); } /** * Get the Native processes of a Mac System * * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public List<NativeProcess> getMacProcesses() throws NativeAccessException { ensureMacSupport(NativeFunction.MAC_PROCESS); return nativeMacSupport.getMacProcesses(); } /** * Get the error associated with the last Native Unix Operation * * @return String error message */ public String getLastMacError() { return nativeMacSupport.getLastError(); } /** * Fetch the list of mounted ZFS roots * * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public List<NativeZfsFileSystem> getZfsRoots() throws NativeAccessException { ensureZfsSupport(NativeFunction.ZFS); return nativeZfsSupport.getZfsRoots(); } /** * Find the ZFS File System by its mount point * * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public NativeZfsFileSystem getZfsByMountPoint(File mountPoint) throws NativeAccessException { ensureZfsSupport(NativeFunction.ZFS); return nativeZfsSupport.getZfsByMountPoint(mountPoint); } /** * Create ZFS File System corresponding to the mount name * * @param mountPoint * @return ZFS File System if created successfully * @throws hudson.util.jna.Native.NativeExecutionException */ public NativeZfsFileSystem createZfs(String mountName) throws NativeAccessException { ensureZfsSupport(NativeFunction.ZFS); return nativeZfsSupport.createZfs(mountName); } /** * Open the target ZFS File System * * @param mountPoint * @return ZFS File System if opened successfully * @throws hudson.util.jna.Native.NativeExecutionException */ public NativeZfsFileSystem openZfs(String target) throws NativeAccessException { ensureZfsSupport(NativeFunction.ZFS); return nativeZfsSupport.openZfs(target); } /** * Check if the named ZFS exists * * @param zfsName * @return * @throws hudson.util.jna.Native.NativeExecutionException */ public boolean zfsExists(String zfsName) throws NativeAccessException { ensureZfsSupport(NativeFunction.ZFS); return nativeZfsSupport.zfsExists(zfsName); } /** * Get the error associated with the last Native Unix Operation * * @return String error message */ public String getLastZfsError() { if (!hasZfsSupport()) { return "Native Unix Support plugin not installed"; } return nativeZfsSupport.getLastError(); } }