1 19 20 package org.netbeans.nbbuild; 21 22 import java.io.ByteArrayInputStream ; 23 import java.util.HashMap ; 24 import java.util.LinkedHashMap ; 25 import java.util.Map ; 26 import org.apache.tools.ant.types.FileSet; 27 import org.apache.tools.ant.BuildException; 28 import org.apache.tools.ant.taskdefs.MatchingTask; 29 import org.apache.tools.ant.DirectoryScanner; 30 import java.io.File ; 31 import java.io.FileOutputStream ; 32 import java.io.IOException ; 33 import java.io.InputStream ; 34 import java.io.OutputStream ; 35 import java.io.OutputStreamWriter ; 36 import java.io.PrintWriter ; 37 import java.text.Collator ; 38 import java.text.DateFormat ; 39 import java.text.SimpleDateFormat ; 40 import java.util.ArrayList ; 41 import java.util.Collection ; 42 import java.util.Comparator ; 43 import java.util.Date ; 44 import java.util.HashSet ; 45 import java.util.List ; 46 import java.util.Set ; 47 import java.util.TimeZone ; 48 import java.util.TreeMap ; 49 import java.util.TreeSet ; 50 import java.util.zip.ZipEntry ; 51 import java.util.zip.ZipFile ; 52 import org.w3c.dom.Element ; 53 import org.w3c.dom.NodeList ; 54 import org.xml.sax.EntityResolver ; 55 import org.xml.sax.InputSource ; 56 import org.xml.sax.SAXException ; 57 58 62 public class MakeUpdateDesc extends MatchingTask { 63 64 protected boolean usedMatchingTask = false; 65 66 public class Group { 67 public List <FileSet> filesets = new ArrayList <FileSet>(); 68 public String name; 69 70 71 public void setName (String s) { 72 name = s; 73 } 74 75 76 public void addFileSet (FileSet set) { 77 filesets.add(set); 78 } 79 } 80 81 82 public class Entityinclude { 83 public String file; 84 87 public void setFile (String f) { 88 file = f; 89 } 90 } 91 92 private List <Entityinclude> entityincludes = new ArrayList <Entityinclude>(); 93 private List <Group> groups = new ArrayList <Group>(); 94 private List <FileSet> filesets = new ArrayList <FileSet>(); 95 96 private File desc; 97 98 99 public void setDesc(File d) { 100 desc = d; 101 } 102 103 104 public Group createGroup () { 105 Group g = new Group (); 106 groups.add (g); 107 return g; 108 } 109 110 111 public Entityinclude createEntityinclude () { 112 Entityinclude i = new Entityinclude (); 113 entityincludes.add (i); 114 return i; 115 } 116 117 120 public void addFileset(FileSet set) { 121 filesets.add(set); 122 } 123 124 private boolean automaticGrouping; 125 129 public void setAutomaticgrouping(boolean b) { 130 automaticGrouping = b; 131 } 132 133 private String dist_base; 134 137 public void setDistBase(String dbase) { 138 dist_base = dbase; 139 } 140 141 private static String xmlEscape(String s) { 143 int max = s.length(); 144 StringBuffer s2 = new StringBuffer ((int)(max * 1.1 + 1)); 145 for (int i = 0; i < max; i++) { 146 char c = s.charAt(i); 147 switch (c) { 148 case '<': 149 s2.append("<"); break; 151 case '>': 152 s2.append(">"); break; 154 case '&': 155 s2.append("&"); break; 157 case '"': 158 s2.append("""); break; 160 default: 161 s2.append(c); 162 break; 163 } 164 } 165 return s2.toString(); 166 } 167 168 public void execute () throws BuildException { 169 Group root = new Group(); 170 for (FileSet fs : filesets) { 171 root.addFileSet(fs); 172 } 173 groups.add(root); 174 if (desc.exists ()) { 175 long time = desc.lastModified (); 177 boolean uptodate = true; 178 179 CHECK: 180 for (Group g : groups) { 181 for (FileSet n : g.filesets) { 182 if ( n != null ) { 183 DirectoryScanner ds = n.getDirectoryScanner(getProject()); 184 String [] files = ds.getIncludedFiles(); 185 File bdir = ds.getBasedir(); 186 for (String file : files) { 187 File n_file = new File (bdir, file); 188 if (n_file.lastModified () > time) { 189 uptodate = false; 190 break CHECK; 191 } 192 } 193 } 194 } 195 } 196 if (uptodate) return; 197 } 198 log ("Creating update description " + desc.getAbsolutePath ()); 199 200 Map <String ,Collection <Module>> modulesByGroup = loadNBMs(); 201 boolean targetClustersDefined = false; 202 for (Collection <Module> modules : modulesByGroup.values()) { 203 for (Module m : modules) { 204 targetClustersDefined |= m.xml.getAttributeNode("targetcluster") != null; 205 } 206 } 207 208 try { 210 desc.delete(); 211 OutputStream os = new FileOutputStream (desc); 212 try { 213 214 PrintWriter pw = new PrintWriter (new OutputStreamWriter (os, "UTF-8")); pw.println ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); pw.println (); 217 DateFormat format = new SimpleDateFormat ("ss/mm/HH/dd/MM/yyyy"); format.setTimeZone(TimeZone.getTimeZone("GMT")); String date = format.format(new Date ()); 220 221 if ( entityincludes.size() > 0 ) { 222 String ent_name = desc.getAbsolutePath(); 224 int xml_idx = ent_name.indexOf(".xml"); if (xml_idx != -1) { 226 ent_name = ent_name.substring (0, xml_idx) + ".ent"; } else { 228 ent_name = ent_name + ".ent"; } 230 File desc_ent = new File (ent_name); 231 desc_ent.delete(); 232 if (targetClustersDefined) { 233 pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.4//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_4.dtd\" ["); 234 } else { 235 pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.3//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_3.dtd\" ["); 237 } 238 pw.println (" <!ENTITY entity SYSTEM \"" + xmlEscape(desc_ent.getName()) + "\">"); int inc_num=0; 241 for (int i=0; i<entityincludes.size(); i++) { 242 Entityinclude ei = entityincludes.get(i); 243 pw.println (" <!ENTITY include" + i + " SYSTEM \"" + xmlEscape(ei.file) + "\">"); } 245 pw.println ("]>"); pw.println (); 247 pw.println ("<module_updates timestamp=\"" + xmlEscape(date) + "\">"); pw.println (" &entity;"); for (int i=0; i<entityincludes.size(); i++) { 250 pw.println (" &include" + i + ";"); } 252 pw.println ("</module_updates>"); pw.println (); 254 pw.flush (); 255 pw.close (); 256 257 os = new FileOutputStream (desc_ent); 258 pw = new PrintWriter (new OutputStreamWriter (os, "UTF-8")); pw.println ("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); pw.println ("<!-- external entity include " + date + " -->"); 261 pw.println (); 262 263 } else { 264 if (targetClustersDefined) { 265 pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.4//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_4.dtd\">"); 266 } else { 267 pw.println("<!DOCTYPE module_updates PUBLIC \"-//NetBeans//DTD Autoupdate Catalog 2.3//EN\" \"http://www.netbeans.org/dtds/autoupdate-catalog-2_3.dtd\">"); 268 } 269 pw.println ("<module_updates timestamp=\"" + date + "\">"); pw.println (); 271 } 272 273 pw.println (); 274 Map <String ,Element > licenses = new HashMap <String ,Element >(); 275 Set<String > licenseNames = new HashSet <String >(); 276 277 for (Map.Entry <String ,Collection <Module>> entry : modulesByGroup.entrySet()) { 278 String groupName = entry.getKey(); 279 log("Creating group \"" + groupName + "\""); 281 if (groupName != null) { 282 pw.println("<module_group name=\"" + xmlEscape(groupName) + "\">"); 283 pw.println(); 284 } 285 for (Module m : entry.getValue()) { 286 Element module = m.xml; 287 if (module.getAttribute("downloadsize").equals("0")) { 288 module.setAttribute("downloadsize", Long.toString(m.nbm.length())); 289 } 290 Element manifest = (Element ) module.getElementsByTagName("manifest").item(0); 291 String name = manifest.getAttribute("OpenIDE-Module-Name"); 292 if (name.length() > 0) { 293 log(" Adding module " + name + " (" + m.nbm.getAbsolutePath() + ")"); 294 } 295 if (dist_base != null) { 296 String prefix; 298 if (dist_base.equals(".")) { 299 prefix = ""; 300 } else { 301 prefix = dist_base + "/"; 302 } 303 module.setAttribute("distribution", prefix + m.nbm.getName()); 304 } 305 NodeList licenseList = module.getElementsByTagName("license"); 306 if (licenseList.getLength() > 0) { 307 Element license = (Element ) licenseList.item(0); 308 licenses.put(license.getAttribute("name"), license); 310 module.removeChild(license); 311 } 312 pw.flush(); 313 XMLUtil.write(module, os); 314 pw.println(); 315 } 316 if (groupName != null) { 317 pw.println("</module_group>"); 318 pw.println(); 319 } 320 } 321 pw.flush(); 322 for (Element license : licenses.values()) { 323 XMLUtil.write(license, os); 324 } 325 if ( entityincludes.size() <= 0 ) { 326 pw.println ("</module_updates>"); pw.println (); 328 } 329 pw.flush (); 330 pw.close (); 331 } finally { 332 os.flush (); 333 os.close (); 334 } 335 } catch (IOException ioe) { 336 desc.delete (); 337 throw new BuildException("Cannot create update description", ioe, getLocation()); 338 } 339 } 340 341 private static class Module { 342 public Module() {} 343 public Element xml; 344 public File nbm; 345 } 346 347 private Map <String ,Collection <Module>> loadNBMs() throws BuildException { 348 final Collator COLL = Collator.getInstance(); 349 Comparator <String > groupNameComparator = new Comparator <String >() { 351 public int compare(String gn1, String gn2) { 352 return gn1 != null ? 353 (gn2 != null ? COLL.compare(gn1, gn2) : 1) : 354 (gn2 != null ? -1 : 0); 355 } 356 }; 357 Map <String ,Collection <Module>> r = automaticGrouping ? 358 new TreeMap <String ,Collection <Module>>(groupNameComparator) : 360 new LinkedHashMap <String ,Collection <Module>>(); 362 Comparator <Module> moduleDisplayNameComparator = new Comparator <Module>() { 364 public int compare(Module m1, Module m2) { 365 int res = COLL.compare(getName(m1), getName(m2)); 366 return res != 0 ? res : System.identityHashCode(m1) - System.identityHashCode(m2); 367 } 368 String getName(Module m) { 369 Element mani = (Element ) m.xml.getElementsByTagName("manifest").item(0); 370 String displayName = mani.getAttribute("OpenIDE-Module-Name"); 371 if (displayName.length() > 0) { 372 return displayName; 373 } else { 374 return mani.getAttribute("OpenIDE-Module"); 375 } 376 } 377 }; 378 for (Group g : groups) { 379 Collection <Module> modules = r.get(g.name); 380 if (modules == null) { 381 modules = new TreeSet <Module>(moduleDisplayNameComparator); 382 r.put(g.name, modules); 383 } 384 for (FileSet fs : g.filesets) { 385 DirectoryScanner ds = fs.getDirectoryScanner(getProject()); 386 for (String file : ds.getIncludedFiles()) { 387 File n_file = new File (fs.getDir(getProject()), file); 388 try { 389 ZipFile zip = new ZipFile (n_file); 390 try { 391 ZipEntry entry = zip.getEntry("Info/info.xml"); 392 if (entry == null) { 393 throw new BuildException("NBM " + n_file + " was malformed: no Info/info.xml", getLocation()); 394 } 395 InputStream is = zip.getInputStream(entry); 396 try { 397 Module m = new Module(); 398 m.xml = XMLUtil.parse(new InputSource (is), false, false, null, new EntityResolver () { 399 public InputSource resolveEntity(String publicId, String systemId) throws SAXException , IOException { 400 return new InputSource (new ByteArrayInputStream (new byte[0])); 401 } 402 }).getDocumentElement(); 403 m.nbm = n_file; 404 Collection <Module> target = modules; 405 if (automaticGrouping && g.name == null) { 406 String categ = ((Element ) m.xml.getElementsByTagName("manifest").item(0)).getAttribute("OpenIDE-Module-Display-Category"); 408 if (categ.length() > 0) { 409 target = r.get(categ); 410 if (target == null) { 411 target = new TreeSet <Module>(moduleDisplayNameComparator); 412 r.put(categ, target); 413 } 414 } 415 } 416 target.add(m); 417 } finally { 418 is.close(); 419 } 420 } finally { 421 zip.close(); 422 } 423 } catch (Exception e) { 424 throw new BuildException("Cannot access nbm file: " + n_file, e, getLocation()); 425 } 426 } 427 } 428 } 429 return r; 430 } 431 432 } 433 | Popular Tags |