source: AE/installer2/src/net/oni2/aeinstaller/backend/depot/DepotManager.java@ 623

Last change on this file since 623 was 621, checked in by alloc, 12 years ago

AEI2:

  • Added offline detection (should run without internet connection)
  • Update check (manual/on startup), not actually updating yet
File size: 13.3 KB
Line 
1package net.oni2.aeinstaller.backend.depot;
2
3import java.io.FileInputStream;
4import java.io.FileNotFoundException;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.UnsupportedEncodingException;
8import java.net.UnknownHostException;
9import java.util.HashMap;
10import java.util.HashSet;
11import java.util.Vector;
12
13import net.oni2.aeinstaller.backend.Settings;
14import net.oni2.aeinstaller.backend.Settings.Platform;
15import net.oni2.aeinstaller.backend.depot.model.File;
16import net.oni2.aeinstaller.backend.depot.model.Node;
17import net.oni2.aeinstaller.backend.depot.model.NodeField_Body;
18import net.oni2.aeinstaller.backend.depot.model.NodeField_Upload;
19import net.oni2.aeinstaller.backend.depot.model.NodeMod;
20import net.oni2.aeinstaller.backend.depot.model.TaxonomyTerm;
21import net.oni2.aeinstaller.backend.depot.model.TaxonomyVocabulary;
22import net.oni2.aeinstaller.backend.mods.ECompatiblePlatform;
23import net.oni2.aeinstaller.backend.network.DrupalJSONQuery;
24
25import org.apache.http.HttpResponse;
26import org.apache.http.client.methods.HttpGet;
27import org.apache.http.client.methods.HttpRequestBase;
28import org.apache.http.impl.client.DefaultHttpClient;
29import org.json.JSONArray;
30import org.json.JSONException;
31import org.json.JSONObject;
32
33import com.thoughtworks.xstream.XStream;
34import com.thoughtworks.xstream.io.xml.StaxDriver;
35
36/**
37 * @author Christian Illy
38 */
39public class DepotManager {
40 private static DepotManager instance = new DepotManager();
41
42 private HashMap<Integer, TaxonomyVocabulary> taxonomyVocabulary = new HashMap<Integer, TaxonomyVocabulary>();
43 private HashMap<Integer, TaxonomyTerm> taxonomyTerms = new HashMap<Integer, TaxonomyTerm>();
44
45 private HashMap<Integer, Node> nodes = new HashMap<Integer, Node>();
46 private HashMap<String, HashMap<Integer, Node>> nodesByType = new HashMap<String, HashMap<Integer, Node>>();
47
48 private HashMap<Integer, File> files = new HashMap<Integer, File>();
49
50 private int vocabId_type = -1;
51 private int vocabId_platform = -1;
52 private int vocabId_instmethod = -1;
53
54 /**
55 * @return Singleton instance
56 */
57 public static DepotManager getInstance() {
58 return instance;
59 }
60
61 /**
62 * Update local Depot information cache
63 *
64 * @param forceRefreshAll
65 * Force refreshing all data, even if it seems to be cached
66 * @param listener
67 * Listener for update status
68 */
69 public void updateInformation(boolean forceRefreshAll,
70 DepotCacheUpdateProgressListener listener) {
71 taxonomyTerms.clear();
72 taxonomyVocabulary.clear();
73
74 HashMap<Integer, Node> oldNodes = null;
75 HashMap<Integer, File> oldFiles = null;
76
77 if (forceRefreshAll) {
78 oldNodes = new HashMap<Integer, Node>();
79 oldFiles = new HashMap<Integer, File>();
80 } else {
81 oldNodes = nodes;
82 oldFiles = files;
83 }
84
85 nodes = new HashMap<Integer, Node>();
86 nodesByType = new HashMap<String, HashMap<Integer, Node>>();
87 files = new HashMap<Integer, File>();
88
89 try {
90 JSONArray ja;
91 JSONObject jo;
92 int page;
93
94 // Get taxonomy vocabulary
95 if (listener != null)
96 listener.cacheUpdateProgress("Updating taxonomy vocabulary", 0,
97 100);
98 page = 0;
99 do {
100 ja = DrupalJSONQuery.getIndex("taxonomy_vocabulary", page, 100);
101 for (int i = 0; i < ja.length(); i++) {
102 jo = ja.getJSONObject(i);
103 TaxonomyVocabulary tv = new TaxonomyVocabulary(jo);
104 taxonomyVocabulary.put(tv.getVid(), tv);
105 }
106 page++;
107 } while (ja.length() > 0);
108
109 // Get taxonomy terms
110 if (listener != null)
111 listener.cacheUpdateProgress("Updating taxonomy terms", 0, 100);
112 page = 0;
113 do {
114 ja = DrupalJSONQuery.getIndex("taxonomy_term", page, 100);
115 for (int i = 0; i < ja.length(); i++) {
116 jo = ja.getJSONObject(i);
117 TaxonomyTerm tt = new TaxonomyTerm(jo);
118 taxonomyTerms.put(tt.getTid(), tt);
119 }
120 page++;
121 } while (ja.length() > 0);
122
123 // Check nodes for new information
124 if (listener != null)
125 listener.cacheUpdateProgress("Checking for new/updated nodes",
126 1, 100);
127 HashSet<Integer> nodesToUpdate = new HashSet<Integer>();
128 page = 0;
129 do {
130 ja = DrupalJSONQuery.getIndex("node", page, 500);
131 for (int i = 0; i < ja.length(); i++) {
132 jo = ja.getJSONObject(i);
133 int nid = jo.getInt("nid");
134 long changedRemote = jo.getLong("changed");
135 if (oldNodes.containsKey(nid)) {
136 if (changedRemote > oldNodes.get(nid).getChanged())
137 nodesToUpdate.add(nid);
138 else {
139 Node n = oldNodes.get(nid);
140 nodes.put(nid, n);
141 if (!nodesByType.containsKey(n.getType()))
142 nodesByType.put(n.getType(),
143 new HashMap<Integer, Node>());
144 nodesByType.get(n.getType()).put(nid, n);
145 }
146 } else {
147 nodesToUpdate.add(nid);
148 }
149 }
150 page++;
151 } while (ja.length() > 0);
152
153 // Check files for new stuff
154 if (listener != null)
155 listener.cacheUpdateProgress("Checking for new/updated files",
156 2, 100);
157 HashSet<Integer> filesToUpdate = new HashSet<Integer>();
158 page = 0;
159 do {
160 ja = DrupalJSONQuery.getIndex("file", page, 500);
161 for (int i = 0; i < ja.length(); i++) {
162 jo = ja.getJSONObject(i);
163 int fid = jo.getInt("fid");
164 long changedRemote = jo.getLong("timestamp");
165 if (oldFiles.containsKey(fid)) {
166 if (changedRemote > oldFiles.get(fid).getTimestamp())
167 filesToUpdate.add(fid);
168 else
169 files.put(fid, oldFiles.get(fid));
170 } else {
171 filesToUpdate.add(fid);
172 }
173 }
174 page++;
175 } while (ja.length() > 0);
176
177 int total = nodesToUpdate.size() + filesToUpdate.size() + 3;
178 int step = 3;
179 // Update nodes with new information
180 for (int nid : nodesToUpdate) {
181 if (listener != null)
182 listener.cacheUpdateProgress("Updating nodes", step++,
183 total);
184
185 ja = DrupalJSONQuery.getItem("node", nid, "");
186 jo = ja.getJSONObject(0);
187 String type = jo.getString("type");
188
189 Node n = null;
190 if (type.equalsIgnoreCase(DepotConfig.getNodeType_Mod()))
191 n = new NodeMod(jo);
192 else
193 n = new Node(jo);
194
195 nodes.put(nid, n);
196 if (!nodesByType.containsKey(type))
197 nodesByType.put(type, new HashMap<Integer, Node>());
198 nodesByType.get(type).put(nid, n);
199 }
200
201 // Update new files
202 for (int fid : filesToUpdate) {
203 if (listener != null)
204 listener.cacheUpdateProgress("Updating files", step++,
205 total);
206
207 ja = DrupalJSONQuery.getItem("file", fid, "&file_contents=0");
208 jo = ja.getJSONObject(0);
209
210 File f = new File(jo);
211 files.put(fid, f);
212 }
213
214 vocabId_type = getVocabulary(
215 DepotConfig.getVocabularyName_ModType()).getVid();
216 vocabId_platform = getVocabulary(
217 DepotConfig.getVocabularyName_Platform()).getVid();
218 vocabId_instmethod = getVocabulary(
219 DepotConfig.getVocabularyName_InstallType()).getVid();
220 } catch (JSONException e) {
221 e.printStackTrace();
222 } catch (Exception e) {
223 System.err.println(e.getMessage());
224 e.printStackTrace();
225 }
226 }
227
228 /**
229 * @return Can we connect to the Depot?
230 */
231 public boolean checkConnection() {
232 HttpRequestBase httpQuery = null;
233
234 try {
235 DefaultHttpClient httpclient = new DefaultHttpClient();
236 httpQuery = new HttpGet(DepotConfig.getDepotUrl());
237
238 HttpResponse response = httpclient.execute(httpQuery);
239
240 int code = response.getStatusLine().getStatusCode();
241
242 return (code >= 200) && (code <= 299);
243 } catch (UnknownHostException e) {
244 } catch (UnsupportedEncodingException e) {
245 e.printStackTrace();
246 } catch (IOException e) {
247 e.printStackTrace();
248 } finally {
249 if (httpQuery != null)
250 httpQuery.releaseConnection();
251 }
252 return false;
253 }
254
255 /**
256 * @return All TaxVocabs
257 */
258 public Vector<TaxonomyVocabulary> getVocabulary() {
259 return new Vector<TaxonomyVocabulary>(taxonomyVocabulary.values());
260 }
261
262 /**
263 * @param id
264 * Get taxonomy vocabulary by given ID
265 * @return TaxVocab
266 */
267 public TaxonomyVocabulary getVocabulary(int id) {
268 return taxonomyVocabulary.get(id);
269 }
270
271 /**
272 * @param name
273 * Get taxonomy vocabulary by given name
274 * @return TaxVocab
275 */
276 public TaxonomyVocabulary getVocabulary(String name) {
277 for (TaxonomyVocabulary v : taxonomyVocabulary.values()) {
278 if (v.getName().equalsIgnoreCase(name))
279 return v;
280 }
281 return null;
282 }
283
284 /**
285 * @param vocabId
286 * Get all taxonomy terms of a given vocabulary
287 * @return TaxTerms
288 */
289 public Vector<TaxonomyTerm> getTaxonomyTermsByVocabulary(int vocabId) {
290 Vector<TaxonomyTerm> res = new Vector<TaxonomyTerm>();
291 for (TaxonomyTerm t : taxonomyTerms.values()) {
292 if (t.getVid() == vocabId)
293 res.add(t);
294 }
295 return res;
296 }
297
298 /**
299 * @param id
300 * Get taxonomy term by given ID
301 * @return TaxTerm
302 */
303 public TaxonomyTerm getTaxonomyTerm(int id) {
304 return taxonomyTerms.get(id);
305 }
306
307 /**
308 * @param name
309 * Get taxonomy term by given name
310 * @return TaxTerm
311 */
312 public TaxonomyTerm getTaxonomyTerm(String name) {
313 for (TaxonomyTerm t : taxonomyTerms.values()) {
314 if (t.getName().equalsIgnoreCase(name))
315 return t;
316 }
317 return null;
318 }
319
320 /**
321 * Get all nodes of given node type
322 *
323 * @param nodeType
324 * Node type
325 * @return Nodes of type nodeType
326 */
327 public Vector<Node> getNodesByType(String nodeType) {
328 return new Vector<Node>(nodesByType.get(nodeType).values());
329 }
330
331 /**
332 * Get a node by node id
333 *
334 * @param id
335 * Node id
336 * @return Node
337 */
338 public Node getNodeById(int id) {
339 return nodes.get(id);
340 }
341
342 /**
343 * Get a Mod-Node by a given package number
344 *
345 * @param packageNumber
346 * Package number to find
347 * @return The Mod-Node or null
348 */
349 public NodeMod getNodeByPackageNumber(int packageNumber) {
350 Vector<Node> files = getNodesByType(DepotConfig.getNodeType_Mod());
351 for (Node n : files) {
352 if (n instanceof NodeMod) {
353 NodeMod nm = (NodeMod) n;
354 if (nm.getPackageNumber() == packageNumber)
355 return nm;
356 }
357 }
358 return null;
359 }
360
361 /**
362 * @return Mod-Nodes
363 */
364 public Vector<NodeMod> getModPackageNodes() {
365 Vector<NodeMod> result = new Vector<NodeMod>();
366 String instMethName = DepotConfig.getTaxonomyName_InstallType_Package();
367
368 Vector<Node> files = getNodesByType(DepotConfig.getNodeType_Mod());
369 for (Node n : files) {
370 if (n instanceof NodeMod) {
371 NodeMod nm = (NodeMod) n;
372 if (nm.getInstallMethod().getName()
373 .equalsIgnoreCase(instMethName))
374 result.add(nm);
375 }
376 }
377 return result;
378 }
379
380 /**
381 * @param node
382 * Node to check validity on
383 * @param platform
384 * Platform to check against
385 * @return True if valid on platform
386 */
387 public boolean isModValidOnPlatform(NodeMod node, Settings.Platform platform) {
388 ECompatiblePlatform plat = node.getPlatform();
389 switch (plat) {
390 case BOTH:
391 return true;
392 case WIN:
393 return (platform == Platform.WIN)
394 || (platform == Platform.LINUX);
395 case MACOS:
396 return (platform == Platform.MACOS);
397 }
398 return false;
399 }
400
401 /**
402 * Checks if the given mod-node is of the given mod-type(s)
403 *
404 * @param node
405 * Node to check
406 * @param type
407 * Type(s) to check
408 * @param or
409 * If false check if all given types are included in node. If
410 * true checks if either of the given types is included.
411 * @return True if of given type(s)
412 */
413 public boolean isModOfType(NodeMod node, HashSet<Integer> type, boolean or) {
414 boolean matching = !or;
415 HashSet<TaxonomyTerm> terms = node.getTypes();
416
417 for (int t : type) {
418 if (or)
419 matching |= terms.contains(t);
420 else
421 matching &= terms.contains(t);
422 }
423 return matching;
424 }
425
426 /**
427 * @return VocabId of Platform vocabulary
428 */
429 public int getVocabIdPlatform() {
430 return vocabId_platform;
431 }
432
433 /**
434 * @return VocabId of Install method vocabulary
435 */
436 public int getVocabIdInstMethod() {
437 return vocabId_instmethod;
438 }
439
440 /**
441 * @return VocabId of Type vocabulary
442 */
443 public int getVocabIdType() {
444 return vocabId_type;
445 }
446
447 /**
448 * @param id
449 * ID of file to get
450 * @return the file
451 */
452 public File getFile(int id) {
453 return files.get(id);
454 }
455
456 /**
457 * Print stats about nodes and files
458 */
459 public void printStats() {
460 System.out.println("Nodes by type:");
461 for (String t : nodesByType.keySet()) {
462 System.out.println(" " + t + ": " + nodesByType.get(t).size());
463 }
464
465 System.out.println("Files: " + files.size());
466 }
467
468 private XStream getXStream() {
469 XStream xs = new XStream(new StaxDriver());
470 xs.alias("Depot", DepotManager.class);
471 xs.alias("File", net.oni2.aeinstaller.backend.depot.model.File.class);
472 xs.alias("Node", Node.class);
473 xs.alias("NodeField_Body", NodeField_Body.class);
474 xs.alias("NodeField_Upload", NodeField_Upload.class);
475 xs.alias("NodeMod", NodeMod.class);
476 xs.alias("TaxonomyTerm", TaxonomyTerm.class);
477 xs.alias("TaxonomyVocabulary", TaxonomyVocabulary.class);
478 return xs;
479 }
480
481 /**
482 * Save Depot cache instance to file
483 *
484 * @param f
485 * File to write to
486 */
487 public void saveToFile(java.io.File f) {
488 try {
489 FileOutputStream fos = new FileOutputStream(f);
490 XStream xs = getXStream();
491 xs.toXML(this, fos);
492 fos.close();
493 } catch (FileNotFoundException e) {
494 e.printStackTrace();
495 } catch (IOException e) {
496 e.printStackTrace();
497 }
498 }
499
500 /**
501 * Load Depot cache instance from file
502 *
503 * @param f
504 * File to read from
505 */
506 public void loadFromFile(java.io.File f) {
507 try {
508 FileInputStream fis = new FileInputStream(f);
509 XStream xs = getXStream();
510 Object obj = xs.fromXML(fis);
511 if (obj instanceof DepotManager)
512 instance = (DepotManager) obj;
513 fis.close();
514 } catch (FileNotFoundException e) {
515 } catch (IOException e) {
516 }
517 }
518}
Note: See TracBrowser for help on using the repository browser.