1 19 package org.java.plugin.tools.ant; 20 21 import java.io.BufferedInputStream ; 22 import java.io.BufferedOutputStream ; 23 import java.io.File ; 24 import java.io.FileInputStream ; 25 import java.io.FileOutputStream ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.OutputStream ; 29 import java.net.URL ; 30 import java.text.DateFormat ; 31 import java.text.ParseException ; 32 import java.text.SimpleDateFormat ; 33 import java.util.Date ; 34 import java.util.HashMap ; 35 import java.util.Iterator ; 36 import java.util.Locale ; 37 import java.util.Map ; 38 import java.util.Properties ; 39 40 import javax.xml.parsers.DocumentBuilder ; 41 import javax.xml.parsers.DocumentBuilderFactory ; 42 import javax.xml.parsers.ParserConfigurationException ; 43 import javax.xml.transform.OutputKeys ; 44 import javax.xml.transform.Transformer ; 45 import javax.xml.transform.TransformerConfigurationException ; 46 import javax.xml.transform.TransformerFactory ; 47 import javax.xml.transform.TransformerFactoryConfigurationError ; 48 import javax.xml.transform.dom.DOMSource ; 49 import javax.xml.transform.stream.StreamResult ; 50 51 import org.apache.tools.ant.BuildException; 52 import org.java.plugin.registry.PluginDescriptor; 53 import org.java.plugin.registry.PluginFragment; 54 import org.java.plugin.registry.Version; 55 import org.java.plugin.util.IoUtil; 56 import org.w3c.dom.Document ; 57 import org.w3c.dom.Element ; 58 import org.w3c.dom.NodeList ; 59 60 77 public class VersionUpdateTask extends BaseJpfTask { 78 private File versionsFile; 79 private boolean alterReferences = false; 80 private boolean timestampVersion = false; 81 82 85 public final void setAlterReferences(final boolean value) { 86 alterReferences = value; 87 } 88 89 92 public void setVersionsFile(final File value) { 93 versionsFile = value; 94 } 95 96 100 public void setTimestampVersion(final boolean value) { 101 timestampVersion = value; 102 } 103 104 107 public void execute() throws BuildException { 108 log("Starting JPF version updater..."); if (versionsFile == null) { 110 throw new BuildException("versionsfile attribute must be set!", getLocation()); 112 } 113 initRegistry(true); 114 if (getVerbose()) { 116 log("Loading versions file " + versionsFile); } 118 Properties versions = new Properties (); 119 if (versionsFile.exists()) { 120 try { 121 InputStream in = 122 new BufferedInputStream (new FileInputStream (versionsFile)); 123 try { 124 versions.load(in); 125 } finally { 126 in.close(); 127 } 128 } catch (IOException ioe) { 129 throw new BuildException("failed reading versions file " + versionsFile, ioe, getLocation()); 131 } 132 } else { 133 log("Versions file " + versionsFile + " not found, new one will be created."); } 136 Map infos = new HashMap (); for (Iterator it = getRegistry().getPluginDescriptors().iterator(); 139 it.hasNext();) { 140 PluginDescriptor descr = (PluginDescriptor) it.next(); 141 File manifestFile = IoUtil.url2file(descr.getLocation()); 142 if (manifestFile == null) { 143 throw new BuildException( 144 "non-local plug-in manifest URL given " + descr.getLocation()); 146 } 147 URL homeUrl = getPathResolver().resolvePath(descr, "/"); File homeFile = IoUtil.url2file(homeUrl); 149 if (homeFile == null) { 150 throw new BuildException( 151 "non-local plug-in home URL given " + homeUrl); 153 } 154 try { 155 infos.put(descr.getId(), new PluginInfo(descr.getId(), 156 versions, manifestFile, homeFile, descr.getVersion())); 157 } catch (ParseException pe) { 158 throw new BuildException("failed parsing versions data " + " for manifest " + manifestFile, pe, getLocation()); } 161 if (getVerbose()) { 162 log("Collected manifest file " + manifestFile); } 164 } 165 for (Iterator it = getRegistry().getPluginFragments().iterator(); 166 it.hasNext();) { 167 PluginFragment descr = (PluginFragment) it.next(); 168 File manifestFile = IoUtil.url2file(descr.getLocation()); 169 if (manifestFile == null) { 170 throw new BuildException( 171 "non-local plug-in fragment manifest URL given " + descr.getLocation()); 173 } 174 URL homeUrl = getPathResolver().resolvePath(descr, "/"); File homeFile = IoUtil.url2file(homeUrl); 176 if (homeFile == null) { 177 throw new BuildException( 178 "non-local plug-in fragment home URL given " + homeUrl); 180 } 181 try { 182 infos.put(descr.getId(), new PluginInfo(descr.getId(), 183 versions, manifestFile, homeFile, descr.getVersion())); 184 } catch (ParseException pe) { 185 throw new BuildException("failed parsing versions data " + " for manifest " + manifestFile, pe, getLocation()); } 188 if (getVerbose()) { 189 log("Populated manifest file " + manifestFile); } 191 } 192 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); 194 builderFactory.setValidating(false); 195 DocumentBuilder builder; 196 try { 197 builder = builderFactory.newDocumentBuilder(); 198 } catch (ParserConfigurationException pce) { 199 throw new BuildException("can't obtain XML document builder ", pce, getLocation()); 201 } 202 if (getVerbose()) { 203 log("Processing versions"); } 205 for (Iterator it = infos.values().iterator(); it.hasNext();) { 206 PluginInfo info = (PluginInfo) it.next(); 207 try { 208 info.processVersion(versions, builder, timestampVersion); 209 } catch (Exception e) { 210 throw new BuildException("failed processing manifest " + info.getManifestFile(), e, getLocation()); 212 } 213 } 214 if (alterReferences) { 215 if (getVerbose()) { 216 log("Processing version references"); } 218 for (Iterator it = infos.values().iterator(); it.hasNext();) { 219 PluginInfo info = (PluginInfo) it.next(); 220 try { 221 info.processVersionReferences(versions, builder); 222 } catch (Exception e) { 223 throw new BuildException("failed processing manifest " + info.getManifestFile(), e, getLocation()); 225 } 226 } 227 } 228 Transformer transformer; 229 try { 230 transformer = TransformerFactory.newInstance().newTransformer(); 231 } catch (TransformerConfigurationException tce) { 232 throw new BuildException("can't obtain XML document transformer ", tce, getLocation()); 234 } catch (TransformerFactoryConfigurationError tfce) { 235 throw new BuildException( 236 "can't obtain XML document transformer factory ", tfce, getLocation()); 238 } 239 transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); transformer.setOutputProperty(OutputKeys.STANDALONE, "no"); transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, 244 "-//JPF//Java Plug-in Manifest 1.0"); transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, 246 "http://jpf.sourceforge.net/plugin_1_0.dtd"); if (getVerbose()) { 248 log("Saving manifests"); } 250 for (Iterator it = infos.values().iterator(); it.hasNext();) { 251 PluginInfo info = (PluginInfo) it.next(); 252 try { 253 info.save(versions, transformer); 254 } catch (Exception e) { 255 throw new BuildException("failed saving manifest " + info.getManifestFile(), e, getLocation()); 257 } 258 } 259 if (getVerbose()) { 261 log("Saving versions file " + versionsFile); } 263 try { 264 OutputStream out = 265 new BufferedOutputStream (new FileOutputStream (versionsFile)); 266 try { 267 versions.store(out, "Plug-in and plug-in fragment versions file"); } finally { 269 out.close(); 270 } 271 } catch (IOException ioe) { 272 throw new BuildException("failed writing versions file " + versionsFile, ioe, getLocation()); 274 } 275 log("... finished JPF version updater"); } 277 278 static final class PluginInfo { 279 private static Date getTimestamp(final File file, 280 final Date parentTimestamp) { 281 Date result; 282 if (parentTimestamp == null) { 283 result = new Date (file.lastModified()); 284 } else { 285 result = new Date (Math.max(parentTimestamp.getTime(), 286 file.lastModified())); 287 } 288 File [] files = file.listFiles(); 289 if (files != null) { 290 for (int i = 0; i < files.length; i++) { 291 result = getTimestamp(files[i], result); 292 } 293 } 294 return result; 295 } 296 297 private static Version upgradeVersion(final Version ver) { 298 if (ver == null) { 299 return new Version(0, 0, 1, null); 300 } 301 return new Version(ver.getMajor(), ver.getMinor(), 302 ver.getBuild() + 1, ver.getName()); 303 } 304 305 private static Version upgradeVersion(final Version ver, 306 final Date timestamp) { 307 DateFormat dtf = 308 new SimpleDateFormat ("yyyyMMddHHmmss", Locale.ENGLISH); if (ver == null) { 310 return new Version(0, 0, 1, dtf.format(timestamp)); 311 } 312 return new Version(ver.getMajor(), ver.getMinor(), 313 ver.getBuild() + 1, dtf.format(timestamp)); 314 } 315 316 private final String id; 317 private final File manifestFile; 318 private final Version oldVersion; 319 private final Date oldTimestamp; 320 private final DateFormat dtf = 321 new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH); private Document doc; 323 private Version newVersion; 324 private Date currentTimestamp; 325 326 PluginInfo(final String anId, final Properties versions, 327 final File aMnifestFile, final File homeFile, 328 final Version currentVersion) throws ParseException { 329 id = anId; 330 String versionStr = versions.getProperty(anId, null); 331 String timestampStr = versions.getProperty(anId + ".timestamp", null); if (versionStr != null) { 333 oldVersion = Version.parse(versionStr); 334 } else { 335 oldVersion = currentVersion; 336 } 337 if (timestampStr != null) { 338 oldTimestamp = dtf.parse(timestampStr); 339 } else { 340 oldTimestamp = null; 341 } 342 manifestFile = aMnifestFile; 343 currentTimestamp = getTimestamp(homeFile, null); 344 versions.setProperty(id + ".timestamp", dtf.format(currentTimestamp)); 346 } 347 348 File getManifestFile() { 349 return manifestFile; 350 } 351 352 void processVersion(final Properties versions, 353 final DocumentBuilder builder, final boolean timestampVersion) 354 throws Exception { 355 if (IoUtil.compareFileDates(oldTimestamp, currentTimestamp)) { 356 newVersion = oldVersion; 357 } else { 358 newVersion = !timestampVersion ? upgradeVersion(oldVersion) 359 : upgradeVersion(oldVersion, currentTimestamp); 360 } 361 versions.setProperty(id, newVersion.toString()); 362 if (oldVersion.equals(newVersion)) { 363 return; 364 } 365 doc = builder.parse(manifestFile); 366 Element root = doc.getDocumentElement(); 367 if (root.hasAttribute("version")) { root.setAttribute("version", newVersion.toString()); } 370 } 371 372 void processVersionReferences(final Properties versions, 373 final DocumentBuilder builder) throws Exception { 374 if (doc == null) { 375 doc = builder.parse(manifestFile); 376 } 377 Element root = doc.getDocumentElement(); 378 if ("plugin-fragment".equals(root.getNodeName())) { processVersionReference(versions, root); 380 } 381 NodeList imports = root.getElementsByTagName("import"); for (int i = 0; i < imports.getLength(); i++) { 383 processVersionReference(versions, (Element ) imports.item(i)); 384 } 385 } 386 387 private void processVersionReference(final Properties versions, 388 final Element elm) { 389 if (!elm.hasAttribute("plugin-version")) { return; 391 } 392 String version = versions.getProperty( 393 elm.getAttribute("plugin-id"), id); if (version != null) { 395 elm.setAttribute("plugin-version", version); } 397 } 398 399 void save(final Properties versions, final Transformer transformer) 400 throws Exception { 401 if (doc == null) { 402 return; 403 } 404 long modified = manifestFile.lastModified(); 405 transformer.transform(new DOMSource (doc), 406 new StreamResult (manifestFile)); 407 manifestFile.setLastModified(modified); 408 } 409 } 410 } 411 | Popular Tags |