View Javadoc
1 /*** 2 * Created by IntelliJ IDEA. 3 * User: Lennart 4 * Date: 24-okt-2003 5 * Time: 16:17:50 6 */ 7 package be.proteomics.maven.distrib; 8 9 import org.apache.maven.repository.GenericArtifact; 10 import org.apache.maven.project.Dependency; 11 12 import java.io.*; 13 import java.util.*; 14 import java.text.SimpleDateFormat; 15 16 17 /* 18 * CVS information: 19 * 20 * $Revision: 1.3 $ 21 * $Date: 2004/03/24 14:39:41 $ 22 */ 23 24 /*** 25 * This class implements a Java Bean for the distrib plugin in Maven that generates a page for 26 * downloading distributions of the software. <br /> 27 * The main responsability for this bean is to create the list of files, sort them in descending order 28 * and create a String with the XDOC code for the table that will hold the links and a description. 29 * 30 * @author Lennart Martens 31 */ 32 public class DistribBean { 33 34 /*** 35 * The String to hold the folder name retrieved by the Jelly script. 36 */ 37 private String iFolder = null; 38 39 /*** 40 * The String to hold the project ID as retrieved by the Jelly script. 41 */ 42 private String iProjectID = null; 43 44 /*** 45 * The file that all output will be written to by the Jelly script. 46 */ 47 private String iDestinationFile = null; 48 49 /*** 50 * The cached contents of the outputfile. 51 */ 52 private String iDestinationFileContents = null; 53 54 /*** 55 * The SimpleDateFormatter. 56 */ 57 private SimpleDateFormat iSDF = null; 58 59 /*** 60 * Default public constructor, as stipulated in the JavaBean contract. 61 */ 62 public DistribBean() {} 63 64 /*** 65 * The work horse of this bean. After construction of the bean, this is the thing to do. 66 * This method fills out the default last modified date format: 'dd/MM/yyyy'. 67 * 68 * @param aFolder String with the folder retrieved by the Jelly script. 69 * @param aID String with the project ID (as used in the artifacts). 70 * @param aDestinationFile outputfile for the generated HTML document. 71 */ 72 public String createDistribTable(String aFolder, String aID, String aDestinationFile) { 73 return this.createDistribTable(aFolder, aID, aDestinationFile, "dd/MM/yyyy"); 74 } 75 76 /*** 77 * The work horse of this bean. After construction of the bean, this is the thing to do. 78 * 79 * @param aFolder String with the folder retrieved by the Jelly script. 80 * @param aID String with the project ID (as used in the artifacts). 81 * @param aDestinationFile outputfile for the generated HTML document. 82 * @param aDateFormat String with the date format desired. 83 */ 84 public String createDistribTable(String aFolder, String aID, String aDestinationFile, String aDateFormat) { 85 // Just to separate the output block of this script from all others. 86 System.out.println(""); 87 iFolder = aFolder.replace('//', '/'); 88 iProjectID = aID; 89 iDestinationFile = aDestinationFile; 90 this.cacheDestinationFile(); 91 System.out.println(" [distrib] Creating distribution report based on the project jars in the '" + iFolder + "' folder."); 92 iSDF = new SimpleDateFormat(aDateFormat); 93 System.out.println(" [distrib] Using date format: " + aDateFormat + "."); 94 return this.generateHTMLTable(); 95 } 96 97 /*** 98 * This method creates the table with the direct download links for all the dependencies. 99 * 100 * @param aDependencies Collection with the dependencies from the Jelly script. 101 * @return String with the HTML code for the dependencies table. 102 */ 103 public String createDependenciesTable(Collection aDependencies) { 104 StringBuffer result = new StringBuffer(); 105 // See if there are any dependencies. 106 if(aDependencies != null && aDependencies.size() > 0) { 107 System.out.println(" [distrib] " + aDependencies.size() + " dependencies found. Creating table of links."); 108 result.append("\n\n\n<table>\n <tr>\n <th>Direct download link</th>\n <th>Project homepage link</th>\n </tr>\n"); 109 110 Iterator iter = aDependencies.iterator(); 111 while(iter.hasNext()) { 112 GenericArtifact ga = (GenericArtifact)iter.next(); 113 String filename = ga.getFile().getName(); 114 Dependency dp = ga.getDependency(); 115 String description = dp.getGroupId(); 116 String url = dp.getUrl(); 117 result.append(" <tr>\n"); 118 result.append(" <td><a href=\"" + filename + "\">" + filename + "</a></td>\n"); 119 result.append(" <td><a href=\""+ url + "\">" + description + "</a></td>\n"); 120 result.append(" </tr>\n"); 121 } 122 123 result.append("</table>\n\n\n"); 124 } else { 125 // No dependencies for this project. 126 System.out.println(" [distrib] No dependencies found. Omitting table of links."); 127 result.append("<i>No dependencies defined in this project</i>"); 128 } 129 130 return result.toString(); 131 } 132 133 /*** 134 * This method attempts to find the destination file, and when found, reads it into the 135 * iDestinationFileContents String variable. If the file was not found, or there was an 136 * error, this variable will be null. 137 */ 138 private void cacheDestinationFile() { 139 // Try to get our hands on the output file. 140 File output = new File(iDestinationFile); 141 if(output.exists()) { 142 StringBuffer temp = new StringBuffer(); 143 // Succes! The output file already is present! 144 // See if we can find an existing description for this distribution filename. 145 try { 146 BufferedReader br = new BufferedReader(new FileReader(iDestinationFile)); 147 String line = null; 148 while((line = br.readLine()) != null) { 149 temp.append(line + "\n"); 150 } 151 iDestinationFileContents = temp.toString(); 152 System.out.println(" [distrib] Existing output file found and read."); 153 br.close(); 154 } catch(IOException ioe) { 155 System.err.println(" [distrib] IOException while attempting to read '" + iDestinationFile + "': " + ioe.getMessage()); 156 } 157 } else { 158 System.out.println(" [distrib] No existing output file found."); 159 } 160 } 161 162 163 /*** 164 * This method takes care of generating the HTML code for the table. 165 * 166 * @return String with the HTML code for the table. 167 */ 168 private String generateHTMLTable() { 169 StringBuffer table = new StringBuffer("\n\n\n<table>\n <tr>\n <th>File download link</th>\n <th>Last modified on</th>\n" + 170 " <th>Description</th>\n </tr>\n"); 171 // Okay, let's find all files in the specified folder. 172 File folder = new File(iFolder); 173 if(!folder.exists()) { 174 try { 175 System.err.println(" [distrib] The folder you specified (" + folder.getCanonicalPath() + ") was not created by the Jelly script! Empty distributions table will be included."); 176 } catch(IOException ioe) { 177 ioe.printStackTrace(); 178 } 179 } else if(!folder.isDirectory()) { 180 System.err.println(" [distrib] The path you specified for writing the XDOC distribution xml page is not a folder! Empty distributions table will be included."); 181 } else { 182 // Now we can do something useful. 183 File[] toInclude = folder.listFiles(new FilenameFilter() { 184 public boolean accept(File dir, String name) { 185 boolean result = false; 186 // Filter on 'projectID'*'.jar'. 187 if(name.startsWith(iProjectID) && name.endsWith(".jar")) { 188 result = true; 189 } 190 return result; 191 } 192 }); 193 // Let's sort the array! 194 Arrays.sort(toInclude, new InnerDescendingFileVersionComparator()); 195 // Array sorted! The most recent one should go on top, so... 196 for(int i = 0; i < toInclude.length; i++) { 197 this.addTableRow(table, toInclude[i]); 198 } 199 } 200 table.append("</table>\n\n\n"); 201 return table.toString(); 202 } 203 204 /*** 205 * This method will add the row tag for the specified file to the specified StringBuffer. 206 * Note that this StringBufefr should already have an opening <table> tag set. 207 * 208 * @param aTable StringBuffer to add the <tr> element to. 209 * @param aFile File to add to the table. 210 */ 211 private void addTableRow(StringBuffer aTable, File aFile) { 212 String filename = aFile.getName(); 213 String description = this.attemptDescriptionRetrieval(filename); 214 aTable.append(" <tr>\n"); 215 aTable.append(" <td><a href=\"" + filename + "\">" + filename + "</a></td>\n"); 216 aTable.append(" <td>" + iSDF.format(new Date(aFile.lastModified())) + "</td>"); 217 // Note the '<!-- filename -->' and '<!-- /filename -->' tags to demarcate the description. 218 // These can later be used to retrieve edited descriptions. 219 aTable.append(" <td><!-- " + filename + " -->" + description + "<!-- /" + filename + " --></td>\n"); 220 aTable.append(" </tr>\n"); 221 } 222 223 /*** 224 * This method attempts to recall an existing description for the specified file. It will 225 * return the description found if succesfull, or 'aFilename + " version."' otherwise. 226 * 227 * @param aFilename String with the filename. 228 * @return String with the description (if found), 'aFilename + " version."' otherwise. 229 */ 230 private String attemptDescriptionRetrieval(String aFilename) { 231 // Start by filling out the default value for the description. 232 String result = aFilename + " version."; 233 // See if the output file was cached. If it wasn't, it is either absent or unreadable. 234 if(iDestinationFileContents != null) { 235 // Okay, in getting here, we can search for the filename in the cached contents of the 236 // output file. 237 int start = iDestinationFileContents.indexOf("<!-- " + aFilename + " -->"); 238 int descriptionStart = start + aFilename.length() + 9; 239 int end = iDestinationFileContents.indexOf("<!-- /" + aFilename + " -->", descriptionStart); 240 // Note that we require the presence of both start and end tags, and that the start tag 241 // should be positioned before the end tag in such a way that they are at least continuous. 242 // Of course, it would be much more fun if there were something useful in between these two tags. 243 if(start >= 0 && end >= 0 && (descriptionStart < end)) { 244 // Found the tags! Let's go get the description! 245 result = iDestinationFileContents.substring(descriptionStart, end).trim(); 246 System.out.println(" [distrib] Found existing description tag for '" + aFilename + "'!"); 247 } else { 248 // Tell the user. 249 System.out.println(" [distrib] Existing description tag for '" + aFilename + "' was not found."); 250 } 251 } 252 return result; 253 } 254 255 /*** 256 * The comparator that sorts Maven-generated jars files in descending according to 257 * their version number. 258 */ 259 private class InnerDescendingFileVersionComparator implements Comparator { 260 261 /*** 262 * This method will decide which of o1, o2 has precedence over the other. 263 * 264 * @param o1 Object to compare with o2. 265 * @param o2 Object to compare with o1. 266 * @return int with the result of the comparison. 267 */ 268 public int compare(Object o1, Object o2) { 269 int result = 0; 270 String a = ((File)o1).getName(); 271 String b = ((File)o2).getName(); 272 //System.out.println(" ** [distrib] Starting with: '" + a + "' and '" + b + "'."); 273 // Remove the leading project id and trailing '.jar', since this is 274 // a common feature (we've selected for this with the FilenameFilter). 275 a = a.substring(iProjectID.length(), a.lastIndexOf(".jar")); 276 b = b.substring(iProjectID.length(), b.lastIndexOf(".jar")); 277 // Leading '-' must be removed as well. 278 while(a.startsWith("-")) { 279 a = a.substring(1); 280 } 281 while(b.startsWith("-")) { 282 b = b.substring(1); 283 } 284 //System.out.println(" ** [distrib] Transformed into: '" + a + "' and '" + b + "'."); 285 // Break the filenames down in their constituent parts. 286 // and evaluate them. 287 // What we do is we check the part up to the first detected '.' 288 // then see if we have a difference. If we have one, calculate 289 // difference and quit. 290 // If we don't have a difference, find the next value up to the next 291 // '.' (or end of the String). Etc. 292 boolean lbContinue = true; 293 while(lbContinue) { 294 // If both a and b are empty Strings, we were/are unable to find a difference. 295 // This should not occur, since it means that the two initial files had the same name 296 // but we'll check anyway. 297 if(a.equals("") && b.equals("")) { 298 result = 0; 299 lbContinue = false; 300 continue; 301 } 302 // tempA equals a, in case there is no '.' left in a, 303 // tempA holds this value. 304 String tempA = a; 305 int startA = -1; 306 if((startA = a.indexOf(".")) >= 0) { 307 // tempA is the element up to the first '.'. 308 tempA = a.substring(0, startA); 309 // Truncate a to hold only the remainder after the first found '.' 310 a = a.substring(startA); 311 // If a holds more than just the '.', remove the '.'. 312 if(a.length() > 1) { 313 a = a.substring(1); 314 } else { 315 // a is just an empty String. 316 a = ""; 317 } 318 } else { 319 a = ""; 320 } 321 // Same for b. 322 String tempB = b; 323 int startB = -1; 324 if((startB = b.indexOf(".")) >= 0) { 325 // tempB is the element up to the first '.'. 326 tempB = b.substring(0, startB); 327 // Truncate a to hold only the remainder after the first found '.' 328 b = b.substring(startB); 329 // If b holds more than just the '.', remove the '.'. 330 if(b.length() > 1) { 331 b = b.substring(1); 332 } else { 333 // b is just an empty String. 334 b = ""; 335 } 336 } else { 337 b = ""; 338 } 339 //System.out.println(" ** [distrib ] tempA (a): '" + tempA + "' (" + a + ") and tempB (b): '" + tempB + "' (" + b + ")."); 340 // Okay, compare tempA and tempB. 341 // See what the Stringcompare tells us. 342 int tempResult = tempA.compareTo(tempB); 343 if(tempResult != 0) { 344 result = tempResult; 345 lbContinue = false; 346 continue; 347 } else { 348 // Just go on with the show. 349 } 350 } 351 // Descending order is requested. 352 return -result; 353 } 354 } 355 }

This page was automatically generated by Maven