1 31 package org.blojsom.plugin.pingback; 32 33 import org.apache.commons.logging.Log; 34 import org.apache.commons.logging.LogFactory; 35 import org.apache.commons.mail.Email; 36 import org.apache.commons.mail.EmailException; 37 import org.apache.commons.mail.HtmlEmail; 38 import org.apache.xmlrpc.AsyncCallback; 39 import org.apache.xmlrpc.XmlRpcClient; 40 import org.blojsom.blog.Blog; 41 import org.blojsom.blog.Entry; 42 import org.blojsom.blog.User; 43 import org.blojsom.event.Event; 44 import org.blojsom.event.EventBroadcaster; 45 import org.blojsom.event.Listener; 46 import org.blojsom.plugin.Plugin; 47 import org.blojsom.plugin.PluginException; 48 import org.blojsom.plugin.admin.event.EntryAddedEvent; 49 import org.blojsom.plugin.admin.event.EntryEvent; 50 import org.blojsom.plugin.admin.event.EntryUpdatedEvent; 51 import org.blojsom.plugin.email.EmailConstants; 52 import org.blojsom.plugin.pingback.event.PingbackAddedEvent; 53 import org.blojsom.plugin.velocity.StandaloneVelocityPlugin; 54 import org.blojsom.util.BlojsomConstants; 55 import org.blojsom.util.BlojsomUtils; 56 import org.blojsom.fetcher.FetcherException; 57 import org.blojsom.fetcher.Fetcher; 58 59 import javax.mail.Session ; 60 import javax.naming.Context ; 61 import javax.naming.InitialContext ; 62 import javax.naming.NamingException ; 63 import javax.servlet.http.HttpServletRequest ; 64 import javax.servlet.http.HttpServletResponse ; 65 import java.io.BufferedReader ; 66 import java.io.IOException ; 67 import java.io.InputStreamReader ; 68 import java.net.HttpURLConnection ; 69 import java.net.MalformedURLException ; 70 import java.net.URL ; 71 import java.util.Date ; 72 import java.util.HashMap ; 73 import java.util.Map ; 74 import java.util.Vector ; 75 import java.util.regex.Matcher ; 76 import java.util.regex.Pattern ; 77 78 86 public class PingbackPlugin extends StandaloneVelocityPlugin implements Plugin, Listener { 87 88 private static Log _logger = LogFactory.getLog(PingbackPlugin.class); 89 90 private static final String PINGBACK_PLUGIN_EMAIL_TEMPLATE_HTML = "org/blojsom/plugin/pingback/pingback-plugin-email-template-html.vm"; 91 private static final String PINGBACK_PLUGIN_EMAIL_TEMPLATE_TEXT = "org/blojsom/plugin/pingback/pingback-plugin-email-template-text.vm"; 92 93 private static final String DEFAULT_PINGBACK_PREFIX = "[blojsom] Pingback on: "; 94 public static final String PINGBACK_PREFIX_IP = "plugin-pingback-email-prefix"; 95 private static final String BLOJSOM_PINGBACK_PLUGIN_BLOG_ENTRY = "BLOJSOM_PINGBACK_PLUGIN_BLOG_ENTRY"; 96 private static final String BLOJSOM_PINGBACK_PLUGIN_PINGBACK = "BLOJSOM_PINGBACK_PLUGIN_PINGBACK"; 97 98 private static final String PINGBACK_METHOD = "pingback.ping"; 99 private static final String X_PINGBACK_HEADER = "X-Pingback"; 100 private static final String PINGBACK_LINK_REGEX = "<link rel=\"pingback\" HREF=\"([^\"]+)\" ?/?>"; 101 private static final String HREF_REGEX = "href\\s*=\\s*\"(.*?)\""; 102 103 106 public static final String BLOJSOM_PINGBACK_PLUGIN_METADATA_IP = "BLOJSOM_PINGBACK_PLUGIN_METADATA_IP"; 107 108 public static final String PINGBACK_MODERATION_ENABLED = "pingback-moderation-enabled"; 110 111 public static final String BLOJSOM_PINGBACK_PLUGIN_APPROVED = "BLOJSOM_PINGBACK_PLUGIN_APPROVED"; 112 public static final String BLOJSOM_PLUGIN_PINGBACK_METADATA_DESTROY = "BLOJSOM_PLUGIN_PINGBACK_METADATA_DESTROY"; 113 public static final String PINGBACK_PLUGIN_METADATA_SEND_PINGBACKS = "send-pingbacks"; 114 115 private String _mailServer; 116 private String _mailServerUsername; 117 private String _mailServerPassword; 118 private Session _session; 119 private EventBroadcaster _eventBroadcaster; 120 private Fetcher _fetcher; 121 122 private PingbackPluginAsyncCallback _callbackHandler; 123 124 127 public PingbackPlugin() { 128 } 129 130 135 public void setEventBroadcaster(EventBroadcaster eventBroadcaster) { 136 _eventBroadcaster = eventBroadcaster; 137 } 138 139 144 public void setFetcher(Fetcher fetcher) { 145 _fetcher = fetcher; 146 } 147 148 153 public void init() throws PluginException { 154 super.init(); 155 156 _callbackHandler = new PingbackPluginAsyncCallback(); 157 158 _mailServer = _servletConfig.getInitParameter(EmailConstants.SMTPSERVER_IP); 159 160 if (_mailServer != null) { 161 if (_mailServer.startsWith("java:comp/env")) { 162 try { 163 Context context = new InitialContext (); 164 _session = (Session ) context.lookup(_mailServer); 165 } catch (NamingException e) { 166 _logger.error(e); 167 throw new PluginException(e); 168 } 169 } else { 170 _mailServerUsername = _servletConfig.getInitParameter(EmailConstants.SMTPSERVER_USERNAME_IP); 171 _mailServerPassword = _servletConfig.getInitParameter(EmailConstants.SMTPSERVER_PASSWORD_IP); 172 } 173 } else { 174 throw new PluginException("Missing SMTP servername servlet initialization parameter: " + EmailConstants.SMTPSERVER_IP); 175 } 176 177 _eventBroadcaster.addListener(this); 178 179 _logger.debug("Initialized pingback plugin"); 180 } 181 182 193 public Entry[] process(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Blog blog, Map context, Entry[] entries) throws PluginException { 194 return entries; 195 } 196 197 203 public void cleanup() throws PluginException { 204 } 205 206 212 public void destroy() throws PluginException { 213 } 214 215 223 protected void setupEmail(Blog blog, Entry entry, Email email) throws EmailException { 224 email.setCharset(BlojsomConstants.UTF8); 225 226 if (_session != null) { 228 email.setMailSession(_session); 229 } else { 230 if (!BlojsomUtils.checkNullOrBlank(_mailServerUsername) && !BlojsomUtils.checkNullOrBlank(_mailServerPassword)) { 232 email.setHostName(_mailServer); 233 email.setAuthentication(_mailServerUsername, _mailServerPassword); 234 } else { 235 email.setHostName(_mailServer); 236 } 237 } 238 239 email.setFrom(blog.getBlogOwnerEmail(), "Blojsom Pingback"); 240 241 String author = entry.getAuthor(); 242 if (BlojsomUtils.checkNullOrBlank(author)) { 243 author = blog.getBlogOwner(); 244 } 245 246 String authorEmail = blog.getBlogOwnerEmail(); 247 248 if (author != null) { 249 try { 250 User user = _fetcher.loadUser(blog, author); 251 252 if (user == null) { 253 authorEmail = blog.getBlogOwnerEmail(); 254 } else { 255 authorEmail = user.getUserEmail(); 256 if (BlojsomUtils.checkNullOrBlank(authorEmail)) { 257 authorEmail = blog.getBlogOwnerEmail(); 258 } 259 } 260 } catch (FetcherException e) { 261 } 262 } 263 264 email.addTo(authorEmail, author); 265 email.setSentDate(new Date ()); 266 } 267 268 273 public void handleEvent(Event event) { 274 if (event instanceof EntryAddedEvent || event instanceof EntryUpdatedEvent) { 275 EntryEvent entryEvent = (EntryEvent) event; 276 277 String text = entryEvent.getEntry().getDescription(); 278 if (!BlojsomUtils.checkNullOrBlank(text) && BlojsomUtils.checkMapForKey(entryEvent.getEntry().getMetaData(), PINGBACK_PLUGIN_METADATA_SEND_PINGBACKS)) 279 { 280 String pingbackURL; 281 StringBuffer sourceURI = new StringBuffer ().append(entryEvent.getBlog().getBlogURL()).append(entryEvent.getEntry().getBlogCategory().getName()).append(entryEvent.getEntry().getPostSlug()); 282 String targetURI; 283 284 Pattern hrefPattern = Pattern.compile(HREF_REGEX, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.UNICODE_CASE | Pattern.DOTALL); 285 Matcher hrefMatcher = hrefPattern.matcher(text); 286 if (_logger.isDebugEnabled()) { 287 _logger.debug("Checking for href's in entry: " + entryEvent.getEntry().getId()); 288 } 289 while (hrefMatcher.find()) { 290 targetURI = hrefMatcher.group(1); 291 if (_logger.isDebugEnabled()) { 292 _logger.debug("Found potential targetURI: " + targetURI); 293 } 294 295 try { 297 HttpURLConnection urlConnection = (HttpURLConnection ) new URL (targetURI).openConnection(); 298 urlConnection.setRequestMethod("GET"); 299 urlConnection.connect(); 300 pingbackURL = urlConnection.getHeaderField(X_PINGBACK_HEADER); 301 302 if (pingbackURL == null) { 304 BufferedReader bufferedReader = new BufferedReader (new InputStreamReader (urlConnection.getInputStream(), BlojsomConstants.UTF8)); 305 StringBuffer content = new StringBuffer (); 306 String input; 307 while ((input = bufferedReader.readLine()) != null) { 308 content.append(input).append(BlojsomConstants.LINE_SEPARATOR); 309 } 310 bufferedReader.close(); 311 312 Pattern pingbackLinkPattern = Pattern.compile(PINGBACK_LINK_REGEX, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.UNICODE_CASE | Pattern.DOTALL); 313 Matcher pingbackLinkMatcher = pingbackLinkPattern.matcher(content.toString()); 314 if (pingbackLinkMatcher.find()) { 315 pingbackURL = pingbackLinkMatcher.group(1); 316 } 317 } 318 319 if (pingbackURL != null && targetURI != null) { 321 Vector parameters = new Vector (); 322 parameters.add(sourceURI.toString()); 323 parameters.add(targetURI); 324 try { 325 if (_logger.isDebugEnabled()) { 326 _logger.debug("Sending pingback to: " + pingbackURL + " sourceURI: " + sourceURI + " targetURI: " + targetURI); 327 } 328 329 XmlRpcClient xmlRpcClient = new XmlRpcClient(pingbackURL); 330 xmlRpcClient.executeAsync(PINGBACK_METHOD, parameters, _callbackHandler); 331 } catch (MalformedURLException e) { 332 if (_logger.isErrorEnabled()) { 333 _logger.error(e); 334 } 335 } 336 } 337 } catch (IOException e) { 338 if (_logger.isErrorEnabled()) { 339 _logger.error(e); 340 } 341 } 342 } 343 } else { 344 if (_logger.isDebugEnabled()) { 345 _logger.debug("No text in blog entry or " + PINGBACK_PLUGIN_METADATA_SEND_PINGBACKS + " not enabled."); 346 } 347 } 348 } else if (event instanceof PingbackAddedEvent) { 349 HtmlEmail email = new HtmlEmail(); 350 PingbackAddedEvent pingbackAddedEvent = (PingbackAddedEvent) event; 351 352 if (pingbackAddedEvent.getBlog().getBlogEmailEnabled().booleanValue()) { 353 try { 354 setupEmail(pingbackAddedEvent.getBlog(), pingbackAddedEvent.getEntry(), email); 355 356 Map emailTemplateContext = new HashMap (); 357 emailTemplateContext.put(BlojsomConstants.BLOJSOM_BLOG, pingbackAddedEvent.getBlog()); 358 emailTemplateContext.put(BLOJSOM_PINGBACK_PLUGIN_PINGBACK, pingbackAddedEvent.getPingback()); 359 emailTemplateContext.put(BLOJSOM_PINGBACK_PLUGIN_BLOG_ENTRY, pingbackAddedEvent.getEntry()); 360 361 String htmlText = mergeTemplate(PINGBACK_PLUGIN_EMAIL_TEMPLATE_HTML, pingbackAddedEvent.getBlog(), emailTemplateContext); 362 String plainText = mergeTemplate(PINGBACK_PLUGIN_EMAIL_TEMPLATE_TEXT, pingbackAddedEvent.getBlog(), emailTemplateContext); 363 364 email.setHtmlMsg(htmlText); 365 email.setTextMsg(plainText); 366 367 String emailPrefix = (String ) pingbackAddedEvent.getBlog().getProperties().get(PINGBACK_PREFIX_IP); 368 if (BlojsomUtils.checkNullOrBlank(emailPrefix)) { 369 emailPrefix = DEFAULT_PINGBACK_PREFIX; 370 } 371 372 email = (HtmlEmail) email.setSubject(emailPrefix + pingbackAddedEvent.getEntry().getTitle()); 373 374 email.send(); 375 } catch (EmailException e) { 376 if (_logger.isErrorEnabled()) { 377 _logger.error(e); 378 } 379 } 380 } 381 } 382 } 383 384 389 public void processEvent(Event event) { 390 } 391 392 395 private class PingbackPluginAsyncCallback implements AsyncCallback { 396 397 400 public PingbackPluginAsyncCallback() { 401 } 402 403 410 public void handleResult(Object o, URL url, String s) { 411 if (_logger.isDebugEnabled()) { 412 _logger.debug(o.toString()); 413 } 414 } 415 416 423 public void handleError(Exception e, URL url, String s) { 424 if (_logger.isErrorEnabled()) { 425 _logger.error(e); 426 } 427 } 428 } 429 } | Popular Tags |