KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > blojsom > plugin > common > RSSEnclosurePlugin


1 /**
2  * Copyright (c) 2003-2006, David A. Czarnecki
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * Redistributions of source code must retain the above copyright notice, this list of conditions and the
9  * following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
11  * following disclaimer in the documentation and/or other materials provided with the distribution.
12  * Neither the name of "David A. Czarnecki" and "blojsom" nor the names of its contributors may be used to
13  * endorse or promote products derived from this software without specific prior written permission.
14  * Products derived from this software may not be called "blojsom", nor may "blojsom" appear in their name,
15  * without prior written permission of David A. Czarnecki.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21  * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */

31 package org.blojsom.plugin.common;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.blojsom.blog.Entry;
36 import org.blojsom.blog.Blog;
37 import org.blojsom.event.Event;
38 import org.blojsom.event.EventBroadcaster;
39 import org.blojsom.event.Listener;
40 import org.blojsom.plugin.Plugin;
41 import org.blojsom.plugin.PluginException;
42 import org.blojsom.plugin.admin.event.ProcessEntryEvent;
43 import org.blojsom.util.BlojsomUtils;
44 import org.blojsom.util.BlojsomConstants;
45
46 import javax.activation.MimetypesFileTypeMap JavaDoc;
47 import javax.servlet.http.HttpServletRequest JavaDoc;
48 import javax.servlet.http.HttpServletResponse JavaDoc;
49 import javax.servlet.ServletConfig JavaDoc;
50 import javax.servlet.ServletContext JavaDoc;
51 import java.io.File JavaDoc;
52 import java.net.HttpURLConnection JavaDoc;
53 import java.net.URL JavaDoc;
54 import java.text.MessageFormat JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.Map JavaDoc;
57 import java.util.TreeMap JavaDoc;
58 import java.util.Properties JavaDoc;
59
60 /**
61  * RSSEnclosurePlugin
62  *
63  * @author David Czarnecki
64  * @version $Id: RSSEnclosurePlugin.java,v 1.3 2006/08/30 13:37:57 czarneckid Exp $
65  * @since blojsom 3.0
66  */

