KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > welcome > content > RSSFeed


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.netbeans.modules.welcome.content;
21
22 import java.awt.Component JavaDoc;
23 import java.awt.Dimension JavaDoc;
24 import java.awt.GridBagConstraints JavaDoc;
25 import java.awt.GridBagLayout JavaDoc;
26 import java.awt.Insets JavaDoc;
27 import java.awt.Toolkit JavaDoc;
28 import java.awt.event.ActionEvent JavaDoc;
29 import java.awt.event.ActionListener JavaDoc;
30 import java.beans.PropertyChangeEvent JavaDoc;
31 import java.beans.PropertyChangeListener JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.net.SocketException JavaDoc;
34 import java.net.UnknownHostException JavaDoc;
35 import java.text.DateFormat JavaDoc;
36 import java.text.ParseException JavaDoc;
37 import java.text.SimpleDateFormat JavaDoc;
38 import java.util.ArrayList JavaDoc;
39 import java.util.Date JavaDoc;
40 import java.util.Locale JavaDoc;
41 import java.util.logging.Level JavaDoc;
42 import java.util.logging.Logger JavaDoc;
43 import javax.swing.JButton JavaDoc;
44 import javax.swing.JComponent JavaDoc;
45 import javax.swing.JLabel JavaDoc;
46 import javax.swing.JPanel JavaDoc;
47 import javax.swing.JScrollPane JavaDoc;
48 import javax.swing.SwingUtilities JavaDoc;
49 import javax.xml.parsers.ParserConfigurationException JavaDoc;
50 import org.openide.ErrorManager;
51 import org.openide.awt.Mnemonics;
52 import org.openide.util.RequestProcessor;
53 import org.openide.util.WeakListeners;
54 import org.openide.xml.XMLUtil;
55 import org.w3c.dom.Node JavaDoc;
56 import org.xml.sax.Attributes JavaDoc;
57 import org.xml.sax.ContentHandler JavaDoc;
58 import org.xml.sax.InputSource JavaDoc;
59 import org.xml.sax.Locator JavaDoc;
60 import org.xml.sax.SAXException JavaDoc;
61 import org.xml.sax.XMLReader JavaDoc;
62
63 public class RSSFeed extends JScrollPane JavaDoc implements Constants, PropertyChangeListener JavaDoc {
64     
65     protected static final int NEWS_COUNT = 10;
66     
67     private String JavaDoc url;
68     
69     private boolean showProxyButton = true;
70
71     private RequestProcessor.Task reloadTimer;
72     private long lastReload = 0;
73
74     public static final String JavaDoc FEED_CONTENT_PROPERTY = "feedContent";
75     
76     private static DateFormat JavaDoc parsingDateFormat = new SimpleDateFormat JavaDoc( "EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH ); // NOI18N
77
private static DateFormat JavaDoc parsingDateFormatShort = new SimpleDateFormat JavaDoc( "EEE, dd MMM yyyy", Locale.ENGLISH ); // NOI18N
78
private static DateFormat JavaDoc printingDateFormat = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT );
79     private static DateFormat JavaDoc printingDateFormatShort = DateFormat.getDateInstance( DateFormat.SHORT );
80
81     public RSSFeed( String JavaDoc url, boolean showProxyButton ) {
82         this.url = url;
83         this.showProxyButton = showProxyButton;
84         setBorder(null);
85         setOpaque(false);
86
87         setBackground( Utils.getColor(DEFAULT_BACKGROUND_COLOR) );
88         getViewport().setBackground( Utils.getColor(DEFAULT_BACKGROUND_COLOR) );
89         setViewportView( buildContentLoadingLabel() );
90         
91         setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_NEVER );
92
93         HttpProxySettings.getDefault().addPropertyChangeListener( WeakListeners.propertyChange( this, HttpProxySettings.getDefault() ) );
94     }
95     
96     public RSSFeed( boolean showProxyButton ) {
97         this( null, showProxyButton );
98     }
99     
100     public void setContent( Component JavaDoc content ) {
101         setViewportView( content );
102         firePropertyChange( FEED_CONTENT_PROPERTY, null, content );
103     }
104
105     public Component JavaDoc getContent() {
106         return getViewport().getView();
107     }
108
109     public void reload() {
110         new Reload().start();
111     }
112
113     protected ArrayList JavaDoc/*<FeedItem>*/ buildItemList() throws SAXException JavaDoc, ParserConfigurationException JavaDoc, IOException JavaDoc {
114         XMLReader JavaDoc reader = XMLUtil.createXMLReader( false, true );
115         FeedHandler handler = new FeedHandler();
116         reader.setContentHandler( handler );
117         reader.setEntityResolver( org.openide.xml.EntityCatalog.getDefault() );
118         reader.setErrorHandler( new ErrorCatcher() );
119
120         reader.parse( new InputSource JavaDoc(url) );
121
122         return handler.getItemList();
123     }
124
125         /** Inner class error catcher for handling SAXParseExceptions */
126     static class ErrorCatcher implements org.xml.sax.ErrorHandler JavaDoc {
127         private void message(Level JavaDoc level, org.xml.sax.SAXParseException JavaDoc e) {
128             Logger JavaDoc l = Logger.getLogger(RSSFeed.class.getName());
129             l.log(level, "Line number:"+e.getLineNumber()); //NOI18N
130
l.log(level, "Column number:"+e.getColumnNumber()); //NOI18N
131
l.log(level, "Public ID:"+e.getPublicId()); //NOI18N
132
l.log(level, "System ID:"+e.getSystemId()); //NOI18N
133
l.log(level, "Error message:"+e.getMessage()); //NOI18N
134
}
135         
136         public void error(org.xml.sax.SAXParseException JavaDoc e) {
137             message(Level.SEVERE, e); //NOI18N
138
}
139         
140         public void warning(org.xml.sax.SAXParseException JavaDoc e) {
141             message(Level.WARNING,e); //NOI18N
142
}
143         
144         public void fatalError(org.xml.sax.SAXParseException JavaDoc e) {
145             message(Level.SEVERE,e); //NOI18N
146
}
147     } //end of inner class ErrorCatcher
148

