package net.oni2.aeinstaller.backend.depot; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.UnknownHostException; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.Vector; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import net.oni2.aeinstaller.backend.Paths; import net.oni2.aeinstaller.backend.Settings; import net.oni2.aeinstaller.backend.depot.model.File; import net.oni2.aeinstaller.backend.depot.model.Node; import net.oni2.aeinstaller.backend.depot.model.NodeField_Body; import net.oni2.aeinstaller.backend.depot.model.NodeField_Upload; import net.oni2.aeinstaller.backend.depot.model.NodeMod; import net.oni2.aeinstaller.backend.depot.model.TaxonomyTerm; import net.oni2.aeinstaller.backend.depot.model.TaxonomyVocabulary; import net.oni2.aeinstaller.backend.network.FileDownloader; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.StaxDriver; /** * @author Christian Illy */ public class DepotManager { private static DepotManager instance = loadFromFile(); private HashMap taxonomyVocabulary = new HashMap(); private HashMap taxonomyTerms = new HashMap(); private HashMap nodes = new HashMap(); private HashMap> nodesByType = new HashMap>(); private HashMap files = new HashMap(); private int vocabId_type = -1; private int vocabId_platform = -1; private int vocabId_instmethod = -1; /** * @return Singleton instance */ public static DepotManager getInstance() { return instance; } /** * Update local Depot information cache */ public void updateInformation() { try { java.io.File zipName = new java.io.File(Paths.getDownloadPath(), "jsoncache.zip"); FileDownloader fd = new FileDownloader(DepotConfig.getDepotUrl() + "jsoncache/jsoncache.zip?ts=" + (new Date().getTime() / 1000), zipName); fd.start(); while (fd.getState() != net.oni2.aeinstaller.backend.network.FileDownloader.EState.FINISHED) { Thread.sleep(50); } ZipFile zf = null; try { zf = new ZipFile(zipName); for (Enumeration e = zf.entries(); e .hasMoreElements();) { ZipEntry ze = e.nextElement(); if (!ze.isDirectory()) { BufferedReader input = new BufferedReader( new InputStreamReader(zf.getInputStream(ze))); StringBuffer json = new StringBuffer(); char data[] = new char[1024]; int dataRead; while ((dataRead = input.read(data, 0, 1024)) != -1) { json.append(data, 0, dataRead); } if (ze.getName().toLowerCase().contains("vocabulary")) { initVocabulary(new JSONArray(json.toString())); } if (ze.getName().toLowerCase().contains("terms")) { initTerms(new JSONArray(json.toString())); } if (ze.getName().toLowerCase().contains("nodes")) { initNodes(new JSONArray(json.toString())); } if (ze.getName().toLowerCase().contains("files")) { initFiles(new JSONArray(json.toString())); } } } } finally { if (zf != null) zf.close(); zipName.delete(); } vocabId_type = getVocabulary( DepotConfig.getVocabularyName_ModType()).getVid(); vocabId_platform = getVocabulary( DepotConfig.getVocabularyName_Platform()).getVid(); vocabId_instmethod = getVocabulary( DepotConfig.getVocabularyName_InstallType()).getVid(); saveToFile(); } catch (JSONException e) { e.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } private void initFiles(JSONArray ja) throws JSONException { files = new HashMap(); JSONObject jo; for (int i = 0; i < ja.length(); i++) { jo = ja.getJSONObject(i); int fid = jo.getInt("fid"); File f = new File(jo); files.put(fid, f); } } private void initNodes(JSONArray ja) throws JSONException { nodes = new HashMap(); nodesByType = new HashMap>(); JSONObject jo; for (int i = 0; i < ja.length(); i++) { jo = ja.getJSONObject(i); int nid = jo.getInt("nid"); String type = jo.getString("type"); Node n = null; if (type.equalsIgnoreCase(DepotConfig.getNodeType_Mod())) n = new NodeMod(jo); else n = new Node(jo); nodes.put(nid, n); if (!nodesByType.containsKey(type)) nodesByType.put(type, new HashMap()); nodesByType.get(type).put(nid, n); } } private void initTerms(JSONArray ja) throws JSONException { taxonomyTerms.clear(); JSONObject jo; for (int i = 0; i < ja.length(); i++) { jo = ja.getJSONObject(i); TaxonomyTerm tt = new TaxonomyTerm(jo); taxonomyTerms.put(tt.getTid(), tt); } } private void initVocabulary(JSONArray ja) throws JSONException { taxonomyVocabulary.clear(); JSONObject jo; for (int i = 0; i < ja.length(); i++) { jo = ja.getJSONObject(i); TaxonomyVocabulary tv = new TaxonomyVocabulary(jo); taxonomyVocabulary.put(tv.getVid(), tv); } } /** * @return Can we connect to the Depot? */ public boolean checkConnection() { HttpRequestBase httpQuery = null; try { DefaultHttpClient httpclient = new DefaultHttpClient(); httpQuery = new HttpHead(DepotConfig.getDepotUrl()); HttpResponse response = httpclient.execute(httpQuery); int code = response.getStatusLine().getStatusCode(); return (code >= 200) && (code <= 299); } catch (UnknownHostException e) { } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (httpQuery != null) httpQuery.releaseConnection(); } return false; } private TaxonomyVocabulary getVocabulary(String name) { for (TaxonomyVocabulary v : taxonomyVocabulary.values()) { if (v.getName().equalsIgnoreCase(name)) return v; } return null; } /** * @param vocabId * Get all taxonomy terms of a given vocabulary * @return TaxTerms */ private Vector getTaxonomyTermsByVocabulary(int vocabId) { Vector res = new Vector(); for (TaxonomyTerm t : taxonomyTerms.values()) { if (t.getVid() == vocabId) res.add(t); } return res; } /** * @return All defined types */ public Vector getTypes() { return getTaxonomyTermsByVocabulary(getVocabIdType()); } /** * @param id * Get taxonomy term by given ID * @return TaxTerm */ public TaxonomyTerm getTaxonomyTerm(int id) { return taxonomyTerms.get(id); } /** * Get all nodes of given node type * * @param nodeType * Node type * @return Nodes of type nodeType */ public Vector getNodesByType(String nodeType) { return new Vector(nodesByType.get(nodeType).values()); } /** * @return Mod-Nodes */ public Vector getModPackageNodes() { Vector result = new Vector(); String instMethName = DepotConfig.getTaxonomyName_InstallType_Package(); Vector files = getNodesByType(DepotConfig.getNodeType_Mod()); for (Node n : files) { if (n instanceof NodeMod) { NodeMod nm = (NodeMod) n; if (nm.getInstallMethod().getName() .equalsIgnoreCase(instMethName)) result.add(nm); } } return result; } /** * @return VocabId of Platform vocabulary */ public int getVocabIdPlatform() { return vocabId_platform; } /** * @return VocabId of Install method vocabulary */ public int getVocabIdInstMethod() { return vocabId_instmethod; } /** * @return VocabId of Type vocabulary */ public int getVocabIdType() { return vocabId_type; } /** * @param id * ID of file to get * @return the file */ public File getFile(int id) { return files.get(id); } /** * Print stats about nodes and files */ public void printStats() { System.out.println("Nodes by type:"); for (String t : nodesByType.keySet()) { System.out.println(" " + t + ": " + nodesByType.get(t).size()); } System.out.println("Files: " + files.size()); } private static XStream getXStream() { XStream xs = new XStream(new StaxDriver()); xs.alias("Depot", DepotManager.class); xs.alias("File", net.oni2.aeinstaller.backend.depot.model.File.class); xs.alias("Node", Node.class); xs.alias("NodeField_Body", NodeField_Body.class); xs.alias("NodeField_Upload", NodeField_Upload.class); xs.alias("NodeMod", NodeMod.class); xs.alias("TaxonomyTerm", TaxonomyTerm.class); xs.alias("TaxonomyVocabulary", TaxonomyVocabulary.class); return xs; } /** * Save Depot cache instance to file */ private void saveToFile() { try { FileOutputStream fos = new FileOutputStream( Settings.getDepotCacheFilename()); XStream xs = getXStream(); xs.toXML(this, fos); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private static DepotManager loadFromFile() { try { FileInputStream fis = new FileInputStream( Settings.getDepotCacheFilename()); XStream xs = getXStream(); Object obj = xs.fromXML(fis); fis.close(); if (obj instanceof DepotManager) return (DepotManager) obj; } catch (FileNotFoundException e) { } catch (IOException e) { } return new DepotManager(); } }