FELIX-1180 Improve Karaf DefaultJDBCLock to use proper logging mechanism instead of System err prints.
- Added bootstrap logger using java.util.logging
- Log file will be the default "out" file appender from log4j config
- File location can be overridden by setting "karaf.bootstrap.log" in config.properties
- There are probably better ways to do this, but this works reasonably well and gives a common logging interface (juli) to work with.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@812015 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/BootstrapLogManager.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/BootstrapLogManager.java
new file mode 100644
index 0000000..bde0b98
--- /dev/null
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/BootstrapLogManager.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  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.
+ */
+package org.apache.felix.karaf.main;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.StreamHandler;
+
+/**
+ * Convenience class for configuring java.util.logging to append to
+ * the configured log4j log.  This could be used for bootstrap logging
+ * prior to start of the framework.
+ * 
+ */
+public class BootstrapLogManager {
+    private static Handler handler;
+    private static final String KARAF_BOOTSTRAP_LOG = "karaf.bootstrap.log";
+
+    private static Properties configProps;
+
+    public static Handler getDefaultHandler () {
+        String filename;
+        File log;
+        Properties props = new Properties();
+        filename = configProps.getProperty(KARAF_BOOTSTRAP_LOG);
+
+        if (filename != null) {
+            log = new File(filename);
+        } else {
+            // Make a best effort to log to the default file appender configured for log4j
+            try {
+                props.load(new FileInputStream("../etc/org.ops4j.pax.logging.cfg"));
+            } catch (IOException e) {
+                props.setProperty("log4j.appender.out.file", "${karaf.base}/data/log/karaf.log");
+            }
+            filename = Main.substVars(props.getProperty("log4j.appender.out.file"),"log4j.appender.out.file", null, null);
+            log = new File(filename);
+        }
+
+
+        try {
+            handler = new BootstrapLogManager.SimpleFileHandler(log);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return handler;
+    }
+
+    public static void setProperties(Properties configProps) {
+        BootstrapLogManager.configProps = configProps;
+    }
+
+
+    /**
+     * Implementation of java.util.logging.Handler that does simple appending
+     * to a named file.  Should be able to use this for bootstrap logging
+     * via java.util.logging prior to startup of pax logging.
+     */
+    public static class SimpleFileHandler extends StreamHandler {
+
+        public SimpleFileHandler (File file) throws IOException {
+            open(file, true);
+        }
+
+        private void open (File logfile, boolean append) throws IOException {
+            if (!logfile.getParentFile().exists()) {
+                logfile.getParentFile().mkdirs();
+            }
+            FileOutputStream fout = new FileOutputStream(logfile, append);
+            BufferedOutputStream out = new BufferedOutputStream(fout);
+            setOutputStream(out);
+        }
+
+        public synchronized void publish (LogRecord record) {
+            if (!isLoggable(record)) {
+                return;
+            }
+            super.publish(record);
+            flush();
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java
index 88fd5bd..3196d57 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/DefaultJDBCLock.java
@@ -23,6 +23,7 @@
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.util.Properties;
+import java.util.logging.Logger;
 
 /**
  * Represents an exclusive lock on a database,
@@ -33,6 +34,7 @@
  */
 public class DefaultJDBCLock implements Lock {
 
+    private static final Logger LOG = Logger.getLogger(DefaultJDBCLock.class.getName());
     private static final String PROPERTY_LOCK_URL               = "karaf.lock.jdbc.url";
     private static final String PROPERTY_LOCK_JDBC_DRIVER       = "karaf.lock.jdbc.driver";
     private static final String PROPERTY_LOCK_JDBC_USER         = "karaf.lock.jdbc.user";
@@ -52,6 +54,7 @@
     private int timeout;
 
     public DefaultJDBCLock(Properties props) {
+        LOG.addHandler(BootstrapLogManager.getDefaultHandler());
         this.url = props.getProperty(PROPERTY_LOCK_URL);
         this.driver = props.getProperty(PROPERTY_LOCK_JDBC_DRIVER);
         this.user = props.getProperty(PROPERTY_LOCK_JDBC_USER);
@@ -91,19 +94,19 @@
             statement = lockConnection.prepareStatement(sql);
             result = statement.execute();
         } catch (Exception e) {
-            System.err.println("Could not obtain connection: " + e.getMessage());
+            LOG.warning("Could not obtain connection: " + e.getMessage());
         } finally {
             if (null != statement) {
                 try {
-                    System.err.println("Cleaning up DB connection.");
+                    LOG.severe("Cleaning up DB connection.");
                     statement.close();
                 } catch (SQLException e1) {
-                    System.err.println("Caught while closing statement: " + e1.getMessage());
+                    LOG.severe("Caught while closing statement: " + e1.getMessage());
                 }
                 statement = null;
             }
         }
-        System.out.println("Connected to data source: " + url);
+        LOG.info("Connected to data source: " + url);
         return result;
     }
 
@@ -117,7 +120,7 @@
         boolean result = false;
         try {
             if (!setUpdateCursor()) {
-                System.err.println("Could not set DB update cursor");
+                LOG.severe("Could not set DB update cursor");
                 return result;
             }
             long time = System.currentTimeMillis();
@@ -127,13 +130,13 @@
                 result=true;
             }
         } catch (Exception e) {
-            System.err.println("Failed to acquire database lock: " + e.getMessage());
+            LOG.warning("Failed to acquire database lock: " + e.getMessage());
         }finally {
             if (statement != null) {
                 try {
                     statement.close();
                 } catch (SQLException e) {
-                    System.err.println("Failed to close statement" + e);
+                    LOG.severe("Failed to close statement" + e);
                 }
             }
         }
@@ -156,7 +159,7 @@
      */
     public boolean isAlive() throws Exception {
         if ((lockConnection == null) || (lockConnection.isClosed())) { 
-            System.err.println("Lost lock!");
+            LOG.severe("Lost lock!");
             return false; 
         }
         PreparedStatement statement = null;
@@ -169,14 +172,14 @@
                 result = false;
             }
         } catch (Exception ex) {
-            System.err.println("Error occured while testing lock: " + ex + " " + ex.getMessage());
+            LOG.severe("Error occured while testing lock: " + ex + " " + ex.getMessage());
             return false;
         } finally {
             if (statement != null) {
                 try {
                     statement.close();
                 } catch (Exception ex1) {
-                    System.err.println("Error occured after testing lock: " + ex1.getMessage());
+                    LOG.severe("Error occured after testing lock: " + ex1.getMessage());
                 }
             }
         }
@@ -204,7 +207,7 @@
                 conn = DriverManager.getConnection(url, username, password);
             }
         } catch (Exception e) {
-            System.err.println("Error occured while setting up JDBC connection: " + e);
+            LOG.severe("Error occured while setting up JDBC connection: " + e);
             throw e; 
         }
         return conn;
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
index 275a405..b11dd25 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/Main.java
@@ -36,6 +36,7 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.StringTokenizer;
+import java.util.logging.Logger;
 import java.util.concurrent.CountDownLatch;
 
 import org.apache.felix.karaf.main.Utils;
