You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by ag...@apache.org on 2007/06/20 17:27:17 UTC

svn commit: r549132 [1/2] - in /roller/trunk/apps/weblogger: src/java/org/apache/roller/weblogger/business/ src/java/org/apache/roller/weblogger/business/hibernate/ src/java/org/apache/roller/weblogger/business/jpa/ src/java/org/apache/roller/weblogger...

Author: agilliland
Date: Wed Jun 20 08:27:15 2007
New Revision: 549132

URL: http://svn.apache.org/viewvc?view=rev&rev=549132
Log:
a number of tweaks and improvements for Weblogger application lifecycle management which is meant to improve the auto install process a bit.

1. Introduced new WebloggerStartup class which acts as the managing class for the core application startup services such as getting the database provider, mail provider, and running db install/upgrade logic.

2. Sectioned out and setup a bootstrapping state and initialization state of the application, each of which are run independently.

3. Removed attempts to run a fallback RollerImpl during the bootstrapping process when the configured Roller class fails, this just doesn't make sense in the end.  If your desired Roller backend fails for some reason you may not want the fallback alternative.

4. Merged many of the install related struts2 actions into one Install action because it was easier that way and the multiple actions weren't really needed.

5. Cleaned up RollerContext startup procedures to make use of this new layered startup procedure.


Added:
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/BootstrapException.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/InitializationException.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/StartupException.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/WebloggerStartup.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/ClasspathDatabaseScriptProvider.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/DatabaseInstaller.java
Removed:
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/DatabaseCreator.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/DatabaseUpgrader.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/struts2/core/CreateDatabase.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/struts2/core/DatabaseError.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/struts2/core/ServletContextDatabaseScriptProvider.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/struts2/core/UpgradeDatabase.java
Modified:
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/DatabaseProvider.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/MailProvider.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/RollerFactory.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/hibernate/HibernateConnectionProvider.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPARollerImpl.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/DatabaseScriptProvider.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/SQLScriptRunner.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/planet/business/jpa/JPARollerPlanetImpl.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/core/RollerContext.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/core/filters/BootstrapFilter.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/core/filters/PersistenceSessionFilter.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/ui/struts2/core/Install.java
    roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/util/MailUtil.java
    roller/trunk/apps/weblogger/web/WEB-INF/classes/struts.xml
    roller/trunk/apps/weblogger/web/WEB-INF/jsps/core/CreateDatabase.jsp
    roller/trunk/apps/weblogger/web/WEB-INF/jsps/core/DatabaseError.jsp
    roller/trunk/apps/weblogger/web/WEB-INF/tiles.xml

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/BootstrapException.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/BootstrapException.java?view=auto&rev=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/BootstrapException.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/BootstrapException.java Wed Jun 20 08:27:15 2007
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business;
+
+import org.apache.roller.weblogger.WebloggerException;
+
+
+/**
+ * Exception generated from Weblogger bootstrapping process.
+ */
+public class BootstrapException extends WebloggerException {
+    
+    public BootstrapException(String msg) {
+        super(msg);
+    }
+    
+    public BootstrapException(String msg, Throwable t) {
+        super(msg, t);
+    }
+    
+}

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/DatabaseProvider.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/DatabaseProvider.java?view=diff&rev=549132&r1=549131&r2=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/DatabaseProvider.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/DatabaseProvider.java Wed Jun 20 08:27:15 2007
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
 package org.apache.roller.weblogger.business;
 
 import java.sql.Connection;
@@ -12,8 +30,10 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.WebloggerException;
+import org.apache.roller.weblogger.business.startup.StartupException;
 import org.apache.roller.weblogger.config.RollerConfig;
 