149     private class Reload extends Thread JavaDoc {
150         public void run() {
151             try {
152                 lastReload = System.currentTimeMillis();
153
154                 ArrayList JavaDoc itemList = buildItemList();
155                 final JPanel JavaDoc contentPanel = new NoHorizontalScrollPanel();
156                 contentPanel.setOpaque( false );
157                 int contentRow = 0;
158
159                 Component JavaDoc header = getContentHeader();
160                 if( null != header ) {
161                     contentPanel.add( header, new GridBagConstraints JavaDoc(0,contentRow++,1,1,0.0,0.0,
162                                 GridBagConstraints.CENTER,GridBagConstraints.BOTH,
163                                 new Insets JavaDoc(0,0,0,0),0,0 ) );
164                 }
165
166                 for( int i=0; i<Math.min(itemList.size(), NEWS_COUNT); i++ ) {
167                     FeedItem item = (FeedItem)itemList.get(i);
168
169                     if( null != item.title && null != item.link ) {
170                         JPanel JavaDoc panel = new JPanel JavaDoc( new GridBagLayout JavaDoc() );
171                         panel.setOpaque( false );
172                         int row = 0;
173                         if( item.dateTime != null) {
174                             JLabel JavaDoc label = new JLabel JavaDoc();
175                             label.setFont( RSS_DESCRIPTION_FONT );
176                             label.setForeground( Utils.getColor(RSS_DATETIME_COLOR) );
177                             label.setText( formatDateTime( item.dateTime ) );
178                             panel.add( label, new GridBagConstraints JavaDoc(0,row++,1,1,0.0,0.0,
179                                     GridBagConstraints.WEST,GridBagConstraints.NONE,
180                                     new Insets JavaDoc(0,TEXT_INSETS_LEFT+5,2,TEXT_INSETS_RIGHT),0,0 ) );
181                         }
182
183                         WebLink linkButton = new WebLink( item.title, item.link, true );
184                         linkButton.getAccessibleContext().setAccessibleName(
185                                 BundleSupport.getAccessibilityName( "WebLink", item.title ) ); //NOI18N
186
linkButton.getAccessibleContext().setAccessibleDescription(
187                                 BundleSupport.getAccessibilityDescription( "WebLink", item.link ) ); //NOI18N
188
linkButton.setFont( HEADER_FONT );
189                         panel.add( linkButton, new GridBagConstraints JavaDoc(0,row++,1,1,1.0,1.0,
190                                 GridBagConstraints.WEST,GridBagConstraints.NONE,
191                                 new Insets JavaDoc(0,5,2,TEXT_INSETS_RIGHT),0,0 ) );
192
193
194                         if (item.description != null) {
195                             JLabel JavaDoc label = new JLabel JavaDoc();
196                             label.setFont( RSS_DESCRIPTION_FONT );
197                             label.setText( "<html>"+trimHtml( item.description ) ); // NOI18N
198
panel.add( label, new GridBagConstraints JavaDoc(0,row++,1,1,1.0,1.0,
199                                     GridBagConstraints.WEST,GridBagConstraints.BOTH,
200                                     new Insets JavaDoc(0,TEXT_INSETS_LEFT+5,0,TEXT_INSETS_RIGHT),0,0 ) );
201                         }
202
203                         contentPanel.add( panel, new GridBagConstraints JavaDoc(0,contentRow++,1,1,1.0,1.0,
204                                 GridBagConstraints.NORTHWEST,GridBagConstraints.BOTH,
205                                 new Insets JavaDoc(contentRow==1 ? UNDER_HEADER_MARGIN : 0,0,16,0),0,0 ) );
206                     }
207                 }
208
209                 SwingUtilities.invokeLater( new Runnable JavaDoc() {
210                     public void run() {
211                         setContent( contentPanel );
212                     }
213                 });
214
215                 //schedule feed reload
216
reloadTimer = RequestProcessor.getDefault().post( this, RSS_FEED_TIMER_RELOAD_MILLIS );
217
218             } catch( UnknownHostException JavaDoc uhE ) {
219                 SwingUtilities.invokeLater( new Runnable JavaDoc() {
220                     public void run() {
221                         setContent( buildProxyPanel() );
222                     }
223                 });
224             } catch( SocketException JavaDoc sE ) {
225                 SwingUtilities.invokeLater( new Runnable JavaDoc() {
226                     public void run() {
227                         setContent( buildProxyPanel() );
228                     }
229                 });
230             } catch( IOException JavaDoc ioE ) {
231                 SwingUtilities.invokeLater( new Runnable JavaDoc() {
232                     public void run() {
233                         setContent( buildProxyPanel() );
234                     }
235                 });
236             } catch( Exception JavaDoc e ) {
237                 SwingUtilities.invokeLater( new Runnable JavaDoc() {
238                     public void run() {
239                         setContent( buildErrorLabel() );
240                     }
241                 });
242                 ErrorManager.getDefault().notify( ErrorManager.INFORMATIONAL, e );
243             }
244         }
245     }
246     
247     protected static String JavaDoc getTextContent(Node JavaDoc node) {
248         Node JavaDoc child = node.getFirstChild();
249         if( null == child )
250             return null;
251         
252         return child.getNodeValue();
253     }
254
255     protected String JavaDoc formatDateTime( String JavaDoc strDateTime ) {
256         try {
257             Date JavaDoc date = parsingDateFormat.parse( strDateTime );
258             return printingDateFormat.format( date );
259         } catch( NumberFormatException JavaDoc nfE ) {
260             //ignore
261
} catch( ParseException JavaDoc pE ) {
262             try {
263                 Date JavaDoc date = parsingDateFormatShort.parse( strDateTime );
264                 return printingDateFormatShort.format( date );
265             } catch( NumberFormatException JavaDoc nfE ) {
266                 //ignore
267
} catch( ParseException JavaDoc otherPE ) {
268                 //ignore
269
}
270         }
271         return strDateTime;
272     }
273     
274     private static final long serialVersionUID = 1L;
275
276     public Dimension JavaDoc getPreferredSize() {
277         Dimension JavaDoc retValue = super.getPreferredSize();
278         retValue.width = 1;
279         retValue.height = 1;
280         return retValue;
281     }
282     
283     public void removeNotify() {
284         //cancel reload timer
285
if( null != reloadTimer ) {
286             reloadTimer.cancel();
287             reloadTimer = null;
288         }
289         super.removeNotify();
290     }
291
292     public void addNotify() {
293         super.addNotify();
294         if( null == reloadTimer && !Boolean.getBoolean("netbeans.full.hack")) {
295             if( System.currentTimeMillis() - lastReload >= RSS_FEED_TIMER_RELOAD_MILLIS ) {
296                 reload();
297             } else {
298                 reloadTimer = RequestProcessor.getDefault().post( new Reload(),
299                         (int)(RSS_FEED_TIMER_RELOAD_MILLIS - (System.currentTimeMillis() - lastReload)) );
300             }
301         }
302     }
303
304     private String JavaDoc trimHtml( String JavaDoc htmlSnippet ) {
305         String JavaDoc res = htmlSnippet.replaceAll( "<[^>]*>", "" ); // NOI18N // NOI18N
306
res = res.replaceAll( "&nbsp;", " " ); // NOI18N // NOI18N
307
res = res.trim();
308         int maxLen = getMaxDecsriptionLength();
309         if( res.length() > maxLen ) {
310             res = res.substring( 0, maxLen ) + "..."; // NOI18N
311
}
312         return res;
313     }
314     
315     protected int getMaxDecsriptionLength() {
316         int verticalSize = Toolkit.getDefaultToolkit().getScreenSize().height;
317         if( verticalSize >= 1200 )
318             return 350;
319         if( verticalSize >= 1024 )
320             return 220;
321         return 140;
322     }
323
324     protected Component JavaDoc getContentHeader() {
325         return null;
326     }
327
328     private JComponent JavaDoc buildProxyPanel() {
329         Component JavaDoc header = getContentHeader();
330         JPanel JavaDoc panel = null == header ? new JPanel JavaDoc(new GridBagLayout JavaDoc()) : new NoHorizontalScrollPanel();
331         panel.setOpaque( false );
332
333         int row = 0;
334         if( null != header ) {
335             panel.add( header, new GridBagConstraints JavaDoc(0,row++,1,1,1.0,0.0,
336                     GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets JavaDoc(0,0,0,0),0,0 ) );
337         }
338
339         panel.add( new JLabel JavaDoc(BundleSupport.getLabel("ErrCannotConnect")), // NOI18N
340
new GridBagConstraints JavaDoc(0,row++,1,1,0.0,0.0,
341                 GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets JavaDoc(5,10,10,5),0,0 ) );
342         if( showProxyButton ) {
343             JButton JavaDoc button = new JButton JavaDoc();
344             Mnemonics.setLocalizedText( button, BundleSupport.getLabel( "ProxyConfig" ) ); // NOI18N
345
button.setOpaque( false );
346             button.addActionListener( new ActionListener JavaDoc() {
347                 public void actionPerformed(ActionEvent JavaDoc e) {
348                     HttpProxySettings.getDefault().showConfigurationDialog();
349                 }
350             });
351             panel.add( button, new GridBagConstraints JavaDoc(0,row++,1,1,0.0,0.0,
352                     GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets JavaDoc(5,10,10,5),0,0 ) );
353         }
354         return panel;
355     }
356
357     private JComponent JavaDoc buildContentLoadingLabel() {
358         JLabel JavaDoc label = new JLabel JavaDoc( BundleSupport.getLabel( "ContentLoading" ) ); // NOI18N
359
label.setHorizontalAlignment( JLabel.CENTER );
360         label.setVerticalAlignment( JLabel.CENTER );
361         label.setForeground( Utils.getColor(DEFAULT_TEXT_COLOR) );
362         label.setBackground( Utils.getColor(DEFAULT_BACKGROUND_COLOR) );
363         label.setOpaque( false );
364         Component JavaDoc header = getContentHeader();
365         if( null != header ) {
366             JPanel JavaDoc panel = new NoHorizontalScrollPanel();
367             panel.setOpaque( false );
368             panel.add( header, new GridBagConstraints JavaDoc(0,0,1,1,1.0,1.0,
369                 GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets JavaDoc(0,0,0,0),0,0 ) );
370             panel.add( label, new GridBagConstraints JavaDoc(0,1,1,1,1.0,1.0,
371                 GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets JavaDoc(0,0,0,0),0,0 ) );
372             return panel;
373         }
374         return label;
375     }
376
377     private JComponent JavaDoc buildErrorLabel() {
378         Component JavaDoc header = getContentHeader();
379         JPanel JavaDoc panel = null == header ? new JPanel JavaDoc(new GridBagLayout JavaDoc()) : new NoHorizontalScrollPanel();
380         panel.setOpaque( false );
381
382         int row = 0;
383         if( null != header ) {
384             panel.add( header, new GridBagConstraints JavaDoc(0,row++,1,1,1.0,0.0,
385                     GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets JavaDoc(0,0,0,0),0,0 ) );
386         }
387
388         panel.add( new JLabel JavaDoc(BundleSupport.getLabel("ErrLoadingFeed")), // NOI18N
389
new GridBagConstraints JavaDoc(0,row++,1,1,0.0,0.0,
390                 GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets JavaDoc(5,10,10,5),0,0 ) );
391         JButton JavaDoc button = new JButton JavaDoc();
392         Mnemonics.setLocalizedText( button, BundleSupport.getLabel( "Reload" ) ); // NOI18N
393
button.setOpaque( false );
394         button.addActionListener( new ActionListener JavaDoc() {
395             public void actionPerformed(ActionEvent JavaDoc e) {
396                 reload();
397             }
398         });
399         panel.add( button, new GridBagConstraints JavaDoc(0,row++,1,1,0.0,0.0,
400                 GridBagConstraints.CENTER,GridBagConstraints.NONE,new Insets JavaDoc(5,10,10,5),0,0 ) );
401         return panel;
402     }
403
404     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
405         if( HttpProxySettings.PROXY_SETTINGS.equals( evt.getPropertyName() ) ) {
406             setViewportView( buildContentLoadingLabel() );
407             reload();
408         }
409     }
410
411     static class FeedHandler implements ContentHandler JavaDoc {
412         private FeedItem currentItem;
413         private StringBuffer JavaDoc textBuffer;
414         private ArrayList JavaDoc<FeedItem> itemList = new ArrayList JavaDoc<FeedItem>( 10 );
415
416         public void setDocumentLocator(Locator JavaDoc locator) {
417         }
418
419         public void startDocument() throws SAXException JavaDoc {
420         }
421
422         public void endDocument() throws SAXException JavaDoc {
423         }
424
425         public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) throws SAXException JavaDoc {
426         }
427
428         public void endPrefixMapping(String JavaDoc prefix) throws SAXException JavaDoc {
429         }
430
431         public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc atts) throws SAXException JavaDoc {
432             if( itemList.size() < NEWS_COUNT ) {
433                 if( "item".equals( localName ) ) { // NOI18N
434
currentItem = new FeedItem();
435                 } else if( "link".equals( localName ) // NOI18N
436
|| "pubDate".equals( localName ) // NOI18N
437
|| "date".equals( localName ) // NOI18N
438
|| "description".equals( localName ) // NOI18N
439
|| "title".equals( localName ) ) { // NOI18N
440
textBuffer = new StringBuffer JavaDoc( 110 );
441                 }
442             }
443         }
444
445         public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
446             if( itemList.size() < NEWS_COUNT ) {
447                 if( "item".equals( localName ) ) { // NOI18N
448
if( null != currentItem && currentItem.isValid() ) {
449                         itemList.add( currentItem );
450                     }
451                     currentItem = null;
452                 } else if( null != currentItem && null != textBuffer ) {
453                     String JavaDoc text = textBuffer.toString().trim();
454                     textBuffer = null;
455                     if( 0 == text.length() )
456                         text = null;
457
458                     if( "link".equals( localName ) ) { // NOI18N
459
currentItem.link = text;
460                     } else if( "pubDate".equals( localName ) // NOI18N
461
|| "date".equals( localName ) ) { // NOI18N
462
currentItem.dateTime = text;
463                     } else if( "title".equals( localName ) ) { // NOI18N
464
currentItem.title = text;
465                     } else if( "description".equals( localName ) ) { // NOI18N
466
currentItem.description = text;
467                     }
468                 }
469             }
470         }
471
472         public void characters(char[] ch, int start, int length) throws SAXException JavaDoc {
473             if( null != textBuffer )
474                 textBuffer.append( ch, start, length );
475         }
476
477         public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException JavaDoc {
478         }
479
480         public void processingInstruction(String JavaDoc target, String JavaDoc data) throws SAXException JavaDoc {
481         }
482
483         public void skippedEntity(String JavaDoc name) throws SAXException JavaDoc {
484         }
485
486         public ArrayList JavaDoc<FeedItem> getItemList() {
487             return itemList;
488         }
489     }
490
491     static class FeedItem {
492         String JavaDoc title;
493         String JavaDoc link;
494         String JavaDoc description;
495         String JavaDoc dateTime;
496
497         boolean isValid() {
498             return null != title && null != link;
499         }
500     }
501 }
502
Popular Tags