KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > platform > internal > EclipseRSSViewer


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.platform.internal;
12
13 import java.io.IOException JavaDoc;
14 import java.io.InputStream JavaDoc;
15 import java.io.PrintWriter JavaDoc;
16 import java.net.MalformedURLException JavaDoc;
17 import java.net.URL JavaDoc;
18 import java.net.URLEncoder JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Stack JavaDoc;
23
24 import javax.xml.parsers.SAXParser JavaDoc;
25 import javax.xml.parsers.SAXParserFactory JavaDoc;
26
27 import org.eclipse.core.runtime.FileLocator;
28 import org.eclipse.core.runtime.IPath;
29 import org.eclipse.core.runtime.Path;
30 import org.eclipse.core.runtime.Platform;
31 import org.eclipse.jface.resource.ImageDescriptor;
32 import org.eclipse.swt.custom.BusyIndicator;
33 import org.eclipse.swt.graphics.Image;
34 import org.eclipse.swt.widgets.Composite;
35 import org.eclipse.swt.widgets.Control;
36 import org.eclipse.ui.PartInitException;
37 import org.eclipse.ui.PlatformUI;
38 import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
39 import org.eclipse.ui.forms.events.HyperlinkAdapter;
40 import org.eclipse.ui.forms.events.HyperlinkEvent;
41 import org.eclipse.ui.forms.widgets.FormText;
42 import org.eclipse.ui.forms.widgets.FormToolkit;
43 import org.eclipse.ui.forms.widgets.ScrolledForm;
44 import org.eclipse.ui.intro.config.IIntroContentProvider;
45 import org.eclipse.ui.intro.config.IIntroContentProviderSite;
46 import org.eclipse.ui.intro.config.IIntroURL;
47 import org.eclipse.ui.intro.config.IntroURLFactory;
48 import org.osgi.framework.Bundle;
49 import org.xml.sax.Attributes JavaDoc;
50 import org.xml.sax.SAXException JavaDoc;
51 import org.xml.sax.helpers.DefaultHandler JavaDoc;
52
53 public class EclipseRSSViewer implements IIntroContentProvider {
54     private static final String JavaDoc NEWS_URL = "http://www.eclipse.org/home/eclipsenews.rss"; //$NON-NLS-1$
55
private static final String JavaDoc INTRO_SHOW_IN_BROWSER = "http://org.eclipse.ui.intro/openBrowser?url="; //$NON-NLS-1$
56
private static final int MAX_NEWS_ITEMS = 5;
57     private static final String JavaDoc HREF_BULLET = "bullet"; //$NON-NLS-1$
58

59     private IIntroContentProviderSite site;
60
61     private boolean disposed;
62
63     private String JavaDoc id;
64
65     private FormToolkit toolkit;
66
67     private Composite parent;
68
69     private Image bulletImage;
70
71     private List JavaDoc items;
72
73     private FormText formText;
74
75     static class NewsItem {
76         String JavaDoc label;
77
78         String JavaDoc url;
79
80         void setLabel(String JavaDoc label) {
81             this.label = label;
82         }
83
84         void setUrl(String JavaDoc url) {
85             this.url = url;
86         }
87     }
88
89     class NewsFeed implements Runnable JavaDoc {
90         public void run() {
91             // important: don't do the work if the
92
// part gets disposed in the process
93
if (disposed)
94                 return;
95             createNewsItems();
96             if (disposed)
97                 return;
98             PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable JavaDoc() {
99                 public void run() {
100                     if (parent != null) {
101                         // we must recreate the content
102
// for SWT because we will use
103
// a gentle incremental reflow.
104
// HTML reflow will simply reload the page.
105
createContent(id, parent, toolkit);
106                         reflow(formText);
107                     }
108                     site.reflow(EclipseRSSViewer.this, true);
109                 }
110             });
111         }
112     }
113
114     /**
115      * Handles RSS XML and populates the items list with at most
116      * MAX_NEWS_ITEMS items.
117      */

