* Added browser like links (Ctrl+Mouseclick on identifier; same as F3 shortcut)
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.news / src / net / sourceforge / phpeclipse / news / Channel.java
1 package net.sourceforge.phpeclipse.news;
2
3 import java.io.InputStream;
4 import java.io.PushbackInputStream;
5 import java.net.URL;
6 import java.net.URLConnection;
7 import java.net.UnknownHostException;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10
11 import javax.xml.parsers.DocumentBuilder;
12 import javax.xml.parsers.DocumentBuilderFactory;
13
14 import org.eclipse.core.runtime.Preferences;
15 import org.w3c.dom.Document;
16 import org.w3c.dom.Element;
17 import org.w3c.dom.NodeList;
18 import org.xml.sax.InputSource;
19
20 /**
21  * @author jnegre - http://www.jnegre.org/
22  *
23  * (c)Copyright 2002 Jérôme Nègre
24  * 
25  */
26 public class Channel {
27
28     private final String url;
29     private final String title;
30
31     private boolean refreshing = false;
32     private String errorMessage = null;
33     private boolean unread = false;
34     
35     private ArrayList items = new ArrayList();
36     private HashSet readUids = null;
37
38     /**
39      * Constructor for Channel.
40      */
41     public Channel(String title, String url) {
42         this(title, url, null);
43     }
44
45     public Channel(String title, String url, HashSet readUids) {
46         this.title = title;
47         this.url = url;
48         this.readUids = readUids;
49     }
50
51
52     public void update() {
53         update(Plugin.getDefault().getPluginPreferences());
54     }
55
56
57     public void update(Preferences prefs) {
58             ArrayList newItems = new ArrayList();
59             String newErrorMessage = null;
60         try {
61             
62             URLConnection conn = new URL(url).openConnection();
63             conn.setRequestProperty("User-Agent", Plugin.userAgent);
64             if(prefs.getBoolean(Plugin.FORCE_CACHE_PREFERENCE)) {
65                 conn.setRequestProperty("Pragma", "no-cache");
66                         conn.setRequestProperty("Cache-Control", "no-cache");
67             }
68             InputStream stream = conn.getInputStream();
69             
70             /* workaround a bug of crimson (it seems to ignore the encoding
71              * if it does not get it the first time it reads bytes from
72              * the stream. We use a PushbackInputStream to be sure that the
73              * encoding declaration is in the buffer)
74              */
75             PushbackInputStream pbStream = new PushbackInputStream(stream,64);
76             byte[] buffer = new byte[64];
77             int pos = 0;
78             while(pos != 64) {
79                 pos += pbStream.read(buffer, pos, 64-pos);
80             }
81             pbStream.unread(buffer);
82             //end workaround
83             
84             DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
85             InputSource inputSource = new InputSource(pbStream);
86             Document doc = parser.parse(inputSource);
87             pbStream.close();
88             NodeList itemNodes = doc.getElementsByTagName("item");
89             for (int i = 0; i < itemNodes.getLength(); i++) {
90                 Item aNewItem = new Item(this, (Element) itemNodes.item(i));
91                 if(aNewItem.isBanned()) continue;
92                 if(readUids!=null && readUids.remove(aNewItem.getUID())) {
93                         aNewItem.setReadFlag(true);
94                 }
95                 int indexOld = items.indexOf(aNewItem);
96                 if(indexOld != -1) {
97                     newItems.add(items.get(indexOld));
98                 } else {
99                     newItems.add(aNewItem);
100                 }
101                 
102             }
103             this.readUids = null;
104         } catch(UnknownHostException e) {
105           // no connection to internet
106         } catch(Exception e) {
107             newErrorMessage = e.toString();
108             Plugin.logInfo("Error in channel update",e);
109         }
110         
111         synchronized(this) {
112             this.errorMessage = newErrorMessage;
113             if(newErrorMessage == null) {
114                 this.items = newItems;
115                 computeUnRead();
116             }
117         }
118     }
119
120     /**
121      * Returns the url.
122      * @return String
123      */
124     public String getUrl() {
125         return url;
126     }
127
128     /**
129      * Returns the errorMessage.
130      * @return String
131      */
132     public synchronized String getErrorMessage() {
133         return errorMessage;
134     }
135
136     /**
137      * Returns the items.
138      * @return ArrayList
139      */
140     public synchronized ArrayList getItems() {
141         return new ArrayList(items);
142     }
143
144     /**
145      * @see java.lang.Object#toString()
146      */
147     public String toString() {
148         return "Channel at "+url;
149     }
150
151     /**
152      * Returns the title.
153      * @return String
154      */
155     public String getTitle() {
156         return title;
157     }
158
159     /**
160      * Returns the refreshing.
161      * @return boolean
162      */
163     public boolean isRefreshing() {
164         return refreshing;
165     }
166
167     /**
168      * Sets the refreshing.
169      * @param refreshing The refreshing to set
170      */
171     public void setRefreshing(boolean refreshing) {
172         this.refreshing = refreshing;
173     }
174
175     /**
176      * Returns the unread.
177      * @return boolean
178      */
179     public boolean isUnread() {
180         return unread;
181     }
182
183     public synchronized void computeUnRead() {
184         this.unread = false;
185         for (int i = 0; i < items.size(); i++) {
186             this.unread = this.unread || !((Item)items.get(i)).isReadFlag();
187         }
188     }
189     
190     public String getUID() {
191         return "CHA" + url;
192     }
193
194 }