001: /**
002: * Copyright (c) 2003-2007, David A. Czarnecki
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * Redistributions of source code must retain the above copyright notice, this list of conditions and the
009: * following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
011: * following disclaimer in the documentation and/or other materials provided with the distribution.
012: * Neither the name of "David A. Czarnecki" and "blojsom" nor the names of its contributors may be used to
013: * endorse or promote products derived from this software without specific prior written permission.
014: * Products derived from this software may not be called "blojsom", nor may "blojsom" appear in their name,
015: * without prior written permission of David A. Czarnecki.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
018: * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
019: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
021: * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
022: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
025: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
029: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030: */package org.blojsom.plugin.syndication;
031:
032: import com.sun.syndication.feed.synd.SyndCategory;
033: import com.sun.syndication.feed.synd.SyndEntry;
034: import com.sun.syndication.feed.synd.SyndFeed;
035: import com.sun.syndication.feed.module.content.ContentModuleImpl;
036: import com.sun.syndication.feed.module.content.ContentModule;
037: import com.sun.syndication.io.FeedException;
038: import com.sun.syndication.io.SyndFeedInput;
039: import com.sun.syndication.io.XmlReader;
040: import org.apache.commons.logging.Log;
041: import org.apache.commons.logging.LogFactory;
042: import org.blojsom.blog.*;
043: import org.blojsom.fetcher.Fetcher;
044: import org.blojsom.fetcher.FetcherException;
045: import org.blojsom.plugin.PluginException;
046: import org.blojsom.plugin.technorati.TechnoratiTagsPlugin;
047: import org.blojsom.plugin.syndication.module.*;
048: import org.blojsom.plugin.admin.WebAdminPlugin;
049: import org.blojsom.util.BlojsomConstants;
050: import org.blojsom.util.BlojsomMetaDataConstants;
051: import org.blojsom.util.BlojsomUtils;
052:
053: import javax.servlet.http.HttpServletRequest;
054: import javax.servlet.http.HttpServletResponse;
055: import java.io.IOException;
056: import java.net.URL;
057: import java.util.List;
058: import java.util.Map;
059:
060: /**
061: * Feed import plugin
062: *
063: * @author David Czarnecki
064: * @version $Id: FeedImportPlugin.java,v 1.9 2007/01/17 02:35:06 czarneckid Exp $
065: * @since blojsom 3.0
066: */
067: public class FeedImportPlugin extends WebAdminPlugin {
068:
069: private Log _logger = LogFactory.getLog(FeedImportPlugin.class);
070:
071: // Localization constants
072: private static final String FAILED_FEED_IMPORT_PERMISSION_KEY = "failed.feed.import.permission.text";
073: private static final String FAILED_FEED_IMPORT_ERROR_KEY = "failed.feed.import.error.text";
074: private static final String FAILED_FEED_IMPORT_IO_KEY = "failed.feed.import.io.text";
075:
076: // Pages
077: private static final String FEED_IMPORT_PAGE = "/org/blojsom/plugin/syndication/templates/feed-import";
078:
079: // Permissions
080: private static final String FEED_IMPORT_PERMISSION = "feed_import_permission";
081:
082: // Form items
083: private static final String IMPORT_URL = "import-url";
084:
085: // Actions
086: private static final String FEED_IMPORT_ACTION = "feed-import";
087:
088: private Fetcher _fetcher;
089:
090: /**
091: * Construct a new instance of the Feed import plugin
092: */
093: public FeedImportPlugin() {
094: }
095:
096: /**
097: * Return the display name for the plugin
098: *
099: * @return Display name for the plugin
100: */
101: public String getDisplayName() {
102: return "Feed Import plugin";
103: }
104:
105: /**
106: * Return the name of the initial editing page for the plugin
107: *
108: * @return Name of the initial editing page for the plugin
109: */
110: public String getInitialPage() {
111: return FEED_IMPORT_PAGE;
112: }
113:
114: /**
115: * Set the {@link Fetcher}
116: *
117: * @param fetcher {@link Fetcher}
118: */
119: public void setFetcher(Fetcher fetcher) {
120: _fetcher = fetcher;
121: }
122:
123: /**
124: * Process the blog entries
125: *
126: * @param httpServletRequest Request
127: * @param httpServletResponse Response
128: * @param blog {@link Blog} instance
129: * @param context Context
130: * @param entries Blog entries retrieved for the particular request
131: * @return Modified set of blog entries
132: * @throws PluginException If there is an error processing the blog entries
133: */
134: public Entry[] process(HttpServletRequest httpServletRequest,
135: HttpServletResponse httpServletResponse, Blog blog,
136: Map context, Entry[] entries) throws PluginException {
137: entries = super .process(httpServletRequest,
138: httpServletResponse, blog, context, entries);
139:
140: String page = BlojsomUtils.getRequestValue(
141: BlojsomConstants.PAGE_PARAM, httpServletRequest);
142: String action = BlojsomUtils.getRequestValue(ACTION_PARAM,
143: httpServletRequest);
144:
145: String username = getUsernameFromSession(httpServletRequest,
146: blog);
147: if (!checkPermission(blog, null, username,
148: FEED_IMPORT_PERMISSION)) {
149: httpServletRequest.setAttribute(
150: BlojsomConstants.PAGE_PARAM,
151: ADMIN_ADMINISTRATION_PAGE);
152: addOperationResultMessage(context, getAdminResource(
153: FAILED_FEED_IMPORT_PERMISSION_KEY,
154: FAILED_FEED_IMPORT_PERMISSION_KEY, blog
155: .getBlogAdministrationLocale()));
156:
157: return entries;
158: }
159:
160: if (ADMIN_LOGIN_PAGE.equals(page)) {
161: return entries;
162: } else if (FEED_IMPORT_ACTION.equals(action)) {
163: if (_logger.isDebugEnabled()) {
164: _logger.debug("User requested feed import action");
165: }
166:
167: String importLocation = BlojsomUtils.getRequestValue(
168: IMPORT_URL, httpServletRequest);
169: if (!BlojsomUtils.checkNullOrBlank(importLocation)) {
170: try {
171: URL importURL = new URL(importLocation);
172: SyndFeedInput input = new SyndFeedInput();
173: SyndFeed feed = input
174: .build(new XmlReader(importURL));
175: SyndEntry entry;
176:
177: List feedEntries = feed.getEntries();
178:
179: StringBuffer statusMessage = new StringBuffer();
180:
181: if (feedEntries.size() > 0) {
182: statusMessage.append("<p>");
183:
184: for (int i = 0; i < feedEntries.size(); i++) {
185: entry = (SyndEntry) feedEntries.get(i);
186:
187: List entryCategories = entry
188: .getCategories();
189:
190: Category category;
191: category = _fetcher.newCategory();
192: String categoryName = "/";
193: if (entryCategories.size() > 0) {
194: categoryName = ((SyndCategory) entryCategories
195: .get(0)).getName();
196: categoryName = categoryName.replaceAll(
197: "[+]", " ");
198: if (categoryName != null) {
199: if (!categoryName.startsWith("/")) {
200: categoryName = "/"
201: + categoryName;
202: }
203:
204: if (!categoryName.endsWith("/")) {
205: categoryName += "/";
206: }
207: }
208: }
209:
210: try {
211: category = _fetcher.loadCategory(blog,
212: categoryName);
213: if (category == null) {
214: category = _fetcher.newCategory();
215: category.setBlogId(blog.getId());
216: category.setName(categoryName);
217: category
218: .setDescription(categoryName
219: .replaceAll("/",
220: " "));
221: }
222: } catch (FetcherException e) {
223: if (_logger.isErrorEnabled()) {
224: _logger.error(e);
225: }
226:
227: category.setBlogId(blog.getId());
228: category.setName(categoryName);
229: }
230:
231: try {
232: _fetcher.saveCategory(blog, category);
233: _fetcher.loadCategory(blog, category);
234: } catch (FetcherException e) {
235: _logger.error(e);
236: statusMessage.append(e.getMessage())
237: .append("<br />");
238: }
239:
240: Entry newEntry;
241: newEntry = _fetcher.newEntry();
242:
243: newEntry.setBlogId(blog.getId());
244: newEntry.setTitle(entry.getTitle());
245: newEntry
246: .setBlogCategoryId(category.getId());
247: newEntry.setBlogCategory(category);
248: newEntry.setDescription(entry
249: .getDescription().getValue());
250: newEntry.setDate(entry.getPublishedDate());
251: newEntry.setModifiedDate(entry
252: .getUpdatedDate());
253: newEntry
254: .setStatus(BlojsomMetaDataConstants.PUBLISHED_STATUS);
255:
256: BlojsomImplementation blojsomImplementation = (BlojsomImplementation) entry
257: .getModule(Blojsom.BLOJSOM_URI);
258: if (blojsomImplementation != null) {
259: if (blojsomImplementation.getAuthor() != null) {
260: newEntry
261: .setAuthor(blojsomImplementation
262: .getAuthor());
263: }
264:
265: if (blojsomImplementation
266: .getTechnoratiTags() != null) {
267: Map metadata = newEntry
268: .getMetaData();
269: metadata
270: .put(
271: TechnoratiTagsPlugin.METADATA_TECHNORATI_TAGS,
272: blojsomImplementation
273: .getTechnoratiTags());
274: newEntry.setMetaData(metadata);
275: }
276:
277: if (blojsomImplementation.getPostSlug() != null) {
278: newEntry
279: .setPostSlug(blojsomImplementation
280: .getPostSlug());
281: }
282:
283: // Handle responses
284: if (blojsomImplementation
285: .getAllowsComments()) {
286: newEntry
287: .setAllowComments(new Integer(
288: 1));
289: } else {
290: newEntry
291: .setAllowComments(new Integer(
292: 0));
293: }
294:
295: if (blojsomImplementation
296: .getAllowsTrackbacks()) {
297: newEntry
298: .setAllowTrackbacks(new Integer(
299: 1));
300: } else {
301: newEntry
302: .setAllowTrackbacks(new Integer(
303: 0));
304: }
305:
306: if (blojsomImplementation
307: .getAllowsPingbacks()) {
308: newEntry
309: .setAllowPingbacks(new Integer(
310: 1));
311: } else {
312: newEntry
313: .setAllowPingbacks(new Integer(
314: 0));
315: }
316:
317: if (blojsomImplementation.getMetadata() != null
318: && blojsomImplementation
319: .getMetadata().size() > 0) {
320: Map metadataForEntry = newEntry
321: .getMetaData();
322: List metadataItems = blojsomImplementation
323: .getMetadata();
324: for (int j = 0; j < metadataItems
325: .size(); j++) {
326: Metadata metadata = (Metadata) metadataItems
327: .get(j);
328:
329: if (metadata.getKey() != null) {
330: metadataForEntry
331: .put(
332: metadata
333: .getKey(),
334: metadata
335: .getValue());
336: }
337: }
338:
339: newEntry
340: .setMetaData(metadataForEntry);
341: }
342: }
343:
344: ContentModuleImpl contentModule = (ContentModuleImpl) entry
345: .getModule(ContentModule.URI);
346: if (contentModule != null) {
347: List encodeds = contentModule
348: .getEncodeds();
349: if (encodeds != null
350: && encodeds.size() > 0) {
351: newEntry.setDescription("");
352:
353: StringBuffer description = new StringBuffer();
354: for (int j = 0; j < encodeds.size(); j++) {
355: String encodedContent = (String) encodeds
356: .get(j);
357: description
358: .append(encodedContent)
359: .append(
360: BlojsomConstants.LINE_SEPARATOR);
361: }
362:
363: newEntry.setDescription(description
364: .toString());
365: }
366: }
367:
368: try {
369: _fetcher.saveEntry(blog, newEntry);
370: _fetcher.loadEntry(blog, newEntry);
371:
372: if (blojsomImplementation != null) {
373: if (blojsomImplementation
374: .getComments() != null
375: && blojsomImplementation
376: .getComments()
377: .size() > 0) {
378: List comments = blojsomImplementation
379: .getComments();
380: for (int j = 0; j < comments
381: .size(); j++) {
382: SimpleComment simpleComment = (SimpleComment) comments
383: .get(j);
384: Comment comment = _fetcher
385: .newComment();
386:
387: comment
388: .setAuthor(simpleComment
389: .getAuthor());
390: comment
391: .setAuthorEmail(simpleComment
392: .getAuthorEmail());
393: comment
394: .setAuthorURL(simpleComment
395: .getAuthorURL());
396: comment
397: .setComment(simpleComment
398: .getComment());
399: comment
400: .setCommentDate(simpleComment
401: .getCommentDate());
402: comment.setIp(simpleComment
403: .getIp());
404: comment
405: .setStatus(simpleComment
406: .getStatus());
407: comment.setBlogId(blog
408: .getId());
409: comment
410: .setBlogEntryId(newEntry
411: .getId());
412:
413: if (simpleComment
414: .getMetadata() != null
415: && simpleComment
416: .getMetadata()
417: .size() > 0) {
418: Map metadataForComment = comment
419: .getMetaData();
420: List metadataItems = simpleComment
421: .getMetadata();
422: for (int k = 0; k < metadataItems
423: .size(); k++) {
424: Metadata metadata = (Metadata) metadataItems
425: .get(k);
426:
427: if (metadata
428: .getKey() != null) {
429: metadataForComment
430: .put(
431: metadata
432: .getKey(),
433: metadata
434: .getValue());
435: }
436: }
437:
438: comment
439: .setMetaData(metadataForComment);
440: }
441:
442: _fetcher.saveComment(blog,
443: comment);
444: }
445: }
446:
447: if (blojsomImplementation
448: .getTrackbacks() != null
449: && blojsomImplementation
450: .getTrackbacks()
451: .size() > 0) {
452: List trackbacks = blojsomImplementation
453: .getTrackbacks();
454: for (int j = 0; j < trackbacks
455: .size(); j++) {
456: SimpleTrackback simpleTrackback = (SimpleTrackback) trackbacks
457: .get(j);
458: Trackback trackback = _fetcher
459: .newTrackback();
460:
461: trackback
462: .setBlogName(simpleTrackback
463: .getBlogName());
464: trackback
465: .setExcerpt(simpleTrackback
466: .getExcerpt());
467: trackback
468: .setUrl(simpleTrackback
469: .getUrl());
470: trackback
471: .setTitle(simpleTrackback
472: .getTitle());
473: trackback
474: .setIp(simpleTrackback
475: .getIp());
476: trackback
477: .setTrackbackDate(simpleTrackback
478: .getTrackbackDate());
479: trackback
480: .setStatus(simpleTrackback
481: .getStatus());
482: trackback
483: .setBlogEntryId(newEntry
484: .getId());
485: trackback.setBlogId(blog
486: .getId());
487:
488: if (simpleTrackback
489: .getMetadata() != null
490: && simpleTrackback
491: .getMetadata()
492: .size() > 0) {
493: Map metadataForTrackback = trackback
494: .getMetaData();
495: List metadataItems = simpleTrackback
496: .getMetadata();
497: for (int k = 0; k < metadataItems
498: .size(); k++) {
499: Metadata metadata = (Metadata) metadataItems
500: .get(k);
501:
502: if (metadata
503: .getKey() != null) {
504: metadataForTrackback
505: .put(
506: metadata
507: .getKey(),
508: metadata
509: .getValue());
510: }
511: }
512:
513: trackback
514: .setMetaData(metadataForTrackback);
515: }
516:
517: _fetcher.saveTrackback(
518: blog, trackback);
519: }
520: }
521:
522: if (blojsomImplementation
523: .getPingbacks() != null
524: && blojsomImplementation
525: .getPingbacks()
526: .size() > 0) {
527: List pingbacks = blojsomImplementation
528: .getPingbacks();
529: for (int j = 0; j < pingbacks
530: .size(); j++) {
531: SimplePingback simplePingback = (SimplePingback) pingbacks
532: .get(j);
533: Pingback pingback = _fetcher
534: .newPingback();
535:
536: pingback
537: .setBlogName(simplePingback
538: .getBlogName());
539: pingback
540: .setExcerpt(simplePingback
541: .getExcerpt());
542: pingback
543: .setUrl(simplePingback
544: .getUrl());
545: pingback
546: .setTitle(simplePingback
547: .getTitle());
548: pingback
549: .setIp(simplePingback
550: .getIp());
551: pingback
552: .setTrackbackDate(simplePingback
553: .getPingbackDate());
554: pingback
555: .setStatus(simplePingback
556: .getStatus());
557: pingback
558: .setSourceURI(simplePingback
559: .getSourceURI());
560: pingback
561: .setTargetURI(simplePingback
562: .getTargetURI());
563: pingback
564: .setBlogEntryId(newEntry
565: .getId());
566: pingback.setBlogId(blog
567: .getId());
568:
569: if (simplePingback
570: .getMetadata() != null
571: && simplePingback
572: .getMetadata()
573: .size() > 0) {
574: Map metadataForPingback = pingback
575: .getMetaData();
576: List metadataItems = simplePingback
577: .getMetadata();
578: for (int k = 0; k < metadataItems
579: .size(); k++) {
580: Metadata metadata = (Metadata) metadataItems
581: .get(k);
582:
583: if (metadata
584: .getKey() != null) {
585: metadataForPingback
586: .put(
587: metadata
588: .getKey(),
589: metadata
590: .getValue());
591: }
592: }
593:
594: pingback
595: .setMetaData(metadataForPingback);
596: }
597:
598: _fetcher.savePingback(blog,
599: pingback);
600: }
601: }
602: }
603: } catch (FetcherException e) {
604: _logger.error(e);
605: statusMessage.append(e.getMessage())
606: .append("<br />");
607: }
608: }
609:
610: statusMessage.append(("</p>"));
611: }
612:
613: String status = "Successfully imported "
614: + feedEntries.size() + " entries";
615: if (statusMessage.length() > 0) {
616: status += "<br /> " + statusMessage.toString();
617: }
618:
619: addOperationResultMessage(context, status);
620: } catch (FeedException e) {
621: if (_logger.isErrorEnabled()) {
622: _logger.error(e);
623: }
624:
625: addOperationResultMessage(context,
626: formatAdminResource(
627: FAILED_FEED_IMPORT_ERROR_KEY,
628: FAILED_FEED_IMPORT_ERROR_KEY,
629: blog.getBlogAdministrationLocale(),
630: new Object[] { e.getMessage() }));
631: } catch (IOException e) {
632: if (_logger.isErrorEnabled()) {
633: _logger.error(e);
634: }
635:
636: addOperationResultMessage(context,
637: formatAdminResource(
638: FAILED_FEED_IMPORT_IO_KEY,
639: FAILED_FEED_IMPORT_IO_KEY,
640: blog.getBlogAdministrationLocale(),
641: new Object[] { e.getMessage() }));
642: } catch (RuntimeException e) {
643: }
644: }
645: }
646:
647: httpServletRequest.setAttribute(BlojsomConstants.PAGE_PARAM,
648: FEED_IMPORT_PAGE);
649:
650: return entries;
651: }
652: }
|