/* This file is part of JFLICKS. JFLICKS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JFLICKS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JFLICKS. If not, see <http://www.gnu.org/licenses/>. */ package org.jflicks.update.system; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jflicks.util.BundleFilter; import org.jflicks.util.Util; /** * * @author Doug Barnum * @version 1.0 */ public final class BundleTree { private static BundleTree instance; private BundleItem bundleItems; /** * Default empty constructor. */ private BundleTree() { } public static BundleTree getInstance() { if (instance == null) { instance = new BundleTree(); } return (instance); } private WhenSize getWhenSize(String urlstr) { WhenSize result = null; if (urlstr != null) { try { URL url = new URL(urlstr); URLConnection conn = url.openConnection(); result = new WhenSize(conn.getLastModified(), (long) conn.getContentLength()); } catch (IOException ex) { System.out.println("Warning: " + ex.getMessage()); } } return (result); } private boolean isNewerURL(File f, String url) { boolean result = false; if ((f != null) && (url != null)) { WhenSize ws = getWhenSize(url); if (ws != null) { result = (f.lastModified() < ws.getWhen()); /* if (result) { // Ok the file is newer. But we want to assume the // file is the same if it's the same size. Looks like // the compiler/jar program sometimes makes the file // off by a byte or two even though no code has changed. // This could be something like a date in the MANIFEST // using the day of the week or something. Whatever we // will assume if there are many code changes then the // file size will be much different. long size = ws.getSize(); if (size != -1L) { result = Math.abs(f.length() - size) > 2L; } } */ } } return (result); } private boolean isNewBundle(String name, File[] array) { boolean result = true; if ((name != null) && (array != null) && (array.length > 0)) { for (int i = 0; i < array.length; i++) { if (name.equals(array[i].getName())) { result = false; break; } } } return (result); } private BundleItem create(Element e) { BundleItem result = null; if (e != null) { String name = e.getAttributeValue("name"); if (name != null) { boolean feature = Util.str2boolean( e.getAttributeValue("feature"), false); result = new BundleItem(); result.setName(name.trim()); result.setFeature(feature); List list = e.getChildren("needs"); if ((list != null) && (list.size() > 0)) { ArrayList<String> nlist = new ArrayList<String>(); for (int i = 0; i < list.size(); i++) { Element nelement = (Element) list.get(i); if (nelement != null) { name = nelement.getAttributeValue("name"); if (name != null) { nlist.add(name.trim()); } } } if (nlist.size() > 0) { String[] ary = nlist.toArray(new String[nlist.size()]); result.setNeedNames(ary); } } } } return (result); } private BundleItem[] parse(String url) { BundleItem[] result = null; if (url != null) { url = url + "bundletree.xml"; SAXBuilder builder = new SAXBuilder(); builder.setValidation(false); builder.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd", false); try { Document doc = builder.build(url); if (doc != null) { Element root = doc.getRootElement(); if (root != null) { List children = root.getChildren("bundle"); if ((children != null) && (children.size() > 0)) { ArrayList<BundleItem> blist = new ArrayList<BundleItem>(); for (int i = 0; i < children.size(); i++) { BundleItem bi = create((Element) children.get(i)); if (bi != null) { blist.add(bi); } } if (blist.size() > 0) { result = blist.toArray(new BundleItem[blist.size()]); } } } } } catch (JDOMException ex) { result = null; } catch (IOException ex) { result = null; } } return (result); } private BundleItem find(String name, BundleItem[] array) { BundleItem result = null; if ((name != null) && (array != null) && (array.length > 0)) { for (int i = 0; i < array.length; i++) { if (name.equals(array[i].getName())) { result = array[i]; break; } } } return (result); } private void aggregate(ArrayList<String> l, String name, BundleItem[] array) { if ((l != null) && (name != null) && (array != null)) { if (!l.contains(name)) { l.add(name); } BundleItem bi = find(name, array); if (bi != null) { String[] needs = bi.getNeedNames(); if ((needs != null) && (needs.length > 0)) { for (int i = 0; i < needs.length; i++) { aggregate(l, needs[i], array); } } } } } public File[] check(String dir, String sourceURL) { File[] result = null; File fdir = new File(dir); if ((fdir != null) && (fdir.isDirectory()) && (sourceURL != null)) { File[] bundles = fdir.listFiles(new BundleFilter()); if ((bundles != null) && (bundles.length > 0)) { // We have bundles to compare... if (!sourceURL.endsWith("/")) { sourceURL = sourceURL + "/"; } ArrayList<File> newer = new ArrayList<File>(); for (int i = 0; i < bundles.length; i++) { String name = bundles[i].getName(); if (name != null) { String turl = sourceURL + name; if (isNewerURL(bundles[i], turl)) { newer.add(bundles[i]); System.out.println(turl + " is newer"); } } } if (newer.size() > 0) { // If anything is new we have to check each one to // see if any have new dependencies. We look for // a bundletree.xml file up at the sourceURL. BundleItem[] biarray = parse(sourceURL); if ((biarray != null) && (biarray.length > 0)) { ArrayList<String> namelist = new ArrayList<String>(); for (int i = 0; i < newer.size(); i++) { String name = newer.get(i).getName(); if (name != null) { name = name.substring(0, name.indexOf(".jar")); aggregate(namelist, name, biarray); } } // Name list should have all unique dependents. for (int i = 0; i < namelist.size(); i++) { String bunname = namelist.get(i) + ".jar"; if (isNewBundle(bunname, bundles)) { File newone = new File(fdir, bunname); newer.add(newone); } } } result = newer.toArray(new File[newer.size()]); } } } return (result); } private class WhenSize { private long when; private long size; public WhenSize(long when, long size) { setWhen(when); setSize(size); } public long getWhen() { return (when); } private void setWhen(long l) { when = l; } public long getSize() { return (size); } private void setSize(long l) { size = l; } } public static void main(String[] args) { String dir = "bundle"; String sourceURL = "http://www.jflicks.org/repository/"; for (int i = 0; i < args.length; i += 2) { if (args[i].equalsIgnoreCase("-dir")) { dir = args[i + 1]; } else if (args[i].equalsIgnoreCase("-sourceURL")) { sourceURL = args[i + 1]; } } BundleTree bt = BundleTree.getInstance(); bt.check(dir, sourceURL); } }