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);
}
}