+
 /**
  * Encapsulates Roller database configuration via JDBC properties or JNDI.
  *
@@ -40,14 +60,12 @@
  * </pre>
  */
 public class DatabaseProvider  {
+    
     private static Log log = LogFactory.getLog(DatabaseProvider.class);
 
     public enum ConfigurationType {JNDI_NAME, JDBC_PROPERTIES;}
-    private ConfigurationType type = ConfigurationType.JNDI_NAME; 
-    
-    private static DatabaseProvider singletonInstance = null;
-    private static WebloggerException startupException = null;
-    private static List<String> startupLog = new ArrayList<String>();
+    private ConfigurationType type = ConfigurationType.JNDI_NAME;
+    private List<String> startupLog = new ArrayList<String>();
     
     private DataSource dataSource = null;    
     private String jndiName = null; 
@@ -63,7 +81,7 @@
      * Reads configuraiton, loads driver or locates data-source and attempts
      * to get test connecton so that we can fail early.
      */ 
-    private DatabaseProvider() throws WebloggerException {
+    public DatabaseProvider() throws StartupException {
         
         String connectionTypeString = 
                 RollerConfig.getProperty("database.configurationType"); 
@@ -91,8 +109,7 @@
                      "ERROR: cannot load JDBC driver class [" + getJdbcDriverClass()+ "]. "
                     +"Likely problem: JDBC driver jar missing from server classpath.";
                 errorMessage(errorMsg);
-                startupException = new WebloggerException(errorMsg, ex);
-                throw startupException;
+                throw new StartupException(errorMsg, ex, startupLog);
             }
             successMessage("SUCCESS: loaded JDBC driver class [" +getJdbcDriverClass()+ "]");
             
@@ -114,8 +131,7 @@
                     "ERROR: cannot locate JNDI DataSource [" +name+ "]. "
                    +"Likely problem: no DataSource or datasource is misconfigured.";
                 errorMessage(errorMsg);
-                startupException =  new WebloggerException(errorMsg, ex);
-                throw startupException;
+                throw new StartupException(errorMsg, ex, startupLog);
             }            
             successMessage("SUCCESS: located JNDI DataSource [" +name+ "]");
         }
@@ -129,11 +145,11 @@
                 "ERROR: unable to obtain database connection. "
                +"Likely problem: bad connection parameters or database unavailable.";
             errorMessage(errorMsg);
-            startupException =  new WebloggerException(errorMsg, t);
-            throw startupException;
+            throw new StartupException(errorMsg, t, startupLog);
         }
     }
     
+    
     private void successMessage(String msg) {
         startupLog.add(msg);
         log.info(msg);
@@ -144,31 +160,11 @@
         log.error(msg);
     }
     
-    /**
-     * Get global database provider singlton, instantiating if necessary.
-     */
-    public static DatabaseProvider getDatabaseProvider() throws WebloggerException {
-        // No need to jam log with database connection attempts
-        if (startupException != null) {
-            throw startupException;
-        }
-        if (singletonInstance == null) {
-            singletonInstance = new DatabaseProvider();
-        }
-        return singletonInstance;
-    }
-    
-    /**
-     * Exception that occured during startup, or null if none occured.
-     */
-    public static WebloggerException getStartupException() {
-        return startupException;
-    }
 
     /** 
      * List of success and error messages when class was first instantiated.
      **/
