1 19 20 package org.netbeans.nbbuild; 21 22 import java.io.File ; 23 import java.io.IOException ; 24 import java.io.StringReader ; 25 import java.net.URI ; 26 import java.util.HashMap ; 27 import java.util.HashSet ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import java.util.SortedMap ; 31 import java.util.SortedSet ; 32 import java.util.TreeSet ; 33 import java.util.jar.Manifest ; 34 import org.apache.tools.ant.AntClassLoader; 35 import org.apache.tools.ant.BuildException; 36 import org.apache.tools.ant.Project; 37 import org.apache.tools.ant.Task; 38 import org.apache.tools.ant.types.Path; 39 import org.w3c.dom.Attr ; 40 import org.w3c.dom.Document ; 41 import org.w3c.dom.Element ; 42 import org.w3c.dom.NamedNodeMap ; 43 import org.w3c.dom.NodeList ; 44 import org.xml.sax.EntityResolver ; 45 import org.xml.sax.InputSource ; 46 import org.xml.sax.SAXException ; 47 48 62 public final class VerifyUpdateCenter extends Task { 63 64 public VerifyUpdateCenter() {} 65 66 private URI updates; 67 public void setUpdates(File f) { 68 updates = f.toURI(); 69 } 70 public void setUpdatesURL(URI u) { 71 updates = u; 72 } 73 74 private URI oldUpdates; 75 public void setOldUpdates(File f) { 76 if (f.isFile()) { 77 oldUpdates = f.toURI(); 78 } else { 79 log("No such file: " + f, Project.MSG_WARN); 80 } 81 } 82 public void setOldUpdatesURL(URI u) { 83 if (u.toString().length() > 0) { 84 oldUpdates = u; 85 } 86 } 87 88 private Path classpath = new Path(getProject()); 89 public void addConfiguredClasspath(Path p) { 90 classpath.append(p); 91 } 92 93 @Override 94 public void execute() throws BuildException { 95 if (updates == null) { 96 throw new BuildException("you must specify updates"); 97 } 98 ClassLoader loader = new AntClassLoader(getProject(), classpath); 99 Set <Manifest > manifests = loadManifests(updates); 100 checkForProblems(findInconsistencies(manifests, loader), "Inconsistency(ies) in " + updates); 101 log(updates + " is internally consistent", Project.MSG_INFO); 102 if (oldUpdates != null) { 103 Map <String ,Manifest > updated = new HashMap <String ,Manifest >(); 104 for (Manifest m : loadManifests(oldUpdates)) { 105 updated.put(findCNB(m), m); 106 } 107 if (!findInconsistencies(new HashSet <Manifest >(updated.values()), loader).isEmpty()) { 108 log(oldUpdates + " is already inconsistent, skipping update check", Project.MSG_WARN); 109 return; 110 } 111 SortedSet <String > updatedCNBs = new TreeSet <String >(); 112 for (Manifest m : manifests) { 113 String cnb = findCNB(m); 114 boolean doUpdate = true; 115 Manifest old = updated.get(cnb); 116 if (old != null) { 117 String oldspec = old.getMainAttributes().getValue("OpenIDE-Module-Specification-Version"); 118 String newspec = m.getMainAttributes().getValue("OpenIDE-Module-Specification-Version"); 119 doUpdate = specGreaterThan(newspec, oldspec); 120 } 121 if (doUpdate) { 122 updated.put(cnb, m); 123 updatedCNBs.add(cnb); 124 } 125 } 126 SortedMap <String ,SortedSet <String >> updateProblems = findInconsistencies(new HashSet <Manifest >(updated.values()), loader); 127 checkForProblems(updateProblems, "Inconsistency(ies) in " + updates + " relative to " + oldUpdates); 128 log(oldUpdates + " after updating " + updatedCNBs + " from " + updates + " remains consistent"); 129 } 130 } 131 132 @SuppressWarnings ("unchecked") 133 private SortedMap <String ,SortedSet <String >> findInconsistencies(Set <Manifest > manifests, ClassLoader loader) throws BuildException { 134 try { 135 return (SortedMap ) loader.loadClass("org.netbeans.ConsistencyVerifier"). 136 getMethod("findInconsistencies", Set .class).invoke(null, manifests); 137 } catch (Exception x) { 138 throw new BuildException(x, getLocation()); 139 } 140 } 141 142 private Set <Manifest > loadManifests(URI u) throws BuildException { 143 try { 144 Document doc = XMLUtil.parse(new InputSource (u.toString()), false, false, null, new EntityResolver () { 145 public InputSource resolveEntity(String pub, String sys) throws SAXException , IOException { 146 if (pub.contains("DTD Autoupdate Catalog")) { 147 return new InputSource (new StringReader ("")); 148 } else { 149 return null; 150 } 151 } 152 }); 153 Set <Manifest > manifests = new HashSet <Manifest >(); 154 NodeList nl = doc.getElementsByTagName("manifest"); 155 for (int i = 0; i < nl.getLength(); i++) { 156 Element m = (Element ) nl.item(i); 157 Manifest mani = new Manifest (); 158 NamedNodeMap map = m.getAttributes(); 159 for (int j = 0; j < map.getLength(); j++) { 160 Attr a = (Attr ) map.item(j); 161 mani.getMainAttributes().putValue(a.getName(), a.getValue()); 162 } 163 manifests.add(mani); 164 } 165 return manifests; 166 } catch (Exception x) { 167 throw new BuildException("Could not load " + u, x, getLocation()); 168 } 169 } 170 171 private static String findCNB(Manifest m) { 172 String name = m.getMainAttributes().getValue("OpenIDE-Module"); 173 if (name == null) { 174 throw new IllegalArgumentException (); 175 } 176 return name.replaceFirst("/\\d+$", ""); 177 } 178 179 private static boolean specGreaterThan(String newspec, String oldspec) { 180 if (newspec == null) { 181 return false; 182 } 183 if (oldspec == null) { 184 return true; 185 } 186 String [] olddigits = oldspec.split("\\."); 187 String [] newdigits = newspec.split("\\."); 188 int oldlen = olddigits.length; 189 int newlen = newdigits.length; 190 int max = Math.max(oldlen, newlen); 191 for (int i = 0; i < max; i++) { 192 int oldd = (i < oldlen) ? Integer.parseInt(olddigits[i]) : 0; 193 int newd = (i < newlen) ? Integer.parseInt(newdigits[i]) : 0; 194 if (oldd != newd) { 195 return newd > oldd; 196 } 197 } 198 return false; 199 } 200 201 private void checkForProblems(SortedMap <String ,SortedSet <String >> problems, String msg) throws BuildException { 202 if (!problems.isEmpty()) { 203 for (Map.Entry <String ,SortedSet <String >> entry : problems.entrySet()) { 204 log("Problems found for module " + entry.getKey() + ": " + entry.getValue(), Project.MSG_ERR); 205 } 206 throw new BuildException(msg, getLocation()); 207 } 208 } 209 210 } 211 | Popular Tags |