svnno****@sourc*****
svnno****@sourc*****
2009年 10月 4日 (日) 15:20:37 JST
Revision: 3695 http://sourceforge.jp/projects/jiemamy/svn/view?view=rev&revision=3695 Author: shin1 Date: 2009-10-04 15:20:37 +0900 (Sun, 04 Oct 2009) Log Message: ----------- Bitlyのユーティリティを復活させた。 ついでにログレベルを全体的に下げた。 Modified Paths: -------------- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/RunInTransaction.java sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Fetch.java sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Tweet.java sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/page/AppengineBaseWebPage.java sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/service/GetEntries.java Added Paths: ----------- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/util/BitlyUtil.java Modified: sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/RunInTransaction.java =================================================================== --- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/RunInTransaction.java 2009-10-04 03:10:32 UTC (rev 3694) +++ sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/RunInTransaction.java 2009-10-04 06:20:37 UTC (rev 3695) @@ -25,7 +25,7 @@ for (int i = 0; i < retryCount; i++) { Transaction transaction = service.beginTransaction(); if (i == 0) { - LOGGER.log(Level.INFO, String.format("start runInTransaction(%s): run=%s:%s", + LOGGER.log(Level.FINE, String.format("start runInTransaction(%s): run=%s:%s", transaction.getId(), inTransaction.getClass().getName(), Integer .toHexString(inTransaction.hashCode()))); } else { @@ -72,9 +72,11 @@ transaction.rollback(); } inTransaction.onException(service, e); - LOGGER.log(Level.WARNING, String.format("failure to runInTransaction(%s): run=%s:%s", - transaction.getId(), inTransaction.getClass().getName(), Integer - .toHexString(inTransaction.hashCode())), e); + if (e instanceof DatastoreTimeoutException == false) { + LOGGER.log(Level.WARNING, String.format("failure to runInTransaction(%s): run=%s:%s", + transaction.getId(), inTransaction.getClass().getName(), Integer + .toHexString(inTransaction.hashCode())), e); + } } public static void run(InTransaction inTransaction) { @@ -161,4 +163,4 @@ } static final Logger LOGGER = Logger.getLogger(RunInTransaction.class.getName()); -} +} \ No newline at end of file Modified: sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Fetch.java =================================================================== --- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Fetch.java 2009-10-04 03:10:32 UTC (rev 3694) +++ sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Fetch.java 2009-10-04 06:20:37 UTC (rev 3695) @@ -28,12 +28,12 @@ public Fetch(PageParameters parameters) { String name = parameters.getString("name"); - LOGGER.log(Level.INFO, name + "のFetchを開始。"); + LOGGER.log(Level.FINE, name + "のFetchを開始。"); Query query = new Query(FeedUrl.kind()).addFilter("name", FilterOperator.EQUAL, name); Entity entity = DatastoreServiceFactory.getDatastoreService().prepare(query) .asSingleEntity(); String url = (String) entity.getProperty("url"); - LOGGER.log(Level.INFO, "url=" + url); + LOGGER.log(Level.FINE, "url=" + url); try { List<SyndEntry> entries = service.service(url); RunInTransaction.run(new SaveFetchHistory(entity.getKey(), entries)); Modified: sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Tweet.java =================================================================== --- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Tweet.java 2009-10-04 03:10:32 UTC (rev 3694) +++ sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/cron/Tweet.java 2009-10-04 06:20:37 UTC (rev 3695) @@ -1,9 +1,12 @@ package com.shin1ogawa.cron; import java.util.Calendar; +import java.util.Date; import java.util.List; import java.util.logging.Level; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.ToStringBuilder; import org.wicketstuff.annotation.mount.MountPath; import twitter4j.Status; @@ -21,6 +24,8 @@ import com.shin1ogawa.entity.Entry; import com.shin1ogawa.page.AppengineBaseWebPage; import com.shin1ogawa.util.ApplicationSettingUtil; +import com.shin1ogawa.util.BitlyUtil; +import com.shin1ogawa.util.BitlyUtil.BitlyVO; @MountPath(path = "/cron/tweet") public class Tweet extends AppengineBaseWebPage { @@ -30,34 +35,54 @@ query.addFilter(Entry.tweeted.name(), FilterOperator.EQUAL, false); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.HOUR_OF_DAY, -3); - query.addFilter(Entry.published.name(), - FilterOperator.GREATER_THAN_OR_EQUAL, calendar.getTime()); + query.addFilter(Entry.published.name(), FilterOperator.GREATER_THAN_OR_EQUAL, calendar + .getTime()); query.addSort(Entry.published.name(), SortDirection.ASCENDING); int limitSizeForTweet = Integer.valueOf((String) ApplicationSettingUtil .getSettingValue("limitSizeForTweet")); - DatastoreService service = DatastoreServiceFactory - .getDatastoreService(); + DatastoreService service = DatastoreServiceFactory.getDatastoreService(); List<Entity> entries = service.prepare(query).asList( FetchOptions.Builder.withLimit(limitSizeForTweet)); - LOGGER.log(Level.INFO, "クエリの実行が完了。size=" + entries.size()); - String user = (String) ApplicationSettingUtil - .getSettingValue("twitter-user"); - String password = (String) ApplicationSettingUtil - .getSettingValue("twitter-password"); + LOGGER.log(Level.FINE, "クエリの実行が完了。size=" + entries.size()); + String user = (String) ApplicationSettingUtil.getSettingValue("twitter-user"); + String password = (String) ApplicationSettingUtil.getSettingValue("twitter-password"); Twitter twitter = new Twitter(user, password); - LOGGER.log(Level.INFO, "Twitterの認証完了。"); + LOGGER.log(Level.FINE, "Twitterの認証完了。"); int failureCount = 0; int successCount = 0; + long now = Calendar.getInstance().getTimeInMillis(); for (Entity entry : entries) { + Object published = entry.getProperty(Entry.published.name()); + if (published != null && published instanceof Date) { + long subtract = now - ((Date) published).getTime(); + subtract = subtract / 1000 /* 秒 *// 60 /* 分 */; + if (subtract > 180) { + // 180分以上昔のEntryはPostしない + LOGGER.log(Level.INFO, "180分以上昔のEntryなのでPostしません。" + + ToStringBuilder.reflectionToString(entry)); + continue; + } + } StringBuilder b = new StringBuilder(); - Object title = entry.getProperty("title"); - b.append(title).append(" ").append(entry.getProperty("link")); + Object title = entry.getProperty(Entry.title.name()); + String link = (String) entry.getProperty(Entry.link.name()); + try { + BitlyVO vo = BitlyUtil.shorten(link); + if (vo.statusCode.equals("OK") && StringUtils.isNotEmpty(vo.shortUrl)) { + link = vo.shortUrl; + } else { + LOGGER.log(Level.INFO, "BitlyVO=" + vo); + } + } catch (Exception e) { + LOGGER.log(Level.WARNING, "bitlyの実行に失敗しました。", e); + } + LOGGER.log(Level.INFO, "bitly=" + link + ", original=" + entry.getProperty(Entry.link.name())); + b.append(title).append(" ").append(link); LOGGER.log(Level.FINE, "Post の準備を開始。 title=" + title); try { Status status = twitter.updateStatus(b.toString()); successCount++; - LOGGER.log(Level.FINE, "Post が終了。 title=" + title + ", status=" - + status); + LOGGER.log(Level.FINE, "Post が終了。 title=" + title + ", status=" + status); } catch (Exception e) { LOGGER.log(Level.WARNING, "Post に失敗. title=" + title, e); failureCount++; @@ -67,7 +92,7 @@ RunInTransaction.run(new SaveInTransaction(entry)); LOGGER.log(Level.FINE, "Datastoreの更新が終了。 title=" + title); } - LOGGER.log(Level.INFO, "Twitterの認証完了。Postに成功した件数=" + successCount - + " Postに失敗した件数=" + failureCount); + LOGGER.log(Level.FINE, "Twitterの認証完了。Postに成功した件数=" + successCount + " Postに失敗した件数=" + + failureCount); } -} +} \ No newline at end of file Modified: sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/page/AppengineBaseWebPage.java =================================================================== --- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/page/AppengineBaseWebPage.java 2009-10-04 03:10:32 UTC (rev 3694) +++ sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/page/AppengineBaseWebPage.java 2009-10-04 06:20:37 UTC (rev 3695) @@ -16,7 +16,7 @@ public AppengineBaseWebPage() { setVersioned(false); - LOGGER.log(Level.INFO, getLogPrefix() + "constructor"); + LOGGER.log(Level.FINE, getLogPrefix() + "constructor"); } @Override @@ -25,7 +25,7 @@ if (Application.get().getConfigurationType() == Application.DEVELOPMENT) { testSerialize(); } - LOGGER.log(Level.INFO, getLogPrefix() + "session.size=" + getSession().getSizeInBytes()); + LOGGER.log(Level.FINE, getLogPrefix() + "session.size=" + getSession().getSizeInBytes()); } private String getLogPrefix() { Modified: sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/service/GetEntries.java =================================================================== --- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/service/GetEntries.java 2009-10-04 03:10:32 UTC (rev 3694) +++ sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/service/GetEntries.java 2009-10-04 06:20:37 UTC (rev 3695) @@ -24,14 +24,14 @@ MalformedURLException, FeedException, IOException { SyndFeedInput input = new SyndFeedInput(); - LOGGER.info("openConnection() start. url=" + urlString); + LOGGER.fine("openConnection() start. url=" + urlString); InputStream inputStream = new URL(urlString).openConnection().getInputStream(); - LOGGER.info("openConnection() end. url=" + urlString); - LOGGER.info("fetch start. url=" + urlString); + LOGGER.fine("openConnection() end. url=" + urlString); + LOGGER.fine("fetch start. url=" + urlString); SyndFeed feed = input.build(new InputSource(inputStream)); @SuppressWarnings("unchecked") List<SyndEntry> entries = (List<SyndEntry>) feed.getEntries(); - LOGGER.info("fetch end. url=" + urlString); + LOGGER.fine("fetch end. url=" + urlString); return entries; } } Added: sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/util/BitlyUtil.java =================================================================== --- sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/util/BitlyUtil.java (rev 0) +++ sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/util/BitlyUtil.java 2009-10-04 06:20:37 UTC (rev 3695) @@ -0,0 +1,84 @@ +package com.shin1ogawa.util; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.logging.Logger; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import com.google.appengine.api.urlfetch.HTTPResponse; +import com.google.appengine.api.urlfetch.URLFetchService; +import com.google.appengine.api.urlfetch.URLFetchServiceFactory; + +public class BitlyUtil { + + static final Logger LOGGER = Logger.getLogger(BitlyUtil.class.getSimpleName()); + + static final String FORMAT = "http://api.bit.ly/shorten?version=2.0.1&login=%s&apiKey=%s&longUrl=%s&format=xml"; + + static final String DEFAULT_LOGIN = "shin1ogawa"; + + static final String DEFAULT_APIKEY = "R_5b082ea6affad0e4c7ed56e031d72549"; + + private BitlyUtil() { + } + + public static BitlyVO shorten(String longUrl) throws MalformedURLException, IOException, + XPathExpressionException, ParserConfigurationException, SAXException { + URLFetchService service = URLFetchServiceFactory.getURLFetchService(); + HTTPResponse response = service.fetch(new URL(String.format(FORMAT, DEFAULT_LOGIN, + DEFAULT_APIKEY, longUrl))); + if (response.getResponseCode() != HttpURLConnection.HTTP_OK) { + throw new RuntimeException(longUrl + " response code=" + response.getResponseCode()); + } + return parse(response); + } + + private static BitlyVO parse(HTTPResponse response) throws ParserConfigurationException, + SAXException, IOException, XPathExpressionException { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document document = builder.parse(new ByteArrayInputStream(response.getContent())); + + XPath xPath = XPathFactory.newInstance().newXPath(); + XPathExpression statusCodeExpression = xPath.compile("//bitly/statusCode"); + XPathExpression errorCodeExpression = xPath.compile("//bitly/errorCode"); + XPathExpression errorMessageExpression = xPath.compile("//bitly/errorMessage"); + XPathExpression shortenUrlExpression = xPath.compile("//bitly/results/nodeKeyVal/shortUrl"); + + return new BitlyVO(statusCodeExpression.evaluate(document), errorCodeExpression + .evaluate(document), errorMessageExpression.evaluate(document), + shortenUrlExpression.evaluate(document)); + } + + public static class BitlyVO { + public final String statusCode; + public final String errorCode; + public final String errorMessage; + public final String shortUrl; + + private BitlyVO(String statusCode, String errorCode, String errorMessage, String shortUrl) { + this.statusCode = statusCode; + this.errorCode = errorCode; + this.errorMessage = errorMessage; + this.shortUrl = shortUrl; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } + } +} \ No newline at end of file Property changes on: sandbox/jiemamy-feeds/src/main/java/com/shin1ogawa/util/BitlyUtil.java ___________________________________________________________________ Added: svn:mime-type + text/plain