All Downloads are FREE. Search and download functionalities are using the official Maven repository.

at.spardat.xma.boot.antext.GenPreloadFile Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     s IT Solutions AT Spardat GmbH - initial API and implementation
 *******************************************************************************/

/*
 * @(#) $Id: GenPreloadFile.java 2318 2008-02-04 10:04:04Z s2877 $
 */
package at.spardat.xma.boot.antext;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

import at.spardat.xma.boot.cache.VersionNumber;
import at.spardat.xma.boot.comp.data.XMAApp;
import at.spardat.xma.boot.comp.data.XMAAppParser;
import at.spardat.xma.boot.comp.data.XMAResource;
import at.spardat.xma.boot.logger.LogLevel;
import at.spardat.xma.boot.logger.Logger;

/**
 * Ant task to generate a html document containing a list of links to all downloadable resources of an XMA application.
 * This html document can be used for preloading these resources. 
* This task has to be called after the task AppDescriptor! * @author s2877 */ public class GenPreloadFile extends Task { private boolean verbose; private File xmaappFile; private File pluginFile; private File preloadFile; private boolean gendeltas; private List deltaInfo = new ArrayList(); final static Pattern versionedfilename = Pattern.compile("(.*)_(\\d+)\\.(\\d+)\\.(\\d+)(.*)"); final static Pattern deltafilename = Pattern.compile("(.*)_(\\d+)\\.(\\d+)\\.(\\d+)-(\\d+)\\.(\\d+)\\.(\\d+)\\.xdelta(.*)"); /** * Set the xma-app.xml file to read the resources */ public void setXmaapp(File xmaappFile) { this.xmaappFile = xmaappFile; } /** * Set the plugins.xml file to read the plugin resources */ public void setPlugin(File pluginFile) { this.pluginFile = pluginFile; } /** * Set the output file to write the preload list */ public void setPreload(File preloadFile) { this.preloadFile = preloadFile; } /** * Turn on verbose output to the ant console */ public void setVerbose(boolean verbose) { this.verbose = verbose; } /** * Set if the URLs for delta download files should be included in the preload file. * If set to true, the URLs of all delta download files of all versioned files without * a -tag are written. For all versioned files with -tag, the * -tag determines which delta download files are written. */ public void setGendeltas(boolean gen) { gendeltas=gen; } /** * Adds nested tag containing customization which delta file URLs * should be included in the preload file. */ public void addConfiguredDeltaInfo(DeltaInfo info) { deltaInfo.add(info); } /** * Called by ant to do the work of the task. * Reads the content of the two input files using classes from XMA-bootrt * and generates the output file containing the list of the resources including the hashvalues in the urls. */ public void execute() throws BuildException { InputStream inapp = null; InputStream inplug = null; PrintWriter out = null; try { Logger logger = Logger.getLogger("build"); logger.setLevel(LogLevel.SEVERE); if(preloadFile==null) throw new BuildException("missing parameter 'preload'"); if(verbose == true) log("generating preload links into " + preloadFile); out = new PrintWriter(new FileWriter(preloadFile)); out.println(""); out.println(""); out.println("Preload"); out.println(""); out.println(""); if(xmaappFile==null) throw new BuildException("missing parameter 'xmaapp'"); if(verbose == true) log("reading resources from " + xmaappFile); inapp = new FileInputStream(xmaappFile); XMAAppParser parser = new XMAAppParser(logger, true ); XMAApp app = parser.parse(inapp); for(Iterator it=app.getAllResources().values().iterator();it.hasNext();) { handleResource((XMAResource)it.next(),out); } if(pluginFile!=null) { if(verbose == true) log("reading resources from " + pluginFile); inplug = new FileInputStream(pluginFile); parser = new XMAAppParser(logger, true ); app = parser.parse(inplug); for(Iterator it=app.getAllResources().values().iterator();it.hasNext();) { handleResource((XMAResource)it.next(),out); } } out.println(""); out.println(""); } catch (BuildException be) { throw be; } catch (Exception e) { throw new BuildException(e); } finally { try { if(inapp != null) inapp.close(); } catch (IOException e2) { } try { if(inplug != null) inplug.close(); } catch (IOException e2) { } if(out != null) out.close(); } } /** * Writes the URL of the given resource as HTML-link to out. * If the given resource is a versioned file (containing the verion number * in the file name), the URLs of its delta download files are written, too, * if gendelta="true" was given. * If a -tag was given for this resource, the -tag overrules * the behaviour. see {@link DeltaInfo}. */ private void handleResource(XMAResource res,PrintWriter out) { String href = res.getHref_(); String hash = res.getVersion_().getVersion(); DeltaInfo delta = findDeltaInfo(href); if(gendeltas||delta!=null) { String[] files = findDeltas(href,delta); for(int i=0;iPreload"); if(verbose) log("generate link to "+file); } } if(delta==null||delta.isPreloadfull()) { String file = VersionNumber.insertHash(href,hash); out.println("Preload"); if(verbose) log("generate link to "+file); } } /** * Finds the DeltaInfo to the given resource name. * name is the relative url to a versioned jar file. * [/]*_...jar * e.g. "clientrt/xmartclient_2.0.0.jar" * The name of the matching DeltaInfo must be the same or may * omit the version number and extention. * e.g. "clientrt/xmartclient" */ private DeltaInfo findDeltaInfo(String name) { for(Iterator it=deltaInfo.iterator();it.hasNext();) { DeltaInfo info = (DeltaInfo)it.next(); if(name.startsWith(info.getName())) { if(name.equals(info.getName())) return info; VersionNumber version = VersionNumber.parse(name); if(version!=null) { if(name.equals(info.getName()+"_"+version.toString()+".jar")) { return info; } } } } return null; } /** * Finds the delta download files for the resource specified by the given * href and returns there relative urls. If delta is null all corresponding * download files are taken. Otherwise only the delta files accepted by * delta are taken.
* The delta download files are searched in the same directory as the versioned resource. */ private String[] findDeltas(String href,final DeltaInfo delta) { File baseDir = preloadFile.getParentFile(); File versionedFile = new File(baseDir,href); File searchDir = versionedFile.getParentFile(); Matcher matcher = versionedfilename.matcher(href); if(matcher.find()) { String pathprefix = null; String string = matcher.group(1); int sep = string.lastIndexOf('/'); if(sep>0) { pathprefix = string.substring(0,sep); string = string.substring(sep+1); } final String prefix = string; final String major = matcher.group(2); final String minor = matcher.group(3); final String bugfix = matcher.group(4); final String postfix = matcher.group(5); String[] found = searchDir.list(new FilenameFilter(){ public boolean accept(File dir, String name) { Matcher matcher = deltafilename.matcher(name); if(!matcher.find()) return false; String string = matcher.group(1); if(!prefix.equals(string)) return false; String oldMajor = matcher.group(2); String oldMinor = matcher.group(3); String oldBugfix = matcher.group(4); string = matcher.group(5); if(!major.equals(string)) return false; string = matcher.group(6); if(!minor.equals(string)) return false; string = matcher.group(7); if(!bugfix.equals(string)) return false; string = matcher.group(8); if(!postfix.equals(string)) return false; if(delta!=null) { return delta.accept(oldMajor,oldMinor,oldBugfix); } return true; }}); if(pathprefix!=null) { for(int i=0;i. * Each deltainfo corresponds to one versioned jar file for which delta download files are contained in * the web application. It is used for fine grained selection of the delta download files choosed for * preload. It supports minimal version, an include list of versions and and exclude list of versions. * Further it can exclude the full version file from the preload. *

* The objects are created by ant for any tag found inside this task and delivered by calling * {@link GenPreloadFile#addConfiguredDeltaInfo(at.spardat.xma.boot.antext.GenPreloadFile.DeltaInfo)}. * */ public static class DeltaInfo { String name; Version minversion; List includes = new ArrayList(); List excludes = new ArrayList(); boolean preloadfull=true; public DeltaInfo() {} /** * Get the name of the affected resource. */ public String getName() { return name; } /** * Set the name of the affected resource. This name is the href of the concerned resource * without the version number and extention. E.g. for "clientrt/xmartclient_2.0.0.jar" * "clientrt/xmartclient" is used as name. */ public void setName(String name) { this.name = name; } /** * Returns if the full version of the resource should be included in the preload. */ public boolean isPreloadfull() { return preloadfull; } /** * Set if the full version of the resource should be included in the preload. */ public void setPreloadfull(boolean preloadfull) { this.preloadfull = preloadfull; } /** * Set the minimum version for delta download files to include in the preload. * Delta files to older versions are omitted. * For the format of the version number see the constructor of Version. * Example: minversion="1.8.2" * Default is empty which means no restriction. */ public void setMinversion(String minversion) { this.minversion = new Version(minversion,true); } /** * Sets a pattern for delta download files to exclude from the preload. * The pattern is a comma seperated list of version numbers and version ranges * |[,|]* * Version numbers may contain wildcards. * For the format of version numbers see the constructor of Version. * For the format of version ranges see VersionRange.parse(). * Example: excludes="1.7.*,1.8.0-1.8.1" * Default is empty meaning no exclusions. */ public void setExcludes(String excludes) { for(StringTokenizer tok=new StringTokenizer(excludes,", \t");tok.hasMoreTokens();) { String token = tok.nextToken(); VersionRange range = VersionRange.parse(token); if(range!=null) this.excludes.add(range); else this.excludes.add(new Version(token,false)); } } /** * Sets a pattern for delta download files to include into the preload. * The pattern is a comma seperated list of version numbers and version ranges * |[,|]* * Version numbers may contain wildcards. * For the format of version numbers see the constructor of Version. * For the format of version ranges see VersionRange.parse(). * Example: includes="1.8.2-1.8.5,2.*.*" * Default is empty meaning all versions. (same as *.*.*) */ public void setIncludes(String includes) { for(StringTokenizer tok=new StringTokenizer(includes,", \t");tok.hasMoreTokens();) { String token = tok.nextToken(); VersionRange range = VersionRange.parse(token); if(range!=null) this.includes.add(range); else this.includes.add(new Version(token,false)); } } /** * Determines if the version number given in the parameters is accepted according * to the settings of minversion, includes and excludes. * If includes have been set, includes must contain the given number to accept it. * If excludes have been set, excludes must not contain the given number to accept it. * If the given number is contained in includes and excludes, it is not accepted. * If minversion have been set, the given number must always be greater or equal to * minversion to be accepted. */ public boolean accept(String major,String minor,String bugfix) { Version toTest = new Version(major,minor,bugfix); if(minversion!=null && minversion.compareTo(toTest)>0) return false; for(Iterator it=excludes.iterator();it.hasNext();) { Object vers = it.next(); if(vers instanceof Version) { if(toTest.compareTo(vers)==0) return false; } else if(vers instanceof VersionRange) { if(((VersionRange)vers).isInRange(toTest)) return false; } } if(includes.size()<=0) return true; for(Iterator it=includes.iterator();it.hasNext();) { Object vers = it.next(); if(vers instanceof Version) { if(toTest.compareTo(vers)==0) return true; } else if(vers instanceof VersionRange) { if(((VersionRange)vers).isInRange(toTest)) return true; } } return false; } } /** * Represents a version number. In contrast to at.spardat.xma.boot.cache.VersionNumber it * supports wildcards (e.g. 1.8.* or 1.*.*). Therfore it has its on compareTo-method which * treats '*' as equal to any digit. */ public static class Version { final static Pattern strict = Pattern.compile("(\\d+)\\.(\\d+)\\.(\\d+)"); final static Pattern fuzzy = Pattern.compile("(\\d+|\\*)\\.(\\d+|\\*)\\.(\\d+|\\*)"); int major,minor,bugfix; boolean majorDefined,minorDefined,bugfixDefined; /** * Constructs a Version from major,minor,bugfix. All three strings must contain * a valid integer. Wildcards are not supported with this constructor. * @throws NumberFormatException if any parameter does not contain a parsable integer. */ public Version(String major,String minor,String bugfix) { this.major=Integer.parseInt(major); this.minor=Integer.parseInt(minor); this.bugfix=Integer.parseInt(bugfix); majorDefined=minorDefined=bugfixDefined=true; } /** * Constructs a Version by parsing it form a String. The string has to be of the format * .. e.g. "1.8.4". * @param version the String to parse. * @param strict if true no wildcards are allowed. If false '*' can be used as wildcard * for any of the three digits. * @throws IllegalArgumentException if the string cannot be parsed sucessfully. */ public Version(String version,boolean strict) { Matcher matcher; if(strict) matcher = Version.strict.matcher(version); else matcher = fuzzy.matcher(version); if(matcher.matches()) { String major = matcher.group(1); String minor = matcher.group(2); String bugfix = matcher.group(3); init(major,minor,bugfix); } else { throw new IllegalArgumentException("'"+version+"' is not a valid version number"); } } /** * Initializes major,minor and bugfix which may contain wildcards here. */ private void init(String major,String minor,String bugfix) { if(!"*".equals(major)) { this.major=Integer.parseInt(major); majorDefined=true; } if(!"*".equals(minor)) { this.minor=Integer.parseInt(minor); minorDefined=true; } if(!"*".equals(bugfix)) { this.bugfix=Integer.parseInt(bugfix); bugfixDefined=true; } } /** * Compares this Version to an other Version. Both Versions may contain * wildcards. A Wildcard is considered equal to any corresponding digit. * E.g 1.8.5 and 1.8.* are considered equal. * @return -1 if this is less than other * 0 if this is equal to other * 1 if this is greater than other */ public int compareTo(Object other) { if(other==null) throw new NullPointerException(); if(!(other instanceof Version)) throw new ClassCastException(); Version version = (Version) other; if(majorDefined&&version.majorDefined) { if(majorversion.major) return 1; } if(minorDefined&&version.minorDefined) { if(minorversion.minor) return 1; } if(bugfixDefined&&version.bugfixDefined) { if(bugfixversion.bugfix) return 1; } return 0; } /** * Returns the string representation of this Version. */ public String toString() { StringBuffer buffer = new StringBuffer(); if(majorDefined) buffer.append(major); else buffer.append('*'); buffer.append('.'); if(minorDefined) buffer.append(minor); else buffer.append('*'); buffer.append('.'); if(bugfixDefined) buffer.append(bugfix); else buffer.append('*'); return buffer.toString(); } } /** * Represents a range of version numbers defined by a minimum and a maximum version number. * Used in build.xml in the propertes "includes" and "excludes" of -tag of this ant task. * String format: ..-.. e.g. includes="1.7.5-1.8.4" */ public static class VersionRange { final static Pattern pattern = Pattern.compile("((\\d+)\\.(\\d+)\\.(\\d+))-((\\d+)\\.(\\d+)\\.(\\d+))"); Version min,max; /** * Parses a version range from a String. * String format: ..-.. e.g. includes="1.7.5-1.8.4" * No withespaces are supported in this string. * @return the parsed range or null if the string does not contain a valid version range. */ public static VersionRange parse(String string) { Matcher matcher = pattern.matcher(string); if(matcher.matches()) { VersionRange result = new VersionRange(); String first = matcher.group(1); result.min=new Version(first,true); String second = matcher.group(5); result.max=new Version(second,true); return result; } else { return null; } } /** * Dedermines if the given version is contained in the range. * The borders of the range are inclusive meaning this method returns true * if min <= version or version <= max. */ public boolean isInRange(Version version) { return min.compareTo(version)<=0 && max.compareTo(version)>=0; } /** * Returns the string representation of the range. */ public String toString() { return min.toString() + "-" + max.toString(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy