/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2004
* Copyright by ESO (in the framework of the ALMA collaboration),
* All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package alma.acs.eclipse.utils.pluginbuilder;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Set;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Read the list of jars from the <code>build.properties</code>.
*
* @author acaproni
* @since ACS-8.0.1
*
*/
public class BuildProperties {
/**
* The name of the file of eclipse properties to read
*/
public static final String fileOfProperties = "build.properties";
/**
* The regular expression with the name of the property in the
* <code>fileOfProperties</code> listing the required jars.
*/
public final Pattern propertyPattern = Pattern.compile("\\s*jars.extra.classpath\\s*=\\s*");
/**
* The regular expression with the name of a jar
*/
public final Pattern jarPattern = Pattern.compile(".*jar");
/**
* The list of required jars read from the file.
* <P>
* The vector preserve the order i.e. item at position 0
* contains the first read jar and so on.
* <P>
* The name of a jar is intended as written in the <code>fileOfProperties</code>
* file like for example <code>platform:/plugin/ACS_Utility_Jars/jacorb.jar</code>.
* <P><b>Note</b>: the order of the entries in the file is important and therefore
* a {@link Set} can't be used.
*/
private final Vector<String> classpathEntries = new Vector<String>();
/**
* Constructor
*
* @param folder The folder containing the <code>fileOfProperties</code> file.
*/
public BuildProperties(String folder) throws Exception {
if (folder==null || folder.isEmpty()) {
throw new IllegalArgumentException("Invalid folder: "+folder);
}
File f = new File(folder+"/"+fileOfProperties);
try {
generateListOfJars(f);
} catch (Throwable t) {
System.out.println(t.getMessage());
t.printStackTrace();
throw new Exception("Error reading "+f.getAbsolutePath(),t);
}
System.out.println(""+classpathEntries.size()+" jars found in "+fileOfProperties);
}
/**
* Read the file and get the jars of the
* <code>propertyPattern</code> property.
* <P>
* Implementation note:
* <OL>
* <LI>scan the file until found a string matching <code>propertyPattern</code>
* <LI>read and concatenate all the jars in the string
* <LI>repeat the previous step if the line continue in the next line
* i.e. the line terminates with "\"
* <LI>clean the string and extract the jar names
* </OL>
*
* @param inF The file to read the list of jars from
*/
private void generateListOfJars(File inF) throws Exception {
if (inF==null || !inF.canRead()) {
throw new IllegalArgumentException("Invalid file");
}
// The reader of the file
BufferedReader reader = new BufferedReader(new FileReader(inF));
// The string containing all the requested jars
StringBuilder builder = new StringBuilder();
// Read all the lines until find the propertyPattern
String line=null;
boolean found = false;
while ((line=reader.readLine())!=null) {
if (line.isEmpty() || line.indexOf("=")==-1) {
// Skip empty lines
continue;
}
String str=line.substring(0, line.indexOf("=")+1);
Matcher m = propertyPattern.matcher(str);
if (m.matches()) {
found=true;
break;
}
}
if (!found) {
throw new Exception(propertyPattern.pattern()+" not found");
}
// The first line starts with the name of the property
Pattern p = Pattern.compile(".*\\\\s*");
// Clean line
String[] temp = propertyPattern.split(line);
System.out.println(temp.length);
for (String s: temp) {
System.out.println(s);
}
line=temp[1];
// The following loop matches all the lines ending with ,\
// i.e. the last line with a valid jar of build.properties
// is not caught by the loop
while (p.matcher(line).matches()) {
// The line ends with ",\"
line = line.trim();
line = line.replace('\\', ' ');
builder.append(line.trim());
line=reader.readLine();
}
builder.append(line.trim());
System.out.println("FOUND: "+builder.toString()+"\n");
// Some cleaning
String str= builder.toString().replaceAll(" ", " ");
while (!str.replaceAll(" ", " ").equals(str)) {
str=str.replaceAll(" ", " ");
}
// Extract the jars and put their names in the classpathEntries vector
String[] pkgs= str.split(",");
for (String jar: pkgs) {
System.out.println("\t>> ["+jar+"]");
classpathEntries.add(jar);
}
System.out.println(classpathEntries.size());
removeDuplicates(classpathEntries);
}
/**
* Get the names of the jars in the passed string String
* <P>
* The names of the jars are intended as written in the <code>fileOfProperties</code>
* file like for example <code>platform:/plugin/ACS_Utility_Jars/jacorb.jar</code>.
* <P>
* A line can contain a comma separated list of jars
*
* @param str The string containing a jar
* @return The names of the jars or
* <code>null</code> if the string does not contain a jar
*/
private String getJarNames(String str) {
if (str==null || str.isEmpty()) {
return null;
}
str=str.trim();
System.out.println("Checking ["+str+"]");
// Check if the line is that containing the name of the property
if (str.indexOf("=")!=-1) {
String[] items = propertyPattern.split(str,1);
System.out.println(items.length);
for (String temp: items) {
System.out.println("\t"+temp);
}
str= items[0].trim();
}
// Clean the string by removing any extra char at the end (",\" for instance)
if (str.endsWith("\\")) {
str = str.substring(0,str.length()-1).trim();
}
return str;
}
/**
* Remove duplicated entries from the vector.
* <P>
* Given that the order of the entries is important, in case
* the same entry appears more then once, the last one will be
* removed.
*
* @param v
*/
private void removeDuplicates(Vector<String> v) {
if (v==null || v.size()==0) {
return;
}
for (int t=0; t<v.size(); t++) {
int pos;
do {
pos = v.lastIndexOf(v.get(t));
if (pos>=0 && pos>t) {
v.remove(pos);
}
}
while (pos>t && pos>=0);
}
}
/**
* Return the name of the jars in the <code>build.properties</code>
* like for example <code>acscommon.jar</code>
*
* @return The name of the jars
*/
public String[] getJars() throws Exception {
String[] ret = new String[classpathEntries.size()];
for (int t=0; t<classpathEntries.size(); t++) {
String fullJarName=classpathEntries.get(t);
if (!fullJarName.toLowerCase().endsWith(".jar")) {
throw new Exception("Wrong jar file name in "+fileOfProperties+": "+fullJarName);
}
fullJarName=fullJarName.trim();
String str[]=fullJarName.split("/");
ret[t]=str[str.length-1];
}
return ret;
}
}