changeset 952:f1c218047e69

Various fixes for the web archive. Reviewed-by: vanaltj Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-January/005447.html
author Severin Gehwolf <sgehwolf@redhat.com>
date Wed, 30 Jan 2013 18:58:52 +0100
parents e3e06ba98c4a
children e20c9ca1571f
files common/core/src/main/java/com/redhat/thermostat/common/config/Configuration.java common/core/src/main/java/com/redhat/thermostat/common/ssl/SSLKeystoreConfiguration.java common/core/src/test/java/com/redhat/thermostat/common/config/ConfigurationTest.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnection.java storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java web/war/pom.xml web/war/src/main/resources/logging.properties web/war/src/main/webapp/WEB-INF/web.xml
diffstat 9 files changed, 181 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/common/core/src/main/java/com/redhat/thermostat/common/config/Configuration.java	Thu Jan 31 18:33:42 2013 +0100
+++ b/common/core/src/main/java/com/redhat/thermostat/common/config/Configuration.java	Wed Jan 30 18:58:52 2013 +0100
@@ -133,5 +133,6 @@
     public void setPrintOSGiInfo(boolean newValue) {
         printOsgiInfo = newValue;
     }
+
 }
 
--- a/common/core/src/main/java/com/redhat/thermostat/common/ssl/SSLKeystoreConfiguration.java	Thu Jan 31 18:33:42 2013 +0100
+++ b/common/core/src/main/java/com/redhat/thermostat/common/ssl/SSLKeystoreConfiguration.java	Wed Jan 30 18:58:52 2013 +0100
@@ -40,9 +40,12 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import com.redhat.thermostat.common.config.Configuration;
 import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.utils.LoggingUtils;
 
 public class SSLKeystoreConfiguration {
 
@@ -51,6 +54,7 @@
     private static final String KEYSTORE_FILE_PWD_KEY = "KEYSTORE_PASSWORD";
     private static final String CMD_CHANNEL_SSL_KEY = "COMMAND_CHANNEL_USE_SSL";
     private static final String MONGO_CONNECTION_USE_SSL_KEY = "MONGODB_CONNECTION_USE_SSL";
+    private static final Logger logger = LoggingUtils.getLogger(SSLKeystoreConfiguration.class);
 
     /**
      * 
@@ -105,7 +109,9 @@
         try {
             loadClientProperties();
         } catch (InvalidConfigurationException e) {
-            // Thermostat home not set? Do something reasonable
+            logger.log(Level.WARNING,
+                    "THERMOSTAT_HOME not set and config file attempted to be " +
+                    		"read from there! Returning false.");
             return result;
         }
         String token = clientProps.getProperty(CMD_CHANNEL_SSL_KEY);
@@ -126,7 +132,9 @@
         try {
             loadClientProperties();
         } catch (InvalidConfigurationException e) {
-            // Thermostat home not set? Do something reasonable
+            logger.log(Level.WARNING,
+                    "THERMOSTAT_HOME not set and config file attempted to be " +
+                            "read from there! Returning false.");
             return result;
         }
         String token = clientProps.getProperty(MONGO_CONNECTION_USE_SSL_KEY);
--- a/common/core/src/test/java/com/redhat/thermostat/common/config/ConfigurationTest.java	Thu Jan 31 18:33:42 2013 +0100
+++ b/common/core/src/test/java/com/redhat/thermostat/common/config/ConfigurationTest.java	Wed Jan 30 18:58:52 2013 +0100
@@ -36,42 +36,66 @@
 
 package com.redhat.thermostat.common.config;
 
+import static org.junit.Assert.fail;
+
 import java.io.File;
 import java.io.IOException;
+import java.util.Properties;
 
 import junit.framework.Assert;
 
-import org.junit.Before;
+import org.junit.After;
 import org.junit.Test;
 
 public class ConfigurationTest {
-
-    @Before
-    public void setUp() throws IOException {
-        System.setProperty("THERMOSTAT_HOME", "/tmp/");
+    
+    @After
+    public void tearDown() {
+        // remove THERMOSTAT_HOME system property for a clean slate
+        Properties props = System.getProperties();
+        Properties newProps = new Properties();
+        for (Object key: props.keySet()) {
+            if (!key.equals("THERMOSTAT_HOME")) {
+                newProps.put(key, props.get(key));
+            }
+        }
+        System.setProperties(newProps);
     }
 
     @Test
     public void testLocations() throws InvalidConfigurationException, IOException {
-        String path = System.getProperty("THERMOSTAT_HOME");
+        String thermostatHome = "/tmp/";
+        System.setProperty("THERMOSTAT_HOME", thermostatHome);
+        
         char s = File.separatorChar;
 
         Configuration config = new Configuration();
 
-        Assert.assertEquals(path, config.getThermostatHome());
+        Assert.assertEquals(thermostatHome, config.getThermostatHome());
 
-        Assert.assertEquals(path + "agent" + s + "agent.properties",
+        Assert.assertEquals(thermostatHome + "agent" + s + "agent.properties",
                             config.getAgentConfigurationFile().getCanonicalPath());
-        Assert.assertEquals(path + "storage", config.getStorageBaseDirectory().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "db.properties",
+        Assert.assertEquals(thermostatHome + "storage", config.getStorageBaseDirectory().getCanonicalPath());
+        Assert.assertEquals(thermostatHome + "storage" + s + "db.properties",
                             config.getStorageConfigurationFile().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "db",
+        Assert.assertEquals(thermostatHome + "storage" + s + "db",
                 config.getStorageDirectory().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "logs" + s + "db.log",
+        Assert.assertEquals(thermostatHome + "storage" + s + "logs" + s + "db.log",
                 config.getStorageLogFile().getCanonicalPath());
-        Assert.assertEquals(path + "storage" + s + "run" + s + "db.pid",
+        Assert.assertEquals(thermostatHome + "storage" + s + "run" + s + "db.pid",
                 config.getStoragePidFile().getCanonicalPath());
 
     }
+    
+    @Test
+    public void instantiationThrowsException() {
+        try {
+            new Configuration();
+            // The web archive uses this. See WebStorageEndPoint#init();
+            fail("Should have thrown InvalidConfigurationException");
+        } catch (InvalidConfigurationException e) {
+            // pass
+        }
+    }
 }
 
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnection.java	Thu Jan 31 18:33:42 2013 +0100
+++ b/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoConnection.java	Wed Jan 30 18:58:52 2013 +0100
@@ -120,8 +120,10 @@
 
     private void createConnection() throws MongoException, UnknownHostException {
         if (SSLKeystoreConfiguration.useSslForMongodb()) {
+            logger.log(Level.FINE, "Using SSL socket for mongodb:// protocol");
             this.m = getSSLMongo();
         } else {
+            logger.log(Level.FINE, "Using plain socket for mongodb://");
             this.m = new Mongo(getServerAddress());
         }
         this.db = m.getDB(THERMOSTAT_DB_NAME);
--- a/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java	Thu Jan 31 18:33:42 2013 +0100
+++ b/storage/mongo/src/main/java/com/redhat/thermostat/storage/mongodb/internal/MongoStorage.java	Wed Jan 30 18:58:52 2013 +0100
@@ -42,6 +42,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
 
 import com.mongodb.BasicDBObject;
 import com.mongodb.DB;
@@ -96,11 +97,12 @@
     private MongoConnection conn;
     private DB db = null;
     private Map<String, DBCollection> collectionCache = new HashMap<String, DBCollection>();
-
+    private CountDownLatch connectedLatch;
     private UUID agentId;
 
     public MongoStorage(StartupConfiguration conf) {
         conn = new MongoConnection(conf);
+        connectedLatch = new CountDownLatch(1);
         conn.addListener(new ConnectionListener() {
             @Override
             public void changed(ConnectionStatus newStatus) {
@@ -109,6 +111,8 @@
                     db = null;
                 case CONNECTED:
                     db = conn.getDB();
+                    // This is important. See comment in registerCategory().
+                    connectedLatch.countDown();
                 default:
                     // ignore other status events
                 }
@@ -226,6 +230,17 @@
             throw new IllegalStateException("Category may only be associated with one backend.");
         }
 
+        // The db field is only set once we've got a connection
+        // established. Wait until we actually get notification
+        // this has happened. Without this sychronization we might
+        // get NPEs since the connection handshake might still be
+        // ongoing.
+        try {
+            connectedLatch.await();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+
         DBCollection coll;
         if (! db.collectionExists(name)) {
             coll = db.createCollection(name, new BasicDBObject("capped", false));
--- a/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java	Thu Jan 31 18:33:42 2013 +0100
+++ b/web/server/src/main/java/com/redhat/thermostat/web/server/WebStorageEndPoint.java	Wed Jan 30 18:58:52 2013 +0100
@@ -44,7 +44,10 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
+import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -61,6 +64,9 @@
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonParser;
+import com.redhat.thermostat.common.config.Configuration;
+import com.redhat.thermostat.common.config.InvalidConfigurationException;
+import com.redhat.thermostat.common.utils.LoggingUtils;
 import com.redhat.thermostat.storage.core.AbstractQuery.Sort;
 import com.redhat.thermostat.storage.core.Category;
 import com.redhat.thermostat.storage.core.Cursor;
@@ -88,6 +94,7 @@
     private static final String ROLE_THERMOSTAT_AGENT = "thermostat-agent";
     private static final String ROLE_THERMOSTAT_CLIENT = "thermostat-client";
     private static final String ROLE_CMD_CHANNEL = "thermostat-cmd-channel";
+    private static final Logger logger = LoggingUtils.getLogger(WebStorageEndPoint.class);
 
     private Storage storage;
     private Gson gson;
@@ -102,7 +109,22 @@
     private Map<String, Integer> categoryIds;
     private Map<Integer, Category<?>> categories;
 
-    public void init() {
+    @Override
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        if (!isThermostatHomeSet()) {
+            // This is the webapp and our entry point into thermostat's web
+            // service. The launcher did not run and hence THERMOSTAT_HOME is
+            // not set and we need to do this ourselves.
+            // In this case THERMOSTAT_HOME is in the WEB-INF/thermostat folder
+            // in order to make it inaccessible via HTTP. This is not a "real"
+            // THERMOSTAT_HOME. For now it only contains an ssl.properties file.
+            String thermostatHome = config.getServletContext().getRealPath(
+                    "/WEB-INF/thermostat");
+            logger.log(Level.INFO, "Setting THERMOSTAT_HOME for webapp to "
+                    + thermostatHome);
+            System.setProperty("THERMOSTAT_HOME", thermostatHome);
+        }
         gson = new GsonBuilder().registerTypeHierarchyAdapter(Pojo.class, new ThermostatGSONConverter()).create();
         categoryIds = new HashMap<>();
         categories = new HashMap<>();
@@ -152,6 +174,17 @@
             verifyToken(req, resp);
         }
     }
+    
+    private boolean isThermostatHomeSet() {
+        try {
+            // this throws config exception if neither the property
+            // nor the env var is set
+            new Configuration();
+            return true;
+        } catch (InvalidConfigurationException e) {
+            return false;
+        }
+    }
 
     private void ping(HttpServletRequest req, HttpServletResponse resp) {
         resp.setStatus(HttpServletResponse.SC_OK);
--- a/web/war/pom.xml	Thu Jan 31 18:33:42 2013 +0100
+++ b/web/war/pom.xml	Wed Jan 30 18:58:52 2013 +0100
@@ -59,7 +59,7 @@
     </dependency>
     <dependency>
       <groupId>com.redhat.thermostat</groupId>
-      <artifactId>thermostat-web-server</artifactId>
+      <artifactId>thermostat-distribution</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
@@ -88,6 +88,32 @@
           <skip>true</skip>
         </configuration>
       </plugin>
+      <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+        <version>2.5</version>
+        <executions>
+          <execution>
+            <id>copy-logging-properties</id>
+            <phase>prepare-package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>src/main/webapp/WEB-INF/thermostat</outputDirectory>
+              <resources>
+                <resource>
+                  <directory>src/../../../distribution/config</directory>
+                  <targetPath>etc</targetPath>
+                  <filtering>true</filtering>
+                  <includes>
+                    <include>ssl.properties</include>
+                  </includes>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/war/src/main/resources/logging.properties	Wed Jan 30 18:58:52 2013 +0100
@@ -0,0 +1,51 @@
+# 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.
+
+###################################################################
+# Thermostat web service (war in tomcat) logging configuration
+###################################################################
+
+handlers = org.apache.juli.FileHandler
+
+############################################################
+# Handler specific properties.
+# Describes specific configuration info for Handlers.
+############################################################
+
+org.apache.juli.FileHandler.level = FINEST
+org.apache.juli.FileHandler.directory = ${catalina.base}/logs
+org.apache.juli.FileHandler.prefix = thermostat-web-storage.
+
+com.redhat.thermostat.handlers = org.apache.juli.FileHandler
+com.redhat.thermostat.level = FINEST
--- a/web/war/src/main/webapp/WEB-INF/web.xml	Thu Jan 31 18:33:42 2013 +0100
+++ b/web/war/src/main/webapp/WEB-INF/web.xml	Wed Jan 30 18:58:52 2013 +0100
@@ -52,5 +52,8 @@
   <security-role>
     <role-name>thermostat-client</role-name>
   </security-role>
+  <security-role>
+    <role-name>thermostat-cmd-channel</role-name>
+  </security-role>
 
 </web-app>