Merge "Do not use deprecated destroyConfigBean in config tests"
authorTony Tkacik <ttkacik@cisco.com>
Wed, 4 Jun 2014 14:25:52 +0000 (14:25 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 4 Jun 2014 14:25:52 +0000 (14:25 +0000)
24 files changed:
opendaylight/config/logback-config-loader/pom.xml [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/Activator.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/impl/LogbackConfigUtil.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/impl/LogbackConfigurationLoader.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/LogbackConfigurationLoaderTest.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/TestAppender.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Debugger.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Errorer.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Informer.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Tracer.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Warner.java [new file with mode: 0644]
opendaylight/config/logback-config-loader/src/test/resources/logback-test.xml [new file with mode: 0755]
opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt.xml [new file with mode: 0755]
opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt2.xml [new file with mode: 0755]
opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt3.xml [new file with mode: 0755]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/NetconfDeviceSalFacade.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/XmlReader.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/json/to/cnsn/test/JsonToCnSnTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/InvokeRpcMethodTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPutOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/xml/to/cnsn/test/XmlToCnSnTest.java

diff --git a/opendaylight/config/logback-config-loader/pom.xml b/opendaylight/config/logback-config-loader/pom.xml
new file mode 100644 (file)
index 0000000..03ff65f
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<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>org.opendaylight.controller</groupId>
+    <artifactId>config-plugin-parent</artifactId>
+    <version>0.2.5-SNAPSHOT</version>
+    <relativePath>../config-plugin-parent</relativePath>
+  </parent>
+  <artifactId>logback-config-loader</artifactId>
+  <packaging>bundle</packaging>
+  <name>${project.artifactId}</name>
+  <prerequisites>
+    <maven>3.0.4</maven>
+  </prerequisites>
+
+  <dependencies>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+
+    <!-- test dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Bundle-Activator>org.opendaylight.controller.logback.config.loader.Activator</Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/Activator.java b/opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/Activator.java
new file mode 100644 (file)
index 0000000..99866d5
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader;
+
+import java.io.File;
+import java.util.List;
+
+import org.opendaylight.controller.logback.config.loader.impl.LogbackConfigUtil;
+import org.opendaylight.controller.logback.config.loader.impl.LogbackConfigurationLoader;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * default activator for loading multiple logback configuration files
+ */
+public class Activator implements BundleActivator {
+
+    /**
+     * expected environment variable name, containing the root folder containing
+     * logback configurations
+     */
+    private static final String LOGBACK_CONFIG_D = "logback.config.d";
+    private static Logger LOG = LoggerFactory.getLogger(Activator.class);
+
+    @Override
+    public void start(BundleContext context) {
+        LOG.info("Starting logback configuration loader");
+        String logbackConfigRoot = System.getProperty(LOGBACK_CONFIG_D);
+        LOG.debug("configRoot: {}", logbackConfigRoot);
+        if (logbackConfigRoot != null) {
+            File logbackConfigRootFile = new File(logbackConfigRoot);
+            List<File> sortedConfigFiles = LogbackConfigUtil.harvestSortedConfigFiles(logbackConfigRootFile);
+            LogbackConfigurationLoader.load(true, sortedConfigFiles.toArray());
+        }
+    }
+
+    @Override
+    public void stop(BundleContext context) {
+        LOG.info("Stopping logback configuration loader");
+        // TODO: need reset/reload default config?
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/impl/LogbackConfigUtil.java b/opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/impl/LogbackConfigUtil.java
new file mode 100644 (file)
index 0000000..ddf14d7
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.impl;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * logback config utils
+ */
+public final class LogbackConfigUtil {
+
+    /** logback config file pattern (*.xml) */
+    protected static final String LOGBACK_CONFIG_FILE_REGEX_SEED = ".+\\.xml";
+    private static final Logger LOG = LoggerFactory
+            .getLogger(LogbackConfigUtil.class);
+
+    /**
+     *  forbidden ctor
+     */
+    private LogbackConfigUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @param logConfigRoot folder containing configuration files
+     * @return sorted list of found files
+     */
+    public static List<File> harvestSortedConfigFiles(File logConfigRoot) {
+        final Pattern xmlFilePattern = Pattern.compile(LOGBACK_CONFIG_FILE_REGEX_SEED);
+        File[] configs = logConfigRoot.listFiles(new FileFilter() {
+            @Override
+            public boolean accept(File pathname) {
+                return pathname.isFile()
+                        && xmlFilePattern.matcher(pathname.getName()).find();
+            }
+        });
+
+        List<File> sortedConfigFiles = new ArrayList<File>(configs.length);
+        for (File cfgItem : configs) {
+            LOG.trace("config: {}", cfgItem.toURI());
+            sortedConfigFiles.add(cfgItem);
+        }
+        Collections.sort(sortedConfigFiles);
+
+        return sortedConfigFiles;
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/impl/LogbackConfigurationLoader.java b/opendaylight/config/logback-config-loader/src/main/java/org/opendaylight/controller/logback/config/loader/impl/LogbackConfigurationLoader.java
new file mode 100644 (file)
index 0000000..2aa6b1a
--- /dev/null
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) 201 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.impl;
+
+import java.io.File;
+import java.net.URL;
+
+import org.slf4j.ILoggerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.StatusPrinter;
+
+/**
+ * Logback configuration loader.
+ * Strategy:
+ * <ol>
+ * <li>reset actual configuration (probably default configuration)</li>
+ * <li>load all given logback config xml files in given order</li>
+ * </ol>
+ */
+public final class LogbackConfigurationLoader {
+
+    private static final Logger LOG = LoggerFactory
+            .getLogger(LogbackConfigurationLoader.class);
+
+    /**
+     *  forbidden ctor
+     */
+    private LogbackConfigurationLoader() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * load given logback configurations in given order, reset existing configuration before applying first one
+     * @param purgeBefore require reset before loading first config
+     * @param args
+     */
+    public static void load(boolean purgeBefore, Object...args) {
+        try {
+            if (purgeBefore) {
+                resetExistingConfiguration();
+            }
+            for (Object logbackConfig : args) {
+                load(logbackConfig);
+            }
+        } catch (IllegalStateException e) {
+            LOG.warn("loading of multiple logback configurations failed", e);
+        }
+    }
+
+    /**
+     * purge existing logback configuration
+     */
+    public static void resetExistingConfiguration() {
+        LOG.trace("resetting existing logback configuration");
+        LoggerContext context = getLoggerContext();
+        JoranConfigurator configurator = new JoranConfigurator();
+        configurator.setContext(context);
+        context.reset();
+    }
+
+    /**
+     * @return logback context
+     */
+    private static LoggerContext getLoggerContext() {
+        ILoggerFactory context = LoggerFactory.getILoggerFactory();
+        if (context != null && context instanceof LoggerContext) {
+            // now SLF4J is bound to logback in the current environment
+            return (LoggerContext) context;
+        }
+        throw new IllegalStateException("current logger factory is not supported: " + context);
+    }
+
+    /**
+     * @param logbackConfig
+     * @param reset true if previous configuration needs to get purged
+     */
+    public static void load(Object logbackConfig) {
+        LOG.trace("BEFORE logback reconfig");
+        try {
+            LoggerContext context = getLoggerContext();
+            JoranConfigurator configurator = new JoranConfigurator();
+            configurator.setContext(context);
+            if (logbackConfig instanceof String) {
+                configurator.doConfigure((String) logbackConfig);
+            } else if (logbackConfig instanceof URL) {
+                configurator.doConfigure((URL) logbackConfig);
+            } else if (logbackConfig instanceof File) {
+                configurator.doConfigure((File) logbackConfig);
+            }
+
+            LOG.trace("applied {}", logbackConfig);
+            StatusPrinter.printInCaseOfErrorsOrWarnings(context);
+        } catch (IllegalStateException | JoranException je) {
+            LOG.warn("Logback configuration loading failed: {}", logbackConfig);
+        }
+        LOG.trace("AFTER logback reconfig");
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/LogbackConfigurationLoaderTest.java b/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/LogbackConfigurationLoaderTest.java
new file mode 100644 (file)
index 0000000..2e9bf1d
--- /dev/null
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.opendaylight.controller.logback.config.loader.impl.LogbackConfigUtil;
+import org.opendaylight.controller.logback.config.loader.impl.LogbackConfigurationLoader;
+import org.opendaylight.controller.logback.config.loader.test.logwork.Debugger;
+import org.opendaylight.controller.logback.config.loader.test.logwork.Errorer;
+import org.opendaylight.controller.logback.config.loader.test.logwork.Informer;
+import org.opendaylight.controller.logback.config.loader.test.logwork.Tracer;
+import org.opendaylight.controller.logback.config.loader.test.logwork.Warner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * test of logging config loader - {@link LogbackConfigurationLoader}
+ */
+@RunWith(JUnit4.class)
+public class LogbackConfigurationLoaderTest {
+
+    /** logback config root */
+    private static final String LOGBACK_D = "/logback.d";
+    private static Logger LOG = LoggerFactory
+            .getLogger(LogbackConfigurationLoaderTest.class);
+
+    /**
+     * Test of method {@link LogbackConfigurationLoader#load(boolean, Object[])}
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testLoad() throws Exception {
+        File logConfigRoot = new File(LogbackConfigurationLoaderTest.class
+                .getResource(LOGBACK_D).getFile());
+        List<File> sortedConfigFiles = LogbackConfigUtil.harvestSortedConfigFiles(logConfigRoot);
+        LogbackConfigurationLoader.load(true, sortedConfigFiles.toArray());
+
+        LOG.info("LOGBACK ready -> about to use it");
+
+        Tracer.doSomeAction();
+        Debugger.doSomeAction();
+        Informer.doSomeAction();
+        Warner.doSomeAction();
+        Errorer.doSomeAction();
+
+        // check logs
+        String[] expectedLogs = new String[] {
+                "LoggingEvent -> [INFO] org.opendaylight.controller.logback.config.loader.test.LogbackConfigurationLoaderTest: LOGBACK ready -> about to use it",
+                "LoggingEvent -> [TRACE] org.opendaylight.controller.logback.config.loader.test.logwork.Tracer: tracing",
+                "LoggingEvent -> [DEBUG] org.opendaylight.controller.logback.config.loader.test.logwork.Tracer: debugging",
+                "LoggingEvent -> [INFO] org.opendaylight.controller.logback.config.loader.test.logwork.Tracer: infoing",
+                "LoggingEvent -> [WARN] org.opendaylight.controller.logback.config.loader.test.logwork.Tracer: warning",
+                "LoggingEvent -> [ERROR] org.opendaylight.controller.logback.config.loader.test.logwork.Tracer: erroring",
+                "LoggingEvent -> [DEBUG] org.opendaylight.controller.logback.config.loader.test.logwork.Debugger: debugging",
+                "LoggingEvent -> [INFO] org.opendaylight.controller.logback.config.loader.test.logwork.Debugger: infoing",
+                "LoggingEvent -> [WARN] org.opendaylight.controller.logback.config.loader.test.logwork.Debugger: warning",
+                "LoggingEvent -> [ERROR] org.opendaylight.controller.logback.config.loader.test.logwork.Debugger: erroring",
+                "LoggingEvent -> [INFO] org.opendaylight.controller.logback.config.loader.test.logwork.Informer: infoing",
+                "LoggingEvent -> [WARN] org.opendaylight.controller.logback.config.loader.test.logwork.Informer: warning",
+                "LoggingEvent -> [ERROR] org.opendaylight.controller.logback.config.loader.test.logwork.Informer: erroring",
+                "LoggingEvent -> [WARN] org.opendaylight.controller.logback.config.loader.test.logwork.Warner: warning",
+                "LoggingEvent -> [ERROR] org.opendaylight.controller.logback.config.loader.test.logwork.Warner: erroring",
+                "LoggingEvent -> [ERROR] org.opendaylight.controller.logback.config.loader.test.logwork.Errorer: erroring"
+
+        };
+
+        List<String> logSnapshot = new ArrayList<>(TestAppender.getLogRecord());
+        for (String logLine : logSnapshot) {
+            LOG.info("\"{}\",", logLine);
+        }
+
+        Assert.assertArrayEquals(expectedLogs, logSnapshot.toArray());
+    }
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/TestAppender.java b/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/TestAppender.java
new file mode 100644 (file)
index 0000000..b273d27
--- /dev/null
@@ -0,0 +1,145 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.qos.logback.classic.spi.LoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.LogbackException;
+import ch.qos.logback.core.filter.Filter;
+import ch.qos.logback.core.spi.FilterReply;
+import ch.qos.logback.core.status.Status;
+
+/**
+ * dummy appender for collecting log messages
+ *
+ * @param <E>
+ */
+public class TestAppender<E> implements Appender<E> {
+
+    private boolean started;
+    private Context context;
+    private String name;
+
+    private static List<String> logRecord = new ArrayList<>();
+
+    @Override
+    public void start() {
+        started = true;
+    }
+
+    @Override
+    public void stop() {
+        started = false;
+    }
+
+    @Override
+    public boolean isStarted() {
+        return started;
+    }
+
+    @Override
+    public void setContext(Context context) {
+        this.context = context;
+    }
+
+    @Override
+    public Context getContext() {
+        return context;
+    }
+
+    @Override
+    public void addStatus(Status status) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addInfo(String msg) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addInfo(String msg, Throwable ex) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addWarn(String msg) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addWarn(String msg, Throwable ex) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addError(String msg) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addError(String msg, Throwable ex) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void addFilter(Filter<E> newFilter) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void clearAllFilters() {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public List<Filter<E>> getCopyOfAttachedFiltersList() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public FilterReply getFilterChainDecision(E event) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void doAppend(E event) throws LogbackException {
+        if (event instanceof LoggingEvent) {
+            LoggingEvent lEvent = (LoggingEvent) event;
+            logRecord.add(String.format("%s -> [%s] %s: %s", event.getClass()
+                    .getSimpleName(), lEvent.getLevel(),
+                    lEvent.getLoggerName(), lEvent.getMessage()));
+        } else {
+            logRecord.add(event.getClass() + " -> " + event.toString());
+        }
+    }
+
+    @Override
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the logRecord
+     */
+    public static List<String> getLogRecord() {
+        return logRecord;
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Debugger.java b/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Debugger.java
new file mode 100644 (file)
index 0000000..a8052f7
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.test.logwork;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * dummy logging guy
+ */
+public class Debugger {
+
+    private static Logger LOG = LoggerFactory.getLogger(Debugger.class);
+
+    /**
+     * all logging
+     */
+    public static void doSomeAction() {
+        LOG.trace("tracing");
+        LOG.debug("debugging");
+        LOG.info("infoing");
+        LOG.warn("warning");
+        LOG.error("erroring");
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Errorer.java b/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Errorer.java
new file mode 100644 (file)
index 0000000..0bcd830
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.test.logwork;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * dummy logging guy
+ */
+public class Errorer {
+
+    private static Logger LOG = LoggerFactory.getLogger(Errorer.class);
+
+    /**
+     * all logging
+     */
+    public static void doSomeAction() {
+        LOG.trace("tracing");
+        LOG.debug("debugging");
+        LOG.info("infoing");
+        LOG.warn("warning");
+        LOG.error("erroring");
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Informer.java b/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Informer.java
new file mode 100644 (file)
index 0000000..44f0931
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.test.logwork;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * dummy logging guy
+ */
+public class Informer {
+
+    private static Logger LOG = LoggerFactory.getLogger(Informer.class);
+
+    /**
+     * all logging
+     */
+    public static void doSomeAction() {
+        LOG.trace("tracing");
+        LOG.debug("debugging");
+        LOG.info("infoing");
+        LOG.warn("warning");
+        LOG.error("erroring");
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Tracer.java b/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Tracer.java
new file mode 100644 (file)
index 0000000..70df607
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.test.logwork;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * dummy logging guy
+ */
+public class Tracer {
+
+    private static Logger LOG = LoggerFactory.getLogger(Tracer.class);
+
+    /**
+     * all logging
+     */
+    public static void doSomeAction() {
+        LOG.trace("tracing");
+        LOG.debug("debugging");
+        LOG.info("infoing");
+        LOG.warn("warning");
+        LOG.error("erroring");
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Warner.java b/opendaylight/config/logback-config-loader/src/test/java/org/opendaylight/controller/logback/config/loader/test/logwork/Warner.java
new file mode 100644 (file)
index 0000000..8093180
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.logback.config.loader.test.logwork;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * dummy logging guy
+ */
+public class Warner {
+
+    private static Logger LOG = LoggerFactory.getLogger(Warner.class);
+
+    /**
+     * all logging
+     */
+    public static void doSomeAction() {
+        LOG.trace("tracing");
+        LOG.debug("debugging");
+        LOG.info("infoing");
+        LOG.warn("warning");
+        LOG.error("erroring");
+    }
+
+}
diff --git a/opendaylight/config/logback-config-loader/src/test/resources/logback-test.xml b/opendaylight/config/logback-config-loader/src/test/resources/logback-test.xml
new file mode 100755 (executable)
index 0000000..7fb760a
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<configuration debug="true">\r
+\r
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
+    <encoder>\r
+      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>\r
+    </encoder>\r
+  </appender>\r
+\r
+  <root level="INFO">\r
+    <appender-ref ref="STDOUT" />\r
+  </root>\r
+\r
+  <!--  Base log level  -->\r
+  <logger name="org.opendaylight.controller.logback.config.loader" level="DEBUG"/>\r
+\r
+</configuration>\r
diff --git a/opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt.xml b/opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt.xml
new file mode 100755 (executable)
index 0000000..ca489d5
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<configuration debug="false">\r
+\r
+  <appender name="TEST" class="org.opendaylight.controller.logback.config.loader.test.TestAppender"/>\r
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
+    <encoder>\r
+      <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>\r
+    </encoder>\r
+  </appender>\r
+\r
+  <root level="INFO">\r
+    <appender-ref ref="TEST" />\r
+    <appender-ref ref="STDOUT" />\r
+  </root>\r
+\r
+  <!--  Base log level  -->\r
+  <logger name="org.opendaylight.controller.logback.config.loader" level="INFO"/>\r
+\r
+</configuration>\r
diff --git a/opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt2.xml b/opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt2.xml
new file mode 100755 (executable)
index 0000000..89f82c5
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<configuration debug="false">\r
+\r
+  <!--  Base log level  -->\r
+  <logger name="org.opendaylight.controller.logback.config.loader" level="DEBUG"/>\r
+  <logger name="org.opendaylight.controller.logback.config.loader.test.logwork.Tracer" level="TRACE"/>\r
+<!--   <logger name="org.opendaylight.controller.logback.config.loader.test.logwork.Debugger" level="DEBUG"/> -->\r
+  <logger name="org.opendaylight.controller.logback.config.loader.test.logwork.Informer" level="DEBUG"/>\r
+  <logger name="org.opendaylight.controller.logback.config.loader.test.logwork.Warner" level="ERROR"/>\r
+  <logger name="org.opendaylight.controller.logback.config.loader.test.logwork.Errorer" level="ERROR"/>\r
+\r
+</configuration>\r
diff --git a/opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt3.xml b/opendaylight/config/logback-config-loader/src/test/resources/logback.d/logback-alt3.xml
new file mode 100755 (executable)
index 0000000..a37b6f7
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<configuration debug="false">\r
+  <root level="INFO">\r
+    <appender-ref ref="TEST" />\r
+  </root>\r
+\r
+  <logger name="org.opendaylight.controller.logback.config.loader.test.logwork.Informer" level="INFO"/>\r
+  <logger name="org.opendaylight.controller.logback.config.loader.test.logwork.Warner" level="WARN"/>\r
+\r
+  <logger name="org.opendaylight.controller.logback.config.loader.test.LogbackConfigurationLoaderTest" level="TRACE"/>\r
+</configuration>\r
index f39c4d579212984ba0e3d4d254e49d8110e31d42..37b87045d5f0f9061f9c276183fb6fc156879060 100644 (file)
@@ -7,11 +7,11 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.sal;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-
 import java.util.concurrent.ExecutorService;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.connect.api.RemoteDeviceHandler;
@@ -29,11 +29,9 @@ import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Lists;
-
 public final class NetconfDeviceSalFacade implements AutoCloseable, RemoteDeviceHandler<NetconfSessionCapabilities> {
 
-    private static final Logger logger= LoggerFactory.getLogger(NetconfDeviceTwoPhaseCommitTransaction.class);
+    private static final Logger logger= LoggerFactory.getLogger(NetconfDeviceSalFacade.class);
     private static final InstanceIdentifier ROOT_PATH = InstanceIdentifier.builder().toInstance();
 
     private final RemoteDeviceId id;
@@ -88,7 +86,11 @@ public final class NetconfDeviceSalFacade implements AutoCloseable, RemoteDevice
         }
 
         if (failedRpcs.isEmpty() == false) {
-            logger.warn("{}: Some rpcs from netconf device were not registered: {}", id, failedRpcs);
+            if (logger.isDebugEnabled()) {
+                logger.warn("{}: Some rpcs from netconf device were not registered: {}", id, failedRpcs);
+            } else {
+                logger.warn("{}: Some rpcs from netconf device were not registered: {}", id, failedRpcs.keySet());
+            }
         }
     }
 
index 593c104dfd63e24efe268358e79bdb5a8a9e5a56..1f7b061e921cd057d13ece0002e998973fb66db2 100644 (file)
@@ -31,6 +31,12 @@ class JsonReader {
         JsonParser parser = new JsonParser();
 
         JsonElement rootElement = parser.parse(new InputStreamReader(entityStream));
+        if( rootElement.isJsonNull() )
+        {
+            //no content, so return null to indicate no input
+            return null;
+        }
+
         if (!rootElement.isJsonObject()) {
             throw new UnsupportedFormatException("Root element of Json has to be Object");
         }
index 5b95f0de1ada80408f24670c310dce35a306ab5d..171805a1798a872ff7f42b821f3201dced670b9f 100644 (file)
@@ -9,6 +9,8 @@ package org.opendaylight.controller.sal.rest.impl;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import java.io.BufferedInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
 import java.util.Stack;
@@ -32,7 +34,17 @@ public class XmlReader {
     private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
     private XMLEventReader eventReader;
 
-    public CompositeNodeWrapper read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException {
+    public CompositeNodeWrapper read(InputStream entityStream) throws XMLStreamException,
+                                                                      UnsupportedFormatException,
+                                                                      IOException {
+        //Get an XML stream which can be marked, and reset, so we can check and see if there is
+        //any content being provided.
+        entityStream = getMarkableStream(entityStream);
+
+        if( isInputStreamEmpty( entityStream ) ) {
+            return null;
+        }
+
         eventReader = xmlInputFactory.createXMLEventReader(entityStream);
 
         if (eventReader.hasNext()) {
@@ -91,6 +103,31 @@ public class XmlReader {
         return root;
     }
 
+    /**
+     * If the input stream is not markable, then it wraps the input stream with a buffered stream,
+     * which is mark able. That way we can check if the stream is empty safely.
+     * @param entityStream
+     * @return
+     */
+    private InputStream getMarkableStream(InputStream entityStream) {
+        if( !entityStream.markSupported() )
+        {
+            entityStream = new BufferedInputStream( entityStream );
+        }
+        return entityStream;
+    }
+
+    private boolean isInputStreamEmpty(InputStream entityStream)
+            throws IOException {
+        boolean isEmpty = false;
+        entityStream.mark( 1 );
+        if( entityStream.read() == -1 ){
+            isEmpty = true;
+        }
+        entityStream.reset();
+        return isEmpty;
+    }
+
     private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
         checkArgument(event != null, "XML Event cannot be NULL!");
         if (event.isStartElement()) {
index ad682bc8291d50e52d674607e30142009bac459e..c0ce90e15dde780a18e40e0e216c78059c9183fc 100644 (file)
@@ -8,13 +8,6 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
 import java.net.URI;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -38,21 +31,11 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.rest.api.Draft02;
 import org.opendaylight.controller.sal.rest.api.RestconfService;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.restconf.rpc.impl.BrokerRpcExecutor;
 import org.opendaylight.controller.sal.restconf.rpc.impl.MountPointRpcExecutor;
 import org.opendaylight.controller.sal.restconf.rpc.impl.RpcExecutor;
-import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
-import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
-import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
-import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
-import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.RestCodec;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorTag;
-import org.opendaylight.controller.sal.restconf.impl.RestconfError.ErrorType;
 import org.opendaylight.controller.sal.streams.listeners.ListenerAdapter;
 import org.opendaylight.controller.sal.streams.listeners.Notificator;
 import org.opendaylight.controller.sal.streams.websockets.WebSocketServer;
@@ -84,6 +67,13 @@ import org.opendaylight.yangtools.yang.model.util.EmptyType;
 import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
 
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
 public class RestconfImpl implements RestconfService {
     private final static RestconfImpl INSTANCE = new RestconfImpl();
 
@@ -401,13 +391,36 @@ public class RestconfImpl implements RestconfService {
         URI rpcNamespace = rpcName.getNamespace();
         if (Objects.equal(rpcNamespace.toString(), SAL_REMOTE_NAMESPACE) &&
             Objects.equal(rpcName.getLocalName(), SAL_REMOTE_RPC_SUBSRCIBE)) {
-
             return invokeSalRemoteRpcSubscribeRPC(payload, rpc.getRpcDefinition());
         }
 
+        validateInput( rpc.getRpcDefinition().getInput(), payload );
+
         return callRpc(rpc, payload);
     }
 
+    private void validateInput(DataSchemaNode inputSchema, CompositeNode payload) {
+        if( inputSchema != null && payload == null )
+        {
+            //expected a non null payload
+            throw new RestconfDocumentedException( "Input is required.",
+                                                   ErrorType.PROTOCOL,
+                                                   ErrorTag.MALFORMED_MESSAGE );
+        }
+        else if( inputSchema == null && payload != null )
+        {
+            //did not expect any input
+            throw new RestconfDocumentedException( "No input expected.",
+                                                   ErrorType.PROTOCOL,
+                                                   ErrorTag.MALFORMED_MESSAGE );
+        }
+        //else
+        //{
+            //TODO: Validate "mandatory" and "config" values here??? Or should those be
+        // validate in a more central location inside MD-SAL core.
+        //}
+    }
+
     private StructuredData invokeSalRemoteRpcSubscribeRPC(final CompositeNode payload,
                                                           final RpcDefinition rpc) {
         final CompositeNode value = this.normalizeNode(payload, rpc.getInput(), null);
@@ -455,8 +468,7 @@ public class RestconfImpl implements RestconfService {
             throw new RestconfDocumentedException(
                     "Content must be empty.", ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
         }
-        final RpcExecutor rpc = resolveIdentifierInInvokeRpc(identifier);
-        return callRpc(rpc, null);
+        return invokeRpc( identifier, (CompositeNode)null );
     }
 
     private RpcExecutor resolveIdentifierInInvokeRpc(final String identifier) {
@@ -586,6 +598,9 @@ public class RestconfImpl implements RestconfService {
     @Override
     public Response updateConfigurationData(final String identifier, final CompositeNode payload) {
         final InstanceIdWithSchemaNode iiWithData = this.controllerContext.toInstanceIdentifier(identifier);
+
+        validateInput(iiWithData.getSchemaNode(), payload);
+
         MountInstance mountPoint = iiWithData.getMountPoint();
         final CompositeNode value = this.normalizeNode(payload, iiWithData.getSchemaNode(), mountPoint);
         RpcResult<TransactionStatus> status = null;
@@ -610,6 +625,12 @@ public class RestconfImpl implements RestconfService {
 
     @Override
     public Response createConfigurationData(final String identifier, final CompositeNode payload) {
+        if( payload == null ) {
+            throw new RestconfDocumentedException( "Input is required.",
+                    ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE );
+        }
+
         URI payloadNS = this.namespace(payload);
         if (payloadNS == null) {
             throw new RestconfDocumentedException(
@@ -685,6 +706,12 @@ public class RestconfImpl implements RestconfService {
 
     @Override
     public Response createConfigurationData(final CompositeNode payload) {
+        if( payload == null ) {
+            throw new RestconfDocumentedException( "Input is required.",
+                    ErrorType.PROTOCOL,
+                    ErrorTag.MALFORMED_MESSAGE );
+        }
+
         URI payloadNS = this.namespace(payload);
         if (payloadNS == null) {
             throw new RestconfDocumentedException(
index 3c70cca0f87806d28b73273423fa7b546b1631c6..47e329cc3ef11a4cdfc8842c9a1285a445989517 100644 (file)
@@ -9,8 +9,11 @@ package org.opendaylight.controller.sal.restconf.impl.json.to.cnsn.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -176,6 +179,14 @@ public class JsonToCnSnTest {
 
     }
 
+    @Test
+    public void testJsonBlankInput() throws Exception{
+        InputStream inputStream = new ByteArrayInputStream( "".getBytes() );
+        CompositeNode compositeNode =
+                JsonToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
+        assertNull( compositeNode );
+    }
+
     /**
      * Tests whether namespace <b>stay unchanged</b> if concrete values are
      * present in composite or simple node and if the method for update is
index c0c86c3f25384fdbd3ea979debef62fa7f1512ab..910ca8e20aab453d02b4e320b0493775666d3575 100644 (file)
@@ -308,7 +308,7 @@ public class InvokeRpcMethodTest {
         ListenableFuture<RpcResult<CompositeNode>> mockListener = mock( ListenableFuture.class );
         when( mockListener.get() ).thenReturn( rpcResult );
 
-        QName cancelToastQName = QName.create( "cancelToast" );
+        QName cancelToastQName = QName.create( "namespace", "2014-05-28", "cancelToast" );
 
         RpcDefinition mockRpc = mock( RpcDefinition.class );
         when( mockRpc.getQName() ).thenReturn( cancelToastQName );
index ce460fe4746d9137f0775f6536297e5cc841ab44..cfbc9fdb767c2c9c8fb8bc7e8d4954f5e5e210e8 100644 (file)
@@ -149,6 +149,8 @@ public class RestPostOperationTest extends JerseyTest {
 
         mockCommitConfigurationDataPostMethod(TransactionStatus.FAILED);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
+
+        assertEquals( 400, post(uri, MediaType.APPLICATION_JSON, "" ));
     }
 
     @Test
@@ -172,6 +174,8 @@ public class RestPostOperationTest extends JerseyTest {
         assertEquals(204, post(uri, Draft02.MediaTypes.DATA + XML, xmlData4));
         uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont";
         assertEquals(204, post(uri, Draft02.MediaTypes.DATA + XML, xmlData3));
+
+        assertEquals( 400, post(uri, MediaType.APPLICATION_JSON, "" ));
     }
 
     private void mockInvokeRpc(CompositeNode result, boolean sucessful) {
index 3af2945526466fabf3e9c139b79eb4134107752f..77b39b73529dca04ee8b6279b824c01a4361bf25 100644 (file)
@@ -22,6 +22,7 @@ import java.util.concurrent.Future;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -31,6 +32,7 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.sal.core.api.mount.MountInstance;
 import org.opendaylight.controller.sal.core.api.mount.MountService;
 import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.RestconfDocumentedExceptionMapper;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
 import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -86,6 +88,7 @@ public class RestPutOperationTest extends JerseyTest {
         resourceConfig = resourceConfig.registerInstances(restconfImpl, StructuredDataToXmlProvider.INSTANCE,
                 StructuredDataToJsonProvider.INSTANCE, XmlToCompositeNodeProvider.INSTANCE,
                 JsonToCompositeNodeProvider.INSTANCE);
+        resourceConfig.registerClasses( RestconfDocumentedExceptionMapper.class );
         return resourceConfig;
     }
 
@@ -100,6 +103,15 @@ public class RestPutOperationTest extends JerseyTest {
 
         mockCommitConfigurationDataPutMethod(TransactionStatus.FAILED);
         assertEquals(500, put(uri, MediaType.APPLICATION_XML, xmlData));
+
+        assertEquals( 400, put(uri, MediaType.APPLICATION_JSON, "" ));
+    }
+
+    @Test
+    public void putConfigStatusCodesEmptyBody() throws UnsupportedEncodingException {
+        String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
+        Response resp = target(uri).request( MediaType.APPLICATION_JSON).put(Entity.entity( "", MediaType.APPLICATION_JSON));
+        assertEquals( 400, put(uri, MediaType.APPLICATION_JSON, "" ));
     }
 
     @Test
index 5008d28bbfb26ea0e8d9ef8ab2b1814e8736671d..5cda4a7f52014dc4a9ab3572d9073877ec12e74e 100644 (file)
@@ -9,8 +9,12 @@ package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
@@ -52,4 +56,27 @@ public class XmlToCnSnTest extends YangAndXmlAndDataSchemaLoader {
         assertEquals("121", lf2.getValue());
     }
 
+    @Test
+    public void testXmlBlankInput() throws Exception{
+        InputStream inputStream = new ByteArrayInputStream( "".getBytes() );
+        CompositeNode compositeNode =
+                XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
+
+        assertNull( compositeNode );
+    }
+
+    @Test
+    public void testXmlBlankInputUnmarkableStream() throws Exception{
+        InputStream inputStream = new ByteArrayInputStream( "".getBytes() ){
+            @Override
+            public boolean markSupported() {
+                return false;
+            }
+        };
+        CompositeNode compositeNode =
+                XmlToCompositeNodeProvider.INSTANCE.readFrom(null, null, null, null, null, inputStream);
+
+        assertNull( compositeNode );
+    }
+
 }