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.Enumeration; import java.util.HashMap; import java.util.HashSet; 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.Settings.Platform; 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.mods.ECompatiblePlatform; import net.oni2.aeinstaller.backend.network.FileDownloader; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; 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 = new DepotManager(); 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 * * @param forceRefreshAll * Force refreshing all data, even if it seems to be cached */ public void updateInformation(boolean forceRefreshAll) { taxonomyTerms.clear(); taxonomyVocabulary.clear(); nodes = new HashMap(); nodesByType = new HashMap>(); files = new HashMap(); try { java.io.File zipName = new java.io.File(Paths.getDownloadPath(), "jsoncache.zip"); FileDownloader fd = new FileDownloader(DepotConfig.getDepotUrl() + "jsoncache/jsoncache.zip", 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(); } catch (JSONException e) { e.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } private void initFiles(JSONArray ja) throws JSONException { 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 { 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 { 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 { 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 HttpGet(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; } /** * @return All TaxVocabs */ public Vector getVocabulary() { return new Vector(taxonomyVocabulary.values()); } /** * @param id * Get taxonomy vocabulary by given ID * @return TaxVocab */ public TaxonomyVocabulary getVocabulary(int id) { return taxonomyVocabulary.get(id); } /** * @param name * Get taxonomy vocabulary by given name * @return TaxVocab */ public 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 */ public Vector getTaxonomyTermsByVocabulary(int vocabId) { Vector res = new Vector(); for (TaxonomyTerm t : taxonomyTerms.values()) { if (t.getVid() == vocabId) res.add(t); } return res; } /** * @param id * Get taxonomy term by given ID * @return TaxTerm */ public TaxonomyTerm getTaxonomyTerm(int id) { return taxonomyTerms.get(id); } /** * @param name * Get taxonomy term by given name * @return TaxTerm */ public TaxonomyTerm getTaxonomyTerm(String name) { for (TaxonomyTerm t : taxonomyTerms.values()) { if (t.getName().equalsIgnoreCase(name)) return t; } return null; } /** * 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()); } /** * Get a node by node id * * @param id * Node id * @return Node */ public Node getNodeById(int id) { return nodes.get(id); } /** * Get a Mod-Node by a given package number * * @param packageNumber * Package number to find * @return The Mod-Node or null */ public NodeMod getNodeByPackageNumber(int packageNumber) { Vector files = getNodesByType(DepotConfig.getNodeType_Mod()); for (Node n : files) { if (n instanceof NodeMod) { NodeMod nm = (NodeMod) n; if (nm.getPackageNumber() == packageNumber) return nm; } } return null; } /** * @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; } /** * @param node * Node to check validity on * @param platform * Platform to check against * @return True if valid on platform */ public boolean isModValidOnPlatform(NodeMod node, Settings.Platform platform) { ECompatiblePlatform plat = node.getPlatform(); switch (plat) { case BOTH: return true; case WIN: return (platform == Platform.WIN) || (platform == Platform.LINUX); case MACOS: return (platform == Platform.MACOS); } return false; } /** * Checks if the given mod-node is of the given mod-type(s) * * @param node * Node to check * @param type * Type(s) to check * @param or * If false check if all given types are included in node. If * true checks if either of the given types is included. * @return True if of given type(s) */ public boolean isModOfType(NodeMod node, HashSet type, boolean or) { boolean matching = !or; HashSet terms = node.getTypes(); for (int t : type) { if (or) matching |= terms.contains(t); else matching &= terms.contains(t); } return matching; } /** * @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 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 * * @param f * File to write to */ public void saveToFile(java.io.File f) { try { FileOutputStream fos = new FileOutputStream(f); XStream xs = getXStream(); xs.toXML(this, fos); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * Load Depot cache instance from file * * @param f * File to read from */ public void loadFromFile(java.io.File f) { try { FileInputStream fis = new FileInputStream(f); XStream xs = getXStream(); Object obj = xs.fromXML(fis); if (obj instanceof DepotManager) instance = (DepotManager) obj; fis.close(); } catch (FileNotFoundException e) { } catch (IOException e) { } } }