# HG changeset patch
# User cli
# Date 1315753279 -7200
# Node ID 8df94bfd3e2f943cebeafe2224e88aced804fd99
# Parent  b78e7761915246923ab36c027531325cc069d4a0
Fix for #14

diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/Main.java
--- a/src/org/sonews/Main.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/Main.java	Sun Sep 11 17:01:19 2011 +0200
@@ -45,6 +45,8 @@
 
 	/** Version information of the sonews daemon */
 	public static final String VERSION = "sonews/1.1.0";
+
+	/** The server's startup date */
 	public static final Date STARTDATE = new Date();
 
 	/**
@@ -81,13 +83,16 @@
 				mlgw = true;
 			} else if (args[n].equals("-p")) {
 				port = Integer.parseInt(args[++n]);
-			} else if (args[n].equals("-plugin")) {
+			} else if (args[n].equals("-plugin-storage")) {
 				System.out.println("Warning: -plugin-storage is not implemented!");
 			} else if (args[n].equals("-plugin-command")) {
 				try {
 					CommandSelector.addCommandHandler(args[++n]);
 				} catch (Exception ex) {
-					Log.get().warning("Could not load command plugin: " + args[n]);
+					StringBuilder strBuf = new StringBuilder();
+					strBuf.append("Could not load command plugin: ");
+					strBuf.append(args[n]);
+					Log.get().warning(strBuf.toString());
 					Log.get().log(Level.INFO, "Main.java", ex);
 				}
 			} else if (args[n].equals("-plugin-storage")) {
@@ -113,10 +118,10 @@
 				Log.get().info("Group 'control' created.");
 			}
 		} catch (StorageBackendException ex) {
-			ex.printStackTrace();
+			Log.get().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
 			System.err.println("Database initialization failed with " + ex.toString());
 			System.err.println("Make sure you have specified the correct database"
-					+ " settings in sonews.conf!");
+							+ " settings in sonews.conf!");
 			return;
 		}
 
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/ShutdownHook.java
--- a/src/org/sonews/ShutdownHook.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/ShutdownHook.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews;
 
 import java.sql.SQLException;
@@ -27,15 +26,13 @@
  * @author Christian Lins
  * @since sonews/0.5.0
  */
