changeset 1159:9f499f1ff126 0.11-branch

Validate as new command Reviewed-by: jerboaa, neugens Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-July/007266.html
author Giovanni Astarita <gastarit@redhat.com>
date Mon, 08 Jul 2013 10:34:08 +0200
parents 99cfefc38e04
children 1d6300d7232f
files common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentParseException.java distribution/assembly/all-plugin-assembly.xml distribution/pom.xml launcher/src/main/java/com/redhat/thermostat/launcher/CommandLineArgumentParseException.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/CommandLineArgumentsParser.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/CommandLineArgumentsParserTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java pom.xml thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginConfigurationValidatorException.java thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginValidator.java thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/internal/ConfigurationValidatorErrorHandler.java thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/PluginValidatorTest.java validate-command/command/pom.xml validate-command/command/src/main/java/com/redhat/thermostat/validate/command/ValidateCommand.java validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/Activator.java validate-command/command/src/main/java/com/redhat/thermostat/validate/command/locale/LocaleResources.java validate-command/command/src/main/resources/com/redhat/thermostat/validate/locale/strings.properties validate-command/command/src/test/java/com/redhat/thermostat/validate/command/ValidateCommandTest.java validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/ActivatorTest.java validate-command/command/src/test/java/com/redhat/thermostat/validate/command/locale/LocaleResourcesTest.java validate-command/command/src/test/resources/correctPlugin.xml validate-command/command/src/test/resources/incorrectPlugin.xml validate-command/distribution/pom.xml validate-command/distribution/thermostat-plugin.xml validate-command/pom.xml
diffstat 28 files changed, 1019 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/CommandLineArgumentParseException.java	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012, 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.cli;
+
+import com.redhat.thermostat.shared.locale.LocalizedString;
+
+public class CommandLineArgumentParseException extends CommandException {
+
+    public CommandLineArgumentParseException(LocalizedString message) {
+        super(message);
+    }
+
+    public CommandLineArgumentParseException(LocalizedString message, Throwable cause) {
+        super(message, cause);
+    }
+
+
+}
+
--- a/distribution/assembly/all-plugin-assembly.xml	Wed Jul 10 17:39:17 2013 -0600
+++ b/distribution/assembly/all-plugin-assembly.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -54,6 +54,7 @@
         <include>com.redhat.thermostat:thermostat-host-overview-distribution</include>
         <include>com.redhat.thermostat:thermostat-numa-distribution</include>
         <include>com.redhat.thermostat:thermostat-thread-distribution</include>
+        <include>com.redhat.thermostat:thermostat-validate-distribution</include>
         <include>com.redhat.thermostat:thermostat-vm-classstat-distribution</include>
         <include>com.redhat.thermostat:thermostat-vm-cpu-distribution</include>
         <include>com.redhat.thermostat:thermostat-vm-gc-distribution</include>
--- a/distribution/pom.xml	Wed Jul 10 17:39:17 2013 -0600
+++ b/distribution/pom.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -474,6 +474,12 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-validate-distribution</artifactId>
+      <version>${project.version}</version>
+      <type>zip</type>
+    </dependency>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
       <artifactId>thermostat-host-memory-distribution</artifactId>
       <version>${project.version}</version>
       <type>zip</type>
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/CommandLineArgumentParseException.java	Wed Jul 10 17:39:17 2013 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012, 2013 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.launcher;
-
-import com.redhat.thermostat.common.cli.CommandException;
-import com.redhat.thermostat.shared.locale.LocalizedString;
-
-public class CommandLineArgumentParseException extends CommandException {
-
-    public CommandLineArgumentParseException(LocalizedString message) {
-        super(message);
-    }
-
-    public CommandLineArgumentParseException(LocalizedString message, Throwable cause) {
-        super(message, cause);
-    }
-
-
-}
-
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CommandLineArgumentsParser.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CommandLineArgumentsParser.java	Mon Jul 08 10:34:08 2013 +0200
@@ -50,7 +50,7 @@
 import org.apache.commons.cli.ParseException;
 
 import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.launcher.CommandLineArgumentParseException;
+import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LauncherImpl.java	Mon Jul 08 10:34:08 2013 +0200
@@ -61,13 +61,13 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandContextFactory;
 import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
 import com.redhat.thermostat.common.cli.Console;
 import com.redhat.thermostat.common.config.ClientPreferences;
 import com.redhat.thermostat.common.tools.ApplicationState;
 import com.redhat.thermostat.common.tools.StorageAuthInfoGetter;
 import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.launcher.BundleManager;