67 public class RSSEnclosurePlugin implements Plugin, Listener {
68
69     private Log _logger = LogFactory.getLog(RSSEnclosurePlugin.class);
70
71     private static final String JavaDoc RSS_ENCLOSURE_TEMPLATE = "org/blojsom/plugin/common/templates/admin-rss-enclosure-attachment.vm";
72     private static final String JavaDoc RSS_ENCLOSURE_ATTACHMENT = "RSS_ENCLOSURE_ATTACHMENT";
73     private static final String JavaDoc RSS_ENCLOSURE_URL_ITEM = "RSS_ENCLOSURE_URL_ITEM";
74     private static final String JavaDoc RSS_ENCLOSURE_LENGTH_ITEM = "RSS_ENCLOSURE_LENGTH_ITEM";
75     private static final String JavaDoc RSS_ENCLOSURE_TYPE_ITEM = "RSS_ENCLOSURE_TYPE_ITEM";
76     private static final String JavaDoc RSS_ENCLOSURE_LINK_TEMPLATE = "<enclosure url=\"{0}\" length=\"{1}\" type=\"{2}\" />";
77
78     protected static final String JavaDoc MIME_TYPE_XMPEGURL = "audio/x-mpegurl m3u";
79     protected static final String JavaDoc MIME_TYPE_XMPEG = "audio/x-mpeg mp1 mp2 mp3 mpa mpega";
80
81     public static final String JavaDoc DEFAULT_MIME_TYPE = "application/octet-stream";
82     public static final String JavaDoc METADATA_RSS_ENCLOSURE = "rss-enclosure";
83     public static final String JavaDoc METADATA_ESS_ENCLOSURE_OBJECT = "rss-enclosure-object";
84
85     public static final String JavaDoc RSS_ENCLOSURE_URL = "rss-enclosure-url";
86     public static final String JavaDoc RSS_ENCLOSURE_LENGTH = "rss-enclosure-length";
87     public static final String JavaDoc RSS_ENCLOSURE_TYPE = "rss-enclosure-type";
88
89     protected EventBroadcaster _eventBroadcaster;
90     protected ServletConfig JavaDoc _servletConfig;
91     protected Properties JavaDoc _blojsomProperties;
92
93     protected String JavaDoc _resourcesDirectory;
94
95     /**
96      * Default constructor
97      */

98     public RSSEnclosurePlugin() {
99     }
100
101     /**
102      * Set the default blojsom properties
103      *
104      * @param blojsomProperties Default blojsom properties
105      */

106     public void setBlojsomProperties(Properties JavaDoc blojsomProperties) {
107         _blojsomProperties = blojsomProperties;
108     }
109
110     /**
111      * Set the {@link ServletConfig}
112      *
113      * @param servletConfig {@link ServletConfig}
114      */

115     public void setServletConfig(ServletConfig JavaDoc servletConfig) {
116         _servletConfig = servletConfig;
117     }
118
119     /**
120      * Set the {@link EventBroadcaster}
121      *
122      * @param eventBroadcaster {@link EventBroadcaster}
123      */

124     public void setEventBroadcaster(EventBroadcaster eventBroadcaster) {
125         _eventBroadcaster = eventBroadcaster;
126     }
127
128     /**
129      * Initialize this plugin. This method only called when the plugin is
130      * instantiated.
131      *
132      * @throws org.blojsom.plugin.PluginException
133      * If there is an error initializing the plugin
134      */

135     public void init() throws PluginException {
136         _resourcesDirectory = _blojsomProperties.getProperty(BlojsomConstants.RESOURCES_DIRECTORY_IP, BlojsomConstants.DEFAULT_RESOURCES_DIRECTORY);
137         _eventBroadcaster.addListener(this);
138
139         _logger.debug("Initialized RSS enclosures plugin");
140     }
141
142     /**
143      * Add additional mime types to the map
144      *
145      * @param mimeTypes Mime types map
146      */

147     protected void addAdditionalMimeTypes(MimetypesFileTypeMap JavaDoc mimeTypes) {
148         mimeTypes.addMimeTypes(MIME_TYPE_XMPEGURL);
149         mimeTypes.addMimeTypes(MIME_TYPE_XMPEG);
150     }
151
152     /**
153      * Process the blog entries
154      *
155      * @param httpServletRequest Request
156      * @param httpServletResponse Response
157      * @param blog {@link Blog} instance
158      * @param context Context
159      * @param entries Blog entries retrieved for the particular request
160      * @return Modified set of blog entries
161      * @throws PluginException If there is an error processing the blog entries
162      */

163     public Entry[] process(HttpServletRequest JavaDoc httpServletRequest, HttpServletResponse JavaDoc httpServletResponse, Blog blog, Map JavaDoc context, Entry[] entries) throws PluginException {
164         ServletContext JavaDoc servletContext = _servletConfig.getServletContext();
165
166         for (int i = 0; i < entries.length; i++) {
167             Entry entry = entries[i];
168             if (BlojsomUtils.checkMapForKey(entry.getMetaData(), RSS_ENCLOSURE_URL) && BlojsomUtils.checkMapForKey(entry.getMetaData(), RSS_ENCLOSURE_LENGTH) && BlojsomUtils.checkMapForKey(entry.getMetaData(), RSS_ENCLOSURE_TYPE))
169             {
170                 String JavaDoc rssEnclosureURL = (String JavaDoc) entry.getMetaData().get(RSS_ENCLOSURE_URL);
171                 rssEnclosureURL = BlojsomUtils.escapeBrackets(rssEnclosureURL);
172
173                 long rssEnclosureLength = -1;
174                 try {
175                     rssEnclosureLength = Long.parseLong((String JavaDoc) entry.getMetaData().get(RSS_ENCLOSURE_LENGTH));
176                 } catch (NumberFormatException JavaDoc e) {
177                 }
178                 String JavaDoc rssEnclosureType = (String JavaDoc) entry.getMetaData().get(RSS_ENCLOSURE_TYPE);
179
180                 String JavaDoc rssEnclosure = MessageFormat.format(RSS_ENCLOSURE_LINK_TEMPLATE, new Object JavaDoc[]{rssEnclosureURL, Long.toString(rssEnclosureLength), rssEnclosureType});
181                 RSSEnclosure rssEnclosureObject = new RSSEnclosure(rssEnclosureURL, rssEnclosureLength, rssEnclosureType);
182
183                 entry.getMetaData().put(METADATA_RSS_ENCLOSURE, rssEnclosure);
184                 entry.getMetaData().put(METADATA_ESS_ENCLOSURE_OBJECT, rssEnclosureObject);
185                 if (_logger.isDebugEnabled()) {
186                     _logger.debug("Added explicit enclosure: " + rssEnclosure);
187                 }
188             } else {
189                 if (BlojsomUtils.checkMapForKey(entry.getMetaData(), METADATA_RSS_ENCLOSURE)) {
190                     String JavaDoc enclosureName = BlojsomUtils.getFilenameFromPath((String JavaDoc) entry.getMetaData().get(METADATA_RSS_ENCLOSURE));
191                     File JavaDoc enclosure = new File JavaDoc(servletContext.getRealPath("/") + _resourcesDirectory + blog.getBlogId() + "/" + enclosureName);
192                     if (enclosure.exists()) {
193                         if (_logger.isDebugEnabled()) {
194                             _logger.debug("Adding enclosure to entry for file: " + enclosureName);
195                         }
196
197                         MimetypesFileTypeMap JavaDoc mimetypesFileTypeMap = new MimetypesFileTypeMap JavaDoc();
198                         addAdditionalMimeTypes(mimetypesFileTypeMap);
199                         String JavaDoc type = mimetypesFileTypeMap.getContentType(enclosure);
200
201                         StringBuffer JavaDoc enclosureElement = new StringBuffer JavaDoc();
202                         String JavaDoc url = blog.getBlogBaseURL() + _resourcesDirectory + blog.getBlogId() + "/" + enclosure.getName();
203                         url = BlojsomUtils.escapeBrackets(url);
204                         enclosureElement.append("<enclosure url=\"");
205                         enclosureElement.append(url);
206                         enclosureElement.append("\" length=\"");
207                         enclosureElement.append(enclosure.length());
208                         enclosureElement.append("\" type=\"");
209                         if (BlojsomUtils.checkNullOrBlank(type)) {
210                             type = DEFAULT_MIME_TYPE;
211                         }
212                         enclosureElement.append(type);
213                         enclosureElement.append("\" />");
214
215                         RSSEnclosure rssEnclosure = new RSSEnclosure(url, enclosure.length(), type);
216                         entry.getMetaData().put(METADATA_RSS_ENCLOSURE, enclosureElement.toString());
217                         entry.getMetaData().put(METADATA_ESS_ENCLOSURE_OBJECT, rssEnclosure);
218                         if (_logger.isDebugEnabled()) {
219                             _logger.debug("Added enclosure: " + enclosureElement.toString());
220                         }
221                     }
222                 }
223             }
224         }
225
226         return entries;
227     }
228
229     /**
230      * Perform any cleanup for the plugin. Called after {@link #process}.
231      *
232      * @throws org.blojsom.plugin.PluginException
233      * If there is an error performing cleanup for this plugin
234      */

235     public void cleanup() throws PluginException {
236     }
237
238     /**
239      * Called when BlojsomServlet is taken out of service
240      *
241      * @throws org.blojsom.plugin.PluginException
242      * If there is an error in finalizing this plugin
243      */

244     public void destroy() throws PluginException {
245     }
246
247     /**
248      * Handle an event broadcast from another component
249      *
250      * @param event {@link org.blojsom.event.Event} to be handled
251      */

252     public void handleEvent(Event event) {
253     }
254
255     /**
256      * Process an event from another component
257      *
258      * @param event {@link org.blojsom.event.Event} to be handled
259      */

260     public void processEvent(Event event) {
261         if (event instanceof ProcessEntryEvent) {
262             if (_logger.isDebugEnabled()) {
263                 _logger.debug("Handling process blog entry event");
264             }
265
266             ProcessEntryEvent processBlogEntryEvent = (ProcessEntryEvent) event;
267             String JavaDoc blogId = processBlogEntryEvent.getBlog().getBlogId();
268
269             Map JavaDoc templateAdditions = (Map JavaDoc) processBlogEntryEvent.getContext().get("BLOJSOM_TEMPLATE_ADDITIONS");
270             if (templateAdditions == null) {
271                 templateAdditions = new TreeMap JavaDoc();
272             }
273
274             templateAdditions.put(getClass().getName(), "#parse('" + RSS_ENCLOSURE_TEMPLATE + "')");
275             processBlogEntryEvent.getContext().put("BLOJSOM_TEMPLATE_ADDITIONS", templateAdditions);
276
277             // Create a list of files in the user's resource directory
278
File JavaDoc resourceDirectory = new File JavaDoc(_servletConfig.getServletContext().getRealPath("/") + _resourcesDirectory + blogId + "/");
279             Map JavaDoc resourceFilesMap = null;
280             if (resourceDirectory.exists()) {
281                 File JavaDoc[] resourceFiles = resourceDirectory.listFiles();
282
283                 if (resourceFiles != null) {
284                     resourceFilesMap = new HashMap JavaDoc(resourceFiles.length);
285                     for (int i = 0; i < resourceFiles.length; i++) {
286                         File JavaDoc resourceFile = resourceFiles[i];
287                         resourceFilesMap.put(resourceFile.getName(), resourceFile.getName());
288                     }
289                 }
290             } else {
291                 resourceFilesMap = new HashMap JavaDoc();
292             }
293
294             // Preserve the current rss enclosure if none submitted
295
if (processBlogEntryEvent.getEntry() != null) {
296                 String JavaDoc currentEnclosure = (String JavaDoc) processBlogEntryEvent.getEntry().getMetaData().get(METADATA_RSS_ENCLOSURE);
297                 String JavaDoc currentEnclosureURL = (String JavaDoc) processBlogEntryEvent.getEntry().getMetaData().get(RSS_ENCLOSURE_URL);
298                 String JavaDoc currentEnclosureLength = (String JavaDoc) processBlogEntryEvent.getEntry().getMetaData().get(RSS_ENCLOSURE_LENGTH);
299                 String JavaDoc currentEnclosureType = (String JavaDoc) processBlogEntryEvent.getEntry().getMetaData().get(RSS_ENCLOSURE_TYPE);
300
301                 if (_logger.isDebugEnabled()) {
302                     _logger.debug("Current enclosure: " + currentEnclosure);
303                 }
304                 processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_ATTACHMENT, currentEnclosure);
305                 processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_URL_ITEM, BlojsomUtils.escapeBrackets(currentEnclosureURL));
306                 processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_LENGTH_ITEM, currentEnclosureLength);
307                 processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_TYPE_ITEM, currentEnclosureType);
308             }
309
310             String JavaDoc rssEnclosure = BlojsomUtils.getRequestValue(METADATA_RSS_ENCLOSURE, processBlogEntryEvent.getHttpServletRequest());
311             String JavaDoc rssEnclosureURL = BlojsomUtils.getRequestValue(RSS_ENCLOSURE_URL, processBlogEntryEvent.getHttpServletRequest());
312             String JavaDoc rssEnclosureLength = BlojsomUtils.getRequestValue(RSS_ENCLOSURE_LENGTH, processBlogEntryEvent.getHttpServletRequest());
313             String JavaDoc rssEnclosureType = BlojsomUtils.getRequestValue(RSS_ENCLOSURE_TYPE, processBlogEntryEvent.getHttpServletRequest());
314
315             if (!BlojsomUtils.checkNullOrBlank(rssEnclosureURL) && (processBlogEntryEvent.getEntry() != null)) {
316                 processBlogEntryEvent.getEntry().getMetaData().put(RSS_ENCLOSURE_URL, rssEnclosureURL);
317                 if (BlojsomUtils.checkNullOrBlank(rssEnclosureLength) && BlojsomUtils.checkNullOrBlank(rssEnclosureType)) {
318                     String JavaDoc[] enclosureProperties = discoverEnclosureProperties(rssEnclosureURL);
319                     rssEnclosureLength = enclosureProperties[0];
320                     rssEnclosureType = enclosureProperties[1];
321                 }
322
323                 processBlogEntryEvent.getEntry().getMetaData().put(RSS_ENCLOSURE_LENGTH, rssEnclosureLength);
324                 processBlogEntryEvent.getEntry().getMetaData().put(RSS_ENCLOSURE_TYPE, rssEnclosureType);
325                 processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_URL_ITEM, BlojsomUtils.escapeBrackets(rssEnclosureURL));
326                 processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_LENGTH_ITEM, rssEnclosureLength);
327                 processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_TYPE_ITEM, rssEnclosureType);
328
329                 if (_logger.isDebugEnabled()) {
330                     _logger.debug("Added/updated RSS enclosure (explict): " + rssEnclosureURL);
331                 }
332             } else {
333                 if (processBlogEntryEvent.getEntry() != null) {
334                     processBlogEntryEvent.getEntry().getMetaData().remove(RSS_ENCLOSURE_URL);
335                     processBlogEntryEvent.getEntry().getMetaData().remove(RSS_ENCLOSURE_TYPE);
336                     processBlogEntryEvent.getEntry().getMetaData().remove(RSS_ENCLOSURE_LENGTH);
337                 }
338
339                 processBlogEntryEvent.getContext().remove(RSS_ENCLOSURE_URL_ITEM);
340                 processBlogEntryEvent.getContext().remove(RSS_ENCLOSURE_TYPE_ITEM);
341                 processBlogEntryEvent.getContext().remove(RSS_ENCLOSURE_LENGTH_ITEM);
342
343                 if (!BlojsomUtils.checkNullOrBlank(rssEnclosure) && processBlogEntryEvent.getEntry() != null) {
344                     processBlogEntryEvent.getEntry().getMetaData().put(METADATA_RSS_ENCLOSURE, rssEnclosure);
345                     processBlogEntryEvent.getContext().put(RSS_ENCLOSURE_ATTACHMENT, rssEnclosure);
346
347                     if (_logger.isDebugEnabled()) {
348                         _logger.debug("Added/updated RSS enclosure: " + BlojsomUtils.getFilenameFromPath(rssEnclosure));
349                     }
350                 } else {
351                     if (processBlogEntryEvent.getEntry() != null) {
352                         processBlogEntryEvent.getEntry().getMetaData().remove(METADATA_RSS_ENCLOSURE);
353                     }
354                     processBlogEntryEvent.getContext().remove(RSS_ENCLOSURE_ATTACHMENT);
355                 }
356             }
357
358             resourceFilesMap = new TreeMap JavaDoc(resourceFilesMap);
359             processBlogEntryEvent.getContext().put("PLUGIN_RSS_ENCLOSURE_FILES", resourceFilesMap);
360         }
361     }
362
363     /**
364      * Discover the content length and content type for an enclosure URL
365      *
366      * @param rssEnclosureURL URL for enclosure
367      * @return String array containing the enclosure's content length and content type
368      */