-    public static List<String> getStartupLog() {
+    public List<String> getStartupLog() {
         return startupLog;
     }
 

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/InitializationException.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/InitializationException.java?view=auto&rev=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/InitializationException.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/InitializationException.java Wed Jun 20 08:27:15 2007
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business;
+
+import org.apache.roller.weblogger.WebloggerException;
+
+
+/**
+ * Exception generated from Weblogger initialization process.
+ */
+public class InitializationException extends WebloggerException {
+    
+    public InitializationException(String msg) {
+        super(msg);
+    }
+    
+    public InitializationException(String msg, Throwable t) {
+        super(msg, t);
+    }
+    
+}

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/MailProvider.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/MailProvider.java?view=diff&rev=549132&r1=549131&r2=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/MailProvider.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/MailProvider.java Wed Jun 20 08:27:15 2007
@@ -28,7 +28,7 @@
 import javax.naming.NamingException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.weblogger.WebloggerException;
+import org.apache.roller.weblogger.business.startup.StartupException;
 import org.apache.roller.weblogger.config.RollerConfig;
 
 
@@ -41,8 +41,6 @@
     
     private enum ConfigurationType {JNDI_NAME, MAIL_PROPERTIES; }
     
-    private static MailProvider singletonInstance = null;
-    
     private Session session = null;
     
     private ConfigurationType type = ConfigurationType.JNDI_NAME;
@@ -53,9 +51,9 @@
     private String mailUsername = null;
     private String mailPassword = null;
 
+    
+    public MailProvider() throws StartupException {
         
-    /** Creates a new instance of MailProvider */
-    public MailProvider() throws WebloggerException {
         String connectionTypeString = RollerConfig.getProperty("mail.configurationType"); 
         if ("properties".equals(connectionTypeString)) {
             type = ConfigurationType.MAIL_PROPERTIES;
@@ -77,7 +75,7 @@
                 Context ctx = (Context) new InitialContext();
                 session = (Session) ctx.lookup(name);
             } catch (NamingException ex) {
-                throw new WebloggerException("ERROR looking up mail-session with JNDI name: " + name);
+                throw new StartupException("ERROR looking up mail-session with JNDI name: " + name);
             }
         } else {
             Properties props = new Properties();
@@ -86,35 +84,32 @@
             if (mailPort != -1) props.put("mail.smtp.port", ""+mailPort);
             session = Session.getDefaultInstance(props, null);
         }
+        
         try {
             Transport transport = getTransport();
             transport.close();
         } catch (Throwable t) {
-            throw new WebloggerException("ERROR connecting to mail server", t);
+            throw new StartupException("ERROR connecting to mail server", t);
         }
         
     }
     
-    public static MailProvider getMailProvider() throws WebloggerException {
-        if (singletonInstance == null) {
-            singletonInstance = new MailProvider();
-        }
-        return singletonInstance;
-    }   
-    
-    public static boolean isMailConfigured() {
-        return singletonInstance != null;
-    }
     
+    /**
+     * Get a mail Session.
+     */
     public Session getSession() {
         return session;
     }
     
+    
     /**
      * Create and connect to transport, caller is responsible for closing transport.
      */
     public Transport getTransport() throws NoSuchProviderException, MessagingException {
+        
         Transport transport = null;
+        
         if (type == ConfigurationType.MAIL_PROPERTIES) {
             // Configure transport ourselves using mail properties
             transport = session.getTransport("smtp"); 
@@ -128,6 +123,8 @@
             transport = session.getTransport(); 
             transport.connect();
         }
+        
         return transport;
     }
+    
 }

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/RollerFactory.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/RollerFactory.java?view=diff&rev=549132&r1=549131&r2=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/RollerFactory.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/RollerFactory.java Wed Jun 20 08:27:15 2007
@@ -21,8 +21,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.WebloggerException;
-import org.apache.roller.weblogger.business.utils.DatabaseCreator;
-import org.apache.roller.weblogger.business.utils.DatabaseUpgrader;
+import org.apache.roller.weblogger.business.startup.WebloggerStartup;
 import org.apache.roller.weblogger.config.PingConfig;
 import org.apache.roller.weblogger.config.RollerConfig;
 
@@ -34,13 +33,11 @@
     
     private static final Log log = LogFactory.getLog(RollerFactory.class);
     
-    private static final String DEFAULT_IMPL =
-        "org.apache.roller.weblogger.business.jpa.JPARollerImpl";
-        //"org.apache.roller.weblogger.business.hibernate.HibernateRollerImpl";
-        //"org.apache.roller.weblogger.business.datamapper.jpa.JPARollerImpl";
+    // have we been bootstrapped yet?
+    private static boolean bootstrapped = false;
     
+    // a reference to the bootstrapped Roller instance
     private static Roller rollerInstance = null;
-    private static boolean bootstrapped = false;
     
     
     // non-instantiable
@@ -50,41 +47,112 @@
     
     
     /**
-     * True if bootstrap process was completed
+     * True if bootstrap process was completed, False otherwise.
      */
     public static boolean isBootstrapped() {
         return bootstrapped;
     }
     