-import com.redhat.thermostat.launcher.CommandLineArgumentParseException;
 import com.redhat.thermostat.launcher.internal.CommandInfo.Environment;
 import com.redhat.thermostat.shared.config.InvalidConfigurationException;
 import com.redhat.thermostat.shared.locale.LocalizedString;
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java	Mon Jul 08 10:34:08 2013 +0200
@@ -96,9 +96,9 @@
             } catch (PluginConfigurationParseException exception) {
                 logger.log(Level.WARNING, "unable to parse plugin configuration", exception);
             } catch (PluginConfigurationValidatorException exception) {
-                logger.log(Level.WARNING, "unable to validate " + exception.getFilePath() + " file\n");
+                logger.log(Level.INFO, "unable to validate " + exception.getFilePath() + " file\n");
             } catch (FileNotFoundException exception) {
-                logger.log(Level.WARNING, "file not found", exception);
+                logger.log(Level.INFO, "file not found", exception);
             }
         }
         combineCommands();
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java	Mon Jul 08 10:34:08 2013 +0200
@@ -53,7 +53,6 @@
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.stream.StreamSource;
 
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionGroup;
@@ -90,24 +89,24 @@
       &lt;name&gt;platform&lt;/name&gt;
       &lt;description&gt;launches a bare bone Platform Client&lt;/description&gt;
       &lt;options&gt; 
-	&lt;group&gt;
-	  &lt;required&gt;true&lt;/required&gt;
-	  &lt;option&gt;
-	    &lt;long&gt;optA&lt;/long&gt;
-	    &lt;short&gt;a&lt;/short&gt;
-	    &lt;required&gt;true&lt;/required&gt;
-	  &lt;/option&gt;
-	  &lt;option&gt;
-	    &lt;long&gt;optB&lt;/long&gt;
-	    &lt;short&gt;b&lt;/short&gt;
-	    &lt;required&gt;true&lt;/required&gt;
+    &lt;group&gt;
+      &lt;required&gt;true&lt;/required&gt;
+      &lt;option&gt;
+        &lt;long&gt;optA&lt;/long&gt;
+        &lt;short&gt;a&lt;/short&gt;
+        &lt;required&gt;true&lt;/required&gt;
+      &lt;/option&gt;
+      &lt;option&gt;
+        &lt;long&gt;optB&lt;/long&gt;
+        &lt;short&gt;b&lt;/short&gt;
+        &lt;required&gt;true&lt;/required&gt;
           &lt;/option&gt;
-	  &lt;option&gt;
-	    &lt;long&gt;optC&lt;/long&gt;
-	    &lt;short&gt;b&lt;/short&gt;	    
-	    &lt;required&gt;false&lt;/required&gt;
-	  &lt;/option&gt;
-	  &lt;option common="true"&gt;
+      &lt;option&gt;
+        &lt;long&gt;optC&lt;/long&gt;
+        &lt;short&gt;b&lt;/short&gt;        
+        &lt;required&gt;false&lt;/required&gt;
+      &lt;/option&gt;
+      &lt;option common="true"&gt;
             &lt;long&gt;dbUrl&lt;/long&gt;
           &lt;/option&gt;
           &lt;option common="true"&gt;
@@ -119,55 +118,55 @@
           &lt;option common="true"&gt;
             &lt;long&gt;logLevel&lt;/long&gt;
           &lt;/option&gt;
-	&lt;/group&gt;   
-	&lt;option&gt;
-	  &lt;long&gt;heapId&lt;/long&gt;
-	  &lt;short&gt;h&lt;/short&gt;
-	  &lt;argument&gt;heapArgument&lt;/argument&gt;
-	  &lt;required&gt;true&lt;/required&gt;
-	  &lt;description&gt;the ID of the heapdump to analyze&lt;/description&gt;
-	&lt;/option&gt;
-	&lt;option&gt;
-	  &lt;long&gt;limit&lt;/long&gt;
-	  &lt;short&gt;L&lt;/short&gt;
-	  &lt;argument&gt;limitArgument&lt;/argument&gt;
-	  &lt;required&gt;false&lt;/required&gt;
-	  &lt;description&gt;limit search to top N results, defaults to 10&lt;/description&gt;
-	&lt;/option&gt;
+    &lt;/group&gt;   
+    &lt;option&gt;
+      &lt;long&gt;heapId&lt;/long&gt;
+      &lt;short&gt;h&lt;/short&gt;
+      &lt;argument&gt;heapArgument&lt;/argument&gt;
+      &lt;required&gt;true&lt;/required&gt;
+      &lt;description&gt;the ID of the heapdump to analyze&lt;/description&gt;
+    &lt;/option&gt;
+    &lt;option&gt;
+      &lt;long&gt;limit&lt;/long&gt;
+      &lt;short&gt;L&lt;/short&gt;
+      &lt;argument&gt;limitArgument&lt;/argument&gt;
+      &lt;required&gt;false&lt;/required&gt;
+      &lt;description&gt;limit search to top N results, defaults to 10&lt;/description&gt;
+    &lt;/option&gt;
       &lt;/options&gt;
       &lt;bundles&gt;
