/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * RepositoryIndexGenerator.java * Copyright (C) 2000-2012 University of Waikato, Hamilton, New Zealand * */ package weka.core; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeMap; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * Class for generating html index files and supporting text files for a Weka * package meta data repository. To Run<br> * <br> * * <code>java weka.core.RepositoryIndexGenerator <path to repository></code> * * @author Mark Hall (mhall{[at]}pentaho{[dot]}com) * @version $Revision: 8989 $ */ public class RepositoryIndexGenerator { public static String HEADER = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n" + "<html>\n<head>\n<title>Waikato Environment for Knowledge Analysis (WEKA)</title>\n" + "<!-- CSS Stylesheet -->\n<style>body\n{\nbackground: #ededed;\ncolor: #666666;\n" + "font: 14px Tahoma, Helvetica, sans-serif;;\nmargin: 5px 10px 5px 10px;\npadding: 0px;\n" + "}\n</style>\n\n</head>\n<body bgcolor=\"#ededed\" text=\"#666666\">\n"; public static String BIRD_IMAGE1 = "<img src=\"Title-Bird-Header.gif\">\n"; public static String BIRD_IMAGE2 = "<img src=\"../Title-Bird-Header.gif\">\n"; public static String PENTAHO_IMAGE1 = "<img src=\"pentaho_logo_rgb_sm.png\">\n\n"; public static String PENTAHO_IMAGE2 = "<img src=\"../pentaho_logo_rgb_sm.png\">\n\n"; private static int[] parseVersion(String version) { int major = 0; int minor = 0; int revision = 0; int[] majMinRev = new int[3]; try { String tmpStr = version; tmpStr = tmpStr.replace('-', '.'); if (tmpStr.indexOf(".") > -1) { major = Integer.parseInt(tmpStr.substring(0, tmpStr.indexOf("."))); tmpStr = tmpStr.substring(tmpStr.indexOf(".") + 1); if (tmpStr.indexOf(".") > -1) { minor = Integer.parseInt(tmpStr.substring(0, tmpStr.indexOf("."))); tmpStr = tmpStr.substring(tmpStr.indexOf(".") + 1); if (!tmpStr.equals("")) { revision = Integer.parseInt(tmpStr); } else { revision = 0; } } else { if (!tmpStr.equals("")) { minor = Integer.parseInt(tmpStr); } else { minor = 0; } } } else { if (!tmpStr.equals("")) { major = Integer.parseInt(tmpStr); } else { major = 0; } } } catch (Exception e) { e.printStackTrace(); major = -1; minor = -1; revision = -1; } finally { majMinRev[0] = major; majMinRev[1] = minor; majMinRev[2] = revision; } return majMinRev; } private static String cleansePropertyValue(String propVal) { propVal = propVal.replace("<", "<"); propVal = propVal.replace(">", ">"); propVal = propVal.replace("@", "{[at]}"); propVal = propVal.replace("\n", "<br/>"); return propVal; } protected static int compare(String version1, String version2) { // parse both of the versions int[] majMinRev1 = parseVersion(version1); int[] majMinRev2 = parseVersion(version2); int result; if (majMinRev1[0] < majMinRev2[0]) { result = -1; } else if (majMinRev1[0] == majMinRev2[0]) { if (majMinRev1[1] < majMinRev2[1]) { result = -1; } else if (majMinRev1[1] == majMinRev2[1]) { if (majMinRev1[2] < majMinRev2[2]) { result = -1; } else if (majMinRev1[2] == majMinRev2[2]) { result = 0; } else { result = 1; } } else { result = 1; } } else { result = 1; } return result; } private static String[] processPackage(File packageDirectory) throws Exception { System.err.println("Processing " + packageDirectory); File[] contents = packageDirectory.listFiles(); File latest = null; ArrayList<File> propsFiles = new ArrayList<File>(); StringBuffer versionsTextBuffer = new StringBuffer(); for (int i = 0; i < contents.length; i++) { if (contents[i].isFile() && contents[i].getName().endsWith(".props")) { propsFiles.add(contents[i]); if (contents[i].getName().equals("Latest.props")) { latest = contents[i]; } /* * else { String versionNumber = contents[i].getName().substring(0, * contents[i].getName().indexOf(".props")); * versionsTextBuffer.append(versionNumber + "\n"); } */ } } File[] sortedPropsFiles = propsFiles.toArray(new File[0]); Arrays.sort(sortedPropsFiles, new Comparator<File>() { @Override public int compare(File first, File second) { String firstV = first.getName().substring(0, first.getName().indexOf(".props")); String secondV = second.getName().substring(0, second.getName().indexOf(".props")); if (firstV.equalsIgnoreCase("Latest")) { return -1; } else if (secondV.equalsIgnoreCase("Latest")) { return 1; } return -RepositoryIndexGenerator.compare(firstV, secondV); } }); StringBuffer indexBuff = new StringBuffer(); indexBuff.append(HEADER + "\n\n"); // indexBuff.append(HEADER + BIRD_IMAGE2); // indexBuff.append(PENTAHO_IMAGE2); Properties latestProps = new Properties(); latestProps.load(new BufferedReader(new FileReader(latest))); String packageName = latestProps.getProperty("PackageName") + ": "; String packageTitle = latestProps.getProperty("Title"); String packageCategory = latestProps.getProperty("Category"); String latestVersion = latestProps.getProperty("Version"); if (packageCategory == null) { packageCategory = ""; } indexBuff.append("<h2>" + packageName + packageTitle + "</h2>\n\n"); String author = latestProps.getProperty("Author"); author = cleansePropertyValue(author); String URL = latestProps.getProperty("URL"); if (URL != null) { URL = cleansePropertyValue(URL); } String maintainer = latestProps.getProperty("Maintainer"); maintainer = cleansePropertyValue(maintainer); indexBuff.append("\n<table>\n"); if (URL != null && URL.length() > 0) { indexBuff.append("<tr><td valign=top>" + "URL" + ":</td><td width=50></td>"); URL = "<a href=\"" + URL + "\">" + URL + "</a>"; indexBuff.append("<td>" + URL + "</td></tr>\n"); } indexBuff.append("<tr><td valign=top>" + "Author" + ":</td><td width=50></td>"); indexBuff.append("<td>" + author + "</td></tr>\n"); indexBuff.append("<tr><td valign=top>" + "Maintainer" + ":</td><td width=50></td>"); indexBuff.append("<td>" + maintainer + "</td></tr>\n"); indexBuff.append("</table>\n<p>\n"); String description = latestProps.getProperty("Description"); indexBuff.append("<p>" + description.replace("\n", "<br/>") + "</p>\n\n"); indexBuff.append("<p>All available versions:<br>\n"); for (int i = 0; i < sortedPropsFiles.length; i++) { if (i > 0) { String versionNumber = sortedPropsFiles[i].getName().substring(0, sortedPropsFiles[i].getName().indexOf(".props")); versionsTextBuffer.append(versionNumber + "\n"); System.err.println(versionNumber); } String name = sortedPropsFiles[i].getName(); name = name.substring(0, name.indexOf(".props")); indexBuff.append("<a href=\"" + name + ".html" + "\">" + name + "</a><br>\n"); StringBuffer version = new StringBuffer(); version.append(HEADER + "\n\n"); // version.append(HEADER + BIRD_IMAGE2); // version.append(PENTAHO_IMAGE2); version.append("<table summary=\"Package " + packageName + " summary\">\n"); Properties versionProps = new Properties(); versionProps .load(new BufferedReader(new FileReader(sortedPropsFiles[i]))); Set<Object> keys = versionProps.keySet(); String[] sortedKeys = keys.toArray(new String[0]); Arrays.sort(sortedKeys); // Iterator<Object> keyI = keys.iterator(); // while (keyI.hasNext()) { for (String key : sortedKeys) { // String key = (String)keyI.next(); if (key.equalsIgnoreCase("PackageName") || key.equalsIgnoreCase("Title") || /* key.equalsIgnoreCase("Description") || */ key.equalsIgnoreCase("DoNotLoadIfFileNotPresentMessage") || key.equalsIgnoreCase("DoNotLoadIfClassNotPresentMessage") || key.equalsIgnoreCase("DoNotLoadIfEnvVarNotSetMessage")) { } else { version.append("<tr><td valign=top>" + key + ":</td><td width=50></td>"); String propValue = versionProps.getProperty(key); if (!key.equalsIgnoreCase("Description")) { propValue = propValue.replace("<", "<"); propValue = propValue.replace(">", ">"); propValue = propValue.replace("@", "{[at]}"); propValue = propValue.replace("\n", "<br/>"); } /* * if (key.equals("Author") || key.equals("Maintainer")) { propValue = * propValue.replace(".", "{[dot]}"); } */ if (key.equals("PackageURL") || key.equals("URL")) { propValue = "<a href=\"" + propValue + "\">" + propValue + "</a>"; } version.append("<td>" + propValue + "</td></tr>\n"); } } version.append("</table>\n</body>\n</html>\n"); String versionHTMLFileName = packageDirectory.getAbsolutePath() + File.separator + name + ".html"; BufferedWriter br = new BufferedWriter( new FileWriter(versionHTMLFileName)); br.write(version.toString()); br.flush(); br.close(); } indexBuff.append("</body>\n</html>\n"); String packageIndexName = packageDirectory.getAbsolutePath() + File.separator + "index.html"; BufferedWriter br = new BufferedWriter(new FileWriter(packageIndexName)); br.write(indexBuff.toString()); br.flush(); br.close(); // write the versions file to the directory String packageVersionsName = packageDirectory.getAbsolutePath() + File.separator + "versions.txt"; br = new BufferedWriter(new FileWriter(packageVersionsName)); br.write(versionsTextBuffer.toString()); br.flush(); br.close(); // return indexBuff.toString(); String[] returnInfo = new String[3]; returnInfo[0] = packageTitle; returnInfo[1] = packageCategory; returnInfo[2] = latestVersion; return returnInfo; } private static void writeMainIndex(Map<String, String[]> packages, File repositoryHome) throws Exception { StringBuffer indexBuf = new StringBuffer(); StringBuffer packageList = new StringBuffer(); // new package list that includes version number of latest version of each // package. We keep the old package list as well for backwards compatibility StringBuffer packageListPlusVersion = new StringBuffer(); indexBuf.append(HEADER + BIRD_IMAGE1); indexBuf.append(PENTAHO_IMAGE1); indexBuf.append("<h1>WEKA Packages </h1>\n\n"); indexBuf.append(/* * "<h3>Download WekaLite</h3>\n<a href=\"wekaLite.jar\">wekaLite.jar</a>" * + */ "<p><b>IMPORTANT: make sure there are no old versions of Weka (<3.7.2) in " + "your CLASSPATH before starting Weka</b>\n\n"); indexBuf.append("<h3>Installation of Packages</h3>\n"); indexBuf .append("A GUI package manager is available from the \"Tools\" menu of" + " the GUIChooser<br><br><code>java -jar weka.jar</code><p>\n\n"); indexBuf.append("For a command line package manager type" + ":<br><br<code>java weka.core.WekaPackageManager -h" + "</code><br><br>\n"); indexBuf.append("<hr/>\n"); indexBuf .append("<h3>Running packaged algorithms from the command line</h3>" + "<code>java weka.Run [algorithm name]</code><p>" + "Substring matching is also supported. E.g. try:<br><br>" + "<code>java weka.Run Bayes</code><hr/>"); Set<String> names = packages.keySet(); indexBuf.append("<h3>Available Packages (" + packages.keySet().size() + ")</h3>\n\n"); indexBuf.append("<table>\n"); Iterator<String> i = names.iterator(); while (i.hasNext()) { String packageName = i.next(); String[] info = packages.get(packageName); String packageTitle = info[0]; String packageCategory = info[1]; String latestVersion = info[2]; String href = "<a href=\"./" + packageName + "/index.html\">" + packageName + "</a>"; indexBuf.append("<tr valign=\"top\">\n"); indexBuf.append("<td>" + href + "</td><td width=50></td><td>" + packageCategory + "</td><td width=50></td><td>" + packageTitle + "</td></tr>\n"); // append to the package list packageList.append(packageName + "\n"); packageListPlusVersion.append(packageName).append(":") .append(latestVersion).append("\n"); } indexBuf.append("</table>\n<hr/>\n</body></html>\n"); String indexName = repositoryHome.getAbsolutePath() + File.separator + "index.html"; BufferedWriter br = new BufferedWriter(new FileWriter(indexName)); br.write(indexBuf.toString()); br.flush(); br.close(); String packageListName = repositoryHome.getAbsolutePath() + File.separator + "packageList.txt"; br = new BufferedWriter(new FileWriter(packageListName)); br.write(packageList.toString()); br.flush(); br.close(); packageListName = repositoryHome.getAbsolutePath() + File.separator + "packageListWithVersion.txt"; br = new BufferedWriter(new FileWriter(packageListName)); br.write(packageListPlusVersion.toString()); br.flush(); br.close(); String numPackagesName = repositoryHome.getAbsolutePath() + File.separator + "numPackages.txt"; br = new BufferedWriter(new FileWriter(numPackagesName)); br.write(packages.keySet().size() + "\n"); br.flush(); br.close(); // create zip archive writeRepoZipFile(repositoryHome, packageList); } private static void transBytes(BufferedInputStream bi, ZipOutputStream z) throws Exception { int b; while ((b = bi.read()) != -1) { z.write(b); } } protected static void writeZipEntryForPackage(File repositoryHome, String packageName, ZipOutputStream zos) throws Exception { ZipEntry packageDir = new ZipEntry(packageName + "/"); zos.putNextEntry(packageDir); ZipEntry z = new ZipEntry(packageName + "/Latest.props"); ZipEntry z2 = new ZipEntry(packageName + "/Latest.html"); FileInputStream fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + packageName + File.separator + "Latest.props"); BufferedInputStream bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + packageName + File.separator + "Latest.html"); bi = new BufferedInputStream(fi); zos.putNextEntry(z2); transBytes(bi, zos); bi.close(); // write the versions.txt file to the zip z = new ZipEntry(packageName + "/versions.txt"); fi = new FileInputStream(packageName + File.separator + "versions.txt"); bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); // write the index.html to the zip z = new ZipEntry(packageName + "/index.html"); fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + packageName + File.separator + "index.html"); bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); // Now process the available versions FileReader vi = new FileReader(repositoryHome.getAbsolutePath() + File.separator + packageName + File.separator + "versions.txt"); BufferedReader bvi = new BufferedReader(vi); String version; while ((version = bvi.readLine()) != null) { z = new ZipEntry(packageName + "/" + version + ".props"); fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + packageName + File.separator + version + ".props"); bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); z = new ZipEntry(packageName + "/" + version + ".html"); fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + packageName + File.separator + version + ".html"); bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); } } protected static void writeRepoZipFile(File repositoryHome, StringBuffer packagesList) { System.out.print("Writing repo archive"); StringReader r = new StringReader(packagesList.toString()); BufferedReader br = new BufferedReader(r); String packageName; try { FileOutputStream fo = new FileOutputStream( repositoryHome.getAbsolutePath() + File.separator + "repo.zip"); ZipOutputStream zos = new ZipOutputStream(fo); while ((packageName = br.readLine()) != null) { writeZipEntryForPackage(repositoryHome, packageName, zos); System.out.print("."); } System.out.println(); // include the package list (legacy) in the zip ZipEntry z = new ZipEntry("packageList.txt"); FileInputStream fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + "packageList.txt"); BufferedInputStream bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); // include the package list with latest version numbers z = new ZipEntry("packageListWithVersion.txt"); fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + "packageListWithVersion.txt"); bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); // Include the top level images FileReader fr = new FileReader(repositoryHome.getAbsolutePath() + File.separator + "images.txt"); br = new BufferedReader(fr); String imageName; while ((imageName = br.readLine()) != null) { z = new ZipEntry(imageName); fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + imageName); bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); } // include the image list in the zip z = new ZipEntry("images.txt"); fi = new FileInputStream(repositoryHome.getAbsolutePath() + File.separator + "images.txt"); bi = new BufferedInputStream(fi); zos.putNextEntry(z); transBytes(bi, zos); bi.close(); zos.close(); File f = new File(repositoryHome.getAbsolutePath() + File.separator + "repo.zip"); long size = f.length(); // write the size of the repo (in KB) to a file FileWriter fw = new FileWriter(repositoryHome.getAbsolutePath() + File.separator + "repoSize.txt"); if (size > 1024) { size /= 1024; } fw.write("" + size); fw.flush(); fw.close(); } catch (Exception ex) { ex.printStackTrace(); } } /** * Main method for running the RepositoryIndexGenerator * * @param args first argument needs to be the path the the repository. */ public static void main(String[] args) { try { if (args.length < 1) { System.err .println("Usage:\n\n\tRepositoryIndexGenerator <path to repository>"); System.exit(1); } StringBuffer mainIndex = new StringBuffer(); File repositoryHome = new File(args[0]); TreeMap<String, String[]> packages = new TreeMap<String, String[]>(); // ArrayList<File> packages = new ArrayList<File>(); File[] contents = repositoryHome.listFiles(); for (int i = 0; i < contents.length; i++) { if (contents[i].isDirectory()) { // packages.add(contents[i]); // process this package and create its index String[] packageInfo = processPackage(contents[i]); packages.put(contents[i].getName(), packageInfo); } } // write the main index file writeMainIndex(packages, repositoryHome); } catch (Exception ex) { ex.printStackTrace(); } } }