-
+    
+    /**
+     * Accessor to the Roller Weblogger business tier.
+     *
+     * @return Roller An instance of Roller.
+     * @throws IllegalStateException If the app has not been properly bootstrapped yet.
+     */
+    public static final Roller getRoller() {
+        if(rollerInstance == null) {
+            throw new IllegalStateException("Roller Weblogger has not been bootstrapped yet");
+        }
+        
+        return rollerInstance;
+    }
+    
+    
     /**
      * Bootstrap the Roller Weblogger business tier.
+     *
+     * Bootstrapping the application effectively instantiates all the necessary
+     * pieces of the business tier and wires them together so that the app is 
+     * ready to run.
+     *
+     * @throws IllegalStateException If the app has not been properly prepared yet.
+     * @throws BootstrapException If an error happens during the bootstrap process.
      */
-    public static final void bootstrap() throws WebloggerException {
+    public static final void bootstrap() throws BootstrapException {
         
-        if ("manual".equals(RollerConfig.getProperty("installation.type"))) {
-            if (DatabaseCreator.isCreationRequired() 
-             || DatabaseUpgrader.isUpgradeRequired()) { 
-                return;
-            }
-        }        
+        // if the app hasn't been properly started so far then bail
+        if (!WebloggerStartup.isPrepared()) {
+            throw new IllegalStateException("Cannot bootstrap until application has been properly prepared");
+        }
+        
+        log.info("Bootstrapping Roller Weblogger business tier");
+        
+        // bootstrap Roller Weblogger business tier
+        
+        // lookup value for the roller classname to use
+        String roller_classname =
+                RollerConfig.getProperty("persistence.roller.classname");
+        if(roller_classname == null || roller_classname.trim().length() < 1) {
+            throw new BootstrapException("Invalid roller classname - "+roller_classname);
+        } else {
+            log.info("Using Roller Impl: " + roller_classname);
+        }
+        
+        try {
+            Class rollerClass = Class.forName(roller_classname);
+            java.lang.reflect.Method instanceMethod =
+                    rollerClass.getMethod("instantiate", (Class[])null);
+            
+            // do the invocation
+            rollerInstance = (Roller) instanceMethod.invoke(rollerClass, (Object[])null);
+            
+            // note that we've now been bootstrapped
+            bootstrapped = true;
+            
+        } catch (Throwable ex) {
+            // bootstrapping failed
+            throw new BootstrapException("Exception doing bootstrapping", ex);
+        }
         
-        // This will cause instantiation and initialziation of Roller impl
-        Roller roller = getRoller();
+        log.info("Roller Weblogger business tier successfully bootstrapped");
+    }
+    
+    
+    /**
+     * Initialize the Roller Weblogger business tier.
+     *
+     * Initialization is used to perform any logic that needs to happen only
+     * once after the application has been properly bootstrapped.
+     *
+     * @throws IllegalStateException If the app has not been bootstrapped yet.
+     * @throws InitializationException If there is an error during initialization.
+     */
+    public static final void initialize() throws InitializationException {
         
         // TODO: this initialization process should probably be controlled by
         // a more generalized application lifecycle event framework
         
-        // Now that Roller has been instantiated, initialize individual managers
-        roller.getPropertiesManager();
-        roller.getIndexManager();
-        roller.getThemeManager();
+        if(!isBootstrapped()) {
+            throw new IllegalStateException("Cannot initialize until application has been properly bootstrapped");
+        }
         
-        // And this will schedule all configured tasks
-        roller.getThreadManager().startTasks();
+        log.info("Initializing Roller Weblogger business tier");
         
-        // Initialize ping systems
         try {
+            
+            Roller roller = getRoller();
+            
+            // Now that Roller has been bootstrapped, initialize individual managers
+            roller.getPropertiesManager();
+            roller.getIndexManager();
+            roller.getThemeManager();
+            
+            // And this will schedule all configured tasks
+            roller.getThreadManager().startTasks();
+            
+            // Initialize ping systems
+
             // Initialize common targets from the configuration
             PingConfig.initializeCommonTargets();
             
@@ -102,67 +170,11 @@
                 log.info("Ping usage has been disabled.  Removing any existing auto ping configurations.");
                 RollerFactory.getRoller().getAutopingManager().removeAllAutoPings();
             }
-        } catch (WebloggerException e) {
-            log.error("ERROR configing ping managers", e);
+        } catch (Throwable t) {
+            throw new InitializationException("Error initializing ping systems", t);
         }
         
-        bootstrapped = true;
-    }
-    
-    
-    /**
-     * Static accessor for the instance of Roller.
-     */
-    public static final Roller getRoller() {
-        
-        // check to see if we need to instantiate
-        if(rollerInstance == null) {
-            
-            // lookup value for the roller classname to use
-            String roller_classname =
-                    RollerConfig.getProperty("persistence.roller.classname");
-            if(roller_classname == null || roller_classname.trim().length() < 1)
-                roller_classname = DEFAULT_IMPL;
-            
-            try {
-                Class rollerClass = Class.forName(roller_classname);
-                java.lang.reflect.Method instanceMethod =
-                        rollerClass.getMethod("instantiate", (Class[])null);
-                
-                // do the invocation
-                rollerInstance = (Roller) instanceMethod.invoke(rollerClass, (Object[])null);
-                
-                log.info("Using Roller Impl: " + roller_classname);
-                
-            } catch (Throwable e) {
-                
-                // uh oh
-                log.error("Error instantiating " + roller_classname, e);
-                
-                try {
-                    // if we didn't already try DEFAULT_IMPL then try it now
-                    if( ! DEFAULT_IMPL.equals(roller_classname)) {
-                        
-                        log.info("** Trying DEFAULT_IMPL "+DEFAULT_IMPL+" **");
-                        
-                        Class rollerClass = Class.forName(DEFAULT_IMPL);
-                        java.lang.reflect.Method instanceMethod =
-                                rollerClass.getMethod("instantiate", (Class[])null);
-                        
-                        // do the invocation
-                        rollerInstance = (Roller) instanceMethod.invoke(rollerClass, (Object[])null);
-                    } else {
-                        // we just do this so that the logger gets the message
-                        throw new Exception("Doh! Couldn't instantiate a roller class");
-                    }
-                    
-                } catch (Exception re) {
-                    log.fatal("Failed to instantiate fallback roller impl", re);
-                }
-            }
-        }
-        
-        return rollerInstance;
+        log.info("Roller Weblogger business tier successfully initialized");
     }
 
 }

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/hibernate/HibernateConnectionProvider.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/hibernate/HibernateConnectionProvider.java?view=diff&rev=549132&r1=549131&r2=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/hibernate/HibernateConnectionProvider.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/hibernate/HibernateConnectionProvider.java Wed Jun 20 08:27:15 2007
@@ -6,7 +6,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.WebloggerException;
-import org.apache.roller.weblogger.business.DatabaseProvider;
+import org.apache.roller.weblogger.business.startup.WebloggerStartup;
 import org.hibernate.HibernateException;
 import org.hibernate.connection.ConnectionProvider;
 
