blob: a8398f17430765b0ee1fe57509c9a502e55fb770 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SelectBundle
* property to set
* basename (bnd, org.eclipse.equinox) required
* separator (-,_) default to _
* criterion OSGi selection criteria [1.0,2.0) required
*
* Contributors:
* egwin - initial conception and implementation
*/
package org.eclipse.persistence.buildtools.ant.taskdefs;
import java.io.File;
import java.io.FilenameFilter;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
import org.eclipse.persistence.buildtools.helper.Version;
public class SelectBundle extends Task {
private boolean includepath = false; // whether to include the path (directory property) in the value of property if selection is successful (default: no)
private boolean versiononly = false; // whether to return bundle version info only, or full bundle name (default: full bundle name)
private String criterion = ""; // the OSGi-like criteria used to 'select' the most appropriate jar. for example:(1.0,2.0]
private String basename = ""; // basename of jar (org.eclipse.persistence.jpa, javax.xml.bind, javax.persistence)
private String directory = ""; // directory to search for the jar
private String property = ""; // property to set with filename of 'selected' jar
private String separator = "_"; // the separator used to differentiate basename and jarversion
private String suffix = "jar"; // suffix of file to find (default: jar)
private boolean minInclusive = false; // local: whether the 'floor' version is inclusive or not "("=true "["=false
private boolean maxInclusive = false; // local: whether the 'ceiling' version is inclusive or not "("=true "["=false
private Version minVersion = null; // local: the value of the "floor" version
private Version maxVersion = null; // local: the value of the "ceiling" version
private String version = ""; // the 'version' component of the "bestmatch" string
private void evaluateCriteria() throws BuildException {
// ()= includes
// []= up to, not including
// should be at most 1 ','
// can have 1 version, or two containing up to four version parts (major.minor.bugfix.qualifier)
if ( !( criterion == null || criterion.length() == 0)) {
int endIndex = criterion.length() - 1;
boolean minSquareBracket = criterion.startsWith("[");
boolean maxSquareBracket = criterion.endsWith("]");
boolean minRoundBracket = criterion.startsWith("(");
boolean maxRoundBracket = criterion.endsWith(")");
boolean initInt = criterion.substring(0,1).contains("0123456789");
boolean endInt = criterion.substring(endIndex-1,endIndex).contains("0123456789");
boolean commapresent = criterion.contains(",");
// validate beginning of string
if ( !( minSquareBracket || minRoundBracket || initInt ) )
throw new BuildException("The criterion attribute must begin with (,[, or a number.", getLocation());
// validate end of string
if ( !( maxSquareBracket || maxRoundBracket || endInt ) )
throw new BuildException("The criterion attribute must end with ),], or a number.", getLocation());
// validate basic syntax
if((initInt && !endInt) || (!initInt && endInt) || (!initInt && !commapresent) || (initInt && commapresent) )
throw new BuildException("The criterion attribute must be a valid OSGi version range string", getLocation());
// determine "floor" version
minInclusive = (minSquareBracket || initInt);
maxInclusive = (maxSquareBracket || endInt);
//singleton version
if(initInt) {
log("evaluateCriteria: Singleton detected", Project.MSG_VERBOSE);
minVersion = new Version(criterion);
// an approximation of infinity (high value for major.monor.micro and qualifier)
maxVersion = new Version("99999.99999.99999.ÿÿÿÿÿÿ");
}
// version range
if(!initInt) {
log("evaluateCriteria: Range(min:" + criterion.substring(1,criterion.indexOf(',')) + ")", Project.MSG_VERBOSE);
minVersion = new Version( criterion.substring(1,criterion.indexOf(',')) );
}
if(!endInt) {
log("evaluateCriteria: Range(max:" + criterion.substring(criterion.indexOf(',')+1,endIndex) + ")", Project.MSG_VERBOSE);
maxVersion = new Version( criterion.substring(criterion.indexOf(',')+1,endIndex) );
}
}
else {
// criteria not specified. Default is "any version" or "[0.0,infinity]"
minInclusive = true;
minVersion = new Version();
// an approximation of infinity (high value for major.monor.micro and qualifier)
maxVersion = new Version("99999.99999.99999.ÿÿÿÿÿÿ");
}
// Debug Logging
if(minInclusive)
log("evaluateCriteria: minInclusive(true)", Project.MSG_VERBOSE);
else
log("evaluateCriteria: minInclusive(false)", Project.MSG_VERBOSE);
if(maxInclusive)
log("evaluateCriteria: maxInclusive(true)", Project.MSG_VERBOSE);
else
log("evaluateCriteria: maxInclusive(false)", Project.MSG_VERBOSE);
log("evaluateCriteria: minVersion(" + minVersion.getIdentifier() + ")", Project.MSG_VERBOSE);
log("evaluateCriteria: maxVersion(" + maxVersion.getIdentifier() + ")", Project.MSG_VERBOSE);
}
private String matchCriteria() {
String bestMatch = null; //filename of file selected
String[] filelist = getListOfFiles(directory);
log("matchCriteria: basename.length='" + Integer.toString(basename.length()) + "'", Project.MSG_VERBOSE);
log("matchCriteria: separator.length='" + Integer.toString(separator.length()) + "'", Project.MSG_VERBOSE);
int relativeVersionIndex = basename.length() + separator.length();
log("matchCriteria: relativeVersionIndex(" + Integer.toString(relativeVersionIndex) + ")", Project.MSG_VERBOSE);
if( filelist != null ) {
log("matchCriteria: filelist.length='" + Integer.toString(filelist.length) + "'", Project.MSG_VERBOSE);
for ( int i=0; i<filelist.length; i++ )
{
int versionEndIndex = filelist[i].indexOf("."+suffix);
log("matchCriteria: versionEndIndex(" + Integer.toString(versionEndIndex)+")", Project.MSG_VERBOSE);
log("matchCriteria: filelist["+ Integer.toString(i) + "](" + filelist[i] + ")", Project.MSG_VERBOSE);
// Should add try block to test for version exception
version = filelist[i].substring(relativeVersionIndex,versionEndIndex);
log("matchCriteria: version string of found file(" + version + ")", Project.MSG_VERBOSE);
if(version.length()>0){
if(minInclusive && maxInclusive) {
if(minVersion.le(version) && maxVersion.ge(version) ){
bestMatch = filelist[i];
}
}
else if (minInclusive && !maxInclusive){
if(minVersion.le(version) && maxVersion.gt(version) ){
bestMatch = filelist[i];
}
}
else if (!minInclusive && maxInclusive){
if(minVersion.lt(version) && maxVersion.ge(version) ){
bestMatch = filelist[i];
}
}
else if (!minInclusive && !maxInclusive ){
if(minVersion.lt(version) && maxVersion.gt(version) ){
bestMatch = filelist[i];
}
}
log("matchCriteria: Best Match so far(" + bestMatch + ")", Project.MSG_VERBOSE);
}
}
log("matchCriteria: BestMatch(" + bestMatch + ")", Project.MSG_VERBOSE);
}
else log("matchCriteria: filelist is null!", Project.MSG_VERBOSE);
return bestMatch;
}
private String[] getListOfFiles(String directory) {
class MyFilter implements FilenameFilter
{
public boolean accept(File directory, String filepattern)
{
if ( filepattern.startsWith(basename + separator) && filepattern.endsWith("." + suffix) ) return true;
return false;
}
}
return new java.io.File(directory).list( new MyFilter() );
}
// The "meat"
public void execute() throws BuildException {
if (getProject() == null) {
throw new IllegalStateException("Project not set!");
}
if (basename == null || basename.length() == 0) {
throw new BuildException("The basename attribute must be present.", getLocation());
}
if (directory == null || directory.length() == 0) {
throw new BuildException("The directory attribute must be present.", getLocation());
}
if (property == null || property.length() == 0) {
throw new BuildException("The property attribute must be present.", getLocation());
}
log("execute: ** Evaluate **", Project.MSG_VERBOSE);
evaluateCriteria();
log("execute: ** Match **", Project.MSG_VERBOSE);
String file = matchCriteria();
if( file != null ){
if (includepath)
getProject().setNewProperty(property, directory+"/"+file);
else {
if (versiononly)
getProject().setNewProperty(property, version);
else
getProject().setNewProperty(property, file);
}
}
log("execute: Search Finished.", Project.MSG_VERBOSE);
}
// Setters
public void setIncludepath(boolean includepath) {
this.includepath = includepath;
}
public void setVersionOnly(boolean versiononly) {
this.versiononly = versiononly;
}
public void setCriterion(String criterion) {
this.criterion = criterion;
}
public void setBasename(String basename) {
this.basename = basename;
}
public void setDirectory(String directory) {
this.directory = directory;
log("setDirectory: directory='" + directory + "'", Project.MSG_VERBOSE);
}
public void setProperty(String property) {
this.property = property;
}
public void setSeparator(String separator) {
if ( (separator.length() > 1) || (separator.length() == 0) ) {
throw new BuildException("The separator attribute can only be a single character.", getLocation());
}
this.separator = separator;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
}