1.1 --- a/org/sonews/config/BackendConfig.java Mon Aug 17 11:00:51 2009 +0200
1.2 +++ b/org/sonews/config/BackendConfig.java Thu Aug 20 14:31:19 2009 +0200
1.3 @@ -62,6 +62,12 @@
1.4 String configValue = values.get(key);
1.5 if(configValue == null)
1.6 {
1.7 + if(StorageManager.current() == null)
1.8 + {
1.9 + Log.msg("Warning: BackendConfig not available, using default.", false);
1.10 + return defaultValue;
1.11 + }
1.12 +
1.13 configValue = StorageManager.current().getConfigValue(key);
1.14 if(configValue == null)
1.15 {
2.1 --- a/org/sonews/config/Config.java Mon Aug 17 11:00:51 2009 +0200
2.2 +++ b/org/sonews/config/Config.java Thu Aug 20 14:31:19 2009 +0200
2.3 @@ -78,7 +78,7 @@
2.4 /** The config key for the filename of the logfile */
2.5 public static final String LOGFILE = "sonews.log";
2.6
2.7 - public static final String[] AVAILABLE_KEYS = {
2.8 + public static final String[] AVAILABLE_KEYS = {
2.9 ARTICLE_MAXSIZE,
2.10 EVENTLOG,
2.11 FEED_NEWSPERRUN,
3.1 --- a/org/sonews/daemon/command/ListCommand.java Mon Aug 17 11:00:51 2009 +0200
3.2 +++ b/org/sonews/daemon/command/ListCommand.java Thu Aug 20 14:31:19 2009 +0200
3.3 @@ -57,15 +57,15 @@
3.4 {
3.5 final String[] command = line.split(" ");
3.6
3.7 - if (command.length >= 2)
3.8 + if(command.length >= 2)
3.9 {
3.10 - if (command[1].equalsIgnoreCase("OVERVIEW.FMT"))
3.11 + if(command[1].equalsIgnoreCase("OVERVIEW.FMT"))
3.12 {
3.13 conn.println("215 information follows");
3.14 conn.println("Subject:\nFrom:\nDate:\nMessage-ID:\nReferences:\nBytes:\nLines:\nXref");
3.15 conn.println(".");
3.16 }
3.17 - else if (command[1].equalsIgnoreCase("NEWSGROUPS"))
3.18 + else if(command[1].equalsIgnoreCase("NEWSGROUPS"))
3.19 {
3.20 conn.println("215 information follows");
3.21 final List<Channel> list = Channel.getAll();
3.22 @@ -75,12 +75,12 @@
3.23 }
3.24 conn.println(".");
3.25 }
3.26 - else if (command[1].equalsIgnoreCase("SUBSCRIPTIONS"))
3.27 + else if(command[1].equalsIgnoreCase("SUBSCRIPTIONS"))
3.28 {
3.29 conn.println("215 information follows");
3.30 conn.println(".");
3.31 }
3.32 - else if (command[1].equalsIgnoreCase("EXTENSIONS"))
3.33 + else if(command[1].equalsIgnoreCase("EXTENSIONS"))
3.34 {
3.35 conn.println("202 Supported NNTP extensions.");
3.36 conn.println("LISTGROUP");
3.37 @@ -88,6 +88,11 @@
3.38 conn.println("XPAT");
3.39 conn.println(".");
3.40 }
3.41 + else if(command[1].equalsIgnoreCase("ACTIVE"))
3.42 + {
3.43 + // TODO: Implement wildcards for LIST ACTIVE
3.44 + printGroupInfo(conn);
3.45 + }
3.46 else
3.47 {
3.48 conn.println("500 unknown argument to LIST command");
3.49 @@ -95,26 +100,31 @@
3.50 }
3.51 else
3.52 {
3.53 - final List<Channel> groups = Channel.getAll();
3.54 - if(groups != null)
3.55 + printGroupInfo(conn);
3.56 + }
3.57 + }
3.58 +
3.59 + private void printGroupInfo(NNTPConnection conn)
3.60 + throws IOException, StorageBackendException
3.61 + {
3.62 + final List<Channel> groups = Channel.getAll();
3.63 + if (groups != null)
3.64 + {
3.65 + conn.println("215 list of newsgroups follows");
3.66 + for (Channel g : groups)
3.67 {
3.68 - conn.println("215 list of newsgroups follows");
3.69 - for (Channel g : groups)
3.70 + if (!g.isDeleted())
3.71 {
3.72 - if(!g.isDeleted())
3.73 - {
3.74 - String writeable = g.isWriteable() ? " y" : " n";
3.75 - // Indeed first the higher article number then the lower
3.76 - conn.println(g.getName() + " " + g.getLastArticleNumber() + " "
3.77 - + g.getFirstArticleNumber() + writeable);
3.78 - }
3.79 + String writeable = g.isWriteable() ? " y" : " n";
3.80 + // Indeed first the higher article number then the lower
3.81 + conn.println(g.getName() + " " + g.getLastArticleNumber() + " " + g.getFirstArticleNumber() + writeable);
3.82 }
3.83 - conn.println(".");
3.84 }
3.85 - else
3.86 - {
3.87 - conn.println("500 server database malfunction");
3.88 - }
3.89 + conn.println(".");
3.90 + }
3.91 + else
3.92 + {
3.93 + conn.println("500 server database malfunction");
3.94 }
3.95 }
3.96
4.1 --- a/org/sonews/daemon/command/PostCommand.java Mon Aug 17 11:00:51 2009 +0200
4.2 +++ b/org/sonews/daemon/command/PostCommand.java Thu Aug 20 14:31:19 2009 +0200
4.3 @@ -21,12 +21,8 @@
4.4 import java.io.IOException;
4.5 import java.io.ByteArrayInputStream;
4.6 import java.io.ByteArrayOutputStream;
4.7 -import java.nio.charset.Charset;
4.8 -import java.nio.charset.IllegalCharsetNameException;
4.9 -import java.nio.charset.UnsupportedCharsetException;
4.10 import java.sql.SQLException;
4.11 import java.util.Arrays;
4.12 -import java.util.Locale;
4.13 import javax.mail.MessagingException;
4.14 import javax.mail.internet.AddressException;
4.15 import javax.mail.internet.InternetHeaders;
4.16 @@ -303,7 +299,7 @@
4.17 boolean success = false;
4.18 String[] groupnames = article.getHeader(Headers.NEWSGROUPS)[0].split(",");
4.19 for(String groupname : groupnames)
4.20 - {
4.21 + {
4.22 Group group = StorageManager.current().getGroup(groupname);
4.23 if(group != null && !group.isDeleted())
4.24 {
4.25 @@ -311,7 +307,7 @@
4.26 {
4.27 // Send to mailing list; the Dispatcher writes
4.28 // statistics to database
4.29 - Dispatcher.toList(article);
4.30 + Dispatcher.toList(article, group.getName());
4.31 success = true;
4.32 }
4.33 else
5.1 --- a/org/sonews/mlgw/Dispatcher.java Mon Aug 17 11:00:51 2009 +0200
5.2 +++ b/org/sonews/mlgw/Dispatcher.java Thu Aug 20 14:31:19 2009 +0200
5.3 @@ -21,6 +21,8 @@
5.4 import java.io.IOException;
5.5 import java.util.ArrayList;
5.6 import java.util.List;
5.7 +import java.util.regex.Matcher;
5.8 +import java.util.regex.Pattern;
5.9 import javax.mail.Address;
5.10 import javax.mail.Authenticator;
5.11 import javax.mail.Message;
5.12 @@ -29,6 +31,7 @@
5.13 import javax.mail.internet.InternetAddress;
5.14 import org.sonews.config.Config;
5.15 import org.sonews.storage.Article;
5.16 +import org.sonews.storage.Group;
5.17 import org.sonews.storage.Headers;
5.18 import org.sonews.storage.StorageBackendException;
5.19 import org.sonews.storage.StorageManager;
5.20 @@ -36,7 +39,7 @@
5.21 import org.sonews.util.Stats;
5.22
5.23 /**
5.24 - * Dispatches messages from mailing list or newsserver or vice versa.
5.25 + * Dispatches messages from mailing list to newsserver or vice versa.
5.26 * @author Christian Lins
5.27 * @since sonews/0.5.0
5.28 */
5.29 @@ -58,86 +61,160 @@
5.30 }
5.31
5.32 }
5.33 +
5.34 + /**
5.35 + * Chunks out the email address of the full List-Post header field.
5.36 + * @param listPostValue
5.37 + * @return The matching email address or null
5.38 + */
5.39 + private static String chunkListPost(String listPostValue)
5.40 + {
5.41 + // listPostValue is of form "<mailto:dev@openoffice.org>"
5.42 + Pattern mailPattern = Pattern.compile("(\\w+[-|.])*\\w+@(\\w+.)+\\w+");
5.43 + Matcher mailMatcher = mailPattern.matcher(listPostValue);
5.44 + if(mailMatcher.find())
5.45 + {
5.46 + return listPostValue.substring(mailMatcher.start(), mailMatcher.end());
5.47 + }
5.48 + else
5.49 + {
5.50 + return null;
5.51 + }
5.52 + }
5.53 +
5.54 + /**
5.55 + * This method inspects the header of the given message, trying
5.56 + * to find the most appropriate recipient.
5.57 + * @param msg
5.58 + * @param fallback If this is false only List-Post and X-List-Post headers
5.59 + * are examined.
5.60 + * @return null or fitting group name for the given message.
5.61 + */
5.62 + private static List<String> getGroupFor(final Message msg, final boolean fallback)
5.63 + throws MessagingException, StorageBackendException
5.64 + {
5.65 + List<String> groups = null;
5.66 +
5.67 + // Is there a List-Post header?
5.68 + String[] listPost = msg.getHeader(Headers.LIST_POST);
5.69 + InternetAddress listPostAddr;
5.70 +
5.71 + if(listPost == null || listPost.length == 0 || "".equals(listPost[0]))
5.72 + {
5.73 + // Is there a X-List-Post header?
5.74 + listPost = msg.getHeader(Headers.X_LIST_POST);
5.75 + }
5.76 +
5.77 + if(listPost != null && listPost.length > 0
5.78 + && !"".equals(listPost[0]) && chunkListPost(listPost[0]) != null)
5.79 + {
5.80 + // listPost[0] is of form "<mailto:dev@openoffice.org>"
5.81 + listPost[0] = chunkListPost(listPost[0]);
5.82 + listPostAddr = new InternetAddress(listPost[0], false);
5.83 + groups = StorageManager.current().getGroupsForList(listPostAddr);
5.84 + }
5.85 + else if(fallback)
5.86 + {
5.87 + Log.msg("Using fallback recipient discovery for: " + msg.getSubject(), true);
5.88 + groups = new ArrayList<String>();
5.89 + // Fallback to TO/CC/BCC addresses
5.90 + Address[] to = msg.getAllRecipients();
5.91 + for(Address toa : to) // Address can have '<' '>' around
5.92 + {
5.93 + if(toa instanceof InternetAddress)
5.94 + {
5.95 + List<String> g = StorageManager.current().getGroupsForList((InternetAddress) toa);
5.96 + groups.addAll(g);
5.97 + }
5.98 + }
5.99 + }
5.100 +
5.101 + return groups;
5.102 + }
5.103
5.104 /**
5.105 * Posts a message that was received from a mailing list to the
5.106 * appropriate newsgroup.
5.107 + * If the message already exists in the storage, this message checks
5.108 + * if it must be posted in an additional group. This can happen for
5.109 + * crosspostings in different mailing lists.
5.110 * @param msg
5.111 */
5.112 public static boolean toGroup(final Message msg)
5.113 {
5.114 try
5.115 {
5.116 - Address[] to = msg.getAllRecipients(); // includes TO/CC/BCC
5.117 - if(to == null || to.length <= 0)
5.118 + // Create new Article object
5.119 + Article article = new Article(msg);
5.120 + boolean posted = false;
5.121 +
5.122 + // Check if this mail is already existing the storage
5.123 + boolean updateReq =
5.124 + StorageManager.current().isArticleExisting(article.getMessageID());
5.125 +
5.126 + List<String> newsgroups = getGroupFor(msg, !updateReq);
5.127 + List<String> oldgroups = new ArrayList<String>();
5.128 + if(updateReq)
5.129 {
5.130 - to = msg.getReplyTo();
5.131 + // Check for duplicate entries of the same group
5.132 + Article oldArticle = StorageManager.current().getArticle(article.getMessageID());
5.133 + List<Group> oldGroups = oldArticle.getGroups();
5.134 + for(Group oldGroup : oldGroups)
5.135 + {
5.136 + if(!newsgroups.contains(oldGroup.getName()))
5.137 + {
5.138 + oldgroups.add(oldGroup.getName());
5.139 + }
5.140 + }
5.141 }
5.142
5.143 - if(to == null || to.length <= 0)
5.144 + if(newsgroups.size() > 0)
5.145 {
5.146 - Log.msg("Skipping message because no recipient!", false);
5.147 - return false;
5.148 + newsgroups.addAll(oldgroups);
5.149 + StringBuilder groups = new StringBuilder();
5.150 + for(int n = 0; n < newsgroups.size(); n++)
5.151 + {
5.152 + groups.append(newsgroups.get(n));
5.153 + if (n + 1 != newsgroups.size())
5.154 + {
5.155 + groups.append(',');
5.156 + }
5.157 + }
5.158 + Log.msg("Posting to group " + groups.toString(), true);
5.159 +
5.160 + article.setGroup(groups.toString());
5.161 + //article.removeHeader(Headers.REPLY_TO);
5.162 + //article.removeHeader(Headers.TO);
5.163 +
5.164 + // Write article to database
5.165 + if(updateReq)
5.166 + {
5.167 + Log.msg("Updating " + article.getMessageID() + " with additional groups", true);
5.168 + StorageManager.current().delete(article.getMessageID());
5.169 + StorageManager.current().addArticle(article);
5.170 + }
5.171 + else
5.172 + {
5.173 + Log.msg("Gatewaying " + article.getMessageID() + " to "
5.174 + + article.getHeader(Headers.NEWSGROUPS)[0], true);
5.175 + StorageManager.current().addArticle(article);
5.176 + Stats.getInstance().mailGatewayed(
5.177 + article.getHeader(Headers.NEWSGROUPS)[0]);
5.178 + }
5.179 + posted = true;
5.180 }
5.181 else
5.182 {
5.183 - boolean posted = false;
5.184 - List<String> newsgroups = new ArrayList<String>();
5.185 -
5.186 - for (Address toa : to) // Address can have '<' '>' around
5.187 + StringBuilder buf = new StringBuilder();
5.188 + for (Address toa : msg.getAllRecipients())
5.189 {
5.190 - if (toa instanceof InternetAddress)
5.191 - {
5.192 - List<String> groups = StorageManager.current()
5.193 - .getGroupsForList((InternetAddress)toa);
5.194 - newsgroups.addAll(groups);
5.195 - }
5.196 + buf.append(' ');
5.197 + buf.append(toa.toString());
5.198 }
5.199 -
5.200 - if (newsgroups.size() > 0)
5.201 - {
5.202 - StringBuilder groups = new StringBuilder();
5.203 - for(int n = 0; n < newsgroups.size(); n++)
5.204 - {
5.205 - groups.append(newsgroups.get(n));
5.206 - if(n + 1 != newsgroups.size())
5.207 - {
5.208 - groups.append(',');
5.209 - }
5.210 - }
5.211 - Log.msg("Posting to group " + groups.toString(), true);
5.212 -
5.213 - // Create new Article object
5.214 - Article article = new Article(msg);
5.215 - article.setGroup(groups.toString());
5.216 - article.removeHeader(Headers.REPLY_TO);
5.217 - article.removeHeader(Headers.TO);
5.218 -
5.219 - // Write article to database
5.220 - if(!StorageManager.current().isArticleExisting(article.getMessageID()))
5.221 - {
5.222 - StorageManager.current().addArticle(article);
5.223 - Stats.getInstance().mailGatewayed(
5.224 - article.getHeader(Headers.NEWSGROUPS)[0]);
5.225 - }
5.226 - else
5.227 - {
5.228 - Log.msg("Article " + article.getMessageID() + " already existing.", true);
5.229 - }
5.230 - posted = true;
5.231 - }
5.232 - else
5.233 - {
5.234 - StringBuilder buf = new StringBuilder();
5.235 - for(Address toa : to)
5.236 - {
5.237 - buf.append(' ');
5.238 - buf.append(toa.toString());
5.239 - }
5.240 - Log.msg("No group for" + buf.toString(), false);
5.241 - }
5.242 - return posted;
5.243 + buf.append(" " + article.getHeader(Headers.LIST_POST)[0]);
5.244 + Log.msg("No group for" + buf.toString(), false);
5.245 }
5.246 + return posted;
5.247 }
5.248 catch(Exception ex)
5.249 {
5.250 @@ -148,56 +225,53 @@
5.251
5.252 /**
5.253 * Mails a message received through NNTP to the appropriate mailing list.
5.254 + * This method MAY be called several times by PostCommand for the same
5.255 + * article.
5.256 */
5.257 - public static void toList(Article article)
5.258 + public static void toList(Article article, String group)
5.259 throws IOException, MessagingException, StorageBackendException
5.260 {
5.261 // Get mailing lists for the group of this article
5.262 - List<String> listAddresses = new ArrayList<String>();
5.263 - String[] groupnames = article.getHeader(Headers.NEWSGROUPS)[0].split(",");
5.264 -
5.265 - for(String groupname : groupnames)
5.266 + List<String> rcptAddresses = StorageManager.current().getListsForGroup(group);
5.267 +
5.268 + if(rcptAddresses == null || rcptAddresses.size() == 0)
5.269 {
5.270 - String listAddress = StorageManager.current().getListForGroup(groupname);
5.271 - if(listAddress != null)
5.272 - {
5.273 - listAddresses.add(listAddress);
5.274 - }
5.275 + Log.msg("No ML-address for " + group + " found.", false);
5.276 + return;
5.277 }
5.278
5.279 - for(String listAddress : listAddresses)
5.280 + for(String rcptAddress : rcptAddresses)
5.281 {
5.282 // Compose message and send it via given SMTP-Host
5.283 String smtpHost = Config.inst().get(Config.MLSEND_HOST, "localhost");
5.284 - int smtpPort = Config.inst().get(Config.MLSEND_PORT, 25);
5.285 + int smtpPort = Config.inst().get(Config.MLSEND_PORT, 25);
5.286 String smtpUser = Config.inst().get(Config.MLSEND_USER, "user");
5.287 - String smtpPw = Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
5.288 + String smtpPw = Config.inst().get(Config.MLSEND_PASSWORD, "mysecret");
5.289 String smtpFrom = Config.inst().get(
5.290 - Config.MLSEND_ADDRESS, article.getHeader(Headers.FROM)[0]);
5.291 + Config.MLSEND_ADDRESS, article.getHeader(Headers.FROM)[0]);
5.292
5.293 // TODO: Make Article cloneable()
5.294 - String group = article.getHeader(Headers.NEWSGROUPS)[0];
5.295 article.getMessageID(); // Make sure an ID is existing
5.296 article.removeHeader(Headers.NEWSGROUPS);
5.297 article.removeHeader(Headers.PATH);
5.298 article.removeHeader(Headers.LINES);
5.299 article.removeHeader(Headers.BYTES);
5.300
5.301 - article.setHeader("To", listAddress);
5.302 - article.setHeader("Reply-To", listAddress);
5.303 + article.setHeader("To", rcptAddress);
5.304 + //article.setHeader("Reply-To", listAddress);
5.305
5.306 - if(Config.inst().get(Config.MLSEND_RW_SENDER, false))
5.307 + if (Config.inst().get(Config.MLSEND_RW_SENDER, false))
5.308 {
5.309 rewriteSenderAddress(article); // Set the SENDER address
5.310 }
5.311
5.312 SMTPTransport smtpTransport = new SMTPTransport(smtpHost, smtpPort);
5.313 - smtpTransport.send(article, smtpFrom, listAddress);
5.314 + smtpTransport.send(article, smtpFrom, rcptAddress);
5.315 smtpTransport.close();
5.316
5.317 Stats.getInstance().mailGatewayed(group);
5.318 - Log.msg("MLGateway: Mail " + article.getHeader("Subject")[0]
5.319 - + " was delivered to " + listAddress + ".", true);
5.320 + Log.msg("MLGateway: Mail " + article.getHeader("Subject")[0]
5.321 + + " was delivered to " + rcptAddress + ".", true);
5.322 }
5.323 }
5.324
6.1 --- a/org/sonews/mlgw/SMTPTransport.java Mon Aug 17 11:00:51 2009 +0200
6.2 +++ b/org/sonews/mlgw/SMTPTransport.java Thu Aug 20 14:31:19 2009 +0200
6.3 @@ -84,6 +84,10 @@
6.4 public void send(Article article, String mailFrom, String rcptTo)
6.5 throws IOException
6.6 {
6.7 + assert(article != null);
6.8 + assert(mailFrom != null);
6.9 + assert(rcptTo != null);
6.10 +
6.11 this.out.println("MAIL FROM: " + mailFrom);
6.12 this.out.flush();
6.13 String line = this.in.readLine();
7.1 --- a/org/sonews/storage/Article.java Mon Aug 17 11:00:51 2009 +0200
7.2 +++ b/org/sonews/storage/Article.java Thu Aug 20 14:31:19 2009 +0200
7.3 @@ -119,7 +119,7 @@
7.4 final Object content = msg.getContent();
7.5 if(content instanceof String)
7.6 {
7.7 - this.body = ((String)content).getBytes();
7.8 + this.body = ((String)content).getBytes(getBodyCharset());
7.9 }
7.10 else if(content instanceof Multipart) // probably subclass MimeMultipart
7.11 {
8.1 --- a/org/sonews/storage/Headers.java Mon Aug 17 11:00:51 2009 +0200
8.2 +++ b/org/sonews/storage/Headers.java Thu Aug 20 14:31:19 2009 +0200
8.3 @@ -33,6 +33,7 @@
8.4 public static final String DATE = "date";
8.5 public static final String FROM = "from";
8.6 public static final String LINES = "lines";
8.7 + public static final String LIST_POST = "list-post";
8.8 public static final String MESSAGE_ID = "message-id";
8.9 public static final String NEWSGROUPS = "newsgroups";
8.10 public static final String NNTP_POSTING_DATE = "nntp-posting-date";
8.11 @@ -45,6 +46,7 @@
8.12 public static final String SUPERSEDES = "subersedes";
8.13 public static final String TO = "to";
8.14 public static final String X_COMPLAINTS_TO = "x-complaints-to";
8.15 + public static final String X_LIST_POST = "x-list-post";
8.16 public static final String X_TRACE = "x-trace";
8.17 public static final String XREF = "xref";
8.18
9.1 --- a/org/sonews/storage/Storage.java Mon Aug 17 11:00:51 2009 +0200
9.2 +++ b/org/sonews/storage/Storage.java Thu Aug 20 14:31:19 2009 +0200
9.3 @@ -31,6 +31,11 @@
9.4 public interface Storage
9.5 {
9.6
9.7 + /**
9.8 + * Stores the given Article in the storage.
9.9 + * @param art
9.10 + * @throws StorageBackendException
9.11 + */
9.12 void addArticle(Article art)
9.13 throws StorageBackendException;
9.14
9.15 @@ -93,7 +98,14 @@
9.16 int getLastArticleNumber(Group group)
9.17 throws StorageBackendException;
9.18
9.19 - String getListForGroup(String groupname)
9.20 + /**
9.21 + * Returns a list of email addresses that are related to the given
9.22 + * groupname. In most cases the list may contain only one entry.
9.23 + * @param groupname
9.24 + * @return
9.25 + * @throws StorageBackendException
9.26 + */
9.27 + List<String> getListsForGroup(String groupname)
9.28 throws StorageBackendException;
9.29
9.30 String getOldestArticle()
10.1 --- a/org/sonews/storage/StorageBackendException.java Mon Aug 17 11:00:51 2009 +0200
10.2 +++ b/org/sonews/storage/StorageBackendException.java Thu Aug 20 14:31:19 2009 +0200
10.3 @@ -31,4 +31,9 @@
10.4 super(cause);
10.5 }
10.6
10.7 + public StorageBackendException(String msg)
10.8 + {
10.9 + super(msg);
10.10 + }
10.11 +
10.12 }
11.1 --- a/org/sonews/storage/impl/JDBCDatabase.java Mon Aug 17 11:00:51 2009 +0200
11.2 +++ b/org/sonews/storage/impl/JDBCDatabase.java Thu Aug 20 14:31:19 2009 +0200
11.3 @@ -1142,28 +1142,27 @@
11.4 }
11.5
11.6 @Override
11.7 - public String getListForGroup(String group)
11.8 + public List<String> getListsForGroup(String group)
11.9 throws StorageBackendException
11.10 {
11.11 - ResultSet rs = null;
11.12 + ResultSet rs = null;
11.13 + List<String> lists = new ArrayList<String>();
11.14
11.15 try
11.16 {
11.17 this.pstmtGetListForGroup.setString(1, group);
11.18 rs = this.pstmtGetListForGroup.executeQuery();
11.19 - if (rs.next())
11.20 +
11.21 + while(rs.next())
11.22 {
11.23 - return rs.getString(1);
11.24 + lists.add(rs.getString(1));
11.25 }
11.26 - else
11.27 - {
11.28 - return null;
11.29 - }
11.30 + return lists;
11.31 }
11.32 catch(SQLException ex)
11.33 {
11.34 restartConnection(ex);
11.35 - return getListForGroup(group);
11.36 + return getListsForGroup(group);
11.37 }
11.38 finally
11.39 {
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/test/unit/MLGWTests.java Thu Aug 20 14:31:19 2009 +0200
12.3 @@ -0,0 +1,38 @@
12.4 +/*
12.5 + * SONEWS News Server
12.6 + * see AUTHORS for the list of contributors
12.7 + *
12.8 + * This program is free software: you can redistribute it and/or modify
12.9 + * it under the terms of the GNU General Public License as published by
12.10 + * the Free Software Foundation, either version 3 of the License, or
12.11 + * (at your option) any later version.
12.12 + *
12.13 + * This program is distributed in the hope that it will be useful,
12.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12.16 + * GNU General Public License for more details.
12.17 + *
12.18 + * You should have received a copy of the GNU General Public License
12.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
12.20 + */
12.21 +
12.22 +package test.unit;
12.23 +
12.24 +import junit.textui.TestRunner;
12.25 +import test.util.mlgw.DispatcherTest;
12.26 +
12.27 +/**
12.28 + * Unit tests for package org.sonews.mlgw.
12.29 + * @author Christian Lins
12.30 + * @since sonews/1.0.3
12.31 + */
12.32 +public class MLGWTests
12.33 +{
12.34 +
12.35 + public static void main(String[] args)
12.36 + {
12.37 + System.out.println("DispatcherTest");
12.38 + TestRunner.run(DispatcherTest.class);
12.39 + }
12.40 +
12.41 +}
13.1 --- a/test/unit/util/ResourceTest.java Mon Aug 17 11:00:51 2009 +0200
13.2 +++ b/test/unit/util/ResourceTest.java Thu Aug 20 14:31:19 2009 +0200
13.3 @@ -41,7 +41,7 @@
13.4 assertNull(url);
13.5
13.6 // This file should exist
13.7 - url = Resource.getAsURL("org/sonews/daemon/Main.class");
13.8 + url = Resource.getAsURL("org/sonews/Main.class");
13.9 assertNotNull(url);
13.10 }
13.11
13.12 @@ -55,7 +55,7 @@
13.13 stream = Resource.getAsStream("this is bullshit");
13.14 assertNull(stream);
13.15
13.16 - stream = Resource.getAsStream("org/sonews/daemon/Main.class");
13.17 + stream = Resource.getAsStream("org/sonews/Main.class");
13.18 assertNotNull(stream);
13.19 }
13.20
13.21 @@ -69,10 +69,10 @@
13.22 str = Resource.getAsString("this is bullshit", true);
13.23 assertNull(str);
13.24
13.25 - str = Resource.getAsString("org/sonews/daemon/Main.class", true);
13.26 + str = Resource.getAsString("org/sonews/Main.class", true);
13.27 assertNotNull(str);
13.28
13.29 - str = Resource.getAsString("org/sonews/daemon/Main.class", false);
13.30 + str = Resource.getAsString("org/sonews/Main.class", false);
13.31 assertNotNull(str);
13.32 assertEquals(str.indexOf("\n"), -1);
13.33 }
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/test/util/mlgw/DispatcherTest.java Thu Aug 20 14:31:19 2009 +0200
14.3 @@ -0,0 +1,71 @@
14.4 +/*
14.5 + * SONEWS News Server
14.6 + * see AUTHORS for the list of contributors
14.7 + *
14.8 + * This program is free software: you can redistribute it and/or modify
14.9 + * it under the terms of the GNU General Public License as published by
14.10 + * the Free Software Foundation, either version 3 of the License, or
14.11 + * (at your option) any later version.
14.12 + *
14.13 + * This program is distributed in the hope that it will be useful,
14.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.16 + * GNU General Public License for more details.
14.17 + *
14.18 + * You should have received a copy of the GNU General Public License
14.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
14.20 + */
14.21 +
14.22 +package test.util.mlgw;
14.23 +
14.24 +import java.lang.reflect.InvocationTargetException;
14.25 +import java.lang.reflect.Method;
14.26 +import junit.framework.TestCase;
14.27 +import org.sonews.mlgw.Dispatcher;
14.28 +
14.29 +/**
14.30 + * Tests the methods of class org.sonews.mlgw.Dispatcher.
14.31 + * @author Christian Lins
14.32 + * @since sonews/1.0.3
14.33 + */
14.34 +public class DispatcherTest extends TestCase
14.35 +{
14.36 +
14.37 + public DispatcherTest()
14.38 + {
14.39 + super("DispatcherTest");
14.40 + }
14.41 +
14.42 + public void testChunkListPost()
14.43 + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
14.44 + {
14.45 + Dispatcher disp = new Dispatcher();
14.46 +
14.47 + Class clazz = disp.getClass();
14.48 + Method methChunkListPost = clazz.getDeclaredMethod("chunkListPost", String.class);
14.49 + methChunkListPost.setAccessible(true);
14.50 +
14.51 + try
14.52 + {
14.53 + // disp.chunkListPost(null)
14.54 + methChunkListPost.invoke(disp, null);
14.55 + fail("Should have raised an IllegalArgumentException");
14.56 + }
14.57 + catch(IllegalArgumentException ex){}
14.58 +
14.59 + // disp.chunkListPost("")
14.60 + Object obj = methChunkListPost.invoke(disp, "");
14.61 + assertNull(obj);
14.62 +
14.63 + // disp.chunkListPost("listPostValue is of form <mailto:dev@openoffice.org>")
14.64 + obj = methChunkListPost.invoke(disp, "listPostValue is of form <mailto:dev@openoffice.org>");
14.65 + assertNotNull(obj);
14.66 + assertEquals("dev@openoffice.org", (String)obj);
14.67 +
14.68 + // disp.chunkListPost("<mailto:frisbee-users@fun.rec.uk.sun.com")
14.69 + obj = methChunkListPost.invoke(disp, "<mailto:frisbee-users@fun.rec.uk.sun.com");
14.70 + assertNotNull(obj);
14.71 + assertEquals("frisbee-users@fun.rec.uk.sun.com", (String)obj);
14.72 + }
14.73 +
14.74 +}