-class ShutdownHook extends Thread
-{
+class ShutdownHook extends Thread {
 
 	/**
 	 * Called when the JVM exits.
 	 */
 	@Override
-	public void run()
-	{
+	public void run() {
 		System.out.println("sonews: Trying to shutdown all threads...");
 
 		Map<Thread, StackTraceElement[]> threadsMap = Thread.getAllStackTraces();
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/acl/AccessControl.java
--- a/src/org/sonews/acl/AccessControl.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/acl/AccessControl.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.acl;
 
 /**
@@ -23,8 +22,7 @@
  * @author Christian Lins
  * @since sonews/1.1
  */
-public interface AccessControl
-{
+public interface AccessControl {
 
 	boolean hasPermission(String user, char[] secret, String permission);
 }
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/acl/AuthInfoCommand.java
--- a/src/org/sonews/acl/AuthInfoCommand.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/acl/AuthInfoCommand.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.acl;
 
 import java.io.IOException;
@@ -28,37 +27,31 @@
  * @author Christian Lins
  * @since sonews/1.1
  */
-public class AuthInfoCommand implements Command
-{
+public class AuthInfoCommand implements Command {
 
 	@Override
-	public String[] getSupportedCommandStrings()
-	{
+	public String[] getSupportedCommandStrings() {
 		throw new UnsupportedOperationException("Not supported yet.");
 	}
 
 	@Override
-	public boolean hasFinished()
-	{
+	public boolean hasFinished() {
 		throw new UnsupportedOperationException("Not supported yet.");
 	}
 
 	@Override
-	public String impliedCapability()
-	{
+	public String impliedCapability() {
 		throw new UnsupportedOperationException("Not supported yet.");
 	}
 
 	@Override
-	public boolean isStateful()
-	{
+	public boolean isStateful() {
 		throw new UnsupportedOperationException("Not supported yet.");
 	}
 
 	@Override
 	public void processLine(NNTPConnection conn, String line, byte[] rawLine)
-		throws IOException, StorageBackendException
-	{
+			throws IOException, StorageBackendException {
 		throw new UnsupportedOperationException("Not supported yet.");
 	}
 }
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/config/AbstractConfig.java
--- a/src/org/sonews/config/AbstractConfig.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/config/AbstractConfig.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.config;
 
 /**
@@ -23,19 +22,16 @@
  * @author Christian Lins
  * @since sonews/0.5.0
  */
-public abstract class AbstractConfig
-{
+public abstract class AbstractConfig {
 
 	public abstract String get(String key, String defVal);
 
-	public int get(final String key, final int defVal)
-	{
+	public int get(final String key, final int defVal) {
 		return Integer.parseInt(
-			get(key, Integer.toString(defVal)));
+				get(key, Integer.toString(defVal)));
 	}
 
-	public boolean get(String key, boolean defVal)
-	{
+	public boolean get(String key, boolean defVal) {
 		String val = get(key, Boolean.toString(defVal));
 		return Boolean.parseBoolean(val);
 	}
@@ -46,8 +42,7 @@
 	 * @param defVal
 	 * @return
 	 */
-	public long get(String key, long defVal)
-	{
+	public long get(String key, long defVal) {
 		String val = get(key, Long.toString(defVal));
 		return Long.parseLong(val);
 	}
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/config/BackendConfig.java
--- a/src/org/sonews/config/BackendConfig.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/config/BackendConfig.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.config;
 
 import java.util.logging.Level;
@@ -30,19 +29,16 @@
  * @author Christian Lins
  * @since sonews/0.5.0
  */
-class BackendConfig extends AbstractConfig
-{
+class BackendConfig extends AbstractConfig {
 
 	private static BackendConfig instance = new BackendConfig();
 
-	public static BackendConfig getInstance()
-	{
+	public static BackendConfig getInstance() {
 		return instance;
 	}
 	private final TimeoutMap<String, String> values = new TimeoutMap<String, String>();
 
-	private BackendConfig()
-	{
+	private BackendConfig() {
 		super();
 	}
 
@@ -54,8 +50,7 @@
 	 * @return
 	 */
 	@Override
-	public String get(String key, String defaultValue)
-	{
+	public String get(String key, String defaultValue) {
 		try {
 			String configValue = values.get(key);
 			if (configValue == null) {
@@ -85,8 +80,7 @@
 	 * @param key
 	 * @param value
 	 */
-	public void set(String key, String value)
-	{
+	public void set(String key, String value) {
 		values.put(key, value);
 
 		try {
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/config/CommandLineConfig.java
--- a/src/org/sonews/config/CommandLineConfig.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/config/CommandLineConfig.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.config;
 
 import java.util.Map;
@@ -25,24 +24,20 @@
  *
  * @author Christian Lins
  */
-class CommandLineConfig extends AbstractConfig
-{
+class CommandLineConfig extends AbstractConfig {
 
 	private static final CommandLineConfig instance = new CommandLineConfig();
 
-	public static CommandLineConfig getInstance()
-	{
+	public static CommandLineConfig getInstance() {
 		return instance;
 	}
 	private final Map<String, String> values = new HashMap<String, String>();
 
-	private CommandLineConfig()
-	{
+	private CommandLineConfig() {
 	}
 
 	@Override
-	public String get(String key, String def)
-	{
+	public String get(String key, String def) {
 		synchronized (this.values) {
 			if (this.values.containsKey(key)) {
 				def = this.values.get(key);
@@ -52,8 +47,7 @@
 	}
 
 	@Override
-	public void set(String key, String val)
-	{
+	public void set(String key, String val) {
 		synchronized (this.values) {
 			this.values.put(key, val);
 		}
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/config/Config.java
--- a/src/org/sonews/config/Config.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/config/Config.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.config;
 
 /**
@@ -23,8 +22,7 @@
  * @author Christian Lins
  * @since sonews/1.0
  */
-public class Config extends AbstractConfig
-{
+public class Config extends AbstractConfig {
 
 	public static final int LEVEL_CLI = 1;
 	public static final int LEVEL_FILE = 2;
@@ -91,18 +89,15 @@
 	};
 	private static Config instance = new Config();
 
-	public static Config inst()
-	{
+	public static Config inst() {
 		return instance;
 	}
 
-	private Config()
-	{
+	private Config() {
 	}
 
 	@Override
-	public String get(String key, String def)
-	{
+	public String get(String key, String def) {
 		String val = CommandLineConfig.getInstance().get(key, null);
 
 		if (val == null) {
@@ -116,8 +111,7 @@
 		return val;
 	}
 
-	public String get(int maxLevel, String key, String def)
-	{
+	public String get(int maxLevel, String key, String def) {
 		String val = CommandLineConfig.getInstance().get(key, null);
 
 		if (val == null && maxLevel >= LEVEL_FILE) {
@@ -131,13 +125,11 @@
 	}
 
 	@Override
-	public void set(String key, String val)
-	{
+	public void set(String key, String val) {
 		set(LEVEL_BACKEND, key, val);
 	}
 
-	public void set(int level, String key, String val)
-	{
+	public void set(int level, String key, String val) {
 		switch (level) {
 			case LEVEL_CLI: {
 				CommandLineConfig.getInstance().set(key, val);
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/daemon/NNTPConnection.java
--- a/src/org/sonews/daemon/NNTPConnection.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/daemon/NNTPConnection.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.daemon;
 
 import java.io.IOException;
@@ -30,6 +29,7 @@
 import java.util.Arrays;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.logging.Level;
 import org.sonews.daemon.command.Command;
 import org.sonews.storage.Article;
 import org.sonews.storage.Group;
@@ -43,8 +43,7 @@
  * @author Christian Lins
  * @since sonews/0.5.0
  */
-public final class NNTPConnection
-{
+public final class NNTPConnection {
 
 	public static final String NEWLINE = "\r\n";    // RFC defines this as newline
 	public static final String MESSAGE_ID_PATTERN = "<[^>]+>";
@@ -62,8 +61,7 @@
 	private SelectionKey writeSelKey = null;
 
 	public NNTPConnection(final SocketChannel channel)
-		throws IOException
-	{
+			throws IOException {
 		if (channel == null) {
 			throw new IllegalArgumentException("channel is null");
 		}
@@ -77,8 +75,7 @@
 	 * safe and returns true of the read lock was successfully set. If the lock
 	 * is still hold by another Thread the method returns false.
 	 */
-	boolean tryReadLock()
-	{
+	boolean tryReadLock() {
 		// As synchronizing simple types may cause deadlocks,
 		// we use a gate object.
 		synchronized (readLockGate) {
@@ -96,8 +93,7 @@
 	 * @throws IllegalMonitorStateException if a Thread not holding the lock
 	 * tries to release it.
 	 */
-	void unlockReadLock()
-	{
+	void unlockReadLock() {
 		synchronized (readLockGate) {
 			if (readLock == Thread.currentThread().hashCode()) {
 				readLock = 0;
@@ -110,8 +106,7 @@
 	/**
 	 * @return Current input buffer of this NNTPConnection instance.
 	 */
-	public ByteBuffer getInputBuffer()
-	{
+	public ByteBuffer getInputBuffer() {
 		return this.lineBuffers.getInputBuffer();
 	}
 
@@ -119,34 +114,29 @@
 	 * @return Output buffer of this NNTPConnection which has at least one byte
 	 * free storage.
 	 */
-	public ByteBuffer getOutputBuffer()
-	{
+	public ByteBuffer getOutputBuffer() {
 		return this.lineBuffers.getOutputBuffer();
 	}
 
 	/**
 	 * @return ChannelLineBuffers instance associated with this NNTPConnection.
 	 */
-	public ChannelLineBuffers getBuffers()
-	{
+	public ChannelLineBuffers getBuffers() {
 		return this.lineBuffers;
 	}
 
 	/**
 	 * @return true if this connection comes from a local remote address.
 	 */
-	public boolean isLocalConnection()
-	{
+	public boolean isLocalConnection() {
 		return ((InetSocketAddress) this.channel.socket().getRemoteSocketAddress()).getHostName().equalsIgnoreCase("localhost");
 	}
 
-	void setWriteSelectionKey(SelectionKey selKey)
-	{
+	void setWriteSelectionKey(SelectionKey selKey) {
 		this.writeSelKey = selKey;
 	}
 
-	public void shutdownInput()
-	{
+	public void shutdownInput() {
 		try {
 			// Closes the input line of the channel's socket, so no new data
 			// will be received and a timeout can be triggered.
@@ -156,14 +146,10 @@
 		}
 	}
 
-	public void shutdownOutput()
-	{
-		cancelTimer.schedule(new TimerTask()
-		{
-
+	public void shutdownOutput() {
+		cancelTimer.schedule(new TimerTask() {
 			@Override
-			public void run()
-			{
+			public void run() {
 				try {
 					// Closes the output line of the channel's socket.
 					channel.socket().shutdownOutput();
@@ -178,41 +164,34 @@
 		}, 3000);
 	}
 
-	public SocketChannel getSocketChannel()
-	{
+	public SocketChannel getSocketChannel() {
 		return this.channel;
 	}
 
-	public Article getCurrentArticle()
-	{
+	public Article getCurrentArticle() {
 		return this.currentArticle;
 	}
 
-	public Charset getCurrentCharset()
-	{
+	public Charset getCurrentCharset() {
 		return this.charset;
 	}
 
 	/**
 	 * @return The currently selected communication channel (not SocketChannel)
 	 */
-	public Group getCurrentChannel()
-	{
+	public Group getCurrentChannel() {
 		return this.currentGroup;
 	}
 
-	public void setCurrentArticle(final Article article)
-	{
+	public void setCurrentArticle(final Article article) {
 		this.currentArticle = article;
 	}
 
-	public void setCurrentGroup(final Group group)
-	{
+	public void setCurrentGroup(final Group group) {
 		this.currentGroup = group;
 	}
 
-	public long getLastActivity()
-	{
+	public long getLastActivity() {
 		return this.lastActivity;
 	}
 
@@ -222,8 +201,7 @@
 	 * @throws IllegalArgumentException if raw is null.
 	 * @throws IllegalStateException if calling thread does not own the readLock.
 	 */
-	void lineReceived(byte[] raw)
-	{
+	void lineReceived(byte[] raw) {
 		if (raw == null) {
 			throw new IllegalArgumentException("raw is null");
 		}
@@ -262,17 +240,25 @@
 			}
 		} catch (ClosedChannelException ex0) {
 			try {
-				Log.get().info("Connection to " + channel.socket().getRemoteSocketAddress()
-					+ " closed: " + ex0);
+				StringBuilder strBuf = new StringBuilder();
+				strBuf.append("Connection to ");
+				strBuf.append(channel.socket().getRemoteSocketAddress());
+				strBuf.append(" closed: ");
+				strBuf.append(ex0);
+				Log.get().info(strBuf.toString());
 			} catch (Exception ex0a) {
 				ex0a.printStackTrace();
 			}
-		} catch (Exception ex1) // This will catch a second StorageBackendException
-		{
+		} catch (Exception ex1) { // This will catch a second StorageBackendException
 			try {
 				command = null;
-				ex1.printStackTrace();
-				println("500 Internal server error");
+				Log.get().log(Level.WARNING, ex1.getLocalizedMessage(), ex1);
+				println("403 Internal server error");
+
+				// Should we end the connection here?
+				// RFC says we MUST return 400 before closing the connection
+				shutdownInput();
+				shutdownOutput();
 			} catch (Exception ex2) {
 				ex2.printStackTrace();
 			}
@@ -289,8 +275,7 @@
 	 * @param line
 	 * @return
 	 */
-	private Command parseCommandLine(String line)
-	{
+	private Command parseCommandLine(String line) {
 		String cmdStr = line.split(" ")[0];
 		return CommandSelector.getInstance().get(cmdStr);
 	}
@@ -303,8 +288,7 @@
 	 * @param line
 	 */
 	public void println(final CharSequence line, final Charset charset)
-		throws IOException
-	{
+			throws IOException {
 		writeToChannel(CharBuffer.wrap(line), charset, line);
 		writeToChannel(CharBuffer.wrap(NEWLINE), charset, null);
 	}
@@ -315,8 +299,7 @@
 	 * @param rawLines
 	 */
 	public void println(final byte[] rawLines)
-		throws IOException
-	{
+			throws IOException {
 		this.lineBuffers.addOutputBuffer(ByteBuffer.wrap(rawLines));
 		writeToChannel(CharBuffer.wrap(NEWLINE), charset, null);
 	}
@@ -328,9 +311,8 @@
 	 * @throws java.io.IOException
 	 */
 	private void writeToChannel(CharBuffer characters, final Charset charset,
-		CharSequence debugLine)
-		throws IOException
-	{
+			CharSequence debugLine)
+			throws IOException {
 		if (!charset.canEncode()) {
 			Log.get().severe("FATAL: Charset " + charset + " cannot encode!");
 			return;
@@ -343,8 +325,7 @@
 		enableWriteEvents(debugLine);
 	}
 
-	private void enableWriteEvents(CharSequence debugLine)
-	{
+	private void enableWriteEvents(CharSequence debugLine) {
 		// Enable OP_WRITE events so that the buffers are processed
 		try {
 			this.writeSelKey.interestOps(SelectionKey.OP_WRITE);
@@ -363,24 +344,20 @@
 	}
 
 	public void println(final CharSequence line)
-		throws IOException
-	{
+			throws IOException {
 		println(line, charset);
 	}
 
 	public void print(final String line)
-		throws IOException
-	{
+			throws IOException {
 		writeToChannel(CharBuffer.wrap(line), charset, line);
 	}
 
-	public void setCurrentCharset(final Charset charset)
-	{
+	public void setCurrentCharset(final Charset charset) {
 		this.charset = charset;
 	}
 
-	void setLastActivity(long timestamp)
-	{
+	void setLastActivity(long timestamp) {
 		this.lastActivity = timestamp;
 	}
 }
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/daemon/command/ListCommand.java
--- a/src/org/sonews/daemon/command/ListCommand.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/daemon/command/ListCommand.java	Sun Sep 11 17:01:19 2011 +0200
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.sonews.daemon.command;
 
 import java.io.IOException;
@@ -34,37 +33,31 @@
  * @author Dennis Schwerdel
  * @since n3tpd/0.1
  */
-public class ListCommand implements Command
-{
+public class ListCommand implements Command {
 
 	@Override
-	public String[] getSupportedCommandStrings()
-	{
-		return new String[] {"LIST"};
+	public String[] getSupportedCommandStrings() {
+		return new String[]{"LIST"};
 	}
 
 	@Override
-	public boolean hasFinished()
-	{
+	public boolean hasFinished() {
 		return true;
 	}
 
 	@Override
-	public String impliedCapability()
-	{
+	public String impliedCapability() {
 		return null;
 	}
 
 	@Override
-	public boolean isStateful()
-	{
+	public boolean isStateful() {
 		return false;
 	}
 
 	@Override
 	public void processLine(NNTPConnection conn, final String line, byte[] raw)
-		throws IOException, StorageBackendException
-	{
+			throws IOException, StorageBackendException {
 		final String[] command = line.split(" ");
 
 		if (command.length >= 2) {
@@ -90,7 +83,7 @@
 				conn.println(".");
 			} else if (command[1].equalsIgnoreCase("ACTIVE")) {
 				String pattern = command.length == 2
-					? null : command[2].replace("*", "\\w*");
+						? null : command[2].replace("*", "\\w*");
 				printGroupInfo(conn, pattern);
 			} else {
 				conn.println("500 unknown argument to LIST command");
@@ -101,21 +94,20 @@
 	}
 
 	private void printGroupInfo(NNTPConnection conn, String pattern)
-		throws IOException, StorageBackendException
-	{
+			throws IOException, StorageBackendException {
 		final List<Group> groups = Group.getAll();
 		if (groups != null) {
 			conn.println("215 list of newsgroups follows");
 			for (Group g : groups) {
 				try {
 					Matcher matcher = pattern == null
-						? null : Pattern.compile(pattern).matcher(g.getName());
+							? null : Pattern.compile(pattern).matcher(g.getName());
 					if (!g.isDeleted()
-						&& (matcher == null || matcher.find())) {
+							&& (matcher == null || matcher.find())) {
 						String writeable = g.isWriteable() ? " y" : " n";
 						// Indeed first the higher article number then the lower
 						conn.println(g.getName() + " " + g.getLastArticleNumber() + " "
-							+ g.getFirstArticleNumber() + writeable);
+								+ g.getFirstArticleNumber() + writeable);
 					}
 				} catch (PatternSyntaxException ex) {
 					Log.get().info(ex.toString());
diff -r b78e77619152 -r 8df94bfd3e2f src/org/sonews/util/Stats.java
--- a/src/org/sonews/util/Stats.java	Sun Sep 11 15:05:04 2011 +0200
+++ b/src/org/sonews/util/Stats.java	Sun Sep 11 17:01:19 2011 +0200
@@ -18,6 +18,7 @@
 package org.sonews.util;
 
 import java.util.Calendar;
+import java.util.logging.Level;
 import org.sonews.config.Config;
 import org.sonews.storage.Group;
 import org.sonews.storage.StorageBackendException;
@@ -63,10 +64,14 @@
 							System.currentTimeMillis(), type, group.getInternalID());
 				}
 			} else {
-				Log.get().info("Group " + groupname + " does not exist.");
+				StringBuilder strBuf = new StringBuilder();
+				strBuf.append("Group ");
+				strBuf.append(groupname);
+				strBuf.append(" does not exist.");
+				Log.get().info(strBuf.toString());
 			}
 		} catch (StorageBackendException ex) {
-			ex.printStackTrace();
+			Log.get().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
 		}
 	}
 
@@ -86,7 +91,7 @@
 		try {
 			return StorageManager.current().countGroups();
 		} catch (StorageBackendException ex) {
-			ex.printStackTrace();
+			Log.get().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
 			return -1;
 		}
 	}
@@ -95,7 +100,7 @@
 		try {
 			return StorageManager.current().countArticles();
 		} catch (StorageBackendException ex) {
-			ex.printStackTrace();
+			Log.get().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
 			return -1;
 		}
 	}
@@ -117,7 +122,7 @@
 		try {
 			return StorageManager.current().getEventsCount(eventType, startTimestamp, endTimestamp, group);
 		} catch (StorageBackendException ex) {
-			ex.printStackTrace();
+			Log.get().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
 			return -1;
 		}
 	}
@@ -146,7 +151,7 @@
 		try {
 			return StorageManager.current().getEventsPerHour(key, gid);
 		} catch (StorageBackendException ex) {
-			ex.printStackTrace();
+			Log.get().log(Level.SEVERE, ex.getLocalizedMessage(), ex);
 			return -1;
 		}
 	}