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