/* * RHQ Management Platform * Copyright (C) 2005-2014 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.core.system; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.hyperic.sigar.DirUsage; import org.hyperic.sigar.win32.RegistryKey; import org.hyperic.sigar.win32.Service; import org.hyperic.sigar.win32.ServiceConfig; import org.hyperic.sigar.win32.Win32Exception; import org.rhq.core.system.windows.DWordRegistryValue; import org.rhq.core.system.windows.MultiSzRegistryValue; import org.rhq.core.system.windows.RegistryEntry; import org.rhq.core.system.windows.RegistryEntry.Root; import org.rhq.core.system.windows.RegistryValue; import org.rhq.core.system.windows.SzRegistryValue; /** * {@link SystemInfo} implementation for the Microsoft Windows operating system platform. This class is used mainly to * obtain information found in the Windows Registry. * * @author John Mazzitelli */ public class WindowsNativeSystemInfo extends NativeSystemInfo { // return The available ServiceInfo. Not all existing services may be returned as Windows may protect some service information. @Override public List<ServiceInfo> getAllServices() throws SystemInfoException { List<ServiceInfo> services = new ArrayList<ServiceInfo>(); try { @SuppressWarnings("unchecked") List<String> serviceNames = Service.getServiceNames(); if (serviceNames != null) { for (String serviceName : serviceNames) { Service s = null; try { s = new Service(serviceName); ServiceConfig sc = s.getConfig(); ServiceInfo si = new ServiceInfo(sc.getName(), sc.getDisplayName(), sc.getDescription(), sc .getPath(), sc.getDependencies()); services.add(si); } catch (Win32Exception e) { ; // Ignore these, it means Sigar was rejected by Windows for the particular Service. } finally { if (null != s) { s.close(); } } } } } catch (Exception e) { throw new SystemInfoException("Cannot obtain Windows Services information", e); } return services; } @Override public DirUsage getDirectoryUsage(String path) { throw new UnsupportedOperationException("Dir Usage not yet supported."); } /** * Gets a list of all the sub-keys that are direct children of the given registry key. You can use the key names * found in the returned list of strings as values to the <code>key</code> parameter for calls to * {@link #getRegistryEntry(Root, String, String)}. * * @param root * @param key * * @return list of child keys * * @throws SystemInfoException */ public List<String> getRegistryChildKeys(Root root, String key) throws SystemInfoException { try { RegistryKey registry = null; switch (root) { case HKEY_CURRENT_USER: { registry = RegistryKey.CurrentUser.openSubKey(key); break; } case HKEY_LOCAL_MACHINE: { registry = RegistryKey.LocalMachine.openSubKey(key); break; } default: { throw new SystemInfoException("Invalid root: " + root); } } List<String> list = new ArrayList<String>(); String[] values = registry.getSubKeyNames(); if (values != null) { list.addAll(Arrays.asList(values)); } return list; } catch (Exception e) { throw new SystemInfoException(e); } } /** * Gets a list of all the names of values of the given registry key. You can use the value names found in the * returned list of strings as values to the <code>name</code> parameter for calls to * {@link #getRegistryEntry(Root, String, String)}. * * @param root * @param key * * @return list of names of values found in that registry key * * @throws SystemInfoException */ public List<String> getRegistryValueNames(Root root, String key) throws SystemInfoException { try { RegistryKey registry = null; switch (root) { case HKEY_CURRENT_USER: { registry = RegistryKey.CurrentUser.openSubKey(key); break; } case HKEY_LOCAL_MACHINE: { registry = RegistryKey.LocalMachine.openSubKey(key); break; } default: { throw new SystemInfoException("Invalid root: " + root); } } List<String> list = new ArrayList<String>(); String[] values = registry.getValueNames(); if (values != null) { list.addAll(Arrays.asList(values)); } return list; } catch (Exception e) { throw new SystemInfoException(e); } } /** * Gets a list of all the value entries of the given registry key. * * @param root * @param key * * @return list of registry entries for the given registry key * * @throws SystemInfoException */ public List<RegistryEntry> getRegistryEntries(Root root, String key) throws SystemInfoException { try { List<String> names = getRegistryValueNames(root, key); List<RegistryEntry> entries = new ArrayList<RegistryEntry>(); for (String name : names) { RegistryEntry entry = getRegistryEntry(root, key, name); entries.add(entry); } return entries; } catch (Exception e) { throw new SystemInfoException(e); } } /** * Returns a registry entry (which includes its value) where the key is located under either the LOCAL_MACHINE or * CURRENT_USER root registry node. * * @param root the root of the registry tree where the registry key is found * @param key the name of the registry key * @param name the name of the key entry value * * @return the value of the registry entry * * @throws SystemInfoException */ public RegistryEntry getRegistryEntry(Root root, String key, String name) throws SystemInfoException { RegistryValue value; switch (root) { case HKEY_LOCAL_MACHINE: { value = getLocalMachineRegistryValue(key, name); break; } case HKEY_CURRENT_USER: { value = getCurrentUserRegistryValue(key, name); break; } default: { throw new SystemInfoException("Invalid root: " + root); } } return new RegistryEntry(root, key, name, value); } /** * Returns a registry value where the key is located under LOCAL_MACHINE. * * @param key the name of the registry key * @param name the name of the key entry value * * @return the value of the registry entry * * @throws SystemInfoException */ private RegistryValue getLocalMachineRegistryValue(String key, String name) throws SystemInfoException { RegistryKey registry; try { registry = RegistryKey.LocalMachine.openSubKey(key); } catch (Exception e) { throw new SystemInfoException(e); } return getRegistryValue(registry, name); } /** * Returns a registry value where the key is located under CURRENT_USER. * * @param key the name of the registry key * @param name the name of the key entry value * * @return the string value of the registry entry * * @throws SystemInfoException */ private RegistryValue getCurrentUserRegistryValue(String key, String name) throws SystemInfoException { RegistryKey registry; try { registry = RegistryKey.CurrentUser.openSubKey(key); } catch (Exception e) { throw new SystemInfoException(e); } return getRegistryValue(registry, name); } private RegistryValue getRegistryValue(RegistryKey registry, String name) throws SystemInfoException { RegistryValue.Type valueType = guessType(registry, name); try { switch (valueType) { // case BINARY: return new BinaryRegistryValue(registry.getByteArrayValue(name)); // case QWORD: return new QWordRegistryValue(registry.getLongValue(name)); // case EXPAND_SZ: return new ExpandSzRegistryValue(registry.getStringValue(name)); case DWORD: { return new DWordRegistryValue(registry.getIntValue(name)); } case SZ: { return new SzRegistryValue(registry.getStringValue(name)); } case MULTI_SZ: { List<String> values = new ArrayList<String>(); registry.getMultiStringValue(name, values); return new MultiSzRegistryValue(values.toArray(new String[0])); } } } catch (Exception e) { throw new SystemInfoException(e); } throw new IllegalStateException("Bad registry value type: " + valueType); } private RegistryValue.Type guessType(RegistryKey registry, String name) { // TODO: SIGAR does not have a nice API to tell me what type a registry key name has - I have to try to guess. // For now, I can only guess at the few types SIGAR knows about. Need to enhance SIGAR to understand // all the types that Windows supports (like QWORD, BINARY, etc). try { registry.getIntValue(name); return RegistryValue.Type.DWORD; } catch (Exception e) { } try { registry.getMultiStringValue(name, new ArrayList<String>()); return RegistryValue.Type.MULTI_SZ; } catch (Exception e) { } try { registry.getStringValue(name); return RegistryValue.Type.SZ; } catch (Exception e) { } throw new SystemInfoException("Unknown registry value type for [" + name + "]"); } }