369     protected String JavaDoc[] discoverEnclosureProperties(String JavaDoc rssEnclosureURL) {
370         String JavaDoc[] enclosureProperties = new String JavaDoc[]{"", ""};
371
372         try {
373             if (!rssEnclosureURL.toLowerCase().startsWith("http://")) {
374                 if (_logger.isDebugEnabled()) {
375                     _logger.debug("RSS enclosure URL not an HTTP-accessible resource");
376                 }
377             } else {
378                 URL JavaDoc enclosure = new URL JavaDoc(rssEnclosureURL);
379                 HttpURLConnection JavaDoc httpURLConnection = (HttpURLConnection JavaDoc) enclosure.openConnection();
380                 httpURLConnection.setRequestMethod("HEAD");
381                 httpURLConnection.connect();
382
383                 enclosureProperties[0] = Integer.toString(httpURLConnection.getContentLength());
384                 enclosureProperties[1] = httpURLConnection.getContentType();
385
386                 httpURLConnection.disconnect();
387             }
388         } catch (Exception JavaDoc e) {
389             if (_logger.isErrorEnabled()) {
390                 _logger.error("Error retrieving enclosure properties", e);
391             }
392         }
393
394         return enclosureProperties;
395     }
396
397     /**
398      * RSS Enclosure
399      *
400      * @author David Czarnecki
401      */

402     public class RSSEnclosure {
403
404         private String JavaDoc url;
405         private long length;
406         private String JavaDoc type;
407
408         /**
409          * Construct an RSS enclosure
410          *
411          * @param url URL to retrieve enclosure
412          * @param length Length of enclosure
413          * @param type Type of enclosure
414          */

415         public RSSEnclosure(String JavaDoc url, long length, String JavaDoc type) {
416             this.url = url;
417             this.length = length;
418             this.type = type;
419         }
420
421         /**
422          * Get the URL for the enclosure
423          *
424          * @return URL for enclosure
425          */

426         public String JavaDoc getUrl() {
427             return url;
428         }
429
430         /**
431          * Get the length of the enclosure
432          *
433          * @return Length of enclosure
434          */

435         public long getLength() {
436             return length;
437         }
438
439         /**
440          * Get the type of the enclosure
441          *
442          * @return Type of enclosure (e.g. audio/mpeg)
443          */

444         public String JavaDoc getType() {
445             return type;
446         }
447     }
448 }
449
450
Popular Tags