# HG changeset patch # User Giovanni Astarita # Date 1370423667 -7200 # Node ID aa48ed4752c164c22eea285174926afd12a0bb53 # Parent a746c19af58f39bf30fd64cfda47ed2e4afc71fb Plugin validator as separate module Reviewed-by: neugens, jerboaa, omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-May/006874.html diff -r a746c19af58f -r aa48ed4752c1 launcher/pom.xml --- a/launcher/pom.xml Mon Jun 03 18:10:51 2013 +0200 +++ b/launcher/pom.xml Wed Jun 05 11:14:27 2013 +0200 @@ -53,23 +53,6 @@ - - - - ${basedir}/../distribution/docs/ - - thermostat-plugin.xsd - - - - - src/main/resources/ - - **/* - - - org.apache.felix @@ -136,6 +119,11 @@ ${project.version} test + + com.redhat.thermostat + thermostat-plugin-validator + ${project.version} + diff -r a746c19af58f -r aa48ed4752c1 launcher/src/main/java/com/redhat/thermostat/launcher/internal/LocaleResources.java --- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LocaleResources.java Mon Jun 03 18:10:51 2013 +0200 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/LocaleResources.java Wed Jun 05 11:14:27 2013 +0200 @@ -59,10 +59,6 @@ LAUNCHER_USER_AUTH_PROMPT_ERROR, LAUNCHER_MALFORMED_URL, LAUNCHER_CONNECTION_ERROR, - - VALIDATION_WARNING, - VALIDATION_ERROR, - VALIDATION_FATAL_ERROR, ; static final String RESOURCE_BUNDLE = "com.redhat.thermostat.launcher.internal.strings"; diff -r a746c19af58f -r aa48ed4752c1 launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java --- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java Mon Jun 03 18:10:51 2013 +0200 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSource.java Wed Jun 05 11:14:27 2013 +0200 @@ -52,6 +52,7 @@ import com.redhat.thermostat.common.utils.LoggingUtils; import com.redhat.thermostat.launcher.internal.PluginConfiguration.CommandExtensions; import com.redhat.thermostat.launcher.internal.PluginConfiguration.NewCommand; +import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException; /** * Searches for plugins under $THERMOSTAT_HOME/plugins/ and diff -r a746c19af58f -r aa48ed4752c1 launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java --- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java Mon Jun 03 18:10:51 2013 +0200 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParser.java Wed Jun 05 11:14:27 2013 +0200 @@ -37,21 +37,16 @@ package com.redhat.thermostat.launcher.internal; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.logging.Logger; @@ -59,10 +54,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; -import javax.xml.validation.Validator; -import javax.xml.XMLConstants; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionGroup; @@ -78,7 +69,8 @@ import com.redhat.thermostat.launcher.internal.CommandInfo.Environment; import com.redhat.thermostat.launcher.internal.PluginConfiguration.CommandExtensions; import com.redhat.thermostat.launcher.internal.PluginConfiguration.NewCommand; -import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException; +import com.redhat.thermostat.plugin.validator.PluginValidator; /** * Parses the configuration of a plugin as specified in an {@code File} or an @@ -207,25 +199,10 @@ // thread safe because there is no state :) public PluginConfiguration parse(File configurationFile) throws FileNotFoundException, PluginConfigurationValidatorException { - validate(new StreamSource(configurationFile)); + PluginValidator validator = new PluginValidator(); + validator.validate(new StreamSource(configurationFile)); return parse(configurationFile.getParentFile().getName(), new FileInputStream(configurationFile)); } - - void validate(StreamSource plugin) throws PluginConfigurationValidatorException { - URL schemaUrl = getClass().getResource("/thermostat-plugin.xsd"); - SchemaFactory schemaFactory = - SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); - - try { - Schema schema = schemaFactory.newSchema(schemaUrl); - Validator validator = schema.newValidator(); - validator.setErrorHandler(new ConfigurationValidatorErrorHandler()); - validator.validate(plugin); - } catch (IOException | SAXException exception) { - throw new PluginConfigurationValidatorException - (plugin.getSystemId(), exception.getLocalizedMessage(), exception); - } - } PluginConfiguration parse(String pluginName, InputStream configurationStream) { try { @@ -553,100 +530,4 @@ } } - private static class ConfigurationValidatorErrorHandler implements ErrorHandler { - - private int warningsErrorsCounter = 0; - private static final Translate translator = LocaleResources.createLocalizer(); - - private enum ErrorType { - WARNING, - ERROR, - FATAL_ERROR; - } - - @Override - public void warning(SAXParseException exception) throws SAXException { - warningsErrorsCounter++; - printInfo(exception, ErrorType.WARNING); - } - - @Override - public void error(SAXParseException exception) throws SAXParseException { - warningsErrorsCounter++; - printInfo(exception, ErrorType.ERROR); - } - - @Override - public void fatalError(SAXParseException exception) throws SAXParseException { - if (warningsErrorsCounter == 0) { - printInfo(exception, ErrorType.FATAL_ERROR); - logger.warning("XML not well formed"); - } - } - - private static void printInfo(SAXParseException e, ErrorType type) { - int columnNumber = e.getColumnNumber(); - int lineNumber = e.getLineNumber(); - - StringBuffer buffer = new StringBuffer(); - - String firstLine = null; - String secondLine = null; - String thirdLine = null; - String errorLine = null; - String pointer = ""; - String absolutePath = e.getSystemId(); - absolutePath = absolutePath.substring(5); - - Map translateKeys = new HashMap<>(); - translateKeys.put(ErrorType.ERROR, LocaleResources.VALIDATION_ERROR); - translateKeys.put(ErrorType.WARNING, LocaleResources.VALIDATION_WARNING); - translateKeys.put(ErrorType.FATAL_ERROR, LocaleResources.VALIDATION_FATAL_ERROR); - - try { - BufferedReader br = new BufferedReader(new FileReader(absolutePath)); - for (int i = 1; i < lineNumber-3; i++) { - br.readLine(); - } - firstLine = br.readLine(); - secondLine = br.readLine(); - thirdLine = br.readLine(); - errorLine = br.readLine(); - - for (int j = 1; j < columnNumber-1; j++) { - pointer = pointer.concat(" "); - } - pointer = pointer.concat("^"); - br.close(); - } catch (IOException exception) { - System.out.println("File not found!");; - } - - buffer.append(translator.localize( - translateKeys.get(type), - absolutePath, - Integer.toString(lineNumber), - Integer.toString(columnNumber)).getContents()); - - buffer.append(formatMessage(e.getLocalizedMessage()) + "\n\n"); - buffer.append(firstLine + "\n"); - buffer.append(secondLine + "\n"); - buffer.append(thirdLine + "\n"); - buffer.append(errorLine + "\n"); - buffer.append(pointer + "\n"); - - logger.warning("\n" + buffer.toString()); - } - - private static String formatMessage(String message) { - String[] arguments = message.split("\"http://icedtea.classpath.org/thermostat/plugins/v1.0\":"); - int size = arguments.length; - String output = ""; - for (int i = 0; i < size; i++) { - output=output.concat(arguments[i]); - } - return output; - } - } - } diff -r a746c19af58f -r aa48ed4752c1 launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationValidatorException.java --- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/PluginConfigurationValidatorException.java Mon Jun 03 18:10:51 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * 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 - * . - * - * 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.internal; - - -public class PluginConfigurationValidatorException extends Exception { - - private static final long serialVersionUID = 1L; - private String filePath; - - /** - * Constructor of PluginConfigurationValidatorException - * @param filePath must include the protocol - * @param message the detailed message - */ - public PluginConfigurationValidatorException(String filePath, String message) { - super(message); - this.filePath = computeFilePath(filePath); - } - - /** - * Constructor of PluginConfigurationValidatorException - * @param filePath must include the protocol - * @param message the detailed message - */ - public PluginConfigurationValidatorException(String filePath, String message, Throwable cause) { - super(message, cause); - this.filePath = computeFilePath(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); - } - -} diff -r a746c19af58f -r aa48ed4752c1 launcher/src/main/resources/com/redhat/thermostat/launcher/internal/strings.properties --- a/launcher/src/main/resources/com/redhat/thermostat/launcher/internal/strings.properties Mon Jun 03 18:10:51 2013 +0200 +++ b/launcher/src/main/resources/com/redhat/thermostat/launcher/internal/strings.properties Wed Jun 05 11:14:27 2013 +0200 @@ -18,8 +18,4 @@ LAUNCHER_USER_AUTH_PROMPT_ERROR = Error while prompting for username and password. LAUNCHER_MALFORMED_URL = Unsupported storage URL: {0} -LAUNCHER_CONNECTION_ERROR = Could not connect to: {0} - -VALIDATION_WARNING = Warning in file {0}:{1}.{2}\n -VALIDATION_ERROR = Error in file {0}:{1}.{2}\n -VALIDATION_FATAL_ERROR = Fatal error in file {0}:{1}.{2}\n \ No newline at end of file +LAUNCHER_CONNECTION_ERROR = Could not connect to: {0} \ No newline at end of file diff -r a746c19af58f -r aa48ed4752c1 launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java --- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java Mon Jun 03 18:10:51 2013 +0200 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginCommandInfoSourceTest.java Wed Jun 05 11:14:27 2013 +0200 @@ -66,6 +66,7 @@ import com.redhat.thermostat.launcher.internal.CommandInfo.Environment; import com.redhat.thermostat.launcher.internal.PluginConfiguration.CommandExtensions; import com.redhat.thermostat.launcher.internal.PluginConfiguration.NewCommand; +import com.redhat.thermostat.plugin.validator.PluginConfigurationValidatorException; public class PluginCommandInfoSourceTest { diff -r a746c19af58f -r aa48ed4752c1 launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java --- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java Mon Jun 03 18:10:51 2013 +0200 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/PluginConfigurationParserTest.java Wed Jun 05 11:14:27 2013 +0200 @@ -76,21 +76,6 @@ } @Test - public void validateEmptyConfiguration() throws IOException { - String config = "\n"; - PluginConfigurationParser parser = new PluginConfigurationParser(); - File testFile = createFile("testSystemId", config); - try { - parser.validate(new StreamSource(testFile)); - fail("should not come here"); - } catch (PluginConfigurationValidatorException e) { - //pass - } finally { - testFile.delete(); - } - } - - @Test public void testMinimalConfiguration() throws UnsupportedEncodingException { PluginConfigurationParser parser = new PluginConfigurationParser(); String config = "" + @@ -141,93 +126,6 @@ } @Test - public void canValidatePluginXMLMultipleTimes() throws Exception { - - try { - String config = "\n" + - "\n" + - " \n" + - " \n" + - " test\n" + - " \n" + - " foo\n" + - " bar\n" + - " baz\n" + - " \n" + - " \n" + - " thermostat-foo\n" + - " \n" + - " \n" + - " \n" + - ""; - PluginConfigurationParser parser = new PluginConfigurationParser(); - File testFile = createFile("testSystemId", config); - parser.validate(new StreamSource(testFile)); - testFile.delete(); - - config = "\n" + - "\n" + - " \n" + - " \n" + - " test\n" + - " \n" + - " foo\n" + - " bar\n" + - " baz\n" + - " \n" + - " \n" + - " thermostat-foo\n" + - " \n" + - " \n" + - " \n" + - ""; - File testFile2 = createFile("testSystemId", config); - parser.validate(new StreamSource(testFile)); - testFile2.delete(); - } catch (PluginConfigurationValidatorException e) { - fail("should not reach here, plugin.xml should be validated according to schema"); - } - } - - @Test - public void validationFailsOnInvalidPluginFile() throws Exception { - String config = "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " test\n" + - " \n" + - " foo\n" + - " bar\n" + - " baz\n" + - " \n" + - " \n" + - " thermostat-foo\n" + - " \n" + - " \n" + - " \n" + - ""; - - PluginConfigurationParser parser = new PluginConfigurationParser(); - File testFile = createFile("testSystemId", config); - try { - parser.validate(new StreamSource(testFile)); - fail("plugin.xml should not validate according to schema"); - } catch (PluginConfigurationValidatorException e) { - //pass - } finally { - testFile.delete(); - } - } - - @Test public void testConfigurationThatAddsNewCommand() throws UnsupportedEncodingException { String config = "\n" + "\n" + - "\n" + - " \n" + - " \n" + - " test\n" + - " just a test\n" + - " \n" + - " \n" + - " true\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " " + - " shell" + - " cli" + - " " + - " \n" + - " \n \t \nfoo\t \n \n\n" + - " \tbar baz\n\n" + - " buzz\n" + - " \n" + - " \n\t\n\t \t\t\n" + - " \t\t\t thermostat-foo\n\t\t\n\n" + - " \n" + - " \n" + - " \n" + - ""; - - PluginConfigurationParser parser = new PluginConfigurationParser(); - File testFile = createFile("testSystemId", config); - try { - parser.validate(new StreamSource(testFile)); - } catch (PluginConfigurationValidatorException e) { - fail("should not reach here, plugin.xml should be validated according to schema"); - } finally { - testFile.delete(); - } - - } - @Test public void testOptionParsing() throws UnsupportedEncodingException { String config = "\n" + "vm-jmx numa laf-utils + thermostat-plugin-validator config integration-tests diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/pom.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/pom.xml Wed Jun 05 11:14:27 2013 +0200 @@ -0,0 +1,115 @@ + + + + 4.0.0 + + com.redhat.thermostat + thermostat + 0.10.0-SNAPSHOT + + + thermostat-plugin-validator + bundle + + Thermostat Plugin Validator + + + + + + ${basedir}/../distribution/docs/ + + thermostat-plugin.xsd + + + + + src/main/resources/ + + **/* + + + + + + org.apache.felix + maven-bundle-plugin + true + + + com.redhat.thermostat.plugin.validator + Red Hat, Inc. + + com.redhat.thermostat.plugin.validator, + + + com.redhat.thermostat.plugin.validator.internal, + com.redhat.thermostat.plugin.validator.locale, + + + <_nouses>true + + + + + + + + + + junit + junit + test + + + + com.redhat.thermostat + thermostat-common-core + ${project.version} + + + + com.redhat.thermostat + thermostat-common-test + ${project.version} + + + + \ No newline at end of file diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginConfigurationValidatorException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginConfigurationValidatorException.java Wed Jun 05 11:14:27 2013 +0200 @@ -0,0 +1,79 @@ +/* + * 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 + * . + * + * 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.plugin.validator; + + +public class PluginConfigurationValidatorException extends Exception { + + private static final long serialVersionUID = 1L; + private String filePath; + + /** + * Constructor of PluginConfigurationValidatorException + * @param filePath must include the protocol + * @param message the detailed message + */ + public PluginConfigurationValidatorException(String filePath, String message) { + super(message); + this.filePath = computeFilePath(filePath); + } + + /** + * Constructor of PluginConfigurationValidatorException + * @param filePath must include the protocol + * @param message the detailed message + */ + public PluginConfigurationValidatorException(String filePath, String message, Throwable cause) { + super(message, cause); + this.filePath = computeFilePath(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); + } + +} diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginValidator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/PluginValidator.java Wed Jun 05 11:14:27 2013 +0200 @@ -0,0 +1,71 @@ +/* + * 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 + * . + * + * 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.plugin.validator; + +import java.io.IOException; +import java.net.URL; + +import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.xml.sax.SAXException; + +import com.redhat.thermostat.plugin.validator.internal.ConfigurationValidatorErrorHandler; + + +public class PluginValidator { + + public void validate(StreamSource plugin) throws PluginConfigurationValidatorException { + URL schemaUrl = PluginValidator.class.getResource("/thermostat-plugin.xsd"); + SchemaFactory schemaFactory = + SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + + try { + Schema schema = schemaFactory.newSchema(schemaUrl); + Validator validator = schema.newValidator(); + validator.setErrorHandler(new ConfigurationValidatorErrorHandler()); + validator.validate(plugin); + } catch (IOException | SAXException exception) { + throw new PluginConfigurationValidatorException + (plugin.getSystemId(), exception.getLocalizedMessage(), exception); + } + } + +} diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/internal/ConfigurationValidatorErrorHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/internal/ConfigurationValidatorErrorHandler.java Wed Jun 05 11:14:27 2013 +0200 @@ -0,0 +1,149 @@ +/* + * 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 + * . + * + * 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.plugin.validator.internal; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import com.redhat.thermostat.plugin.validator.locale.LocaleResources; +import com.redhat.thermostat.shared.locale.Translate; +import com.redhat.thermostat.common.utils.LoggingUtils; + +public class ConfigurationValidatorErrorHandler implements ErrorHandler { + + private static final Logger logger = LoggingUtils.getLogger(ConfigurationValidatorErrorHandler.class); + private int warningsErrorsCounter = 0; + private static final Translate translator = LocaleResources.createLocalizer(); + + private enum ErrorType { + WARNING, + ERROR, + FATAL_ERROR; + } + + @Override + public void warning(SAXParseException exception) throws SAXException { + warningsErrorsCounter++; + printInfo(exception, ErrorType.WARNING); + } + + @Override + public void error(SAXParseException exception) throws SAXParseException { + warningsErrorsCounter++; + printInfo(exception, ErrorType.ERROR); + } + + @Override + public void fatalError(SAXParseException exception) throws SAXParseException { + if (warningsErrorsCounter == 0) { + printInfo(exception, ErrorType.FATAL_ERROR); + logger.warning("XML not well formed"); + } + } + + private static void printInfo(SAXParseException e, ErrorType type) { + int columnNumber = e.getColumnNumber(); + int lineNumber = e.getLineNumber(); + + StringBuffer buffer = new StringBuffer(); + + String firstLine = null; + String secondLine = null; + String thirdLine = null; + String errorLine = null; + String pointer = ""; + String absolutePath = e.getSystemId(); + absolutePath = absolutePath.substring(5); + + Map translateKeys = new HashMap<>(); + translateKeys.put(ErrorType.ERROR, LocaleResources.VALIDATION_ERROR); + translateKeys.put(ErrorType.WARNING, LocaleResources.VALIDATION_WARNING); + translateKeys.put(ErrorType.FATAL_ERROR, LocaleResources.VALIDATION_FATAL_ERROR); + + try { + BufferedReader br = new BufferedReader(new FileReader(absolutePath)); + for (int i = 1; i < lineNumber-3; i++) { + br.readLine(); + } + firstLine = br.readLine(); + secondLine = br.readLine(); + thirdLine = br.readLine(); + errorLine = br.readLine(); + + for (int j = 1; j < columnNumber-1; j++) { + pointer = pointer.concat(" "); + } + pointer = pointer.concat("^"); + br.close(); + } catch (IOException exception) { + System.out.println("File not found!");; + } + + buffer.append(translator.localize( + translateKeys.get(type), + absolutePath, + Integer.toString(lineNumber), + Integer.toString(columnNumber)).getContents()); + + buffer.append(formatMessage(e.getLocalizedMessage()) + "\n\n"); + buffer.append(firstLine + "\n"); + buffer.append(secondLine + "\n"); + buffer.append(thirdLine + "\n"); + buffer.append(errorLine + "\n"); + buffer.append(pointer + "\n"); + + logger.warning("\n" + buffer.toString()); + } + + private static String formatMessage(String message) { + String[] arguments = message.split("\"http://icedtea.classpath.org/thermostat/plugins/v1.0\":"); + int size = arguments.length; + String output = ""; + for (int i = 0; i < size; i++) { + output=output.concat(arguments[i]); + } + return output; + } +} diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/locale/LocaleResources.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/src/main/java/com/redhat/thermostat/plugin/validator/locale/LocaleResources.java Wed Jun 05 11:14:27 2013 +0200 @@ -0,0 +1,55 @@ +/* + * 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 + * . + * + * 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.plugin.validator.locale; + +import com.redhat.thermostat.shared.locale.Translate; + + +public enum LocaleResources { + + VALIDATION_WARNING, + VALIDATION_ERROR, + VALIDATION_FATAL_ERROR, + ; + + static final String RESOURCE_BUNDLE = "com.redhat.thermostat.plugin.validator.strings"; + + public static Translate createLocalizer() { + return new Translate<>(RESOURCE_BUNDLE, LocaleResources.class); + } + +} diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/src/main/resources/com/redhat/thermostat/plugin/validator/strings.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/src/main/resources/com/redhat/thermostat/plugin/validator/strings.properties Wed Jun 05 11:14:27 2013 +0200 @@ -0,0 +1,3 @@ +VALIDATION_WARNING = Warning in file {0}:{1}.{2}\n +VALIDATION_ERROR = Error in file {0}:{1}.{2}\n +VALIDATION_FATAL_ERROR = Fatal error in file {0}:{1}.{2}\n \ No newline at end of file diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/PluginValidatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/PluginValidatorTest.java Wed Jun 05 11:14:27 2013 +0200 @@ -0,0 +1,227 @@ +/* + * 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 + * . + * + * 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.plugin.validator; + + +import static org.junit.Assert.fail; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import javax.xml.transform.stream.StreamSource; + +import org.junit.Test; + +public class PluginValidatorTest { + + @Test + public void validateEmptyConfiguration() throws IOException { + String config = "\n"; + File testFile = createFile("testSystemId", config); + PluginValidator validator = new PluginValidator(); + try { + validator.validate(new StreamSource(testFile)); + fail("should not come here"); + } catch (PluginConfigurationValidatorException e) { + //pass + } finally { + testFile.delete(); + } + } + + @Test + public void canValidatePluginXMLMultipleTimes() throws Exception { + + try { + String config = "\n" + + "\n" + + " \n" + + " \n" + + " test\n" + + " \n" + + " foo\n" + + " bar\n" + + " baz\n" + + " \n" + + " \n" + + " thermostat-foo\n" + + " \n" + + " \n" + + " \n" + + ""; + File testFile = createFile("testSystemId", config); + PluginValidator validator = new PluginValidator(); + validator.validate(new StreamSource(testFile)); + testFile.delete(); + + config = "\n" + + "\n" + + " \n" + + " \n" + + " test\n" + + " \n" + + " foo\n" + + " bar\n" + + " baz\n" + + " \n" + + " \n" + + " thermostat-foo\n" + + " \n" + + " \n" + + " \n" + + ""; + File testFile2 = createFile("testSystemId", config); + PluginValidator validator2 = new PluginValidator(); + validator2.validate(new StreamSource(testFile)); + testFile2.delete(); + } catch (PluginConfigurationValidatorException e) { + fail("should not reach here, plugin.xml should be validated according to schema"); + } + } + + @Test + public void validationFailsOnInvalidPluginFile() throws Exception { + String config = "\n" + + "\n" + + " \n" + + " \n" + // Error line + " \n" + + " test\n" + + " \n" + + " foo\n" + + " bar\n" + + " baz\n" + + " \n" + + " \n" + + " thermostat-foo\n" + + " \n" + + " \n" + + " \n" + + ""; + + File testFile = createFile("testSystemId", config); + PluginValidator validator = new PluginValidator(); + try { + validator.validate(new StreamSource(testFile)); + fail("plugin.xml should not validate according to schema"); + } catch (PluginConfigurationValidatorException e) { + //pass + } finally { + testFile.delete(); + } + } + + @Test + public void canValidateCorrectFile() throws IOException { + String config = "\n" + + "\n" + + " \n" + + " \n" + + " test\n" + + " just a test\n" + + " \n" + + " \n" + + " true\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " cli\n" + + " \n" + + " \n" + + " \n \t \nfoo\t \n \n\n" + + " \tbar baz\n\n" + + " buzz\n" + + " \n" + + " \n\t\n\t \t\t\n" + + " \t\t\t thermostat-foo\n\t\t\n\n" + + " \n" + + " \n" + + " \n" + + ""; + + File testFile = createFile("testSystemId", config); + PluginValidator validator = new PluginValidator(); + try { + validator.validate(new StreamSource(testFile)); + } catch (PluginConfigurationValidatorException e) { + fail("should not reach here, plugin.xml should be validated according to schema"); + } finally { + testFile.delete(); + } + + } + + private File createFile(String fileName, String contents) throws IOException { + FileWriter fstream = new FileWriter(fileName); + BufferedWriter out = new BufferedWriter(fstream); + out.write(contents); + out.close(); + return new File(fileName); + } + +} diff -r a746c19af58f -r aa48ed4752c1 thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/locale/LocaleResourcesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thermostat-plugin-validator/src/test/java/com/redhat/thermostat/plugin/validator/locale/LocaleResourcesTest.java Wed Jun 05 11:14:27 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 + * . + * + * 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.plugin.validator.locale; + +import com.redhat.thermostat.testutils.AbstractLocaleResourcesTest; + +public class LocaleResourcesTest extends AbstractLocaleResourcesTest { + + @Override + protected Class getEnumClass() { + return LocaleResources.class; + } + + @Override + protected String getResourceBundle() { + return LocaleResources.RESOURCE_BUNDLE; + } + +}