Java tutorial
/* * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. * * Copyright (c) 2014, Gluu */ package org.gluu.oxtrust.ldap.service; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URL; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.exec.CommandLine; import org.apache.commons.io.IOUtils; import org.gluu.oxtrust.config.OxTrustConfiguration; import org.gluu.oxtrust.model.GluuAppliance; import org.gluu.oxtrust.util.NumberHelper; import org.gluu.oxtrust.util.OxTrustConstants; import org.gluu.site.ldap.persistence.exception.LdapMappingException; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.AutoCreate; import org.jboss.seam.annotations.Create; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.async.Asynchronous; import org.jboss.seam.annotations.async.Expiration; import org.jboss.seam.annotations.async.IntervalDuration; import org.jboss.seam.async.QuartzTriggerHandle; import org.jboss.seam.log.Log; import org.xdi.config.oxtrust.ApplicationConfiguration; import org.xdi.util.ArrayHelper; import org.xdi.util.StringHelper; import org.xdi.util.process.ProcessHelper; /** * Gather periodically site and server status * * @author Yuriy Movchan Date: 11.22.2010 */ @AutoCreate @Scope(ScopeType.APPLICATION) @Name("statusCheckerTimer") public class StatusCheckerTimer { @Logger private Log log; @In private ApplianceService applianceService; @In private GroupService groupService; @In private PersonService personService; @In private CentralLdapService centralLdapService; @In private OxTrustConfiguration oxTrustConfiguration; private NumberFormat numberFormat; @Create public void create() { this.numberFormat = NumberFormat.getNumberInstance(Locale.US); } @Asynchronous public QuartzTriggerHandle scheduleStatusChecking(@Expiration Date when, @IntervalDuration Long interval) { process(when, interval); return null; } /** * Gather periodically site and server status * * @param when * Date * @param interval * Interval */ private void process(Date when, Long interval) { log.debug("Starting update of appliance status"); ApplicationConfiguration applicationConfiguration = oxTrustConfiguration.getApplicationConfiguration(); if (!applicationConfiguration.isUpdateApplianceStatus()) { return; } GluuAppliance appliance; try { appliance = applianceService.getAppliance(); } catch (LdapMappingException ex) { log.error("Failed to load current appliance", ex); return; } // Execute facter and update appliance attributes setFactorAttributes(appliance); // Execute df and update appliance attributes setDfAttributes(appliance); // Set HTTPD attributes setHttpdAttributes(appliance); try { setCertificateExpiryAttributes(appliance); } catch (Exception ex) { log.error("Failed to check certificate expiration", ex); } // setVDSAttributes(appliance); appliance.setLastUpdate(toIntString(System.currentTimeMillis() / 1000)); try { applianceService.updateAppliance(appliance); } catch (LdapMappingException ex) { log.error("Failed to update current appliance", ex); return; } if (centralLdapService.isUseCentralServer()) { try { GluuAppliance tmpAppliance = new GluuAppliance(); tmpAppliance.setDn(appliance.getDn()); boolean existAppliance = centralLdapService.containsAppliance(tmpAppliance); if (existAppliance) { centralLdapService.updateAppliance(appliance); } else { centralLdapService.addAppliance(appliance); } } catch (LdapMappingException ex) { log.error("Failed to update appliance at central server", ex); return; } } log.debug("Appliance status update finished"); } private void setCertificateExpiryAttributes(GluuAppliance appliance) { if (isLinux()) { String programPath = OxTrustConstants.PROGRAM_CHECK_SSL; String[] outputLines = runCheck(programPath); int expiresAfter = -1; if (ArrayHelper.isEmpty(outputLines) || (outputLines.length < 1) || StringHelper.isEmpty(outputLines[0]) || outputLines[0].startsWith("SSL_CERT CRITICAL")) { String message = String.format("%s retuned an unexpected value", programPath); log.error(message); } else { try { if (outputLines.length == 1) { expiresAfter = Integer.parseInt(outputLines[0]); } else { String message = String.format("%s retuned an unexpected " + "number of lines", programPath); log.error(message); } } catch (NumberFormatException e) { String message = String.format("%s retuned an unexpected value", programPath); log.error(message); } } appliance.setSslExpiry(toIntString(expiresAfter)); } } private String[] runCheck(String programPath) { ByteArrayOutputStream bos = new ByteArrayOutputStream(4096); boolean result = false; try { result = ProcessHelper.executeProgram(programPath, false, 0, bos); } catch (Exception e) { String message = String.format("Failed to run %s : %s", programPath, e.getMessage()); log.error(message); } finally { IOUtils.closeQuietly(bos); } String[] outputLines = null; if (result) { String resultOutput = null; try { resultOutput = new String(bos.toByteArray(), "UTF-8"); } catch (UnsupportedEncodingException ex) { String message = String.format("Failed to parse program %s output", programPath); log.error(message, ex); } if (resultOutput != null) { outputLines = resultOutput.split("\\r?\\n"); } } else { String message = String.format("There was an error executing command %s", programPath); log.error(message); } return outputLines; } private void setHttpdAttributes(GluuAppliance appliance) { log.debug("Setting httpd attributes"); ApplicationConfiguration applicationConfiguration = oxTrustConfiguration.getApplicationConfiguration(); String page = getHttpdPage(applicationConfiguration.getIdpUrl(), OxTrustConstants.HTTPD_TEST_PAGE_NAME); appliance.setGluuHttpStatus(Boolean.toString(OxTrustConstants.HTTPD_TEST_PAGE_CONTENT.equals(page))); } /* private void setVDSAttributes(GluuAppliance appliance) { log.debug("Setting VDS attributes"); ApplicationConfiguration applicationConfiguration = oxTrustConfiguration.getApplicationConfiguration(); // Run vds check only on if vds.test.filter is set if (applicationConfiguration.getVdsFilter() == null) { return; } String serverURL = applicationConfiguration.getVdsLdapServer().split(":")[0]; int serverPort = Integer.parseInt(applicationConfiguration.getVdsLdapServer().split(":")[1]); String bindDN = applicationConfiguration.getVdsBindDn(); String bindPassword = null; try { bindPassword = StringEncrypter.defaultInstance().decrypt(applicationConfiguration.getVdsBindPassword()); } catch (EncryptionException e1) { log.error("Failed to decrypt VDS bind password: %s", e1.getMessage()); } String vdsFilter = applicationConfiguration.getVdsFilter(); String baseDN = applicationConfiguration.getBaseDN(); LDAPConnectionPool connectionPool = null; String[] objectclasses = null; try { ServerSet vdsServerSet; boolean useSSL = "ldaps".equals(applicationConfiguration.getVdsLdapProtocol()); if (useSSL) { SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager()); vdsServerSet = new SingleServerSet(serverURL, serverPort, sslUtil.createSSLSocketFactory()); } else { vdsServerSet = new SingleServerSet(serverURL, serverPort); } SimpleBindRequest bindRequest = new SimpleBindRequest(bindDN, bindPassword); connectionPool = new LDAPConnectionPool(vdsServerSet, bindRequest, 10); SearchResult entry = connectionPool.search(baseDN, SearchScope.BASE, vdsFilter); objectclasses = entry.getSearchEntries().get(0).getAttribute("objectclass").getValues(); } catch (Exception e) { appliance.setGluuVDSStatus(Boolean.toString(false)); log.error(String.format("Failed to get objectclass values from VDS. error: %s", e.getMessage())); } finally { if (connectionPool != null) { connectionPool.close(); } else { log.error(String.format("Unable to connect to VDS server. Is it running on %s:%s ?", serverURL, serverPort)); } } boolean topPresent = false; boolean vdapcontainerPresent = false; boolean vdlabelPresent = false; boolean vdDirectoryViewPresent = false; if (objectclasses != null && objectclasses.length > 0) { Arrays.sort(objectclasses); topPresent = Arrays.binarySearch(objectclasses, "top") >= 0; vdapcontainerPresent = Arrays.binarySearch(objectclasses, "vdapcontainer") >= 0; vdlabelPresent = Arrays.binarySearch(objectclasses, "vdlabel") >= 0; vdDirectoryViewPresent = Arrays.binarySearch(objectclasses, "vdDirectoryView") >= 0; } appliance.setGluuVDSStatus(Boolean.toString(topPresent && vdapcontainerPresent && vdlabelPresent && vdDirectoryViewPresent)); } */ private String getHttpdPage(String idpUrl, String httpdTestPageName) { String[] urlParts = idpUrl.split("://"); if ("https".equals(urlParts[0])) { // Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { } } }; // Install the all-trusting trust manager try { SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); } catch (Exception e) { } } StringBuilder sb = new StringBuilder(); // Now you can access an https URL without having the certificate in the // truststore try { String[] hostAndPort = urlParts[1].split(":"); URL url = null; if (hostAndPort.length < 2) { url = new URL(urlParts[0], hostAndPort[0], httpdTestPageName); } else { url = new URL(urlParts[0], hostAndPort[0], Integer.parseInt(hostAndPort[1]), httpdTestPageName); } InputStream in = url.openConnection().getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } in.close(); } catch (Exception e) { // log.error("Failed to get test page: ", e); } return sb.toString(); } private void setFactorAttributes(GluuAppliance appliance) { log.debug("Setting facter attributes"); // Run facter only on linux if (!isLinux()) { return; } String programPath = OxTrustConstants.PROGRAM_FACTER; ByteArrayOutputStream bos = new ByteArrayOutputStream(4096); try { boolean result = ProcessHelper.executeProgram(programPath, false, 0, bos); if (!result) { return; } } finally { IOUtils.closeQuietly(bos); } String resultOutput = null; try { resultOutput = new String(bos.toByteArray(), "UTF-8"); } catch (UnsupportedEncodingException ex) { log.error("Failed to parse program {0} output", ex, programPath); return; } String[] outputLines = resultOutput.split("\\r?\\n"); // Update appliance attributes appliance.setFreeMemory(toIntString(getFacterPercentResult(outputLines, OxTrustConstants.FACTER_FREE_MEMORY, OxTrustConstants.FACTER_FREE_MEMORY_TOTAL))); appliance.setFreeSwap(toIntString(getFacterPercentResult(outputLines, OxTrustConstants.FACTER_FREE_SWAP, OxTrustConstants.FACTER_FREE_SWAP_TOTAL))); appliance.setHostname(getFacterResult(outputLines, OxTrustConstants.FACTER_HOST_NAME)); appliance.setIpAddress(getFacterResult(outputLines, OxTrustConstants.FACTER_IP_ADDRESS)); appliance.setLoadAvg(getFacterResult(outputLines, OxTrustConstants.FACTER_LOAD_AVERAGE)); getFacterBandwidth(getFacterResult(outputLines, OxTrustConstants.FACTER_BANDWIDTH_USAGE), appliance); appliance.setSystemUptime(getFacterResult(outputLines, OxTrustConstants.FACTER_SYSTEM_UP_TIME)); } private void getFacterBandwidth(String facterResult, GluuAppliance appliance) { log.debug("Setting bandwidth attributes"); if (facterResult != null) { String[] lines = facterResult.split("\n"); SimpleDateFormat monthFormat = new SimpleDateFormat("MMM ''yy"); String month = monthFormat.format(new Date()); Pattern curent = Pattern.compile("^\\s*" + month); for (String line : lines) { Matcher match = curent.matcher(line); if (match.find()) { line = line.replaceAll("^\\s*" + month, ""); String[] values = line.split("\\|"); appliance.setGluuBandwidthRX(values[0].replaceAll("^\\s*", "").replaceAll("\\s*$", "")); appliance.setGluuBandwidthTX(values[1].replaceAll("^\\s*", "").replaceAll("\\s*$", "")); } } } else { appliance.setGluuBandwidthRX("-1"); appliance.setGluuBandwidthTX("-1"); } } private void setDfAttributes(GluuAppliance appliance) { log.debug("Setting df attributes"); // Run df only on linux if (!isLinux()) { return; } String programPath = OxTrustConstants.PROGRAM_DF; CommandLine commandLine = new CommandLine(programPath); commandLine.addArgument("/"); commandLine.addArgument("--human-readable"); ByteArrayOutputStream bos = new ByteArrayOutputStream(4096); try { boolean result = ProcessHelper.executeProgram(commandLine, false, 0, bos); if (!result) { return; } } finally { IOUtils.closeQuietly(bos); } String resultOutput = null; try { resultOutput = new String(bos.toByteArray(), "UTF-8"); } catch (UnsupportedEncodingException ex) { log.error("Failed to parse program {0} output", ex, programPath); return; } String[] outputLines = resultOutput.split("\\r?\\n"); String[] outputValues = null; if (outputLines.length == 2) { outputValues = outputLines[1].split("\\s+"); } else if (outputLines.length == 3) { outputValues = outputLines[2].split("\\s+"); } if (outputValues != null) { if (outputValues.length < 6) { return; } Number usedDiskSpace = getNumber(outputValues[4]); Number freeDiskSpace = usedDiskSpace == null ? null : 100 - usedDiskSpace.doubleValue(); // Update appliance attributes appliance.setFreeDiskSpace(toIntString(freeDiskSpace)); } } private boolean isLinux() { String osName = System.getProperty("os.name"); return !StringHelper.isEmpty(osName) && osName.toLowerCase().contains("linux"); } private String getFacterResult(String[] lines, String param) { log.debug("Setting facter param: " + param); String paramPattern = param + OxTrustConstants.FACTER_PARAM_VALUE_DIVIDER; boolean valueStarted = false; String value = ""; List<String> facterLines = Arrays.asList(lines); Iterator<String> lineIterator = facterLines.iterator(); while (lineIterator.hasNext()) { String line = lineIterator.next(); if (!valueStarted) { // start searching for the line with param if (line.startsWith(paramPattern)) { valueStarted = true; int index = line.indexOf(OxTrustConstants.FACTER_PARAM_VALUE_DIVIDER); if (index > -1) { value = line.substring(index + OxTrustConstants.FACTER_PARAM_VALUE_DIVIDER.length()); } } else { continue; } log.debug(line); } else { //check if there are any additional lines int index = line.indexOf(OxTrustConstants.FACTER_PARAM_VALUE_DIVIDER); if (index == -1) { // this line has no value name, so it must be continuation of the previous value. value += "\n" + line; } else { // this line has it's own value, so the value we were looking for has ended. valueStarted = false; continue; } } } return value.equals("") ? null : value; } private Number getFacterNumberResult(String[] lines, String param) { String value = getFacterResult(lines, param); if (value == null) { return null; } return getNumber(value); } private Number getFacterPercentResult(String[] lines, String paramValue, String paramTotal) { Number value = getFacterNumberResult(lines, paramValue); Number total = getFacterNumberResult(lines, paramTotal); return getNumber(value, total); } private Number getNumber(String value) { int multiplier = 1; if (value.contains("KB")) { multiplier = 1024; } else if (value.contains("MB")) { multiplier = 1024 * 1024; } else if (value.contains("GB")) { multiplier = 1024 * 1024 * 1024; } try { return multiplier * numberFormat.parse(value).doubleValue(); } catch (ParseException ex) { } return null; } private Number getNumber(Number value, Number total) { if ((value == null) || (total == null) || (value.doubleValue() == 0.0d) || (total.doubleValue() == 0.0)) { return null; } return NumberHelper.round(value.doubleValue() / total.doubleValue(), 2) * 100; } private String toIntString(Number number) { return (number == null) ? null : String.valueOf(number.intValue()); } }