/******************************************************************************* * Copyright (c) 2007, 2008 Edgar Espina. * 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 * *******************************************************************************/ package org.deved.antlride.core.resources; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.deved.antlride.core.AntlrCore; import org.deved.antlride.core.env.JavaEnvironment; import org.deved.antlride.core.env.JavaEnvironmentRepository; import org.deved.antlride.core.env.JavaEnvironmentRepositoryLookup; import org.eclipse.core.runtime.IPath; public class AntlrPackages { private static final String ANTLR_AVAILABLE_PKG = "antlr.packages"; public static final String[] PROPERTIES = { "Version", "Description" }; private static final Pattern VERSION = Pattern.compile("\\d+(\\.\\w+)+"); private static final String PACKAGES_FILE = "antlr-packages.xml"; private static final String ANTLR_DESC = "antlr.%s.desc"; private static final String ANTLR_CP = "antlr.%s.cp"; private static final String ANTLR_CREATED = "antlr.%s.created"; private static final String ANTLR_SELECTED = "antlr.%s.selected"; private static final String ANTLR_HOME = "antlr.%s.home"; private static ArrayList<AntlrPackage> _packageList; private List<AntlrPackage> packageList; private AntlrPackages(List<AntlrPackage> packageList) { this.packageList = new ArrayList<AntlrPackage>(packageList); } public static AntlrPackages getInstance() { // force a reload from disk _packageList = null; return new AntlrPackages(getCachedPackageList()); } public boolean exist(AntlrPackage antlrPackage) { return packageList.contains(antlrPackage); } public boolean register(AntlrPackage antlrPackage) { if (!packageList.contains(antlrPackage)) { packageList.add(antlrPackage); if (packageList.size() == 1) { antlrPackage.setSelected(true); } return true; } return false; } public void unregister(AntlrPackage antlrPackage) { packageList.remove(antlrPackage); } public void save() throws IOException { getCachedPackageList().clear(); getCachedPackageList().addAll(packageList); savePackages(); } public AntlrPackage[] getPackages() { return packageList.toArray(new AntlrPackage[packageList.size()]); } public static AntlrPackage[] getAvailablePackages() { List<AntlrPackage> list = getCachedPackageList(); return list.toArray(new AntlrPackage[list.size()]); } public static AntlrPackage getPackage(String pckname) { List<AntlrPackage> list = getCachedPackageList(); for (AntlrPackage ap : list) { if (ap.getVersion().equals(pckname)) { return ap; } } return null; } public AntlrPackage getSelectedPackage() { for (AntlrPackage antlrPackage : packageList) { if (antlrPackage.isSelected()) { return antlrPackage; } } return null; } public int getSelectedPackageIndex() { return packageList.indexOf(getSelectedPackage()); } public static String[] getAvailablePackageNames() { List<AntlrPackage> list = getCachedPackageList(); String[] names = new String[list.size()]; for (int i = 0; i < names.length; i++) { names[i] = list.get(i).getVersion(); } return names; } private static void savePackages() throws IOException { Properties properties = new Properties(); StringBuilder versions = new StringBuilder(); String[] packageNames = getAvailablePackageNames(); if (packageNames.length > 0) { for (String pname : packageNames) { versions.append(pname); versions.append(","); } versions.delete(versions.length() - 1, versions.length()); properties.setProperty(ANTLR_AVAILABLE_PKG, versions.toString()); AntlrPackage[] packages = getAvailablePackages(); for (AntlrPackage ap : packages) { properties.put(String.format(ANTLR_CP, ap.getVersion()), ap .getClasspathAsString()); properties.put(String.format(ANTLR_HOME, ap.getVersion()), ap .getHome()); properties.put(String.format(ANTLR_DESC, ap.getVersion()), ap .getDescription()); properties.put(String.format(ANTLR_CREATED, ap.getVersion()), new Long(ap.getCreated()).toString()); properties.put(String.format(ANTLR_SELECTED, ap.getVersion()), new Boolean(ap.isSelected()).toString()); } } OutputStream out = new BufferedOutputStream(new FileOutputStream( getPackagesFile())); properties.storeToXML(out, "ANTLR Packages"); out.flush(); out.close(); } /** * Search for jar files at the ANTLR HOME PATH. The algorithm append the * 'lib' path to the ANTLR HOME PATH and search for any *.jar files located * in the 'lib' directory. * * @param path * The ANTLR HOME PATH * @return The files found under the lib directory * @throws FileNotFoundException */ private static File[] getJarFiles(IPath path) { IPath libPath = path.append("lib"); File rootDir = libPath.toFile(); if (!rootDir.exists()) { // ANTLR 3.2+ version rootDir = path.toFile(); } File[] jarFiles = rootDir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return !name.startsWith(".") && name.endsWith(".jar"); } }); return jarFiles; } /** * Create an ANTLR package from the path. The algorithm search for jar files * under the given path then it try to launch the org.antlr.Tool class and * ask for the version, if the process respond OK the package will be * created * * @param path * The ANTLR HOME PATH * @return A new ANTLR package * @throws InvalidPackageException */ public static AntlrPackage createPackage(IPath path) throws InvalidPackageException { Process process = null; BufferedReader in = null; StringBuilder err = new StringBuilder(); try { // scan the antlr home directory File[] jarFiles = getJarFiles(path); // build the classpath with all the files found StringBuilder classpath = new StringBuilder(); if (jarFiles != null && jarFiles.length > 0) { for (int i = 0; i < jarFiles.length; i++) { File jarFile = jarFiles[i]; classpath.append(jarFile.getAbsolutePath()); classpath.append(File.pathSeparator); } // remove the last separator classpath.setLength(classpath.length() - File.pathSeparator.length()); } AntlrPackage antlrPackage = null; if (classpath.length() > 0) { try { // start a jvm and ask to org.antlr.Tool for version JavaEnvironmentRepository javaEnvironmentRepository = JavaEnvironmentRepositoryLookup .lookup(); JavaEnvironment environment = javaEnvironmentRepository .getEnvironment(); String[] cmd = { environment.getJavaPath().toOSString(), "-classpath", classpath.toString(), "org.antlr.Tool", "-version", "-verbose" }; for (String c : cmd) { err.append(c).append(" "); } err.append("\n"); ProcessBuilder pb = new ProcessBuilder(cmd); process = pb.start(); int status = process.waitFor(); in = new BufferedReader(new InputStreamReader(process .getErrorStream())); String line = in.readLine(); if (status == 0) { if (line != null) { Matcher matcher = VERSION.matcher(line); String version = null; while (matcher.find()) { version = matcher.group(); } // create only if the version can be taken from // ANTLR if (version != null) { antlrPackage = new AntlrPackage(path .toOSString(), line, version, classpath .toString()); } } } else { // error while (line != null) { err.append(line).append("\n"); line = in.readLine(); } } } catch (Exception ex) { throw new InvalidPackageException(ex); } } if (antlrPackage == null) { throw new InvalidPackageException(err.toString().trim()); } return antlrPackage; } finally { if (in != null) { try { in.close(); } catch (IOException ex) { } } if (process != null) { try { process.destroy(); } catch (Exception ex) { } } } } private static List<AntlrPackage> getCachedPackageList() { if (_packageList == null) { _packageList = new ArrayList<AntlrPackage>(); File file = getPackagesFile(); if (file.exists()) { try { InputStream in = new BufferedInputStream( new FileInputStream(file)); Properties properties = new Properties(); properties.loadFromXML(in); String availablePkgs = properties .getProperty(ANTLR_AVAILABLE_PKG); if (availablePkgs != null) { String[] packages = availablePkgs.split(","); for (String packageName : packages) { String home = properties.getProperty(String.format( ANTLR_HOME, packageName)); String desc = properties.getProperty(String.format( ANTLR_DESC, packageName)); String cp = properties.getProperty(String.format( ANTLR_CP, packageName)); long created = Long.parseLong(properties .getProperty(String.format(ANTLR_CREATED, packageName), Long.MAX_VALUE + "")); boolean selected = Boolean.valueOf(properties .getProperty(String.format(ANTLR_SELECTED, packageName), Boolean.FALSE .toString())); _packageList.add(new AntlrPackage(home, desc, packageName, cp, created, selected)); } in.close(); Collections.sort(_packageList); } } catch (IOException e) { AntlrCore.error(e); } } } return _packageList; } private static File getPackagesFile() { IPath root = AntlrCore.getDefault().getStateLocation(); return new File(root.toFile(), PACKAGES_FILE); } }