118     private class RSSHandler extends DefaultHandler JavaDoc {
119
120         private static final String JavaDoc ELEMENT_RSS = "rss"; //$NON-NLS-1$
121
private static final String JavaDoc ELEMENT_CHANNEL = "channel"; //$NON-NLS-1$
122
private static final String JavaDoc ELEMENT_ITEM = "item"; //$NON-NLS-1$
123
private static final String JavaDoc ELEMENT_TITLE = "title"; //$NON-NLS-1$
124
private static final String JavaDoc ELEMENT_LINK = "link"; //$NON-NLS-1$
125

126         private Stack JavaDoc stack = new Stack JavaDoc();
127         private StringBuffer JavaDoc buf;
128         private NewsItem item;
129         
130         public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc attributes) throws SAXException JavaDoc {
131             stack.push(qName);
132             // it's a title/link in an item
133
if ((ELEMENT_TITLE.equals(qName) || ELEMENT_LINK.equals(qName))
134                     && (item != null)) {
135                 // prepare the buffer; we're expecting chars
136
buf = new StringBuffer JavaDoc();
137             }
138             // it's an item in a channel in rss
139
else if (ELEMENT_ITEM.equals(qName)
140                     && (ELEMENT_CHANNEL.equals(stack.get(1)))
141                     && (ELEMENT_RSS.equals(stack.get(0)))
142                     && (stack.size() == 3)
143                     && (items.size() < MAX_NEWS_ITEMS)) {
144                 // prepare the item
145
item = new NewsItem();
146             }
147         }
148         
149         public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
150             stack.pop();
151             if (item != null) {
152                 if (buf != null) {
153                     if (ELEMENT_TITLE.equals(qName)) {
154                         item.setLabel(buf.toString().trim());
155                         buf = null;
156                     }
157                     else if (ELEMENT_LINK.equals(qName)) {
158                         item.setUrl(buf.toString().trim());
159                         buf = null;
160                     }
161                 }
162                 else {
163                     if (ELEMENT_ITEM.equals(qName)) {
164                         // ensure we have a valid item
165
if (item.label != null && item.label.length() > 0 &&
166                                 item.url != null && item.url.length() > 0) {
167                             items.add(item);
168                         }
169                         item = null;
170                     }
171                 }
172             }
173         }
174         
175         public void characters(char[] ch, int start, int length) throws SAXException JavaDoc {
176             // were we expecting chars?
177
if (buf != null) {
178                 buf.append(new String JavaDoc(ch, start, length));
179             }
180         }
181     }
182
183     
184     public void init(IIntroContentProviderSite site) {
185         this.site = site;
186         Thread JavaDoc newsWorker = new Thread JavaDoc(new NewsFeed());
187         newsWorker.start();
188     }
189
190     public void createContent(String JavaDoc id, PrintWriter JavaDoc out) {
191         if (disposed)
192             return;
193         this.id = id;
194         if (items == null) {
195             out.print("<p class=\"status-text\">"); //$NON-NLS-1$
196
out.print(Messages.getString("EclipseRSSViewer_loading")); //$NON-NLS-1$
197
out.println("</p>"); //$NON-NLS-1$
198
} else {
199             if (items.size() > 0) {
200                 out.println("<ul id=\"eclipse-news\">"); //$NON-NLS-1$
201
for (int i = 0; i < items.size(); i++) {
202                     NewsItem item = (NewsItem) items.get(i);
203                     out.print("<li>"); //$NON-NLS-1$
204
out.print("<a class=\"topicList\" HREF=\""); //$NON-NLS-1$
205
out.print(createExternalURL(item.url));
206                     out.print("\">"); //$NON-NLS-1$
207
out.print(item.label);
208                     out.print("</a>"); //$NON-NLS-1$
209
out.println("</li>"); //$NON-NLS-1$
210
}
211             } else {
212                 out.print("<p class=\"status-text\">"); //$NON-NLS-1$
213
out.print(Messages.getString("EclipseRSSViewer_noNews")); //$NON-NLS-1$
214
out.println("</p>"); //$NON-NLS-1$
215
}
216             out.println("</ul>"); //$NON-NLS-1$
217
}
218     }
219
220     public void createContent(String JavaDoc id, Composite parent, FormToolkit toolkit) {
221         if (disposed)
222             return;
223         if (formText == null) {
224             // a one-time pass
225
formText = toolkit.createFormText(parent, true);
226             formText.addHyperlinkListener(new HyperlinkAdapter() {
227                 public void linkActivated(HyperlinkEvent e) {
228                     doNavigate((String JavaDoc) e.getHref());
229                 }
230             });
231             bulletImage = createImage(new Path("images/topiclabel/arrow.gif")); //$NON-NLS-1$
232
if (bulletImage!=null)
233                 formText.setImage(HREF_BULLET, bulletImage);
234             this.parent = parent;
235             this.toolkit = toolkit;
236             this.id = id;
237         }
238         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
239         buffer.append("<form>"); //$NON-NLS-1$
240
if (items == null) {
241             buffer.append("<p>"); //$NON-NLS-1$
242
buffer.append(Messages.getString("EclipseRSSViewer_loading")); //$NON-NLS-1$
243
buffer.append("</p>"); //$NON-NLS-1$
244
} else {
245             if (items.size() > 0) {
246                 for (int i = 0; i < items.size(); i++) {
247                     NewsItem item = (NewsItem) items.get(i);
248                     buffer.append("<li style=\"image\" value=\""); //$NON-NLS-1$
249
buffer.append(HREF_BULLET);
250                     buffer.append("\">"); //$NON-NLS-1$
251
buffer.append("<a HREF=\""); //$NON-NLS-1$
252
buffer.append(item.url);
253                     buffer.append("\">"); //$NON-NLS-1$
254
buffer.append(item.label);
255                     buffer.append("</a>"); //$NON-NLS-1$
256
buffer.append("</li>"); //$NON-NLS-1$
257
}
258             } else {
259                 buffer.append("<p>"); //$NON-NLS-1$
260
buffer.append(Messages.getString("EclipseRSSViewer_noNews")); //$NON-NLS-1$
261
buffer.append("</p>"); //$NON-NLS-1$
262
}
263         }
264         buffer.append("</form>"); //$NON-NLS-1$
265
formText.setText(buffer.toString(), true, false);
266     }
267
268     private String JavaDoc createExternalURL(String JavaDoc url) {
269         //TODO don't know which encoding to pass here - revisit
270
return INTRO_SHOW_IN_BROWSER+
271                             URLEncoder.encode(url);
272     }
273
274     private Image createImage(IPath path) {
275         Bundle bundle = Platform.getBundle("org.eclipse.platform"); //$NON-NLS-1$
276
URL JavaDoc url = FileLocator.find(bundle, path, null);
277         try {
278             url = FileLocator.toFileURL(url);
279             ImageDescriptor desc = ImageDescriptor.createFromURL(url);
280             return desc.createImage();
281         } catch (IOException JavaDoc e) {
282             return null;
283         }
284     }
285
286     private void doNavigate(final String JavaDoc url) {
287         BusyIndicator.showWhile(PlatformUI.getWorkbench().getDisplay(),
288                 new Runnable JavaDoc() {
289                     public void run() {
290                         IIntroURL introUrl = IntroURLFactory
291                                 .createIntroURL(url);
292                         if (introUrl != null) {
293                             // execute the action embedded in the IntroURL
294
introUrl.execute();
295                             return;
296                         }
297                         // delegate to the browser support
298
openBrowser(url);
299                     }
300                 });
301     }
302
303     private void openBrowser(String JavaDoc href) {
304         try {
305             URL JavaDoc url = new URL JavaDoc(href);
306             IWorkbenchBrowserSupport support = PlatformUI.getWorkbench()
307                     .getBrowserSupport();
308             support.getExternalBrowser().openURL(url);
309         } catch (PartInitException e) {
310         } catch (MalformedURLException JavaDoc e) {
311         }
312     }
313
314     private void createNewsItems() {
315         items = Collections.synchronizedList(new ArrayList JavaDoc());
316         InputStream JavaDoc in = null;
317         try {
318             URL JavaDoc url = new URL JavaDoc(NEWS_URL);
319             in = url.openStream();
320             SAXParser JavaDoc parser = SAXParserFactory.newInstance().newSAXParser();
321             parser.parse(in, new RSSHandler());
322         }
323         catch (Exception JavaDoc e) {
324             // if anything goes wrong, fail silently; it will show a
325
// "no news available" message.
326
}
327         finally {
328             try {
329                 if (in != null) {
330                     in.close();
331                 }
332             }
333             catch (IOException JavaDoc e) {
334                 // nothing we can do here
335
}
336         }
337     }
338
339     /*
340      * This method is copied from Section and seems useful in general. Perhaps
341      * we should move it into content provider site, something like
342      * 'reflow(Control startingControl)'
343      */

344
345     private void reflow(Control initiator) {
346         Control c = initiator;
347         while (c != null) {
348             c.setRedraw(false);
349             c = c.getParent();
350             if (c instanceof ScrolledForm) {
351                 break;
352             }
353         }
354         c = initiator;
355         while (c != null) {
356             if (c instanceof Composite)
357                 ((Composite) c).layout(true);
358             c = c.getParent();
359             if (c instanceof ScrolledForm) {
360                 ((ScrolledForm) c).reflow(true);
361                 break;
362             }
363         }
364         c = initiator;
365         while (c != null) {
366             c.setRedraw(true);
367             c = c.getParent();
368             if (c instanceof ScrolledForm) {
369                 break;
370             }
371         }
372     }
373
374     public void dispose() {
375         if (bulletImage != null) {
376             bulletImage.dispose();
377             bulletImage = null;
378         }
379         disposed = true;
380     }
381 }
Popular Tags