KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > myorg > feedreader > RssNode


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.myorg.feedreader;
21
22 import com.sun.syndication.feed.synd.SyndEntry;
23 import com.sun.syndication.feed.synd.SyndFeed;
24 import java.awt.Image JavaDoc;
25 import java.awt.event.ActionEvent JavaDoc;
26 import java.beans.IntrospectionException JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.io.ObjectOutputStream JavaDoc;
30 import java.net.MalformedURLException JavaDoc;
31 import java.net.URL JavaDoc;
32 import javax.swing.AbstractAction JavaDoc;
33 import javax.swing.Action JavaDoc;
34 import org.openide.DialogDisplayer;
35 import org.openide.ErrorManager;
36 import org.openide.NotifyDescriptor;
37 import org.openide.actions.DeleteAction;
38 import org.openide.actions.OpenAction;
39 import org.openide.cookies.InstanceCookie;
40 import org.openide.cookies.OpenCookie;
41 import org.openide.filesystems.FileLock;
42 import org.openide.filesystems.FileObject;
43 import org.openide.filesystems.Repository;
44 import org.openide.loaders.DataFolder;
45 import org.openide.loaders.DataObject;
46 import org.openide.loaders.DataObjectNotFoundException;
47 import org.openide.nodes.BeanNode;
48 import org.openide.nodes.Children;
49 import org.openide.nodes.FilterNode;
50 import org.openide.nodes.Node;
51 import org.openide.util.Lookup;
52 import org.openide.util.NbBundle;
53 import org.openide.util.Utilities;
54 import org.openide.util.actions.SystemAction;
55 import org.openide.util.lookup.Lookups;
56 import org.openide.util.lookup.ProxyLookup;
57
58 public class RssNode extends FilterNode {
59     
60     /** Declaring the children of the root RSS node */
61     public RssNode(Node folderNode) {
62         super(folderNode, new RssFolderChildren(folderNode));
63     }
64     
65     /** Declaring the Add Feed action and Add Folder action */
66     public Action JavaDoc[] getActions(boolean popup) {
67         DataFolder df = (DataFolder)getLookup().lookup(DataFolder.class);
68         return new Action JavaDoc[] {
69             new AddRssAction(df),
70             new AddFolderAction(df)
71         };
72     }
73     
74     /** Getting the root node */
75     public static class RootRssNode extends RssNode {
76         public RootRssNode() throws DataObjectNotFoundException {
77             super(DataObject.find(
78                     Repository.getDefault().getDefaultFileSystem()
79                     .getRoot().getFileObject("RssFeeds")).getNodeDelegate());
80         }
81         
82         public String JavaDoc getDisplayName() {
83             return NbBundle.getMessage(RssNode.class, "FN_title");
84         }
85     }
86     
87     /** Getting the children of the root node */
88     private static class RssFolderChildren extends FilterNode.Children {
89         RssFolderChildren(Node rssFolderNode) {
90             super(rssFolderNode);
91         }
92         
93         protected Node[] createNodes(Object JavaDoc key) {
94             Node n = (Node) key;
95             if (n.getLookup().lookup(DataFolder.class) != null) {
96                 return new Node[] {new RssNode(n)};
97             } else {
98                 Feed feed = getFeed(n);
99                 if (feed != null) {
100                     try {
101                         return new Node[] {new OneFeedNode(n, feed.getSyndFeed())};
102                     } catch (IOException JavaDoc ioe) {
103                         ErrorManager.getDefault().notify(ioe);
104                     }
105                 }
106             }
107             // best effort
108
return new Node[] {new FilterNode(n)};
109         }
110     }
111     
112     /** Getting the feed node and wrapping it in a FilterNode */
113     private static class OneFeedNode extends FilterNode {
114         
115         OneFeedNode(Node feedFileNode, SyndFeed feed) {
116             super(feedFileNode,
117                     new FeedChildren(feed),
118                     new ProxyLookup(new Lookup[] {
119                 Lookups.fixed(new Object JavaDoc[] {feed}),
120                 feedFileNode.getLookup()
121             }));
122         }
123         
124         public String JavaDoc getDisplayName() {
125             SyndFeed feed = (SyndFeed) getLookup().lookup(SyndFeed.class);
126             return feed.getTitle();
127         }
128         
129         public Image JavaDoc getIcon(int type) {
130             return Utilities.loadImage("org/myorg/feedreader/rss16.gif");
131         }
132         
133         public Image JavaDoc getOpenedIcon(int type) {
134             return getIcon(type);
135         }
136         
137         public Action JavaDoc[] getActions(boolean context) {
138             return new Action JavaDoc[] { SystemAction.get(DeleteAction.class) };
139         }
140         
141     }
142     
143     /** Defining the children of a feed node */
144     private static class FeedChildren extends Children.Keys {
145         private final SyndFeed feed;
146         public FeedChildren(SyndFeed feed) {
147             this.feed = feed;
148         }
149         
150         protected void addNotify() {
151             setKeys(feed.getEntries());
152         }
153         
154         public Node[] createNodes(Object JavaDoc key) {
155             try {
156                 return new Node[] { new EntryBeanNode((SyndEntry) key) };
157             } catch (IntrospectionException JavaDoc ex) {
158                 assert false : ex;
159                 return new Node[0];
160             }
161         }
162     }
163     
164     /** Wrapping the children in a FilterNode */
165     private static class EntryBeanNode extends FilterNode {
166         
167         private final SyndEntry entry;
168         
169         public EntryBeanNode(SyndEntry entry) throws IntrospectionException JavaDoc {
170             super(new BeanNode(entry), Children.LEAF, Lookups.fixed(new Object JavaDoc[] { entry, new EntryOpenCookie(entry) }));
171             this.entry = entry;
172         }
173         
174         /** Using HtmlDisplayName ensures any HTML in RSS entry titles are properly handled, escaped, entities resolved, etc. */
175         public String JavaDoc getHtmlDisplayName() {
176             return entry.getTitle();
177         }
178         
179         /** Making a tooltip out of the entry's description */
180         public String JavaDoc getShortDescription() {
181             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
182             sb.append("Author: " + entry.getAuthor() + "; ");
183             if (entry.getPublishedDate() != null) {
184                 sb.append("Published: ").append(entry.getPublishedDate().toString());
185             }
186             return sb.toString();
187         }
188         
189         /** Providing the Open action on a feed entry */
190         public Action JavaDoc[] getActions(boolean popup) {
191             return new Action JavaDoc[] { SystemAction.get(OpenAction.class) };
192         }
193         
194         public Action JavaDoc getPreferredAction() {
195             return (SystemAction) getActions(false) [0];
196         }
197         
198     }
199     
200     /** Specifying what should happen when the user invokes the Open action */
201     private static class EntryOpenCookie implements OpenCookie {
202         
203         private final SyndEntry entry;
204         
205         EntryOpenCookie(SyndEntry entry) {
206             this.entry = entry;
207         }
208         
209         public void open() {
210             BrowserTopComponent btc = BrowserTopComponent.getBrowserComponent(entry.getTitle());
211             btc.open();
212             btc.requestActive();
213             btc.setPage(entry.getUri());
214         }
215         
216     }
217     
218     /** Looking up a feed */
219     private static Feed getFeed(Node node) {
220         InstanceCookie ck = (InstanceCookie) node.getCookie(InstanceCookie.class);
221         if (ck == null) {
222             throw new IllegalStateException JavaDoc("Bogus file in feeds folder: " + node.getLookup().lookup(FileObject.class));
223         }
224         try {
225             return (Feed) ck.instanceCreate();
226         } catch (ClassNotFoundException JavaDoc ex) {
227             ErrorManager.getDefault().notify(ex);
228         } catch (IOException JavaDoc ex) {
229             ErrorManager.getDefault().notify(ex);
230         }
231         return null;
232     }
233     
234     /** An action for adding a folder to organize feeds into groups */
235     private static class AddFolderAction extends AbstractAction JavaDoc {
236         
237         private final DataFolder folder;
238         
239         public AddFolderAction(DataFolder df) {
240             super(NbBundle.getMessage(RssNode.class, "FN_addfolderbutton"));
241             folder = df;
242         }
243         
244         public void actionPerformed(ActionEvent JavaDoc ae) {
245             NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine(
246                     NbBundle.getMessage(RssNode.class, "FN_askfolder_msg"),
247                     NbBundle.getMessage(RssNode.class, "FN_askfolder_title"),
248                     NotifyDescriptor.OK_CANCEL_OPTION,
249                     NotifyDescriptor.PLAIN_MESSAGE);
250             
251             Object JavaDoc result = DialogDisplayer.getDefault().notify(nd);
252             
253             if (result.equals(NotifyDescriptor.OK_OPTION)) {
254                 final String JavaDoc folderString = nd.getInputText();
255                 try {
256                     DataFolder.create(folder, folderString);
257                 } catch (IOException JavaDoc ex) {
258                     ErrorManager.getDefault().notify(ex);
259                 }
260             }
261         }
262     }
263     
264     /** An action for adding a feed */
265     private static class AddRssAction extends AbstractAction JavaDoc {
266         
267         private final DataFolder folder;
268         
269         public AddRssAction(DataFolder df) {
270             super(NbBundle.getMessage(RssNode.class, "FN_addbutton"));
271             folder = df;
272         }
273         
274         public void actionPerformed(ActionEvent JavaDoc ae) {
275             NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine(
276                     NbBundle.getMessage(RssNode.class, "FN_askurl_msg"),
277                     NbBundle.getMessage(RssNode.class, "FN_askurl_title"),
278                     NotifyDescriptor.OK_CANCEL_OPTION,
279                     NotifyDescriptor.PLAIN_MESSAGE);
280             
281             Object JavaDoc result = DialogDisplayer.getDefault().notify(nd);
282             
283             if (result.equals(NotifyDescriptor.OK_OPTION)) {
284                 String JavaDoc urlString = nd.getInputText();
285                 URL JavaDoc url;
286                 try {
287                     url = new URL JavaDoc(urlString);
288                 } catch (MalformedURLException JavaDoc e) {
289                     String JavaDoc message = NbBundle.getMessage(RssNode.class, "FN_askurl_err", urlString);
290                     ErrorManager.getDefault().annotate(e, ErrorManager.ERROR, null, message, null, null);
291                     ErrorManager.getDefault().notify(e);
292                     return;
293                 }
294                 try {
295                     checkConnection(url);
296                 } catch (IOException JavaDoc e) {
297                     String JavaDoc message = NbBundle.getMessage(RssNode.class, "FN_cannotConnect_err", urlString);
298                     ErrorManager.getDefault().annotate(e, ErrorManager.ERROR, null, message, null, null);
299                     ErrorManager.getDefault().notify(e);
300                     return;
301                 }
302                 Feed f = new Feed(url);
303                 FileObject fld = folder.getPrimaryFile();
304                 String JavaDoc baseName = "RssFeed";
305                 int ix = 1;
306                 while (fld.getFileObject(baseName + ix, "ser") != null) {
307                     ix++;
308                 }
309                 try {
310                     FileObject writeTo = fld.createData(baseName + ix, "ser");
311                     FileLock lock = writeTo.lock();
312                     try {
313                         ObjectOutputStream JavaDoc str = new ObjectOutputStream JavaDoc(writeTo.getOutputStream(lock));
314                         try {
315                             str.writeObject(f);
316                         } finally {
317                             str.close();
318                         }
319                     } finally {
320                         lock.releaseLock();
321                     }
322                 } catch (IOException JavaDoc ioe) {
323                     ErrorManager.getDefault().notify(ioe);
324                 }
325             }
326         }
327         
328         private static void checkConnection(final URL JavaDoc url) throws IOException JavaDoc {
329             InputStream JavaDoc is = url.openStream();
330             is.close();
331         }
332         
333     }
334     
335 }
336
Popular Tags