1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.robsite.extension.rss;
18
19 import java.io.InputStream;
20 import java.util.ArrayList;
21
22 import java.util.Map;
23 import javax.swing.Timer;
24 import javax.swing.event.ChangeEvent;
25 import javax.swing.event.ChangeListener;
26 import oracle.ide.Ide;
27 import oracle.ide.IdeAction;
28 import oracle.ide.IdeEvent;
29 import oracle.ide.IdeListener;
30 import oracle.ide.MenuConstants;
31 import oracle.ide.addin.Addin;
32 import oracle.ide.addin.Controller;
33 import oracle.ide.docking.DockStation;
34 import oracle.ide.panels.Navigable;
35
36 import oracle.javatools.Environment;
37
38 import org.robsite.extension.rss.model.Channels;
39
40 /***
41 * The RSS News Reader extension.
42 *
43 * @author brian_duff@sourceforge.net
44 * @version $Revision: 1.1.1.1 $
45 */
46 public class NewsFeedExtension implements Addin
47 {
48 public static final String VIEW_ID = "RSSNewsWindow";
49 static final String PREFS_KEY = "newsFeedPrefs";
50
51 private ArrayList _changeListeners = new ArrayList();
52 private static NewsFeedExtension s_instance;
53 private NewsDockableWindow _dockableWindow;
54
55 private ResHelper _res = new ResHelper( "Extension" );
56
57 /***
58 * The runnable that actually checks news.
59 */
60 private NewsCheckRunnable _checkRunnable;
61
62 /***
63 * The timer that notifies the news check runnable to wake up and check
64 * news periodically.
65 */
66 private Timer _timer;
67
68
69
70 /***
71 * Get the singleton news feed extension.
72 *
73 * @return get the only instance of this extension class. May return null
74 * if the extension has not been initialized.
75 */
76 public static NewsFeedExtension get()
77 {
78 return s_instance;
79 }
80
81 /***
82 * Get the news dockable window.
83 *
84 * @return the news dockable window. This may be null if the window has
85 * never been shown or is currently not visible.
86 */
87 public synchronized NewsDockableWindow getNewsDockable()
88 {
89 return _dockableWindow;
90 }
91
92 /***
93 * Set the news dockable window. This is used only by the news dockable
94 * window itself to notify the extension when the window is visible.
95 *
96 * @param newsDockable the news dockable.
97 */
98 synchronized void setNewsDockable( NewsDockableWindow newsDockable )
99 {
100 _dockableWindow = newsDockable;
101
102 if ( newsDockable != null && _checkRunnable != null )
103 {
104 _checkRunnable.forceUpdate();
105 }
106 }
107
108 /***
109 * Get the preferences object.
110 *
111 * @return preferences.
112 */
113 public NewsFeedPreferences getPreferences()
114 {
115 NewsFeedPreferences prefs = (NewsFeedPreferences)
116 Ide.getSettings().getData( PREFS_KEY );
117
118 if ( prefs == null )
119 {
120 prefs = new NewsFeedPreferences();
121 prefs.setCheckDelaySeconds( 600 );
122 prefs.setHTTPTimeout( 3000 );
123 prefs.setCheckAutomatically( true );
124 prefs.setSyncChannels( true );
125 prefs.setCheckOnStartup( true );
126 prefs.setDirectoryURL( "http://otn.oracle.com/products/jdev/htdocs/partners/addins/exchange/rss/newsdirectory.xml" );
127
128 Ide.getSettings().putData( PREFS_KEY, prefs );
129 }
130
131 return prefs;
132 }
133
134 public Channels getChannels()
135 {
136 return getPreferences().getChannels();
137 }
138
139 /***
140 * Start (or restart) the timer which periodically updates.
141 */
142 private void restartTimer()
143 {
144 if ( _timer != null )
145 {
146 _timer.stop();
147 _timer = null;
148 }
149
150 if ( getPreferences().isCheckAutomatically() )
151 {
152 _timer = new Timer(
153 getPreferences().getCheckDelaySeconds() * 1000,
154 _checkRunnable
155 );
156 _timer.setRepeats( true );
157 _timer.start();
158 }
159 }
160
161
162
163
164
165 public void initialize()
166 {
167 s_instance = this;
168
169
170 Ide.getVersionInfo().addComponent(
171 NewsFeedExtension.class.getPackage().getSpecificationTitle(),
172 NewsFeedExtension.class.getPackage().getImplementationVersion()
173 );
174
175
176
177 DockStation.getDockStation().registerDockableFactory(
178 VIEW_ID, new NewsDockableFactory()
179 );
180
181 getPreferences();
182
183
184 Ide.getSettings().registerUI(
185 new Navigable( _res.getRes( "PreferencesName" ),
186 NewsFeedPreferencesPanel.class ) );
187
188
189
190
191
192 NewsFeedController controller = new NewsFeedController();
193
194 createAction( controller, Commands.VIEW_NEWS_DOCKABLE,
195 "org.robsite.extension.rss.ViewNewsDockableCommand",
196 _res.getRes( "CheckRSSNews" ),
197 _res.getRes( "CheckRSSNewsMnemonic" ).charAt( 0 )
198 );
199
200 createAction( controller, Commands.VIEW_NEWS_DOCKABLE_VIEW,
201 "org.robsite.extension.rss.ViewNewsDockableCommand",
202 _res.getRes( "RSSNews" ),
203 _res.getRes( "RSSNewsMnemonic" ).charAt( 0 )
204 );
205
206 createAction( controller, Commands.MARK_AS_READ,
207 "org.robsite.extension.rss.MarkAsReadCommand",
208 _res.getRes( "MarkAsRead" ),
209 _res.getRes( "MarkAsReadMnemonic" ).charAt( 0 )
210 );
211
212 createAction( controller, Commands.OPEN_IN_BROWSER,
213 "org.robsite.extension.rss.OpenInBrowserCommand",
214 _res.getRes( "OpenInBrowser" ),
215 _res.getRes( "OpenInBrowserMnemonic" ).charAt( 0 )
216 );
217
218
219
220 Ide.getMenubar().add(
221 Ide.getMenubar().createMenuItem(
222 Commands.getAction( Commands.VIEW_NEWS_DOCKABLE )
223 ),
224 Environment.getJMenu( Ide.getMainWindow().MENU_HELP ),
225 MenuConstants.SECTION_HELP_UPDATES
226 );
227
228
229
230 Ide.getMenubar().add(
231 Ide.getMenubar().createMenuItem(
232 Commands.getAction( Commands.VIEW_NEWS_DOCKABLE_VIEW )
233 ),
234 Environment.getJMenu( Ide.getMainWindow().MENU_VIEW ),
235 MenuConstants.SECTION_VIEW_ADDINS
236 );
237
238
239
240
241
242
243
244
245 Ide.addIdeListener( new IdeListener() {
246 public void mainWindowClosing( IdeEvent ideEvent ) {}
247 public void mainWindowOpened( IdeEvent ideEvent )
248 {
249 try
250 {
251 _checkRunnable = new NewsCheckRunnable( NewsFeedExtension.this );
252 Thread t = new Thread( _checkRunnable, "RSS News Check Thread" );
253 t.start();
254
255
256
257 if ( getPreferences().isCheckOnStartup() )
258 {
259 _checkRunnable.forceUpdate();
260 }
261
262 restartTimer();
263
264
265
266 getPreferences().addChangeListener( new ChangeListener() {
267 public void stateChanged( ChangeEvent ce )
268 {
269 restartTimer();
270
271
272
273 _checkRunnable.forceUpdate();
274 }
275 });
276 }
277 finally
278 {
279
280 Ide.removeIdeListener( this );
281 }
282 }
283 public void addinsLoaded( IdeEvent ideEvent ) {}
284 });
285
286 }
287
288 public void shutdown()
289 {
290 s_instance = null;
291 }
292
293 public float version()
294 {
295
296
297 return 9.0517f;
298 }
299
300 public float ideVersion()
301 {
302
303 return 0;
304 }
305
306 public boolean canShutdown()
307 {
308 return true;
309 }
310
311
312
313
314 /***
315 * Utility method to create and register an IDE action.
316 *
317 * @param controller the controller to associate with the action
318 * @param id the command name for the action.
319 * @param commandClass the command class for the action.
320 * @param label the label for the action.
321 * @param mnemonic the mnemonic for the action.
322 */
323 private void createAction(
324 Controller controller, String id, String commandClass, String label,
325 int mnemonic )
326 {
327
328
329
330
331
332 IdeAction.get(
333 Commands.id( id ),
334 commandClass,
335 label,
336 null,
337 new Integer( mnemonic ),
338 null,
339 null,
340 true
341 ).addController( controller );
342 }
343 }