@@ -126,6 +127,8 @@
 
     public static final String PROPERTY_LOCK_CLASS_DEFAULT = SimpleFileLock.class.getName();
 
+    Logger LOG = Logger.getLogger(this.getClass().getName());
+
     private File karafHome;
     private File karafBase;
     private Properties configProps = null;
@@ -157,6 +160,8 @@
 
         // Read configuration properties.
         configProps = loadConfigProperties();
+        BootstrapLogManager.setProperties(configProps);
+        LOG.addHandler(BootstrapLogManager.getDefaultHandler());
 
         // Copy framework properties from the system properties.
         Main.copySystemProperties(configProps);
@@ -991,7 +996,7 @@
                 for (;;) {
                     if (lock.lock()) {
                         if (lockLogged) {
-                            System.out.println("Lock acquired.");
+                            LOG.info("Lock acquired.");
                         }
                         setStartLevel(defaultStartLevel);
                         for (;;) {
@@ -1001,12 +1006,12 @@
                             Thread.sleep(lockDelay);
                         }
                         if (framework.getState() == Bundle.ACTIVE && !exiting) {
-                            System.out.println("Lost the lock, stopping this instance ...");
+                            LOG.info("Lost the lock, stopping this instance ...");
                             setStartLevel(lockStartLevel);
                         }
                         break;
                     } else if (!lockLogged) {
-                        System.out.println("Waiting for the lock ...");
+                        LOG.info("Waiting for the lock ...");
                         lockLogged = true;
                     }
                     Thread.sleep(lockDelay);
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/SimpleFileLock.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/SimpleFileLock.java
index 110058f..92373a9 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/SimpleFileLock.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/SimpleFileLock.java
@@ -23,9 +23,11 @@
 import java.io.RandomAccessFile;
 import java.nio.channels.FileLock;
 import java.util.Properties;
+import java.util.logging.Logger;
 
 public class SimpleFileLock implements Lock {
 
+    private static final Logger LOG = Logger.getLogger(SimpleFileLock.class.getName());
     private static final String PROPERTY_LOCK_DIR = "karaf.lock.dir";
     private static final String PROP_KARAF_BASE = "karaf.base";
     private RandomAccessFile lockFile;
@@ -33,6 +35,8 @@
 
     public SimpleFileLock(Properties props) {
         try {
+
+            LOG.addHandler( BootstrapLogManager.getDefaultHandler() );
             String lock = props.getProperty(PROPERTY_LOCK_DIR);
 
             if (lock != null) {
@@ -50,6 +54,7 @@
     }
 
     public boolean lock() throws Exception {
+        LOG.info("locking");
         if (lock == null) {
             lock = lockFile.getChannel().tryLock();
         }
@@ -57,6 +62,7 @@
     }
 
     public void release() throws Exception {
+        LOG.info("releasing");
         if (lock != null && lock.isValid()) {
             lock.release();
             lock.channel().close();
diff --git a/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java b/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java
index 3e675f4..aae25ef 100644
--- a/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java
+++ b/karaf/main/src/main/java/org/apache/felix/karaf/main/Statements.java
@@ -22,9 +22,11 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.logging.Logger;
 
 public class Statements {
 
+    private static Logger LOG = Logger.getLogger(Statements.class.getName());
     private String lockTableName = "KARAF_LOCK";
     private String clusterName = "karaf";
     private String lockCreateStatement;
@@ -32,6 +34,8 @@
     private String lockUpdateStatement;
 
     public Statements(String tableName, String clusterName) {
+        LOG.addHandler( BootstrapLogManager.getDefaultHandler() );
+        
         this.lockTableName = tableName; 
         this.clusterName = clusterName;
         this.lockCreateStatement="create table " + lockTableName + " (TIME bigint, CLUSTER varchar(20))";
@@ -67,7 +71,7 @@
                 rs = lockConnection.getMetaData().getTables(null, null, lockTableName, new String[] {"TABLE"});
                 alreadyExists = rs.next();
             } catch (Throwable ignore) {
-                System.err.println(ignore);
+                LOG.severe("Error testing for db table: " + ignore);
             } finally {
                 close(rs);
             }
@@ -82,19 +86,19 @@
                 try {
                     s.execute(createStatments[i]);
                 } catch (SQLException e) {
-                    System.err.println("Could not create JDBC tables; they could already exist."
-                                 + " Failure was: " + createStatments[i] + " Message: " + e.getMessage()
-                                 + " SQLState: " + e.getSQLState() + " Vendor code: " + e.getErrorCode());
+                    LOG.severe("Could not create JDBC tables; they could already exist."
+                             + " Failure was: " + createStatments[i] + " Message: " + e.getMessage()
+                             + " SQLState: " + e.getSQLState() + " Vendor code: " + e.getErrorCode());
                 }
             }
             lockConnection.commit();
         } catch (Exception ignore) {
-            System.err.println(ignore);
+            LOG.severe("Error occured during initialization: " + ignore);
         } finally {
             try {
                 if (s != null) { s.close(); }
             } catch (Throwable e) {
-                // ignore
+                LOG.severe("Error occured while closing connection: " + e);
             }
         }
     }
@@ -103,7 +107,7 @@
         try {
             rs.close();
         } catch (Throwable e) {
-            // ignore
+            LOG.severe("Error occured while releasing ResultSet: " + e);
         }
     }