-	&lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-	&lt;bundle&gt;thermostat-platform-swing-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-swing-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
       &lt;/bundles&gt;
       &lt;dependencies&gt;
-	&lt;dependency&gt;thermostat-client-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
+    &lt;dependency&gt;thermostat-client-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
       &lt;/dependencies&gt;
     &lt;/command&gt;
     &lt;command&gt;
       &lt;name&gt;platform2&lt;/name&gt;
       &lt;description&gt;launches a bare bone Platform Client&lt;/description&gt;
        &lt;options&gt; 
-	&lt;option&gt;
-	  &lt;long&gt;heapId2&lt;/long&gt;
-	  &lt;short&gt;h&lt;/short&gt;
-	  &lt;argument&gt;heapId2Argument&lt;/argument&gt;
-	  &lt;required&gt;true&lt;/required&gt;
-	  &lt;description&gt;the ID of the heapdump to analyze&lt;/description&gt;
-	&lt;/option&gt;
-	&lt;option&gt;
-	  &lt;long&gt;limit2&lt;/long&gt;
-	  &lt;short&gt;L&lt;/short&gt;
-	  &lt;argument&gt;limit2Argument&lt;/argument&gt;
-	  &lt;required&gt;false&lt;/required&gt;
-	  &lt;description&gt;limit search to top N results, defaults to 10&lt;/description&gt;
-	&lt;/option&gt;
+    &lt;option&gt;
+      &lt;long&gt;heapId2&lt;/long&gt;
+      &lt;short&gt;h&lt;/short&gt;
+      &lt;argument&gt;heapId2Argument&lt;/argument&gt;
+      &lt;required&gt;true&lt;/required&gt;
+      &lt;description&gt;the ID of the heapdump to analyze&lt;/description&gt;
+    &lt;/option&gt;
+    &lt;option&gt;
+      &lt;long&gt;limit2&lt;/long&gt;
+      &lt;short&gt;L&lt;/short&gt;
+      &lt;argument&gt;limit2Argument&lt;/argument&gt;
+      &lt;required&gt;false&lt;/required&gt;
+      &lt;description&gt;limit search to top N results, defaults to 10&lt;/description&gt;
+    &lt;/option&gt;
       &lt;/options&gt;
       &lt;bundles&gt;
-	&lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-	&lt;bundle&gt;thermostat-platform-controllers-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-controllers-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
       &lt;/bundles&gt;
       &lt;dependencies&gt;
-	&lt;dependency&gt;thermostat-common-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
+    &lt;dependency&gt;thermostat-common-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
       &lt;/dependencies&gt;
     &lt;/command&gt;
   &lt;/commands&gt;
@@ -176,14 +175,14 @@
       &lt;name&gt;platform3&lt;/name&gt;
       &lt;bundles&gt;
         &lt;bundle&gt;thermostat-platform-common-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-	&lt;bundle&gt;thermostat-platform-controllers-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-	&lt;bundle&gt;thermostat-platform-command-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-	&lt;bundle&gt;thermostat-platform-common-export-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
-	&lt;bundle&gt;thermostat-platform-swing-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-controllers-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-command-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-common-export-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
+    &lt;bundle&gt;thermostat-platform-swing-0.6.0-SNAPSHOT.jar&lt;/bundle&gt;
       &lt;/bundles&gt;
       &lt;dependencies&gt;
-	&lt;dependency&gt;thermostat-common-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
-	&lt;dependency&gt;thermostat-client-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
+    &lt;dependency&gt;thermostat-common-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
+    &lt;dependency&gt;thermostat-client-core-0.6.0-SNAPSHOT.jar&lt;/dependency&gt;
       &lt;/dependencies&gt;
     &lt;/extension&gt;
   &lt;/extensions&gt;
