1 11 package org.eclipse.platform.internal; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.io.PrintWriter ; 16 import java.net.MalformedURLException ; 17 import java.net.URL ; 18 import java.net.URLEncoder ; 19 import java.util.ArrayList ; 20 import java.util.Collections ; 21 import java.util.List ; 22 import java.util.Stack ; 23 24 import javax.xml.parsers.SAXParser ; 25 import javax.xml.parsers.SAXParserFactory ; 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 ; 50 import org.xml.sax.SAXException ; 51 import org.xml.sax.helpers.DefaultHandler ; 52 53 public class EclipseRSSViewer implements IIntroContentProvider { 54 private static final String NEWS_URL = "http://www.eclipse.org/home/eclipsenews.rss"; private static final String INTRO_SHOW_IN_BROWSER = "http://org.eclipse.ui.intro/openBrowser?url="; private static final int MAX_NEWS_ITEMS = 5; 57 private static final String HREF_BULLET = "bullet"; 59 private IIntroContentProviderSite site; 60 61 private boolean disposed; 62 63 private String id; 64 65 private FormToolkit toolkit; 66 67 private Composite parent; 68 69 private Image bulletImage; 70 71 private List items; 72 73 private FormText formText; 74 75 static class NewsItem { 76 String label; 77 78 String url; 79 80 void setLabel(String label) { 81 this.label = label; 82 } 83 84 void setUrl(String url) { 85 this.url = url; 86 } 87 } 88 89 class NewsFeed implements Runnable { 90 public void run() { 91 if (disposed) 94 return; 95 createNewsItems(); 96 if (disposed) 97 return; 98 PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable () { 99 public void run() { 100 if (parent != null) { 101 createContent(id, parent, toolkit); 106 reflow(formText); 107 } 108 site.reflow(EclipseRSSViewer.this, true); 109 } 110 }); 111 } 112 } 113 114 118 private class RSSHandler extends DefaultHandler { 119 120 private static final String ELEMENT_RSS = "rss"; private static final String ELEMENT_CHANNEL = "channel"; private static final String ELEMENT_ITEM = "item"; private static final String ELEMENT_TITLE = "title"; private static final String ELEMENT_LINK = "link"; 126 private Stack stack = new Stack (); 127 private StringBuffer buf; 128 private NewsItem item; 129 130 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 131 stack.push(qName); 132 if ((ELEMENT_TITLE.equals(qName) || ELEMENT_LINK.equals(qName)) 134 && (item != null)) { 135 buf = new StringBuffer (); 137 } 138 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 item = new NewsItem(); 146 } 147 } 148 149 public void endElement(String uri, String localName, String qName) throws SAXException { 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 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 { 176 if (buf != null) { 178 buf.append(new String (ch, start, length)); 179 } 180 } 181 } 182 183 184 public void init(IIntroContentProviderSite site) { 185 this.site = site; 186 Thread newsWorker = new Thread (new NewsFeed()); 187 newsWorker.start(); 188 } 189 190 public void createContent(String id, PrintWriter out) { 191 if (disposed) 192 return; 193 this.id = id; 194 if (items == null) { 195 out.print("<p class=\"status-text\">"); out.print(Messages.getString("EclipseRSSViewer_loading")); out.println("</p>"); } else { 199 if (items.size() > 0) { 200 out.println("<ul id=\"eclipse-news\">"); for (int i = 0; i < items.size(); i++) { 202 NewsItem item = (NewsItem) items.get(i); 203 out.print("<li>"); out.print("<a class=\"topicList\" HREF=\""); out.print(createExternalURL(item.url)); 206 out.print("\">"); out.print(item.label); 208 out.print("</a>"); out.println("</li>"); } 211 } else { 212 out.print("<p class=\"status-text\">"); out.print(Messages.getString("EclipseRSSViewer_noNews")); out.println("</p>"); } 216 out.println("</ul>"); } 218 } 219 220 public void createContent(String id, Composite parent, FormToolkit toolkit) { 221 if (disposed) 222 return; 223 if (formText == null) { 224 formText = toolkit.createFormText(parent, true); 226 formText.addHyperlinkListener(new HyperlinkAdapter() { 227 public void linkActivated(HyperlinkEvent e) { 228 doNavigate((String ) e.getHref()); 229 } 230 }); 231 bulletImage = createImage(new Path("images/topiclabel/arrow.gif")); if (bulletImage!=null) 233 formText.setImage(HREF_BULLET, bulletImage); 234 this.parent = parent; 235 this.toolkit = toolkit; 236 this.id = id; 237 } 238 StringBuffer buffer = new StringBuffer (); 239 buffer.append("<form>"); if (items == null) { 241 buffer.append("<p>"); buffer.append(Messages.getString("EclipseRSSViewer_loading")); buffer.append("</p>"); } 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=\""); buffer.append(HREF_BULLET); 250 buffer.append("\">"); buffer.append("<a HREF=\""); buffer.append(item.url); 253 buffer.append("\">"); buffer.append(item.label); 255 buffer.append("</a>"); buffer.append("</li>"); } 258 } else { 259 buffer.append("<p>"); buffer.append(Messages.getString("EclipseRSSViewer_noNews")); buffer.append("</p>"); } 263 } 264 buffer.append("</form>"); formText.setText(buffer.toString(), true, false); 266 } 267 268 private String createExternalURL(String url) { 269 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"); URL 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 e) { 282 return null; 283 } 284 } 285 286 private void doNavigate(final String url) { 287 BusyIndicator.showWhile(PlatformUI.getWorkbench().getDisplay(), 288 new Runnable () { 289 public void run() { 290 IIntroURL introUrl = IntroURLFactory 291 .createIntroURL(url); 292 if (introUrl != null) { 293 introUrl.execute(); 295 return; 296 } 297 openBrowser(url); 299 } 300 }); 301 } 302 303 private void openBrowser(String href) { 304 try { 305 URL url = new URL (href); 306 IWorkbenchBrowserSupport support = PlatformUI.getWorkbench() 307 .getBrowserSupport(); 308 support.getExternalBrowser().openURL(url); 309 } catch (PartInitException e) { 310 } catch (MalformedURLException e) { 311 } 312 } 313 314 private void createNewsItems() { 315 items = Collections.synchronizedList(new ArrayList ()); 316 InputStream in = null; 317 try { 318 URL url = new URL (NEWS_URL); 319 in = url.openStream(); 320 SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 321 parser.parse(in, new RSSHandler()); 322 } 323 catch (Exception e) { 324 } 327 finally { 328 try { 329 if (in != null) { 330 in.close(); 331 } 332 } 333 catch (IOException e) { 334 } 336 } 337 } 338 339 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 |