@@ -27,13 +27,7 @@
 
     /** Get connecetion from Roller's Database provider */
     public Connection getConnection() throws SQLException {
-        try {
-            return DatabaseProvider.getDatabaseProvider().getConnection();
-        } catch (WebloggerException ex) {
-            // The DatabaseProvider should have been constructed long before 
-            // we get to this point, so this should never ever happen
-            throw new RuntimeException("ERROR getting database provider", ex);
-        }
+        return WebloggerStartup.getDatabaseProvider().getConnection();
     }
 
     /** Close connection by calling connection.close() */

Modified: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPARollerImpl.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPARollerImpl.java?view=diff&rev=549132&r1=549131&r2=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPARollerImpl.java (original)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPARollerImpl.java Wed Jun 20 08:27:15 2007
@@ -26,7 +26,6 @@
 import java.util.Properties;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.roller.weblogger.business.jpa.JPAPersistenceStrategy;
 import org.apache.roller.weblogger.WebloggerException;
 import org.apache.roller.weblogger.business.BookmarkManager;
 import org.apache.roller.weblogger.business.DatabaseProvider;
@@ -40,6 +39,7 @@
 import org.apache.roller.weblogger.business.pings.PingQueueManager;
 import org.apache.roller.weblogger.business.pings.PingTargetManager;
 import org.apache.roller.weblogger.business.referrers.RefererManager;
+import org.apache.roller.weblogger.business.startup.WebloggerStartup;
 import org.apache.roller.weblogger.config.RollerConfig;
 
 
