You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2016/10/26 22:11:38 UTC

[16/42] incubator-geode git commit: GEODE-288: move admin package to internal

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 <code>distributed-system</code> element. */
+  public static final String DISTRIBUTED_SYSTEM =
+    "distributed-system";
+
+  /** The name of the <code>id</code> attribute. */
+  public static final String ID = "id";
+
+  /** The name of the <code>disable-tcp</code> attribute. */
+  public static final String DISABLE_TCP = "disable-tcp";
+
+  /** The name of the <code>remote-command</code> element. */
+  public static final String REMOTE_COMMAND = "remote-command";
+
+  /** The name of the <code>locators</code> element. */
+  public static final String LOCATORS = ConfigurationProperties.LOCATORS;
+
+  /** The name of the <code>ssl</code> element. */
+  public static final String SSL = "ssl";
+
+  /** The name of the <code>cache-server</code> element */
+  public static final String CACHE_SERVER = "cache-server";
+
+  /** The name of the <code>multicast</code> element */
+  public static final String MULTICAST = "multicast";
+
+  /** The name of the <code>locator</code> element */
+  public static final String LOCATOR = "locator";
+
+  /** The name of the <code>port</code> attribute */
+  public static final String PORT = "port";
+
+  /** The name of the <code>address</code> attribute */
+  public static final String ADDRESS = "address";
+
+  /** The name of the <code>host</code> element. */
+  public static final String HOST = "host";
+
+  /** The name of the <code>working-directory</code> element */
+  public static final String WORKING_DIRECTORY = "working-directory";
+
+  /** The name of the <code>product-directory</code> element */
+  public static final String PRODUCT_DIRECTORY = "product-directory";
+
+  /** The name of the <code>protocols</code> element */
+  public static final String PROTOCOLS = "protocols";
+
+  /** The name of the <code>ciphers</code> element */
+  public static final String CIPHERS = "ciphers";
+
+  /** The name of the <code>property</code> element */
+  public static final String PROPERTY = "property";
+
+  /** Name of the <code>authentication-required</code> attribute */
+  public static final String AUTHENTICATION_REQUIRED =
+    "authentication-required";
+
+  /** The name of the <code>key</code> element */
+  public static final String KEY = "key";
+
+  /** The name of the <code>value</code> element */
+  public static final String VALUE = "value";
+  
+  /** The name of the <code>classpath</code> element */
+  public static final String CLASSPATH = "classpath";
+
+  ///////////////////////  Instance Methods  ///////////////////////
+
+  /**
+   * Given a public id, attempt to resolve it to a DTD.  Returns an
+   * <code>InputSoure</code> 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
+ * <code>AdminDistributedSystem</code>.  This class is used mainly for
+ * testing.
+ *
+ * @since GemFire 4.0
+ */
+public class ManagedEntityConfigXmlGenerator
+  extends ManagedEntityConfigXml implements XMLReader {
+
+  /** An empty <code>Attributes</code> */
+  private static Attributes EMPTY = new AttributesImpl();
+
+  /////////////////////////  Instance Fields  ////////////////////////
+
+  /** The <code>AdminDistributedSystem</code> 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 <code>AdminDistributedSystem</code>.
+   */
+  public static void generate(AdminDistributedSystem system,
+                              PrintWriter pw) {
+    (new ManagedEntityConfigXmlGenerator(system)).generate(pw);
+  }
+
+  /////////////////////////  Constructors  //////////////////////////
+
+  /**
+   * Creates a new generator for the given
+   * <code>AdminDistributedSystem</code>. 
+   */
+  private ManagedEntityConfigXmlGenerator(AdminDistributedSystem
+                                          system) {
+    this.system = system;
+  }
+
+  ///////////////////////  Instance Methods  ///////////////////////
+
+  /**
+   * Generates XML and writes it to the given <code>PrintWriter</code>
+   */
+  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
+   * <code>CacheServer</code>s 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
+   * <code>CacheServerConfig</code>.
+   */
+  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 <code>DistributedSystemConfig</code> 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
+   * <code>DistributedSystemConfig</code>.
+   *
+   * @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 <code>s</code> 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 <code>distributed-system</code> element is encountered, we
+   * push the <code>DistributedSystemConfig</code> 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 <code>distributed-system</code> element is finished
+   */
+  private void endDistributedSystem() {
+    
+  }
+
+  /**
+   * When a <code>multicast</code> is first encountered, get the
+   * <code>DistributedSystemConfig</code> 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 <code>remote-command</code> element.  The item on top of
+   * the stack may be a <code>DistributedSystemConfig</code> or it
+   * might be a <code>ManagedEntityConfig</code>.
+   */
+  private void startRemoteCommand(Attributes atts) {
+
+  }
+
+  /**
+   * Ends a <code>remote-command</code> element.  Pop the command off
+   * the top of the stack and set it on the
+   * <code>DistributedSystemConfig</code> or it might be a
+   * <code>ManagedEntityConfig</code> 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 <code>ManagedEntityConfig</code> 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 <code>String</code> 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
+   * <code>characters</code> callbacks.  Coalesce multiple callbacks
+   * into one big string by using a <code>StringBuffer</code>.  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 <code>DefaultHandler</code>, but
+   * <B>is not</B> a <code>DefaultHandler</code>.
+   */
+  static class DefaultHandlerDelegate extends DefaultHandler {
+    /** The <code>ManagedEntityConfigXmlParser</code> that does the
+     * real work */ 
+    private ManagedEntityConfigXmlParser handler;
+
+    /**
+     * Creates a new <code>DefaultHandlerDelegate</code> that
+     * delegates to the given
+     * <code>ManagedEntityConfigXmlParser</code>.
+     */
+    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
+   * <code>$GEMFIRE/bin</code> taking into account the {@linkplain
+   * ManagedEntityConfig#getProductDirectory product directory} and the
+   * platform's file separator.
+   *
+   * <P>
+   *
+   * 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
+   *        <code>$GEMFIRE/bin</code>.
+   */
+  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 <code>SystemMember</code> 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 <code>ManagedSystemMemberImpl</code> that
+   * represents an existing member of an
+   * <code>AdminDistributedSystem</code>.
+   */
+  protected ManagedSystemMemberImpl(AdminDistributedSystemImpl system, 
+                                    GemFireVM vm) 
+    throws AdminException {
+
+    super(system, vm);
+    this.controller = system.getEntityController();
+  }
+
+  /**
+   * Creates a new <code>ManagedSystemMemberImpl</code> that
+   * represents a non-existing member with the given
+   * <code>ManagedEntityConfig</code> 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 <code>vm</code> is <code>null</code>.
+   */
+  @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 <code>StringBuffer</code>
+   * 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 <code>MemberHealthConfig</code>
+ *
+ *
+ * @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 <code>MemberHealthConfigImpl</code> 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 <code>MemberHealthEvaluator</code>
+   */
+  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<DistributedMember, Set<PersistentID>> 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<PersistentID> persistentIds;
+    if(cache == null) {
+      persistentIds = new HashSet<PersistentID>();
+    } 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<DistributedMember, Set<PersistentID>> results = Collections.synchronizedMap(new HashMap<DistributedMember, Set<PersistentID>>());
+    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<PersistentID> 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<PersistentID> persistentIds;
+  
+  public PrepareBackupResponse() {
+    super();
+  }
+
+  public PrepareBackupResponse(InternalDistributedMember sender, HashSet<PersistentID> persistentIds) {
+    this.setRecipient(sender);
+    this.persistentIds = persistentIds;
+  }
+  
+  public HashSet<PersistentID> 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 <code>StatisticResource</code>
+ *
+ * @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 <code>java.lang.Number</code> 
+   */
+  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();
+	}
+  
+}
+