@@ -200,8 +199,15 @@
     
     public PluginConfiguration parse(File configurationFile) throws FileNotFoundException, PluginConfigurationValidatorException {
         PluginValidator validator = new PluginValidator();
-        validator.validate(new StreamSource(configurationFile));
-        return parse(configurationFile.getParentFile().getName(), new FileInputStream(configurationFile));
+        validator.validate(configurationFile, false);
+        PluginConfiguration config = null;
+        try (FileInputStream fis = new FileInputStream(configurationFile)) {
+            config = parse(configurationFile.getParentFile().getName(), fis);
+            
+        } catch (IOException ioFisClosed) {
+            // ignore if fis closing fails
+        }
+        return config;
     }
     
     PluginConfiguration parse(String pluginName, InputStream configurationStream) {
@@ -232,7 +238,7 @@
                 if (node.getNodeName().equals("commands")) {
                     commands = parseCommands(pluginName, node);
                 } else if (node.getNodeName().equals("extensions")) {
-                	extensions = parseExtensions(pluginName, node);
+                    extensions = parseExtensions(pluginName, node);
                 }
             }
         }
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/CommandLineArgumentsParserTest.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/CommandLineArgumentsParserTest.java	Mon Jul 08 10:34:08 2013 +0200
@@ -48,7 +48,7 @@
 import org.junit.Test;
 
 import com.redhat.thermostat.common.cli.Arguments;
-import com.redhat.thermostat.launcher.CommandLineArgumentParseException;
+import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
 
 public class CommandLineArgumentsParserTest {
 
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java	Mon Jul 08 10:34:08 2013 +0200
@@ -44,17 +44,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.BufferedWriter;
 import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 import java.util.List;
 
-import javax.xml.transform.stream.StreamSource;
-
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.OptionGroup;
 import org.apache.commons.cli.Options;
--- a/pom.xml	Wed Jul 10 17:39:17 2013 -0600
+++ b/pom.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -151,6 +151,7 @@
     <module>numa</module>
     <module>laf-utils</module>
     <module>thermostat-plugin-validator</module>
+    <module>validate-command</module>
     <module>config</module>
     <!-- development related modules -->
     <module>integration-tests</module>
--- a/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginConfigurationValidatorException.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginConfigurationValidatorException.java	Mon Jul 08 10:34:08 2013 +0200
@@ -44,36 +44,26 @@
     
     /**
      * Constructor of PluginConfigurationValidatorException
-     * @param filePath must include the protocol 
+     * @param filePath The absolute path to the file which failed to validate.
      * @param message the detailed message
      */
     public PluginConfigurationValidatorException(String filePath, String message) {
         super(message);
-        this.filePath = computeFilePath(filePath);
+        this.filePath = filePath;
     }
     
     /**
      * Constructor of PluginConfigurationValidatorException
-     * @param filePath must include the protocol 
+     * @param filePath The absolute path to the file which failed to validate.
      * @param message the detailed message
      */
     public PluginConfigurationValidatorException(String filePath, String message, Throwable cause) {
         super(message, cause);
-        this.filePath = computeFilePath(filePath);
+        this.filePath = filePath;
     }
     
     public String getFilePath() {
         return filePath;
     }
     
-    /**
-     * Computes the file path removing the protocol scheme
-     * @param filePath must include the protocol
-     * @return the path without the protocol scheme
-     */
-    private String computeFilePath(String filePath) {
-        // the substring starts from position 5, skipping "file:" filePath content 
-        return filePath.substring(5);
-    }
-
 }
--- a/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginValidator.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginValidator.java	Mon Jul 08 10:34:08 2013 +0200
@@ -36,6 +36,9 @@
 
 package com.redhat.thermostat.plugin.validator;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.net.URL;
 
