Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D585D200BBB for ; Thu, 27 Oct 2016 00:12:01 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id D3F14160B04; Wed, 26 Oct 2016 22:12:01 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 5BDE0160AFD for ; Thu, 27 Oct 2016 00:11:59 +0200 (CEST) Received: (qmail 56091 invoked by uid 500); 26 Oct 2016 22:11:58 -0000 Mailing-List: contact commits-help@geode.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.incubator.apache.org Delivered-To: mailing list commits@geode.incubator.apache.org Received: (qmail 56070 invoked by uid 99); 26 Oct 2016 22:11:58 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Oct 2016 22:11:58 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id E793FC0C81 for ; Wed, 26 Oct 2016 22:11:57 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -6.219 X-Spam-Level: X-Spam-Status: No, score=-6.219 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-2.999] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id 6SjJtWn2gNKQ for ; Wed, 26 Oct 2016 22:11:50 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id D58B45FB5F for ; Wed, 26 Oct 2016 22:11:29 +0000 (UTC) Received: (qmail 52511 invoked by uid 99); 26 Oct 2016 22:11:23 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 26 Oct 2016 22:11:23 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 82F2FE97DD; Wed, 26 Oct 2016 22:11:23 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: klund@apache.org To: commits@geode.incubator.apache.org Date: Wed, 26 Oct 2016 22:11:38 -0000 Message-Id: In-Reply-To: <606d6e83890e45d287c1a915237dfb50@git.apache.org> References: <606d6e83890e45d287c1a915237dfb50@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [16/42] incubator-geode git commit: GEODE-288: move admin package to internal archived-at: Wed, 26 Oct 2016 22:12:02 -0000 http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXml.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXml.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXml.java new file mode 100644 index 0000000..3b56342 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXml.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.distributed.ConfigurationProperties; +import org.apache.geode.internal.ClassPathLoader; +import org.apache.geode.internal.admin.api.DistributedSystemConfig; +import org.apache.geode.internal.i18n.LocalizedStrings; +import org.xml.sax.*; + +import java.io.InputStream; + +/** + * The abstract superclass of classes that convert XML into a {@link + * DistributedSystemConfig} and vice versa. + * It provides helper methods and constants. + * + * @since GemFire 4.0 + */ +abstract class ManagedEntityConfigXml implements EntityResolver, ErrorHandler { + + /** The location of the DTD file */ + protected static final String DTD_LOCATION = + "/org/apache/geode/internal/admin/doc-files/ds5_0.dtd"; + + /** The URL for the DTD */ + protected static final String SYSTEM_ID = + "http://www.gemstone.com/dtd/ds5_0.dtd"; + + /** The public ID for the DTD */ + protected static final String PUBLIC_ID = + "-//GemStone Systems, Inc.//GemFire Distributed System 5.0//EN"; + + /** The name of the distributed-system element. */ + public static final String DISTRIBUTED_SYSTEM = + "distributed-system"; + + /** The name of the id attribute. */ + public static final String ID = "id"; + + /** The name of the disable-tcp attribute. */ + public static final String DISABLE_TCP = "disable-tcp"; + + /** The name of the remote-command element. */ + public static final String REMOTE_COMMAND = "remote-command"; + + /** The name of the locators element. */ + public static final String LOCATORS = ConfigurationProperties.LOCATORS; + + /** The name of the ssl element. */ + public static final String SSL = "ssl"; + + /** The name of the cache-server element */ + public static final String CACHE_SERVER = "cache-server"; + + /** The name of the multicast element */ + public static final String MULTICAST = "multicast"; + + /** The name of the locator element */ + public static final String LOCATOR = "locator"; + + /** The name of the port attribute */ + public static final String PORT = "port"; + + /** The name of the address attribute */ + public static final String ADDRESS = "address"; + + /** The name of the host element. */ + public static final String HOST = "host"; + + /** The name of the working-directory element */ + public static final String WORKING_DIRECTORY = "working-directory"; + + /** The name of the product-directory element */ + public static final String PRODUCT_DIRECTORY = "product-directory"; + + /** The name of the protocols element */ + public static final String PROTOCOLS = "protocols"; + + /** The name of the ciphers element */ + public static final String CIPHERS = "ciphers"; + + /** The name of the property element */ + public static final String PROPERTY = "property"; + + /** Name of the authentication-required attribute */ + public static final String AUTHENTICATION_REQUIRED = + "authentication-required"; + + /** The name of the key element */ + public static final String KEY = "key"; + + /** The name of the value element */ + public static final String VALUE = "value"; + + /** The name of the classpath element */ + public static final String CLASSPATH = "classpath"; + + /////////////////////// Instance Methods /////////////////////// + + /** + * Given a public id, attempt to resolve it to a DTD. Returns an + * InputSoure for the DTD. + */ + public InputSource resolveEntity(String publicId, String systemId) + throws SAXException { + + if (publicId == null || systemId == null) { + throw new SAXException(LocalizedStrings.ManagedEntityConfigXml_PUBLIC_ID_0_SYSTEM_ID_1.toLocalizedString(new Object[] {publicId, systemId})); + } + + // Figure out the location for the publicId. + String location = DTD_LOCATION; + + InputSource result; +// if (location != null) (cannot be null) + { + InputStream stream = ClassPathLoader.getLatest().getResourceAsStream(getClass(), location); + if (stream != null) { + result = new InputSource(stream); + } else { + throw new SAXNotRecognizedException(LocalizedStrings.ManagedEntityConfigXml_DTD_NOT_FOUND_0.toLocalizedString(location)); + } + +// } else { +// throw new SAXNotRecognizedException(LocalizedStrings.ManagedEntityConfigXml_COULD_NOT_FIND_DTD_FOR_0_1.toLocalizedString(new Object[] {publicId, systemId})); + } + + return result; + } + + /** + * Warnings are ignored + */ + public void warning(SAXParseException ex) throws SAXException { + + } + + /** + * Throws a {@link org.apache.geode.cache.CacheXmlException} + */ + public void error(SAXParseException ex) throws SAXException { + IllegalArgumentException ex2 = new IllegalArgumentException(LocalizedStrings.ManagedEntityConfigXml_ERROR_WHILE_PARSING_XML.toLocalizedString()); + ex2.initCause(ex); + throw ex2; + } + + /** + * Throws a {@link org.apache.geode.cache.CacheXmlException} + */ + public void fatalError(SAXParseException ex) throws SAXException { + IllegalArgumentException ex2 = new IllegalArgumentException(LocalizedStrings.ManagedEntityConfigXml_FATAL_ERROR_WHILE_PARSING_XML.toLocalizedString()); + ex2.initCause(ex); + throw ex2; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlGenerator.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlGenerator.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlGenerator.java new file mode 100644 index 0000000..b61adcd --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlGenerator.java @@ -0,0 +1,392 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.internal.Assert; +import org.apache.geode.internal.admin.api.AdminDistributedSystem; +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.CacheServer; +import org.apache.geode.internal.admin.api.CacheServerConfig; +import org.apache.geode.internal.admin.api.DistributedSystemConfig; +import org.apache.geode.internal.admin.api.DistributionLocator; +import org.apache.geode.internal.admin.api.DistributionLocatorConfig; +import org.apache.geode.internal.admin.api.ManagedEntityConfig; +import org.apache.geode.internal.i18n.LocalizedStrings; + +import javax.xml.transform.*; +//import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamResult; +import org.xml.sax.*; +//import org.xml.sax.ext.*; +import org.xml.sax.helpers.AttributesImpl; +import java.io.*; +import java.util.*; + +/** + * Generates XML data that represents the managed entities in an + * AdminDistributedSystem. This class is used mainly for + * testing. + * + * @since GemFire 4.0 + */ +public class ManagedEntityConfigXmlGenerator + extends ManagedEntityConfigXml implements XMLReader { + + /** An empty Attributes */ + private static Attributes EMPTY = new AttributesImpl(); + + ///////////////////////// Instance Fields //////////////////////// + + /** The AdminDistributedSystem for which we are + * generating XML */ + private AdminDistributedSystem system; + + /** The content handler to which SAX events are generated */ + private ContentHandler handler; + + ///////////////////////// Static Methods //////////////////////// + + /** + * Generates an XML representation of all of the managed entities in + * the given AdminDistributedSystem. + */ + public static void generate(AdminDistributedSystem system, + PrintWriter pw) { + (new ManagedEntityConfigXmlGenerator(system)).generate(pw); + } + + ///////////////////////// Constructors ////////////////////////// + + /** + * Creates a new generator for the given + * AdminDistributedSystem. + */ + private ManagedEntityConfigXmlGenerator(AdminDistributedSystem + system) { + this.system = system; + } + + /////////////////////// Instance Methods /////////////////////// + + /** + * Generates XML and writes it to the given PrintWriter + */ + private void generate(PrintWriter pw) { + // Use JAXP's transformation API to turn SAX events into pretty + // XML text + try { + Source src = new SAXSource(this, new InputSource()); + Result res = new StreamResult(pw); + + TransformerFactory xFactory = TransformerFactory.newInstance(); + Transformer xform = xFactory.newTransformer(); + xform.setOutputProperty(OutputKeys.METHOD, "xml"); + xform.setOutputProperty(OutputKeys.INDENT, "yes"); + xform.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, SYSTEM_ID); + xform.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, PUBLIC_ID); + xform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + xform.transform(src, res); + pw.flush(); + + } catch (Exception ex) { + RuntimeException ex2 = new RuntimeException(LocalizedStrings.ManagedEntityConfigXmlGenerator_EXCEPTION_THROWN_WHILE_GENERATING_XML.toLocalizedString()); + ex2.initCause(ex); + throw ex2; + } + } + + /** + * Called by the transformer to parse the "input source". We ignore + * the input source and, instead, generate SAX events to the {@link + * #setContentHandler ContentHandler}. + */ + public void parse(InputSource input) throws SAXException { + Assert.assertTrue(this.handler != null); + + handler.startDocument(); + + AttributesImpl atts = new AttributesImpl(); + + atts.addAttribute("", "", ID, "", + String.valueOf(this.system.getConfig().getSystemId())); + + handler.startElement("", DISTRIBUTED_SYSTEM, DISTRIBUTED_SYSTEM, atts); + + // Add generation methods here + try { + generateRemoteCommand(); + generateDiscovery(); + generateSSL(); + generateCacheServers(); + + } catch (AdminException ex) { + throw new SAXException(LocalizedStrings.ManagedEntityConfigXmlGenerator_AN_ADMINEXCEPTION_WAS_THROWN_WHILE_GENERATING_XML.toLocalizedString(), ex); + } + + handler.endElement("", DISTRIBUTED_SYSTEM, DISTRIBUTED_SYSTEM); + handler.endDocument(); + } + + /** + * Generates XML for the remote command + */ + private void generateRemoteCommand() throws SAXException { + String remoteCommand = this.system.getRemoteCommand(); + + handler.startElement("", REMOTE_COMMAND, REMOTE_COMMAND, EMPTY); + + handler.characters(remoteCommand.toCharArray(), 0, + remoteCommand.length()); + + handler.endElement("", REMOTE_COMMAND, REMOTE_COMMAND); + } + + /** + * Generates XML for locators in the distributed system + */ + private void generateDiscovery() throws SAXException { + handler.startElement("", LOCATORS, LOCATORS, EMPTY); + + generateLocators(); + + handler.endElement("", LOCATORS, LOCATORS); + } + + /** + * Generates XML for the distributed system's locators + */ + private void generateLocators() throws SAXException { + DistributionLocator[] locators = + this.system.getDistributionLocators(); + for (int i = 0; i < locators.length; i++) { + generateLocator(locators[i].getConfig()); + } + } + + /** + * Generates XML for a locator + */ + private void generateLocator(DistributionLocatorConfig config) + throws SAXException { + + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute("", "", PORT, "", + String.valueOf(config.getPort())); + + handler.startElement("", LOCATOR, LOCATOR, atts); + + generateEntityConfig(config); + + handler.endElement("", LOCATOR, LOCATOR); + } + + /** + * Generates XML for attributes common to all managed entities. + */ + private void generateEntityConfig(ManagedEntityConfig config) + throws SAXException { + + String host = config.getHost(); + if (host != null) { + handler.startElement("", HOST, HOST, EMPTY); + handler.characters(host.toCharArray(), 0, host.length()); + handler.endElement("", HOST, HOST); + } + + String remoteCommand = config.getRemoteCommand(); + if (remoteCommand != null) { + handler.startElement("", REMOTE_COMMAND, REMOTE_COMMAND, EMPTY); + handler.characters(remoteCommand.toCharArray(), 0, + remoteCommand.length()); + handler.endElement("", REMOTE_COMMAND, REMOTE_COMMAND); + } + + String workingDirectory = config.getWorkingDirectory(); + if (workingDirectory != null) { + handler.startElement("", WORKING_DIRECTORY, WORKING_DIRECTORY, EMPTY); + handler.characters(workingDirectory.toCharArray(), 0, + workingDirectory.length()); + handler.endElement("", WORKING_DIRECTORY, WORKING_DIRECTORY); + } + + String productDirectory = config.getProductDirectory(); + if (productDirectory != null) { + handler.startElement("", PRODUCT_DIRECTORY, PRODUCT_DIRECTORY, EMPTY); + handler.characters(productDirectory.toCharArray(), 0, + productDirectory.length()); + handler.endElement("", PRODUCT_DIRECTORY, PRODUCT_DIRECTORY); + } + } + + /** + * Generates XML for the SSL configuration of the distributed + * system. + */ + private void generateSSL() throws SAXException { + DistributedSystemConfig config = this.system.getConfig(); + + boolean sslEnabled = config.isSSLEnabled(); + if (!sslEnabled) { + return; + } + + AttributesImpl atts = new AttributesImpl(); + atts.addAttribute("", "", AUTHENTICATION_REQUIRED, "", + String.valueOf(config.isSSLAuthenticationRequired())); + + handler.startElement("", SSL, SSL, atts); + + String protocols = config.getSSLProtocols(); + if (protocols != null) { + handler.startElement("", PROTOCOLS, PROTOCOLS, EMPTY); + handler.characters(protocols.toCharArray(), 0, + protocols.length()); + handler.endElement("", PROTOCOLS, PROTOCOLS); + } + + String ciphers = config.getSSLCiphers(); + if (ciphers != null) { + handler.startElement("", CIPHERS, CIPHERS, EMPTY); + handler.characters(ciphers.toCharArray(), 0, + ciphers.length()); + handler.endElement("", CIPHERS, CIPHERS); + } + + Properties sslProps = config.getSSLProperties(); + for (Iterator iter = sslProps.entrySet().iterator(); + iter.hasNext(); ) { + Map.Entry entry = (Map.Entry) iter.next(); + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + + handler.startElement("", PROPERTY, PROPERTY, EMPTY); + + handler.startElement("", KEY, KEY, EMPTY); + handler.characters(key.toCharArray(), 0, key.length()); + handler.endElement("", KEY, KEY); + + handler.startElement("", VALUE, VALUE, EMPTY); + handler.characters(value.toCharArray(), 0, value.length()); + handler.endElement("", VALUE, VALUE); + + handler.endElement("", PROPERTY, PROPERTY); + } + + handler.endElement("", SSL, SSL); + } + + /** + * Generates an XML representation of the + * CacheServers in the distributed system. + */ + private void generateCacheServers() + throws SAXException, AdminException { + + CacheServer[] servers = this.system.getCacheServers(); + for (int i = 0; i < servers.length; i++) { + generateCacheServer(servers[i].getConfig()); + } + } + + /** + * Generates an XML representation of a + * CacheServerConfig. + */ + private void generateCacheServer(CacheServerConfig config) + throws SAXException { + + handler.startElement("", CACHE_SERVER, CACHE_SERVER, EMPTY); + + generateEntityConfig(config); + + String classpath = config.getClassPath(); + if (classpath != null) { + handler.startElement("", CLASSPATH, CLASSPATH, EMPTY); + handler.characters(classpath.toCharArray(), 0, + classpath.length()); + handler.endElement("", CLASSPATH, CLASSPATH); + } + + handler.endElement("", CACHE_SERVER, CACHE_SERVER); + } + + /** + * Keep track of the content handler for use during {@link #parse(String)}. + */ + public void setContentHandler(ContentHandler handler) { + this.handler = handler; + } + + public ContentHandler getContentHandler() { + return this.handler; + } + + public ErrorHandler getErrorHandler() { + return this; + } + + ////////// Inherited methods that don't do anything ////////// + + public boolean getFeature(String name) + throws SAXNotRecognizedException, SAXNotSupportedException { + return false; + } + + public void setFeature(String name, boolean value) + throws SAXNotRecognizedException, SAXNotSupportedException { + + } + + public Object getProperty(String name) + throws SAXNotRecognizedException, SAXNotSupportedException { + + return null; + } + + public void setProperty(String name, Object value) + throws SAXNotRecognizedException, SAXNotSupportedException { + + } + + public void setEntityResolver(EntityResolver resolver) { + + } + + public EntityResolver getEntityResolver() { + return this; + } + + public void setDTDHandler(DTDHandler handler) { + + } + + public DTDHandler getDTDHandler() { + return null; + } + + public void setErrorHandler(ErrorHandler handler) { + + } + + public void parse(String systemId) + throws IOException, SAXException { + + } + + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlParser.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlParser.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlParser.java new file mode 100644 index 0000000..4814d4d --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityConfigXmlParser.java @@ -0,0 +1,626 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.internal.Assert; +import org.apache.geode.internal.admin.api.AdminXmlException; +import org.apache.geode.internal.admin.api.CacheServerConfig; +import org.apache.geode.internal.admin.api.DistributedSystemConfig; +import org.apache.geode.internal.admin.api.DistributionLocatorConfig; +import org.apache.geode.internal.admin.api.ManagedEntityConfig; +import org.apache.geode.internal.i18n.LocalizedStrings; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; +import java.io.*; +import java.util.*; + +/** + * Parses an XML file and configures a {@link DistributedSystemConfig} + * from it. + * + * @since GemFire 4.0 + */ +public class ManagedEntityConfigXmlParser + extends ManagedEntityConfigXml implements ContentHandler { + + /** The DistributedSystemConfig to be configured */ + private DistributedSystemConfig config; + + /** The stack of intermediate values used while parsing */ + private Stack stack = new Stack(); + + ////////////////////// Static Methods ////////////////////// + + /** + * Parses XML data and from it configures a + * DistributedSystemConfig. + * + * @throws AdminXmlException + * If an error is encountered while parsing the XML + */ + public static void parse(InputStream is, + DistributedSystemConfig config) { + ManagedEntityConfigXmlParser handler = + new ManagedEntityConfigXmlParser(); + handler.config = config; + + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(true); + SAXParser parser = factory.newSAXParser(); + parser.parse(is, new DefaultHandlerDelegate(handler)); + + } catch (Exception ex) { + if (ex instanceof AdminXmlException) { + throw (AdminXmlException) ex; + + } else if (ex.getCause() instanceof AdminXmlException) { + throw (AdminXmlException) ex.getCause(); + + } else if (ex instanceof SAXException) { + // Silly JDK 1.4.2 XML parser wraps RunTime exceptions in a + // SAXException. Pshaw! + + SAXException sax = (SAXException) ex; + Exception cause = sax.getException(); + if (cause instanceof AdminXmlException) { + throw (AdminXmlException) cause; + } + } + + throw new AdminXmlException(LocalizedStrings.ManagedEntityConfigXmlParser_WHILE_PARSING_XML.toLocalizedString(), ex); + } + } + + /** + * Helper method for parsing an integer + * + * @throws org.apache.geode.cache.CacheXmlException + * If s is a malformed integer + */ + private static int parseInt(String s) { + try { + return Integer.parseInt(s); + + } catch (NumberFormatException ex) { + throw new AdminXmlException(LocalizedStrings.ManagedEntityConfigXmlParser_MALFORMED_INTEGER_0.toLocalizedString(s), ex); + } + } + + ////////////////////// Instance Methods ////////////////////// + +// if (this.system.isMcastEnabled()) { +// generateMulticast(); +// } + + public void startElement(String namespaceURI, String localName, + String qName, Attributes atts) + throws SAXException { + + if (qName.equals(DISTRIBUTED_SYSTEM)) { + startDistributedSystem(atts); + + } else if (qName.equals(REMOTE_COMMAND)) { + startRemoteCommand(atts); + + } else if (qName.equals(LOCATORS)) { + startLocators(atts); + + } else if (qName.equals(MULTICAST)) { + startMulticast(atts); + + } else if (qName.equals(LOCATOR)) { + startLocator(atts); + + } else if (qName.equals(HOST)) { + startHost(atts); + + } else if (qName.equals(WORKING_DIRECTORY)) { + startWorkingDirectory(atts); + + } else if (qName.equals(PRODUCT_DIRECTORY)) { + startProductDirectory(atts); + + } else if (qName.equals(SSL)) { + startSSL(atts); + + } else if (qName.equals(PROTOCOLS)) { + startProtocols(atts); + + } else if (qName.equals(CIPHERS)) { + startCiphers(atts); + + } else if (qName.equals(PROPERTY)) { + startProperty(atts); + + } else if (qName.equals(KEY)) { + startKey(atts); + + } else if (qName.equals(VALUE)) { + startValue(atts); + + } else if (qName.equals(CACHE_SERVER)) { + startCacheServer(atts); + + } else if (qName.equals(CLASSPATH)) { + startClassPath(atts); + + } else { + throw new AdminXmlException(LocalizedStrings.ManagedEntityConfigXmlParser_UNKNOWN_XML_ELEMENT_0.toLocalizedString(qName)); + } + } + + public void endElement(String namespaceURI, String localName, + String qName) + throws SAXException { + + if (qName.equals(DISTRIBUTED_SYSTEM)) { + endDistributedSystem(); + + } else if (qName.equals(REMOTE_COMMAND)) { + endRemoteCommand(); + + } else if (qName.equals(LOCATORS)) { + endLocators(); + + } else if (qName.equals(MULTICAST)) { + endMulticast(); + + } else if (qName.equals(LOCATOR)) { + endLocator(); + + } else if (qName.equals(HOST)) { + endHost(); + + } else if (qName.equals(WORKING_DIRECTORY)) { + endWorkingDirectory(); + + } else if (qName.equals(PRODUCT_DIRECTORY)) { + endProductDirectory(); + + } else if (qName.equals(SSL)) { + endSSL(); + + } else if (qName.equals(PROTOCOLS)) { + endProtocols(); + + } else if (qName.equals(CIPHERS)) { + endCiphers(); + + } else if (qName.equals(PROPERTY)) { + endProperty(); + + } else if (qName.equals(KEY)) { + endKey(); + + } else if (qName.equals(VALUE)) { + endValue(); + + } else if (qName.equals(CACHE_SERVER)) { + endCacheServer(); + + } else if (qName.equals(CLASSPATH)) { + endClassPath(); + + } else { + throw new AdminXmlException(LocalizedStrings.ManagedEntityConfigXmlParser_UNKNOWN_XML_ELEMENT_0.toLocalizedString(qName)); + } + } + + /** + * When a distributed-system element is encountered, we + * push the DistributedSystemConfig on the stack. + */ + private void startDistributedSystem(Attributes atts) { + Assert.assertTrue(stack.isEmpty()); + + String id = atts.getValue(ID); + if (id != null) { + this.config.setSystemId(id); + } + + String disable_tcp = atts.getValue(DISABLE_TCP); + if (disable_tcp != null) { + this.config.setDisableTcp(DISABLE_TCP.equalsIgnoreCase("true")); + } + + stack.push(this.config); + } + + /** + * When a distributed-system element is finished + */ + private void endDistributedSystem() { + + } + + /** + * When a multicast is first encountered, get the + * DistributedSystemConfig off of the top of the stack + * and set its multicast config appropriately. + */ + private void startMulticast(Attributes atts) { + DistributedSystemConfig config = + (DistributedSystemConfig) stack.peek(); + + String port = atts.getValue(PORT); + config.setMcastPort(parseInt(port)); + + String address = atts.getValue(ADDRESS); + if (address != null) { + config.setMcastAddress(address); + } + } + + private void endMulticast() { + + } + + /** + * Starts a remote-command element. The item on top of + * the stack may be a DistributedSystemConfig or it + * might be a ManagedEntityConfig. + */ + private void startRemoteCommand(Attributes atts) { + + } + + /** + * Ends a remote-command element. Pop the command off + * the top of the stack and set it on the + * DistributedSystemConfig or it might be a + * ManagedEntityConfig on top of the stack. + */ + private void endRemoteCommand() { + String remoteCommand = popString(); + Object top = stack.peek(); + Assert.assertTrue(top != null); + + if (top instanceof DistributedSystemConfig) { + ((DistributedSystemConfig) top).setRemoteCommand(remoteCommand); + + } else if (top instanceof ManagedEntityConfig) { + ((ManagedEntityConfig) top).setRemoteCommand(remoteCommand); + + } else { + String s = "Did not expect a " + top.getClass().getName() + + " on top of the stack"; + Assert.assertTrue(false, s); + } + } + + private void startLocators(Attributes atts) { + + } + + private void endLocators() { + + } + + private void startLocator(Attributes atts) { + String port = atts.getValue(PORT); + + DistributedSystemConfig system = + (DistributedSystemConfig) stack.peek(); + system.setMcastPort(0); + + DistributionLocatorConfig config = + system.createDistributionLocatorConfig(); + + config.setPort(parseInt(port)); + + stack.push(config); + } + + private void endLocator() { + Object o = stack.pop(); + Assert.assertTrue(o instanceof DistributionLocatorConfig); + } + + private void startHost(Attributes atts) { + + } + + /** + * We assume that there is a ManagedEntityConfig on top + * of the stack. + */ + private void endHost() { + String host = popString(); + ManagedEntityConfig config = (ManagedEntityConfig) stack.peek(); + config.setHost(host); + } + + private void startWorkingDirectory(Attributes atts) { + + } + + private void endWorkingDirectory() { + String workingDirectory = popString(); + ManagedEntityConfig config = (ManagedEntityConfig) stack.peek(); + config.setWorkingDirectory(workingDirectory); + } + + private void startProductDirectory(Attributes atts) { + + } + + private void endProductDirectory() { + String productDirectory = popString(); + ManagedEntityConfig config = (ManagedEntityConfig) stack.peek(); + config.setProductDirectory(productDirectory); + } + + private void startSSL(Attributes atts) { + DistributedSystemConfig config = + (DistributedSystemConfig) stack.peek(); + config.setSSLEnabled(true); + + String authenticationRequired = + atts.getValue(AUTHENTICATION_REQUIRED); + config.setSSLAuthenticationRequired(Boolean.valueOf(authenticationRequired).booleanValue()); + } + + private void endSSL() { + + } + + private void startProtocols(Attributes atts) { + + } + + private void endProtocols() { + String protocols = popString(); + DistributedSystemConfig config = + (DistributedSystemConfig) stack.peek(); + config.setSSLProtocols(protocols); + } + + private void startCiphers(Attributes atts) { + + } + + private void endCiphers() { + String ciphers = popString(); + DistributedSystemConfig config = + (DistributedSystemConfig) stack.peek(); + config.setSSLCiphers(ciphers); + } + + private void startProperty(Attributes atts) { + + } + + private void endProperty() { + String value = popString(); + String key = popString(); + DistributedSystemConfig config = + (DistributedSystemConfig) stack.peek(); + config.addSSLProperty(key, value); + } + + private void startKey(Attributes atts) { + + } + + private void endKey() { + String key = popString(); + stack.push(key); + } + + private void startValue(Attributes atts) { + + } + + private void endValue() { + String value = popString(); + stack.push(value); + } + + private void startCacheServer(Attributes atts) { + DistributedSystemConfig config = + (DistributedSystemConfig) stack.peek(); + CacheServerConfig server = + config.createCacheServerConfig(); + stack.push(server); + } + + private void endCacheServer() { + /* CacheServerConfig server = (CacheServerConfig) */ stack.pop(); + } + + private void startClassPath(Attributes atts) { + + } + + private void endClassPath() { + String classpath = popString(); + CacheServerConfig server = (CacheServerConfig) stack.peek(); + server.setClassPath(classpath); + } + + /** + * Pops a String off of the stack. + */ + private String popString() { + Object o = stack.pop(); + + if (o instanceof StringBuffer) { + StringBuffer sb = (StringBuffer) o; + return sb.toString(); + + } else { + return (String) o; + } + } + + /** + * Long strings in XML files may generate multiple + * characters callbacks. Coalesce multiple callbacks + * into one big string by using a StringBuffer. See + * bug 32122. + */ + public void characters(char[] ch, int start, int length) + throws SAXException { + + Object top = stack.peek(); + + StringBuffer sb; + if (top instanceof StringBuffer) { + sb = (StringBuffer) top; + + } else { + sb = new StringBuffer(); + stack.push(sb); + } + + sb.append(ch, start, length); + } + + ////////// Inherited methods that don't do anything ////////// + + public void setDocumentLocator(Locator locator) { } + + public void startDocument() throws SAXException { } + + public void endDocument() throws SAXException { } + + public void startPrefixMapping(String prefix, String uri) + throws SAXException { } + + public void endPrefixMapping(String prefix) + throws SAXException { } + + public void ignorableWhitespace(char[] ch, int start, int length) + throws SAXException { } + + public void processingInstruction(String target, String data) + throws SAXException { } + + public void skippedEntity(String name) throws SAXException { } + + /////////////////////// Inner Classes /////////////////////// + + /** + * Class that delegates all of the methods of a {@link + * DefaultHandler} to a {@link ManagedEntityConfigXmlParser} that + * implements all of the methods of DefaultHandler, but + * is not a DefaultHandler. + */ + static class DefaultHandlerDelegate extends DefaultHandler { + /** The ManagedEntityConfigXmlParser that does the + * real work */ + private ManagedEntityConfigXmlParser handler; + + /** + * Creates a new DefaultHandlerDelegate that + * delegates to the given + * ManagedEntityConfigXmlParser. + */ + public DefaultHandlerDelegate(ManagedEntityConfigXmlParser handler) { + this.handler = handler; + } + + @Override + public InputSource resolveEntity(String publicId, + String systemId) + throws SAXException { + return handler.resolveEntity(publicId, systemId); + } + + @Override + public void setDocumentLocator(Locator locator) { + handler.setDocumentLocator(locator); + } + + @Override + public void startDocument() throws SAXException { + handler.startDocument(); + } + + @Override + public void endDocument() throws SAXException { + handler.endDocument(); + } + + @Override + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + handler.startPrefixMapping(prefix, uri); + } + + @Override + public void endPrefixMapping(String prefix) throws SAXException { + handler.endPrefixMapping(prefix); + } + + @Override + public void startElement(String uri, String localName, + String qName, Attributes attributes) + throws SAXException { + handler.startElement(uri, localName, qName, attributes); + } + + @Override + public void endElement(String uri, String localName, String qName) + throws SAXException { + handler.endElement(uri, localName, qName); + } + + @Override + public void characters(char[] ch, int start, int length) + throws SAXException { + handler.characters(ch, start, length); + } + + @Override + public void ignorableWhitespace(char[] ch, int start, int length) + throws SAXException { + handler.ignorableWhitespace(ch, start, length); + } + + @Override + public void processingInstruction(String target, String data) + throws SAXException { + handler.processingInstruction(target, data); + } + + @Override + public void skippedEntity(String name) throws SAXException { + handler.skippedEntity(name); + } + + @Override + public void warning(SAXParseException e) throws SAXException { + handler.warning(e); + } + + @Override + public void error(SAXParseException e) throws SAXException { + handler.error(e); + } + + @Override + public void fatalError(SAXParseException e) throws SAXException { + handler.fatalError(e); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityController.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityController.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityController.java new file mode 100644 index 0000000..da4c0db --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityController.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.internal.admin.api.DistributedSystemConfig; +import org.apache.geode.internal.admin.api.ManagedEntity; +import org.apache.geode.internal.admin.api.ManagedEntityConfig; + +/** + * Defines the actual administration (starting, stopping, etc.) of + * GemFire {@link ManagedEntity}s. + * + */ +interface ManagedEntityController { + /** + * Starts a managed entity. + */ + public void start(final InternalManagedEntity entity); + + /** + * Stops a managed entity. + */ + public void stop(final InternalManagedEntity entity); + + /** + * Returns whether or not a managed entity is running + */ + public boolean isRunning(InternalManagedEntity entity); + + /** + * Returns the contents of a locator's log file. Other APIs are + * used to get the log file of managed entities that are also system + * members. + */ + public String getLog(DistributionLocatorImpl locator); + + /** + * Returns the full path to the executable in + * $GEMFIRE/bin taking into account the {@linkplain + * ManagedEntityConfig#getProductDirectory product directory} and the + * platform's file separator. + * + *

+ * + * Note: we should probably do a better job of determine whether or + * not the machine on which the entity runs is Windows or Linux. + * + * @param executable + * The name of the executable that resides in + * $GEMFIRE/bin. + */ + public String getProductExecutable(InternalManagedEntity entity, String executable); + + /** + * Builds optional SSL command-line arguments. Returns null if SSL is not + * enabled for the distributed system. + */ + public String buildSSLArguments(DistributedSystemConfig config); +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityControllerFactory.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityControllerFactory.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityControllerFactory.java new file mode 100755 index 0000000..1663c1e --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedEntityControllerFactory.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.logging.log4j.Logger; + +import org.apache.geode.internal.admin.api.AdminDistributedSystem; +import org.apache.geode.internal.admin.api.ManagedEntity; +import org.apache.geode.internal.ClassPathLoader; +import org.apache.geode.internal.logging.LogService; +import org.apache.geode.internal.logging.log4j.LogMarker; + +/** + * Creates ManagedEntityController for administration (starting, stopping, etc.) + * of GemFire {@link ManagedEntity}s. + * + */ +public class ManagedEntityControllerFactory { + + private static final Logger logger = LogService.getLogger(); + + private static final String ENABLED_MANAGED_ENTITY_CONTROLLER_CLASS_NAME = "EnabledManagedEntityController"; + + static ManagedEntityController createManagedEntityController(final AdminDistributedSystem system) { + if (isEnabledManagedEntityController()) { + logger.info(LogMarker.CONFIG, "Local and remote OS command invocations are enabled for the Admin API."); + return createEnabledManagedEntityController(system); + } else { + logger.info(LogMarker.CONFIG, "Local and remote OS command invocations are disabled for the Admin API."); + return new DisabledManagedEntityController(); + } + } + + public static boolean isEnabledManagedEntityController() { + try { + ClassPathLoader.getLatest().forName(ENABLED_MANAGED_ENTITY_CONTROLLER_CLASS_NAME); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + private static ManagedEntityController createEnabledManagedEntityController(final AdminDistributedSystem system) { + return new EnabledManagedEntityController(system); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedSystemMemberImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedSystemMemberImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedSystemMemberImpl.java new file mode 100644 index 0000000..3dbe385 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/ManagedSystemMemberImpl.java @@ -0,0 +1,271 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.ConfigurationParameter; +import org.apache.geode.internal.admin.api.ManagedEntityConfig; +import org.apache.geode.internal.admin.GemFireVM; + +import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; + +/** + * A SystemMember that is also managed (or manageable) by + * the admin API. + * + * This class must be public so that its methods can be invoked + * reflectively (for MBean operations) on instances of its + * subclasses. + * + * @since GemFire 4.0 + */ +public abstract class ManagedSystemMemberImpl extends SystemMemberImpl + implements InternalManagedEntity { + + /** Controller for starting and stopping local or remote managers */ + protected ManagedEntityController controller; + + /** The state of this managed entity (see bug 32455) */ + private int state = UNKNOWN; + + /** A lock that is obtained while this entity's state changes */ + private final Object stateChange = new Object(); + + ////////////////////// Constructors ////////////////////// + + /** + * Creates a new ManagedSystemMemberImpl that + * represents an existing member of an + * AdminDistributedSystem. + */ + protected ManagedSystemMemberImpl(AdminDistributedSystemImpl system, + GemFireVM vm) + throws AdminException { + + super(system, vm); + this.controller = system.getEntityController(); + } + + /** + * Creates a new ManagedSystemMemberImpl that + * represents a non-existing member with the given + * ManagedEntityConfig that has not yet been started. + */ + protected ManagedSystemMemberImpl(AdminDistributedSystemImpl system, + ManagedEntityConfig config) + throws AdminException { + + super(system); + this.internalId = null; + this.id = getNewId(); + this.host = config.getHost(); + this.name = this.id; + this.controller = system.getEntityController(); + } + + ////////////////////// Instance Methods ////////////////////// + + public String getWorkingDirectory() { + return this.getEntityConfig().getWorkingDirectory(); + } + + public void setWorkingDirectory(String workingDirectory) { + this.getEntityConfig().setWorkingDirectory(workingDirectory); + } + + public String getProductDirectory() { + return this.getEntityConfig().getProductDirectory(); + } + + public void setProductDirectory(String productDirectory) { + this.getEntityConfig().setProductDirectory(productDirectory); + } + + @Override + public String getHost() { + return this.getEntityConfig().getHost(); + } + + public int setState(int state) { + if (this.stateChange == null) { + // The initial state is set in the constructor before + // stateChange is initialized. + int oldState = this.state; + this.state = state; + return oldState; + + } else { + synchronized (this.stateChange) { + int oldState = this.state; + this.state = state; + + this.stateChange.notifyAll(); + + return oldState; + } + } + } + + /** + * Returns whether or not this managed system member needs to be + * stopped. If this member is stopped or is stopping, then it does + * not need to be stopped. Otherwise, it will atomically place this + * member in the {@link #STOPPING} state. See bug 32455. + */ + protected boolean needToStop() { + synchronized (this.stateChange) { + if (this.state == STOPPED || this.state == STOPPING) { + return false; + + } else { + setState(STOPPING); + return true; + } + } + } + + /** + * Returns whether or not this managed system member needs to be + * started. If this member is started or is starting, then it + * does not need to be started. Otherwise, it will atomically + * place this member in the {@link #STARTING} state. See bug + * 32455. + */ + protected boolean needToStart() { + synchronized (this.stateChange) { + if (this.state == RUNNING || this.state == STARTING) { + return false; + + } else { + setState(STARTING); + return true; + } + } + } + + /** + * Sets the state of this managed system member depending on whether + * or not vm is null. + */ + @Override + void setGemFireVM(GemFireVM vm) throws AdminException { + super.setGemFireVM(vm); + if (vm != null) { + this.setState(RUNNING); + + } else { + this.setState(STOPPED); + } + } + + /** + * Waits until this system member's "state" is {@link #RUNNING}. + */ + public boolean waitToStart(long timeout) + throws InterruptedException { + + if (Thread.interrupted()) throw new InterruptedException(); + + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < timeout) { + synchronized (this.stateChange) { + if (this.state == RUNNING) { + break; + + } else { + this.stateChange.wait(System.currentTimeMillis() - start); + } + } + } + + synchronized (this.stateChange) { + return this.state == RUNNING; + } + } + + /** + * Waits until this system member's "state" is {@link #STOPPED}. + */ + public boolean waitToStop(long timeout) + throws InterruptedException { + + if (Thread.interrupted()) throw new InterruptedException(); + long start = System.currentTimeMillis(); + while (System.currentTimeMillis() - start < timeout) { + synchronized (this.stateChange) { + if (this.state == STOPPED) { + break; + + } else { + this.stateChange.wait(System.currentTimeMillis() - start); + } + } + } + + synchronized (this.stateChange) { + return this.state == STOPPED; + } + } + + /** + * Appends configuration information to a StringBuffer + * that contains a command line. Handles certain configuration + * parameters specially. + */ + protected void appendConfiguration(StringBuffer sb) { + ConfigurationParameter[] params = this.getConfiguration(); + for (int i = 0; i < params.length; i++) { + ConfigurationParameter param = params[i]; + + if (!param.isModifiable()) { + continue; + } + + String name = param.getName(); + String value = param.getValueAsString(); + + if (value != null && !value.equals("")) { + if (name.equals(LOCATORS)) { + // Use the new locator syntax so that is plays nicely with + // rsh. See bug 32306. + String locator = value; + int firstBracket = locator.indexOf('['); + int lastBracket = locator.indexOf(']'); + + if (firstBracket > -1 && lastBracket > -1) { + String host = locator.substring(0, firstBracket); + String port = + locator.substring(firstBracket + 1, lastBracket); + locator = host + ":" + port; + } + + sb.append(" "); + sb.append(name); + sb.append("="); + sb.append(locator); + + } else { + sb.append(" "); + sb.append(name); + sb.append("="); + sb.append(value); + } + } + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthConfigImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthConfigImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthConfigImpl.java new file mode 100644 index 0000000..a0c932b --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthConfigImpl.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.internal.admin.api.MemberHealthConfig; + +// @todo Make this class (and all of its subclasses) {@link java.io.Externalizable} or +// {@link org.apache.geode.DataSerializable}. +/** + * The implementation of MemberHealthConfig + * + * + * @since GemFire 3.5 + */ +public abstract class MemberHealthConfigImpl + implements MemberHealthConfig, java.io.Serializable { + + private static final long serialVersionUID = 3966032573073580490L; + + /** The maximum process size (in megabytes) of a healthy member of + * the distributed system. */ + private long maxVMProcessSize = DEFAULT_MAX_VM_PROCESS_SIZE; + + /** The maximum number of enqueued incoming or outgoing + * messages that a healthy member of a distributed system can + * have. */ + private long maxMessageQueueSize = DEFAULT_MAX_MESSAGE_QUEUE_SIZE; + + /** The maximum number message replies that can timeout in a healthy + * member. */ + private long maxReplyTimeouts = DEFAULT_MAX_REPLY_TIMEOUTS; + + /** The maximum multicast retransmit / multicast message count ratio + */ + private double maxRetransmissionRatio = DEFAULT_MAX_RETRANSMISSION_RATIO; + + + /////////////////////// Constructors /////////////////////// + + /** + * Creates a new MemberHealthConfigImpl with the + * default configuration. + */ + MemberHealthConfigImpl() { + + } + + ///////////////////// Instance Methods ////////////////////// + + public long getMaxVMProcessSize() { + return this.maxVMProcessSize; + } + + public void setMaxVMProcessSize(long size) { + this.maxVMProcessSize = size; + } + + public long getMaxMessageQueueSize() { + return this.maxMessageQueueSize; + } + + public void setMaxMessageQueueSize(long maxMessageQueueSize) { + this.maxMessageQueueSize = maxMessageQueueSize; + } + + public long getMaxReplyTimeouts() { + return this.maxReplyTimeouts; + } + + public void setMaxReplyTimeouts(long maxReplyTimeouts) { + this.maxReplyTimeouts = maxReplyTimeouts; + } + + public double getMaxRetransmissionRatio() { + return this.maxRetransmissionRatio; + } + + public void setMaxRetransmissionRatio(double ratio) { + this.maxRetransmissionRatio = ratio; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthEvaluator.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthEvaluator.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthEvaluator.java new file mode 100644 index 0000000..6ee6b62 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/MemberHealthEvaluator.java @@ -0,0 +1,243 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.CancelException; +import org.apache.geode.cache.CacheFactory; +import org.apache.geode.distributed.internal.*; +import org.apache.geode.internal.*; +import org.apache.geode.internal.admin.api.GemFireHealthConfig; +import org.apache.geode.internal.admin.api.MemberHealthConfig; +import org.apache.geode.internal.i18n.LocalizedStrings; +import org.apache.geode.internal.cache.CachePerfStats; +import org.apache.geode.internal.cache.GemFireCacheImpl; +import org.apache.geode.internal.statistics.GemFireStatSampler; +import org.apache.geode.internal.statistics.platform.ProcessStats; + +import java.util.*; + +/** + * Contains the logic for evaluating the health of a GemFire + * distributed system member according to the thresholds provided in a + * {@link MemberHealthConfig}. + * + * @see VMStats + * @see ProcessStats + * @see DMStats + * + * + * @since GemFire 3.5 + */ +/** + * + */ +class MemberHealthEvaluator extends AbstractHealthEvaluator { + + /** The config from which we get the evaluation criteria */ + private MemberHealthConfig config; + + /** The description of the member being evaluated */ + private String description; + +// /** Statistics about this VM (may be null) */ +// private VMStatsContract vmStats; + + /** Statistics about this process (may be null) */ + private ProcessStats processStats; + + /** Statistics about the distribution manager */ + private DMStats dmStats; + + /** The previous value of the reply timeouts stat */ + private long prevReplyTimeouts; + + ////////////////////// Constructors ////////////////////// + + /** + * Creates a new MemberHealthEvaluator + */ + MemberHealthEvaluator(GemFireHealthConfig config, + DM dm) { + super(config, dm); + + this.config = config; + InternalDistributedSystem system = dm.getSystem(); + + GemFireStatSampler sampler = system.getStatSampler(); + if (sampler != null) { + // Sampling is enabled +// this.vmStats = sampler.getVMStats(); + this.processStats = sampler.getProcessStats(); + } + + this.dmStats = dm.getStats(); + + StringBuffer sb = new StringBuffer(); + sb.append("Application VM member "); + sb.append(dm.getId()); + int pid = OSProcess.getId(); + if (pid != 0) { + sb.append(" with pid "); + sb.append(pid); + } + this.description = sb.toString(); + } + + //////////////////// Instance Methods //////////////////// + + @Override + protected String getDescription() { + return this.description; + } + + /** + * Checks to make sure that the {@linkplain + * ProcessStats#getProcessSize VM's process size} is less than the + * {@linkplain MemberHealthConfig#getMaxVMProcessSize threshold}. + * If not, the status is "okay" health. + */ + void checkVMProcessSize(List status) { + // There is no need to check isFirstEvaluation() + if (this.processStats == null) { + return; + } + + long vmSize = this.processStats.getProcessSize(); + long threshold = this.config.getMaxVMProcessSize(); + if (vmSize > threshold) { + String s = LocalizedStrings.MemberHealthEvaluator_THE_SIZE_OF_THIS_VM_0_MEGABYTES_EXCEEDS_THE_THRESHOLD_1_MEGABYTES.toLocalizedString(new Object[] {Long.valueOf(vmSize), Long.valueOf(threshold)}); + status.add(okayHealth(s)); + } + } + + /** + * Checks to make sure that the size of the distribution manager's + * {@linkplain DMStats#getOverflowQueueSize() overflow} message + * queue does not exceed the {@linkplain + * MemberHealthConfig#getMaxMessageQueueSize threshold}. If not, + * the status is "okay" health. + */ + void checkMessageQueueSize(List status) { + long threshold = this.config.getMaxMessageQueueSize(); + long overflowSize = this.dmStats.getOverflowQueueSize(); + if (overflowSize > threshold) { + String s = LocalizedStrings.MemberHealthEvaluator_THE_SIZE_OF_THE_OVERFLOW_QUEUE_0_EXCEEDS_THE_THRESHOLD_1.toLocalizedString(new Object[] { Long.valueOf(overflowSize), Long.valueOf(threshold)}); + status.add(okayHealth(s)); + } + } + + /** + * Checks to make sure that the number of {@linkplain + * DMStats#getReplyTimeouts reply timeouts} does not exceed the + * {@linkplain MemberHealthConfig#getMaxReplyTimeouts threshold}. + * If not, the status is "okay" health. + */ + void checkReplyTimeouts(List status) { + if (isFirstEvaluation()) { + return; + } + + long threshold = this.config.getMaxReplyTimeouts(); + long deltaReplyTimeouts = + this.dmStats.getReplyTimeouts() - prevReplyTimeouts; + if (deltaReplyTimeouts > threshold) { + String s = LocalizedStrings.MemberHealthEvaluator_THE_NUMBER_OF_MESSAGE_REPLY_TIMEOUTS_0_EXCEEDS_THE_THRESHOLD_1.toLocalizedString(new Object[] { Long.valueOf(deltaReplyTimeouts), Long.valueOf(threshold)}); + status.add(okayHealth(s)); + } + } + + /** + * See if the multicast retransmission ratio is okay + */ + void checkRetransmissionRatio(List status) { + double threshold = this.config.getMaxRetransmissionRatio(); + int mcastMessages = this.dmStats.getMcastWrites(); + if (mcastMessages > 100000) { // avoid initial state & int overflow + // the ratio we actually use here is (retransmit requests) / (mcast datagram writes) + // a single retransmit request may include multiple missed messages + double ratio = (this.dmStats.getMcastRetransmits() * 1.0) / + (this.dmStats.getMcastWrites() * 1.0); + if (ratio > threshold) { + String s = "The number of message retransmissions (" + + ratio + ") exceeds the threshold (" + threshold + ")"; + status.add(okayHealth(s)); + } + } + } + +/** + * The function keeps updating the health of the cache based on + * roles required by the regions and their reliablity policies. + * + * */ + + void checkCacheRequiredRolesMeet(List status){ + // will have to call here okeyHealth() or poorHealth() + //GemFireCache cache = (GemFireCache)CacheFactory.getAnyInstance(); + + //CachePerfStats cPStats= null; + try{ + GemFireCacheImpl cache = (GemFireCacheImpl)CacheFactory.getAnyInstance(); + CachePerfStats cPStats= null; + cPStats= cache.getCachePerfStats(); + + if(cPStats.getReliableRegionsMissingFullAccess()> 0){ + // health is okay. + int numRegions = cPStats.getReliableRegionsMissingFullAccess(); + status.add(okayHealth(LocalizedStrings.MemberHealthEvaluator_THERE_ARE_0_REGIONS_MISSING_REQUIRED_ROLES_BUT_ARE_CONFIGURED_FOR_FULL_ACCESS.toLocalizedString(Integer.valueOf(numRegions)))); + }else if(cPStats.getReliableRegionsMissingLimitedAccess() > 0){ + // health is poor + int numRegions = cPStats.getReliableRegionsMissingLimitedAccess(); + status.add(poorHealth(LocalizedStrings.MemberHealthEvaluator_THERE_ARE_0_REGIONS_MISSING_REQUIRED_ROLES_AND_CONFIGURED_WITH_LIMITED_ACCESS.toLocalizedString(Integer.valueOf(numRegions)))); + }else if (cPStats.getReliableRegionsMissingNoAccess() > 0){ + // health is poor + int numRegions = cPStats.getReliableRegionsMissingNoAccess(); + status.add(poorHealth(LocalizedStrings.MemberHealthEvaluator_THERE_ARE_0_REGIONS_MISSING_REQUIRED_ROLES_AND_CONFIGURED_WITHOUT_ACCESS.toLocalizedString(Integer.valueOf(numRegions)))); + }//else{ + // health is good/okay + // status.add(okayHealth("All regions have there required roles meet")); + //} + } + catch (CancelException ignore) { + } + } + + + /** + * Updates the previous values of statistics + */ + private void updatePrevious() { + this.prevReplyTimeouts = this.dmStats.getReplyTimeouts(); + } + + @Override + protected void check(List status) { + checkVMProcessSize(status); + checkMessageQueueSize(status); + checkReplyTimeouts(status); + // will have to add another call to check for roles + // missing and reliablity attributed. + checkCacheRequiredRolesMeet(status); + + updatePrevious(); + } + + @Override + void close() { + + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupRequest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupRequest.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupRequest.java new file mode 100644 index 0000000..5f7e9ba --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupRequest.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.logging.log4j.Logger; + +import org.apache.geode.CancelException; +import org.apache.geode.cache.persistence.PersistentID; +import org.apache.geode.distributed.DistributedMember; +import org.apache.geode.distributed.internal.DM; +import org.apache.geode.distributed.internal.DistributionManager; +import org.apache.geode.distributed.internal.DistributionMessage; +import org.apache.geode.distributed.internal.ReplyException; +import org.apache.geode.internal.admin.remote.AdminFailureResponse; +import org.apache.geode.internal.admin.remote.AdminMultipleReplyProcessor; +import org.apache.geode.internal.admin.remote.AdminResponse; +import org.apache.geode.internal.admin.remote.CliLegacyMessage; +import org.apache.geode.internal.cache.GemFireCacheImpl; +import org.apache.geode.internal.cache.persistence.BackupManager; +import org.apache.geode.internal.i18n.LocalizedStrings; +import org.apache.geode.internal.logging.LogService; +import org.apache.geode.internal.logging.log4j.LocalizedMessage; + +/** + * A request to from an admin VM to all non admin members + * to start a backup. In the prepare phase of the backup, + * the members will suspend bucket destroys to make sure + * buckets aren't missed during the backup. + * + * + */ +public class PrepareBackupRequest extends CliLegacyMessage { + private static final Logger logger = LogService.getLogger(); + + public PrepareBackupRequest() { + + } + + public static Map> send(DM dm, Set recipients) { + PrepareBackupRequest request = new PrepareBackupRequest(); + request.setRecipients(recipients); + + PrepareBackupReplyProcessor replyProcessor = new PrepareBackupReplyProcessor(dm, recipients); + request.msgId = replyProcessor.getProcessorId(); + dm.putOutgoing(request); + try { + replyProcessor.waitForReplies(); + } catch (ReplyException e) { + if(!(e.getCause() instanceof CancelException)) { + throw e; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + AdminResponse response = request.createResponse((DistributionManager)dm); + response.setSender(dm.getDistributionManagerId()); + replyProcessor.process(response); + return replyProcessor.results; + } + + @Override + protected AdminResponse createResponse(DistributionManager dm) { + GemFireCacheImpl cache = GemFireCacheImpl.getInstance(); + HashSet persistentIds; + if(cache == null) { + persistentIds = new HashSet(); + } else { + try { + BackupManager manager = cache.startBackup(getSender()); + persistentIds = manager.prepareBackup(); + } catch(IOException e) { + logger.error(LocalizedMessage.create(LocalizedStrings.CliLegacyMessage_ERROR, this.getClass()), e); + return AdminFailureResponse.create(dm, getSender(), e); + } + } + + + return new PrepareBackupResponse(this.getSender(), persistentIds); + } + + public int getDSFID() { + return PREPARE_BACKUP_REQUEST; + } + + private static class PrepareBackupReplyProcessor extends AdminMultipleReplyProcessor { + Map> results = Collections.synchronizedMap(new HashMap>()); + public PrepareBackupReplyProcessor(DM dm, Collection initMembers) { + super(dm, initMembers); + } + + @Override + protected boolean stopBecauseOfExceptions() { + return false; + } + + @Override + protected void process(DistributionMessage msg, boolean warn) { + if(msg instanceof PrepareBackupResponse) { + final HashSet persistentIds = ((PrepareBackupResponse) msg).getPersistentIds(); + if(persistentIds != null && !persistentIds.isEmpty()) { + results.put(msg.getSender(), persistentIds); + } + } + super.process(msg, warn); + } + + + + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupResponse.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupResponse.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupResponse.java new file mode 100644 index 0000000..d8dd033 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/PrepareBackupResponse.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.HashSet; + +import org.apache.geode.DataSerializer; +import org.apache.geode.cache.persistence.PersistentID; +import org.apache.geode.distributed.internal.membership.InternalDistributedMember; +import org.apache.geode.internal.admin.remote.AdminResponse; + +/** + * The response to the {@link PrepareBackupRequest} + * + * + */ +public class PrepareBackupResponse extends AdminResponse { + + private HashSet persistentIds; + + public PrepareBackupResponse() { + super(); + } + + public PrepareBackupResponse(InternalDistributedMember sender, HashSet persistentIds) { + this.setRecipient(sender); + this.persistentIds = persistentIds; + } + + public HashSet getPersistentIds() { + return persistentIds; + } + + @Override + public void fromData(DataInput in) throws IOException, ClassNotFoundException { + super.fromData(in); + persistentIds = DataSerializer.readHashSet(in); + } + + + + @Override + public void toData(DataOutput out) throws IOException { + super.toData(out); + DataSerializer.writeHashSet(persistentIds, out); + } + + + + @Override + protected Object clone() throws CloneNotSupportedException { + // TODO Auto-generated method stub + return super.clone(); + } + + public int getDSFID() { + return PREPARE_BACKUP_RESPONSE; + } + + @Override + public String toString() { + return getClass().getName() + ": " + persistentIds; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticImpl.java new file mode 100755 index 0000000..6f28491 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticImpl.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.internal.admin.Stat; +import org.apache.geode.internal.admin.api.Statistic; + +/** + * Implementation of a single statistic in a StatisticResource + * + * @since GemFire 3.5 + * + */ +public class StatisticImpl +implements Statistic { + + private static final long serialVersionUID = 3899296873901634399L; + + private Stat internalStat; + + protected StatisticImpl() { + } + + protected StatisticImpl(Stat internalStat) { + this.internalStat = internalStat; + } + + /** + * @return the identifying name of this stat + */ + public String getName() { + return this.internalStat.getName(); + } + + /** + * @return the value of this stat as a java.lang.Number + */ + public Number getValue() { + return this.internalStat.getValue(); + } + + /** + * @return a display string for the unit of measurement (if any) this stat represents + */ + public String getUnits() { + return this.internalStat.getUnits(); + } + + /** + * @return true if this stat represents a numeric value which always increases + */ + public boolean isCounter() { + return this.internalStat.isCounter(); + } + + /** + * @return the full description of this stat + */ + public String getDescription() { + return this.internalStat.getDescription(); + } + + /** + * Sets the internal stat which allows us to reuse the wrapper object and + * handle refreshes along with isWriteable set to false on the attribute. + */ + protected void setStat(Stat internalStat) { + this.internalStat = internalStat; + } + + /** + * Returns a string representation of the object. + * + * @return a string representation of the object + */ + @Override + public String toString() { + return getName(); + } + +} + http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/096b622d/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticResourceImpl.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticResourceImpl.java b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticResourceImpl.java new file mode 100755 index 0000000..83e4c30 --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/internal/admin/api/impl/StatisticResourceImpl.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geode.internal.admin.api.impl; + +import org.apache.geode.internal.admin.api.AdminException; +import org.apache.geode.internal.admin.api.StatisticResource; +import org.apache.geode.internal.admin.api.SystemMember; +import org.apache.geode.internal.admin.api.Statistic; +import org.apache.geode.internal.Assert; +import org.apache.geode.internal.admin.Stat; +import org.apache.geode.internal.admin.StatResource; +import org.apache.geode.internal.i18n.LocalizedStrings; +//import org.apache.geode.internal.admin.SystemMember; + +import java.util.ArrayList; +//import java.util.Date; +import java.util.List; + +/** + * Provides monitoring of a statistic resource. + * + * @since GemFire 3.5 + */ +public class StatisticResourceImpl +implements StatisticResource { + + /** The underlying remote StatResource which this object delegates to */ + protected StatResource statResource; + /** Displayable name of this statistic resource */ + protected String name; + /** Description of this statistic resource */ + protected String description; + /** Classification type of this statistic resource */ + protected String type; + /** GemFire system member which owns this statistic resource */ + protected SystemMember member; + /** The array of statistics in this resource */ + protected Statistic[] statistics; // = new Statistic[0]; + + // ------------------------------------------------------------------------- + // Constructor(s) + // ------------------------------------------------------------------------- + + /** + * Constructs an instance of StatisticResourceImpl. + * + * @param statResource the admin StatResource to manage/monitor + * @param member the SystemMember owning this resource + * @exception AdminException + * if unable to create this StatisticResource for administration + */ + public StatisticResourceImpl(StatResource statResource, + SystemMember member) + throws AdminException { + this.statResource = statResource; + this.member = member; + this.name = this.statResource.getName(); + this.description = this.statResource.getDescription(); + this.type = this.statResource.getType(); + } + + // ------------------------------------------------------------------------- + // Attributes accessors and mutators + // ------------------------------------------------------------------------- + + public String getName() { + return this.name; + } + + public String getDescription() { + return this.description; + } + + public String getType() { + return this.type; + } + + public String getOwner() { + return this.member.toString(); + } + + public Statistic[] getStatistics() { + if (this.statistics == null) { + try { + refresh(); + } + catch (AdminException e) { + this.statistics = new Statistic[0]; + } + } + return this.statistics; + } + + public long getUniqueId() { + return this.statResource.getResourceUniqueID(); + } + + // ------------------------------------------------------------------------- + // Operations + // ------------------------------------------------------------------------- + + public void refresh() throws AdminException { + Stat[] stats = null; + if (this.statResource != null) { + stats = this.statResource.getStats(); + } + if (stats == null || stats.length < 1) { + throw new AdminException(LocalizedStrings.StatisticResourceImpl_FAILED_TO_REFRESH_STATISTICS_0_FOR_1.toLocalizedString(getType()+"-"+getName(), getOwner())); + } + + if (this.statistics == null || this.statistics.length < 1) { + // define new statistics instances... + List statList = new ArrayList(); + for (int i = 0; i < stats.length; i++) { + statList.add(createStatistic(stats[i])); + } + this.statistics = (Statistic[]) statList.toArray(new Statistic[0]); + } + else { + // update the existing instances... + for (int i = 0; i < stats.length; i++) { + updateStatistic(stats[i]); + } + } + } + + // ------------------------------------------------------------------------- + // Non-public implementation methods + // ------------------------------------------------------------------------- + + /** + * Updates the value of the {@link Statistic} corresponding to the internal + * {@link org.apache.geode.internal.admin.Stat} + * + * @param stat the internal stat to use in updating the matching statistic + */ + private void updateStatistic(Stat stat) { + for (int i = 0; i < this.statistics.length; i++) { + if (this.statistics[i].getName().equals(stat.getName())) { + ((StatisticImpl)this.statistics[i]).setStat(stat); + return; + } + } + Assert.assertTrue(false, "Unknown stat: " + stat.getName()); + } + + /** + * Creates a new {@link StatisticImpl} to represent the internal {@link + * org.apache.geode.internal.admin.Stat} + * + * @param stat the internal stat to wrap in a new statistic + */ + protected Statistic createStatistic(Stat stat) { + return new StatisticImpl(stat); + } + + /** + * Returns a string representation of the object. + * + * @return a string representation of the object + */ + @Override + public String toString() { + return getName(); + } + +} +