Clean up error handling to make things slightly friendlier on an initial install.
[cfb.git] / prod / net / jaekl / cfb / CFB.java
index 63271ec9cdd5c3036b2875ab68a59e8a53fce7b3..c6c995d41cf70e66d9ecdb54329fca321b18cd3c 100644 (file)
@@ -21,6 +21,7 @@ import java.util.Locale.Category;
 import net.jaekl.cfb.analyze.Analysis;
 import net.jaekl.cfb.analyze.Analyzer;
 import net.jaekl.cfb.analyze.Delta;
+import net.jaekl.cfb.analyze.FBMsgFileNotFoundException;
 import net.jaekl.cfb.analyze.HtmlReport;
 import net.jaekl.cfb.analyze.MessageMap;
 import net.jaekl.cfb.analyze.Notifier;
@@ -29,6 +30,8 @@ import net.jaekl.cfb.db.TypeMismatchException;
 import net.jaekl.cfb.db.driver.DbDriver;
 import net.jaekl.cfb.db.driver.PostgresqlDriver;
 import net.jaekl.cfb.store.DbStore;
+import net.jaekl.cfb.store.StoreException;
+import net.jaekl.cfb.util.Env;
 import net.jaekl.qd.xml.XmlParseException;
 
 import org.apache.commons.cli.CommandLine;
@@ -39,9 +42,11 @@ import org.apache.commons.cli.ParseException;
 import org.xml.sax.SAXException;
 
 public class CFB {
+       public static final String FINDBUGS_HOME = "FINDBUGS_HOME";     // name of the FINDBUGS_HOME environment variable
+       
        DbDriver m_driver;
        CfbSchema m_schema;
-       CfbBundle m_bundle;     
+       volatile static CfbBundle m_bundle = null;      
        Locale m_locale;
        
        Config m_config;
@@ -59,7 +64,6 @@ public class CFB {
                m_driver = new PostgresqlDriver();
                m_schema = new CfbSchema(m_driver);
                m_locale = locale;
-               m_bundle = CfbBundle.getInst(m_locale);
                m_config = new Config();
                
                m_configFile = new File("config.properties");
@@ -71,6 +75,18 @@ public class CFB {
                m_output = null;
        }
        
+       static CfbBundle getBundle(Locale locale) {
+               CfbBundle bundle = m_bundle;
+               if (null == bundle) {
+                       synchronized(CFB.class) {
+                               if (null == m_bundle) {
+                                       m_bundle = bundle = CfbBundle.getInst(locale);
+                               }
+                       }
+               }
+               return bundle;
+       }
+       
        Options createOptions() {
                Options opt = new Options();
                
@@ -139,8 +155,8 @@ public class CFB {
                help.printHelp(pw, 80, getClass().getName(), "", opt, 0, 0, "", true);
        }
        
-       String trans(String key) {
-               return m_bundle.get(key);
+       String trans(String key, Object... params) {
+               return getBundle(m_locale).get(key, params);
        }
        
        String getenv(String varName) {
@@ -184,8 +200,31 @@ public class CFB {
                File findBugsDir = getFindBugsDir();
                File workDir = new File(".");
                MessageMap messageMap = new MessageMap();
-               messageMap.load(findBugsDir, Locale.getDefault(Category.DISPLAY));
+               try {
+                       messageMap.load(findBugsDir, Locale.getDefault(Category.DISPLAY));
+               }
+               catch (FBMsgFileNotFoundException exc) {
+                       reportException(pw, exc);
+                       return;
+               }
                
+               if (!ensureDbInitialized(pw, messageMap)) {
+                       return;
+               }
+               
+               Analyzer analyzer = new Analyzer(messageMap);
+               Analysis analysis = analyzer.analyze(pw, workDir, m_fbp, m_projName, m_buildNum);
+               if (null == analysis) {
+                       pw.println(trans(CfbBundle.ANALYSIS_FAILED));
+                       return;
+               }
+               
+               storeAndReport(pw, messageMap, analysis);
+       }
+
+       boolean ensureDbInitialized(PrintWriter pw, MessageMap messageMap)
+                       throws TypeMismatchException 
+       {
                try (Connection con = m_driver.connect(
                                        m_config.getDbHost(), m_config.getDbPort(), 
                                        m_config.getDbName(), 
@@ -196,23 +235,22 @@ public class CFB {
                        
                        if (m_removeSchema) {
                                m_schema.purge(con);
-                               return;
+                               return false;   // do not continue execution
                        }
                        m_schema.ensureDbInitialized(con);
                        messageMap.loadIds(con, m_driver);
                }
                catch (SQLException exc) {
                        reportUnableToConnect(pw, exc);
-                       return;
-               }
-               
-               Analyzer analyzer = new Analyzer(messageMap);
-               Analysis analysis = analyzer.analyze(pw, workDir, m_fbp, m_projName, m_buildNum);
-               if (null == analysis) {
-                       pw.println(trans(CfbBundle.ANALYSIS_FAILED));
-                       return;
+                       return false;   // do not continue execution
                }
                
+               return true;    // all OK; continue execution
+       }
+
+       void storeAndReport(PrintWriter pw, MessageMap messageMap, Analysis analysis) 
+                       throws TypeMismatchException, IOException 
+       {
                try (
                                Connection con = m_driver.connect(
                                                m_config.getDbHost(), m_config.getDbPort(), 
@@ -227,19 +265,36 @@ public class CFB {
                        Analysis prior = store.getPrior(analysis);
                        Delta delta = new Delta(prior, analysis);
 
-                       HtmlReport report = new HtmlReport(m_bundle, messageMap.getColl(), delta);
+                       HtmlReport report = new HtmlReport(getBundle(m_locale), messageMap.getColl(), delta);
                        if (null != m_output) {
                                report.write(m_output);
                        }
                        
-                       Notifier notifier = new Notifier(m_bundle, m_config);
+                       Notifier notifier = new Notifier(getBundle(m_locale), m_config);
                        notifier.sendEmailIfNeeded(pw, report);
                }
+               catch (StoreException exc) {
+                       exc.printStackTrace(pw);
+               }
                catch (SQLException exc) {
                        reportUnableToConnect(pw, exc);
-                       return;
                }
        }
+       
+       void reportException(PrintWriter pw, FBMsgFileNotFoundException exc) {
+               exc.printStackTrace(pw);
+               
+               pw.println(trans(CfbBundle.CANNOT_LOAD_FBMSG_FILE, exc.getFilename()));
+               
+               String fbHome = Env.get(FINDBUGS_HOME);
+               if (null == fbHome) {
+                       pw.println(trans(CfbBundle.FINDBUGS_HOME_IS_NOT_SET, FINDBUGS_HOME));
+               }
+               else {
+                       pw.println(trans(CfbBundle.FINDBUGS_HOME_IS_SET_TO, FINDBUGS_HOME, fbHome));
+               }
+
+       }
 
        private void reportUnableToConnect(PrintWriter pw, SQLException exc) {
                String cannotConnectFormat = trans(CfbBundle.CANNOT_CONNECT);