Report every found version.
[jSite.git] / src / de / todesbaum / jsite / gui / UpdateChecker.java
1 /*
2  * jSite-remote - UpdateChecker.java -
3  * Copyright © 2008 David Roden
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
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 de.todesbaum.jsite.gui;
21
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Properties;
27
28 import javax.swing.JFrame;
29
30 import de.todesbaum.jsite.application.Freenet7Interface;
31 import de.todesbaum.jsite.main.Main;
32 import de.todesbaum.jsite.main.Version;
33 import de.todesbaum.util.freenet.fcp2.Client;
34 import de.todesbaum.util.freenet.fcp2.ClientGet;
35 import de.todesbaum.util.freenet.fcp2.Connection;
36 import de.todesbaum.util.freenet.fcp2.Message;
37 import de.todesbaum.util.freenet.fcp2.Persistence;
38 import de.todesbaum.util.freenet.fcp2.ReturnType;
39 import de.todesbaum.util.freenet.fcp2.Verbosity;
40 import de.todesbaum.util.io.Closer;
41
42 /**
43  * Checks for newer versions of jSite.
44  *
45  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
46  */
47 public class UpdateChecker implements Runnable {
48
49         /** Counter for connection names. */
50         private static int counter = 0;
51
52         /** The edition for the update check URL. */
53         private static final int UPDATE_EDITION = 0;
54
55         /** The URL for update checks. */
56         private static final String UPDATE_KEY = "USK@e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE";
57
58         /** Object used for synchronization. */
59         private final Object syncObject = new Object();
60
61         /** Update listeners. */
62         private final List<UpdateListener> updateListeners = new ArrayList<UpdateListener>();
63
64         /** Whether the main thread should stop. */
65         private boolean shouldStop = false;
66
67         /** Current last found edition of update key. */
68         private int lastUpdateEdition = UPDATE_EDITION;
69
70         /** Last found version. */
71         private Version lastVersion = Main.getVersion();
72
73         /** The parent of the dialog. */
74         private final JFrame parent;
75
76         /** The freenet interface. */
77         private final Freenet7Interface freenetInterface;
78
79         /**
80          * Creates a new update checker that uses the given frame as its parent and
81          * communications via the given freenet interface.
82          *
83          * @param parent
84          *            The parent of the dialog
85          * @param freenetInterface
86          *            The freenet interface
87          */
88         public UpdateChecker(JFrame parent, Freenet7Interface freenetInterface) {
89                 this.parent = parent;
90                 this.freenetInterface = freenetInterface;
91         }
92
93         //
94         // EVENT LISTENER MANAGEMENT
95         //
96
97         public void addUpdateListener(UpdateListener updateListener) {
98                 updateListeners.add(updateListener);
99         }
100
101         public void removeUpdateListener(UpdateListener updateListener) {
102                 updateListeners.remove(updateListener);
103         }
104
105         protected void fireUpdateFound(Version foundVersion, long versionTimestamp) {
106                 for (UpdateListener updateListener : updateListeners) {
107                         updateListener.foundUpdateData(foundVersion, versionTimestamp);
108                 }
109         }
110
111         //
112         // ACTIONS
113         //
114
115         public void start() {
116                 new Thread(this).start();
117         }
118
119         public void stop() {
120                 synchronized (syncObject) {
121                         shouldStop = true;
122                         syncObject.notifyAll();
123                 }
124         }
125
126         //
127         // PRIVATE METHODS
128         //
129
130         private boolean shouldStop() {
131                 synchronized (syncObject) {
132                         return shouldStop;
133                 }
134         }
135
136         private String constructUpdateKey(int edition) {
137                 return UPDATE_KEY + "/jSite/" + edition + "/jSite.properties";
138         }
139
140         //
141         // INTERFACE Runnable
142         //
143
144         public void run() {
145                 Connection connection = freenetInterface.getConnection("jSite-" + ++counter + "-UpdateChecker");
146                 try {
147                         connection.connect();
148                 } catch (IOException e1) {
149                         e1.printStackTrace();
150                 }
151                 Client client = new Client(connection);
152                 boolean checkNow = false;
153                 int currentEdition = lastUpdateEdition;
154                 while (!shouldStop()) {
155                         checkNow = false;
156                         System.out.println("Trying " + constructUpdateKey(currentEdition));
157                         ClientGet clientGet = new ClientGet("get-update-key");
158                         clientGet.setUri(constructUpdateKey(currentEdition));
159                         clientGet.setPersistence(Persistence.CONNECTION);
160                         clientGet.setReturnType(ReturnType.direct);
161                         clientGet.setVerbosity(Verbosity.ALL);
162                         try {
163                                 client.execute(clientGet);
164                                 boolean stop = false;
165                                 while (!stop) {
166                                         Message message = client.readMessage();
167                                         System.out.println(message);
168                                         if ("GetFailed".equals(message.getName())) {
169                                                 if ("27".equals(message.get("code"))) {
170                                                         String editionString = message.get("redirecturi").split("/")[2];
171                                                         int editionNumber = -1;
172                                                         try {
173                                                                 editionNumber = Integer.parseInt(editionString);
174                                                         } catch (NumberFormatException nfe1) {
175                                                                 /* ignore. */
176                                                         }
177                                                         if (editionNumber != -1) {
178                                                                 System.out.println("Found new edition " + editionNumber);
179                                                                 currentEdition = editionNumber;
180                                                                 lastUpdateEdition = editionNumber;
181                                                                 checkNow = true;
182                                                                 break;
183                                                         }
184                                                 }
185                                         }
186                                         if ("AllData".equals(message.getName())) {
187                                                 System.out.println("Update data found.");
188                                                 InputStream dataInputStream = null;
189                                                 Properties properties = new Properties();
190                                                 try {
191                                                         dataInputStream = message.getPayloadInputStream();
192                                                         properties.load(dataInputStream);
193                                                 } finally {
194                                                         Closer.close(dataInputStream);
195                                                 }
196
197                                                 String foundVersionString = properties.getProperty("jSite.Version");
198                                                 if (foundVersionString != null) {
199                                                         Version foundVersion = Version.parse(foundVersionString);
200                                                         if (foundVersion != null) {
201                                                                 lastVersion = foundVersion;
202                                                                 String versionTimestampString = properties.getProperty("jSite.Date");
203                                                                 System.out.println(versionTimestampString);
204                                                                 long versionTimestamp = -1;
205                                                                 try {
206                                                                         versionTimestamp = Long.parseLong(versionTimestampString);
207                                                                 } catch (NumberFormatException nfe1) {
208                                                                         /* ignore. */
209                                                                 }
210                                                                 fireUpdateFound(foundVersion, versionTimestamp);
211                                                                 stop = true;
212                                                                 checkNow = true;
213                                                                 ++currentEdition;
214                                                         }
215                                                 }
216                                         }
217                                 }
218                         } catch (IOException e) {
219                                 System.out.println("Got IOException: " + e.getMessage());
220                                 e.printStackTrace();
221                         }
222                         if (!checkNow && !shouldStop()) {
223                                 synchronized (syncObject) {
224                                         try {
225                                                 syncObject.wait(15 * 60 * 1000);
226                                         } catch (InterruptedException ie1) {
227                                                 /* ignore. */
228                                         }
229                                 }
230                         }
231                 }
232         }
233 }