/* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.user.tools.util; import com.google.gwt.dev.cfg.ModuleDefLoader; import java.io.File; import java.io.FileNotFoundException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.List; /** * Utility methods used by ApplicationCreator. * */ public class CreatorUtilities { /** * Create a PATH style string separated by the specified delimiter (';' for * windows, ':' for UNIX) Note that this method prepends the delimiter to the * front of the string. There is an existing path we want to append to. * * @param delimiter The delimiter string to place between variables. * @param paths The list of paths to concatenate together. * @return the concatenated list of paths as a single string. */ public static String appendPaths(String delimiter, List<String> paths) { if (paths == null) { return ""; } StringBuilder buf = new StringBuilder(); for (String value : paths) { buf.append(delimiter); buf.append(value); } return buf.toString(); } /** * Create the extra path entries for an Eclipse '.launch' file in XML format. * * @param extraClassPaths a list of paths/.jar files to add to the class path * @return A string formatted to include in the .launch file */ public static String createEclipseExtraLaunchPaths( List<String> extraClassPaths) throws FileNotFoundException { if (extraClassPaths == null) { return ""; } // Create an entry for an Eclipse launch file additional classpath entry. StringBuilder buf = new StringBuilder(); for (String path : extraClassPaths) { File f = new File(path); if (!f.exists()) { throw new FileNotFoundException("extraClassPath: " + path + "Must be present before .launch file can be created"); } String lcPath = path.toLowerCase(); if (f.isDirectory()) { // For a directory, we assume it contains compiled class files buf.append("<listEntry value=\"<?xml version="1.0" "); buf.append("encoding="UTF-8" standalone="no""); buf.append("?> <runtimeClasspathEntry "); buf.append("internalArchive=""); buf.append(path); buf.append("" path="3" type="2"/> \"/>"); buf.append("\n"); } else if (lcPath.endsWith(".jar") || lcPath.endsWith(".zip")) { // Any plain file we assume is an external library (e.g. a .jar file) buf.append("<listEntry value=\"<?xml version="1.0" "); buf.append("encoding="UTF-8"?> <runtimeClasspathEntry "); buf.append("externalArchive=""); buf.append(path); buf.append("" path="3" type="2"/> \"/>"); buf.append("\n"); } else { throw new RuntimeException("Don't know how to handle path: " + path + ". It doesn't appear to be a directory or a .jar/.zip file"); } } return buf.toString(); } /** * Returns <code>true</code> if <code>moduleName</code> is a valid module * name. */ public static boolean isValidModuleName(String moduleName) { return moduleName.matches("[\\w]+(\\.[\\w]+)+"); } /** * Check to see that the userJar and pathList files all exist, and that the * moduleList entries can be found within the jars. * * @param userJar The full path to gwt-user.jar * @param pathList A list of jar files to add to the class path. * @param moduleList A list of GWT module names to add as 'inherits' tags * @return <code>true</code> if all validations pass. */ public static boolean validatePathsAndModules(String userJar, List<String> pathList, List<String> moduleList) { List<URL> urlList = new ArrayList<URL>(); if (!addURL(urlList, userJar)) { return false; } if (pathList != null) { for (String path : pathList) { if (!addURL(urlList, path)) { return false; } } } /* * Create a class loader from the extra class paths and the current class * loader. The assumption is that if the userJar isn't available right now, * that the current class loader will contain the same gwt.xml module def * files. */ final URL urlArray[] = urlList.toArray(new URL[urlList.size()]); URLClassLoader classLoader = AccessController.doPrivileged( new PrivilegedAction<URLClassLoader>() { public URLClassLoader run() { return new URLClassLoader(urlArray, CreatorUtilities.class.getClassLoader()); } }); if (moduleList != null) { for (String module : moduleList) { String modulePath = module.replace(".", "/") + ModuleDefLoader.GWT_MODULE_XML_SUFFIX; URL found = classLoader.getResource(modulePath); if (found == null) { System.err.println("Couldn't find module definition file " + modulePath + " in class path."); return false; } } } return true; } /** * Append a path to a list of URLs. * * @param urls list to append to * @param pathToAdd string to append as the last entry in the URL list. * @return <code>true</code> on success. <code>false</code> if an error * occurs (malformed URL or missing file.) */ private static boolean addURL(List<URL> urls, String pathToAdd) { File f = new File(pathToAdd); // Ignore gwt-user.jar in the validation. This helps the build process // get by when overriding the location of the .jar with -Dgwt.devjar if (!pathToAdd.matches(".*gwt-user.jar") && !f.exists()) { System.err.println("Couldn't find library file or path " + pathToAdd); return false; } try { urls.add(f.toURI().toURL()); } catch (MalformedURLException urlEx) { urlEx.printStackTrace(); return false; } return true; } }