@@ -87,7 +87,7 @@
             }
         }
         
-        DatabaseProvider dbProvider = DatabaseProvider.getDatabaseProvider();
+        DatabaseProvider dbProvider = WebloggerStartup.getDatabaseProvider();
         if (dbProvider.getType() == DatabaseProvider.ConfigurationType.JNDI_NAME) {
             strategy = new JPAPersistenceStrategy(
                 "RollerPU", "java:comp/env/" + dbProvider.getJndiName(), props); 

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/StartupException.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/StartupException.java?view=auto&rev=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/StartupException.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/StartupException.java Wed Jun 20 08:27:15 2007
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.startup;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.roller.weblogger.WebloggerException;
+
+
+/**
+ * Exception generated from Weblogger startup process.
+ */
+public class StartupException extends WebloggerException {
+    
+    private final List<String> startupLog;
+    
+    
+    public StartupException(String msg) {
+        super(msg);
+        this.startupLog = Collections.EMPTY_LIST;
+    }
+    
+    public StartupException(String msg, Throwable t) {
+        super(msg, t);
+        this.startupLog = Collections.EMPTY_LIST;
+    }
+    
+    public StartupException(String msg, List<String> log) {
+        super(msg);
+        
+        if(log != null) {
+            this.startupLog = log;
+        } else {
+            this.startupLog = Collections.EMPTY_LIST;
+        }
+    }
+    
+    public StartupException(String msg, Throwable t, List<String> log) {
+        super(msg, t);
+        
+        if(log != null) {
+            this.startupLog = log;
+        } else {
+            this.startupLog = Collections.EMPTY_LIST;
+        }
+    }
+    
+    
+    public List<String> getStartupLog() {
+        return startupLog;
+    }
+    
+}

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/WebloggerStartup.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/WebloggerStartup.java?view=auto&rev=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/WebloggerStartup.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/startup/WebloggerStartup.java Wed Jun 20 08:27:15 2007
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.startup;
+
+import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.business.DatabaseProvider;
+import org.apache.roller.weblogger.business.MailProvider;
+import org.apache.roller.weblogger.business.utils.ClasspathDatabaseScriptProvider;
+import org.apache.roller.weblogger.business.utils.DatabaseInstaller;
+import org.apache.roller.weblogger.config.RollerConfig;
+
+
+/**
+ * Manages Roller Weblogger startup process.
+ */
+public final class WebloggerStartup {
+    
+    private static final Log log = LogFactory.getLog(WebloggerStartup.class);
+    
+    private static boolean prepared = false;
+    
+    private static DatabaseProvider dbProvider = null;
+    private static StartupException dbProviderException = null;
+    
+    private static MailProvider mailProvider = null;
+    
+    private static DatabaseInstaller dbInstaller = null;
+    
+    
+    // non-instantiable
+    private WebloggerStartup() {}
+    
+    
+    /**
+     * Is the Roller Weblogger app properly prepared to be bootstrapped?
+     */
+    public static boolean isPrepared() {
+        return prepared;
+    }
+    
+    
+    /**
+     * Get a reference to the currently configured DatabaseProvider.
+     *
+     * @return DatabaseProvider The configured database provider.
+     * @throws IllegalStateException If the app has not been properly prepared yet.
+     */
+    public static DatabaseProvider getDatabaseProvider() {
+        if (dbProvider == null) {
+            throw new IllegalStateException("Roller Weblogger has not been prepared yet");
+        }
+        return dbProvider;
+    }
+    
+    
+    /**
+     * Get a reference to the exception thrown while instantiating the 
+     * database provider, if any.
+     *
+     * @return StartupException Exception from db provider, or null if no exception thrown.
+     */
+    public static StartupException getDatabaseProviderException() {
+        return dbProviderException;
+    }
+    
+    
+    /**
+     * Get a reference to the currently configured MailProvider, if available.
+     *
+     * @return MailProvider The configured mail provider, or null if none configured.
+     */
+    public static MailProvider getMailProvider() {
+        return mailProvider;
+    }
+    
+    
+    /**
+     * Does the app need to create the database tables?
+     */
+    public static boolean isDatabaseCreationRequired() {
+        return getDatabaseInstaller().isCreationRequired();
+    }
+    
+    
+    /**
+     * Run database creation scripts.
+     */
+    public static List<String> createDatabase() throws StartupException {
+        
+        DatabaseInstaller installer = getDatabaseInstaller();
+        try {
+            installer.createDatabase();
+            
+            // any time we've successfully installed a db we are prepared
+            prepared = true;
+            
+        } catch (StartupException se) {
+            throw new StartupException(se.getMessage(), se.getRootCause(), installer.getMessages());
+        }
+        
+        return installer.getMessages();
+    }
+    
+    
+    /**
+     * Does the app require any upgrading?
+     */
+    public static boolean isDatabaseUpgradeRequired() {
+        return getDatabaseInstaller().isUpgradeRequired();
+    }
+    
+    
+    /**
+     * Run database upgrade work, optionally including upgrade scripts.
+     */
+    public static List<String> upgradeDatabase(boolean runScripts) 
+            throws StartupException {
+        
+        DatabaseInstaller installer = getDatabaseInstaller();
+        try {
+            installer.upgradeDatabase(true);
+            
+            // any time we've successfully upgraded a db we are prepared
+            prepared = true;
+            
+        } catch (StartupException se) {
+            throw new StartupException(se.getMessage(), se.getRootCause(), installer.getMessages());
+        }
+        
+        return installer.getMessages();
+    }
+    
+    
+    /**
+     * Get a database installer.
+     *
+     * @return DatabaseInstaller A database installer.
+     * @throws IllegalStateException If the database provider has not been properly setup yet.
+     */
+    private static DatabaseInstaller getDatabaseInstaller() {
+        return new DatabaseInstaller(getDatabaseProvider(), new ClasspathDatabaseScriptProvider());
+    }
+    
+    
+    /**
+     * Run the Roller Weblogger preparation sequence.
+     *
+     * This sequence is what prepares the core services of the application such
+     * as setting up the database and mail providers.
+     */
+    public static void prepare() throws StartupException {
+        
+        // setup database provider
+        try {
+            dbProvider = new DatabaseProvider();
+        } catch(StartupException ex) {
+            dbProviderException = ex;
+            throw ex;
+        }
+        
+        // setup mail provider, if configured
+        try {
+            mailProvider = new MailProvider();
+        } catch(StartupException ex) {
+            log.warn("Failed to setup mail provider, continuing anways", ex);
+        }
+        
+        // now we need to deal with database install/upgrade logic
+        if("manual".equals(RollerConfig.getProperty("installation.type"))) {
+            
+            // if we are doing manual install then all that is needed is the
+            // app handled database upgrade work, not the db scripts
+            DatabaseInstaller dbInstaller = getDatabaseInstaller();
+            if(dbInstaller.isUpgradeRequired()) {
+                dbInstaller.upgradeDatabase(false);
+            }
+            
+            prepared = true;
+            
+        } else {
+            
+            // we are in auto install mode, so see if there is any work to do
+            DatabaseInstaller dbInstaller = getDatabaseInstaller();
+            if(!dbInstaller.isCreationRequired() && 
+                    !dbInstaller.isUpgradeRequired()) {
+                prepared = true;
+            }
+        }
+        
+    }
+    
+}

Added: roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/ClasspathDatabaseScriptProvider.java
URL: http://svn.apache.org/viewvc/roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/ClasspathDatabaseScriptProvider.java?view=auto&rev=549132
==============================================================================
--- roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/ClasspathDatabaseScriptProvider.java (added)
+++ roller/trunk/apps/weblogger/src/java/org/apache/roller/weblogger/business/utils/ClasspathDatabaseScriptProvider.java Wed Jun 20 08:27:15 2007
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.business.utils;
+
+import java.io.InputStream;
+
+
+/**
+ * Reads dbscripts from the classpath.
+ */
+public class ClasspathDatabaseScriptProvider implements DatabaseScriptProvider {
+    
+    public InputStream getDatabaseScript(String path) {
+        return ClasspathDatabaseScriptProvider.class.getResourceAsStream(
+                "/dbscripts/" + path);
+    }
+    
+}