changeset 1220:71b72b655b84

Implement check for which categories we allow to get registered. Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-August/007805.html
author Severin Gehwolf <sgehwolf@redhat.com>
date Tue, 06 Aug 2013 12:29:07 +0200
parents 57db66363d91
children 39c571af1003
files host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatCategoryRegistration.java host-cpu/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatCategoryRegistrationTest.java host-memory/common/src/main/java/com/redhat/thermostat/host/memory/common/internal/MemoryStatCategoryRegistration.java host-memory/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration host-memory/common/src/test/java/com/redhat/thermostat/host/memory/common/internal/MemoryStatCategoryRegistrationTest.java numa/common/src/main/java/com/redhat/thermostat/numa/common/internal/NumaDAOCategoryRegistration.java numa/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration numa/common/src/test/java/com/redhat/thermostat/numa/common/internal/NumaDAOCategoryRegistrationTest.java storage/core/src/main/java/com/redhat/thermostat/storage/core/auth/CategoryRegistration.java storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/DAOImplCategoryRegistration.java storage/core/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/DAOImplCategoryRegistrationTest.java thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistration.java thread/collector/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistrationTest.java vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatCategoryRegistration.java vm-classstat/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration vm-classstat/common/src/test/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatCategoryRegistrationTest.java vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatCategoryRegistration.java vm-cpu/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration vm-cpu/common/src/test/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatCategoryRegistrationTest.java vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatCategoryRegistration.java vm-gc/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatCategoryRegistrationTest.java vm-heap-analysis/common/src/main/java/com/redhat/thermostat/vm/heap/analysis/common/internal/HeapDAOCategoryRegistration.java vm-heap-analysis/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration vm-heap-analysis/common/src/test/java/com/redhat/thermostat/vm/heap/analysis/common/internal/HeapDAOCategoryRegistrationTest.java vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOCategoryRegistration.java vm-jmx/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration vm-jmx/common/src/test/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOCategoryRegistrationTest.java vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatCategoryRegistration.java vm-memory/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration vm-memory/common/src/test/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatCategoryRegistrationTest.java web/server/src/main/java/com/redhat/thermostat/web/server/KnownCategoryRegistry.java web/server/src/main/java/com/redhat/thermostat/web/server/KnownCategoryRegistryFactory.java web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java web/server/src/test/java/com/redhat/thermostat/web/server/KnownCategoryRegistryTest.java web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java
diffstat 39 files changed, 2140 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-cpu/common/src/main/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.host.cpu.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class CpuStatCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(1);
+        categories.add(CpuStatDAOImpl.cpuStatCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-cpu/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.host.cpu.common.internal.CpuStatCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-cpu/common/src/test/java/com/redhat/thermostat/host/cpu/common/internal/CpuStatCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.host.cpu.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.host.cpu.common.CpuStatDAO;
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+
+public class CpuStatCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        CpuStatCategoryRegistration reg = new CpuStatCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(1, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(CpuStatDAO.cpuStatCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(CpuStatCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, CpuStatCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration cpuStatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(CpuStatCategoryRegistration.class.getName())) {
+                cpuStatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(cpuStatReg);
+        assertEquals(1, cpuStatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-memory/common/src/main/java/com/redhat/thermostat/host/memory/common/internal/MemoryStatCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.host.memory.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class MemoryStatCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(1);
+        categories.add(MemoryStatDAOImpl.memoryStatCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-memory/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.host.memory.common.internal.MemoryStatCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host-memory/common/src/test/java/com/redhat/thermostat/host/memory/common/internal/MemoryStatCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.host.memory.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.host.memory.common.MemoryStatDAO;
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+
+public class MemoryStatCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        MemoryStatCategoryRegistration reg = new MemoryStatCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(1, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(MemoryStatDAO.memoryStatCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(MemoryStatCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, MemoryStatCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration memoryStatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(MemoryStatCategoryRegistration.class.getName())) {
+                memoryStatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(memoryStatReg);
+        assertEquals(1, memoryStatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/numa/common/src/main/java/com/redhat/thermostat/numa/common/internal/NumaDAOCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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.numa.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.numa.common.NumaDAO;
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class NumaDAOCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(2);
+        categories.add(NumaDAO.numaHostCategory.getName());
+        categories.add(NumaDAO.numaStatCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/numa/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.numa.common.internal.NumaDAOCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/numa/common/src/test/java/com/redhat/thermostat/numa/common/internal/NumaDAOCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,94 @@
+/*
+ * 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.numa.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.numa.common.NumaDAO;
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+
+public class NumaDAOCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        NumaDAOCategoryRegistration reg = new NumaDAOCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(2, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(NumaDAO.numaHostCategory.getName()));
+        assertTrue(categories.contains(NumaDAO.numaStatCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(NumaDAOCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, NumaDAOCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration numaCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(NumaDAOCategoryRegistration.class.getName())) {
+                numaCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(numaCatReg);
+        assertEquals(2, numaCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/core/auth/CategoryRegistration.java	Tue Aug 06 12:29:07 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.storage.core.auth;
+
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.Category;
+
+/**
+ * {@link ServiceLoader} interface used for registering
+ * trusted {@link Category}s. The web storage endpoint
+ * uses implementations of this interface in order to collect
+ * the set of all trusted categories.
+ *
+ */
+public interface CategoryRegistration {
+
+    /**
+     * 
+     * @return The set of category names to register.
+     */
+    Set<String> getCategoryNames();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/dao/DAOImplCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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.storage.internal.dao;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.BackendInfoDAO;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class DAOImplCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(5);
+        categories.add(HostInfoDAO.hostInfoCategory.getName());
+        categories.add(AgentInfoDAO.CATEGORY.getName());
+        categories.add(VmInfoDAO.vmInfoCategory.getName());
+        categories.add(BackendInfoDAO.CATEGORY.getName());
+        categories.add(NetworkInterfaceInfoDAO.networkInfoCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/dao/DAOImplCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,99 @@
+/*
+ * 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.storage.internal.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.dao.AgentInfoDAO;
+import com.redhat.thermostat.storage.dao.BackendInfoDAO;
+import com.redhat.thermostat.storage.dao.HostInfoDAO;
+import com.redhat.thermostat.storage.dao.NetworkInterfaceInfoDAO;
+import com.redhat.thermostat.storage.dao.VmInfoDAO;
+
+public class DAOImplCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        DAOImplCategoryRegistration reg = new DAOImplCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(5, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(HostInfoDAO.hostInfoCategory.getName()));
+        assertTrue(categories.contains(VmInfoDAO.vmInfoCategory.getName()));
+        assertTrue(categories.contains(AgentInfoDAO.CATEGORY.getName()));
+        assertTrue(categories.contains(NetworkInterfaceInfoDAO.networkInfoCategory.getName()));
+        assertTrue(categories.contains(BackendInfoDAO.CATEGORY.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, DAOImplCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration daoImplReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(DAOImplCategoryRegistration.class.getName())) {
+                daoImplReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(1, registrations.size());
+        assertNotNull(daoImplReg);
+        assertEquals(5, daoImplReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistration.java	Tue Aug 06 12:29:07 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.thread.dao.impl;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class ThreadDAOCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(5);
+        categories.add(ThreadDao.DEADLOCK_INFO.getName());
+        categories.add(ThreadDao.THREAD_CAPABILITIES.getName());
+        categories.add(ThreadDao.THREAD_HARVESTING_STATUS.getName());
+        categories.add(ThreadDao.THREAD_INFO.getName());
+        categories.add(ThreadDao.THREAD_SUMMARY.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/collector/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.thread.dao.impl.ThreadDAOCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thread/collector/src/test/java/com/redhat/thermostat/thread/dao/impl/ThreadDAOCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,97 @@
+/*
+ * 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.thread.dao.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+import com.redhat.thermostat.thread.dao.ThreadDao;
+
+public class ThreadDAOCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        ThreadDAOCategoryRegistration reg = new ThreadDAOCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(5, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(ThreadDao.DEADLOCK_INFO.getName()));
+        assertTrue(categories.contains(ThreadDao.THREAD_CAPABILITIES.getName()));
+        assertTrue(categories.contains(ThreadDao.THREAD_INFO.getName()));
+        assertTrue(categories.contains(ThreadDao.THREAD_SUMMARY.getName()));
+        assertTrue(categories.contains(ThreadDao.THREAD_HARVESTING_STATUS.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(ThreadDAOCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, ThreadDAOCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration threadCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(ThreadDAOCategoryRegistration.class.getName())) {
+                threadCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(threadCatReg);
+        assertEquals(5, threadCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/common/src/main/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.vm.classstat.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.vm.classstat.common.VmClassStatDAO;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class VmClassStatCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(1);
+        categories.add(VmClassStatDAO.vmClassStatsCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.vm.classstat.common.internal.VmClassStatCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-classstat/common/src/test/java/com/redhat/thermostat/vm/classstat/common/internal/VmClassStatCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.vm.classstat.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+import com.redhat.thermostat.vm.classstat.common.VmClassStatDAO;
+
+public class VmClassStatCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        VmClassStatCategoryRegistration reg = new VmClassStatCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(1, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(VmClassStatDAO.vmClassStatsCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(VmClassStatCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, VmClassStatCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration vmClassStatCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(VmClassStatCategoryRegistration.class.getName())) {
+                vmClassStatCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(vmClassStatCatReg);
+        assertEquals(1, vmClassStatCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/common/src/main/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.vm.cpu.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.vm.cpu.common.VmCpuStatDAO;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class VmCpuStatCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(1);
+        categories.add(VmCpuStatDAO.vmCpuStatCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.vm.cpu.common.internal.VmCpuStatCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-cpu/common/src/test/java/com/redhat/thermostat/vm/cpu/common/internal/VmCpuStatCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.vm.cpu.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+import com.redhat.thermostat.vm.cpu.common.VmCpuStatDAO;
+
+public class VmCpuStatCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        VmCpuStatCategoryRegistration reg = new VmCpuStatCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(1, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(VmCpuStatDAO.vmCpuStatCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(VmCpuStatCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, VmCpuStatCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration vmCpuStatCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(VmCpuStatCategoryRegistration.class.getName())) {
+                vmCpuStatCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(vmCpuStatCatReg);
+        assertEquals(1, vmCpuStatCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/common/src/main/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.vm.gc.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.vm.gc.common.VmGcStatDAO;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class VmGcStatCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(1);
+        categories.add(VmGcStatDAO.vmGcStatCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.vm.gc.common.internal.VmGcStatCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-gc/common/src/test/java/com/redhat/thermostat/vm/gc/common/internal/VmGcStatCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.vm.gc.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+import com.redhat.thermostat.vm.gc.common.VmGcStatDAO;
+
+public class VmGcStatCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        VmGcStatCategoryRegistration reg = new VmGcStatCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(1, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(VmGcStatDAO.vmGcStatCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(VmGcStatCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, VmGcStatCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration vmGcStatCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(VmGcStatCategoryRegistration.class.getName())) {
+                vmGcStatCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(vmGcStatCatReg);
+        assertEquals(1, vmGcStatCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-heap-analysis/common/src/main/java/com/redhat/thermostat/vm/heap/analysis/common/internal/HeapDAOCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.vm.heap.analysis.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.vm.heap.analysis.common.HeapDAO;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class HeapDAOCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(1);
+        categories.add(HeapDAO.heapInfoCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-heap-analysis/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.vm.heap.analysis.common.internal.HeapDAOCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-heap-analysis/common/src/test/java/com/redhat/thermostat/vm/heap/analysis/common/internal/HeapDAOCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.vm.heap.analysis.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+import com.redhat.thermostat.vm.heap.analysis.common.HeapDAO;
+
+public class HeapDAOCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        HeapDAOCategoryRegistration reg = new HeapDAOCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(1, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(HeapDAO.heapInfoCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(HeapDAOCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, HeapDAOCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration heapCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(HeapDAOCategoryRegistration.class.getName())) {
+                heapCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(heapCatReg);
+        assertEquals(1, heapCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-jmx/common/src/main/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.vm.jmx.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class JmxNotificationDAOCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(2);
+        categories.add(JmxNotificationDAOImpl.NOTIFICATION_STATUS.getName());
+        categories.add(JmxNotificationDAOImpl.NOTIFICATIONS.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-jmx/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.vm.jmx.common.internal.JmxNotificationDAOCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-jmx/common/src/test/java/com/redhat/thermostat/vm/jmx/common/internal/JmxNotificationDAOCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.vm.jmx.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+
+public class JmxNotificationDAOCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        JmxNotificationDAOCategoryRegistration reg = new JmxNotificationDAOCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(2, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(JmxNotificationDAOImpl.NOTIFICATION_STATUS.getName()));
+        assertTrue(categories.contains(JmxNotificationDAOImpl.NOTIFICATIONS.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(JmxNotificationDAOCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, JmxNotificationDAOCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration jmxNotificationCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(JmxNotificationDAOCategoryRegistration.class.getName())) {
+                jmxNotificationCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(jmxNotificationCatReg);
+        assertEquals(2, jmxNotificationCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-memory/common/src/main/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatCategoryRegistration.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,60 @@
+/*
+ * 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.vm.memory.common.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.vm.memory.common.VmMemoryStatDAO;
+
+/**
+ * Registers the category used by this maven module. The web storage
+ * endpoint only allows categories to be registered which it knows of
+ * ahead of time.
+ *
+ */
+public class VmMemoryStatCategoryRegistration implements CategoryRegistration {
+
+    @Override
+    public Set<String> getCategoryNames() {
+        Set<String> categories = new HashSet<>(1);
+        categories.add(VmMemoryStatDAO.vmMemoryStatsCategory.getName());
+        return categories;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-memory/common/src/main/resources/META-INF/services/com.redhat.thermostat.storage.core.auth.CategoryRegistration	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,1 @@
+com.redhat.thermostat.vm.memory.common.internal.VmMemoryStatCategoryRegistration
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-memory/common/src/test/java/com/redhat/thermostat/vm/memory/common/internal/VmMemoryStatCategoryRegistrationTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * 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.vm.memory.common.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+import com.redhat.thermostat.storage.internal.dao.DAOImplCategoryRegistration;
+import com.redhat.thermostat.vm.memory.common.VmMemoryStatDAO;
+
+public class VmMemoryStatCategoryRegistrationTest {
+
+    @Test
+    public void registersAllCategories() {
+        VmMemoryStatCategoryRegistration reg = new VmMemoryStatCategoryRegistration();
+        Set<String> categories = reg.getCategoryNames();
+        assertEquals(1, categories.size());
+        assertFalse("null descriptor not allowed", categories.contains(null));
+        assertTrue(categories.contains(VmMemoryStatDAO.vmMemoryStatsCategory.getName()));
+    }
+    
+    /*
+     * The web storage end-point uses service loader in order to determine the
+     * list of trusted/known categories. This test is to ensure service loading
+     * works for this module's regs. E.g. renaming of the impl class without
+     * changing META-INF/com.redhat.thermostat.storage.core.auth.CategoryRegistration
+     */
+    @Test
+    public void serviceLoaderCanLoadRegistration() {
+        Set<String> expectedClassNames = new HashSet<>();
+        expectedClassNames.add(VmMemoryStatCategoryRegistration.class.getName());
+        expectedClassNames.add(DAOImplCategoryRegistration.class.getName());
+        ServiceLoader<CategoryRegistration> loader = ServiceLoader.load(CategoryRegistration.class, VmMemoryStatCategoryRegistration.class.getClassLoader());
+        List<CategoryRegistration> registrations = new ArrayList<>(1);
+        CategoryRegistration vmMemoryStatCatReg = null;
+        for (CategoryRegistration r: loader) {
+            assertTrue(expectedClassNames.contains(r.getClass().getName()));
+            if (r.getClass().getName().equals(VmMemoryStatCategoryRegistration.class.getName())) {
+                vmMemoryStatCatReg = r;
+            }
+            registrations.add(r);
+        }
+        // storage-core + this module
+        assertEquals(2, registrations.size());
+        assertNotNull(vmMemoryStatCatReg);
+        assertEquals(1, vmMemoryStatCatReg.getCategoryNames().size());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/server/src/main/java/com/redhat/thermostat/web/server/KnownCategoryRegistry.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * 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.web.server;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import com.redhat.thermostat.storage.core.Category;
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+
+/**
+ * Registers trusted category names.
+ *
+ * @see CategoryRegistration
+ * @see Category
+ */
+final class KnownCategoryRegistry {
+
+    private static final ServiceLoader<CategoryRegistration> TRUSTED_CATEGORIES = ServiceLoader
+            .load(CategoryRegistration.class);
+    private final Set<String> trustedCategories;
+    
+    KnownCategoryRegistry() {
+        this(TRUSTED_CATEGORIES);
+    }
+    
+    KnownCategoryRegistry(Iterable<CategoryRegistration> registrations) {
+        trustedCategories = new HashSet<>();
+        for (CategoryRegistration reg: registrations) {
+            Set<String> currentRegs = reg.getCategoryNames();
+            if (currentRegs.contains(null)) {
+                String msg = "null name not allowed!";
+                throw new IllegalStateException(msg);
+            }
+            trustedCategories.addAll(currentRegs);
+        }
+    }
+    
+    Set<String> getRegisteredCategoryNames() {
+        // return a read-only view of registered category names.
+        return Collections.unmodifiableSet(trustedCategories);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/server/src/main/java/com/redhat/thermostat/web/server/KnownCategoryRegistryFactory.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.web.server;
+
+/*
+ * Testing aid in order to be able to inject a KnownCategoryRegistry.
+ *
+ */
+class KnownCategoryRegistryFactory {
+
+    private static KnownCategoryRegistry knownRegistry;
+    
+    static KnownCategoryRegistry getInstance() {
+        if (knownRegistry == null) {
+            return new KnownCategoryRegistry();
+        } else {
+            return knownRegistry;
+        }
+    }
+    
+    static void setInstance(KnownCategoryRegistry reg) {
+        knownRegistry = reg;
+    }
+}
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java	Fri Aug 16 14:59:33 2013 +0200
+++ b/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java	Tue Aug 06 12:29:07 2013 +0200
@@ -156,6 +156,8 @@
     private Set<String> knownStatementDescriptors;
     // read-only map of known descriptors => descriptor metadata
     private Map<String, StatementDescriptorMetadataFactory> descMetadataFactories;
+    // read-only set of all known categories which we allow to get registered.
+    private Set<String> knownCategoryNames;
 
     @Override
     public void init(ServletConfig config) throws ServletException {
@@ -191,6 +193,9 @@
         KnownDescriptorRegistry descRegistry = KnownDescriptorRegistryFactory.getInstance();
         knownStatementDescriptors = descRegistry.getRegisteredDescriptors();
         descMetadataFactories = descRegistry.getDescriptorMetadataFactories();
+        // Set the set of category names which we allow to get registered
+        KnownCategoryRegistry categoryRegistry = KnownCategoryRegistryFactory.getInstance();
+        knownCategoryNames = categoryRegistry.getRegisteredCategoryNames();
     }
     
     @Override
@@ -478,7 +483,15 @@
             } else {
                 // Regular, non-aggregate category. Those categories we actually
                 // need to register with backing storage.
-                // 
+                //
+                // Make sure we only register known categories
+                if (! knownCategoryNames.contains(categoryName)) {
+                    logger.log(Level.WARNING,
+                        "Attempt to register category which we don't know of! Name was '"
+                                + categoryName + "'");
+                    resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
+                    return;
+                }
                 // The following has the side effect of registering the newly
                 // deserialized Category in the Categories class.
                 category = gson.fromJson(categoryParam, Category.class);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/server/src/test/java/com/redhat/thermostat/web/server/KnownCategoryRegistryTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -0,0 +1,124 @@
+/*
+ * 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.web.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
+
+public class KnownCategoryRegistryTest {
+    
+    private static final String DUPLICATE_CAT_NAME = "some-category";
+
+    @Test
+    public void canAddCategories() {
+        Set<String> categoryNames = new HashSet<>();
+        categoryNames.add("some-category"); // duplicate
+        categoryNames.add("some-other-category");
+        Iterable<CategoryRegistration> regs = getRegs(categoryNames);
+        KnownCategoryRegistry reg = null;
+        try {
+            reg = new KnownCategoryRegistry(regs);
+        } catch (IllegalStateException e) {
+            // should not fail
+            fail(e.getMessage());
+        }
+        Set<String> actualRegs = reg.getRegisteredCategoryNames();
+        assertFalse(actualRegs.contains(null));
+        assertEquals(2, actualRegs.size());
+        for (String item: categoryNames) {
+            assertTrue(actualRegs.contains(item));
+        }
+    }
+    
+    private Iterable<CategoryRegistration> getRegs(Set<String> categoryNames) {
+        Set<CategoryRegistration> regs = new HashSet<>();
+        regs.add(new TestCategoryRegistration(categoryNames));
+        Set<String> myDup = new HashSet<>();
+        myDup.add(DUPLICATE_CAT_NAME);
+        regs.add(new TestCategoryRegistration(myDup));
+        return regs;
+    }
+
+    @Test
+    public void refuseToAddNullCategoryName() {
+        Set<String> categoryNames = new HashSet<>();
+        categoryNames.add(null);
+        categoryNames.add("some-other-category");
+        Iterable<CategoryRegistration> regs = getRegs(categoryNames);
+        try {
+            new KnownCategoryRegistry(regs);
+            fail("Should not reach here, null name added!");
+        } catch (IllegalStateException e) {
+            // pass
+        }
+    }
+    
+    @Test
+    public void canLoadRegistrationsInClasspath() {
+        KnownCategoryRegistry reg = new KnownCategoryRegistry();
+        Set<String> actualRegs = reg.getRegisteredCategoryNames();
+        assertNotNull(actualRegs);
+        // storage-core registers them. no-other modules in classpath.
+        assertEquals(5, actualRegs.size());
+    }
+    
+    private static class TestCategoryRegistration implements CategoryRegistration {
+
+        private final Set<String> catNames;
+        
+        private TestCategoryRegistration(Set<String> catNames) {
+            this.catNames = catNames;
+        }
+        
+        @Override
+        public Set<String> getCategoryNames() {
+            return catNames;
+        }
+        
+    }
+    
+}
--- a/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java	Fri Aug 16 14:59:33 2013 +0200
+++ b/web/server/src/test/java/com/redhat/thermostat/web/server/WebStorageEndpointTest.java	Tue Aug 06 12:29:07 2013 +0200
@@ -114,6 +114,7 @@
 import com.redhat.thermostat.storage.core.StatementDescriptor;
 import com.redhat.thermostat.storage.core.Update;
 import com.redhat.thermostat.storage.core.auth.DescriptorMetadata;
+import com.redhat.thermostat.storage.core.auth.CategoryRegistration;
 import com.redhat.thermostat.storage.core.auth.StatementDescriptorRegistration;
 import com.redhat.thermostat.storage.dao.HostInfoDAO;
 import com.redhat.thermostat.storage.model.AggregateCount;
@@ -184,13 +185,14 @@
     private static Key<String> key1;
     private static Key<Integer> key2;
     private static Category<TestClass> category;
+    private static String categoryName = "test";
     private ExpressionFactory factory;
 
     @BeforeClass
     public static void setupCategory() {
         key1 = new Key<>("key1", true);
         key2 = new Key<>("key2", false);
-        category = new Category<>("test", TestClass.class, key1, key2);
+        category = new Category<>(categoryName, TestClass.class, key1, key2);
     }
 
     @AfterClass
@@ -234,6 +236,8 @@
             server.stop();
             server.join();
         }
+        KnownCategoryRegistryFactory.setInstance(null);
+        KnownDescriptorRegistryFactory.setKnownDescriptorRegistry(null);
     }
 
     /**
@@ -313,6 +317,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory(testuser, password);
         
         String endpoint = getEndpoint();
@@ -365,6 +372,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory("ignored1", "ignored2");
         
         TestClass expected1 = new TestClass();
@@ -463,9 +473,10 @@
     @Test
     public void authorizedFilteredQuery() throws Exception {
         Category oldCategory = category;
+        String categoryName = "test-authorizedFilteredQuery";
         // redefine category to include the agentId key in the category.
         // undone via a the try-finally block.
-        category = new Category("test-authorizedFilteredQuery", TestClass.class, key1, key2, Key.AGENT_ID);
+        category = new Category(categoryName, TestClass.class, key1, key2, Key.AGENT_ID);
         try {
             String strDescriptor = "QUERY " + category.getName() + " WHERE '" +
                     key1.getName() + "' = ?s SORT '" + key1.getName() + "' DSC LIMIT 42";
@@ -490,6 +501,9 @@
                     startServer(port, loginService);
                 }
             });
+            // This makes register category work for the "test" category.
+            // Undone via @After
+            setupTrustedCategory(categoryName);
             registerCategory("ignored1", "ignored2");
             
             TestClass expected1 = new TestClass();
@@ -695,6 +709,17 @@
         verifyNoMoreInteractions(mockMongoQuery);
     }
     
+    private void setupTrustedCategory(String categoryName) {
+        Set<String> descs = new HashSet<>();
+        descs.add(categoryName);
+        CategoryRegistration reg = mock(CategoryRegistration.class);
+        when(reg.getCategoryNames()).thenReturn(descs);
+        List<CategoryRegistration> regs = new ArrayList<>(1);
+        regs.add(reg);
+        KnownCategoryRegistry registry = new KnownCategoryRegistry(regs);
+        KnownCategoryRegistryFactory.setInstance(registry);
+    }
+    
     private void setupTrustedStatementRegistry(String strDescriptor, DescriptorMetadata metadata) {
         Set<String> descs = new HashSet<>();
         descs.add(strDescriptor);
@@ -704,6 +729,48 @@
         KnownDescriptorRegistry registry = new KnownDescriptorRegistry(regs);
         KnownDescriptorRegistryFactory.setKnownDescriptorRegistry(registry);
     }
+    
+    @Test
+    public void cannotRegisterCategoryWithoutRegistrationOnInit() throws Exception {
+        // need this in order to pass basic permissions.
+        String[] roleNames = new String[] {
+                Roles.REGISTER_CATEGORY
+        };
+        String username = "testuser";
+        String password = "testpassword";
+        final LoginService loginService = new TestLoginService(username, password, roleNames); 
+        port = FreePortFinder.findFreePort(new TryPort() {
+            
+            @Override
+            public void tryPort(int port) throws Exception {
+                startServer(port, loginService);
+            }
+        });
+        try {
+            String endpoint = getEndpoint();
+            URL url = new URL(endpoint + "/register-category");
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            String enc = "UTF-8";
+            conn.setRequestProperty("Content-Encoding", enc);
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            conn.setRequestMethod("POST");
+            sendAuthentication(conn, username, password);
+            OutputStream out = conn.getOutputStream();
+            Gson gson = new Gson();
+            OutputStreamWriter writer = new OutputStreamWriter(out);
+            writer.write("name=");
+            writer.write(URLEncoder.encode(category.getName(), enc));
+            writer.write("&category=");
+            writer.write(URLEncoder.encode(gson.toJson(category), enc));
+            writer.flush();
+
+            // "test" category name not registered, expecting forbidden.
+            assertEquals(HttpServletResponse.SC_FORBIDDEN, conn.getResponseCode());
+        } catch (IOException e) {
+            fail("Should not throw exception! " + e.getMessage());
+        }
+    }
 
     @Test
     public void unauthorizedPrepareStmt() throws Exception {
@@ -739,6 +806,9 @@
             }
         });
         if (doRegisterCategory) {
+            // This makes register category work for the "test" category.
+            // Undone via @After
+            setupTrustedCategory(categoryName);
             registerCategory(testuser, password);
         }
         
@@ -819,6 +889,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory(testuser, password);
         
         Replace replace = mock(Replace.class);
@@ -869,6 +942,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory(testuser, password);
         
         String endpoint = getEndpoint();
@@ -912,6 +988,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory(testuser, password);
         
         Add insert = mock(Add.class);
@@ -962,6 +1041,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory(testuser, password);
         
         String endpoint = getEndpoint();
@@ -1011,6 +1093,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory(testuser, password);
         
         
@@ -1069,6 +1154,9 @@
                 startServer(port, loginService);
             }
         });
+        // This makes register category work for the "test" category.
+        // Undone via @After
+        setupTrustedCategory(categoryName);
         registerCategory(testuser, password);
         
         Update mockUpdate = mock(Update.class);