1.1 --- a/src/org/sonews/storage/impl/DrupalDatabase.java Tue Oct 11 16:34:17 2011 +0200
1.2 +++ b/src/org/sonews/storage/impl/DrupalDatabase.java Wed Oct 12 00:11:25 2011 +0200
1.3 @@ -17,29 +17,26 @@
1.4 */
1.5 package org.sonews.storage.impl;
1.6
1.7 -import java.io.UnsupportedEncodingException;
1.8 import java.sql.Connection;
1.9 import java.sql.DriverManager;
1.10 import java.sql.PreparedStatement;
1.11 import java.sql.ResultSet;
1.12 -import java.sql.SQLException;
1.13 import java.sql.Statement;
1.14 import java.text.SimpleDateFormat;
1.15 import java.util.ArrayList;
1.16 import java.util.Collections;
1.17 -import java.util.Date;
1.18 import java.util.List;
1.19 import java.util.Locale;
1.20 import java.util.logging.Level;
1.21 import java.util.logging.Logger;
1.22 -import javax.mail.internet.MailDateFormat;
1.23 -import javax.mail.internet.MimeUtility;
1.24 -import org.apache.commons.codec.net.BCodec;
1.25 +import javax.mail.Message;
1.26 import org.apache.commons.codec.net.QuotedPrintableCodec;
1.27 import org.sonews.config.Config;
1.28 import org.sonews.feed.Subscription;
1.29 import org.sonews.storage.Article;
1.30 import org.sonews.storage.ArticleHead;
1.31 +import org.sonews.storage.DrupalArticle;
1.32 +import org.sonews.storage.DrupalMessage;
1.33 import org.sonews.storage.Group;
1.34 import org.sonews.storage.Storage;
1.35 import org.sonews.storage.StorageBackendException;
1.36 @@ -54,14 +51,11 @@
1.37 private static final Logger log = Logger.getLogger(DrupalDatabase.class.getName());
1.38 public static final String CHARSET = "UTF-8";
1.39 public static final String CRLF = "\r\n";
1.40 - public static final int MAX_RESTARTS = 2;
1.41 - /** How many times the database connection was reinitialized */
1.42 - protected int restarts = 0;
1.43 protected Connection conn = null;
1.44 private QuotedPrintableCodec qpc = new QuotedPrintableCodec(CHARSET);
1.45 private SimpleDateFormat RFC822_DATE = new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US);
1.46 // TODO: správná doména
1.47 - private String myDomain = "kinderporno.cz";
1.48 + private String myDomain = "nntp.i1984.cz";
1.49
1.50 public DrupalDatabase() throws StorageBackendException {
1.51 connectDatabase();
1.52 @@ -137,73 +131,12 @@
1.53 return null;
1.54 } else {
1.55 return Long.parseLong(localPart[1]);
1.56 + // If needed:
1.57 + // parseGroupName() will be same as this method, just with:
1.58 + // return localPart[2];
1.59 }
1.60 }
1.61
1.62 - private static String parseGroupName(String messageID) {
1.63 - String[] localPart = parseMessageID(messageID);
1.64 - if (localPart == null) {
1.65 - return null;
1.66 - } else {
1.67 - return localPart[2];
1.68 - }
1.69 - }
1.70 -
1.71 - private static String constructMessageId(int articleID, int groupID, String groupName, String domainName) {
1.72 - StringBuilder sb = new StringBuilder();
1.73 - sb.append("<");
1.74 - sb.append(articleID);
1.75 - sb.append("-");
1.76 - sb.append(groupID);
1.77 - sb.append("-");
1.78 - sb.append(groupName);
1.79 - sb.append("@");
1.80 - sb.append(domainName);
1.81 - sb.append(">");
1.82 - return sb.toString();
1.83 - }
1.84 -
1.85 - /**
1.86 - *
1.87 - * @param sb header list to be appended with new header. List must be terminated by line end.
1.88 - * @param key header name (without : and space)
1.89 - * @param value header value
1.90 - * @param encode true if value should be encoded/escaped before appending
1.91 - * @throws UnsupportedEncodingException
1.92 - */
1.93 - private static void addHeader(StringBuilder sb, String key, String value, boolean encode) throws UnsupportedEncodingException {
1.94 - sb.append(key);
1.95 - sb.append(": ");
1.96 - if (encode) {
1.97 - sb.append(MimeUtility.encodeWord(value));
1.98 - } else {
1.99 - sb.append(value);
1.100 - }
1.101 - sb.append(CRLF);
1.102 - }
1.103 -
1.104 - private String constructHeaders(ResultSet rs) throws SQLException, UnsupportedEncodingException {
1.105 - StringBuilder sb = new StringBuilder();
1.106 -
1.107 - addHeader(sb, "Message-id", constructMessageId(rs.getInt("id"), rs.getInt("group_id"), rs.getString("group_name"), myDomain), false);
1.108 - addHeader(sb, "From", MimeUtility.encodeWord(rs.getString("sender_name")) + " <>", false);
1.109 - addHeader(sb, "Subject", rs.getString("subject"), true);
1.110 - /** TODO: správný formát data: */
1.111 - addHeader(sb, "Date", RFC822_DATE.format(new Date(rs.getLong("created"))), false);
1.112 - addHeader(sb, "Content-Type", "text/html; charset=" + CHARSET, false);
1.113 - addHeader(sb, "Content-Transfer-Encoding", "quoted-printable", false);
1.114 - //addHeader(sb, "Content-Transfer-Encoding", "base64", false);
1.115 -
1.116 - Integer parentID = rs.getInt("parent_id");
1.117 - if (parentID != null && parentID > 0) {
1.118 - String parentMessageID = constructMessageId(parentID, rs.getInt("group_id"), rs.getString("group_name"), myDomain);
1.119 - addHeader(sb, "In-Reply-To", parentMessageID, false);
1.120 - addHeader(sb, "References", parentMessageID, false);
1.121 - }
1.122 -
1.123 - return sb.toString();
1.124 - }
1.125 -
1.126 @Override
1.127 public List<Group> getGroups() throws StorageBackendException {
1.128 PreparedStatement ps = null;
1.129 @@ -275,13 +208,8 @@
1.130 rs = ps.executeQuery();
1.131
1.132 if (rs.next()) {
1.133 - String headers = constructHeaders(rs);
1.134 - // TODO: fold?
1.135 - BCodec bc = new BCodec(CHARSET);
1.136 - byte[] body = qpc.encode(rs.getString("text")).getBytes();
1.137 - //byte[] body = bc.encode(rs.getString("text")).getBytes();
1.138 -
1.139 - return new Article(headers, body);
1.140 + DrupalMessage m = new DrupalMessage(rs, myDomain, true);
1.141 + return new DrupalArticle(m);
1.142 } else {
1.143 return null;
1.144 }
1.145 @@ -297,7 +225,6 @@
1.146 PreparedStatement ps = null;
1.147 ResultSet rs = null;
1.148 try {
1.149 - // TODO: je nutné řazení?
1.150 ps = conn.prepareStatement("SELECT * FROM nntp_article WHERE group_id = ? AND id >= ? AND id <= ? ORDER BY id");
1.151 ps.setLong(1, group.getInternalID());
1.152 ps.setLong(2, first);
1.153 @@ -307,7 +234,8 @@
1.154 List<Pair<Long, ArticleHead>> heads = new ArrayList<Pair<Long, ArticleHead>>();
1.155
1.156 while (rs.next()) {
1.157 - String headers = constructHeaders(rs);
1.158 + DrupalMessage m = new DrupalMessage(rs, myDomain, false);
1.159 + String headers = m.getHeaders();
1.160 heads.add(new Pair<Long, ArticleHead>(rs.getLong("id"), new ArticleHead(headers)));
1.161 }
1.162
1.163 @@ -320,13 +248,6 @@
1.164 }
1.165
1.166 @Override
1.167 - public List<Pair<Long, String>> getArticleHeaders(Group group, long start, long end, String header, String pattern) throws StorageBackendException {
1.168 - log.log(Level.SEVERE, "TODO: getArticleHeaders {0} / {1} / {2} / {3} / {4}", new Object[]{group, start, end, header, pattern});
1.169 - /** TODO: */
1.170 - return Collections.emptyList();
1.171 - }
1.172 -
1.173 - @Override
1.174 public long getArticleIndex(Article article, Group group) throws StorageBackendException {
1.175 Long id = parseArticleID(article.getMessageID());
1.176 if (id == null) {
1.177 @@ -416,24 +337,6 @@
1.178 }
1.179 }
1.180
1.181 - //
1.182 - // --- zatím neimplementovat ---
1.183 - //
1.184 - @Override
1.185 - public void addArticle(Article art) throws StorageBackendException {
1.186 - log.log(Level.SEVERE, "TODO: addArticle {0}", new Object[]{art});
1.187 - }
1.188 -
1.189 - @Override
1.190 - public void addEvent(long timestamp, int type, long groupID) throws StorageBackendException {
1.191 - log.log(Level.SEVERE, "TODO: addEvent {0} / {1} / {2}", new Object[]{timestamp, type, groupID});
1.192 - }
1.193 -
1.194 - @Override
1.195 - public void addGroup(String groupname, int flags) throws StorageBackendException {
1.196 - log.log(Level.SEVERE, "TODO: addGroup {0} / {1}", new Object[]{groupname, flags});
1.197 - }
1.198 -
1.199 @Override
1.200 public int countArticles() throws StorageBackendException {
1.201 PreparedStatement ps = null;
1.202 @@ -467,6 +370,45 @@
1.203 }
1.204
1.205 @Override
1.206 + public int getPostingsCount(String groupname) throws StorageBackendException {
1.207 + PreparedStatement ps = null;
1.208 + ResultSet rs = null;
1.209 + try {
1.210 + ps = conn.prepareStatement("SELECT count(*) FROM nntp_article WHERE group_name = ?");
1.211 + ps.setString(1, groupname);
1.212 + rs = ps.executeQuery();
1.213 + rs.next();
1.214 + return rs.getInt(1);
1.215 + } catch (Exception e) {
1.216 + throw new StorageBackendException(e);
1.217 + } finally {
1.218 + close(null, ps, rs);
1.219 + }
1.220 + }
1.221 +
1.222 + @Override
1.223 + public List<Pair<Long, String>> getArticleHeaders(Group group, long start, long end, String header, String pattern) throws StorageBackendException {
1.224 + log.log(Level.SEVERE, "TODO: getArticleHeaders {0} / {1} / {2} / {3} / {4}", new Object[]{group, start, end, header, pattern});
1.225 + /** TODO: */
1.226 + return Collections.emptyList();
1.227 + }
1.228 +
1.229 + @Override
1.230 + public void addArticle(Article art) throws StorageBackendException {
1.231 + log.log(Level.SEVERE, "TODO: addArticle {0}", new Object[]{art});
1.232 + }
1.233 +
1.234 + @Override
1.235 + public void addEvent(long timestamp, int type, long groupID) throws StorageBackendException {
1.236 + log.log(Level.SEVERE, "TODO: addEvent {0} / {1} / {2}", new Object[]{timestamp, type, groupID});
1.237 + }
1.238 +
1.239 + @Override
1.240 + public void addGroup(String groupname, int flags) throws StorageBackendException {
1.241 + log.log(Level.SEVERE, "TODO: addGroup {0} / {1}", new Object[]{groupname, flags});
1.242 + }
1.243 +
1.244 + @Override
1.245 public void delete(String messageID) throws StorageBackendException {
1.246 log.log(Level.SEVERE, "TODO: delete {0}", new Object[]{messageID});
1.247 }
1.248 @@ -478,6 +420,11 @@
1.249 }
1.250
1.251 @Override
1.252 + public void setConfigValue(String key, String value) throws StorageBackendException {
1.253 + log.log(Level.SEVERE, "TODO: setConfigValue {0} = {1}", new Object[]{key, value});
1.254 + }
1.255 +
1.256 + @Override
1.257 public int getEventsCount(int eventType, long startTimestamp, long endTimestamp, Group group) throws StorageBackendException {
1.258 log.log(Level.SEVERE, "TODO: getEventsCount {0} / {1} / {2} / {3}", new Object[]{eventType, startTimestamp, endTimestamp, group});
1.259 return 0;
1.260 @@ -508,23 +455,6 @@
1.261 }
1.262
1.263 @Override
1.264 - public int getPostingsCount(String groupname) throws StorageBackendException {
1.265 - PreparedStatement ps = null;
1.266 - ResultSet rs = null;
1.267 - try {
1.268 - ps = conn.prepareStatement("SELECT count(*) FROM nntp_article WHERE group_name = ?");
1.269 - ps.setString(1, groupname);
1.270 - rs = ps.executeQuery();
1.271 - rs.next();
1.272 - return rs.getInt(1);
1.273 - } catch (Exception e) {
1.274 - throw new StorageBackendException(e);
1.275 - } finally {
1.276 - close(null, ps, rs);
1.277 - }
1.278 - }
1.279 -
1.280 - @Override
1.281 public List<Subscription> getSubscriptions(int type) throws StorageBackendException {
1.282 log.log(Level.SEVERE, "TODO: getSubscriptions {0}", new Object[]{type});
1.283 return Collections.emptyList();
1.284 @@ -536,11 +466,6 @@
1.285 }
1.286
1.287 @Override
1.288 - public void setConfigValue(String key, String value) throws StorageBackendException {
1.289 - log.log(Level.SEVERE, "TODO: setConfigValue {0} = {1}", new Object[]{key, value});
1.290 - }
1.291 -
1.292 - @Override
1.293 public boolean update(Article article) throws StorageBackendException {
1.294 log.log(Level.SEVERE, "TODO: update {0}", new Object[]{article});
1.295 throw new StorageBackendException("Not implemented yet.");