View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.plugin.news;
21  
22  import java.io.InputStream;
23  import java.text.DateFormat;
24  import java.text.SimpleDateFormat;
25  import java.util.Locale;
26  import java.util.StringTokenizer;
27  import java.util.Vector;
28  
29  import javax.swing.Action;
30  import javax.swing.SwingUtilities;
31  
32  import net.n3.nanoxml.IXMLElement;
33  import net.n3.nanoxml.IXMLParser;
34  import net.n3.nanoxml.IXMLReader;
35  import net.n3.nanoxml.StdXMLReader;
36  import net.n3.nanoxml.XMLParserFactory;
37  
38  import org.apache.log4j.Logger;
39  import org.xnap.gui.XNapFrame;
40  import org.xnap.gui.action.PluginDialogAction;
41  import org.xnap.net.HttpConnection;
42  import org.xnap.plugin.AbstractPlugin;
43  import org.xnap.plugin.PluginInfo;
44  import org.xnap.plugin.PluginManager;
45  import org.xnap.util.Scheduler;
46  import org.xnap.util.VersionParser;
47  import org.xnap.util.XNapTask;
48  
49  /***
50   * Provides a plugin fetching xnaps release news.  */
51  public class NewsPlugin extends AbstractPlugin 
52  {
53  	//--- Constant(s) ---
54  	public static final String XNAP_NEWS_FEED = "http://sourceforge.net/export/rss2_projnews.php?group_id=9285&rss_fulltext=1";
55  
56  	//--- Data field(s) ---
57  
58      private static Logger logger = Logger.getLogger(NewsPlugin.class);
59      private static NewsPlugin instance;	
60  	private static DateFormat dateFormatter
61  		= new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
62  	private XNapTask updateTask;
63  	private NewsPanel newsPanel;
64  	
65  	//--- Constructor(s) ---
66  
67      public NewsPlugin()
68  	{
69  	}
70  
71      //--- Method(s) ---
72  
73      public static NewsPlugin getInstance()
74      {
75  		return instance;
76      }
77  
78      /***
79       * Starts the plugin.
80       */
81      public void start() 
82      {
83  		instance = this;
84      }
85  
86      /***
87       * Starts the GUI of the plugin.
88       */
89      public void startGUI()
90      {
91      	newsPanel = new NewsPanel();
92      	XNapFrame.getInstance().getSearchPanel().setLogoPanel(newsPanel);	
93      	
94  		// fetch feed immediately and update every 12 hours
95      	updateTask = new UpdateTask();
96      	Scheduler.run(0, 12 * 60 * 60 * 1000, updateTask);
97  	}
98  
99  
100 	/***
101      * Stops the plugin. Disposes all singletons.
102      */
103     public void stop()
104     {
105 		instance = null;
106     }
107 
108     /***
109      * Stops the GUI of the plugin.
110      */
111     public void stopGUI()
112     {
113     	updateTask.cancel();
114     	updateTask = null;
115 
116     	XNapFrame.getInstance().getSearchPanel().setLogoPanel(null);
117     	newsPanel = null;
118     }
119 
120 	/***
121 	 * Fetches the XNap news feed. */
122 	private void fetchFeed()
123 	{
124 		try {
125 			HttpConnection conn = new HttpConnection();
126 			conn.connect(XNAP_NEWS_FEED);
127 			InputStream in = conn.getInputStream();
128 			IXMLParser parser = XMLParserFactory.createDefaultXMLParser();
129 			IXMLReader reader = new StdXMLReader(in);
130 			parser.setReader(reader);
131 
132 			IXMLElement xml = (IXMLElement)parser.parse();
133 			Vector items
134 				= xml.getFirstChildNamed("channel").getChildrenNamed("item");
135 
136 			for (int i=0; i < items.size(); i++) {
137 				IXMLElement xitem = ((IXMLElement)items.get(i));
138 				String title = xitem.getFirstChildNamed("title").getContent();
139 				if (isAlreadyInstalled(title)) {
140 					continue;
141 				}
142 
143 				final DefaultNewsItem item = new DefaultNewsItem();			
144 				if (title != null) {
145 					item.setTitle(title);
146 				}
147 				if (xitem.getFirstChildNamed("description") != null) {
148 					item.setDescription(xitem.getFirstChildNamed("description").getContent());
149 				}
150 				if (xitem.getFirstChildNamed("author") != null) {
151 					String s = xitem.getFirstChildNamed("author").getContent();
152 					// remove email address part
153 					int j = s.indexOf("@");
154 					item.setAuthor((j != -1) ? s.substring(0, j) : s);
155 				}
156 				if (xitem.getFirstChildNamed("link") != null) {
157 					item.setLink(xitem.getFirstChildNamed("link").getContent());
158 				}
159 				if (xitem.getFirstChildNamed("pubDate") != null) {
160 					item.setDate(dateFormatter.parse(xitem.getFirstChildNamed("pubDate").getContent()));
161 				}
162 				
163 				// new core release
164 				item.setActions(new Action[] { new PluginDialogAction() });						
165 
166 				Runnable runner = new Runnable()
167 					{
168 						public void run()
169 						{							
170 							newsPanel.add(item);
171 						}
172 					};
173 				SwingUtilities.invokeLater(runner);
174 			}
175 
176 		} 
177 		catch (Exception e) {
178 			logger.debug("Could not fetch the news feed.", e);
179 		}
180 	}
181 
182 	private boolean isAlreadyInstalled(String title)
183 	{
184 		if (title == null || title.indexOf("released") == -1) {
185 			return false;
186 		}
187 		
188 		StringTokenizer t = new StringTokenizer(title);
189 		if (t.countTokens() == 3) {
190 			if (t.nextToken().equals("XNap")) {
191 				if (VersionParser.compare(PluginManager.getCoreVersion(),
192 										  t.nextToken()) >= 0) {
193 					// core version is already installed, do not show news
194 					if (t.nextToken().equals("released")) {
195 						return true;
196 					}
197 				}
198 			}
199 		}
200 		else if (t.countTokens() >= 4) {
201 			String plugin = t.nextToken();
202 			if (plugin.equals("XNap")) {
203 				plugin = t.nextToken();
204 			}
205 			if (t.nextToken().toLowerCase().equals("plugin")) {
206 				PluginInfo info = PluginManager.getInstance().getInfoByName(plugin);
207 				String version = t.nextToken(); 
208 				if (info != null 
209 					&& info.isEnabled() 
210 					&& VersionParser.compare(info.getVersion(), version) >= 0) {
211 					// plugin is already installed and enabled, do not show news
212 					if (t.hasMoreTokens() && t.nextToken().equals("released")) {
213 						return true;
214 					}
215 				}
216 			}
217 		}
218 
219 		return false;
220 	}
221 	
222 	private class UpdateTask extends XNapTask
223 	{
224 		public void run()
225 		{
226 			NewsPlugin.this.fetchFeed();
227 		}
228 	}
229 
230 }