1 |
package net.oni2.aeinstaller.backend.depot; |
2 |
|
3 |
import java.io.BufferedReader; |
4 |
import java.io.FileInputStream; |
5 |
import java.io.FileNotFoundException; |
6 |
import java.io.FileOutputStream; |
7 |
import java.io.IOException; |
8 |
import java.io.InputStreamReader; |
9 |
import java.io.UnsupportedEncodingException; |
10 |
import java.net.UnknownHostException; |
11 |
import java.util.Date; |
12 |
import java.util.Enumeration; |
13 |
import java.util.HashMap; |
14 |
import java.util.Vector; |
15 |
import java.util.zip.ZipEntry; |
16 |
import java.util.zip.ZipFile; |
17 |
|
18 |
import net.oni2.aeinstaller.backend.Paths; |
19 |
import net.oni2.aeinstaller.backend.depot.model.File; |
20 |
import net.oni2.aeinstaller.backend.depot.model.Node; |
21 |
import net.oni2.aeinstaller.backend.depot.model.NodeField_Body; |
22 |
import net.oni2.aeinstaller.backend.depot.model.NodeField_Upload; |
23 |
import net.oni2.aeinstaller.backend.depot.model.NodeMod; |
24 |
import net.oni2.aeinstaller.backend.depot.model.TaxonomyTerm; |
25 |
import net.oni2.aeinstaller.backend.depot.model.TaxonomyVocabulary; |
26 |
import net.oni2.aeinstaller.backend.network.FileDownloader; |
27 |
|
28 |
import org.apache.http.HttpResponse; |
29 |
import org.apache.http.client.methods.HttpHead; |
30 |
import org.apache.http.client.methods.HttpRequestBase; |
31 |
import org.apache.http.impl.client.DefaultHttpClient; |
32 |
import org.json.JSONArray; |
33 |
import org.json.JSONException; |
34 |
import org.json.JSONObject; |
35 |
|
36 |
import com.thoughtworks.xstream.XStream; |
37 |
import com.thoughtworks.xstream.io.xml.StaxDriver; |
38 |
|
39 |
/** |
40 |
* @author Christian Illy |
41 |
*/ |
42 |
public class DepotManager { |
43 |
private static DepotManager instance = loadFromFile(); |
44 |
|
45 |
private HashMap<Integer, TaxonomyVocabulary> taxonomyVocabulary = new HashMap<Integer, TaxonomyVocabulary>(); |
46 |
private HashMap<Integer, TaxonomyTerm> taxonomyTerms = new HashMap<Integer, TaxonomyTerm>(); |
47 |
|
48 |
private HashMap<Integer, Node> nodes = new HashMap<Integer, Node>(); |
49 |
private HashMap<String, HashMap<Integer, Node>> nodesByType = new HashMap<String, HashMap<Integer, Node>>(); |
50 |
|
51 |
private HashMap<Integer, File> files = new HashMap<Integer, File>(); |
52 |
|
53 |
private int vocabId_type = -1; |
54 |
private int vocabId_platform = -1; |
55 |
private int vocabId_instmethod = -1; |
56 |
|
57 |
/** |
58 |
* @return Singleton instance |
59 |
*/ |
60 |
public static DepotManager getInstance() { |
61 |
return instance; |
62 |
} |
63 |
|
64 |
/** |
65 |
* Update local Depot information cache |
66 |
*/ |
67 |
public void updateInformation() { |
68 |
try { |
69 |
java.io.File zipName = new java.io.File(Paths.getDownloadPath(), |
70 |
"jsoncache.zip"); |
71 |
FileDownloader fd = new FileDownloader(DepotConfig.getDepotUrl() |
72 |
+ "jsoncache/jsoncache.zip?ts=" |
73 |
+ (new Date().getTime() / 1000), zipName); |
74 |
fd.start(); |
75 |
while (fd.getState() != net.oni2.aeinstaller.backend.network.FileDownloader.EState.FINISHED) { |
76 |
Thread.sleep(50); |
77 |
} |
78 |
|
79 |
ZipFile zf = null; |
80 |
try { |
81 |
zf = new ZipFile(zipName); |
82 |
for (Enumeration<? extends ZipEntry> e = zf.entries(); e |
83 |
.hasMoreElements();) { |
84 |
ZipEntry ze = e.nextElement(); |
85 |
if (!ze.isDirectory()) { |
86 |
BufferedReader input = new BufferedReader( |
87 |
new InputStreamReader(zf.getInputStream(ze))); |
88 |
StringBuffer json = new StringBuffer(); |
89 |
|
90 |
char data[] = new char[1024]; |
91 |
int dataRead; |
92 |
while ((dataRead = input.read(data, 0, 1024)) != -1) { |
93 |
json.append(data, 0, dataRead); |
94 |
} |
95 |
|
96 |
if (ze.getName().toLowerCase().contains("vocabulary")) { |
97 |
initVocabulary(new JSONArray(json.toString())); |
98 |
} |
99 |
if (ze.getName().toLowerCase().contains("terms")) { |
100 |
initTerms(new JSONArray(json.toString())); |
101 |
} |
102 |
if (ze.getName().toLowerCase().contains("nodes")) { |
103 |
initNodes(new JSONArray(json.toString())); |
104 |
} |
105 |
if (ze.getName().toLowerCase().contains("files")) { |
106 |
initFiles(new JSONArray(json.toString())); |
107 |
} |
108 |
} |
109 |
} |
110 |
} finally { |
111 |
if (zf != null) |
112 |
zf.close(); |
113 |
zipName.delete(); |
114 |
} |
115 |
|
116 |
vocabId_type = getVocabulary( |
117 |
DepotConfig.getVocabularyName_ModType()).getVid(); |
118 |
vocabId_platform = getVocabulary( |
119 |
DepotConfig.getVocabularyName_Platform()).getVid(); |
120 |
vocabId_instmethod = getVocabulary( |
121 |
DepotConfig.getVocabularyName_InstallType()).getVid(); |
122 |
|
123 |
saveToFile(); |
124 |
} catch (JSONException e) { |
125 |
e.printStackTrace(); |
126 |
} catch (IOException e1) { |
127 |
e1.printStackTrace(); |
128 |
} catch (InterruptedException e) { |
129 |
e.printStackTrace(); |
130 |
} |
131 |
} |
132 |
|
133 |
private void initFiles(JSONArray ja) throws JSONException { |
134 |
files = new HashMap<Integer, File>(); |
135 |
JSONObject jo; |
136 |
for (int i = 0; i < ja.length(); i++) { |
137 |
jo = ja.getJSONObject(i); |
138 |
int fid = jo.getInt("fid"); |
139 |
|
140 |
File f = new File(jo); |
141 |
files.put(fid, f); |
142 |
} |
143 |
} |
144 |
|
145 |
private void initNodes(JSONArray ja) throws JSONException { |
146 |
nodes = new HashMap<Integer, Node>(); |
147 |
nodesByType = new HashMap<String, HashMap<Integer, Node>>(); |
148 |
JSONObject jo; |
149 |
for (int i = 0; i < ja.length(); i++) { |
150 |
jo = ja.getJSONObject(i); |
151 |
|
152 |
int nid = jo.getInt("nid"); |
153 |
String type = jo.getString("type"); |
154 |
|
155 |
Node n = null; |
156 |
if (type.equalsIgnoreCase(DepotConfig.getNodeType_Mod())) |
157 |
n = new NodeMod(jo); |
158 |
else |
159 |
n = new Node(jo); |
160 |
|
161 |
nodes.put(nid, n); |
162 |
if (!nodesByType.containsKey(type)) |
163 |
nodesByType.put(type, new HashMap<Integer, Node>()); |
164 |
nodesByType.get(type).put(nid, n); |
165 |
} |
166 |
} |
167 |
|
168 |
private void initTerms(JSONArray ja) throws JSONException { |
169 |
taxonomyTerms.clear(); |
170 |
JSONObject jo; |
171 |
for (int i = 0; i < ja.length(); i++) { |
172 |
jo = ja.getJSONObject(i); |
173 |
TaxonomyTerm tt = new TaxonomyTerm(jo); |
174 |
taxonomyTerms.put(tt.getTid(), tt); |
175 |
} |
176 |
} |
177 |
|
178 |
private void initVocabulary(JSONArray ja) throws JSONException { |
179 |
taxonomyVocabulary.clear(); |
180 |
JSONObject jo; |
181 |
for (int i = 0; i < ja.length(); i++) { |
182 |
jo = ja.getJSONObject(i); |
183 |
TaxonomyVocabulary tv = new TaxonomyVocabulary(jo); |
184 |
taxonomyVocabulary.put(tv.getVid(), tv); |
185 |
} |
186 |
} |
187 |
|
188 |
/** |
189 |
* @return Can we connect to the Depot? |
190 |
*/ |
191 |
public boolean checkConnection() { |
192 |
HttpRequestBase httpQuery = null; |
193 |
|
194 |
try { |
195 |
DefaultHttpClient httpclient = new DefaultHttpClient(); |
196 |
httpQuery = new HttpHead(DepotConfig.getDepotUrl()); |
197 |
|
198 |
HttpResponse response = httpclient.execute(httpQuery); |
199 |
|
200 |
int code = response.getStatusLine().getStatusCode(); |
201 |
|
202 |
return (code >= 200) && (code <= 299); |
203 |
} catch (UnknownHostException e) { |
204 |
} catch (UnsupportedEncodingException e) { |
205 |
e.printStackTrace(); |
206 |
} catch (IOException e) { |
207 |
e.printStackTrace(); |
208 |
} finally { |
209 |
if (httpQuery != null) |
210 |
httpQuery.releaseConnection(); |
211 |
} |
212 |
return false; |
213 |
} |
214 |
|
215 |
private TaxonomyVocabulary getVocabulary(String name) { |
216 |
for (TaxonomyVocabulary v : taxonomyVocabulary.values()) { |
217 |
if (v.getName().equalsIgnoreCase(name)) |
218 |
return v; |
219 |
} |
220 |
return null; |
221 |
} |
222 |
|
223 |
/** |
224 |
* @param vocabId |
225 |
* Get all taxonomy terms of a given vocabulary |
226 |
* @return TaxTerms |
227 |
*/ |
228 |
private Vector<TaxonomyTerm> getTaxonomyTermsByVocabulary(int vocabId) { |
229 |
Vector<TaxonomyTerm> res = new Vector<TaxonomyTerm>(); |
230 |
for (TaxonomyTerm t : taxonomyTerms.values()) { |
231 |
if (t.getVid() == vocabId) |
232 |
res.add(t); |
233 |
} |
234 |
return res; |
235 |
} |
236 |
|
237 |
/** |
238 |
* @return All defined types |
239 |
*/ |
240 |
public Vector<TaxonomyTerm> getTypes() { |
241 |
return getTaxonomyTermsByVocabulary(getVocabIdType()); |
242 |
} |
243 |
|
244 |
/** |
245 |
* @param id |
246 |
* Get taxonomy term by given ID |
247 |
* @return TaxTerm |
248 |
*/ |
249 |
public TaxonomyTerm getTaxonomyTerm(int id) { |
250 |
return taxonomyTerms.get(id); |
251 |
} |
252 |
|
253 |
/** |
254 |
* Get all nodes of given node type |
255 |
* |
256 |
* @param nodeType |
257 |
* Node type |
258 |
* @return Nodes of type nodeType |
259 |
*/ |
260 |
public Vector<Node> getNodesByType(String nodeType) { |
261 |
return new Vector<Node>(nodesByType.get(nodeType).values()); |
262 |
} |
263 |
|
264 |
/** |
265 |
* @return Mod-Nodes |
266 |
*/ |
267 |
public Vector<NodeMod> getModPackageNodes() { |
268 |
Vector<NodeMod> result = new Vector<NodeMod>(); |
269 |
String instMethName = DepotConfig.getTaxonomyName_InstallType_Package(); |
270 |
|
271 |
Vector<Node> files = getNodesByType(DepotConfig.getNodeType_Mod()); |
272 |
for (Node n : files) { |
273 |
if (n instanceof NodeMod) { |
274 |
NodeMod nm = (NodeMod) n; |
275 |
if (nm.getInstallMethod().getName() |
276 |
.equalsIgnoreCase(instMethName)) { |
277 |
try { |
278 |
nm.getPackageNumber(); |
279 |
result.add(nm); |
280 |
} catch (NumberFormatException e) { |
281 |
System.err.println("Node " + nm.getNid() |
282 |
+ " does not have a package number!!!"); |
283 |
} |
284 |
} |
285 |
} |
286 |
} |
287 |
return result; |
288 |
} |
289 |
|
290 |
/** |
291 |
* @return VocabId of Platform vocabulary |
292 |
*/ |
293 |
public int getVocabIdPlatform() { |
294 |
return vocabId_platform; |
295 |
} |
296 |
|
297 |
/** |
298 |
* @return VocabId of Install method vocabulary |
299 |
*/ |
300 |
public int getVocabIdInstMethod() { |
301 |
return vocabId_instmethod; |
302 |
} |
303 |
|
304 |
/** |
305 |
* @return VocabId of Type vocabulary |
306 |
*/ |
307 |
public int getVocabIdType() { |
308 |
return vocabId_type; |
309 |
} |
310 |
|
311 |
/** |
312 |
* @param id |
313 |
* ID of file to get |
314 |
* @return the file |
315 |
*/ |
316 |
public File getFile(int id) { |
317 |
return files.get(id); |
318 |
} |
319 |
|
320 |
/** |
321 |
* Print stats about nodes and files |
322 |
*/ |
323 |
public void printStats() { |
324 |
System.out.println("Nodes by type:"); |
325 |
for (String t : nodesByType.keySet()) { |
326 |
System.out.println(" " + t + ": " + nodesByType.get(t).size()); |
327 |
} |
328 |
|
329 |
System.out.println("Files: " + files.size()); |
330 |
} |
331 |
|
332 |
private static XStream getXStream() { |
333 |
XStream xs = new XStream(new StaxDriver()); |
334 |
xs.alias("Depot", DepotManager.class); |
335 |
xs.alias("File", net.oni2.aeinstaller.backend.depot.model.File.class); |
336 |
xs.alias("Node", Node.class); |
337 |
xs.alias("NodeField_Body", NodeField_Body.class); |
338 |
xs.alias("NodeField_Upload", NodeField_Upload.class); |
339 |
xs.alias("NodeMod", NodeMod.class); |
340 |
xs.alias("TaxonomyTerm", TaxonomyTerm.class); |
341 |
xs.alias("TaxonomyVocabulary", TaxonomyVocabulary.class); |
342 |
return xs; |
343 |
} |
344 |
|
345 |
/** |
346 |
* Save Depot cache instance to file |
347 |
*/ |
348 |
private void saveToFile() { |
349 |
try { |
350 |
FileOutputStream fos = new FileOutputStream( |
351 |
Paths.getDepotCacheFilename()); |
352 |
XStream xs = getXStream(); |
353 |
xs.toXML(this, fos); |
354 |
fos.close(); |
355 |
} catch (FileNotFoundException e) { |
356 |
e.printStackTrace(); |
357 |
} catch (IOException e) { |
358 |
e.printStackTrace(); |
359 |
} |
360 |
} |
361 |
|
362 |
private static DepotManager loadFromFile() { |
363 |
try { |
364 |
FileInputStream fis = new FileInputStream( |
365 |
Paths.getDepotCacheFilename()); |
366 |
XStream xs = getXStream(); |
367 |
Object obj = xs.fromXML(fis); |
368 |
fis.close(); |
369 |
if (obj instanceof DepotManager) |
370 |
return (DepotManager) obj; |
371 |
} catch (FileNotFoundException e) { |
372 |
} catch (IOException e) { |
373 |
} |
374 |
return new DepotManager(); |
375 |
} |
376 |
} |