@@ -51,21 +54,25 @@
 
 
 public class PluginValidator {
-    
-    public void validate(StreamSource plugin) throws PluginConfigurationValidatorException {
+
+    public void validate(File pluginXml, boolean isCommand) throws PluginConfigurationValidatorException, FileNotFoundException {
         URL schemaUrl = PluginValidator.class.getResource("/thermostat-plugin.xsd");
         SchemaFactory schemaFactory = 
                 SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
         
-        try {
+        try (FileInputStream fis = new FileInputStream(pluginXml)) {
             Schema schema = schemaFactory.newSchema(schemaUrl);
             Validator validator = schema.newValidator();
-            validator.setErrorHandler(new ConfigurationValidatorErrorHandler());
-            validator.validate(plugin);
-        } catch (IOException | SAXException exception) {
+            validator.setErrorHandler(new ConfigurationValidatorErrorHandler(pluginXml, isCommand));
+            validator.validate(new StreamSource(fis));
+        } catch (SAXException exception) {
             throw new PluginConfigurationValidatorException
-                (plugin.getSystemId(), exception.getLocalizedMessage(), exception);
-        }
+            (pluginXml.getAbsolutePath(), exception.getLocalizedMessage(), exception);
+        } catch (FileNotFoundException fnfe) {
+            throw fnfe;
+        } catch (IOException ioe) {
+            throw new  PluginConfigurationValidatorException(ioe.getLocalizedMessage(), ioe.getMessage());
+        } 
     }
 
 }
--- a/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/internal/ConfigurationValidatorErrorHandler.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/internal/ConfigurationValidatorErrorHandler.java	Mon Jul 08 10:34:08 2013 +0200
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.plugin.validator.internal;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.HashMap;
@@ -56,12 +57,19 @@
     private static final Logger logger = LoggingUtils.getLogger(ConfigurationValidatorErrorHandler.class);
     private int warningsErrorsCounter = 0;
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+    private final File pluginXML;
+    private boolean isCommand;
     
     private enum ErrorType {
         WARNING,
         ERROR,
         FATAL_ERROR;
     }
+    
+    public ConfigurationValidatorErrorHandler(File pluginXML, boolean isCommand) {
+        this.pluginXML = pluginXML;
+        this.isCommand = isCommand;
+    }
 
     @Override
     public void warning(SAXParseException exception) throws SAXException {
@@ -79,11 +87,11 @@
     public void fatalError(SAXParseException exception) throws SAXParseException {
         if (warningsErrorsCounter == 0) {
             printInfo(exception, ErrorType.FATAL_ERROR);
-            logger.warning("XML not well formed");
+            logger.info("XML not well formed");
         }
     }
 
-    private static void printInfo(SAXParseException e, ErrorType type) {
+    private void printInfo(SAXParseException e, ErrorType type) {
         int columnNumber = e.getColumnNumber();
         int lineNumber = e.getLineNumber();
         
@@ -94,8 +102,7 @@
         String thirdLine = null;
         String errorLine = null;
         String pointer = "";
-        String absolutePath = e.getSystemId();
-        absolutePath = absolutePath.substring(5);
+        String absolutePath = pluginXML.getAbsolutePath();
         
         Map<ErrorType,LocaleResources> translateKeys = new HashMap<>();
         translateKeys.put(ErrorType.ERROR, LocaleResources.VALIDATION_ERROR);
@@ -134,7 +141,12 @@
         buffer.append(errorLine + "\n");
         buffer.append(pointer  + "\n");
         
-        logger.warning("\n" + buffer.toString());
+        if (isCommand) {
+            System.out.println(buffer.toString());
+        } else {
+            logger.info(buffer.toString());
+        }
+        
     }
     
     private static String formatMessage(String message) {
--- a/thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/PluginValidatorTest.java	Wed Jul 10 17:39:17 2013 -0600
+++ b/thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/PluginValidatorTest.java	Mon Jul 08 10:34:08 2013 +0200
@@ -44,8 +44,6 @@
 import java.io.FileWriter;
 import java.io.IOException;
 
-import javax.xml.transform.stream.StreamSource;
-
 import org.junit.Test;
 
 public class PluginValidatorTest {
@@ -56,7 +54,7 @@
         File testFile = createFile("testSystemId", config);
         PluginValidator validator = new PluginValidator();
         try {
-            validator.validate(new StreamSource(testFile));
+            validator.validate(testFile, false);
             fail("should not come here");
         } catch (PluginConfigurationValidatorException e) {
             //pass
@@ -89,7 +87,7 @@
                     "</plugin>";
             File testFile = createFile("testSystemId", config);
             PluginValidator validator = new PluginValidator();
-            validator.validate(new StreamSource(testFile));
+            validator.validate(testFile, false);
             testFile.delete();
         
             config = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
@@ -112,7 +110,7 @@
                     "</plugin>";
             File testFile2 = createFile("testSystemId", config);
             PluginValidator validator2 = new PluginValidator();
-            validator2.validate(new StreamSource(testFile));
+            validator2.validate(testFile, false);
             testFile2.delete();
         } catch (PluginConfigurationValidatorException e) {
            fail("should not reach here, plugin.xml should be validated according to schema");
@@ -144,7 +142,7 @@
         File testFile = createFile("testSystemId", config);
         PluginValidator validator = new PluginValidator();
         try {
-            validator.validate(new StreamSource(testFile));
+            validator.validate(testFile, false);
             fail("plugin.xml should not validate according to schema");
         } catch (PluginConfigurationValidatorException e) {
             //pass
@@ -207,7 +205,7 @@
         File testFile = createFile("testSystemId", config);
         PluginValidator validator = new PluginValidator();
         try {
-            validator.validate(new StreamSource(testFile));
+            validator.validate(testFile, false);
         } catch (PluginConfigurationValidatorException e) {
            fail("should not reach here, plugin.xml should be validated according to schema");
         } finally {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/pom.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012, 2013 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>validate-command</artifactId>
+    <version>0.10.0-SNAPSHOT</version>
+  </parent>
+  
+  <artifactId>thermostat-validate-command</artifactId>
+  <packaging>bundle</packaging>
+  
+  <name>Thermostat Validate Command plugin</name>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>com.redhat.thermostat.validate.command</Bundle-SymbolicName>
+            <Bundle-Vendor>Red Hat, Inc.</Bundle-Vendor>
+            <Export-Package>
+              com.redhat.thermostat.validate.command,
+            </Export-Package>
+            <Private-Package>
+              com.redhat.thermostat.validate.command.internal,
+              com.redhat.thermostat.validate.command.locale,
+            </Private-Package>
+            <Bundle-Activator>com.redhat.thermostat.validate.command.internal.Activator</Bundle-Activator>
+            <!-- Do not autogenerate uses clauses in Manifests -->
+            <_nouses>true</_nouses>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-common-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-plugin-validator</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-shared-config</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/ValidateCommand.java	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.validate.command;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
+import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException;
+import com.redhat.thermostat.plugin.validator.PluginValidator;
+import com.redhat.thermostat.shared.locale.Translate;
+import com.redhat.thermostat.validate.command.locale.LocaleResources;
+
+public class ValidateCommand implements Command {
+
+    private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
+
+    public void run(CommandContext ctx) throws CommandException {
+        Arguments args = ctx.getArguments();
+        PluginValidator validator = new PluginValidator();
+        File pluginFile = null;
+        String argString = null;
+        
+            try {
+                argString = args.getNonOptionArguments().get(0);
+                pluginFile = new File(argString);
+                validator.validate(pluginFile, true);
+                ctx.getConsole().getOutput().println(translator.localize(
+                                LocaleResources.VALIDATION_SUCCESSFUL, pluginFile.getAbsolutePath())
+                                .getContents());
+                
+            } catch (PluginConfigurationValidatorException e) {
+                ctx.getConsole().getError().println(translator.localize(
+                                LocaleResources.VALIDATION_FAILED, pluginFile.getAbsolutePath())
+                               .getContents());
+                
+            } catch (IndexOutOfBoundsException | NullPointerException e) {
+                throw new CommandLineArgumentParseException
+                (translator.localize(
+                        LocaleResources.FILE_REQUIRED));
+                
+            } catch (FileNotFoundException fnfe) {
+                throw new CommandLineArgumentParseException
+                (translator.localize(
+                        LocaleResources.FILE_NOT_FOUND, pluginFile.getAbsolutePath()));
+            }        
+    }
+
+    public boolean isStorageRequired() {
+        return false;
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/internal/Activator.java	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012, 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.validate.command.internal;
+
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import com.redhat.thermostat.common.cli.Command;
+import com.redhat.thermostat.validate.command.ValidateCommand;
+
+public class Activator implements BundleActivator {
+
+    private ServiceRegistration registration;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        Hashtable<String,String> properties = new Hashtable<>();
+        properties.put(Command.NAME, "validate");
+        registration = context.registerService(Command.class.getName(), new ValidateCommand(), properties);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        registration.unregister();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/main/java/com/redhat/thermostat/validate/command/locale/LocaleResources.java	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012, 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.validate.command.locale;
+
+import com.redhat.thermostat.shared.locale.Translate;
+
+
+public enum LocaleResources {
+    
+    VALIDATION_SUCCESSFUL,
+    VALIDATION_FAILED, 
+    
+    FILE_REQUIRED,
+    FILE_NOT_FOUND, 
+    ;
+
+    static final String RESOURCE_BUNDLE =
+            "com.redhat.thermostat.validate.locale.strings";
+
+    public static Translate<LocaleResources> createLocalizer() {
+        return new Translate(RESOURCE_BUNDLE, LocaleResources.class);
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/main/resources/com/redhat/thermostat/validate/locale/strings.properties	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,5 @@
+VALIDATION_SUCCESSFUL = Validation successful for file {0}\n
+VALIDATION_FAILED = Validation failed for file {0}\n
+
+FILE_REQUIRED = Could not parse argument: missing file name
+FILE_NOT_FOUND = File {0} not found. Please check the file name and/or the path
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/ValidateCommandTest.java	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.validate.command;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.cli.MissingArgumentException;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.redhat.thermostat.common.cli.Arguments;
+import com.redhat.thermostat.common.cli.CommandContext;
+import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.CommandLineArgumentParseException;
+import com.redhat.thermostat.common.cli.Console;
+import com.redhat.thermostat.plugin.validator.PluginValidator;
+
+public class ValidateCommandTest {
+    
+    private ValidateCommand cmd;
+    private CommandContext ctxt;
+    private Arguments mockArgs;
+    private Console console;
+    private String fileName;
+    private List<String> list = new ArrayList<>();
+    private ByteArrayOutputStream outputBaos, errorBaos;
+    private PrintStream output, error;
+        
+    @Before
+    public void setUp() {
+        
+        cmd = new ValidateCommand();
+        ctxt = mock(CommandContext.class);
+        mockArgs = mock(Arguments.class);
+        console = mock(Console.class);
+
+        outputBaos = new ByteArrayOutputStream();
+        output = new PrintStream(outputBaos);
+        
+        errorBaos = new ByteArrayOutputStream();
+        error = new PrintStream(errorBaos);
+        
+        when(ctxt.getArguments()).thenReturn(mockArgs);
+        when(ctxt.getConsole()).thenReturn(console);
+        when(console.getError()).thenReturn(error);
+        when(console.getOutput()).thenReturn(output);
+        when(mockArgs.getNonOptionArguments()).thenReturn(list);
+        
+    }
+    
+    @Test
+    public void validateIncorrectFile() throws CommandException, MissingArgumentException {
+        fileName = PluginValidator.class.getResource("/incorrectPlugin.xml").getPath().toString();
+        list.add(fileName);
+        
+        cmd.run(ctxt);
+        
+        String actual = new String(errorBaos.toByteArray());
+        String expected = "Validation failed for file " + fileName + "\n\n";
+        assertEquals(expected, actual);
+
+        assertEquals("", new String(outputBaos.toByteArray()));
+    }
+
+    @Test
+    public void validateCorrectFile() throws CommandException, MissingArgumentException {
+        fileName = PluginValidator.class.getResource("/correctPlugin.xml").getPath().toString();
+        list.add(fileName);
+        
+        cmd.run(ctxt);
+        
+        String expected = "Validation successful for file " + fileName + "\n\n";
+        String actual = new String(outputBaos.toByteArray());
+        assertEquals(expected, actual);
+        
+        assertEquals("", new String(errorBaos.toByteArray()));
+    }
+    
+    @Test
+    public void validateNonExistingFile() throws CommandException, MissingArgumentException {
+        fileName = "/nonExistingFile.xml";
+        list.add(fileName);
+        
+        try {
+            cmd.run(ctxt);    
+        } catch(CommandLineArgumentParseException clpae) {
+            // pass
+        }
+    }
+    
+    @Test
+    public void missingFileAsArgument() throws CommandException, MissingArgumentException {
+        
+        try {
+            cmd.run(ctxt);    
+        } catch(CommandLineArgumentParseException clpae) {
+            // pass
+        }
+    }
+    
+    @Test
+    public void testStorageRequired() {
+        assertFalse(cmd.isStorageRequired());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/internal/ActivatorTest.java	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012, 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.validate.command.internal;
+
+import static com.redhat.thermostat.testutils.Asserts.assertCommandIsRegistered;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.testutils.StubBundleContext;
+import com.redhat.thermostat.validate.command.ValidateCommand;
+
+public class ActivatorTest {
+
+    @Test
+    public void testCommandsRegistered() throws Exception {
+        StubBundleContext ctx = new StubBundleContext();
+        
+        Activator activator = new Activator();
+        
+        activator.start(ctx);
+
+        assertCommandIsRegistered(ctx, "validate", ValidateCommand.class);
+        
+        activator.stop(ctx);
+        
+        assertEquals(0, ctx.getAllServices().size());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/test/java/com/redhat/thermostat/validate/command/locale/LocaleResourcesTest.java	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012, 2013 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.validate.command.locale;
+
+import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest;
+
+public class LocaleResourcesTest extends AbstractLocaleResourcesTest<LocaleResources> {
+
+    @Override
+    protected Class<LocaleResources> getEnumClass() {
+        return LocaleResources.class;
+    }
+
+    @Override
+    protected String getResourceBundle() {
+        return LocaleResources.RESOURCE_BUNDLE;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/test/resources/correctPlugin.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://icedtea.classpath.org/thermostat/plugins/v1.0"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://icedtea.classpath.org/thermostat/plugins/v1.0 thermostat-plugin.xsd">
+  <extensions>
+    <extension>
+      <name>test</name>
+      <bundles>
+        <bundle>foo</bundle>
+        <bundle>bar</bundle>
+        <bundle>baz</bundle>
+      </bundles>
+      <dependencies>
+        <dependency>thermostat-foo</dependency>
+      </dependencies>
+    </extension>
+  </extensions>
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/command/src/test/resources/incorrectPlugin.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<plugin xmlns="http://icedtea.classpath.org/thermostat/plugins/v1.0"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:schemaLocation="http://icedtea.classpath.org/thermostat/plugins/v1.0 thermostat-plugin.xsd">
+  <extensions>
+    <something>
+    <extension>
+      <name>test</name>
+      <bundles>
+        <bundle>foo</bundle>
+        <bundle>bar</bundle>
+        <bundle>baz</bundle>
+      </bundles>
+      <dependencies>
+        <dependency>thermostat-foo</dependency>
+      </dependencies>
+    </extension>
+  </extensions>
+</plugin>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/distribution/pom.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012, 2013 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>validate-command</artifactId>
+    <version>0.10.0-SNAPSHOT</version>
+  </parent>
+  
+  <artifactId>thermostat-validate-distribution</artifactId>
+  <packaging>pom</packaging>
+  
+  <name>Thermostat Validate plugin distribution</name>
+  
+  <properties>
+    <thermostat.plugin>validate</thermostat.plugin>
+  </properties>
+  
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <dependencies>
+          <dependency>
+            <groupId>com.redhat.thermostat</groupId>
+            <artifactId>thermostat-assembly</artifactId>
+            <version>${project.version}</version>
+          </dependency>
+        </dependencies>
+        <configuration>
+          <descriptorRefs>
+            <descriptorRef>plugin-assembly</descriptorRef>
+          </descriptorRefs>
+          <appendAssemblyId>false</appendAssemblyId>
+        </configuration>
+        <executions>
+          <execution>
+            <id>assemble-plugin</id>
+            <phase>package</phase>
+            <goals>
+              <goal>single</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <!-- Explicitly list all plug-in artifacts, transitive dependencies
+       are not included in assembly. -->
+  <dependencies>
+    <dependency>
+      <groupId>com.redhat.thermostat</groupId>
+      <artifactId>thermostat-validate-command</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/distribution/thermostat-plugin.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<!-- 
+
+ Copyright 2012, 2013 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<plugin xmlns="http://icedtea.classpath.org/thermostat/plugins/v1.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://icedtea.classpath.org/thermostat/plugins/v1.0 thermostat-plugin.xsd">
+  <commands>
+    <command>
+      <name>validate</name>
+      <description>validates a thermostat plug-in XML file against the schema</description>
+      <arguments>
+        <argument>file</argument>
+      </arguments>
+      <environments>
+        <environment>cli</environment>
+        <environment>shell</environment>
+      </environments>
+      <bundles>
+        <bundle>thermostat-validate-command-${project.version}.jar</bundle>
+      </bundles>
+      <dependencies>
+        <dependency>thermostat-common-core-${project.version}.jar</dependency>
+        <dependency>thermostat-shared-config-${project.version}.jar</dependency>
+        <dependency>thermostat-plugin-validator-${project.version}.jar</dependency>
+      </dependencies>
+    </command>
+  </commands>
+</plugin>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/validate-command/pom.xml	Mon Jul 08 10:34:08 2013 +0200
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ Copyright 2012, 2013 Red Hat, Inc.
+
+ This file is part of Thermostat.
+
+ Thermostat is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ Thermostat is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Thermostat; see the file COPYING.  If not see
+ <http://www.gnu.org/licenses />.
+
+ Linking this code with other modules is making a combined work
+ based on this code.  Thus, the terms and conditions of the GNU
+ General Public License cover the whole combination.
+
+ As a special exception, the copyright holders of this code give
+ you permission to link this code with independent modules to
+ produce an executable, regardless of the license terms of these
+ independent modules, and to copy and distribute the resulting
+ executable under terms of your choice, provided that you also
+ meet, for each linked independent module, the terms and conditions
+ of the license of that module.  An independent module is a module
+ which is not derived from or based on this code.  If you modify
+ this code, you may extend this exception to your version of the
+ library, but you are not obligated to do so.  If you do not wish
+ to do so, delete this exception statement from your version.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>com.redhat.thermostat</groupId>
+    <artifactId>thermostat</artifactId>
+    <version>0.10.0-SNAPSHOT</version>
+  </parent>
+  <artifactId>validate-command</artifactId>
+  <packaging>pom</packaging>
+  
+  <name>Thermostat Validate command</name>
+  
+  <description>Validator for thermostat plugin XML files</description>
+  
+  <modules>
+    <module>command</module>
+    <module>distribution</module>
+  </modules>
+</project>